Index: openacs-4/packages/ajaxhelper/ajaxhelper.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/ajaxhelper.info,v diff -u -N -r1.4 -r1.5 --- openacs-4/packages/ajaxhelper/ajaxhelper.info 20 Apr 2006 12:31:27 -0000 1.4 +++ openacs-4/packages/ajaxhelper/ajaxhelper.info 20 Aug 2006 14:39:20 -0000 1.5 @@ -8,13 +8,13 @@ t ajax - + Hamilton Chua - Provides helper procs to generate javascript for Ajax and cinematic effects. Include Scriptaculous (1.6.1) Javascript Libraries and the Yahoo UI Libraries. + Provides helper procs to generate javascript used for Ajax and generating cinematic effects. Includes Scriptaculous (1.6.2) Javascript Libraries and the Yahoo UI Libraries (0.11.2). Solution Grove 0 - + Index: openacs-4/packages/ajaxhelper/tcl/ajax-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/tcl/ajax-procs.tcl,v diff -u -N -r1.3 -r1.4 --- openacs-4/packages/ajaxhelper/tcl/ajax-procs.tcl 5 Apr 2006 06:38:41 -0000 1.3 +++ openacs-4/packages/ajaxhelper/tcl/ajax-procs.tcl 20 Aug 2006 14:39:20 -0000 1.4 @@ -1,8 +1,7 @@ ad_library { Library for Ajax Helper Procs - based on - Scriptaculous and Prototype for Ajax and Effects + based on Scriptaculous and Prototype for Ajax and Effects OverlibMWS for Popups @author Hamilton Chua (ham@solutiongrove.com) @@ -14,7 +13,7 @@ ad_proc -private ah::get_package_id { } { - Return the package_id of the installed and mounted ajax helper + Return the package_id of the installed and mounted ajax helper instance @author Hamilton Chua (ham@solutiongrove.com) @creation-date 2006-01-16 @@ -47,87 +46,94 @@ Receives a string and surrounds it with single quotes. This is a utility proc used to make a parameter passed to a proc a string. The assumption is that an element passed as a parameter is a javascript variable. + + @author Hamilton Chua (ham@solutiongrove.com) + @creation-date 2006-01-16 + @return } { return "'$element'" } -ad_proc -public ah::js_sources { - {-default:boolean} - {-source ""} - {-withbubble:boolean} - {-scrollable:boolean} - {-draggable:boolean} -} { +ad_proc -private ah::dynamic_load_functions { - Generates the < script > syntax needed on the head - for each set of javascript files this package uses or needs to source. - The code : -
-		[ah::js_sources -default]
-	
- will load the prototype javascript library and scriptaculous javascript files by default. +} { + Generates the javascript functions that perform dynamic loading of local javascript files. + http://www.phpied.com/javascript-include/ + WARNING : experimental - It's not recommended to mix scriptaculous and rico. - @author Hamilton Chua (ham@solutiongrove.com) - @creation-date 2006-01-16 + @creation-date 2006-04-20 - @param default Loads the prototype and scriptaculous javascript libraries. - @param source The caller can specify which set of javascript source files to load. - Valid values include - "rounder" : to load the rico corner rounder functions only, use this if you are working primarily with scriptaculous, - "rico" : to load the rico javascript library, - "overlibws" : to load the overlibmws javascript files for dhtml callouts and popups. +} { + set ah_base_url [ah::get_url] + set script "" + return $script +} - @param withbubble Do we want to use the overlibmws plugin for bubble callouts ? - @param scrollable Do we want to use the overlibmws scrollable plugin ? - @param draggable Do we want to use the overlibmws draggable plugin ? +ad_proc -public ah::js_include { + {-js_file ""} +} { + Generates the javscript to include a js file dynamically via DOM to the head section of the page. + WARNING : experimental - @return + @author Hamilton Chua (ham@solutiongrove.com) + @creation-date 2006-04-20 +} { + return "js_include_once('$js_file'); " +} - @error +ad_proc -public ah::js_source_dynamic { + {-js "default"} + {-enclose:boolean} +} { + Uses the javascript dynamic loading functions to load the comma separated list of javascript source file. + WARNING : experimental + @author Hamilton Chua (ham@solutiongrove.com) + @creation-date 2006-04-20 + + + @param js A comma separated list of js files to load. + Possible values include prototype, scriptaculous, rounder, rico, overlibmws, overlibmws_bubble, overlibmws_scroll, overlibmws_drag + @param enclose Specify this if you want the javascript to be enclosed in script tags, which is usually the case unless you include this along with other javascript. } { + set ah_base_url [ah::get_url] set script "" - - if { $default_p } { - # load prototype and scriptaculous js files - append script " \n" - append script " \n" - } else { - if { [info exists source] } { - # load other js libraries - switch $source { - "rico" { - append script " \n" - } - "rounder" { - append script " \n" - } - "overlibmws" { - append script " \n" - append script "\n" - if { $withbubble_p } { - append script "\n" - append script "\n" - } - if { $scrollable_p } { - append script "\n" - } - if { $draggable_p } { - append script "\n" - } - } - default { - # invalid value for source - } + set js_file_list [split $js ","] + + foreach x $js_file_list { + switch $x { + "rico" { + append script [ah::js_include -js_file "${ah_base_url}rico/rico.js"] } + "rounder" { + append script [ah::js_include -js_file "${ah_base_url}rico/rico.js"] + append script [ah::js_include -js_file "${ah_base_url}rico/rounder.js"] + } + "overlibmws" { + append script [ah::js_include -js_file "${ah_base_url}overlibmws/overlibmws.js"] + append script [ah::js_include -js_file "${ah_base_url}overlibmws/overlibmws_overtwo.js"] + } + "overlibmws_bubble" { + append script [ah::js_include -js_file "${ah_base_url}overlibmws/overlibmws_bubble.js"] + } + "overlibmws_scroll" { + append script [ah::js_include -js_file "${ah_base_url}overlibmws/overlibmws_scroll.js"] + } + "overlibmws_drag" { + append script [ah::js_include -js_file "${ah_base_url}overlibmws/overlibmws_draggable.js"] + } + default { + append script [ah::js_include -js_file "${ah_base_url}prototype/prototype.js"] + append script [ah::js_include -js_file "${ah_base_url}scriptaculous/scriptaculous.js"] + } } } - return $script + if { $enclose_p } { set script [ah::enclose_in_script -script ${script} ] } + return $script } ad_proc -private ah::enclose_in_script { @@ -139,7 +145,7 @@ @param script string to enclose in javascript tags. } { - set tag "" return $tag @@ -154,6 +160,7 @@ } { Use prototype's Event object to watch/listen to a specific event from a specific html element. Valid events include click, load, mouseover etc. + See ah::yui::addlistener for Yahoo's implementation which some say is more superior. @author Hamilton Chua (ham@solutiongrove.com) @creation-date 2006-02-28 @@ -196,6 +203,7 @@ ad_proc -public ah::ajaxrequest { -url:required + {-asynchronous "true"} {-pars ""} {-options ""} } { @@ -212,9 +220,10 @@ @param url the url that the javascript will call/query @param pars the parameters that will be passed to Ajax.Request. these parameters should normally be enclosed in single quotes ('') unless you intend to provide a javascript variable or function as a parameter @param options the options that will be passed to the Ajax.Request javascript function + @param asynchronous the default is true } { - set preoptions "asynchronous:'true',method:'post'" + set preoptions "asynchronous:${asynchronous},method:'post'" if { [exists_and_not_null pars] } { append preoptions ",parameters:$pars" @@ -228,6 +237,7 @@ ad_proc -public ah::ajaxupdate { -container:required -url:required + {-asynchronous "true"} {-pars ""} {-options ""} {-effect ""} @@ -236,7 +246,7 @@ {-container_is_var:boolean} } { Generate an Ajax.Updater javascript object. - The parameters are passed directly to Ajax.Update script. + The parameters are passed directly to the Ajax.Update script. You can optionally specify an effect to use as the container is updated. By default it will use the "Appear" effect. Parameters and options are case sensitive, refer to scriptaculous documentation. @@ -268,7 +278,7 @@ set container [ah::isnot_js_var $container] } - set preoptions "asynchronous:'true',method:'post'" + set preoptions "asynchronous:$asynchronous,method:'post'" if { [exists_and_not_null pars] } { append preoptions ",parameters:$pars" @@ -296,6 +306,7 @@ The ah::source must be executed with -source "overlibmws" For more information about the options that you can pass http://www.macridesweb.com/oltest/ + See ah::yui::tooltip for Yahoo's implementation @author Hamilton Chua (ham@solutiongrove.com) @creation-date 2006-02-12 @@ -346,7 +357,7 @@ This proc will generate mouseover and mouseout javascript for dhtml callout or popup using overlibmws and the overlibmws bubble plugin. - The ah::source must be called with -source "overlibmws" -withbubble + The ah::source must be called with -source "overlibmws,overlibmws_bubble" @author Hamilton Chua (ham@solutiongrove.com) @creation-date 2006-01-16 @@ -356,7 +367,6 @@ @param textsize the size of the text in the popup @return - @error } { @@ -382,6 +392,9 @@ @param url the url to make the xmlhttp call to @param pars the parameters in querystring format you want to pass to the url + @param options the options you want to pass to overlibmws + @param type parameter specific to the bubble callout + @param textsize the size of the text in the callout @return @@ -411,10 +424,10 @@ @param element the page element that you want to apply the effect to @param effect specify one of the scriptaculous effects you want to implement - @param options specify the options to pass to the javascript + @param options specify the options to pass to the scritpaculous javascript + @param element_is_var specify this if the element you are passing is a javascript variable @return - @error } { @@ -431,7 +444,7 @@ {-options ""} {-element_is_var:boolean} } { - Generates javascript that toggle the state of an element. + Generates javascript that toggles the state of an element. The parameters are passed directly to the scriptaculous toggle script. Parameters and options are case sensitive, refer to scriptaculous documentation. http://wiki.script.aculo.us/scriptaculous/show/Effect.toggle @@ -441,9 +454,10 @@ @param element the page element that you want to apply the effect to @param effect specify one of the scriptaculous effects you want to toggle - - @return - + @param options specify the options to pass to the scritpaculous javascript + @param element_is_var specify this if the element you are passing is a javascript variable + + @return @error } { @@ -481,9 +495,7 @@ if { !$element_is_var_p } { set element [ah::isnot_js_var $element] } - set script "new Draggable \($element,\{$options\}\);" - return $script } @@ -534,9 +546,9 @@ @creation-date 2006-02-24 @param element the page element that you want to be a droppable + @param element_is_var specify this parameter if the element you are passing is a javscript variable @return - @error } { @@ -563,10 +575,11 @@ @param element the page element that you want to apply the effect to @param options specify the scriptaculous options + @param element_is_var specify this parameter if the element you are passing is a javscript variable @return - @error + } { if { !$element_is_var_p } { set element [ah::isnot_js_var $element] @@ -598,4 +611,62 @@ } set script "Rico.Corner.round\($element, \{$options\}\); " return $script +} + +ad_proc -public ah::js_sources { + {-source "default"} +} { + + Will load the prototype javascript library and scriptaculous javascript files. + + @author Hamilton Chua (ham@solutiongrove.com) + @creation-date 2006-01-16 + + @param source The caller can specify which set of javascript source files to load. This can be a comma seprated list + Valid values include + "default" : to load prototype and scriptaculous libraries + "rounder" : to load the rico corner rounder functions only, use this if you are working primarily with scriptaculous, + "rico" : to load the rico javascript library, + "overlibmws" : to load the overlibmws javascript files for dhtml callouts and popups. + "overlibmws_bubble" : to load the overlibmws javascript files for dhtml callouts and popups. + "overlibmws_scroll" : to load the overlibmws javascript files for dhtml bubble callouts and popups that scroll. + "overlibmws_drag" : to load the overlibmws javascript files for draggable dhtml callouts and popups. + + @return + @error +} { + + set ah_base_url [ah::get_url] + set js_file_list [split $source ","] + set script "" + + foreach x $js_file_list { + switch $x { + "rico" { + append script " \n" + } + "rounder" { + append script " \n" } + "overlibmws" { + append script " \n" + append script "\n" + } + "overlibmws_bubble" { + append script "\n" + append script "\n" + } + "overlibmws_scroll" { + append script "\n" + } + "overlibmws_drag" { + append script "\n" + } + default { + append script " \n" + append script " \n" + } + } + } + + return $script } \ No newline at end of file Index: openacs-4/packages/ajaxhelper/tcl/ajax-yahoo-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/tcl/ajax-yahoo-procs.tcl,v diff -u -N -r1.1 -r1.2 --- openacs-4/packages/ajaxhelper/tcl/ajax-yahoo-procs.tcl 5 Apr 2006 06:38:41 -0000 1.1 +++ openacs-4/packages/ajaxhelper/tcl/ajax-yahoo-procs.tcl 20 Aug 2006 14:39:20 -0000 1.2 @@ -7,26 +7,84 @@ @creation-date 2006-01-16 } -namespace eval ah::yahoo { } +namespace eval ah::yui { } -ad_proc -public ah::yahoo::js_sources { - {-default:boolean} - {-source ""} +ad_proc -public ah::yui::js_source_dynamic { + {-js "default"} + {-enclose:boolean} } { + Dynamically Loads the Yahoo UI javascript libraries. + WARNING : experimental, use ah::yui::js_sources instead + + + @author Hamilton Chua (ham@solutiongrove.com) + @creation-date 2006-04-20 + + @param js Comma separated list of javascript files to load + Valid values include + "default" : loads yui.js and dom.js, the most commonly used + "animation" : loads js for animation + "event" : loads js for event monitoring (e.g. listnern) + "treeview" : loads js for Yahoo's Tree View control + "calendar" : loads js for Yahoo's Calendar Control + "dragdrop" : loads js for Yahoo's Drag and Drop functions + "slider" : loads js for slider functions + +} { + + set ah_base_url [ah::get_url] + set script "" + set js_file_list [split $js ","] + foreach x $js_file_list { + switch $x { + "animation" { + append script [ah::js_include -js_file "${ah_base_url}yui/animation/animation.js"] + } + "event" { + append script [ah::js_include -js_file "${ah_base_url}yui/event/event.js"] + } + "treeview" { + append script [ah::js_include -js_file "${ah_base_url}yui/treeview/treeview.js"] + } + "calendar" { + append script [ah::js_include -js_file "${ah_base_url}yui/calendar/calendar.js"] + } + "dragdrop" { + append script [ah::js_include -js_file "${ah_base_url}yui/dragdrop/dragdrop.js"] + } + "slider" { + append script [ah::js_include -js_file "${ah_base_url}yui/slider/slider.js"] + } + default { + append script [ah::js_include -js_file "${ah_base_url}yui/yui.js"] + append script [ah::js_include -js_file "${ah_base_url}yui/dom/dom.js"] + } + } + } + + if { $enclose_p } { set script [ah::enclose_in_script -script ${script} ] } + + return $script +} + +ad_proc -public ah::yui::js_sources { + {-source "default"} +} { + Generates the < script > syntax needed on the head - for Yahoo's User Interface Library + for yui's User Interface Library The code :
-		[ah::yahoo::js_sources -default]
+		[ah::yui::js_sources -default]
 	
will load the default YUI javascript library which includes the connections and doms js files @author Hamilton Chua (ham@solutiongrove.com) @creation-date 2006-01-16 @param default Loads the prototype and scriptaculous javascript libraries. - @param source The caller can specify which set of javascript source files to load. + @param source The caller can specify which set of javascript source files to load. You can specify more than one by separating the list with commas. Valid values include "animation" : loads animation.js "event" : loads events.js @@ -36,50 +94,48 @@ "slider" : loads slider.js @return - @error } { set ah_base_url [ah::get_url] set script "" - - if { $default_p } { - append script " \n" - append script " \n" - } else { - if { [info exists source] } { - # load other js libraries - switch $source { - "animation" { - append script " \n" - } - "event" { - append script " \n" - } - "treeview" { - append script " \n" - } - "calendar" { - append script " \n" - } - "dragdrop" { - append script " \n" - } - "slider" { - append script " \n" - } - - default { - # invalid value for source - } + set js_file_list [split $source ","] + + foreach x $js_file_list { + switch $x { + "animation" { + append script " \n" } + "event" { + append script " \n" + } + "treeview" { + append script " \n" + } + "calendar" { + append script " \n" + } + "dragdrop" { + append script " \n" + } + "slider" { + append script " \n" + } + "container" { + append script " \n" + append script " \n" + } + default { + append script " \n" + append script " \n" + } } } return $script } -ad_proc -public ah::yahoo::addlistener { +ad_proc -public ah::yui::addlistener { -element:required -event:required {-callback ""} @@ -91,4 +147,19 @@ set element [ah::isnot_js_var $element] } return "YAHOO.util.Event.addListener($element,\"$event\",${callback});\n" +} + +ad_proc -public ah::yui::tooltip { + -varname:required + -element:required + -message:required + {-enclose:boolean} + {-options ""} +} { + Generates the javascript to create a tooltip using yahoo's user interface javascript library. + For this to work, the default and container sources need to be loaded, see ah::yui::js_sources +} { + set script "var $varname = new YAHOO.widget.Tooltip(\"alertTip\", { context:\"$element\", text:\"$message\", $options });" + if { $enclose_p } { set script [ah::enclose_in_script -script ${script} ] } + return $script } \ No newline at end of file Index: openacs-4/packages/ajaxhelper/www/dynamicInclude.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/Attic/dynamicInclude.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/dynamicInclude.js 20 Aug 2006 14:39:21 -0000 1.1 @@ -0,0 +1,155 @@ +//Javascript dynamic Include Library +//Code derived from: +//Author: Stoyan Stefanov +//SITE: www.phpied.com +//email: ssttoo at gmaildotcom +//mad props due.. +//I made the manager objects and added the css methods so +//I can use this library for both +//me: Greg Patmore +//hit me up: //greg at ito-ydotcom + + +//js + +//holds the currently loaded .js libraries +//NOTE: idiot alert! any files included outside these methods cannot be +// referenced by this array +var js_includes = new Array(); + + +//use this manager to keep things simple +function JSManager(){ + this.included = js_includes; + this.include = js_include_once; + this.remove = js_remove_include; +} + +function js_include_dom(script_filename) { + var html_doc = document.getElementsByTagName('head').item(0); + var js = document.createElement('script'); + js.setAttribute('language', 'javascript'); + js.setAttribute('type', 'text/javascript'); + js.setAttribute('src', script_filename); + html_doc.appendChild(js); + return false; +} + +function js_include_once(script_filename) { + if (!in_array(script_filename, js_includes)) { + js_includes[js_includes.length] = script_filename; + js_include_dom(script_filename); + } +} + +//"un-includes" the included js file from the document +//use sparingly, as it's a memory whore +//NOTE: will not kill any timeouts you may have going +// but the script will be removed from the rendered source +function js_remove_include(scriptname){ + var docScripts = document.getElementsByTagName('script'); + for(var i=0;i 0) this.index-- else this.index = this.entryCount-1; + this.getEntry(this.index).scrollIntoView(true); }, markNext: function() { if(this.index < this.entryCount-1) this.index++ else this.index = 0; + this.getEntry(this.index).scrollIntoView(false); }, getEntry: function(index) { @@ -531,7 +536,7 @@ Element.hide(this.element); this.createForm(); this.element.parentNode.insertBefore(this.form, this.element); - Field.scrollFreeActivate(this.editField); + if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField); // stop the event to avoid a page refresh in Safari if (evt) { Event.stop(evt); @@ -636,6 +641,7 @@ Element.removeClassName(this.form, this.options.loadingClassName); this.editField.disabled = false; this.editField.value = transport.responseText.stripTags(); + Field.scrollFreeActivate(this.editField); }, onclickCancel: function() { this.onComplete(); 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 -N -r1.3 -r1.4 --- openacs-4/packages/ajaxhelper/www/scriptaculous/dragdrop.js 20 Apr 2006 12:31:28 -0000 1.3 +++ openacs-4/packages/ajaxhelper/www/scriptaculous/dragdrop.js 20 Aug 2006 14:39:23 -0000 1.4 @@ -5,6 +5,9 @@ /*--------------------------------------------------------------------------*/ +if(typeof Effect == 'undefined') + throw("dragdrop.js requires including script.aculo.us' effects.js library"); + var Droppables = { drops: [], @@ -204,21 +207,31 @@ /*--------------------------------------------------------------------------*/ var Draggable = Class.create(); +Draggable._revertCache = {}; +Draggable._dragging = {}; + Draggable.prototype = { initialize: function(element) { var options = Object.extend({ handle: false, starteffect: function(element) { - element._opacity = Element.getOpacity(element); + element._opacity = Element.getOpacity(element); + Draggable._dragging[element] = true; 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}); + Draggable._revertCache[element] = + new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, + queue: {scope:'_draggable', position:'end'} + }); }, 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}); + var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0; + new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, + queue: {scope:'_draggable', position:'end'}, + afterFinish: function(){ Draggable._dragging[element] = false } + }); }, zindex: 1000, revert: false, @@ -264,6 +277,8 @@ }, initDrag: function(event) { + if(typeof Draggable._dragging[this.element] != undefined && + Draggable._dragging[this.element]) return; if(Event.isLeftClick(event)) { // abort on form elements, fixes a Firefox issue var src = Event.element(event); @@ -274,9 +289,9 @@ src.tagName=='BUTTON' || src.tagName=='TEXTAREA')) return; - if(this.element._revert) { - this.element._revert.cancel(); - this.element._revert = null; + if(Draggable._revertCache[this.element]) { + Draggable._revertCache[this.element].cancel(); + Draggable._revertCache[this.element] = null; } var pointer = [Event.pointerX(event), Event.pointerY(event)]; @@ -442,6 +457,7 @@ }, 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(this.scroll.bind(this), 10); @@ -708,7 +724,7 @@ if(!Element.isParent(dropon, element)) { var index; - var children = Sortable.findElements(dropon, {tag: droponOptions.tag}); + var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); var child = null; if(children) { @@ -869,7 +885,7 @@ if (options.tree) { return Sortable.tree(element, arguments[1]).children.map( function (item) { - return [name + Sortable._constructIndex(item) + "=" + + return [name + Sortable._constructIndex(item) + "[id]=" + encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); }).flatten().join('&'); } else { 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 -N -r1.3 -r1.4 --- openacs-4/packages/ajaxhelper/www/scriptaculous/effects.js 20 Apr 2006 12:31:28 -0000 1.3 +++ openacs-4/packages/ajaxhelper/www/scriptaculous/effects.js 20 Aug 2006 14:39:23 -0000 1.4 @@ -105,6 +105,9 @@ var Effect = { tagifyText: function(element) { + if(typeof Builder == 'undefined') + throw("Effect.tagifyText requires including script.aculo.us' builder.js library"); + var tagifyStyle = 'position:relative'; if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1'; element = $(element); @@ -161,9 +164,8 @@ Effect.Transitions = {} -Effect.Transitions.linear = function(pos) { - return pos; -} +Effect.Transitions.linear = Prototype.K; + Effect.Transitions.sinoidal = function(pos) { return (-Math.cos(pos*Math.PI)/2) + 0.5; } @@ -353,7 +355,7 @@ initialize: function(element) { this.element = $(element); // make this work on IE on elements without 'layout' - if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) + if(/MSIE/.test(navigator.userAgent) && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); var options = Object.extend({ from: this.element.getOpacity() || 0.0, @@ -393,8 +395,8 @@ }, update: function(position) { this.element.setStyle({ - left: this.options.x * position + this.originalLeft + 'px', - top: this.options.y * position + this.originalTop + 'px' + left: Math.round(this.options.x * position + this.originalLeft) + 'px', + top: Math.round(this.options.y * position + this.originalTop) + 'px' }); } }); @@ -433,7 +435,7 @@ this.originalLeft = this.element.offsetLeft; var fontSize = this.element.getStyle('font-size') || '100%'; - ['em','px','%'].each( function(fontSizeType) { + ['em','px','%','pt'].each( function(fontSizeType) { if(fontSize.indexOf(fontSizeType)>0) { this.fontSize = parseFloat(fontSize); this.fontSizeType = fontSizeType; @@ -462,8 +464,8 @@ }, setDimensions: function(height, width) { var d = {}; - if(this.options.scaleX) d.width = width + 'px'; - if(this.options.scaleY) d.height = height + 'px'; + if(this.options.scaleX) d.width = Math.round(width) + 'px'; + if(this.options.scaleY) d.height = Math.round(height) + 'px'; if(this.options.scaleFromCenter) { var topd = (height - this.dims[0])/2; var leftd = (width - this.dims[1])/2; @@ -589,7 +591,7 @@ Effect.BlindUp = function(element) { element = $(element); element.makeClipping(); - return new Effect.Scale(element, 0, + return new Effect.Scale(element, 0, Object.extend({ scaleContent: false, scaleX: false, restoreAfterFinish: true, @@ -604,28 +606,27 @@ Effect.BlindDown = function(element) { element = $(element); var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, - Object.extend({ scaleContent: false, - scaleX: false, - scaleFrom: 0, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makeClipping(); - effect.element.setStyle({height: '0px'}); - effect.element.show(); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - } - }, arguments[1] || {}) - ); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping(); + effect.element.setStyle({height: '0px'}); + effect.element.show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || {})); } Effect.SwitchOff = function(element) { element = $(element); var oldOpacity = element.getInlineOpacity(); - return new Effect.Appear(element, { + return new Effect.Appear(element, Object.extend({ duration: 0.4, from: 0, transition: Effect.Transitions.flicker, @@ -645,7 +646,7 @@ } }) } - }); + }, arguments[1] || {})); } Effect.DropOut = function(element) { @@ -729,7 +730,7 @@ }, arguments[1] || {}) ); } - + Effect.SlideUp = function(element) { element = $(element); element.cleanWhitespace(); 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 -N -r1.3 -r1.4 --- openacs-4/packages/ajaxhelper/www/scriptaculous/scriptaculous.js 20 Apr 2006 12:31:28 -0000 1.3 +++ openacs-4/packages/ajaxhelper/www/scriptaculous/scriptaculous.js 20 Aug 2006 14:39:23 -0000 1.4 @@ -20,7 +20,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var Scriptaculous = { - Version: '1.6.1', + Version: '1.6.2', require: function(libraryName) { // inserting via DOM fails in Safari 2.0, so brute force approach document.write(''); Index: openacs-4/packages/ajaxhelper/www/scriptaculous/slider.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/scriptaculous/Attic/slider.js,v diff -u -N -r1.2 -r1.3 --- openacs-4/packages/ajaxhelper/www/scriptaculous/slider.js 31 Mar 2006 08:15:36 -0000 1.2 +++ openacs-4/packages/ajaxhelper/www/scriptaculous/slider.js 20 Aug 2006 14:39:23 -0000 1.3 @@ -64,8 +64,13 @@ this.alignY = parseInt(this.options.alignY || '0'); this.trackLength = this.maximumOffset() - this.minimumOffset(); - this.handleLength = this.isVertical() ? this.handles[0].offsetHeight : this.handles[0].offsetWidth; + this.handleLength = this.isVertical() ? + (this.handles[0].offsetHeight != 0 ? + this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) : + (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : + this.handles[0].style.width.replace(/px$/,"")); + this.active = false; this.dragging = false; this.disabled = false; @@ -137,8 +142,8 @@ }, setValue: function(sliderValue, handleIdx){ if(!this.active) { - this.activeHandle = this.handles[handleIdx]; - this.activeHandleIdx = handleIdx; + this.activeHandleIdx = handleIdx || 0; + this.activeHandle = this.handles[this.activeHandleIdx]; this.updateStyles(); } handleIdx = handleIdx || this.activeHandleIdx || 0; @@ -180,8 +185,11 @@ return(this.isVertical() ? this.alignY : this.alignX); }, maximumOffset: function(){ - return(this.isVertical() ? - this.track.offsetHeight - this.alignY : this.track.offsetWidth - this.alignX); + return(this.isVertical() ? + (this.track.offsetHeight != 0 ? this.track.offsetHeight : + this.track.style.height.replace(/px$/,"")) - this.alignY : + (this.track.offsetWidth != 0 ? this.track.offsetWidth : + this.track.style.width.replace(/px$/,"")) - this.alignY); }, isVertical: function(){ return (this.axis == 'vertical'); @@ -217,7 +225,8 @@ var handle = Event.element(event); var pointer = [Event.pointerX(event), Event.pointerY(event)]; - if(handle==this.track) { + var track = handle; + if(track==this.track) { var offsets = Position.cumulativeOffset(this.track); this.event = event; this.setValue(this.translateToValue( 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 -N -r1.3 -r1.4 --- openacs-4/packages/ajaxhelper/www/scriptaculous/unittest.js 20 Apr 2006 12:31:28 -0000 1.3 +++ openacs-4/packages/ajaxhelper/www/scriptaculous/unittest.js 20 Aug 2006 14:39:23 -0000 1.4 @@ -303,6 +303,13 @@ this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); } catch(e) { this.error(e); } }, + assertMatch: function(expected, actual) { + var message = arguments[2] || 'assertMatch'; + var regex = new RegExp(expected); + try { (regex.exec(actual)) ? this.pass() : + this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); } + catch(e) { this.error(e); } + }, assertHidden: function(element) { var message = arguments[1] || 'assertHidden'; this.assertEqual("none", element.style.display, message); Index: openacs-4/packages/ajaxhelper/www/yahoo/YAHOO.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yahoo/Attic/YAHOO.js,v diff -u -N --- openacs-4/packages/ajaxhelper/www/yahoo/YAHOO.js 5 Apr 2006 06:38:42 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,63 +0,0 @@ -/* -Copyright (c) 2006 Yahoo! Inc. All rights reserved. -version 0.9.0 -*/ - -/** - * @class The Yahoo global namespace - */ -var YAHOO = function() { - - return { - - /** - * Yahoo presentation platform utils namespace - */ - util: {}, - - /** - * Yahoo presentation platform widgets namespace - */ - widget: {}, - - /** - * Yahoo presentation platform examples namespace - */ - example: {}, - - /** - * Returns the namespace specified and creates it if it doesn't exist - * - * YAHOO.namespace("property.package"); - * YAHOO.namespace("YAHOO.property.package"); - * - * Either of the above would create YAHOO.property, then - * YAHOO.property.package - * - * @param {String} sNameSpace String representation of the desired - * namespace - * @return {Object} A reference to the namespace object - */ - namespace: function( sNameSpace ) { - - if (!sNameSpace || !sNameSpace.length) { - return null; - } - - var levels = sNameSpace.split("."); - - var currentNS = YAHOO; - - // YAHOO is implied, so it is ignored if it is included - for (var i=(levels[0] == "YAHOO") ? 1 : 0; i0){ - this.setHeader(o); - } - postData?o.conn.send(postData):o.conn.send(null); - - return o; - } - }, - - /** - * This method serves as a timer that polls the XHR object's readyState - * property during a transaction, instead of binding a callback to the - * onreadystatechange event. Upon readyState 4, handleTransactionResponse - * will process the response, and the timer will be cleared. - * - * @private - * @param {object} o The connection object - * @param callback User-defined callback object - * @param callbackArg User-defined arguments passed to the callback - * @return void - */ - handleReadyState:function(o, callback) - { - var oConn = this; - var poll = window.setInterval( - function(){ - if(o.conn.readyState==4){ - oConn.handleTransactionResponse(o, callback); - window.clearInterval(poll); - } - } - ,this._polling_interval); - }, - - /** - * This method attempts to interpret the server response and - * determine whether the transaction was successful, or if an error or - * exception was encountered. - * - * @private - * @param {object} o The connection object - * @param {function} callback - User-defined callback object - * @param {} callbackArg - User-defined arguments to be passed to the callback - * @return void - */ - handleTransactionResponse:function(o, callback) - { - var httpStatus; - var responseObject; - - try{ - httpStatus = o.conn.status; - } - catch(e){ - // 13030 is the custom code to indicate the condition -- in Mozilla/FF -- - // when the o object's status and statusText properties are - // unavailable, and a query attempt throws an exception. - httpStatus = 13030; - } - - if(httpStatus == 200){ - responseObject = this.createResponseObject(o, callback.argument); - if(callback.success){ - if(!callback.scope){ - callback.success(responseObject); - } - else{ - callback.success.apply(callback.scope, [responseObject]); - } - } - } - else{ - switch(httpStatus){ - // The following case labels are wininet.dll error codes that may be encountered. - // Server timeout - case 12002: - // 12029 to 12031 correspond to dropped connections. - case 12029: - case 12030: - case 12031: - // Connection closed by server. - case 12152: - // See above comments for variable status. - case 13030: - responseObject = this.createExceptionObject(o, callback.argument); - if(callback.failure){ - if(!callback.scope){ - callback.failure(responseObject); - } - else{ - callback.failure.apply(callback.scope,[responseObject]); - } - } - break; - default: - responseObject = this.createResponseObject(o, callback.argument); - if(callback.failure){ - if(!callback.scope){ - callback.failure(responseObject); - } - else{ - callback.failure.apply(callback.scope,[responseObject]); - } - } - } - } - - this.releaseObject(o); - }, - - /** - * This method evaluates the server response, creates and returns the results via - * its properties. Success and failure cases(and exceptions) will differ in their defined properties - * but property "type" will confirm the transaction's status. - * @private - * @param {object} o The connection object - * @param {} callbackArg User-defined arguments to be passed to the callback - * @param {boolean} isSuccess Indicates whether the transaction was successful or not. - * @return object - */ - createResponseObject:function(o, callbackArg) - { - var obj = {}; - - obj.tId = o.tId; - obj.status = o.conn.status; - obj.statusText = o.conn.statusText; - obj.allResponseHeaders = o.conn.getAllResponseHeaders(); - obj.responseText = o.conn.responseText; - obj.responseXML = o.conn.responseXML; - if(callbackArg){ - obj.argument = callbackArg; - } - - return obj; - }, - - /** - * If a transaction cannot be completed due to dropped or closed connections, - * there may be not be enough information to build a full response object. - * The object's property "type" value will be "failure", and two additional - * unique, properties are added - errorCode and errorText. - * @private - * @param {int} tId Transaction Id - * @param callbackArg The user-defined arguments - * @param {string} errorCode Error code associated with the exception. - * @param {string} errorText Error message describing the exception. - * @return object - */ - createExceptionObject:function(tId, callbackArg) - { - var COMM_CODE = 0; - var COMM_ERROR = 'communication failure'; - - var obj = {}; - - obj.tId = tId; - obj.status = COMM_CODE; - obj.statusText = COMM_ERROR; - if(callbackArg){ - obj.argument = callbackArg; - } - - return obj; - }, - - /** - * Accessor that stores the HTTP headers for each transaction. - * @public - * @param {string} label The HTTP header label - * @param {string} value The HTTP header value - * @return void - */ - initHeader:function(label,value) - { - var oHeader = [label,value]; - this._http_header.push(oHeader); - }, - - /** - * Accessor that sets the HTTP headers for each transaction. - * @private - * @param {object} o The connection object for the transaction. - * @return void - */ - setHeader:function(o) - { - var oHeader = this._http_header; - for(var i=0;i= this.left && - region.right <= this.right && - region.top >= this.top && - region.bottom <= this.bottom ); -}; - -/** - * Returns the area of the region - * - * @return {int} the region's area - */ -YAHOO.util.Region.prototype.getArea = function() { - return ( (this.bottom - this.top) * (this.right - this.left) ); -}; - -/** - * Returns the region where the passed in region overlaps with this one - * - * @param {Region} region The region that intersects - * @return {Region} The overlap region, or null if there is no overlap - */ -YAHOO.util.Region.prototype.intersect = function(region) { - var t = Math.max( this.top, region.top ); - var r = Math.min( this.right, region.right ); - var b = Math.min( this.bottom, region.bottom ); - var l = Math.max( this.left, region.left ); - - if (b >= t && r >= l) { - return new YAHOO.util.Region(t, r, b, l); - } else { - return null; - } -}; - -/** - * Returns the region representing the smallest region that can contain both - * the passed in region and this region. - * - * @param {Region} region The region that to create the union with - * @return {Region} The union region - */ -YAHOO.util.Region.prototype.union = function(region) { - var t = Math.min( this.top, region.top ); - var r = Math.max( this.right, region.right ); - var b = Math.max( this.bottom, region.bottom ); - var l = Math.min( this.left, region.left ); - - return new YAHOO.util.Region(t, r, b, l); -}; - -/** - * toString - * @return string the region properties - */ -YAHOO.util.Region.prototype.toString = function() { - return ( "Region {" + - " t: " + this.top + - ", r: " + this.right + - ", b: " + this.bottom + - ", l: " + this.left + - "}" ); -} - -/** - * Returns a region that is occupied by the DOM element - * - * @param {HTMLElement} el The element - * @return {Region} The region that the element occupies - * @static - */ -YAHOO.util.Region.getRegion = function(el) { - var p = YAHOO.util.Dom.getXY(el); - - var t = p[1]; - var r = p[0] + el.offsetWidth; - var b = p[1] + el.offsetHeight; - var l = p[0]; - - return new YAHOO.util.Region(t, r, b, l); -}; - -///////////////////////////////////////////////////////////////////////////// - - -/** - * @class - * - * A point is a region that is special in that it represents a single point on - * the grid. - * - * @param {int} x The X position of the point - * @param {int} y The Y position of the point - * @constructor - * @extends Region - */ -YAHOO.util.Point = function(x, y) { - /** - * The X position of the point - * @type int - */ - this.x = x; - - /** - * The Y position of the point - * @type int - */ - this.y = y; - - this.top = y; - this.right = x; - this.bottom = y; - this.left = x; -}; - -YAHOO.util.Point.prototype = new YAHOO.util.Region(); Index: openacs-4/packages/ajaxhelper/www/yahoo/dragdrop/license.txt =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yahoo/dragdrop/Attic/license.txt,v diff -u -N --- openacs-4/packages/ajaxhelper/www/yahoo/dragdrop/license.txt 5 Apr 2006 06:38:43 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,35 +0,0 @@ -Software License Agreement (BSD License) - -Copyright (c) 2006, Yahoo! Inc. -All rights reserved. - -Redistribution and use of this software in source and binary forms, with -or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of Yahoo! Inc. nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of Yahoo! Inc. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Index: openacs-4/packages/ajaxhelper/www/yahoo/dragdrop/build/YAHOO.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yahoo/dragdrop/build/Attic/YAHOO.js,v diff -u -N --- openacs-4/packages/ajaxhelper/www/yahoo/dragdrop/build/YAHOO.js 5 Apr 2006 06:38:43 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,63 +0,0 @@ -/* -Copyright (c) 2006 Yahoo! Inc. All rights reserved. -version 0.9.0 -*/ - -/** - * @class The Yahoo global namespace - */ -var YAHOO = function() { - - return { - - /** - * Yahoo presentation platform utils namespace - */ - util: {}, - - /** - * Yahoo presentation platform widgets namespace - */ - widget: {}, - - /** - * Yahoo presentation platform examples namespace - */ - example: {}, - - /** - * Returns the namespace specified and creates it if it doesn't exist - * - * YAHOO.namespace("property.package"); - * YAHOO.namespace("YAHOO.property.package"); - * - * Either of the above would create YAHOO.property, then - * YAHOO.property.package - * - * @param {String} sNameSpace String representation of the desired - * namespace - * @return {Object} A reference to the namespace object - */ - namespace: function( sNameSpace ) { - - if (!sNameSpace || !sNameSpace.length) { - return null; - } - - var levels = sNameSpace.split("."); - - var currentNS = YAHOO; - - // YAHOO is implied, so it is ignored if it is included - for (var i=(levels[0] == "YAHOO") ? 1 : 0; i - *
  • linked element: the element that is passed into the constructor. - * This is the element which defines the boundaries for interaction with - * other DragDrop objects.
  • - *
  • handle element(s): The drag operation only occurs if the element that - * was clicked matches a handle element. By default this is the linked - * element, but there are times that you will want only a portion of the - * linked element to initiate the drag operation, and the setHandleElId() - * method provides a way to define this.
  • - *
  • drag element: this represents an the element that would be moved along - * with the cursor during a drag operation. By default, this is the linked - * element itself as in {@link YAHOO.util.DD}. setDragElId() lets you define - * a separate element that would be moved, as in {@link YAHOO.util.DDProxy} - *
  • - * - * This class should not be instantiated until the onload event to ensure that - * the associated elements are available. - * The following would define a DragDrop obj that would interact with any - * other * DragDrop obj in the "group1" group: - *
    - *  dd = new YAHOO.util.DragDrop("div1", "group1");
    - * 
    - * Since none of the event handlers have been implemented, nothing would - * actually happen if you were to run the code above. Normally you would - * override this class or one of the default implementations, but you can - * also override the methods you want on an instance of the class... - *
    - *  dd.onDragDrop = function(e, id) {
    - *   alert("dd was dropped on " + id);
    - *  }
    - * 
    - * @constructor - * @param {String} id of the element that is linked to this instance - * @param {String} sGroup the group of related DragDrop objects - */ -YAHOO.util.DragDrop = function(id, sGroup) { - if (id) { - this.init(id, sGroup); - } -}; - -YAHOO.util.DragDrop.prototype = { - - /** - * The id of the element associated with this object. This is what we - * refer to as the "linked element" because the size and position of - * this element is used to determine when the drag and drop objects have - * interacted. - * - * @type String - */ - id: null, - - /** - * The id of the element that will be dragged. By default this is same - * as the linked element , but could be changed to another element. Ex: - * YAHOO.util.DDProxy - * - * @type String - * @private - */ - dragElId: null, - - /** - * the id of the element that initiates the drag operation. By default - * this is the linked element, but could be changed to be a child of this - * element. This lets us do things like only starting the drag when the - * header element within the linked html element is clicked. - * - * @type String - * @private - */ - handleElId: null, - - /** - * An array of HTML tags that will be ignored if clicked. - */ - invalidHandleTypes: null, - - /** - * The linked element's absolute X position at the time the drag was - * started - * - * @type int - * @private - */ - startPageX: 0, - - /** - * The linked element's absolute X position at the time the drag was - * started - * - * @type int - * @private - */ - startPageY: 0, - - /** - * The group defines a logical collection of DragDrop objects that are - * related. Instances only get events when interacting with other - * DragDrop object in the same group. This lets us define multiple - * groups using a single DragDrop subclass if we want. - * - */ - groups: null, - - /** - * Individual drag/drop instances can be locked. This will prevent - * onmousedown start drag. - * - * @type boolean - * @private - */ - locked: false, - - /** - * Lock this instance - */ - lock: function() { this.locked = true; }, - - /** - * Unlock this instace - */ - unlock: function() { this.locked = false; }, - - /** - * By default, all insances can be a drop target. This can be disabled by - * setting isTarget to false. - * - * @type boolean - */ - isTarget: true, - - /** - * The padding configured for this drag and drop object for calculating - * the drop zone intersection with this object. - */ - padding: null, - - /** - * @private - */ - _domRef: null, - - /** - * Internal typeof flag - * @private - */ - __ygDragDrop: true, - - /** - * Set to true when horizontal contraints are applied - * - * @type boolean - * @private - */ - constrainX: false, - - /** - * Set to true when vertical contraints are applied - * - * @type boolean - * @private - */ - constrainY: false, - - /** - * The left constraint - * - * @type int - * @private - */ - minX: 0, - - /** - * The right constraint - * - * @type int - * @private - */ - maxX: 0, - - /** - * The up constraint - * - * @type int - * @private - */ - minY: 0, - - /** - * The down constraint - * - * @type int - * @private - */ - maxY: 0, - - /** - * Maintain offsets when we resetconstraints. Used to maintain the - * slider thumb value, and this needs to be fixed. - * @type boolean - */ - maintainOffset: false, - - /** - * Array of pixel locations the element will snap to if we specified a - * horizontal graduation/interval. This array is generated automatically - * when you define a tick interval. - * @type int[] - */ - xTicks: null, - - /** - * Array of pixel locations the element will snap to if we specified a - * vertical graduation/interval. This array is generated automatically - * when you define a tick interval. - * @type int[] - */ - yTicks: null, - - /** - * By default the drag and drop instance will only respond to the primary - * button click (left button for a right-handed mouse). Set to true to - * allow drag and drop to start with any mouse click that is propogated - * by the browser - * @type boolean - */ - primaryButtonOnly: true, - - /** - * Code that executes immediately before the startDrag event - * @private - */ - b4StartDrag: function(x, y) { }, - - /** - * Abstract method called after a drag/drop object is clicked - * and the drag or mousedown time thresholds have beeen met. - * - * @param {int} X click location - * @param {int} Y click location - */ - startDrag: function(x, y) { /* override this */ }, - - /** - * Code that executes immediately before the onDrag event - * @private - */ - b4Drag: function(e) { }, - - /** - * Abstract method called during the onMouseMove event while dragging an - * object. - * - * @param {Event} e - */ - onDrag: function(e) { /* override this */ }, - - /** - * Code that executes immediately before the onDragEnter event - * @private - */ - // b4DragEnter: function(e) { }, - - /** - * Abstract method called when this element fist begins hovering over - * another DragDrop obj - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this is hovering over. In INTERSECT mode, an array of one or more - * dragdrop items being hovered over. - */ - onDragEnter: function(e, id) { /* override this */ }, - - /** - * Code that executes immediately before the onDragOver event - * @private - */ - b4DragOver: function(e) { }, - - /** - * Abstract method called when this element is hovering over another - * DragDrop obj - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this is hovering over. In INTERSECT mode, an array of dd items - * being hovered over. - */ - onDragOver: function(e, id) { /* override this */ }, - - /** - * Code that executes immediately before the onDragOut event - * @private - */ - b4DragOut: function(e) { }, - - /** - * Abstract method called when we are no longer hovering over an element - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this was hovering over. In INTERSECT mode, an array of dd items - * that the mouse is no longer over. - */ - onDragOut: function(e, id) { /* override this */ }, - - /** - * Code that executes immediately before the onDragDrop event - * @private - */ - b4DragDrop: function(e) { }, - - /** - * Abstract method called when this item is dropped on another DragDrop - * obj - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this was dropped on. In INTERSECT mode, an array of dd items this - * was dropped on. - */ - onDragDrop: function(e, id) { /* override this */ }, - - /** - * Code that executes immediately before the endDrag event - * @private - */ - b4EndDrag: function(e) { }, - - /** - * Fired when we are done dragging the object - * - * @param {Event} e - */ - endDrag: function(e) { /* override this */ }, - - /** - * Code executed immediately before the onMouseDown event - - * @param {Event} e - * @private - */ - b4MouseDown: function(e) { }, - - /** - * Event handler that fires when a drag/drop obj gets a mousedown - * @param {Event} e - */ - onMouseDown: function(e) { /* override this */ }, - - /** - * Event handler that fires when a drag/drop obj gets a mouseup - * @param {Event} e - */ - onMouseUp: function(e) { /* override this */ }, - - /** - * Returns a reference to the linked element - * - * @return {Object} the html element - */ - getEl: function() { - if (!this._domRef) { - this._domRef = this.DDM.getElement(this.id); - } - - return this._domRef; - }, - - /** - * Returns a reference to the actual element to drag. By default this is - * the same as the html element, but it can be assigned to another - * element. An example of this can be found in YAHOO.util.DDProxy - * - * @return {Object} the html element - */ - getDragEl: function() { - return this.DDM.getElement(this.dragElId); - }, - - /** - * Sets up the DragDrop object. Must be called in the constructor of any - * YAHOO.util.DragDrop subclass - * - * @param id the id of the linked element - * @param {String} sGroup the group of related items - * element is supposed to be a target only, set to false. - */ - init: function(id, sGroup) { - this.initTarget(id, sGroup); - YAHOO.util.Event.addListener(id, "mousedown", - this.handleMouseDown, this, true); - }, - - /** - * Initializes Targeting functionality only... the object does not - * get a mousedown handler. - * - * @param id the id of the linked element - * @param {String} sGroup the group of related items - * element is supposed to be a target only, set to false. - */ - initTarget: function(id, sGroup) { - - // create a local reference to the drag and drop manager - this.DDM = YAHOO.util.DDM; - - // create a logger instance - this.logger = new ygLogger("DragDrop"); - - // set the default padding - this.padding = [0, 0, 0, 0]; - - // initialize the groups array - this.groups = {}; - - // set the id - this.id = id; - - // the element is a drag handle by default - this.setDragElId(id); - - // by default, clicked anchors will not start drag operations - this.invalidHandleTypes = {a : "a"}; - - // We don't want to register this as the handle with the manager - // so we just set the id rather than calling the setter - this.handleElId = id; - - // cache the position of the element if we can - if (document && document.body) { - this.setInitPosition(); - } - - // add to an interaction group - this.addToGroup((sGroup) ? sGroup : "default"); - - }, - - /** - * Configures the padding for the target zone in px. Effectively expands - * (or reduces) the virtual object size for targeting calculations. - * Supports css-style shorthand; if only one parameter is passed, all sides - * will have that padding, and if only two are passed, the top and bottom - * will have the first param, the left and right the second. - * @param {int} iTop Top pad - * @param {int} iRight Right pad - * @param {int} iBot Bot pad - * @param {int} iLeft Left pad - */ - setPadding: function(iTop, iRight, iBot, iLeft) { - // this.padding = [iLeft, iRight, iTop, iBot]; - if (!iRight && 0 !== iRight) { - this.padding = [iTop, iTop, iTop, iTop]; - } else if (!iBot && 0 !== iBot) { - this.padding = [iTop, iRight, iTop, iRight]; - } else { - this.padding = [iTop, iRight, iBot, iLeft]; - } - }, - - /** - * Stores the initial placement of the dd element - */ - setInitPosition: function(diffX, diffY) { - var el = this.getEl(); - - if (!this.DDM.verifyEl(el)) { - this.logger.debug(this.id + " element is broken"); - return; - } - - var dx = diffX || 0; - var dy = diffY || 0; - - var p = YAHOO.util.Dom.getXY( el ); - - this.initPageX = p[0] - dx; - this.initPageY = p[1] - dy; - - this.lastPageX = p[0]; - this.lastPageY = p[1]; - - this.setStartPosition(p); - }, - - /** - * Sets the start position of the element. This is set when the obj - * is initialized, the reset when a drag is started. - * @param pos current position (from previous lookup) - * @private - */ - setStartPosition: function(pos) { - - var p = pos || YAHOO.util.Dom.getXY( this.getEl() ); - - this.startPageX = p[0]; - this.startPageY = p[1]; - }, - - /** - * Add this instance to a group of related drag/drop objects. All - * instances belong to at least one group, and can belong to as many - * groups as needed. - * - * @param sGroup {string} the name of the group - */ - addToGroup: function(sGroup) { - this.groups[sGroup] = true; - this.DDM.regDragDrop(this, sGroup); - }, - - /** - * Allows you to specify that an element other than the linked element - * will be moved with the cursor during a drag - * - * @param id the id of the element that will be used to initiate the drag - */ - setDragElId: function(id) { - this.dragElId = id; - }, - - /** - * Allows you to specify a child of the linked element that should be - * used to initiate the drag operation. An example of this would be if - * you have a content div with text and links. Clicking anywhere in the - * content area would normally start the drag operation. Use this method - * to specify that an element inside of the content div is the element - * that starts the drag operation. - * - * @param id the id of the element that will be used to initiate the drag - */ - setHandleElId: function(id) { - this.handleElId = id; - this.DDM.regHandle(this.id, id); - }, - - /** - * Allows you to set an element outside of the linked element as a drag - * handle - */ - setOuterHandleElId: function(id) { - this.logger.debug("Adding outer handle event: " + id); - YAHOO.util.Event.addListener(id, "mousedown", - this.handleMouseDown, this, true); - this.setHandleElId(id); - }, - - /** - * Remove all drag and drop hooks for this element - */ - unreg: function() { - this.logger.debug("DragDrop obj cleanup " + this.id); - YAHOO.util.Event.removeListener(this.id, "mousedown", - this.handleMouseDown); - this._domRef = null; - this.DDM._remove(this); - }, - - /** - * Returns true if this instance is locked, or the drag drop mgr is locked - * (meaning that all drag/drop is disabled on the page.) - * - * @return {boolean} true if this obj or all drag/drop is locked, else - * false - */ - isLocked: function() { - return (this.DDM.isLocked() || this.locked); - }, - - /** - * Fired when this object is clicked - * - * @param {Event} e - * @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj) - * @private - */ - handleMouseDown: function(e, oDD) { - - this.logger.debug("isLocked: " + this.isLocked()); - - var EU = YAHOO.util.Event; - - - var button = e.which || e.button; - this.logger.debug("button: " + button); - - if (this.primaryButtonOnly && button > 1) { - this.logger.debug("Mousedown was not produced by the primary button"); - return; - } - - if (this.isLocked()) { - this.logger.debug("Drag and drop is disabled, aborting"); - return; - } - - this.logger.debug("mousedown " + this.id); - - this.DDM.refreshCache(this.groups); - - // Only process the event if we really clicked within the linked - // element. The reason we make this check is that in the case that - // another element was moved between the clicked element and the - // cursor in the time between the mousedown and mouseup events. When - // this happens, the element gets the next mousedown event - // regardless of where on the screen it happened. - var pt = new YAHOO.util.Point(EU.getPageX(e), EU.getPageY(e)); - if ( this.DDM.isOverTarget(pt, this) ) { - - this.logger.debug("click is legit"); - - // check to see if the handle was clicked - var srcEl = EU.getTarget(e); - - if (this.isValidHandleChild(srcEl) && - (this.id == this.handleElId || - this.DDM.handleWasClicked(srcEl, this.id)) ) { - - // set the initial element position - this.setStartPosition(); - - this.logger.debug("firing onMouseDown events"); - - - this.b4MouseDown(e); - this.onMouseDown(e); - this.DDM.handleMouseDown(e, this); - - this.DDM.stopEvent(e); - } - } - }, - - /** - * Allows you to specify a tag name that should not start a drag operation - * when clicked. This is designed to facilitate embedding links within a - * drag handle that do something other than start the drag. - * - * @param {string} tagName the type of element to exclude - */ - addInvalidHandleType: function(tagName) { - var type = tagName.toUpperCase(); - this.invalidHandleTypes[type] = type; - }, - - /** - * Unsets an excluded tag name set by addInvalidHandleType - * - * @param {string} tagName the type of element to unexclude - */ - removeInvalidHandleType: function(tagName) { - var type = tagName.toUpperCase(); - this.invalidHandleTypes[type] = null; - }, - - /** - * Checks the tag exclusion list to see if this click should be ignored - * - * @param {ygNode} node - * @return {boolean} true if this is a valid tag type, false if not - */ - isValidHandleChild: function(node) { - var type = node.nodeName; - - if (type == "#text") { - // this.logger.debug("text node, getting parent node type"); - type = node.parentNode.nodeName; - } - - return (!this.invalidHandleTypes[type]); - }, - - /** - * Create the array of horizontal tick marks if an interval was specified - * in setXConstraint(). - * - * @private - */ - setXTicks: function(iStartX, iTickSize) { - this.xTicks = []; - this.xTickSize = iTickSize; - - var tickMap = {}; - - for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) { - if (!tickMap[i]) { - this.xTicks[this.xTicks.length] = i; - tickMap[i] = true; - } - } - - for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) { - if (!tickMap[i]) { - this.xTicks[this.xTicks.length] = i; - tickMap[i] = true; - } - } - - this.xTicks.sort(this.DDM.numericSort) ; - this.logger.debug("xTicks: " + this.xTicks.join()); - }, - - /** - * Create the array of vertical tick marks if an interval was specified in - * setYConstraint(). - * - * @private - */ - setYTicks: function(iStartY, iTickSize) { - this.yTicks = []; - this.yTickSize = iTickSize; - - var tickMap = {}; - - for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) { - if (!tickMap[i]) { - this.yTicks[this.yTicks.length] = i; - tickMap[i] = true; - } - } - - for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) { - if (!tickMap[i]) { - this.yTicks[this.yTicks.length] = i; - tickMap[i] = true; - } - } - - this.yTicks.sort(this.DDM.numericSort) ; - this.logger.debug("yTicks: " + this.yTicks.join()); - }, - - /** - * By default, the element can be dragged any place on the screen. Use - * this method to limit the horizontal travel of the element. Pass in - * 0,0 for the parameters if you want to lock the drag to the y axis. - * - * @param {int} iLeft the number of pixels the element can move to the left - * @param {int} iRight the number of pixels the element can move to the - * right - * @param {int} iTickSize optional parameter for specifying that the - * element - * should move iTickSize pixels at a time. - */ - setXConstraint: function(iLeft, iRight, iTickSize) { - this.leftConstraint = iLeft; - this.rightConstraint = iRight; - - this.minX = this.initPageX - iLeft; - this.maxX = this.initPageX + iRight; - if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); } - - this.constrainX = true; - this.logger.debug("initPageX:" + this.initPageX + " minX:" + this.minX + - " maxX:" + this.maxX); - }, - - /** - * By default, the element can be dragged any place on the screen. Set - * this to limit the vertical travel of the element. Pass in 0,0 for the - * parameters if you want to lock the drag to the x axis. - * - * @param {int} iUp the number of pixels the element can move up - * @param {int} iDown the number of pixels the element can move down - * @param {int} iTickSize optional parameter for specifying that the - * element should move iTickSize pixels at a time. - */ - setYConstraint: function(iUp, iDown, iTickSize) { - this.topConstraint = iUp; - this.bottomConstraint = iDown; - - this.minY = this.initPageY - iUp; - this.maxY = this.initPageY + iDown; - if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); } - - this.constrainY = true; - - this.logger.debug("initPageY:" + this.initPageY + " minY:" + this.minY + - " maxY:" + this.maxY); - }, - - /** - * resetConstraints must be called if you manually reposition a dd element. - * @param {boolean} maintainOffset - */ - resetConstraints: function() { - - // this.logger.debug("init pagexy: " + this.initPageX + ", " + - // this.initPageY); - // this.logger.debug("last pagexy: " + this.lastPageX + ", " + - // this.lastPageY); - - // figure out how much this thing has moved - var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0; - var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0; - - // this.logger.debug("diff: " + dx + ", " + dy); - - // reset the initial location - this.setInitPosition(dx, dy); - - if (this.constrainX) { - this.setXConstraint( this.leftConstraint, - this.rightConstraint, - this.xTickSize ); - } - - if (this.constrainY) { - this.setYConstraint( this.topConstraint, - this.bottomConstraint, - this.yTickSize ); - } - }, - - /** - * Normally the drag element is moved pixel by pixel, but we can specify - * that it move a number of pixels at a time. This method resolves the - * location when we have it set up like this. - * - * @param {int} val where we want to place the object - * @param {int[]} tickArray sorted array of valid points - * @return {int} the closest tick - * @private - */ - getTick: function(val, tickArray) { - - if (!tickArray) { - // If tick interval is not defined, it is effectively 1 pixel, - // so we return the value passed to us. - return val; - } else if (tickArray[0] >= val) { - // The value is lower than the first tick, so we return the first - // tick. - return tickArray[0]; - } else { - for (var i = 0; i < tickArray.length; ++i) { - var next = i + 1; - if (tickArray[next] && tickArray[next] >= val) { - var diff1 = val - tickArray[i]; - var diff2 = tickArray[next] - val; - return (diff2 > diff1) ? tickArray[i] : tickArray[next]; - } - } - - // The value is larger than the last tick, so we return the last - // tick. - return tickArray[tickArray.length - 1]; - } - }, - - /** - * toString method - * @return {string} string representation of the dd obj - */ - toString: function(val, tickArray) { - return ("YAHOO.util.DragDrop {" + this.id + "}"); - } - -}; - -/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */ - -// Only load the library once. Rewriting the manager class would orphan -// existing drag and drop instances. -if (!YAHOO.util.DragDropMgr) { - - /** - * @class Handles the element interaction for all DragDrop items in the - * window. Generally, you will not call this class directly, but it does - * have helper methods that could be useful in your DragDrop - * implementations. This class should not be instantiated; all methods - * are are static. - * - * @constructor - */ - YAHOO.util.DragDropMgr = new function() { - - /** - * utility package shorthand - * @private - */ - var UTIL = YAHOO.util; - - /** - * Two dimensional Array of registered DragDrop objects. The first - * dimension is the DragDrop item group, the second the DragDrop - * object. - * - * @private - */ - this.ids = {}; - - /** - * Array of element ids defined as drag handles. Used to determine - * if the element that generated the mousedown event is actually the - * handle and not the html element itself. - * - * @private - */ - this.handleIds = {}; - - /** - * the DragDrop object that is currently being dragged - * - * @type DragDrop - * @private - **/ - this.dragCurrent = null; - - /** - * the DragDrop object(s) that are being hovered over - * - * @type Array - * @private - */ - this.dragOvers = {}; - - /** - * @private - */ - this.logger = null; - - /** - * the X distance between the cursor and the object being dragged - * - * @type int - * @private - */ - this.deltaX = 0; - - /** - * the Y distance between the cursor and the object being dragged - * - * @type int - * @private - */ - this.deltaY = 0; - - /** - * Flag to determine if we should prevent the default behavior of the - * events we define. By default this is true, but this can be set to - * false if you need the default behavior (not recommended) - * - * @type boolean - */ - this.preventDefault = true; - - /** - * Flag to determine if we should stop the propagation of the events - * we generate. This is true by default but you may want to set it to - * false if the html element contains other features that require the - * mouse click. - * - * @type boolean - */ - this.stopPropagation = true; - - /** - * @private - */ - this.initalized = false; - - /** - * All drag and drop can be disabled. - * - * @private - */ - this.locked = false; - - /** - * Called the first time an element is registered. - * - * @private - */ - this.init = function() { - this.logger = new ygLogger("DragDropMgr"); - }; - - /** - * In point mode, drag and drop interaction is defined by the - * location of the cursor during the drag/drop - * @type int - */ - this.POINT = 0; - - /** - * In intersect mode, drag and drop interactio nis defined by the - * overlap of two or more drag and drop objects. - * @type int - */ - this.INTERSECT = 1; - - /** - * The current drag and drop mode. Default it point mode - * @type int - */ - this.mode = this.POINT; - - /** - * Runs method on all drag and drop objects - * @private - */ - this._execOnAll = function(sMethod, args) { - for (var i in this.ids) { - for (var j in this.ids[i]) { - var oDD = this.ids[i][j]; - if (! this.isTypeOfDD(oDD)) { - continue; - } - oDD[sMethod].apply(oDD, args); - } - } - }; - - /** - * Drag and drop initialization. Sets up the global event handlers - * @private - */ - this._onLoad = function() { - - this._execOnAll("setInitPosition", []); - - this.logger = new ygLogger("DragDropMgr"); - this.logger.debug("DDM onload"); - - var EU = UTIL.Event; - - EU.addListener(document, "mouseup", this.handleMouseUp, this, true); - EU.addListener(document, "mousemove", this.handleMouseMove, this, true); - EU.addListener(window, "unload", this._onUnload, this, true); - EU.addListener(window, "resize", this._onResize, this, true); - // EU.addListener(window, "mouseout", this._test); - - this.initalized = true; - - }; - - /** - * Reset constraints on all drag and drop objs - * @private - */ - this._onResize = function(e) { - this.logger.debug("window resize"); - this._execOnAll("resetConstraints", []); - }; - - /** - * Lock all drag and drop functionality - */ - this.lock = function() { this.locked = true; }; - - /** - * Unlock all drag and drop functionality - */ - this.unlock = function() { this.locked = false; }; - - /** - * Is drag and drop locked? - * - * @return {boolean} True if drag and drop is locked, false otherwise. - */ - this.isLocked = function() { return this.locked; }; - - /** - * Location cache that is set for all drag drop objects when a drag is - * initiated, cleared when the drag is finished. - * - * @private - */ - this.locationCache = {}; - - /** - * Set useCache to false if you want to force object the lookup of each - * drag and drop linked element constantly during a drag. - * @type boolean - */ - this.useCache = true; - - /** - * The number of pixels that the mouse needs to move after the - * mousedown before the drag is initiated. Default=3; - * @type int - */ - this.clickPixelThresh = 3; - - /** - * The number of milliseconds after the mousedown event to initiate the - * drag if we don't get a mouseup event. Default=1000 - * @type int - */ - this.clickTimeThresh = 1000; - - /** - * Flag that indicates that either the drag pixel threshold or the - * mousdown time threshold has been met - * @type boolean - * @private - */ - this.dragThreshMet = false; - - /** - * Timeout used for the click time threshold - * @type Object - * @private - */ - this.clickTimeout = null; - - /** - * The X position of the mousedown event stored for later use when a - * drag threshold is met. - * @type int - * @private - */ - this.startX = 0; - - /** - * The Y position of the mousedown event stored for later use when a - * drag threshold is met. - * @type int - * @private - */ - this.startY = 0; - - /** - * Each DragDrop instance must be registered with the DragDropMgr. - * This is executed in ygDragDrop.init() - * - * @param {DragDrop} oDD the DragDrop object to register - * @param {String} sGroup the name of the group this element belongs to - */ - this.regDragDrop = function(oDD, sGroup) { - if (!this.initialized) { this.init(); } - - if (!this.ids[sGroup]) { - this.ids[sGroup] = {}; - } - this.ids[sGroup][oDD.id] = oDD; - }; - - /** - * Unregisters a drag and drop item. This is executed in - * ygDragDrop.unreg, use that method instead of calling this directly. - * @private - */ - this._remove = function(oDD) { - for (var g in oDD.groups) { - if (g && this.ids[g][oDD.id]) { - delete this.ids[g][oDD.id]; - } - } - delete this.handleIds[oDD.id]; - }; - - /** - * Each DragDrop handle element must be registered. This is done - * automatically when executing ygDragDrop.setHandleElId() - * - * @param {String} sDDId the DragDrop id this element is a handle for - * @param {String} sHandleId the id of the element that is the drag - * handle - */ - this.regHandle = function(sDDId, sHandleId) { - if (!this.handleIds[sDDId]) { - this.handleIds[sDDId] = {}; - } - this.handleIds[sDDId][sHandleId] = sHandleId; - }; - - /** - * Utility function to determine if a given element has been - * registered as a drag drop item. - * - * @param {String} id the element id to check - * @return {boolean} true if this element is a DragDrop item, - * false otherwise - */ - this.isDragDrop = function(id) { - return ( this.getDDById(id) ) ? true : false; - }; - - /** - * Returns the drag and drop instances that are in all groups the - * passed in instance belongs to. - * - * @param {ygDragDrop} p_oDD the obj to get related data for - * @param {boolean} bTargetsOnly if true, only return targetable objs - * @return {ygDragDrop[]} the related instances - */ - this.getRelated = function(p_oDD, bTargetsOnly) { - var oDDs = []; - for (var i in p_oDD.groups) { - for (j in this.ids[i]) { - var dd = this.ids[i][j]; - if (! this.isTypeOfDD(dd)) { - continue; - } - if (!bTargetsOnly || dd.isTarget) { - oDDs[oDDs.length] = dd; - } - } - } - - return oDDs; - }; - - /** - * Returns true if the specified dd target is a legal target for - * the specifice drag obj - * - * @param {ygDragDrop} the drag obj - * @param {ygDragDrop) the target - * @return {boolean} true if the target is a legal target for the - * dd obj - */ - this.isLegalTarget = function (oDD, oTargetDD) { - var targets = this.getRelated(oDD); - for (var i =0;i this.clickPixelThresh || - diffY > this.clickPixelThresh) { - this.logger.debug("pixel threshold met"); - this.startDrag(this.startX, this.startY); - } - } - - if (this.dragThreshMet) { - this.dragCurrent.b4Drag(e); - this.dragCurrent.onDrag(e); - this.fireEvents(e, false); - } - - this.stopEvent(e); - }; - - /** - * Iterates over all of the DragDrop elements to find ones we are - * hovering over or dropping on - * - * @param {Event} e the event - * @param {boolean} isDrop is this a drop op or a mouseover op? - * @private - */ - this.fireEvents = function(e, isDrop) { - var dc = this.dragCurrent; - - // If the user did the mouse up outside of the window, we could - // get here even though we have ended the drag. - if (!dc || dc.isLocked()) { - return; - } - - var x = UTIL.Event.getPageX(e); - var y = UTIL.Event.getPageY(e); - var pt = new YAHOO.util.Point(x,y); - - // cache the previous dragOver array - var oldOvers = []; - - var outEvts = []; - var overEvts = []; - var dropEvts = []; - var enterEvts = []; - - // Check to see if the object we were hovering over is no longer - // being hovered over so we can fire the onDragOut event - for (var i in this.dragOvers) { - - var ddo = this.dragOvers[i]; - - if (! this.isTypeOfDD(ddo)) { - continue; - } - - if (! this.isOverTarget(pt, ddo, this.mode)) { - outEvts.push( ddo ); - } - - oldOvers[i] = true; - delete this.dragOvers[i]; - } - - for (var sGroup in dc.groups) { - // this.logger.debug("Processing group " + sGroup); - - if ("string" != typeof sGroup) { - continue; - } - - for (i in this.ids[sGroup]) { - var oDD = this.ids[sGroup][i]; - if (! this.isTypeOfDD(oDD)) { - continue; - } - - if (oDD.isTarget && !oDD.isLocked() && oDD != dc) { - if (this.isOverTarget(pt, oDD, this.mode)) { - // look for drop interactions - if (isDrop) { - dropEvts.push( oDD ); - // look for drag enter and drag over interactions - } else { - - // initial drag over: dragEnter fires - if (!oldOvers[oDD.id]) { - enterEvts.push( oDD ); - // subsequent drag overs: dragOver fires - } else { - overEvts.push( oDD ); - } - - this.dragOvers[oDD.id] = oDD; - } - } - } - } - } - - if (this.mode) { - if (outEvts.length > 0) { - dc.b4DragOut(e, outEvts); - dc.onDragOut(e, outEvts); - } - - if (enterEvts.length > 0) { - dc.onDragEnter(e, enterEvts); - } - - if (overEvts.length > 0) { - dc.b4DragOver(e, overEvts); - dc.onDragOver(e, overEvts); - } - - if (dropEvts.length > 0) { - dc.b4DragDrop(e, dropEvts); - dc.onDragDrop(e, dropEvts); - } - - } else { - // fire dragout events - for (i=0; i < outEvts.length; ++i) { - this.logger.debug(dc.id+" onDragOut: " + outEvts[i].id); - dc.b4DragOut(e, outEvts[i].id); - dc.onDragOut(e, outEvts[i].id); - } - - // fire enter events - for (i=0; i < enterEvts.length; ++i) { - this.logger.debug(dc.id + " dragEnter " + enterEvts[i].id); - // dc.b4DragEnter(e, oDD.id); - dc.onDragEnter(e, enterEvts[i].id); - } - - // fire over events - for (i=0; i < overEvts.length; ++i) { - this.logger.debug(dc.id + " dragOver " + overEvts[i].id); - dc.b4DragOver(e, overEvts[i].id); - dc.onDragOver(e, overEvts[i].id); - } - - // fire drop events - for (i=0; i < dropEvts.length; ++i) { - this.logger.debug(dc.id + " dragDrop " + dropEvts[i].id); - dc.b4DragDrop(e, dropEvts[i].id); - dc.onDragDrop(e, dropEvts[i].id); - } - - } - - }; - - /** - * Helper function for getting the best match from the list of drag - * and drop objects returned by the drag and drop events when we are - * in INTERSECT mode. It returns either the first object that the - * cursor is over, or the object that has the greatest overlap with - * the dragged element. - * - * @param {ygDragDrop[]} dds The array of drag and drop objects - * targeted - * @return {ygDragDrop} The best single match - */ - this.getBestMatch = function(dds) { - var winner = null; - // Return null if the input is not what we expect - //if (!dds || !dds.length || dds.length == 0) { - // winner = null; - // If there is only one item, it wins - //} else if (dds.length == 1) { - - if (dds.length == 1) { - winner = dds[0]; - } else { - // Loop through the targeted items - for (var i=0; i= loc[3] && x <= loc[1] && y >= loc[0] && y <= loc[2]); - //oDDTarget.cursorIsOver = loc.contains( new YAHOO.util.Point(x, y) ); - oDDTarget.cursorIsOver = loc.contains( pt ); - oDDTarget.overlap = null; - - // if (this.INTERSECT == this.mode) { - if (intersect) { - - var curRegion = - YAHOO.util.Region.getRegion(this.dragCurrent.getDragEl()); - var overlap = curRegion.intersect(loc); - - if (overlap) { - oDDTarget.overlap = overlap; - return true; - } else { - return false; - } - - } else { - return oDDTarget.cursorIsOver; - } - }; - - /** - * @private - */ - this._onUnload = function(e, me) { - this.unregAll(); - }; - - /** - * Cleans up the drag and drop events and objects. - * - * @private - */ - this.unregAll = function() { - this.logger.debug("unregister all"); - - if (this.dragCurrent) { - this.stopDrag(); - this.dragCurrent = null; - } - - this._execOnAll("unreg", []); - - for (i in this.elementCache) { - delete this.elementCache[i]; - } - - this.elementCache = {}; - this.ids = {}; - }; - - /** - * A cache of DOM elements - * - * @private - */ - this.elementCache = {}; - - /** - * Get the wrapper for the DOM element specified - * - * @param {String} id the id of the elment to get - * @return {YAHOO.util.DDM.ElementWrapper} the wrapped element - * @private - */ - this.getElWrapper = function(id) { - var oWrapper = this.elementCache[id]; - if (!oWrapper || !oWrapper.el) { - // this.logger.debug("adding element cache: " + id); - oWrapper = this.elementCache[id] = - new this.ElementWrapper(document.getElementById(id)); - } - return oWrapper; - }; - - /** - * Returns the actual DOM element - * - * @param {String} id the id of the elment to get - * @return {Object} The element - */ - this.getElement = function(id) { - // return this.getElWrapper(id).el; - return document.getElementById(id); - }; - - /** - * Returns the style property for the DOM element (i.e., - * document.getElById(id).style) - * - * @param {String} id the id of the elment to get - * @return {Object} The style property of the element - */ - this.getCss = function(id) { - // return this.getElWrapper(id).css; - var css = null; - var el = document.getElementById(id); - if (el) { - css = el.style; - } - - return css; - }; - - /** - * Inner class for cached elements - */ - this.ElementWrapper = function(el) { - /** - * @private - */ - this.el = el || null; - /** - * @private - */ - this.id = this.el && el.id; - /** - * @private - */ - this.css = this.el && el.style; - }; - - /** - * Returns the X position of an html element - * @param el the element for which to get the position - * @return {int} the X coordinate - */ - this.getPosX = function(el) { - return YAHOO.util.Dom.getX(el); - }; - - /** - * Returns the Y position of an html element - * @param el the element for which to get the position - * @return {int} the Y coordinate - */ - this.getPosY = function(el) { - return YAHOO.util.Dom.getY(el); - }; - - /** - * Swap two nodes. In IE, we use the native method, for others we - * emulate the IE behavior - * - * @param n1 the first node to swap - * @param n2 the other node to swap - */ - this.swapNode = function(n1, n2) { - if (n1.swapNode) { - n1.swapNode(n2); - } else { - // the node reference order for the swap is a little tricky. - var p = n2.parentNode; - var s = n2.nextSibling; - n1.parentNode.replaceChild(n2,n1); - p.insertBefore(n1,s); - } - }; - - /** - * @private - */ - this.getScroll = function () { - var t, l; - if (document.documentElement && document.documentElement.scrollTop) { - t = document.documentElement.scrollTop; - l = document.documentElement.scrollLeft; - } else if (document.body) { - t = document.body.scrollTop; - l = document.body.scrollLeft; - } - return { top: t, left: l }; - }; - - /** - * Returns the specified element style property - * @param {HTMLElement} el the element - * @param {string} styleProp the style property - * @return {string} The value of the style property - */ - this.getStyle = function(el, styleProp) { - if (el.style.styleProp) { - return el.style.styleProp; - } else if (el.currentStyle) { - return el.currentStyle[styleProp]; - } else if (document.defaultView) { - return document.defaultView.getComputedStyle(el, null). - getPropertyValue(styleProp); - } - }; - - /** - * Gets the scrollTop - * - * @return {int} the document's scrollTop - */ - this.getScrollTop = function () { return this.getScroll().top; }; - - /** - * Gets the scrollLeft - * - * @return {int} the document's scrollTop - */ - this.getScrollLeft = function () { return this.getScroll().left; }; - - this.moveToEl = function (moveEl, targetEl) { - var aCoord = YAHOO.util.Dom.getXY(targetEl); - this.logger.debug("moveToEl: " + aCoord); - YAHOO.util.Dom.setXY(moveEl, aCoord); - }; - - /** - * Gets the client height - * - * @return {int} client height in px - */ - this.getClientHeight = function() { - return (window.innerHeight) ? window.innerHeight : - (document.documentElement && document.documentElement.clientHeight) ? - document.documentElement.clientHeight : document.body.offsetHeight; - }; - - /** - * Gets the client width - * - * @return {int} client width in px - */ - this.getClientWidth = function() { - return (window.innerWidth) ? window.innerWidth : - (document.documentElement && document.documentElement.clientWidth) ? - document.documentElement.clientWidth : document.body.offsetWidth; - }; - - /** - * numeric array sort function - */ - this.numericSort = function(a, b) { return (a - b); }; - - /** - * @private - */ - this._timeoutCount = 0; - - /** - * @private - * Trying to make the load order less important. Without this we get - * an error if this file is loaded before the Event Utility. - */ - this._addListeners = function() { - if ( UTIL.Event && - document && - document.body ) { - - this._onLoad(); - } else { - if (this._timeoutCount > 500) { - this.logger.debug("DragDrop requires the Event Utility"); - } else { - setTimeout("YAHOO.util.DDM._addListeners()", 10); - this._timeoutCount += 1; - } - } - - }; - - /** - * Recursively searches the immediate parent and all child nodes for - * the handle element in order to determine wheter or not it was - * clicked. - * - * @param node the html element to inspect - */ - this.handleWasClicked = function(node, id) { - if (this.isHandle(id, node.id)) { - this.logger.debug("clicked node is a handle"); - return true; - } else { - // check to see if this is a text node child of the one we want - var p = node.parentNode; - // this.logger.debug("p: " + p); - - while (p) { - if (this.isHandle(id, p.id)) { - return true; - } else { - this.logger.debug(p.id + " is not a handle"); - p = p.parentNode; - } - } - } - - return false; - }; - - }; - - // shorter alias, save a few bytes - YAHOO.util.DDM = YAHOO.util.DragDropMgr; - YAHOO.util.DDM._addListeners(); - -} - -/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */ - -/** - * @class a DragDrop implementation where the linked element follows the - * mouse cursor. - * - * @extends DragDrop - * @constructor - * @param {String} id the id of the linked element - * @param {String} sGroup the group of related DragDrop items - */ -YAHOO.util.DD = function(id, sGroup) { - if (id) { - this.init(id, sGroup); - this.logger.setModuleName("DD"); - } -}; - -YAHOO.util.DD.prototype = new YAHOO.util.DragDrop(); - -/** - * Should we auto-scroll? Defaults to true - * - * @type boolean - */ -YAHOO.util.DD.prototype.scroll = true; - -/** - * Sets the pointer offset to the distance between the linked element's top - * left corner and the location the element was clicked - * - * @param {int} iPageX the X coordinate of the click - * @param {int} iPageY the Y coordinate of the click - */ -YAHOO.util.DD.prototype.autoOffset = function(iPageX, iPageY) { - var el = this.getEl(); - var aCoord = YAHOO.util.Dom.getXY(el); - var x = iPageX - aCoord[0]; - var y = iPageY - aCoord[1]; - this.setDelta(x, y); - this.logger.debug("autoOffset el pos: " + aCoord + ", delta: " + x + "," + y); -}; - -/** - * Sets the pointer offset. You can call this directly to force the offset to - * be in a particular location (e.g., pass in 0,0 to set it to the center of the - * object, as done in ygDDSliderBG) - * - * @param {int} iDeltaX the distance from the left - * @param {int} iDeltaY the distance from the top - */ -YAHOO.util.DD.prototype.setDelta = function(iDeltaX, iDeltaY) { - this.deltaX = iDeltaX; - this.deltaY = iDeltaY; - this.logger.debug("deltaX:" + this.deltaX + ", deltaY:" + this.deltaY); -}; - -/** - * Sets the drag element to the location of the mousedown or click event, - * maintaining the cursor location relative to the location on the element - * that was clicked. Override this if you want to place the element in a - * location other than where the cursor is. - * - * @param {int} iPageX the X coordinate of the mousedown or drag event - * @param {int} iPageY the Y coordinate of the mousedown or drag event - */ - -YAHOO.util.DD.prototype.setDragElPos = function(iPageX, iPageY) { - this.alignElWithMouse(this.getDragEl(), iPageX, iPageY); -}; - -/** - * Sets the element to the location of the mousedown or click event, - * maintaining the cursor location relative to the location on the element - * that was clicked. Override this if you want to place the element in a - * location other than where the cursor is. - * - * @param {HTMLElement} el the element to move - * @param {int} iPageX the X coordinate of the mousedown or drag event - * @param {int} iPageY the Y coordinate of the mousedown or drag event - */ -YAHOO.util.DD.prototype.alignElWithMouse = function(el, iPageX, iPageY) { - var oCoord = this.getTargetCoord(iPageX, iPageY); - var aCoord = [oCoord.x, oCoord.y]; - // this.logger.debug("****alignElWithMouse : " + el.id + ", " + aCoord + ", " + el.style.display); - YAHOO.util.Dom.setXY(el, aCoord); - - this.cachePosition(oCoord.x, oCoord.y); - - this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth); -}; - -/** - * Saves the most recent position so that we can reset the constraints and - * tick marks on-demand. We need to know this so that we can calculate the - * number of pixels the element is offset from its original position. - */ -YAHOO.util.DD.prototype.cachePosition = function(iPageX, iPageY) { - if (iPageX) { - this.lastPageX = iPageX; - this.lastPageY = iPageY; - } else { - var aCoord = YAHOO.util.Dom.getXY(this.getEl()); - this.lastPageX = aCoord[0]; - this.lastPageY = aCoord[1]; - } -}; - -/** - * Auto-scroll the window if the dragged object has been moved beyond the - * visible window boundary. - * - * @param {int} x the drag element's x position - * @param {int} y the drag element's y position - * @param {int} h the height of the drag element - * @param {int} w the width of the drag element - * @private - */ -YAHOO.util.DD.prototype.autoScroll = function(x, y, h, w) { - - if (this.scroll) { - // The client height - var clientH = this.DDM.getClientHeight(); - - // The client width - var clientW = this.DDM.getClientWidth(); - - // The amt scrolled down - var st = this.DDM.getScrollTop(); - - // The amt scrolled right - var sl = this.DDM.getScrollLeft(); - - // Location of the bottom of the element - var bot = h + y; - - // Location of the right of the element - var right = w + x; - - // The distance from the cursor to the bottom of the visible area, - // adjusted so that we don't scroll if the cursor is beyond the - // element drag constraints - var toBot = (clientH + st - y - this.deltaY); - - // The distance from the cursor to the right of the visible area - var toRight = (clientW + sl - x - this.deltaX); - - // this.logger.debug( " x: " + x + " y: " + y + " h: " + h + - // " clientH: " + clientH + " clientW: " + clientW + - // " st: " + st + " sl: " + sl + " bot: " + bot + - // " right: " + right + " toBot: " + toBot + " toRight: " + toRight); - - // How close to the edge the cursor must be before we scroll - // var thresh = (document.all) ? 100 : 40; - var thresh = 40; - - // How many pixels to scroll per autoscroll op. This helps to reduce - // clunky scrolling. IE is more sensitive about this ... it needs this - // value to be higher. - var scrAmt = (document.all) ? 80 : 30; - - // Scroll down if we are near the bottom of the visible page and the - // obj extends below the crease - if ( bot > clientH && toBot < thresh ) { - window.scrollTo(sl, st + scrAmt); - } - - // Scroll up if the window is scrolled down and the top of the object - // goes above the top border - if ( y < st && st > 0 && y - st < thresh ) { - window.scrollTo(sl, st - scrAmt); - } - - // Scroll right if the obj is beyond the right border and the cursor is - // near the border. - if ( right > clientW && toRight < thresh ) { - window.scrollTo(sl + scrAmt, st); - } - - // Scroll left if the window has been scrolled to the right and the obj - // extends past the left border - if ( x < sl && sl > 0 && x - sl < thresh ) { - window.scrollTo(sl - scrAmt, st); - } - } -}; - -/** - * Finds the location the element should be placed if we want to move - * it to where the mouse location less the click offset would place us. - * - * @param {int} iPageX the X coordinate of the click - * @param {int} iPageY the Y coordinate of the click - * @return an object that contains the coordinates (Object.x and Object.y) - * @private - */ -YAHOO.util.DD.prototype.getTargetCoord = function(iPageX, iPageY) { - - // this.logger.debug("getTargetCoord: " + iPageX + ", " + iPageY); - - var x = iPageX - this.deltaX; - var y = iPageY - this.deltaY; - - if (this.constrainX) { - if (x < this.minX) { x = this.minX; } - if (x > this.maxX) { x = this.maxX; } - } - - if (this.constrainY) { - if (y < this.minY) { y = this.minY; } - if (y > this.maxY) { y = this.maxY; } - } - - x = this.getTick(x, this.xTicks); - y = this.getTick(y, this.yTicks); - - // this.logger.debug("getTargetCoord " + - // " iPageX: " + iPageX + - // " iPageY: " + iPageY + - // " x: " + x + ", y: " + y); - - return {x:x, y:y}; -}; - -// overrides YAHOO.util.DragDrop -YAHOO.util.DD.prototype.b4MouseDown = function(e) { - // this.resetConstraints(); - this.autoOffset(YAHOO.util.Event.getPageX(e), - YAHOO.util.Event.getPageY(e)); -}; - -// overrides YAHOO.util.DragDrop -YAHOO.util.DD.prototype.b4Drag = function(e) { - this.setDragElPos(YAHOO.util.Event.getPageX(e), - YAHOO.util.Event.getPageY(e)); -}; - - -/////////////////////////////////////////////////////////////////////////////// -// Debugging ygDragDrop events that can be overridden -/////////////////////////////////////////////////////////////////////////////// -/* -YAHOO.util.DD.prototype.startDrag = function(x, y) { - this.logger.debug(this.id.toString() + " startDrag"); -}; - -YAHOO.util.DD.prototype.onDrag = function(e) { - this.logger.debug(this.id.toString() + " onDrag"); -}; - -YAHOO.util.DD.prototype.onDragEnter = function(e, id) { - this.logger.debug(this.id.toString() + " onDragEnter: " + id); -}; - -YAHOO.util.DD.prototype.onDragOver = function(e, id) { - this.logger.debug(this.id.toString() + " onDragOver: " + id); -}; - -YAHOO.util.DD.prototype.onDragOut = function(e, id) { - this.logger.debug(this.id.toString() + " onDragOut: " + id); -}; - -YAHOO.util.DD.prototype.onDragDrop = function(e, id) { - this.logger.debug(this.id.toString() + " onDragDrop: " + id); -}; - -YAHOO.util.DD.prototype.endDrag = function(e) { - this.logger.debug(this.id.toString() + " endDrag"); -}; -*/ - -/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */ - -/** - * @class a DragDrop implementation that inserts an empty, bordered div into - * the document that follows the cursor during drag operations. At the time of - * the click, the frame div is resized to the dimensions of the linked html - * element, and moved to the exact location of the linked element. - * - * @extends YAHOO.util.DD - * @constructor - * @param {String} id the id of the linked html element - * @param {String} sGroup the group of related DragDrop objects - */ -YAHOO.util.DDProxy = function(id, sGroup) { - if (id) { - this.init(id, sGroup); - this.initFrame(); - this.logger.setModuleName("DDProxy"); - } -}; - -YAHOO.util.DDProxy.prototype = new YAHOO.util.DD(); - -/** - * A reference to the one div element we create for all instances of this class - * - * @type Object - */ -YAHOO.util.DDProxy.frameDiv = null; - -/** - * the drag frame div id - * - * @type String - */ -YAHOO.util.DDProxy.dragElId = "ygddfdiv"; - -/** - * The border width of the frame. This is used when we resize the frame to - * the size of the linked element. We substract the border width to make - * the div the correct size. - * - * @TODO find a better way to handle this - * - * @type int - */ -YAHOO.util.DDProxy.prototype.borderWidth = 2; - -/** - * By default we resize the drag frame to be the same size as the element - * we want to drag (this is to get the frame effect). We can turn it off - * if we want a different behavior (ex: ygDDMy2) - * - * @type boolean - */ -YAHOO.util.DDProxy.prototype.resizeFrame = true; - -/** - * By default the frame is positioned exactly where the drag element is, so - * we use the cursor offset provided by YAHOO.util.DD. Another option that works only if - * you do not have constraints on the obj is to have the drag frame centered - * around the cursor. Set centerFrame to true for this effect. Ex: - * ygDDMy2 - * - * @type boolean - */ -YAHOO.util.DDProxy.prototype.centerFrame = false; - -/** - * Create the drag frame if needed - */ -YAHOO.util.DDProxy.createFrame = function() { - var THIS = YAHOO.util.DDProxy; - - if (!document || !document.body) { - setTimeout(THIS.createFrame, 50); - return; - } - - if (!THIS.frameDiv) { - THIS.frameDiv = document.createElement("div"); - THIS.frameDiv.id = THIS.dragElId; - var s = THIS.frameDiv.style; - s.position = "absolute"; - s.visibility = "hidden"; - s.cursor = "move"; - s.border = "2px solid #aaa"; - s.zIndex = 999; - - document.body.appendChild(THIS.frameDiv); - } -}; - -/** - * Initialization for the drag frame element. Must be called in the - * constructor of all subclasses - */ -YAHOO.util.DDProxy.prototype.initFrame = function() { - YAHOO.util.DDProxy.createFrame(); - this.setDragElId(YAHOO.util.DDProxy.dragElId); - this.useAbsMath = true; -}; - -/** - * Resizes the drag frame to the dimensions of the clicked object, positions - * it over the object, and finally displays it - * - * @param {int} iPageX X click position - * @param {int} iPageY Y click position - * @private - */ -YAHOO.util.DDProxy.prototype.showFrame = function(iPageX, iPageY) { - var el = this.getEl(); - - var s = this.getDragEl().style; - - if (this.resizeFrame) { - s.width = (parseInt(el.offsetWidth) - (2*this.borderWidth)) + "px"; - s.height = (parseInt(el.offsetHeight) - (2*this.borderWidth)) + "px"; - } - - if (this.centerFrame) { - this.setDelta(Math.round(parseInt(s.width)/2), - Math.round(parseInt(s.width)/2)); - } - - this.setDragElPos(iPageX, iPageY); - - s.visibility = ""; -}; - -// overrides YAHOO.util.DragDrop -YAHOO.util.DDProxy.prototype.b4MouseDown = function(e) { - var x = YAHOO.util.Event.getPageX(e); - var y = YAHOO.util.Event.getPageY(e); - this.autoOffset(x, y); - this.setDragElPos(x, y); -}; - -// overrides YAHOO.util.DragDrop -YAHOO.util.DDProxy.prototype.b4StartDrag = function(x, y) { - // show the drag frame - this.logger.debug("start drag show frame, x: " + x + ", y: " + y); - this.showFrame(x, y); -}; - -// overrides YAHOO.util.DragDrop -YAHOO.util.DDProxy.prototype.b4EndDrag = function(e) { - this.logger.debug(this.id + " b4EndDrag"); - - // hide the drag frame - var s = this.getDragEl().style; - s.visibility = "hidden"; -}; - -// overrides YAHOO.util.DragDrop -// By default we try to move the element to the last location of the frame. -// This is so that the default behavior mirrors that of YAHOO.util.DD. -YAHOO.util.DDProxy.prototype.endDrag = function(e) { - this.logger.debug(this.id + " endDrag"); - var lel = this.getEl(); - var del = this.getDragEl(); - - // Show the drag frame briefly so we can get its position - del.style.visibility = ""; - - // Hide the linked element before the move to get around a Safari - // rendering bug. - lel.style.visibility = "hidden"; - YAHOO.util.DDM.moveToEl(lel, del); - del.style.visibility = "hidden"; - lel.style.visibility = ""; -}; - -/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */ - -/** - * @class a DragDrop implementation that does not move, but can be a drop - * target. You would get the same result by simply omitting implementation - * for the event callbacks, but this way we reduce the processing cost of the - * event listener and the callbacks. - * - * @extends YAHOO.util.DragDrop - * @constructor - * @param {String} id the id of the element that is a drop target - * @param {String} sGroup the group of related DragDrop objects - */ - -YAHOO.util.DDTarget = function(id, sGroup) { - if (id) { - this.initTarget(id, sGroup); - this.logger.setModuleName("DDTarget"); - } -}; - -YAHOO.util.DDTarget.prototype = new YAHOO.util.DragDrop(); - Index: openacs-4/packages/ajaxhelper/www/yahoo/dragdrop/build/dragdrop.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yahoo/dragdrop/build/Attic/dragdrop.js,v diff -u -N --- openacs-4/packages/ajaxhelper/www/yahoo/dragdrop/build/dragdrop.js 5 Apr 2006 06:38:43 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,2426 +0,0 @@ -/* -Copyright (c) 2006 Yahoo! Inc. All rights reserved. -version 0.9.0 -*/ - -/** - * @class Defines the interface and base operation of items that that can be - * dragged or can be drop targets. It was designed to be extended, overriding - * the event handlers for startDrag, onDrag, onDragOver, onDragOut. - * Up to three html elements can be associated with a DragDrop instance: - *
      - *
    • linked element: the element that is passed into the constructor. - * This is the element which defines the boundaries for interaction with - * other DragDrop objects.
    • - *
    • handle element(s): The drag operation only occurs if the element that - * was clicked matches a handle element. By default this is the linked - * element, but there are times that you will want only a portion of the - * linked element to initiate the drag operation, and the setHandleElId() - * method provides a way to define this.
    • - *
    • drag element: this represents an the element that would be moved along - * with the cursor during a drag operation. By default, this is the linked - * element itself as in {@link YAHOO.util.DD}. setDragElId() lets you define - * a separate element that would be moved, as in {@link YAHOO.util.DDProxy} - *
    • - *
    - * This class should not be instantiated until the onload event to ensure that - * the associated elements are available. - * The following would define a DragDrop obj that would interact with any - * other * DragDrop obj in the "group1" group: - *
    - *  dd = new YAHOO.util.DragDrop("div1", "group1");
    - * 
    - * Since none of the event handlers have been implemented, nothing would - * actually happen if you were to run the code above. Normally you would - * override this class or one of the default implementations, but you can - * also override the methods you want on an instance of the class... - *
    - *  dd.onDragDrop = function(e, id) {
    - *   alert("dd was dropped on " + id);
    - *  }
    - * 
    - * @constructor - * @param {String} id of the element that is linked to this instance - * @param {String} sGroup the group of related DragDrop objects - */ -YAHOO.util.DragDrop = function(id, sGroup) { - if (id) { - this.init(id, sGroup); - } -}; - -YAHOO.util.DragDrop.prototype = { - - /** - * The id of the element associated with this object. This is what we - * refer to as the "linked element" because the size and position of - * this element is used to determine when the drag and drop objects have - * interacted. - * - * @type String - */ - id: null, - - /** - * The id of the element that will be dragged. By default this is same - * as the linked element , but could be changed to another element. Ex: - * YAHOO.util.DDProxy - * - * @type String - * @private - */ - dragElId: null, - - /** - * the id of the element that initiates the drag operation. By default - * this is the linked element, but could be changed to be a child of this - * element. This lets us do things like only starting the drag when the - * header element within the linked html element is clicked. - * - * @type String - * @private - */ - handleElId: null, - - /** - * An array of HTML tags that will be ignored if clicked. - */ - invalidHandleTypes: null, - - /** - * The linked element's absolute X position at the time the drag was - * started - * - * @type int - * @private - */ - startPageX: 0, - - /** - * The linked element's absolute X position at the time the drag was - * started - * - * @type int - * @private - */ - startPageY: 0, - - /** - * The group defines a logical collection of DragDrop objects that are - * related. Instances only get events when interacting with other - * DragDrop object in the same group. This lets us define multiple - * groups using a single DragDrop subclass if we want. - * - */ - groups: null, - - /** - * Individual drag/drop instances can be locked. This will prevent - * onmousedown start drag. - * - * @type boolean - * @private - */ - locked: false, - - /** - * Lock this instance - */ - lock: function() { this.locked = true; }, - - /** - * Unlock this instace - */ - unlock: function() { this.locked = false; }, - - /** - * By default, all insances can be a drop target. This can be disabled by - * setting isTarget to false. - * - * @type boolean - */ - isTarget: true, - - /** - * The padding configured for this drag and drop object for calculating - * the drop zone intersection with this object. - */ - padding: null, - - /** - * @private - */ - _domRef: null, - - /** - * Internal typeof flag - * @private - */ - __ygDragDrop: true, - - /** - * Set to true when horizontal contraints are applied - * - * @type boolean - * @private - */ - constrainX: false, - - /** - * Set to true when vertical contraints are applied - * - * @type boolean - * @private - */ - constrainY: false, - - /** - * The left constraint - * - * @type int - * @private - */ - minX: 0, - - /** - * The right constraint - * - * @type int - * @private - */ - maxX: 0, - - /** - * The up constraint - * - * @type int - * @private - */ - minY: 0, - - /** - * The down constraint - * - * @type int - * @private - */ - maxY: 0, - - /** - * Maintain offsets when we resetconstraints. Used to maintain the - * slider thumb value, and this needs to be fixed. - * @type boolean - */ - maintainOffset: false, - - /** - * Array of pixel locations the element will snap to if we specified a - * horizontal graduation/interval. This array is generated automatically - * when you define a tick interval. - * @type int[] - */ - xTicks: null, - - /** - * Array of pixel locations the element will snap to if we specified a - * vertical graduation/interval. This array is generated automatically - * when you define a tick interval. - * @type int[] - */ - yTicks: null, - - /** - * By default the drag and drop instance will only respond to the primary - * button click (left button for a right-handed mouse). Set to true to - * allow drag and drop to start with any mouse click that is propogated - * by the browser - * @type boolean - */ - primaryButtonOnly: true, - - /** - * Code that executes immediately before the startDrag event - * @private - */ - b4StartDrag: function(x, y) { }, - - /** - * Abstract method called after a drag/drop object is clicked - * and the drag or mousedown time thresholds have beeen met. - * - * @param {int} X click location - * @param {int} Y click location - */ - startDrag: function(x, y) { /* override this */ }, - - /** - * Code that executes immediately before the onDrag event - * @private - */ - b4Drag: function(e) { }, - - /** - * Abstract method called during the onMouseMove event while dragging an - * object. - * - * @param {Event} e - */ - onDrag: function(e) { /* override this */ }, - - /** - * Code that executes immediately before the onDragEnter event - * @private - */ - // b4DragEnter: function(e) { }, - - /** - * Abstract method called when this element fist begins hovering over - * another DragDrop obj - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this is hovering over. In INTERSECT mode, an array of one or more - * dragdrop items being hovered over. - */ - onDragEnter: function(e, id) { /* override this */ }, - - /** - * Code that executes immediately before the onDragOver event - * @private - */ - b4DragOver: function(e) { }, - - /** - * Abstract method called when this element is hovering over another - * DragDrop obj - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this is hovering over. In INTERSECT mode, an array of dd items - * being hovered over. - */ - onDragOver: function(e, id) { /* override this */ }, - - /** - * Code that executes immediately before the onDragOut event - * @private - */ - b4DragOut: function(e) { }, - - /** - * Abstract method called when we are no longer hovering over an element - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this was hovering over. In INTERSECT mode, an array of dd items - * that the mouse is no longer over. - */ - onDragOut: function(e, id) { /* override this */ }, - - /** - * Code that executes immediately before the onDragDrop event - * @private - */ - b4DragDrop: function(e) { }, - - /** - * Abstract method called when this item is dropped on another DragDrop - * obj - * - * @param {Event} e - * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element - * id this was dropped on. In INTERSECT mode, an array of dd items this - * was dropped on. - */ - onDragDrop: function(e, id) { /* override this */ }, - - /** - * Code that executes immediately before the endDrag event - * @private - */ - b4EndDrag: function(e) { }, - - /** - * Fired when we are done dragging the object - * - * @param {Event} e - */ - endDrag: function(e) { /* override this */ }, - - /** - * Code executed immediately before the onMouseDown event - - * @param {Event} e - * @private - */ - b4MouseDown: function(e) { }, - - /** - * Event handler that fires when a drag/drop obj gets a mousedown - * @param {Event} e - */ - onMouseDown: function(e) { /* override this */ }, - - /** - * Event handler that fires when a drag/drop obj gets a mouseup - * @param {Event} e - */ - onMouseUp: function(e) { /* override this */ }, - - /** - * Returns a reference to the linked element - * - * @return {Object} the html element - */ - getEl: function() { - if (!this._domRef) { - this._domRef = this.DDM.getElement(this.id); - } - - return this._domRef; - }, - - /** - * Returns a reference to the actual element to drag. By default this is - * the same as the html element, but it can be assigned to another - * element. An example of this can be found in YAHOO.util.DDProxy - * - * @return {Object} the html element - */ - getDragEl: function() { - return this.DDM.getElement(this.dragElId); - }, - - /** - * Sets up the DragDrop object. Must be called in the constructor of any - * YAHOO.util.DragDrop subclass - * - * @param id the id of the linked element - * @param {String} sGroup the group of related items - * element is supposed to be a target only, set to false. - */ - init: function(id, sGroup) { - this.initTarget(id, sGroup); - YAHOO.util.Event.addListener(id, "mousedown", - this.handleMouseDown, this, true); - }, - - /** - * Initializes Targeting functionality only... the object does not - * get a mousedown handler. - * - * @param id the id of the linked element - * @param {String} sGroup the group of related items - * element is supposed to be a target only, set to false. - */ - initTarget: function(id, sGroup) { - - // create a local reference to the drag and drop manager - this.DDM = YAHOO.util.DDM; - - - // set the default padding - this.padding = [0, 0, 0, 0]; - - // initialize the groups array - this.groups = {}; - - // set the id - this.id = id; - - // the element is a drag handle by default - this.setDragElId(id); - - // by default, clicked anchors will not start drag operations - this.invalidHandleTypes = {a : "a"}; - - // We don't want to register this as the handle with the manager - // so we just set the id rather than calling the setter - this.handleElId = id; - - // cache the position of the element if we can - if (document && document.body) { - this.setInitPosition(); - } - - // add to an interaction group - this.addToGroup((sGroup) ? sGroup : "default"); - - }, - - /** - * Configures the padding for the target zone in px. Effectively expands - * (or reduces) the virtual object size for targeting calculations. - * Supports css-style shorthand; if only one parameter is passed, all sides - * will have that padding, and if only two are passed, the top and bottom - * will have the first param, the left and right the second. - * @param {int} iTop Top pad - * @param {int} iRight Right pad - * @param {int} iBot Bot pad - * @param {int} iLeft Left pad - */ - setPadding: function(iTop, iRight, iBot, iLeft) { - // this.padding = [iLeft, iRight, iTop, iBot]; - if (!iRight && 0 !== iRight) { - this.padding = [iTop, iTop, iTop, iTop]; - } else if (!iBot && 0 !== iBot) { - this.padding = [iTop, iRight, iTop, iRight]; - } else { - this.padding = [iTop, iRight, iBot, iLeft]; - } - }, - - /** - * Stores the initial placement of the dd element - */ - setInitPosition: function(diffX, diffY) { - var el = this.getEl(); - - if (!this.DDM.verifyEl(el)) { - return; - } - - var dx = diffX || 0; - var dy = diffY || 0; - - var p = YAHOO.util.Dom.getXY( el ); - - this.initPageX = p[0] - dx; - this.initPageY = p[1] - dy; - - this.lastPageX = p[0]; - this.lastPageY = p[1]; - - this.setStartPosition(p); - }, - - /** - * Sets the start position of the element. This is set when the obj - * is initialized, the reset when a drag is started. - * @param pos current position (from previous lookup) - * @private - */ - setStartPosition: function(pos) { - - var p = pos || YAHOO.util.Dom.getXY( this.getEl() ); - - this.startPageX = p[0]; - this.startPageY = p[1]; - }, - - /** - * Add this instance to a group of related drag/drop objects. All - * instances belong to at least one group, and can belong to as many - * groups as needed. - * - * @param sGroup {string} the name of the group - */ - addToGroup: function(sGroup) { - this.groups[sGroup] = true; - this.DDM.regDragDrop(this, sGroup); - }, - - /** - * Allows you to specify that an element other than the linked element - * will be moved with the cursor during a drag - * - * @param id the id of the element that will be used to initiate the drag - */ - setDragElId: function(id) { - this.dragElId = id; - }, - - /** - * Allows you to specify a child of the linked element that should be - * used to initiate the drag operation. An example of this would be if - * you have a content div with text and links. Clicking anywhere in the - * content area would normally start the drag operation. Use this method - * to specify that an element inside of the content div is the element - * that starts the drag operation. - * - * @param id the id of the element that will be used to initiate the drag - */ - setHandleElId: function(id) { - this.handleElId = id; - this.DDM.regHandle(this.id, id); - }, - - /** - * Allows you to set an element outside of the linked element as a drag - * handle - */ - setOuterHandleElId: function(id) { - YAHOO.util.Event.addListener(id, "mousedown", - this.handleMouseDown, this, true); - this.setHandleElId(id); - }, - - /** - * Remove all drag and drop hooks for this element - */ - unreg: function() { - YAHOO.util.Event.removeListener(this.id, "mousedown", - this.handleMouseDown); - this._domRef = null; - this.DDM._remove(this); - }, - - /** - * Returns true if this instance is locked, or the drag drop mgr is locked - * (meaning that all drag/drop is disabled on the page.) - * - * @return {boolean} true if this obj or all drag/drop is locked, else - * false - */ - isLocked: function() { - return (this.DDM.isLocked() || this.locked); - }, - - /** - * Fired when this object is clicked - * - * @param {Event} e - * @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj) - * @private - */ - handleMouseDown: function(e, oDD) { - - - var EU = YAHOO.util.Event; - - - var button = e.which || e.button; - - if (this.primaryButtonOnly && button > 1) { - return; - } - - if (this.isLocked()) { - return; - } - - - this.DDM.refreshCache(this.groups); - - // Only process the event if we really clicked within the linked - // element. The reason we make this check is that in the case that - // another element was moved between the clicked element and the - // cursor in the time between the mousedown and mouseup events. When - // this happens, the element gets the next mousedown event - // regardless of where on the screen it happened. - var pt = new YAHOO.util.Point(EU.getPageX(e), EU.getPageY(e)); - if ( this.DDM.isOverTarget(pt, this) ) { - - - // check to see if the handle was clicked - var srcEl = EU.getTarget(e); - - if (this.isValidHandleChild(srcEl) && - (this.id == this.handleElId || - this.DDM.handleWasClicked(srcEl, this.id)) ) { - - // set the initial element position - this.setStartPosition(); - - - this.b4MouseDown(e); - this.onMouseDown(e); - this.DDM.handleMouseDown(e, this); - - this.DDM.stopEvent(e); - } - } - }, - - /** - * Allows you to specify a tag name that should not start a drag operation - * when clicked. This is designed to facilitate embedding links within a - * drag handle that do something other than start the drag. - * - * @param {string} tagName the type of element to exclude - */ - addInvalidHandleType: function(tagName) { - var type = tagName.toUpperCase(); - this.invalidHandleTypes[type] = type; - }, - - /** - * Unsets an excluded tag name set by addInvalidHandleType - * - * @param {string} tagName the type of element to unexclude - */ - removeInvalidHandleType: function(tagName) { - var type = tagName.toUpperCase(); - this.invalidHandleTypes[type] = null; - }, - - /** - * Checks the tag exclusion list to see if this click should be ignored - * - * @param {ygNode} node - * @return {boolean} true if this is a valid tag type, false if not - */ - isValidHandleChild: function(node) { - var type = node.nodeName; - - if (type == "#text") { - type = node.parentNode.nodeName; - } - - return (!this.invalidHandleTypes[type]); - }, - - /** - * Create the array of horizontal tick marks if an interval was specified - * in setXConstraint(). - * - * @private - */ - setXTicks: function(iStartX, iTickSize) { - this.xTicks = []; - this.xTickSize = iTickSize; - - var tickMap = {}; - - for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) { - if (!tickMap[i]) { - this.xTicks[this.xTicks.length] = i; - tickMap[i] = true; - } - } - - for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) { - if (!tickMap[i]) { - this.xTicks[this.xTicks.length] = i; - tickMap[i] = true; - } - } - - this.xTicks.sort(this.DDM.numericSort) ; - }, - - /** - * Create the array of vertical tick marks if an interval was specified in - * setYConstraint(). - * - * @private - */ - setYTicks: function(iStartY, iTickSize) { - this.yTicks = []; - this.yTickSize = iTickSize; - - var tickMap = {}; - - for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) { - if (!tickMap[i]) { - this.yTicks[this.yTicks.length] = i; - tickMap[i] = true; - } - } - - for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) { - if (!tickMap[i]) { - this.yTicks[this.yTicks.length] = i; - tickMap[i] = true; - } - } - - this.yTicks.sort(this.DDM.numericSort) ; - }, - - /** - * By default, the element can be dragged any place on the screen. Use - * this method to limit the horizontal travel of the element. Pass in - * 0,0 for the parameters if you want to lock the drag to the y axis. - * - * @param {int} iLeft the number of pixels the element can move to the left - * @param {int} iRight the number of pixels the element can move to the - * right - * @param {int} iTickSize optional parameter for specifying that the - * element - * should move iTickSize pixels at a time. - */ - setXConstraint: function(iLeft, iRight, iTickSize) { - this.leftConstraint = iLeft; - this.rightConstraint = iRight; - - this.minX = this.initPageX - iLeft; - this.maxX = this.initPageX + iRight; - if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); } - - this.constrainX = true; - }, - - /** - * By default, the element can be dragged any place on the screen. Set - * this to limit the vertical travel of the element. Pass in 0,0 for the - * parameters if you want to lock the drag to the x axis. - * - * @param {int} iUp the number of pixels the element can move up - * @param {int} iDown the number of pixels the element can move down - * @param {int} iTickSize optional parameter for specifying that the - * element should move iTickSize pixels at a time. - */ - setYConstraint: function(iUp, iDown, iTickSize) { - this.topConstraint = iUp; - this.bottomConstraint = iDown; - - this.minY = this.initPageY - iUp; - this.maxY = this.initPageY + iDown; - if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); } - - this.constrainY = true; - - }, - - /** - * resetConstraints must be called if you manually reposition a dd element. - * @param {boolean} maintainOffset - */ - resetConstraints: function() { - - - // figure out how much this thing has moved - var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0; - var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0; - - - // reset the initial location - this.setInitPosition(dx, dy); - - if (this.constrainX) { - this.setXConstraint( this.leftConstraint, - this.rightConstraint, - this.xTickSize ); - } - - if (this.constrainY) { - this.setYConstraint( this.topConstraint, - this.bottomConstraint, - this.yTickSize ); - } - }, - - /** - * Normally the drag element is moved pixel by pixel, but we can specify - * that it move a number of pixels at a time. This method resolves the - * location when we have it set up like this. - * - * @param {int} val where we want to place the object - * @param {int[]} tickArray sorted array of valid points - * @return {int} the closest tick - * @private - */ - getTick: function(val, tickArray) { - - if (!tickArray) { - // If tick interval is not defined, it is effectively 1 pixel, - // so we return the value passed to us. - return val; - } else if (tickArray[0] >= val) { - // The value is lower than the first tick, so we return the first - // tick. - return tickArray[0]; - } else { - for (var i = 0; i < tickArray.length; ++i) { - var next = i + 1; - if (tickArray[next] && tickArray[next] >= val) { - var diff1 = val - tickArray[i]; - var diff2 = tickArray[next] - val; - return (diff2 > diff1) ? tickArray[i] : tickArray[next]; - } - } - - // The value is larger than the last tick, so we return the last - // tick. - return tickArray[tickArray.length - 1]; - } - }, - - /** - * toString method - * @return {string} string representation of the dd obj - */ - toString: function(val, tickArray) { - return ("YAHOO.util.DragDrop {" + this.id + "}"); - } - -}; - -/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */ - -// Only load the library once. Rewriting the manager class would orphan -// existing drag and drop instances. -if (!YAHOO.util.DragDropMgr) { - - /** - * @class Handles the element interaction for all DragDrop items in the - * window. Generally, you will not call this class directly, but it does - * have helper methods that could be useful in your DragDrop - * implementations. This class should not be instantiated; all methods - * are are static. - * - * @constructor - */ - YAHOO.util.DragDropMgr = new function() { - - /** - * utility package shorthand - * @private - */ - var UTIL = YAHOO.util; - - /** - * Two dimensional Array of registered DragDrop objects. The first - * dimension is the DragDrop item group, the second the DragDrop - * object. - * - * @private - */ - this.ids = {}; - - /** - * Array of element ids defined as drag handles. Used to determine - * if the element that generated the mousedown event is actually the - * handle and not the html element itself. - * - * @private - */ - this.handleIds = {}; - - /** - * the DragDrop object that is currently being dragged - * - * @type DragDrop - * @private - **/ - this.dragCurrent = null; - - /** - * the DragDrop object(s) that are being hovered over - * - * @type Array - * @private - */ - this.dragOvers = {}; - - /** - * @private - */ - - /** - * the X distance between the cursor and the object being dragged - * - * @type int - * @private - */ - this.deltaX = 0; - - /** - * the Y distance between the cursor and the object being dragged - * - * @type int - * @private - */ - this.deltaY = 0; - - /** - * Flag to determine if we should prevent the default behavior of the - * events we define. By default this is true, but this can be set to - * false if you need the default behavior (not recommended) - * - * @type boolean - */ - this.preventDefault = true; - - /** - * Flag to determine if we should stop the propagation of the events - * we generate. This is true by default but you may want to set it to - * false if the html element contains other features that require the - * mouse click. - * - * @type boolean - */ - this.stopPropagation = true; - - /** - * @private - */ - this.initalized = false; - - /** - * All drag and drop can be disabled. - * - * @private - */ - this.locked = false; - - /** - * Called the first time an element is registered. - * - * @private - */ - this.init = function() { - }; - - /** - * In point mode, drag and drop interaction is defined by the - * location of the cursor during the drag/drop - * @type int - */ - this.POINT = 0; - - /** - * In intersect mode, drag and drop interactio nis defined by the - * overlap of two or more drag and drop objects. - * @type int - */ - this.INTERSECT = 1; - - /** - * The current drag and drop mode. Default it point mode - * @type int - */ - this.mode = this.POINT; - - /** - * Runs method on all drag and drop objects - * @private - */ - this._execOnAll = function(sMethod, args) { - for (var i in this.ids) { - for (var j in this.ids[i]) { - var oDD = this.ids[i][j]; - if (! this.isTypeOfDD(oDD)) { - continue; - } - oDD[sMethod].apply(oDD, args); - } - } - }; - - /** - * Drag and drop initialization. Sets up the global event handlers - * @private - */ - this._onLoad = function() { - - this._execOnAll("setInitPosition", []); - - - var EU = UTIL.Event; - - EU.addListener(document, "mouseup", this.handleMouseUp, this, true); - EU.addListener(document, "mousemove", this.handleMouseMove, this, true); - EU.addListener(window, "unload", this._onUnload, this, true); - EU.addListener(window, "resize", this._onResize, this, true); - // EU.addListener(window, "mouseout", this._test); - - this.initalized = true; - - }; - - /** - * Reset constraints on all drag and drop objs - * @private - */ - this._onResize = function(e) { - this._execOnAll("resetConstraints", []); - }; - - /** - * Lock all drag and drop functionality - */ - this.lock = function() { this.locked = true; }; - - /** - * Unlock all drag and drop functionality - */ - this.unlock = function() { this.locked = false; }; - - /** - * Is drag and drop locked? - * - * @return {boolean} True if drag and drop is locked, false otherwise. - */ - this.isLocked = function() { return this.locked; }; - - /** - * Location cache that is set for all drag drop objects when a drag is - * initiated, cleared when the drag is finished. - * - * @private - */ - this.locationCache = {}; - - /** - * Set useCache to false if you want to force object the lookup of each - * drag and drop linked element constantly during a drag. - * @type boolean - */ - this.useCache = true; - - /** - * The number of pixels that the mouse needs to move after the - * mousedown before the drag is initiated. Default=3; - * @type int - */ - this.clickPixelThresh = 3; - - /** - * The number of milliseconds after the mousedown event to initiate the - * drag if we don't get a mouseup event. Default=1000 - * @type int - */ - this.clickTimeThresh = 1000; - - /** - * Flag that indicates that either the drag pixel threshold or the - * mousdown time threshold has been met - * @type boolean - * @private - */ - this.dragThreshMet = false; - - /** - * Timeout used for the click time threshold - * @type Object - * @private - */ - this.clickTimeout = null; - - /** - * The X position of the mousedown event stored for later use when a - * drag threshold is met. - * @type int - * @private - */ - this.startX = 0; - - /** - * The Y position of the mousedown event stored for later use when a - * drag threshold is met. - * @type int - * @private - */ - this.startY = 0; - - /** - * Each DragDrop instance must be registered with the DragDropMgr. - * This is executed in ygDragDrop.init() - * - * @param {DragDrop} oDD the DragDrop object to register - * @param {String} sGroup the name of the group this element belongs to - */ - this.regDragDrop = function(oDD, sGroup) { - if (!this.initialized) { this.init(); } - - if (!this.ids[sGroup]) { - this.ids[sGroup] = {}; - } - this.ids[sGroup][oDD.id] = oDD; - }; - - /** - * Unregisters a drag and drop item. This is executed in - * ygDragDrop.unreg, use that method instead of calling this directly. - * @private - */ - this._remove = function(oDD) { - for (var g in oDD.groups) { - if (g && this.ids[g][oDD.id]) { - delete this.ids[g][oDD.id]; - } - } - delete this.handleIds[oDD.id]; - }; - - /** - * Each DragDrop handle element must be registered. This is done - * automatically when executing ygDragDrop.setHandleElId() - * - * @param {String} sDDId the DragDrop id this element is a handle for - * @param {String} sHandleId the id of the element that is the drag - * handle - */ - this.regHandle = function(sDDId, sHandleId) { - if (!this.handleIds[sDDId]) { - this.handleIds[sDDId] = {}; - } - this.handleIds[sDDId][sHandleId] = sHandleId; - }; - - /** - * Utility function to determine if a given element has been - * registered as a drag drop item. - * - * @param {String} id the element id to check - * @return {boolean} true if this element is a DragDrop item, - * false otherwise - */ - this.isDragDrop = function(id) { - return ( this.getDDById(id) ) ? true : false; - }; - - /** - * Returns the drag and drop instances that are in all groups the - * passed in instance belongs to. - * - * @param {ygDragDrop} p_oDD the obj to get related data for - * @param {boolean} bTargetsOnly if true, only return targetable objs - * @return {ygDragDrop[]} the related instances - */ - this.getRelated = function(p_oDD, bTargetsOnly) { - var oDDs = []; - for (var i in p_oDD.groups) { - for (j in this.ids[i]) { - var dd = this.ids[i][j]; - if (! this.isTypeOfDD(dd)) { - continue; - } - if (!bTargetsOnly || dd.isTarget) { - oDDs[oDDs.length] = dd; - } - } - } - - return oDDs; - }; - - /** - * Returns true if the specified dd target is a legal target for - * the specifice drag obj - * - * @param {ygDragDrop} the drag obj - * @param {ygDragDrop) the target - * @return {boolean} true if the target is a legal target for the - * dd obj - */ - this.isLegalTarget = function (oDD, oTargetDD) { - var targets = this.getRelated(oDD); - for (var i =0;i this.clickPixelThresh || - diffY > this.clickPixelThresh) { - this.startDrag(this.startX, this.startY); - } - } - - if (this.dragThreshMet) { - this.dragCurrent.b4Drag(e); - this.dragCurrent.onDrag(e); - this.fireEvents(e, false); - } - - this.stopEvent(e); - }; - - /** - * Iterates over all of the DragDrop elements to find ones we are - * hovering over or dropping on - * - * @param {Event} e the event - * @param {boolean} isDrop is this a drop op or a mouseover op? - * @private - */ - this.fireEvents = function(e, isDrop) { - var dc = this.dragCurrent; - - // If the user did the mouse up outside of the window, we could - // get here even though we have ended the drag. - if (!dc || dc.isLocked()) { - return; - } - - var x = UTIL.Event.getPageX(e); - var y = UTIL.Event.getPageY(e); - var pt = new YAHOO.util.Point(x,y); - - // cache the previous dragOver array - var oldOvers = []; - - var outEvts = []; - var overEvts = []; - var dropEvts = []; - var enterEvts = []; - - // Check to see if the object we were hovering over is no longer - // being hovered over so we can fire the onDragOut event - for (var i in this.dragOvers) { - - var ddo = this.dragOvers[i]; - - if (! this.isTypeOfDD(ddo)) { - continue; - } - - if (! this.isOverTarget(pt, ddo, this.mode)) { - outEvts.push( ddo ); - } - - oldOvers[i] = true; - delete this.dragOvers[i]; - } - - for (var sGroup in dc.groups) { - - if ("string" != typeof sGroup) { - continue; - } - - for (i in this.ids[sGroup]) { - var oDD = this.ids[sGroup][i]; - if (! this.isTypeOfDD(oDD)) { - continue; - } - - if (oDD.isTarget && !oDD.isLocked() && oDD != dc) { - if (this.isOverTarget(pt, oDD, this.mode)) { - // look for drop interactions - if (isDrop) { - dropEvts.push( oDD ); - // look for drag enter and drag over interactions - } else { - - // initial drag over: dragEnter fires - if (!oldOvers[oDD.id]) { - enterEvts.push( oDD ); - // subsequent drag overs: dragOver fires - } else { - overEvts.push( oDD ); - } - - this.dragOvers[oDD.id] = oDD; - } - } - } - } - } - - if (this.mode) { - if (outEvts.length > 0) { - dc.b4DragOut(e, outEvts); - dc.onDragOut(e, outEvts); - } - - if (enterEvts.length > 0) { - dc.onDragEnter(e, enterEvts); - } - - if (overEvts.length > 0) { - dc.b4DragOver(e, overEvts); - dc.onDragOver(e, overEvts); - } - - if (dropEvts.length > 0) { - dc.b4DragDrop(e, dropEvts); - dc.onDragDrop(e, dropEvts); - } - - } else { - // fire dragout events - for (i=0; i < outEvts.length; ++i) { - dc.b4DragOut(e, outEvts[i].id); - dc.onDragOut(e, outEvts[i].id); - } - - // fire enter events - for (i=0; i < enterEvts.length; ++i) { - // dc.b4DragEnter(e, oDD.id); - dc.onDragEnter(e, enterEvts[i].id); - } - - // fire over events - for (i=0; i < overEvts.length; ++i) { - dc.b4DragOver(e, overEvts[i].id); - dc.onDragOver(e, overEvts[i].id); - } - - // fire drop events - for (i=0; i < dropEvts.length; ++i) { - dc.b4DragDrop(e, dropEvts[i].id); - dc.onDragDrop(e, dropEvts[i].id); - } - - } - - }; - - /** - * Helper function for getting the best match from the list of drag - * and drop objects returned by the drag and drop events when we are - * in INTERSECT mode. It returns either the first object that the - * cursor is over, or the object that has the greatest overlap with - * the dragged element. - * - * @param {ygDragDrop[]} dds The array of drag and drop objects - * targeted - * @return {ygDragDrop} The best single match - */ - this.getBestMatch = function(dds) { - var winner = null; - // Return null if the input is not what we expect - //if (!dds || !dds.length || dds.length == 0) { - // winner = null; - // If there is only one item, it wins - //} else if (dds.length == 1) { - - if (dds.length == 1) { - winner = dds[0]; - } else { - // Loop through the targeted items - for (var i=0; i= loc[3] && x <= loc[1] && y >= loc[0] && y <= loc[2]); - //oDDTarget.cursorIsOver = loc.contains( new YAHOO.util.Point(x, y) ); - oDDTarget.cursorIsOver = loc.contains( pt ); - oDDTarget.overlap = null; - - // if (this.INTERSECT == this.mode) { - if (intersect) { - - var curRegion = - YAHOO.util.Region.getRegion(this.dragCurrent.getDragEl()); - var overlap = curRegion.intersect(loc); - - if (overlap) { - oDDTarget.overlap = overlap; - return true; - } else { - return false; - } - - } else { - return oDDTarget.cursorIsOver; - } - }; - - /** - * @private - */ - this._onUnload = function(e, me) { - this.unregAll(); - }; - - /** - * Cleans up the drag and drop events and objects. - * - * @private - */ - this.unregAll = function() { - - if (this.dragCurrent) { - this.stopDrag(); - this.dragCurrent = null; - } - - this._execOnAll("unreg", []); - - for (i in this.elementCache) { - delete this.elementCache[i]; - } - - this.elementCache = {}; - this.ids = {}; - }; - - /** - * A cache of DOM elements - * - * @private - */ - this.elementCache = {}; - - /** - * Get the wrapper for the DOM element specified - * - * @param {String} id the id of the elment to get - * @return {YAHOO.util.DDM.ElementWrapper} the wrapped element - * @private - */ - this.getElWrapper = function(id) { - var oWrapper = this.elementCache[id]; - if (!oWrapper || !oWrapper.el) { - oWrapper = this.elementCache[id] = - new this.ElementWrapper(document.getElementById(id)); - } - return oWrapper; - }; - - /** - * Returns the actual DOM element - * - * @param {String} id the id of the elment to get - * @return {Object} The element - */ - this.getElement = function(id) { - // return this.getElWrapper(id).el; - return document.getElementById(id); - }; - - /** - * Returns the style property for the DOM element (i.e., - * document.getElById(id).style) - * - * @param {String} id the id of the elment to get - * @return {Object} The style property of the element - */ - this.getCss = function(id) { - // return this.getElWrapper(id).css; - var css = null; - var el = document.getElementById(id); - if (el) { - css = el.style; - } - - return css; - }; - - /** - * Inner class for cached elements - */ - this.ElementWrapper = function(el) { - /** - * @private - */ - this.el = el || null; - /** - * @private - */ - this.id = this.el && el.id; - /** - * @private - */ - this.css = this.el && el.style; - }; - - /** - * Returns the X position of an html element - * @param el the element for which to get the position - * @return {int} the X coordinate - */ - this.getPosX = function(el) { - return YAHOO.util.Dom.getX(el); - }; - - /** - * Returns the Y position of an html element - * @param el the element for which to get the position - * @return {int} the Y coordinate - */ - this.getPosY = function(el) { - return YAHOO.util.Dom.getY(el); - }; - - /** - * Swap two nodes. In IE, we use the native method, for others we - * emulate the IE behavior - * - * @param n1 the first node to swap - * @param n2 the other node to swap - */ - this.swapNode = function(n1, n2) { - if (n1.swapNode) { - n1.swapNode(n2); - } else { - // the node reference order for the swap is a little tricky. - var p = n2.parentNode; - var s = n2.nextSibling; - n1.parentNode.replaceChild(n2,n1); - p.insertBefore(n1,s); - } - }; - - /** - * @private - */ - this.getScroll = function () { - var t, l; - if (document.documentElement && document.documentElement.scrollTop) { - t = document.documentElement.scrollTop; - l = document.documentElement.scrollLeft; - } else if (document.body) { - t = document.body.scrollTop; - l = document.body.scrollLeft; - } - return { top: t, left: l }; - }; - - /** - * Returns the specified element style property - * @param {HTMLElement} el the element - * @param {string} styleProp the style property - * @return {string} The value of the style property - */ - this.getStyle = function(el, styleProp) { - if (el.style.styleProp) { - return el.style.styleProp; - } else if (el.currentStyle) { - return el.currentStyle[styleProp]; - } else if (document.defaultView) { - return document.defaultView.getComputedStyle(el, null). - getPropertyValue(styleProp); - } - }; - - /** - * Gets the scrollTop - * - * @return {int} the document's scrollTop - */ - this.getScrollTop = function () { return this.getScroll().top; }; - - /** - * Gets the scrollLeft - * - * @return {int} the document's scrollTop - */ - this.getScrollLeft = function () { return this.getScroll().left; }; - - this.moveToEl = function (moveEl, targetEl) { - var aCoord = YAHOO.util.Dom.getXY(targetEl); - YAHOO.util.Dom.setXY(moveEl, aCoord); - }; - - /** - * Gets the client height - * - * @return {int} client height in px - */ - this.getClientHeight = function() { - return (window.innerHeight) ? window.innerHeight : - (document.documentElement && document.documentElement.clientHeight) ? - document.documentElement.clientHeight : document.body.offsetHeight; - }; - - /** - * Gets the client width - * - * @return {int} client width in px - */ - this.getClientWidth = function() { - return (window.innerWidth) ? window.innerWidth : - (document.documentElement && document.documentElement.clientWidth) ? - document.documentElement.clientWidth : document.body.offsetWidth; - }; - - /** - * numeric array sort function - */ - this.numericSort = function(a, b) { return (a - b); }; - - /** - * @private - */ - this._timeoutCount = 0; - - /** - * @private - * Trying to make the load order less important. Without this we get - * an error if this file is loaded before the Event Utility. - */ - this._addListeners = function() { - if ( UTIL.Event && - document && - document.body ) { - - this._onLoad(); - } else { - if (this._timeoutCount > 500) { - } else { - setTimeout("YAHOO.util.DDM._addListeners()", 10); - this._timeoutCount += 1; - } - } - - }; - - /** - * Recursively searches the immediate parent and all child nodes for - * the handle element in order to determine wheter or not it was - * clicked. - * - * @param node the html element to inspect - */ - this.handleWasClicked = function(node, id) { - if (this.isHandle(id, node.id)) { - return true; - } else { - // check to see if this is a text node child of the one we want - var p = node.parentNode; - - while (p) { - if (this.isHandle(id, p.id)) { - return true; - } else { - p = p.parentNode; - } - } - } - - return false; - }; - - }; - - // shorter alias, save a few bytes - YAHOO.util.DDM = YAHOO.util.DragDropMgr; - YAHOO.util.DDM._addListeners(); - -} - -/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */ - -/** - * @class a DragDrop implementation where the linked element follows the - * mouse cursor. - * - * @extends DragDrop - * @constructor - * @param {String} id the id of the linked element - * @param {String} sGroup the group of related DragDrop items - */ -YAHOO.util.DD = function(id, sGroup) { - if (id) { - this.init(id, sGroup); - } -}; - -YAHOO.util.DD.prototype = new YAHOO.util.DragDrop(); - -/** - * Should we auto-scroll? Defaults to true - * - * @type boolean - */ -YAHOO.util.DD.prototype.scroll = true; - -/** - * Sets the pointer offset to the distance between the linked element's top - * left corner and the location the element was clicked - * - * @param {int} iPageX the X coordinate of the click - * @param {int} iPageY the Y coordinate of the click - */ -YAHOO.util.DD.prototype.autoOffset = function(iPageX, iPageY) { - var el = this.getEl(); - var aCoord = YAHOO.util.Dom.getXY(el); - var x = iPageX - aCoord[0]; - var y = iPageY - aCoord[1]; - this.setDelta(x, y); -}; - -/** - * Sets the pointer offset. You can call this directly to force the offset to - * be in a particular location (e.g., pass in 0,0 to set it to the center of the - * object, as done in ygDDSliderBG) - * - * @param {int} iDeltaX the distance from the left - * @param {int} iDeltaY the distance from the top - */ -YAHOO.util.DD.prototype.setDelta = function(iDeltaX, iDeltaY) { - this.deltaX = iDeltaX; - this.deltaY = iDeltaY; -}; - -/** - * Sets the drag element to the location of the mousedown or click event, - * maintaining the cursor location relative to the location on the element - * that was clicked. Override this if you want to place the element in a - * location other than where the cursor is. - * - * @param {int} iPageX the X coordinate of the mousedown or drag event - * @param {int} iPageY the Y coordinate of the mousedown or drag event - */ - -YAHOO.util.DD.prototype.setDragElPos = function(iPageX, iPageY) { - this.alignElWithMouse(this.getDragEl(), iPageX, iPageY); -}; - -/** - * Sets the element to the location of the mousedown or click event, - * maintaining the cursor location relative to the location on the element - * that was clicked. Override this if you want to place the element in a - * location other than where the cursor is. - * - * @param {HTMLElement} el the element to move - * @param {int} iPageX the X coordinate of the mousedown or drag event - * @param {int} iPageY the Y coordinate of the mousedown or drag event - */ -YAHOO.util.DD.prototype.alignElWithMouse = function(el, iPageX, iPageY) { - var oCoord = this.getTargetCoord(iPageX, iPageY); - var aCoord = [oCoord.x, oCoord.y]; - YAHOO.util.Dom.setXY(el, aCoord); - - this.cachePosition(oCoord.x, oCoord.y); - - this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth); -}; - -/** - * Saves the most recent position so that we can reset the constraints and - * tick marks on-demand. We need to know this so that we can calculate the - * number of pixels the element is offset from its original position. - */ -YAHOO.util.DD.prototype.cachePosition = function(iPageX, iPageY) { - if (iPageX) { - this.lastPageX = iPageX; - this.lastPageY = iPageY; - } else { - var aCoord = YAHOO.util.Dom.getXY(this.getEl()); - this.lastPageX = aCoord[0]; - this.lastPageY = aCoord[1]; - } -}; - -/** - * Auto-scroll the window if the dragged object has been moved beyond the - * visible window boundary. - * - * @param {int} x the drag element's x position - * @param {int} y the drag element's y position - * @param {int} h the height of the drag element - * @param {int} w the width of the drag element - * @private - */ -YAHOO.util.DD.prototype.autoScroll = function(x, y, h, w) { - - if (this.scroll) { - // The client height - var clientH = this.DDM.getClientHeight(); - - // The client width - var clientW = this.DDM.getClientWidth(); - - // The amt scrolled down - var st = this.DDM.getScrollTop(); - - // The amt scrolled right - var sl = this.DDM.getScrollLeft(); - - // Location of the bottom of the element - var bot = h + y; - - // Location of the right of the element - var right = w + x; - - // The distance from the cursor to the bottom of the visible area, - // adjusted so that we don't scroll if the cursor is beyond the - // element drag constraints - var toBot = (clientH + st - y - this.deltaY); - - // The distance from the cursor to the right of the visible area - var toRight = (clientW + sl - x - this.deltaX); - - - // How close to the edge the cursor must be before we scroll - // var thresh = (document.all) ? 100 : 40; - var thresh = 40; - - // How many pixels to scroll per autoscroll op. This helps to reduce - // clunky scrolling. IE is more sensitive about this ... it needs this - // value to be higher. - var scrAmt = (document.all) ? 80 : 30; - - // Scroll down if we are near the bottom of the visible page and the - // obj extends below the crease - if ( bot > clientH && toBot < thresh ) { - window.scrollTo(sl, st + scrAmt); - } - - // Scroll up if the window is scrolled down and the top of the object - // goes above the top border - if ( y < st && st > 0 && y - st < thresh ) { - window.scrollTo(sl, st - scrAmt); - } - - // Scroll right if the obj is beyond the right border and the cursor is - // near the border. - if ( right > clientW && toRight < thresh ) { - window.scrollTo(sl + scrAmt, st); - } - - // Scroll left if the window has been scrolled to the right and the obj - // extends past the left border - if ( x < sl && sl > 0 && x - sl < thresh ) { - window.scrollTo(sl - scrAmt, st); - } - } -}; - -/** - * Finds the location the element should be placed if we want to move - * it to where the mouse location less the click offset would place us. - * - * @param {int} iPageX the X coordinate of the click - * @param {int} iPageY the Y coordinate of the click - * @return an object that contains the coordinates (Object.x and Object.y) - * @private - */ -YAHOO.util.DD.prototype.getTargetCoord = function(iPageX, iPageY) { - - - var x = iPageX - this.deltaX; - var y = iPageY - this.deltaY; - - if (this.constrainX) { - if (x < this.minX) { x = this.minX; } - if (x > this.maxX) { x = this.maxX; } - } - - if (this.constrainY) { - if (y < this.minY) { y = this.minY; } - if (y > this.maxY) { y = this.maxY; } - } - - x = this.getTick(x, this.xTicks); - y = this.getTick(y, this.yTicks); - - - return {x:x, y:y}; -}; - -// overrides YAHOO.util.DragDrop -YAHOO.util.DD.prototype.b4MouseDown = function(e) { - // this.resetConstraints(); - this.autoOffset(YAHOO.util.Event.getPageX(e), - YAHOO.util.Event.getPageY(e)); -}; - -// overrides YAHOO.util.DragDrop -YAHOO.util.DD.prototype.b4Drag = function(e) { - this.setDragElPos(YAHOO.util.Event.getPageX(e), - YAHOO.util.Event.getPageY(e)); -}; - -/////////////////////////////////////////////////////////////////////////////// -// Debugging ygDragDrop events that can be overridden -/////////////////////////////////////////////////////////////////////////////// -/* -YAHOO.util.DD.prototype.startDrag = function(x, y) { -}; - -YAHOO.util.DD.prototype.onDrag = function(e) { -}; - -YAHOO.util.DD.prototype.onDragEnter = function(e, id) { -}; - -YAHOO.util.DD.prototype.onDragOver = function(e, id) { -}; - -YAHOO.util.DD.prototype.onDragOut = function(e, id) { -}; - -YAHOO.util.DD.prototype.onDragDrop = function(e, id) { -}; - -YAHOO.util.DD.prototype.endDrag = function(e) { -}; -*/ - -/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */ - -/** - * @class a DragDrop implementation that inserts an empty, bordered div into - * the document that follows the cursor during drag operations. At the time of - * the click, the frame div is resized to the dimensions of the linked html - * element, and moved to the exact location of the linked element. - * - * @extends YAHOO.util.DD - * @constructor - * @param {String} id the id of the linked html element - * @param {String} sGroup the group of related DragDrop objects - */ -YAHOO.util.DDProxy = function(id, sGroup) { - if (id) { - this.init(id, sGroup); - this.initFrame(); - } -}; - -YAHOO.util.DDProxy.prototype = new YAHOO.util.DD(); - -/** - * A reference to the one div element we create for all instances of this class - * - * @type Object - */ -YAHOO.util.DDProxy.frameDiv = null; - -/** - * the drag frame div id - * - * @type String - */ -YAHOO.util.DDProxy.dragElId = "ygddfdiv"; - -/** - * The border width of the frame. This is used when we resize the frame to - * the size of the linked element. We substract the border width to make - * the div the correct size. - * - * @TODO find a better way to handle this - * - * @type int - */ -YAHOO.util.DDProxy.prototype.borderWidth = 2; - -/** - * By default we resize the drag frame to be the same size as the element - * we want to drag (this is to get the frame effect). We can turn it off - * if we want a different behavior (ex: ygDDMy2) - * - * @type boolean - */ -YAHOO.util.DDProxy.prototype.resizeFrame = true; - -/** - * By default the frame is positioned exactly where the drag element is, so - * we use the cursor offset provided by YAHOO.util.DD. Another option that works only if - * you do not have constraints on the obj is to have the drag frame centered - * around the cursor. Set centerFrame to true for this effect. Ex: - * ygDDMy2 - * - * @type boolean - */ -YAHOO.util.DDProxy.prototype.centerFrame = false; - -/** - * Create the drag frame if needed - */ -YAHOO.util.DDProxy.createFrame = function() { - var THIS = YAHOO.util.DDProxy; - - if (!document || !document.body) { - setTimeout(THIS.createFrame, 50); - return; - } - - if (!THIS.frameDiv) { - THIS.frameDiv = document.createElement("div"); - THIS.frameDiv.id = THIS.dragElId; - var s = THIS.frameDiv.style; - s.position = "absolute"; - s.visibility = "hidden"; - s.cursor = "move"; - s.border = "2px solid #aaa"; - s.zIndex = 999; - - document.body.appendChild(THIS.frameDiv); - } -}; - -/** - * Initialization for the drag frame element. Must be called in the - * constructor of all subclasses - */ -YAHOO.util.DDProxy.prototype.initFrame = function() { - YAHOO.util.DDProxy.createFrame(); - this.setDragElId(YAHOO.util.DDProxy.dragElId); - this.useAbsMath = true; -}; - -/** - * Resizes the drag frame to the dimensions of the clicked object, positions - * it over the object, and finally displays it - * - * @param {int} iPageX X click position - * @param {int} iPageY Y click position - * @private - */ -YAHOO.util.DDProxy.prototype.showFrame = function(iPageX, iPageY) { - var el = this.getEl(); - - var s = this.getDragEl().style; - - if (this.resizeFrame) { - s.width = (parseInt(el.offsetWidth) - (2*this.borderWidth)) + "px"; - s.height = (parseInt(el.offsetHeight) - (2*this.borderWidth)) + "px"; - } - - if (this.centerFrame) { - this.setDelta(Math.round(parseInt(s.width)/2), - Math.round(parseInt(s.width)/2)); - } - - this.setDragElPos(iPageX, iPageY); - - s.visibility = ""; -}; - -// overrides YAHOO.util.DragDrop -YAHOO.util.DDProxy.prototype.b4MouseDown = function(e) { - var x = YAHOO.util.Event.getPageX(e); - var y = YAHOO.util.Event.getPageY(e); - this.autoOffset(x, y); - this.setDragElPos(x, y); -}; - -// overrides YAHOO.util.DragDrop -YAHOO.util.DDProxy.prototype.b4StartDrag = function(x, y) { - // show the drag frame - this.showFrame(x, y); -}; - -// overrides YAHOO.util.DragDrop -YAHOO.util.DDProxy.prototype.b4EndDrag = function(e) { - - // hide the drag frame - var s = this.getDragEl().style; - s.visibility = "hidden"; -}; - -// overrides YAHOO.util.DragDrop -// By default we try to move the element to the last location of the frame. -// This is so that the default behavior mirrors that of YAHOO.util.DD. -YAHOO.util.DDProxy.prototype.endDrag = function(e) { - var lel = this.getEl(); - var del = this.getDragEl(); - - // Show the drag frame briefly so we can get its position - del.style.visibility = ""; - - // Hide the linked element before the move to get around a Safari - // rendering bug. - lel.style.visibility = "hidden"; - YAHOO.util.DDM.moveToEl(lel, del); - del.style.visibility = "hidden"; - lel.style.visibility = ""; -}; - -/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */ - -/** - * @class a DragDrop implementation that does not move, but can be a drop - * target. You would get the same result by simply omitting implementation - * for the event callbacks, but this way we reduce the processing cost of the - * event listener and the callbacks. - * - * @extends YAHOO.util.DragDrop - * @constructor - * @param {String} id the id of the element that is a drop target - * @param {String} sGroup the group of related DragDrop objects - */ - -YAHOO.util.DDTarget = function(id, sGroup) { - if (id) { - this.initTarget(id, sGroup); - } -}; - -YAHOO.util.DDTarget.prototype = new YAHOO.util.DragDrop(); - Index: openacs-4/packages/ajaxhelper/www/yahoo/event/license.txt =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yahoo/event/Attic/license.txt,v diff -u -N --- openacs-4/packages/ajaxhelper/www/yahoo/event/license.txt 5 Apr 2006 06:38:43 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,35 +0,0 @@ -Software License Agreement (BSD License) - -Copyright (c) 2006, Yahoo! Inc. -All rights reserved. - -Redistribution and use of this software in source and binary forms, with -or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of Yahoo! Inc. nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of Yahoo! Inc. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Index: openacs-4/packages/ajaxhelper/www/yahoo/event/build/YAHOO.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yahoo/event/build/Attic/YAHOO.js,v diff -u -N --- openacs-4/packages/ajaxhelper/www/yahoo/event/build/YAHOO.js 5 Apr 2006 06:38:43 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,63 +0,0 @@ -/* -Copyright (c) 2006 Yahoo! Inc. All rights reserved. -version 0.9.0 -*/ - -/** - * @class The Yahoo global namespace - */ -var YAHOO = function() { - - return { - - /** - * Yahoo presentation platform utils namespace - */ - util: {}, - - /** - * Yahoo presentation platform widgets namespace - */ - widget: {}, - - /** - * Yahoo presentation platform examples namespace - */ - example: {}, - - /** - * Returns the namespace specified and creates it if it doesn't exist - * - * YAHOO.namespace("property.package"); - * YAHOO.namespace("YAHOO.property.package"); - * - * Either of the above would create YAHOO.property, then - * YAHOO.property.package - * - * @param {String} sNameSpace String representation of the desired - * namespace - * @return {Object} A reference to the namespace object - */ - namespace: function( sNameSpace ) { - - if (!sNameSpace || !sNameSpace.length) { - return null; - } - - var levels = sNameSpace.split("."); - - var currentNS = YAHOO; - - // YAHOO is implied, so it is ignored if it is included - for (var i=(levels[0] == "YAHOO") ? 1 : 0; i - * - The type of event - * - All of the arguments fire() was executed with as an array - * - The custom object (if any) that was passed into the subscribe() method - * - * - * @param {Array} an arbitrary set of parameters to pass to the handler - */ - fire: function() { - for (var i=0; i= 0) { - cacheItem = listeners[index]; - } - - if (!el || !cacheItem) { - return false; - } - - - if (el.removeEventListener) { - el.removeEventListener(sType, cacheItem[this.WFN], false); - // alert("adsf"); - } else if (el.detachEvent) { - el.detachEvent("on" + sType, cacheItem[this.WFN]); - } - - // removed the wrapped handler - delete listeners[index][this.WFN]; - delete listeners[index][this.FN]; - delete listeners[index]; - - return true; - - }, - - /** - * Returns the event's target element - * @param {Event} ev the event - * @param {boolean} resolveTextNode when set to true the target's - * parent will be returned if the target is a - * text node - * @return {HTMLElement} the event's target - */ - getTarget: function(ev, resolveTextNode) { - var t = ev.target || ev.srcElement; - - if (resolveTextNode && t && "#text" == t.nodeName) { - return t.parentNode; - } else { - return t; - } - }, - - /** - * Returns the event's pageX - * @param {Event} ev the event - * @return {int} the event's pageX - */ - getPageX: function(ev) { - var x = ev.pageX; - if (!x && 0 !== x) { - x = ev.clientX || 0; - - if ( this.isIE ) { - x += this._getScrollLeft(); - } - } - - return x; - }, - - /** - * Returns the event's pageY - * @param {Event} ev the event - * @return {int} the event's pageY - */ - getPageY: function(ev) { - var y = ev.pageY; - if (!y && 0 !== y) { - y = ev.clientY || 0; - - if ( this.isIE ) { - y += this._getScrollTop(); - } - } - - return y; - }, - - /** - * Returns the event's related target - * @param {Event} ev the event - * @return {HTMLElement} the event's relatedTarget - */ - getRelatedTarget: function(ev) { - var t = ev.relatedTarget; - if (!t) { - if (ev.type == "mouseout") { - t = ev.toElement; - } else if (ev.type == "mouseover") { - t = ev.fromElement; - } - } - - return t; - }, - - /** - * Returns the time of the event. If the time is not included, the - * event is modified using the current time. - * @param {Event} ev the event - * @return {Date} the time of the event - */ - getTime: function(ev) { - if (!ev.time) { - var t = new Date().getTime(); - try { - ev.time = t; - } catch(e) { - // can't set the time property - return t; - } - } - - return ev.time; - }, - - /** - * Convenience method for stopPropagation + preventDefault - * @param {Event} ev the event - */ - stopEvent: function(ev) { - this.stopPropagation(ev); - this.preventDefault(ev); - }, - - /** - * Stops event propagation - * @param {Event} ev the event - */ - stopPropagation: function(ev) { - if (ev.stopPropagation) { - ev.stopPropagation(); - } else { - ev.cancelBubble = true; - } - }, - - /** - * Prevents the default behavior of the event - * @param {Event} ev the event - */ - preventDefault: function(ev) { - if (ev.preventDefault) { - ev.preventDefault(); - } else { - ev.returnValue = false; - } - }, - - /** - * Returns the event, should not be necessary for user to call - * @param {Event} the event parameter from the handler - * @return {Event} the event - */ - getEvent: function(e) { - var ev = e || window.event; - - if (!ev) { - var c = this.getEvent.caller; - while (c) { - ev = c.arguments[0]; - if (ev && Event == ev.constructor) { - break; - } - c = c.caller; - } - } - - return ev; - }, - - /** - * Returns the charcode for an event - * @param {Event} ev the event - * @return {int} the event's charCode - */ - getCharCode: function(ev) { - return ev.charCode || (ev.type == "keypress") ? ev.keyCode : 0; - }, - - /** - * @private - * Locating the saved event handler data by function ref - */ - _getCacheIndex: function(el, sType, fn) { - for (var i=0; i< listeners.length; ++i) { - var li = listeners[i]; - if ( li && - li[this.FN] == fn && - li[this.EL] == el && - li[this.TYPE] == sType ) { - return i; - } - } - - return -1; - }, - - /** - * We want to be able to use getElementsByTagName as a collection - * to attach a group of events to. Unfortunately, different - * browsers return different types of collections. This function - * tests to determine if the object is array-like. It will also - * fail if the object is an array, but is empty. - * @param o the object to test - * @return {boolean} true if the object is array-like and populated - */ - _isValidCollection: function(o) { - // alert(o.constructor.toString()) - // alert(typeof o) - - return ( o && // o is something - o.length && // o is indexed - typeof o != "string" && // o is not a string - !o.tagName && // o is not an HTML element - !o.alert && // o is not a window - typeof o[0] != "undefined" ); - - }, - - /** - * @private - * DOM element cache - */ - elCache: {}, - - /** - * We cache elements bound by id because when the unload event - * fires, we can no longer use document.getElementById - * @private - */ - getEl: function(id) { - /* - // this is a problem when replaced via document.getElementById - if (! this.elCache[id]) { - try { - var el = document.getElementById(id); - if (el) { - this.elCache[id] = el; - } - } catch (er) { - } - } - return this.elCache[id]; - */ - - return document.getElementById(id); - }, - - /** - * Clears the element cache - */ - clearCache: function() { - for (i in this.elCache) { - delete this.elCache[i]; - } - }, - - /** - * Called by CustomEvent instances to provide a handle to the - * event * that can be removed later on. Should be package - * protected. - * @private - */ - regCE: function(ce) { - customEvents.push(ce); - }, - - /** - * @private - * hook up any deferred listeners - */ - _load: function(e) { - loadComplete = true; - }, - - /** - * Polling function that runs before the onload event fires, - * attempting * to attach to DOM Nodes as soon as they are - * available - * @private - */ - _tryPreloadAttach: function() { - - // keep trying until after the page is loaded. We need to - // check the page load state prior to trying to bind the - // elements so that we can be certain all elements have been - // tested appropriately - var tryAgain = !loadComplete; - - for (var i=0; i < delayedListeners.length; ++i) { - var d = delayedListeners[i]; - // There may be a race condition here, so we need to - // verify the array element is usable. - if (d) { - - // el will be null if document.getElementById did not - // work - var el = this.getEl(d[this.EL]); - - if (el) { - this.on(el, d[this.TYPE], d[this.FN], - d[this.SCOPE], d[this.ADJ_SCOPE]); - delete delayedListeners[i]; - } - } - } - - if (tryAgain) { - setTimeout("YAHOO.util.Event._tryPreloadAttach()", 50); - } - }, - - /** - * Removes all listeners registered by pe.event. Called - * automatically during the unload event. - */ - _unload: function(e, me) { - for (var i=0; i < unloadListeners.length; ++i) { - var l = unloadListeners[i]; - if (l) { - var scope = (l[this.ADJ_SCOPE]) ? l[this.SCOPE]: window; - l[this.FN].call(scope, this.getEvent(e), l[this.SCOPE] ); - } - } - - if (listeners && listeners.length > 0) { - for (i = 0; i < listeners.length; ++i) { - l = listeners[i]; - if (l) { - this.removeListener(l[this.EL], l[this.TYPE], - l[this.FN]); - } - } - - this.clearCache(); - } - - for (i = 0; i < customEvents.length; ++i) { - customEvents[i].unsubscribeAll(); - delete customEvents[i]; - } - - for (i = 0; i < legacyEvents.length; ++i) { - // dereference the element - delete legacyEvents[i][0]; - // delete the array item - delete legacyEvents[i]; - } - }, - - /** - * Returns scrollLeft - * @private - */ - _getScrollLeft: function() { - return this._getScroll()[1]; - }, - - /** - * Returns scrollTop - * @private - */ - _getScrollTop: function() { - return this._getScroll()[0]; - }, - - /** - * Returns the scrollTop and scrollLeft. Used to calculate the - * pageX and pageY in Internet Explorer - * @private - */ - _getScroll: function() { - var dd = document.documentElement; db = document.body; - if (dd && dd.scrollTop) { - return [dd.scrollTop, dd.scrollLeft]; - } else if (db) { - return [db.scrollTop, db.scrollLeft]; - } else { - return [0, 0]; - } - } - }; - } (); - - YAHOO.util.Event.on = YAHOO.util.Event.addListener; - - if (document && document.body) { - YAHOO.util.Event._load(); - } else { - YAHOO.util.Event.on(window, "load", YAHOO.util.Event._load, - YAHOO.util.Event, true); - } - - YAHOO.util.Event.on(window, "unload", YAHOO.util.Event._unload, - YAHOO.util.Event, true); - - YAHOO.util.Event._tryPreloadAttach(); - -} - Index: openacs-4/packages/ajaxhelper/www/yui/animation/README =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yui/animation/Attic/README,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/yui/animation/README 20 Aug 2006 14:39:26 -0000 1.1 @@ -0,0 +1,24 @@ +Animation Release Notes + +*** version 0.11.1 *** + +* changed "prototype" shorthand to "proto" (workaround firefox < 1.5 scoping bug) + +*** version 0.11.0 *** + +* ColorAnim subclass added +* Motion and Scroll now inherit from ColorAnim +* getDefaultUnit method added +* defaultUnit and defaultUnits deprecated +* getDefault and setDefault methods deprecated + +*** version 0.10.0 *** + +* Scroll now handles relative ("by") animation correctly + +* Now converts "auto" values of "from" to appropriate initial values + +*** version 0.9.0 *** + +* Initial release + Index: openacs-4/packages/ajaxhelper/www/yui/animation/animation-debug.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yui/animation/Attic/animation-debug.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/yui/animation/animation-debug.js 20 Aug 2006 14:39:26 -0000 1.1 @@ -0,0 +1,1261 @@ +/* +Copyright (c) 2006, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +Version: 0.11.1 +*/ + + +/** + * + * Base class for animated DOM objects. + * @class Base animation class that provides the interface for building animated effects. + *

    Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);

    + * @requires YAHOO.util.AnimMgr + * @requires YAHOO.util.Easing + * @requires YAHOO.util.Dom + * @requires YAHOO.util.Event + * @requires YAHOO.util.CustomEvent + * @constructor + * @param {String or HTMLElement} el Reference to the element that will be animated + * @param {Object} attributes The attribute(s) to be animated. + * Each attribute is an object with at minimum a "to" or "by" member defined. + * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). + * All attribute names use camelCase. + * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based + * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) + */ + +YAHOO.util.Anim = function(el, attributes, duration, method) { + if (el) { + this.init(el, attributes, duration, method); + } +}; + +YAHOO.util.Anim.prototype = { + /** + * toString method + * @return {String} string represenation of anim obj + */ + toString: function() { + var el = this.getEl(); + var id = el.id || el.tagName; + return ("Anim " + id); + }, + + patterns: { // cached for performance + noNegatives: /width|height|opacity|padding/i, // keep at zero or above + offsetAttribute: /^((width|height)|(top|left))$/, // use offsetValue as default + defaultUnit: /width|height|top$|bottom$|left$|right$/i, // use 'px' by default + offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset + }, + + /** + * Returns the value computed by the animation's "method". + * @param {String} attr The name of the attribute. + * @param {Number} start The value this attribute should start from for this animation. + * @param {Number} end The value this attribute should end at for this animation. + * @return {Number} The Value to be applied to the attribute. + */ + doMethod: function(attr, start, end) { + return this.method(this.currentFrame, start, end - start, this.totalFrames); + }, + + /** + * Applies a value to an attribute + * @param {String} attr The name of the attribute. + * @param {Number} val The value to be applied to the attribute. + * @param {String} unit The unit ('px', '%', etc.) of the value. + */ + setAttribute: function(attr, val, unit) { + if ( this.patterns.noNegatives.test(attr) ) { + val = (val > 0) ? val : 0; + } + + YAHOO.util.Dom.setStyle(this.getEl(), attr, val + unit); + }, + + /** + * Returns current value of the attribute. + * @param {String} attr The name of the attribute. + * @return {Number} val The current value of the attribute. + */ + getAttribute: function(attr) { + var el = this.getEl(); + var val = YAHOO.util.Dom.getStyle(el, attr); + + if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) { + return parseFloat(val); + } + + var a = this.patterns.offsetAttribute.exec(attr) || []; + var pos = !!( a[3] ); // top or left + var box = !!( a[2] ); // width or height + + // use offsets for width/height and abs pos top/left + if ( box || (YAHOO.util.Dom.getStyle(el, 'position') == 'absolute' && pos) ) { + val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)]; + } else { // default to zero for other 'auto' + val = 0; + } + + return val; + }, + + /** + * Returns the unit to use when none is supplied. + * Applies the "defaultUnit" test to decide whether to use pixels or not + * @param {attr} attr The name of the attribute. + * @return {String} The default unit to be used. + */ + getDefaultUnit: function(attr) { + if ( this.patterns.defaultUnit.test(attr) ) { + return 'px'; + } + + return ''; + }, + + /** + * Sets the actual values to be used during the animation. + * Should only be needed for subclass use. + * @param {Object} attr The attribute object + * @private + */ + setRuntimeAttribute: function(attr) { + var start; + var end; + var attributes = this.attributes; + + this.runtimeAttributes[attr] = {}; + + var isset = function(prop) { + return (typeof prop !== 'undefined'); + }; + + if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) { + return false; // note return; nothing to animate to + } + + start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr); + + // To beats by, per SMIL 2.1 spec + if ( isset(attributes[attr]['to']) ) { + end = attributes[attr]['to']; + } else if ( isset(attributes[attr]['by']) ) { + if (start.constructor == Array) { + end = []; + for (var i = 0, len = start.length; i < len; ++i) { + end[i] = start[i] + attributes[attr]['by'][i]; + } + } else { + end = start + attributes[attr]['by']; + } + } + + this.runtimeAttributes[attr].start = start; + this.runtimeAttributes[attr].end = end; + + // set units if needed + this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr); + }, + + /** + * @param {String or HTMLElement} el Reference to the element that will be animated + * @param {Object} attributes The attribute(s) to be animated. + * Each attribute is an object with at minimum a "to" or "by" member defined. + * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). + * All attribute names use camelCase. + * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based + * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) + */ + init: function(el, attributes, duration, method) { + /** + * Whether or not the animation is running. + * @private + * @type Boolean + */ + var isAnimated = false; + + /** + * A Date object that is created when the animation begins. + * @private + * @type Date + */ + var startTime = null; + + /** + * The number of frames this animation was able to execute. + * @private + * @type Int + */ + var actualFrames = 0; + + /** + * The element to be animated. + * @private + * @type HTMLElement + */ + el = YAHOO.util.Dom.get(el); + + /** + * The collection of attributes to be animated. + * Each attribute must have at least a "to" or "by" defined in order to animate. + * If "to" is supplied, the animation will end with the attribute at that value. + * If "by" is supplied, the animation will end at that value plus its starting value. + * If both are supplied, "to" is used, and "by" is ignored. + * @member YAHOO#util#Anim + * Optional additional member include "from" (the value the attribute should start animating from, defaults to current value), and "unit" (the units to apply to the values). + * @type Object + */ + this.attributes = attributes || {}; + + /** + * The length of the animation. Defaults to "1" (second). + * @type Number + */ + this.duration = duration || 1; + + /** + * The method that will provide values to the attribute(s) during the animation. + * Defaults to "YAHOO.util.Easing.easeNone". + * @type Function + */ + this.method = method || YAHOO.util.Easing.easeNone; + + /** + * Whether or not the duration should be treated as seconds. + * Defaults to true. + * @type Boolean + */ + this.useSeconds = true; // default to seconds + + /** + * The location of the current animation on the timeline. + * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time. + * @type Int + */ + this.currentFrame = 0; + + /** + * The total number of frames to be executed. + * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time. + * @type Int + */ + this.totalFrames = YAHOO.util.AnimMgr.fps; + + + /** + * Returns a reference to the animated element. + * @return {HTMLElement} + */ + this.getEl = function() { return el; }; + + /** + * Checks whether the element is currently animated. + * @return {Boolean} current value of isAnimated. + */ + this.isAnimated = function() { + return isAnimated; + }; + + /** + * Returns the animation start time. + * @return {Date} current value of startTime. + */ + this.getStartTime = function() { + return startTime; + }; + + this.runtimeAttributes = {}; + + var logger = {}; + logger.log = function() {YAHOO.log.apply(window, arguments)}; + + logger.log('creating new instance of ' + this); + + /** + * Starts the animation by registering it with the animation manager. + */ + this.animate = function() { + if ( this.isAnimated() ) { return false; } + + this.currentFrame = 0; + + this.totalFrames = ( this.useSeconds ) ? Math.ceil(YAHOO.util.AnimMgr.fps * this.duration) : this.duration; + + YAHOO.util.AnimMgr.registerElement(this); + }; + + /** + * Stops the animation. Normally called by AnimMgr when animation completes. + */ + this.stop = function() { + YAHOO.util.AnimMgr.stop(this); + }; + + var onStart = function() { + this.onStart.fire(); + for (var attr in this.attributes) { + this.setRuntimeAttribute(attr); + } + + isAnimated = true; + actualFrames = 0; + startTime = new Date(); + }; + + /** + * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s). + * @private + */ + + var onTween = function() { + var data = { + duration: new Date() - this.getStartTime(), + currentFrame: this.currentFrame + }; + + data.toString = function() { + return ( + 'duration: ' + data.duration + + ', currentFrame: ' + data.currentFrame + ); + }; + + this.onTween.fire(data); + + var runtimeAttributes = this.runtimeAttributes; + + for (var attr in runtimeAttributes) { + this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit); + } + + actualFrames += 1; + }; + + var onComplete = function() { + var actual_duration = (new Date() - startTime) / 1000 ; + + var data = { + duration: actual_duration, + frames: actualFrames, + fps: actualFrames / actual_duration + }; + + data.toString = function() { + return ( + 'duration: ' + data.duration + + ', frames: ' + data.frames + + ', fps: ' + data.fps + ); + }; + + isAnimated = false; + actualFrames = 0; + this.onComplete.fire(data); + }; + + /** + * Custom event that fires after onStart, useful in subclassing + * @private + */ + this._onStart = new YAHOO.util.CustomEvent('_start', this, true); + + /** + * Custom event that fires when animation begins + * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction) + */ + this.onStart = new YAHOO.util.CustomEvent('start', this); + + /** + * Custom event that fires between each frame + * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction) + */ + this.onTween = new YAHOO.util.CustomEvent('tween', this); + + /** + * Custom event that fires after onTween + * @private + */ + this._onTween = new YAHOO.util.CustomEvent('_tween', this, true); + + /** + * Custom event that fires when animation ends + * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction) + */ + this.onComplete = new YAHOO.util.CustomEvent('complete', this); + /** + * Custom event that fires after onComplete + * @private + */ + this._onComplete = new YAHOO.util.CustomEvent('_complete', this, true); + + this._onStart.subscribe(onStart); + this._onTween.subscribe(onTween); + this._onComplete.subscribe(onComplete); + } +}; + +/** + * @class Handles animation queueing and threading. + * Used by Anim and subclasses. + */ +YAHOO.util.AnimMgr = new function() { + /** + * Reference to the animation Interval + * @private + * @type Int + */ + var thread = null; + + /** + * The current queue of registered animation objects. + * @private + * @type Array + */ + var queue = []; + + /** + * The number of active animations. + * @private + * @type Int + */ + var tweenCount = 0; + + /** + * Base frame rate (frames per second). + * Arbitrarily high for better x-browser calibration (slower browsers drop more frames). + * @type Int + * + */ + this.fps = 200; + + /** + * Interval delay in milliseconds, defaults to fastest possible. + * @type Int + * + */ + this.delay = 1; + + /** + * Adds an animation instance to the animation queue. + * All animation instances must be registered in order to animate. + * @param {object} tween The Anim instance to be be registered + */ + this.registerElement = function(tween) { + queue[queue.length] = tween; + tweenCount += 1; + tween._onStart.fire(); + this.start(); + }; + + this.unRegister = function(tween, index) { + tween._onComplete.fire(); + index = index || getIndex(tween); + if (index != -1) { queue.splice(index, 1); } + + tweenCount -= 1; + if (tweenCount <= 0) { this.stop(); } + }; + + /** + * Starts the animation thread. + * Only one thread can run at a time. + */ + this.start = function() { + if (thread === null) { thread = setInterval(this.run, this.delay); } + }; + + /** + * Stops the animation thread or a specific animation instance. + * @param {object} tween A specific Anim instance to stop (optional) + * If no instance given, Manager stops thread and all animations. + */ + this.stop = function(tween) { + if (!tween) { + clearInterval(thread); + for (var i = 0, len = queue.length; i < len; ++i) { + if (queue[i].isAnimated()) { + this.unRegister(tween, i); + } + } + queue = []; + thread = null; + tweenCount = 0; + } + else { + this.unRegister(tween); + } + }; + + /** + * Called per Interval to handle each animation frame. + */ + this.run = function() { + for (var i = 0, len = queue.length; i < len; ++i) { + var tween = queue[i]; + if ( !tween || !tween.isAnimated() ) { continue; } + + if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null) + { + tween.currentFrame += 1; + + if (tween.useSeconds) { + correctFrame(tween); + } + tween._onTween.fire(); + } + else { YAHOO.util.AnimMgr.stop(tween, i); } + } + }; + + var getIndex = function(anim) { + for (var i = 0, len = queue.length; i < len; ++i) { + if (queue[i] == anim) { + return i; // note return; + } + } + return -1; + }; + + /** + * On the fly frame correction to keep animation on time. + * @private + * @param {Object} tween The Anim instance being corrected. + */ + var correctFrame = function(tween) { + var frames = tween.totalFrames; + var frame = tween.currentFrame; + var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames); + var elapsed = (new Date() - tween.getStartTime()); + var tweak = 0; + + if (elapsed < tween.duration * 1000) { // check if falling behind + tweak = Math.round((elapsed / expected - 1) * tween.currentFrame); + } else { // went over duration, so jump to end + tweak = frames - (frame + 1); + } + if (tweak > 0 && isFinite(tweak)) { // adjust if needed + if (tween.currentFrame + tweak >= frames) {// dont go past last frame + tweak = frames - (frame + 1); + } + + tween.currentFrame += tweak; + } + }; +}; +/** + * + * @class Used to calculate Bezier splines for any number of control points. + * + */ +YAHOO.util.Bezier = new function() +{ + /** + * Get the current position of the animated element based on t. + * Each point is an array of "x" and "y" values (0 = x, 1 = y) + * At least 2 points are required (start and end). + * First point is start. Last point is end. + * Additional control points are optional. + * @param {Array} points An array containing Bezier points + * @param {Number} t A number between 0 and 1 which is the basis for determining current position + * @return {Array} An array containing int x and y member data + */ + this.getPosition = function(points, t) + { + var n = points.length; + var tmp = []; + + for (var i = 0; i < n; ++i){ + tmp[i] = [points[i][0], points[i][1]]; // save input + } + + for (var j = 1; j < n; ++j) { + for (i = 0; i < n - j; ++i) { + tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0]; + tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1]; + } + } + + return [ tmp[0][0], tmp[0][1] ]; + + }; +}; +/** + * @class ColorAnim subclass for color fading + *

    Usage: var myAnim = new Y.ColorAnim(el, { backgroundColor: { from: '#FF0000', to: '#FFFFFF' } }, 1, Y.Easing.easeOut);

    + *

    Color values can be specified with either 112233, #112233, [255,255,255], or rgb(255,255,255) + * @requires YAHOO.util.Anim + * @requires YAHOO.util.AnimMgr + * @requires YAHOO.util.Easing + * @requires YAHOO.util.Bezier + * @requires YAHOO.util.Dom + * @requires YAHOO.util.Event + * @constructor + * @param {HTMLElement | String} el Reference to the element that will be animated + * @param {Object} attributes The attribute(s) to be animated. + * Each attribute is an object with at minimum a "to" or "by" member defined. + * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). + * All attribute names use camelCase. + * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based + * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) + */ +(function() { + YAHOO.util.ColorAnim = function(el, attributes, duration, method) { + YAHOO.util.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method); + }; + + YAHOO.extend(YAHOO.util.ColorAnim, YAHOO.util.Anim); + + // shorthand + var Y = YAHOO.util; + var superclass = Y.ColorAnim.superclass; + var proto = Y.ColorAnim.prototype; + + /** + * toString method + * @return {String} string represenation of anim obj + */ + proto.toString = function() { + var el = this.getEl(); + var id = el.id || el.tagName; + return ("ColorAnim " + id); + }; + + /** + * Only certain attributes should be treated as colors. + * @type Object + */ + proto.patterns.color = /color$/i; + proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i; + proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i; + proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i; + + /** + * Attempts to parse the given string and return a 3-tuple. + * @param {String} s The string to parse. + * @return {Array} The 3-tuple of rgb values. + */ + proto.parseColor = function(s) { + if (s.length == 3) { return s; } + + var c = this.patterns.hex.exec(s); + if (c && c.length == 4) { + return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ]; + } + + c = this.patterns.rgb.exec(s); + if (c && c.length == 4) { + return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ]; + } + + c = this.patterns.hex3.exec(s); + if (c && c.length == 4) { + return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ]; + } + + return null; + }; + + /** + * Returns current value of the attribute. + * @param {String} attr The name of the attribute. + * @return {Number} val The current value of the attribute. + */ + proto.getAttribute = function(attr) { + var el = this.getEl(); + if ( this.patterns.color.test(attr) ) { + var val = YAHOO.util.Dom.getStyle(el, attr); + + if (val == 'transparent') { // bgcolor default + var parent = el.parentNode; // try and get from an ancestor + val = Y.Dom.getStyle(parent, attr); + + while (parent && val == 'transparent') { + parent = parent.parentNode; + val = Y.Dom.getStyle(parent, attr); + if (parent.tagName.toUpperCase() == 'HTML') { + val = 'ffffff'; + } + } + } + } else { + val = superclass.getAttribute.call(this, attr); + } + + return val; + }; + + /** + * Returns the value computed by the animation's "method". + * @param {String} attr The name of the attribute. + * @param {Number} start The value this attribute should start from for this animation. + * @param {Number} end The value this attribute should end at for this animation. + * @return {Number} The Value to be applied to the attribute. + */ + proto.doMethod = function(attr, start, end) { + var val; + + if ( this.patterns.color.test(attr) ) { + val = []; + for (var i = 0, len = start.length; i < len; ++i) { + val[i] = superclass.doMethod.call(this, attr, start[i], end[i]); + } + + val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')'; + } + else { + val = superclass.doMethod.call(this, attr, start, end); + } + + return val; + }; + + /** + * Sets the actual values to be used during the animation. + * Should only be needed for subclass use. + * @param {Object} attr The attribute object + * @private + */ + proto.setRuntimeAttribute = function(attr) { + superclass.setRuntimeAttribute.call(this, attr); + + if ( this.patterns.color.test(attr) ) { + var attributes = this.attributes; + var start = this.parseColor(this.runtimeAttributes[attr].start); + var end = this.parseColor(this.runtimeAttributes[attr].end); + // fix colors if going "by" + if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) { + end = this.parseColor(attributes[attr].by); + + for (var i = 0, len = start.length; i < len; ++i) { + end[i] = start[i] + end[i]; + } + } + + this.runtimeAttributes[attr].start = start; + this.runtimeAttributes[attr].end = end; + } + }; +})();/* +TERMS OF USE - EASING EQUATIONS +Open source under the BSD License. +Copyright � 2001 Robert Penner All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +YAHOO.util.Easing = { + + /** + * Uniform speed between points. + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeNone: function (t, b, c, d) { + return c*t/d + b; + }, + + /** + * Begins slowly and accelerates towards end. (quadratic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeIn: function (t, b, c, d) { + return c*(t/=d)*t + b; + }, + + /** + * Begins quickly and decelerates towards end. (quadratic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeOut: function (t, b, c, d) { + return -c *(t/=d)*(t-2) + b; + }, + + /** + * Begins slowly and decelerates towards end. (quadratic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeBoth: function (t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t + b; + return -c/2 * ((--t)*(t-2) - 1) + b; + }, + + /** + * Begins slowly and accelerates towards end. (quartic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeInStrong: function (t, b, c, d) { + return c*(t/=d)*t*t*t + b; + }, + + /** + * Begins quickly and decelerates towards end. (quartic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeOutStrong: function (t, b, c, d) { + return -c * ((t=t/d-1)*t*t*t - 1) + b; + }, + + /** + * Begins slowly and decelerates towards end. (quartic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeBothStrong: function (t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t*t + b; + return -c/2 * ((t-=2)*t*t*t - 2) + b; + }, + + /** + * snap in elastic effect + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number} p Period (optional) + * @return {Number} The computed value for the current animation frame. + */ + + elasticIn: function (t, b, c, d, a, p) { + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (!a || a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + }, + + /** + * snap out elastic effect + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number} p Period (optional) + * @return {Number} The computed value for the current animation frame. + */ + elasticOut: function (t, b, c, d, a, p) { + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (!a || a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; + }, + + /** + * snap both elastic effect + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number} p Period (optional) + * @return {Number} The computed value for the current animation frame. + */ + elasticBoth: function (t, b, c, d, a, p) { + if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); + if (!a || a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; + }, + + + /** + * back easing in - backtracking slightly, then reversing direction and moving to target + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number) s Overshoot (optional) + * @return {Number} The computed value for the current animation frame. + */ + backIn: function (t, b, c, d, s) { + if (typeof s == 'undefined') s = 1.70158; + return c*(t/=d)*t*((s+1)*t - s) + b; + }, + + /** + * back easing out - moving towards target, overshooting it slightly, + * then reversing and coming back to target + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number) s Overshoot (optional) + * @return {Number} The computed value for the current animation frame. + */ + backOut: function (t, b, c, d, s) { + if (typeof s == 'undefined') s = 1.70158; + return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; + }, + + /** + * back easing in/out - backtracking slightly, then reversing direction and moving to target, + * then overshooting target, reversing, and finally coming back to target + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number) s Overshoot (optional) + * @return {Number} The computed value for the current animation frame. + */ + backBoth: function (t, b, c, d, s) { + if (typeof s == 'undefined') s = 1.70158; + if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; + return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; + }, + + /** + * bounce in + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + bounceIn: function (t, b, c, d) { + return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b; + }, + + /** + * bounce out + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + bounceOut: function (t, b, c, d) { + if ((t/=d) < (1/2.75)) { + return c*(7.5625*t*t) + b; + } else if (t < (2/2.75)) { + return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; + } else if (t < (2.5/2.75)) { + return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; + } else { + return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; + } + }, + + /** + * bounce both + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + bounceBoth: function (t, b, c, d) { + if (t < d/2) return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b; + return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b; + } +}; + +/** + * @class Anim subclass for moving elements along a path defined by the "points" member of "attributes". All "points" are arrays with x, y coordinates. + *

    Usage: var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);

    + * @requires YAHOO.util.Anim + * @requires YAHOO.util.AnimMgr + * @requires YAHOO.util.Easing + * @requires YAHOO.util.Bezier + * @requires YAHOO.util.Dom + * @requires YAHOO.util.Event + * @requires YAHOO.util.CustomEvent + * @constructor + * @param {String or HTMLElement} el Reference to the element that will be animated + * @param {Object} attributes The attribute(s) to be animated. + * Each attribute is an object with at minimum a "to" or "by" member defined. + * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). + * All attribute names use camelCase. + * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based + * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) + */ +(function() { + YAHOO.util.Motion = function(el, attributes, duration, method) { + if (el) { // dont break existing subclasses not using YAHOO.extend + YAHOO.util.Motion.superclass.constructor.call(this, el, attributes, duration, method); + } + }; + + YAHOO.extend(YAHOO.util.Motion, YAHOO.util.ColorAnim); + + // shorthand + var Y = YAHOO.util; + var superclass = Y.Motion.superclass; + var proto = Y.Motion.prototype; + + /** + * toString method + * @return {String} string represenation of anim obj + */ + proto.toString = function() { + var el = this.getEl(); + var id = el.id || el.tagName; + return ("Motion " + id); + }; + + proto.patterns.points = /^points$/i; + + /** + * Applies a value to an attribute + * @param {String} attr The name of the attribute. + * @param {Number} val The value to be applied to the attribute. + * @param {String} unit The unit ('px', '%', etc.) of the value. + */ + proto.setAttribute = function(attr, val, unit) { + if ( this.patterns.points.test(attr) ) { + unit = unit || 'px'; + superclass.setAttribute.call(this, 'left', val[0], unit); + superclass.setAttribute.call(this, 'top', val[1], unit); + } else { + superclass.setAttribute.call(this, attr, val, unit); + } + }; + + /** + * Sets the default value to be used when "from" is not supplied. + * @param {String} attr The attribute being set. + * @param {Number} val The default value to be applied to the attribute. + */ + proto.getAttribute = function(attr) { + if ( this.patterns.points.test(attr) ) { + var val = [ + superclass.getAttribute.call(this, 'left'), + superclass.getAttribute.call(this, 'top') + ]; + } else { + val = superclass.getAttribute.call(this, attr); + } + + return val; + }; + + /** + * Returns the value computed by the animation's "method". + * @param {String} attr The name of the attribute. + * @param {Number} start The value this attribute should start from for this animation. + * @param {Number} end The value this attribute should end at for this animation. + * @return {Number} The Value to be applied to the attribute. + */ + proto.doMethod = function(attr, start, end) { + var val = null; + + if ( this.patterns.points.test(attr) ) { + var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100; + val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t); + } else { + val = superclass.doMethod.call(this, attr, start, end); + } + return val; + }; + + /** + * Sets the actual values to be used during the animation. + * Should only be needed for subclass use. + * @param {Object} attr The attribute object + * @private + */ + proto.setRuntimeAttribute = function(attr) { + if ( this.patterns.points.test(attr) ) { + var el = this.getEl(); + var attributes = this.attributes; + var start; + var control = attributes['points']['control'] || []; + var end; + var i, len; + + if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points + control = [control]; + } else { // break reference to attributes.points.control + var tmp = []; + for (i = 0, len = control.length; i< len; ++i) { + tmp[i] = control[i]; + } + control = tmp; + } + + if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative + Y.Dom.setStyle(el, 'position', 'relative'); + } + + if ( isset(attributes['points']['from']) ) { + Y.Dom.setXY(el, attributes['points']['from']); // set position to from point + } + else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position + + start = this.getAttribute('points'); // get actual top & left + + // TO beats BY, per SMIL 2.1 spec + if ( isset(attributes['points']['to']) ) { + end = translateValues.call(this, attributes['points']['to'], start); + + var pageXY = Y.Dom.getXY(this.getEl()); + for (i = 0, len = control.length; i < len; ++i) { + control[i] = translateValues.call(this, control[i], start); + } + + + } else if ( isset(attributes['points']['by']) ) { + end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ]; + + for (i = 0, len = control.length; i < len; ++i) { + control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ]; + } + } + + this.runtimeAttributes[attr] = [start]; + + if (control.length > 0) { + this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control); + } + + this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end; + } + else { + superclass.setRuntimeAttribute.call(this, attr); + } + }; + + var translateValues = function(val, start) { + var pageXY = Y.Dom.getXY(this.getEl()); + val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ]; + + return val; + }; + + var isset = function(prop) { + return (typeof prop !== 'undefined'); + }; +})(); +/** + * @class Anim subclass for scrolling elements to a position defined by the "scroll" member of "attributes". All "scroll" members are arrays with x, y scroll positions. + *

    Usage: var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);

    + * @requires YAHOO.util.Anim + * @requires YAHOO.util.AnimMgr + * @requires YAHOO.util.Easing + * @requires YAHOO.util.Bezier + * @requires YAHOO.util.Dom + * @requires YAHOO.util.Event + * @requires YAHOO.util.CustomEvent + * @constructor + * @param {String or HTMLElement} el Reference to the element that will be animated + * @param {Object} attributes The attribute(s) to be animated. + * Each attribute is an object with at minimum a "to" or "by" member defined. + * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). + * All attribute names use camelCase. + * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based + * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) + */ +(function() { + YAHOO.util.Scroll = function(el, attributes, duration, method) { + if (el) { // dont break existing subclasses not using YAHOO.extend + YAHOO.util.Scroll.superclass.constructor.call(this, el, attributes, duration, method); + } + }; + + YAHOO.extend(YAHOO.util.Scroll, YAHOO.util.ColorAnim); + + // shorthand + var Y = YAHOO.util; + var superclass = Y.Scroll.superclass; + var proto = Y.Scroll.prototype; + + /** + * toString method + * @return {String} string represenation of anim obj + */ + proto.toString = function() { + var el = this.getEl(); + var id = el.id || el.tagName; + return ("Scroll " + id); + }; + + /** + * Returns the value computed by the animation's "method". + * @param {String} attr The name of the attribute. + * @param {Number} start The value this attribute should start from for this animation. + * @param {Number} end The value this attribute should end at for this animation. + * @return {Number} The Value to be applied to the attribute. + */ + proto.doMethod = function(attr, start, end) { + var val = null; + + if (attr == 'scroll') { + val = [ + this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames), + this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames) + ]; + + } else { + val = superclass.doMethod.call(this, attr, start, end); + } + return val; + }; + + /** + * Returns current value of the attribute. + * @param {String} attr The name of the attribute. + * @return {Number} val The current value of the attribute. + */ + proto.getAttribute = function(attr) { + var val = null; + var el = this.getEl(); + + if (attr == 'scroll') { + val = [ el.scrollLeft, el.scrollTop ]; + } else { + val = superclass.getAttribute.call(this, attr); + } + + return val; + }; + + /** + * Applies a value to an attribute + * @param {String} attr The name of the attribute. + * @param {Number} val The value to be applied to the attribute. + * @param {String} unit The unit ('px', '%', etc.) of the value. + */ + proto.setAttribute = function(attr, val, unit) { + var el = this.getEl(); + + if (attr == 'scroll') { + el.scrollLeft = val[0]; + el.scrollTop = val[1]; + } else { + superclass.setAttribute.call(this, attr, val, unit); + } + }; +})(); Index: openacs-4/packages/ajaxhelper/www/yui/animation/animation-min.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yui/animation/Attic/animation-min.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/yui/animation/animation-min.js 20 Aug 2006 14:39:26 -0000 1.1 @@ -0,0 +1 @@ +/* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt Version: 0.11.1 */ YAHOO.util.Anim=function(el,attributes,duration,method){if(el){this.init(el,attributes,duration,method);}};YAHOO.util.Anim.prototype={toString:function(){var el=this.getEl();var id=el.id||el.tagName;return("Anim "+id);},patterns:{noNegatives:/width|height|opacity|padding/i,offsetAttribute:/^((width|height)|(top|left))$/,defaultUnit:/width|height|top$|bottom$|left$|right$/i,offsetUnit:/\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i},doMethod:function(attr,start,end){return this.method(this.currentFrame,start,end-start,this.totalFrames);},setAttribute:function(attr,val,unit){if(this.patterns.noNegatives.test(attr)){val=(val>0)?val:0;}YAHOO.util.Dom.setStyle(this.getEl(),attr,val+unit);},getAttribute:function(attr){var el=this.getEl();var val=YAHOO.util.Dom.getStyle(el,attr);if(val!=='auto'&&!this.patterns.offsetUnit.test(val)){return parseFloat(val);}var a=this.patterns.offsetAttribute.exec(attr)||[];var pos=!!(a[3]);var box=!!(a[2]);if(box||(YAHOO.util.Dom.getStyle(el,'position')=='absolute'&&pos)){val=el['offset'+a[0].charAt(0).toUpperCase()+a[0].substr(1)];}else{val=0;}return val;},getDefaultUnit:function(attr){if(this.patterns.defaultUnit.test(attr)){return'px';}return'';},setRuntimeAttribute:function(attr){var start;var end;var attributes=this.attributes;this.runtimeAttributes[attr]={};var isset=function(prop){return(typeof prop!=='undefined');};if(!isset(attributes[attr]['to'])&&!isset(attributes[attr]['by'])){return false;}start=(isset(attributes[attr]['from']))?attributes[attr]['from']:this.getAttribute(attr);if(isset(attributes[attr]['to'])){end=attributes[attr]['to'];}else if(isset(attributes[attr]['by'])){if(start.constructor==Array){end=[];for(var i=0,len=start.length;i0&&isFinite(tweak)){if(tween.currentFrame+tweak>=frames){tweak=frames-(frame+1);}tween.currentFrame+=tweak;}};};YAHOO.util.Bezier=new function(){this.getPosition=function(points,t){var n=points.length;var tmp=[];for(var i=0;i0&&!(control[0]instanceof Array)){control=[control];}else{var tmp=[];for(i=0,len=control.length;i0){this.runtimeAttributes[attr]=this.runtimeAttributes[attr].concat(control);}this.runtimeAttributes[attr][this.runtimeAttributes[attr].length]=end;}else{superclass.setRuntimeAttribute.call(this,attr);}};var translateValues=function(val,start){var pageXY=Y.Dom.getXY(this.getEl());val=[val[0]-pageXY[0]+start[0],val[1]-pageXY[1]+start[1]];return val;};var isset=function(prop){return(typeof prop!=='undefined');};})();(function(){YAHOO.util.Scroll=function(el,attributes,duration,method){if(el){YAHOO.util.Scroll.superclass.constructor.call(this,el,attributes,duration,method);}};YAHOO.extend(YAHOO.util.Scroll,YAHOO.util.ColorAnim);var Y=YAHOO.util;var superclass=Y.Scroll.superclass;var proto=Y.Scroll.prototype;proto.toString=function(){var el=this.getEl();var id=el.id||el.tagName;return("Scroll "+id);};proto.doMethod=function(attr,start,end){var val=null;if(attr=='scroll'){val=[this.method(this.currentFrame,start[0],end[0]-start[0],this.totalFrames),this.method(this.currentFrame,start[1],end[1]-start[1],this.totalFrames)];}else{val=superclass.doMethod.call(this,attr,start,end);}return val;};proto.getAttribute=function(attr){var val=null;var el=this.getEl();if(attr=='scroll'){val=[el.scrollLeft,el.scrollTop];}else{val=superclass.getAttribute.call(this,attr);}return val;};proto.setAttribute=function(attr,val,unit){var el=this.getEl();if(attr=='scroll'){el.scrollLeft=val[0];el.scrollTop=val[1];}else{superclass.setAttribute.call(this,attr,val,unit);}};})(); Index: openacs-4/packages/ajaxhelper/www/yui/animation/animation.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yui/animation/Attic/animation.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/yui/animation/animation.js 20 Aug 2006 14:39:26 -0000 1.1 @@ -0,0 +1,1255 @@ +/* +Copyright (c) 2006, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +Version: 0.11.1 +*/ +/** + * + * Base class for animated DOM objects. + * @class Base animation class that provides the interface for building animated effects. + *

    Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);

    + * @requires YAHOO.util.AnimMgr + * @requires YAHOO.util.Easing + * @requires YAHOO.util.Dom + * @requires YAHOO.util.Event + * @requires YAHOO.util.CustomEvent + * @constructor + * @param {String or HTMLElement} el Reference to the element that will be animated + * @param {Object} attributes The attribute(s) to be animated. + * Each attribute is an object with at minimum a "to" or "by" member defined. + * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). + * All attribute names use camelCase. + * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based + * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) + */ + +YAHOO.util.Anim = function(el, attributes, duration, method) { + if (el) { + this.init(el, attributes, duration, method); + } +}; + +YAHOO.util.Anim.prototype = { + /** + * toString method + * @return {String} string represenation of anim obj + */ + toString: function() { + var el = this.getEl(); + var id = el.id || el.tagName; + return ("Anim " + id); + }, + + patterns: { // cached for performance + noNegatives: /width|height|opacity|padding/i, // keep at zero or above + offsetAttribute: /^((width|height)|(top|left))$/, // use offsetValue as default + defaultUnit: /width|height|top$|bottom$|left$|right$/i, // use 'px' by default + offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset + }, + + /** + * Returns the value computed by the animation's "method". + * @param {String} attr The name of the attribute. + * @param {Number} start The value this attribute should start from for this animation. + * @param {Number} end The value this attribute should end at for this animation. + * @return {Number} The Value to be applied to the attribute. + */ + doMethod: function(attr, start, end) { + return this.method(this.currentFrame, start, end - start, this.totalFrames); + }, + + /** + * Applies a value to an attribute + * @param {String} attr The name of the attribute. + * @param {Number} val The value to be applied to the attribute. + * @param {String} unit The unit ('px', '%', etc.) of the value. + */ + setAttribute: function(attr, val, unit) { + if ( this.patterns.noNegatives.test(attr) ) { + val = (val > 0) ? val : 0; + } + + YAHOO.util.Dom.setStyle(this.getEl(), attr, val + unit); + }, + + /** + * Returns current value of the attribute. + * @param {String} attr The name of the attribute. + * @return {Number} val The current value of the attribute. + */ + getAttribute: function(attr) { + var el = this.getEl(); + var val = YAHOO.util.Dom.getStyle(el, attr); + + if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) { + return parseFloat(val); + } + + var a = this.patterns.offsetAttribute.exec(attr) || []; + var pos = !!( a[3] ); // top or left + var box = !!( a[2] ); // width or height + + // use offsets for width/height and abs pos top/left + if ( box || (YAHOO.util.Dom.getStyle(el, 'position') == 'absolute' && pos) ) { + val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)]; + } else { // default to zero for other 'auto' + val = 0; + } + + return val; + }, + + /** + * Returns the unit to use when none is supplied. + * Applies the "defaultUnit" test to decide whether to use pixels or not + * @param {attr} attr The name of the attribute. + * @return {String} The default unit to be used. + */ + getDefaultUnit: function(attr) { + if ( this.patterns.defaultUnit.test(attr) ) { + return 'px'; + } + + return ''; + }, + + /** + * Sets the actual values to be used during the animation. + * Should only be needed for subclass use. + * @param {Object} attr The attribute object + * @private + */ + setRuntimeAttribute: function(attr) { + var start; + var end; + var attributes = this.attributes; + + this.runtimeAttributes[attr] = {}; + + var isset = function(prop) { + return (typeof prop !== 'undefined'); + }; + + if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) { + return false; // note return; nothing to animate to + } + + start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr); + + // To beats by, per SMIL 2.1 spec + if ( isset(attributes[attr]['to']) ) { + end = attributes[attr]['to']; + } else if ( isset(attributes[attr]['by']) ) { + if (start.constructor == Array) { + end = []; + for (var i = 0, len = start.length; i < len; ++i) { + end[i] = start[i] + attributes[attr]['by'][i]; + } + } else { + end = start + attributes[attr]['by']; + } + } + + this.runtimeAttributes[attr].start = start; + this.runtimeAttributes[attr].end = end; + + // set units if needed + this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr); + }, + + /** + * @param {String or HTMLElement} el Reference to the element that will be animated + * @param {Object} attributes The attribute(s) to be animated. + * Each attribute is an object with at minimum a "to" or "by" member defined. + * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). + * All attribute names use camelCase. + * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based + * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) + */ + init: function(el, attributes, duration, method) { + /** + * Whether or not the animation is running. + * @private + * @type Boolean + */ + var isAnimated = false; + + /** + * A Date object that is created when the animation begins. + * @private + * @type Date + */ + var startTime = null; + + /** + * The number of frames this animation was able to execute. + * @private + * @type Int + */ + var actualFrames = 0; + + /** + * The element to be animated. + * @private + * @type HTMLElement + */ + el = YAHOO.util.Dom.get(el); + + /** + * The collection of attributes to be animated. + * Each attribute must have at least a "to" or "by" defined in order to animate. + * If "to" is supplied, the animation will end with the attribute at that value. + * If "by" is supplied, the animation will end at that value plus its starting value. + * If both are supplied, "to" is used, and "by" is ignored. + * @member YAHOO#util#Anim + * Optional additional member include "from" (the value the attribute should start animating from, defaults to current value), and "unit" (the units to apply to the values). + * @type Object + */ + this.attributes = attributes || {}; + + /** + * The length of the animation. Defaults to "1" (second). + * @type Number + */ + this.duration = duration || 1; + + /** + * The method that will provide values to the attribute(s) during the animation. + * Defaults to "YAHOO.util.Easing.easeNone". + * @type Function + */ + this.method = method || YAHOO.util.Easing.easeNone; + + /** + * Whether or not the duration should be treated as seconds. + * Defaults to true. + * @type Boolean + */ + this.useSeconds = true; // default to seconds + + /** + * The location of the current animation on the timeline. + * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time. + * @type Int + */ + this.currentFrame = 0; + + /** + * The total number of frames to be executed. + * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time. + * @type Int + */ + this.totalFrames = YAHOO.util.AnimMgr.fps; + + + /** + * Returns a reference to the animated element. + * @return {HTMLElement} + */ + this.getEl = function() { return el; }; + + /** + * Checks whether the element is currently animated. + * @return {Boolean} current value of isAnimated. + */ + this.isAnimated = function() { + return isAnimated; + }; + + /** + * Returns the animation start time. + * @return {Date} current value of startTime. + */ + this.getStartTime = function() { + return startTime; + }; + + this.runtimeAttributes = {}; + + + + /** + * Starts the animation by registering it with the animation manager. + */ + this.animate = function() { + if ( this.isAnimated() ) { return false; } + + this.currentFrame = 0; + + this.totalFrames = ( this.useSeconds ) ? Math.ceil(YAHOO.util.AnimMgr.fps * this.duration) : this.duration; + + YAHOO.util.AnimMgr.registerElement(this); + }; + + /** + * Stops the animation. Normally called by AnimMgr when animation completes. + */ + this.stop = function() { + YAHOO.util.AnimMgr.stop(this); + }; + + var onStart = function() { + this.onStart.fire(); + for (var attr in this.attributes) { + this.setRuntimeAttribute(attr); + } + + isAnimated = true; + actualFrames = 0; + startTime = new Date(); + }; + + /** + * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s). + * @private + */ + + var onTween = function() { + var data = { + duration: new Date() - this.getStartTime(), + currentFrame: this.currentFrame + }; + + data.toString = function() { + return ( + 'duration: ' + data.duration + + ', currentFrame: ' + data.currentFrame + ); + }; + + this.onTween.fire(data); + + var runtimeAttributes = this.runtimeAttributes; + + for (var attr in runtimeAttributes) { + this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit); + } + + actualFrames += 1; + }; + + var onComplete = function() { + var actual_duration = (new Date() - startTime) / 1000 ; + + var data = { + duration: actual_duration, + frames: actualFrames, + fps: actualFrames / actual_duration + }; + + data.toString = function() { + return ( + 'duration: ' + data.duration + + ', frames: ' + data.frames + + ', fps: ' + data.fps + ); + }; + + isAnimated = false; + actualFrames = 0; + this.onComplete.fire(data); + }; + + /** + * Custom event that fires after onStart, useful in subclassing + * @private + */ + this._onStart = new YAHOO.util.CustomEvent('_start', this, true); + + /** + * Custom event that fires when animation begins + * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction) + */ + this.onStart = new YAHOO.util.CustomEvent('start', this); + + /** + * Custom event that fires between each frame + * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction) + */ + this.onTween = new YAHOO.util.CustomEvent('tween', this); + + /** + * Custom event that fires after onTween + * @private + */ + this._onTween = new YAHOO.util.CustomEvent('_tween', this, true); + + /** + * Custom event that fires when animation ends + * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction) + */ + this.onComplete = new YAHOO.util.CustomEvent('complete', this); + /** + * Custom event that fires after onComplete + * @private + */ + this._onComplete = new YAHOO.util.CustomEvent('_complete', this, true); + + this._onStart.subscribe(onStart); + this._onTween.subscribe(onTween); + this._onComplete.subscribe(onComplete); + } +}; + +/** + * @class Handles animation queueing and threading. + * Used by Anim and subclasses. + */ +YAHOO.util.AnimMgr = new function() { + /** + * Reference to the animation Interval + * @private + * @type Int + */ + var thread = null; + + /** + * The current queue of registered animation objects. + * @private + * @type Array + */ + var queue = []; + + /** + * The number of active animations. + * @private + * @type Int + */ + var tweenCount = 0; + + /** + * Base frame rate (frames per second). + * Arbitrarily high for better x-browser calibration (slower browsers drop more frames). + * @type Int + * + */ + this.fps = 200; + + /** + * Interval delay in milliseconds, defaults to fastest possible. + * @type Int + * + */ + this.delay = 1; + + /** + * Adds an animation instance to the animation queue. + * All animation instances must be registered in order to animate. + * @param {object} tween The Anim instance to be be registered + */ + this.registerElement = function(tween) { + queue[queue.length] = tween; + tweenCount += 1; + tween._onStart.fire(); + this.start(); + }; + + this.unRegister = function(tween, index) { + tween._onComplete.fire(); + index = index || getIndex(tween); + if (index != -1) { queue.splice(index, 1); } + + tweenCount -= 1; + if (tweenCount <= 0) { this.stop(); } + }; + + /** + * Starts the animation thread. + * Only one thread can run at a time. + */ + this.start = function() { + if (thread === null) { thread = setInterval(this.run, this.delay); } + }; + + /** + * Stops the animation thread or a specific animation instance. + * @param {object} tween A specific Anim instance to stop (optional) + * If no instance given, Manager stops thread and all animations. + */ + this.stop = function(tween) { + if (!tween) { + clearInterval(thread); + for (var i = 0, len = queue.length; i < len; ++i) { + if (queue[i].isAnimated()) { + this.unRegister(tween, i); + } + } + queue = []; + thread = null; + tweenCount = 0; + } + else { + this.unRegister(tween); + } + }; + + /** + * Called per Interval to handle each animation frame. + */ + this.run = function() { + for (var i = 0, len = queue.length; i < len; ++i) { + var tween = queue[i]; + if ( !tween || !tween.isAnimated() ) { continue; } + + if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null) + { + tween.currentFrame += 1; + + if (tween.useSeconds) { + correctFrame(tween); + } + tween._onTween.fire(); + } + else { YAHOO.util.AnimMgr.stop(tween, i); } + } + }; + + var getIndex = function(anim) { + for (var i = 0, len = queue.length; i < len; ++i) { + if (queue[i] == anim) { + return i; // note return; + } + } + return -1; + }; + + /** + * On the fly frame correction to keep animation on time. + * @private + * @param {Object} tween The Anim instance being corrected. + */ + var correctFrame = function(tween) { + var frames = tween.totalFrames; + var frame = tween.currentFrame; + var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames); + var elapsed = (new Date() - tween.getStartTime()); + var tweak = 0; + + if (elapsed < tween.duration * 1000) { // check if falling behind + tweak = Math.round((elapsed / expected - 1) * tween.currentFrame); + } else { // went over duration, so jump to end + tweak = frames - (frame + 1); + } + if (tweak > 0 && isFinite(tweak)) { // adjust if needed + if (tween.currentFrame + tweak >= frames) {// dont go past last frame + tweak = frames - (frame + 1); + } + + tween.currentFrame += tweak; + } + }; +}; +/** + * + * @class Used to calculate Bezier splines for any number of control points. + * + */ +YAHOO.util.Bezier = new function() +{ + /** + * Get the current position of the animated element based on t. + * Each point is an array of "x" and "y" values (0 = x, 1 = y) + * At least 2 points are required (start and end). + * First point is start. Last point is end. + * Additional control points are optional. + * @param {Array} points An array containing Bezier points + * @param {Number} t A number between 0 and 1 which is the basis for determining current position + * @return {Array} An array containing int x and y member data + */ + this.getPosition = function(points, t) + { + var n = points.length; + var tmp = []; + + for (var i = 0; i < n; ++i){ + tmp[i] = [points[i][0], points[i][1]]; // save input + } + + for (var j = 1; j < n; ++j) { + for (i = 0; i < n - j; ++i) { + tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0]; + tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1]; + } + } + + return [ tmp[0][0], tmp[0][1] ]; + + }; +}; +/** + * @class ColorAnim subclass for color fading + *

    Usage: var myAnim = new Y.ColorAnim(el, { backgroundColor: { from: '#FF0000', to: '#FFFFFF' } }, 1, Y.Easing.easeOut);

    + *

    Color values can be specified with either 112233, #112233, [255,255,255], or rgb(255,255,255) + * @requires YAHOO.util.Anim + * @requires YAHOO.util.AnimMgr + * @requires YAHOO.util.Easing + * @requires YAHOO.util.Bezier + * @requires YAHOO.util.Dom + * @requires YAHOO.util.Event + * @constructor + * @param {HTMLElement | String} el Reference to the element that will be animated + * @param {Object} attributes The attribute(s) to be animated. + * Each attribute is an object with at minimum a "to" or "by" member defined. + * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). + * All attribute names use camelCase. + * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based + * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) + */ +(function() { + YAHOO.util.ColorAnim = function(el, attributes, duration, method) { + YAHOO.util.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method); + }; + + YAHOO.extend(YAHOO.util.ColorAnim, YAHOO.util.Anim); + + // shorthand + var Y = YAHOO.util; + var superclass = Y.ColorAnim.superclass; + var proto = Y.ColorAnim.prototype; + + /** + * toString method + * @return {String} string represenation of anim obj + */ + proto.toString = function() { + var el = this.getEl(); + var id = el.id || el.tagName; + return ("ColorAnim " + id); + }; + + /** + * Only certain attributes should be treated as colors. + * @type Object + */ + proto.patterns.color = /color$/i; + proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i; + proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i; + proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i; + + /** + * Attempts to parse the given string and return a 3-tuple. + * @param {String} s The string to parse. + * @return {Array} The 3-tuple of rgb values. + */ + proto.parseColor = function(s) { + if (s.length == 3) { return s; } + + var c = this.patterns.hex.exec(s); + if (c && c.length == 4) { + return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ]; + } + + c = this.patterns.rgb.exec(s); + if (c && c.length == 4) { + return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ]; + } + + c = this.patterns.hex3.exec(s); + if (c && c.length == 4) { + return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ]; + } + + return null; + }; + + /** + * Returns current value of the attribute. + * @param {String} attr The name of the attribute. + * @return {Number} val The current value of the attribute. + */ + proto.getAttribute = function(attr) { + var el = this.getEl(); + if ( this.patterns.color.test(attr) ) { + var val = YAHOO.util.Dom.getStyle(el, attr); + + if (val == 'transparent') { // bgcolor default + var parent = el.parentNode; // try and get from an ancestor + val = Y.Dom.getStyle(parent, attr); + + while (parent && val == 'transparent') { + parent = parent.parentNode; + val = Y.Dom.getStyle(parent, attr); + if (parent.tagName.toUpperCase() == 'HTML') { + val = 'ffffff'; + } + } + } + } else { + val = superclass.getAttribute.call(this, attr); + } + + return val; + }; + + /** + * Returns the value computed by the animation's "method". + * @param {String} attr The name of the attribute. + * @param {Number} start The value this attribute should start from for this animation. + * @param {Number} end The value this attribute should end at for this animation. + * @return {Number} The Value to be applied to the attribute. + */ + proto.doMethod = function(attr, start, end) { + var val; + + if ( this.patterns.color.test(attr) ) { + val = []; + for (var i = 0, len = start.length; i < len; ++i) { + val[i] = superclass.doMethod.call(this, attr, start[i], end[i]); + } + + val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')'; + } + else { + val = superclass.doMethod.call(this, attr, start, end); + } + + return val; + }; + + /** + * Sets the actual values to be used during the animation. + * Should only be needed for subclass use. + * @param {Object} attr The attribute object + * @private + */ + proto.setRuntimeAttribute = function(attr) { + superclass.setRuntimeAttribute.call(this, attr); + + if ( this.patterns.color.test(attr) ) { + var attributes = this.attributes; + var start = this.parseColor(this.runtimeAttributes[attr].start); + var end = this.parseColor(this.runtimeAttributes[attr].end); + // fix colors if going "by" + if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) { + end = this.parseColor(attributes[attr].by); + + for (var i = 0, len = start.length; i < len; ++i) { + end[i] = start[i] + end[i]; + } + } + + this.runtimeAttributes[attr].start = start; + this.runtimeAttributes[attr].end = end; + } + }; +})();/* +TERMS OF USE - EASING EQUATIONS +Open source under the BSD License. +Copyright � 2001 Robert Penner All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +YAHOO.util.Easing = { + + /** + * Uniform speed between points. + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeNone: function (t, b, c, d) { + return c*t/d + b; + }, + + /** + * Begins slowly and accelerates towards end. (quadratic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeIn: function (t, b, c, d) { + return c*(t/=d)*t + b; + }, + + /** + * Begins quickly and decelerates towards end. (quadratic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeOut: function (t, b, c, d) { + return -c *(t/=d)*(t-2) + b; + }, + + /** + * Begins slowly and decelerates towards end. (quadratic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeBoth: function (t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t + b; + return -c/2 * ((--t)*(t-2) - 1) + b; + }, + + /** + * Begins slowly and accelerates towards end. (quartic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeInStrong: function (t, b, c, d) { + return c*(t/=d)*t*t*t + b; + }, + + /** + * Begins quickly and decelerates towards end. (quartic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeOutStrong: function (t, b, c, d) { + return -c * ((t=t/d-1)*t*t*t - 1) + b; + }, + + /** + * Begins slowly and decelerates towards end. (quartic) + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + easeBothStrong: function (t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t*t + b; + return -c/2 * ((t-=2)*t*t*t - 2) + b; + }, + + /** + * snap in elastic effect + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number} p Period (optional) + * @return {Number} The computed value for the current animation frame. + */ + + elasticIn: function (t, b, c, d, a, p) { + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (!a || a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + }, + + /** + * snap out elastic effect + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number} p Period (optional) + * @return {Number} The computed value for the current animation frame. + */ + elasticOut: function (t, b, c, d, a, p) { + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (!a || a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; + }, + + /** + * snap both elastic effect + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number} p Period (optional) + * @return {Number} The computed value for the current animation frame. + */ + elasticBoth: function (t, b, c, d, a, p) { + if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); + if (!a || a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; + }, + + /** + * back easing in - backtracking slightly, then reversing direction and moving to target + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number) s Overshoot (optional) + * @return {Number} The computed value for the current animation frame. + */ + backIn: function (t, b, c, d, s) { + if (typeof s == 'undefined') s = 1.70158; + return c*(t/=d)*t*((s+1)*t - s) + b; + }, + + /** + * back easing out - moving towards target, overshooting it slightly, + * then reversing and coming back to target + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number) s Overshoot (optional) + * @return {Number} The computed value for the current animation frame. + */ + backOut: function (t, b, c, d, s) { + if (typeof s == 'undefined') s = 1.70158; + return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; + }, + + /** + * back easing in/out - backtracking slightly, then reversing direction and moving to target, + * then overshooting target, reversing, and finally coming back to target + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @param {Number) s Overshoot (optional) + * @return {Number} The computed value for the current animation frame. + */ + backBoth: function (t, b, c, d, s) { + if (typeof s == 'undefined') s = 1.70158; + if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; + return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; + }, + + /** + * bounce in + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + bounceIn: function (t, b, c, d) { + return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b; + }, + + /** + * bounce out + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + bounceOut: function (t, b, c, d) { + if ((t/=d) < (1/2.75)) { + return c*(7.5625*t*t) + b; + } else if (t < (2/2.75)) { + return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; + } else if (t < (2.5/2.75)) { + return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; + } else { + return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; + } + }, + + /** + * bounce both + * @param {Number} t Time value used to compute current value. + * @param {Number} b Starting value. + * @param {Number} c Delta between start and end values. + * @param {Number} d Total length of animation. + * @return {Number} The computed value for the current animation frame. + */ + bounceBoth: function (t, b, c, d) { + if (t < d/2) return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b; + return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b; + } +}; + +/** + * @class Anim subclass for moving elements along a path defined by the "points" member of "attributes". All "points" are arrays with x, y coordinates. + *

    Usage: var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);

    + * @requires YAHOO.util.Anim + * @requires YAHOO.util.AnimMgr + * @requires YAHOO.util.Easing + * @requires YAHOO.util.Bezier + * @requires YAHOO.util.Dom + * @requires YAHOO.util.Event + * @requires YAHOO.util.CustomEvent + * @constructor + * @param {String or HTMLElement} el Reference to the element that will be animated + * @param {Object} attributes The attribute(s) to be animated. + * Each attribute is an object with at minimum a "to" or "by" member defined. + * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). + * All attribute names use camelCase. + * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based + * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) + */ +(function() { + YAHOO.util.Motion = function(el, attributes, duration, method) { + if (el) { // dont break existing subclasses not using YAHOO.extend + YAHOO.util.Motion.superclass.constructor.call(this, el, attributes, duration, method); + } + }; + + YAHOO.extend(YAHOO.util.Motion, YAHOO.util.ColorAnim); + + // shorthand + var Y = YAHOO.util; + var superclass = Y.Motion.superclass; + var proto = Y.Motion.prototype; + + /** + * toString method + * @return {String} string represenation of anim obj + */ + proto.toString = function() { + var el = this.getEl(); + var id = el.id || el.tagName; + return ("Motion " + id); + }; + + proto.patterns.points = /^points$/i; + + /** + * Applies a value to an attribute + * @param {String} attr The name of the attribute. + * @param {Number} val The value to be applied to the attribute. + * @param {String} unit The unit ('px', '%', etc.) of the value. + */ + proto.setAttribute = function(attr, val, unit) { + if ( this.patterns.points.test(attr) ) { + unit = unit || 'px'; + superclass.setAttribute.call(this, 'left', val[0], unit); + superclass.setAttribute.call(this, 'top', val[1], unit); + } else { + superclass.setAttribute.call(this, attr, val, unit); + } + }; + + /** + * Sets the default value to be used when "from" is not supplied. + * @param {String} attr The attribute being set. + * @param {Number} val The default value to be applied to the attribute. + */ + proto.getAttribute = function(attr) { + if ( this.patterns.points.test(attr) ) { + var val = [ + superclass.getAttribute.call(this, 'left'), + superclass.getAttribute.call(this, 'top') + ]; + } else { + val = superclass.getAttribute.call(this, attr); + } + + return val; + }; + + /** + * Returns the value computed by the animation's "method". + * @param {String} attr The name of the attribute. + * @param {Number} start The value this attribute should start from for this animation. + * @param {Number} end The value this attribute should end at for this animation. + * @return {Number} The Value to be applied to the attribute. + */ + proto.doMethod = function(attr, start, end) { + var val = null; + + if ( this.patterns.points.test(attr) ) { + var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100; + val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t); + } else { + val = superclass.doMethod.call(this, attr, start, end); + } + return val; + }; + + /** + * Sets the actual values to be used during the animation. + * Should only be needed for subclass use. + * @param {Object} attr The attribute object + * @private + */ + proto.setRuntimeAttribute = function(attr) { + if ( this.patterns.points.test(attr) ) { + var el = this.getEl(); + var attributes = this.attributes; + var start; + var control = attributes['points']['control'] || []; + var end; + var i, len; + + if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points + control = [control]; + } else { // break reference to attributes.points.control + var tmp = []; + for (i = 0, len = control.length; i< len; ++i) { + tmp[i] = control[i]; + } + control = tmp; + } + + if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative + Y.Dom.setStyle(el, 'position', 'relative'); + } + + if ( isset(attributes['points']['from']) ) { + Y.Dom.setXY(el, attributes['points']['from']); // set position to from point + } + else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position + + start = this.getAttribute('points'); // get actual top & left + + // TO beats BY, per SMIL 2.1 spec + if ( isset(attributes['points']['to']) ) { + end = translateValues.call(this, attributes['points']['to'], start); + + var pageXY = Y.Dom.getXY(this.getEl()); + for (i = 0, len = control.length; i < len; ++i) { + control[i] = translateValues.call(this, control[i], start); + } + + + } else if ( isset(attributes['points']['by']) ) { + end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ]; + + for (i = 0, len = control.length; i < len; ++i) { + control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ]; + } + } + + this.runtimeAttributes[attr] = [start]; + + if (control.length > 0) { + this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control); + } + + this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end; + } + else { + superclass.setRuntimeAttribute.call(this, attr); + } + }; + + var translateValues = function(val, start) { + var pageXY = Y.Dom.getXY(this.getEl()); + val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ]; + + return val; + }; + + var isset = function(prop) { + return (typeof prop !== 'undefined'); + }; +})(); +/** + * @class Anim subclass for scrolling elements to a position defined by the "scroll" member of "attributes". All "scroll" members are arrays with x, y scroll positions. + *

    Usage: var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);

    + * @requires YAHOO.util.Anim + * @requires YAHOO.util.AnimMgr + * @requires YAHOO.util.Easing + * @requires YAHOO.util.Bezier + * @requires YAHOO.util.Dom + * @requires YAHOO.util.Event + * @requires YAHOO.util.CustomEvent + * @constructor + * @param {String or HTMLElement} el Reference to the element that will be animated + * @param {Object} attributes The attribute(s) to be animated. + * Each attribute is an object with at minimum a "to" or "by" member defined. + * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). + * All attribute names use camelCase. + * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based + * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) + */ +(function() { + YAHOO.util.Scroll = function(el, attributes, duration, method) { + if (el) { // dont break existing subclasses not using YAHOO.extend + YAHOO.util.Scroll.superclass.constructor.call(this, el, attributes, duration, method); + } + }; + + YAHOO.extend(YAHOO.util.Scroll, YAHOO.util.ColorAnim); + + // shorthand + var Y = YAHOO.util; + var superclass = Y.Scroll.superclass; + var proto = Y.Scroll.prototype; + + /** + * toString method + * @return {String} string represenation of anim obj + */ + proto.toString = function() { + var el = this.getEl(); + var id = el.id || el.tagName; + return ("Scroll " + id); + }; + + /** + * Returns the value computed by the animation's "method". + * @param {String} attr The name of the attribute. + * @param {Number} start The value this attribute should start from for this animation. + * @param {Number} end The value this attribute should end at for this animation. + * @return {Number} The Value to be applied to the attribute. + */ + proto.doMethod = function(attr, start, end) { + var val = null; + + if (attr == 'scroll') { + val = [ + this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames), + this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames) + ]; + + } else { + val = superclass.doMethod.call(this, attr, start, end); + } + return val; + }; + + /** + * Returns current value of the attribute. + * @param {String} attr The name of the attribute. + * @return {Number} val The current value of the attribute. + */ + proto.getAttribute = function(attr) { + var val = null; + var el = this.getEl(); + + if (attr == 'scroll') { + val = [ el.scrollLeft, el.scrollTop ]; + } else { + val = superclass.getAttribute.call(this, attr); + } + + return val; + }; + + /** + * Applies a value to an attribute + * @param {String} attr The name of the attribute. + * @param {Number} val The value to be applied to the attribute. + * @param {String} unit The unit ('px', '%', etc.) of the value. + */ + proto.setAttribute = function(attr, val, unit) { + var el = this.getEl(); + + if (attr == 'scroll') { + el.scrollLeft = val[0]; + el.scrollTop = val[1]; + } else { + superclass.setAttribute.call(this, attr, val, unit); + } + }; +})(); Index: openacs-4/packages/ajaxhelper/www/yui/autocomplete/README =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yui/autocomplete/Attic/README,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/yui/autocomplete/README 20 Aug 2006 14:39:26 -0000 1.1 @@ -0,0 +1,30 @@ +AutoComplete Release Notes + +*** version 0.11.0 *** + +* The method getListIds() has been deprecated for getListItems(), which returns +an array of DOM references. + +* All classnames have been prefixed with "yui-ac-". + +* Container elements should no longer have CSS property "display" set to "none". + +* The useIFrame property can now be set after instantiation. + +* On some browsers, the unmatchedItemSelectEvent may not be fired properly when +delimiter characters are defined. + +* On some browsers, defining delimiter characters while enabling forceSelection +may result in unexpected behavior. + + + +*** version 0.10.0 *** + +* Initial release + +* In order to enable the useIFrame property, it should be set in the +constructor. + +* On some browsers, defining delimiter characters while enabling forceSelection +may result in unexpected behavior. Index: openacs-4/packages/ajaxhelper/www/yui/autocomplete/autocomplete-debug.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/yui/autocomplete/Attic/autocomplete-debug.js,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/ajaxhelper/www/yui/autocomplete/autocomplete-debug.js 20 Aug 2006 14:39:26 -0000 1.1 @@ -0,0 +1,5568 @@ +/* + +Copyright (c) 2006, Yahoo! Inc. All rights reserved. + +Code licensed under the BSD License: + +http://developer.yahoo.com/yui/license.txt + +version: 0.11.0 + +*/ + + + +/****************************************************************************/ + +/****************************************************************************/ + +/****************************************************************************/ + + + +/** + + * Class providing the customizable functionality of a plug-and-play DHTML + + * auto complete widget. Some key features: + + *
      + + *
    • Navigate with up/down arrow keys and/or mouse to pick a selection
    • + + *
    • The drop down container can "roll down" or "fly out" via configurable + + * animation
    • + + *
    • UI look-and-feel customizable through CSS, including container + + * attributes, borders, position, fonts, etc
    • + + *
    + + * + + * requires YAHOO.util.Dom Dom utility + + * requires YAHOO.util.Event Event utility + + * requires YAHOO.widget.DataSource Data source class + + * see YAHOO.util.Animation Animation utility + + * see JSON JSON library + + * + + * @constructor + + * @param {element | string} inputEl DOM element reference or string ID of the auto complete input field + + * @param {element | string} containerEl DOM element reference or string ID of the auto complete <div> + + * container + + * @param {object} oDataSource Instance of YAHOO.widget.DataSource for query/results + + * @param {object} oConfigs Optional object literal of config params + + */ + +YAHOO.widget.AutoComplete = function(inputEl,containerEl,oDataSource,oConfigs) { + + if(inputEl && containerEl && oDataSource) { + + // Validate data source + + if (oDataSource && (oDataSource instanceof YAHOO.widget.DataSource)) { + + this.dataSource = oDataSource; + + } + + else { + + YAHOO.log("Could not instantiate AutoComplete due to an invalid DataSource", "error", this.toString()); + + return; + + } + + + + // Validate input element + + if(YAHOO.util.Dom.inDocument(inputEl)) { + + if(typeof inputEl == "string") { + + this._sName = "instance" + YAHOO.widget.AutoComplete._nIndex + " " + inputEl; + + this._oTextbox = document.getElementById(inputEl); + + } + + else { + + this._sName = (inputEl.id) ? + + "instance" + YAHOO.widget.AutoComplete._nIndex + " " + inputEl.id: + + "instance" + YAHOO.widget.AutoComplete._nIndex; + + this._oTextbox = inputEl; + + } + + } + + else { + + YAHOO.log("Could not instantiate AutoComplete due to an invalid input element", "error", this.toString()); + + return; + + } + + + + // Validate container element + + if(YAHOO.util.Dom.inDocument(containerEl)) { + + if(typeof containerEl == "string") { + + this._oContainer = document.getElementById(containerEl); + + } + + else { + + this._oContainer = containerEl; + + } + + if(this._oContainer.style.display == "none") { + + YAHOO.log("The container may not display properly if display is set to \"none\" in CSS", "warn", this.toString()); + + } + + } + + else { + + YAHOO.log("Could not instantiate AutoComplete due to an invalid container element", "error", this.toString()); + + return; + + } + + + + // Set any config params passed in to override defaults + + if (typeof oConfigs == "object") { + + for(var sConfig in oConfigs) { + + if (sConfig) { + + this[sConfig] = oConfigs[sConfig]; + + } + + } + + } + + + + // Initialization sequence + + this._initContainer(); + + this._initProps(); + + this._initList(); + + this._initContainerHelpers(); + + + + // Set up events + + var oSelf = this; + + var oTextbox = this._oTextbox; + + // Events are actually for the content module within the container + + var oContent = this._oContainer._oContent; + + + + // Dom events + + YAHOO.util.Event.addListener(oTextbox,"keyup",oSelf._onTextboxKeyUp,oSelf); + + YAHOO.util.Event.addListener(oTextbox,"keydown",oSelf._onTextboxKeyDown,oSelf); + + YAHOO.util.Event.addListener(oTextbox,"keypress",oSelf._onTextboxKeyPress,oSelf); + + YAHOO.util.Event.addListener(oTextbox,"focus",oSelf._onTextboxFocus,oSelf); + + YAHOO.util.Event.addListener(oTextbox,"blur",oSelf._onTextboxBlur,oSelf); + + YAHOO.util.Event.addListener(oContent,"mouseover",oSelf._onContainerMouseover,oSelf); + + YAHOO.util.Event.addListener(oContent,"mouseout",oSelf._onContainerMouseout,oSelf); + + YAHOO.util.Event.addListener(oContent,"scroll",oSelf._onContainerScroll,oSelf); + + YAHOO.util.Event.addListener(oContent,"resize",oSelf._onContainerResize,oSelf); + + if(oTextbox.form) { + + YAHOO.util.Event.addListener(oTextbox.form,"submit",oSelf._onFormSubmit,oSelf); + + } + + + + // Custom events + + this.textboxFocusEvent = new YAHOO.util.CustomEvent("textboxFocus", this); + + this.textboxKeyEvent = new YAHOO.util.CustomEvent("textboxKey", this); + + this.dataRequestEvent = new YAHOO.util.CustomEvent("dataRequest", this); + + this.dataReturnEvent = new YAHOO.util.CustomEvent("dataReturn", this); + + this.dataErrorEvent = new YAHOO.util.CustomEvent("dataError", this); + + this.containerExpandEvent = new YAHOO.util.CustomEvent("containerExpand", this); + + this.typeAheadEvent = new YAHOO.util.CustomEvent("typeAhead", this); + + this.itemMouseOverEvent = new YAHOO.util.CustomEvent("itemMouseOver", this); + + this.itemMouseOutEvent = new YAHOO.util.CustomEvent("itemMouseOut", this); + + this.itemArrowToEvent = new YAHOO.util.CustomEvent("itemArrowTo", this); + + this.itemArrowFromEvent = new YAHOO.util.CustomEvent("itemArrowFrom", this); + + this.itemSelectEvent = new YAHOO.util.CustomEvent("itemSelect", this); + + this.unmatchedItemSelectEvent = new YAHOO.util.CustomEvent("unmatchedItemSelect", this); + + this.selectionEnforceEvent = new YAHOO.util.CustomEvent("selectionEnforce", this); + + this.containerCollapseEvent = new YAHOO.util.CustomEvent("containerCollapse", this); + + this.textboxBlurEvent = new YAHOO.util.CustomEvent("textboxBlur", this); + + + + // Finish up + + oTextbox.setAttribute("autocomplete","off"); + + YAHOO.widget.AutoComplete._nIndex++; + + YAHOO.log("AutoComplete initialized","info",this.toString()); + + } + + // Required arguments were not found + + else { + + YAHOO.log("Could not instantiate AutoComplete due invalid arguments", "error", this.toString()); + + } + +}; + + + +/*************************************************************************** + + * Public member variables + + ***************************************************************************/ + +/** + + * The data source object that encapsulates the data used for auto completion. + + * This object should be an inherited object from YAHOO.widget.DataSource. + + * + + * @type object + + */ + +YAHOO.widget.AutoComplete.prototype.dataSource = null; + + + +/** + + * Number of characters that must be entered before querying for results. + + * Default: 1. + + * + + * @type number + + */ + +YAHOO.widget.AutoComplete.prototype.minQueryLength = 1; + + + +/** + + * Maximum number of results to display in auto complete container. Default: 10. + + * + + * @type number + + */ + +YAHOO.widget.AutoComplete.prototype.maxResultsDisplayed = 10; + + + +/** + + * Number of seconds to delay before submitting a query request. If a query + + * request is received before a previous one has completed its delay, the + + * previous request is cancelled and the new request is set to the delay. + + * Default: 0.5. + + * + + * @type number + + */ + +YAHOO.widget.AutoComplete.prototype.queryDelay = 0.5; + + + +/** + + * Class name of a highlighted item within the auto complete container. + + * Default: "yui-ac-highlight". + + * + + * @type string + + */ + +YAHOO.widget.AutoComplete.prototype.highlightClassName = "yui-ac-highlight"; + + + +/** + + * Class name of a pre-highlighted item within the auto complete container. + + * Default: null. + + * + + * @type string + + */ + +YAHOO.widget.AutoComplete.prototype.prehighlightClassName = null; + + + +/** + + * Query delimiter. A single character separator for multiple delimited + + * selections. Multiple delimiter characteres may be defined as an array of + + * strings. A null value or empty string indicates that query results cannot + + * be delimited. This feature is not recommended if you need forceSelection to + + * be true. Default: null. + + * + + * @type string or array + + */ + +YAHOO.widget.AutoComplete.prototype.delimChar = null; + + + +/** + + * Whether or not the first item in the auto complete container should be + + * automatically highlighted on expand. Default: true. + + * + + * @type boolean + + */ + +YAHOO.widget.AutoComplete.prototype.autoHighlight = true; + + + +/** + + * Whether or not the auto complete input field should be automatically updated + + * with the first query result as the user types, auto-selecting the substring + + * that the user has not typed. Default: false. + + * + + * @type boolean + + */ + +YAHOO.widget.AutoComplete.prototype.typeAhead = false; + + + +/** + + * Whether or not to animate the expansion/collapse of the auto complete + + * container in the horizontal direction. Default: false. + + * + + * @type boolean + + */ + +YAHOO.widget.AutoComplete.prototype.animHoriz = false; + + + +/** + + * Whether or not to animate the expansion/collapse of the auto complete + + * container in the vertical direction. Default: true. + + * + + * @type boolean + + */ + +YAHOO.widget.AutoComplete.prototype.animVert = true; + + + +/** + + * Speed of container expand/collapse animation, in seconds. Default: 0.3. + + * + + * @type number + + */ + +YAHOO.widget.AutoComplete.prototype.animSpeed = 0.3; + + + +/** + + * Whether or not to force the user's selection to match one of the query + + * results. Enabling this feature essentially transforms the auto complete form + + * input field into a <select> field. This feature is not recommended + + * with delimiter character(s) defined. Default: false. + + * + + * @type boolean + + */ + +YAHOO.widget.AutoComplete.prototype.forceSelection = false; + + + +/** + + * Whether or not to allow browsers to cache user-typed input in the input + + * field. Disabling this feature will prevent the widget from setting the + + * autocomplete="off" on the auto complete input field. When autocomplete="off" + + * and users click the back button after form submission, user-typed input can + + * be prefilled by the browser from its cache. This caching of user input may + + * not be desired for sensitive data, such as credit card numbers, in which + + * case, implementers should consider setting allowBrowserAutocomplete to false. + + * Default: true. + + * + + * @type boolean + + */ + +YAHOO.widget.AutoComplete.prototype.allowBrowserAutocomplete = true; + + + +/** + + * Whether or not the auto complete container should always be displayed. + + * Enabling this feature prevents the toggling of the container to a collapsed + + * state. Default: false. + + * + + * @type boolean + + */ + +YAHOO.widget.AutoComplete.prototype.alwaysShowContainer = false; + + + +/** + + * Whether or not to use an iFrame to layer over Windows form elements in + + * IE. Set to true only when the auto complete container will be on top of a + + * <select> field in IE and thus exposed to the IE z-index bug (i.e., + + * 5.5 < IE < 7). Default:false. + + * + + * @type boolean + + */ + +YAHOO.widget.AutoComplete.prototype.useIFrame = false; + + + +/** + + * Configurable iFrame src used when useIFrame = true. Implementations over SSL + + * should set this parameter to an appropriate https location in order to avoid + + * security-related browser errors. Default:"about:blank". + + * + + * @type boolean + + */ + +YAHOO.widget.AutoComplete.prototype.iFrameSrc = "about:blank"; + + + +/** + + * Whether or not the auto complete container should have a shadow. Default:false. + + * + + * @type boolean + + */ + +YAHOO.widget.AutoComplete.prototype.useShadow = false; + + + +/*************************************************************************** + + * Public methods + + ***************************************************************************/ + + /** + + * Public accessor to the unique name of the auto complete instance. + + * + + * @return {string} Unique name of the auto complete instance + + */ + +YAHOO.widget.AutoComplete.prototype.getName = function() { + + return this._sName; + +}; + + + + /** + + * Public accessor to the unique name of the auto complete instance. + + * + + * @return {string} Unique name of the auto complete instance + + */ + +YAHOO.widget.AutoComplete.prototype.toString = function() { + + return "AutoComplete " + this._sName; + +}; + + + +/** + + * Public accessor to the internal array of DOM <li> elements that + + * display query results within the auto complete container. + + * + + * @return {array} Array of <li> elements within the auto complete + + * container + + */ + +YAHOO.widget.AutoComplete.prototype.getListItems = function() { + + return this._aListItems; + +}; + + + +/** + + * Public accessor to the data held in an <li> element of the + + * auto complete container. + + * + + * @return {object or array} Object or array of result data or null + + */ + +YAHOO.widget.AutoComplete.prototype.getListItemData = function(oListItem) { + + if(oListItem._oResultData) { + + return oListItem._oResultData; + + } + + else { + + return false; + + } + +}; + + + +/** + + * Sets HTML markup for the auto complete container header. This markup will be + + * inserted within a <div> tag with a class of "ac_hd". + + * + + * @param {string} sHeader HTML markup for container header + + */ + +YAHOO.widget.AutoComplete.prototype.setHeader = function(sHeader) { + + if(sHeader) { + + if(this._oContainer._oContent._oHeader) { + + this._oContainer._oContent._oHeader.innerHTML = sHeader; + + this._oContainer._oContent._oHeader.style.display = "block"; + + } + + } + + else { + + this._oContainer._oContent._oHeader.innerHTML = ""; + + this._oContainer._oContent._oHeader.style.display = "none"; + + } + +}; + + + +/** + + * Sets HTML markup for the auto complete container footer. This markup will be + + * inserted within a <div> tag with a class of "ac_ft". + + * + + * @param {string} sFooter HTML markup for container footer + + */ + +YAHOO.widget.AutoComplete.prototype.setFooter = function(sFooter) { + + if(sFooter) { + + if(this._oContainer._oContent._oFooter) { + + this._oContainer._oContent._oFooter.innerHTML = sFooter; + + this._oContainer._oContent._oFooter.style.display = "block"; + + } + + } + + else { + + this._oContainer._oContent._oFooter.innerHTML = ""; + + this._oContainer._oContent._oFooter.style.display = "none"; + + } + +}; + + + +/** + + * Sets HTML markup for the auto complete container body. This markup will be + + * inserted within a <div> tag with a class of "ac_bd". + + * + + * @param {string} sHeader HTML markup for container body + + */ + +YAHOO.widget.AutoComplete.prototype.setBody = function(sBody) { + + if(sBody) { + + if(this._oContainer._oContent._oBody) { + + this._oContainer._oContent._oBody.innerHTML = sBody; + + this._oContainer._oContent._oBody.style.display = "block"; + + this._oContainer._oContent.style.display = "block"; + + } + + } + + else { + + this._oContainer._oContent._oBody.innerHTML = ""; + + this._oContainer._oContent.style.display = "none"; + + } + + this._maxResultsDisplayed = 0; + +}; + + + +/** + + * Overridable method that converts a result item object into HTML markup + + * for display. Return data values are accessible via the oResultItem object, + + * and the key return value will always be oResultItem[0]. Markup will be + + * displayed within <li> element tags in the container. + + * + + * @param {object} oResultItem Result item object representing one query result + + * @param {string} sQuery The current query string + + * @return {string} HTML markup of formatted result data + + */ + +YAHOO.widget.AutoComplete.prototype.formatResult = function(oResultItem, sQuery) { + + var sResult = oResultItem[0]; + + if(sResult) { + + return sResult; + + } + + else { + + return ""; + + } + +}; + + + +/** + + * Makes query request to the data source. + + * + + * @param {string} sQuery Query string. + + */ + +YAHOO.widget.AutoComplete.prototype.sendQuery = function(sQuery) { + + if(sQuery) { + + this._sendQuery(sQuery); + + } + + else { + + YAHOO.log("Query could not be sent because the string value was empty or null.","warn",this.toString()); + + return; + + } + +}; + + + +/*************************************************************************** + + * Events + + ***************************************************************************/ + +/** + + * Fired when the auto complete text input box receives focus. Subscribers + + * receive the following array:
    + + * - args[0] The auto complete object instance + + */ + +YAHOO.widget.AutoComplete.prototype.textboxFocusEvent = null; + + + +/** + + * Fired when the auto complete text input box receives key input. Subscribers + + * receive the following array:
    + + * - args[0] The auto complete object instance + + * - args[1] The keycode number + + */ + +YAHOO.widget.AutoComplete.prototype.textboxKeyEvent = null; + + + +/** + + * Fired when the auto complete instance makes a query to the data source. + + * Subscribers receive the following array:
    + + * - args[0] The auto complete object instance + + * - args[1] The query string + + */ + +YAHOO.widget.AutoComplete.prototype.dataRequestEvent = null; + + + +/** + + * Fired when the auto complete instance receives query results from the data + + * source. Subscribers receive the following array:
    + + * - args[0] The auto complete object instance + + * - args[1] The query string + + * - args[2] Results array + + */ + +YAHOO.widget.AutoComplete.prototype.dataReturnEvent = null; + + + +/** + + * Fired when the auto complete instance does not receive query results from the + + * data source due to an error. Subscribers receive the following array:
    + + * - args[0] The auto complete object instance + + * - args[1] The query string + + */ + +YAHOO.widget.AutoComplete.prototype.dataErrorEvent = null; + + + +/** + + * Fired when the auto complete container is expanded. If alwaysShowContainer is + + * enabled, then containerExpandEvent will be fired when the container is + + * populated with results. Subscribers receive the following array:
    + + * - args[0] The auto complete object instance + + */ + +YAHOO.widget.AutoComplete.prototype.containerExpandEvent = null; + + + +/** + + * Fired when the auto complete textbox has been prefilled by the type-ahead + + * feature. Subscribers receive the following array:
    + + * - args[0] The auto complete object instance + + * - args[1] The query string + + * - args[2] The prefill string + + */ + +YAHOO.widget.AutoComplete.prototype.typeAheadEvent = null; + + + +/** + + * Fired when result item has been moused over. Subscribers receive the following + + * array:
    + + * - args[0] The auto complete object instance + + * - args[1] The <li> element item moused to + + */ + +YAHOO.widget.AutoComplete.prototype.itemMouseOverEvent = null; + + + +/** + + * Fired when result item has been moused out. Subscribers receive the + + * following array:
    + + * - args[0] The auto complete object instance + + * - args[1] The <li> element item moused from + + */ + +YAHOO.widget.AutoComplete.prototype.itemMouseOutEvent = null; + + + +/** + + * Fired when result item has been arrowed to. Subscribers receive the following + + * array:
    + + * - args[0] The auto complete object instance + + * - args[1] The <li> element item arrowed to + + */ + +YAHOO.widget.AutoComplete.prototype.itemArrowToEvent = null; + + + +/** + + * Fired when result item has been arrowed away from. Subscribers receive the + + * following array:
    + + * - args[0] The auto complete object instance + + * - args[1] The <li> element item arrowed from + + */ + +YAHOO.widget.AutoComplete.prototype.itemArrowFromEvent = null; + + + +/** + + * Fired when an item is selected via mouse click, ENTER key, or TAB key. + + * Subscribers receive the following array:
    + + * - args[0] The auto complete object instance + + * - args[1] The selected <li> element item + + * - args[2] The data returned for the item, either as an object, or mapped from the schema into an array + + */ + +YAHOO.widget.AutoComplete.prototype.itemSelectEvent = null; + + + +/** + + * Fired when an user selection does not match any of the displayed result items. + + * Note that this event may not behave as expected when delimiter characters + + * have been defined. Subscribers receive the following array:
    + + * - args[0] The auto complete object instance + + * - args[1] The user selection + + */ + +YAHOO.widget.AutoComplete.prototype.unmatchedItemSelectEvent = null; + + + +/** + + * Fired if forceSelection is enabled and the user's input has been cleared + + * because it did not match one of the returned query results. Subscribers + + * receive the following array:
    + + * - args[0] The auto complete object instance + + */ + +YAHOO.widget.AutoComplete.prototype.selectionEnforceEvent = null; + + + +/** + + * Fired when the auto complete container is collapsed. If alwaysShowContainer is + + * enabled, then containerCollapseEvent will be fired when the container is + + * cleared of results. Subscribers receive the following array:
    + + * - args[0] The auto complete object instance + + */ + +YAHOO.widget.AutoComplete.prototype.containerCollapseEvent = null; + + + +/** + + * Fired when the auto complete text input box loses focus. Subscribers receive + + * an array of the following array:
    + + * - args[0] The auto complete object instance + + */ + +YAHOO.widget.AutoComplete.prototype.textboxBlurEvent = null; + + + +/*************************************************************************** + + * Private member variables + + ***************************************************************************/ + +/** + + * Internal class variable to index multiple auto complete instances. + + * + + * @type number + + * @private + + */ + +YAHOO.widget.AutoComplete._nIndex = 0; + + + +/** + + * Name of auto complete instance. + + * + + * @type string + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._sName = null; + + + +/** + + * Text input box DOM element. + + * + + * @type object + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._oTextbox = null; + + + +/** + + * Whether or not the textbox is currently in focus. If query results come back + + * but the user has already moved on, do not proceed with auto complete behavior. + + * + + * @type boolean + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._bFocused = true; + + + +/** + + * Animation instance for container expand/collapse. + + * + + * @type boolean + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._oAnim = null; + + + +/** + + * Container DOM element. + + * + + * @type object + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._oContainer = null; + + + +/** + + * Whether or not the auto complete container is currently open. + + * + + * @type boolean + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._bContainerOpen = false; + + + +/** + + * Whether or not the mouse is currently over the auto complete + + * container. This is necessary in order to prevent clicks on container items + + * from being text input box blur events. + + * + + * @type boolean + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._bOverContainer = false; + + + +/** + + * Array of <li> elements references that contain query results within the + + * auto complete container. + + * + + * @type array + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._aListItems = null; + + + +/** + + * Number of <li> elements currently displayed in auto complete container. + + * + + * @type number + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._nDisplayedItems = 0; + + + +/** + + * Internal count of <li> elements displayed and hidden in auto complete container. + + * + + * @type number + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._maxResultsDisplayed = 0; + + + +/** + + * Current query string + + * + + * @type string + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._sCurQuery = null; + + + +/** + + * Past queries this session (for saving delimited queries). + + * + + * @type string + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._sSavedQuery = null; + + + +/** + + * Pointer to the currently highlighted <li> element in the container. + + * + + * @type object + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._oCurItem = null; + + + +/** + + * Whether or not an item has been selected since the container was populated + + * with results. Reset to false by _populateList, and set to true when item is + + * selected. + + * + + * @type boolean + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._bItemSelected = false; + + + +/** + + * Key code of the last key pressed in textbox. + + * + + * @type number + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._nKeyCode = null; + + + +/** + + * Delay timeout ID. + + * + + * @type number + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._nDelayID = -1; + + + +/*************************************************************************** + + * Private methods + + ***************************************************************************/ + +/** + + * Updates and validates latest public config properties. + + * + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._initProps = function() { + + // Correct any invalid values + + var minQueryLength = this.minQueryLength; + + if(isNaN(minQueryLength) || (minQueryLength < 1)) { + + minQueryLength = 1; + + } + + var maxResultsDisplayed = this.maxResultsDisplayed; + + if(isNaN(this.maxResultsDisplayed) || (this.maxResultsDisplayed < 1)) { + + this.maxResultsDisplayed = 10; + + } + + var queryDelay = this.queryDelay; + + if(isNaN(this.queryDelay) || (this.queryDelay < 0)) { + + this.queryDelay = 0.5; + + } + + var aDelimChar = (this.delimChar) ? this.delimChar : null; + + if(aDelimChar) { + + if(typeof aDelimChar == "string") { + + this.delimChar = [aDelimChar]; + + } + + else if(aDelimChar.constructor != Array) { + + this.delimChar = null; + + } + + } + + var animSpeed = this.animSpeed; + + if((this.animHoriz || this.animVert) && YAHOO.util.Anim) { + + if(isNaN(animSpeed) || (animSpeed < 0)) { + + animSpeed = 0.3; + + } + + if(!this._oAnim ) { + + oAnim = new YAHOO.util.Anim(this._oContainer._oContent, {}, this.animSpeed); + + this._oAnim = oAnim; + + } + + else { + + this._oAnim.duration = animSpeed; + + } + + } + + if(this.forceSelection && this.delimChar) { + + YAHOO.log("The forceSelection feature has been enabled with delimChar defined.","warn", this.toString()); + + } + + if(this.alwaysShowContainer && (this.useShadow || this.useIFrame)) { + + YAHOO.log("The features useShadow and useIFrame are not compatible with the alwaysShowContainer feature.","warn", this.toString()); + + } + + + + if(this.alwaysShowContainer) { + + this._bContainerOpen = true; + + } + +}; + + + +/** + + * Initializes the auto complete container helpers if they are enabled and do + + * not exist + + * + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._initContainerHelpers = function() { + + if(this.useShadow && !this._oContainer._oShadow) { + + var oShadow = document.createElement("div"); + + oShadow.className = "yui-ac-shadow"; + + this._oContainer._oShadow = this._oContainer.appendChild(oShadow); + + } + + if(this.useIFrame && !this._oContainer._oIFrame) { + + var oIFrame = document.createElement("iframe"); + + oIFrame.src = this.iFrameSrc; + + oIFrame.frameBorder = 0; + + oIFrame.scrolling = "no"; + + oIFrame.style.position = "absolute"; + + oIFrame.style.width = "100%"; + + oIFrame.style.height = "100%"; + + this._oContainer._oIFrame = this._oContainer.appendChild(oIFrame); + + } + +}; + + + +/** + + * Initializes the auto complete container once at object creation + + * + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._initContainer = function() { + + if(!this._oContainer._oContent) { + + // The oContent div helps size the iframe and shadow properly + + var oContent = document.createElement("div"); + + oContent.className = "yui-ac-content"; + + oContent.style.display = "none"; + + this._oContainer._oContent = this._oContainer.appendChild(oContent); + + + + var oHeader = document.createElement("div"); + + oHeader.className = "yui-ac-hd"; + + oHeader.style.display = "none"; + + this._oContainer._oContent._oHeader = this._oContainer._oContent.appendChild(oHeader); + + + + var oBody = document.createElement("div"); + + oBody.className = "yui-ac-bd"; + + this._oContainer._oContent._oBody = this._oContainer._oContent.appendChild(oBody); + + + + var oFooter = document.createElement("div"); + + oFooter.className = "yui-ac-ft"; + + oFooter.style.display = "none"; + + this._oContainer._oContent._oFooter = this._oContainer._oContent.appendChild(oFooter); + + } + + else { + + YAHOO.log("Could not initialize the container","warn",this.toString()); + + } + +}; + + + +/** + + * Clears out contents of container body and creates up to + + * YAHOO.widget.AutoComplete#maxResultsDisplayed <li> elements in an + + * <ul> element. + + * + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._initList = function() { + + this._aListItems = []; + + while(this._oContainer._oContent._oBody.hasChildNodes()) { + + var oldListItems = this.getListItems(); + + if(oldListItems) { + + for(var oldi = oldListItems.length-1; oldi >= 0; i--) { + + oldListItems[oldi] = null; + + } + + } + + this._oContainer._oContent._oBody.innerHTML = ""; + + } + + + + var oList = document.createElement("ul"); + + oList = this._oContainer._oContent._oBody.appendChild(oList); + + for(var i=0; i 0) { + + var nDelayID = + + setTimeout(function(){oSelf._sendQuery(sText);},(oSelf.queryDelay * 1000)); + + + + if (oSelf._nDelayID != -1) { + + clearTimeout(oSelf._nDelayID); + + } + + + + oSelf._nDelayID = nDelayID; + + } + + else { + + // No delay so send request immediately + + oSelf._sendQuery(sText); + + } + +}; + + + +/** + + * Whether or not key is functional or should be ignored. Note that the right + + * arrow key is NOT an ignored key since it triggers queries for certain intl + + * charsets. + + * + + * @param {number} nKeycode Code of key pressed + + * @return {boolean} Whether or not to be ignore key + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._isIgnoreKey = function(nKeyCode) { + + if ((nKeyCode == 9) || (nKeyCode == 13) || // tab, enter + + (nKeyCode == 16) || (nKeyCode == 17) || // shift, ctl + + (nKeyCode >= 18 && nKeyCode <= 20) || // alt,pause/break,caps lock + + (nKeyCode == 27) || // esc + + (nKeyCode >= 33 && nKeyCode <= 35) || // page up,page down,end + + (nKeyCode >= 36 && nKeyCode <= 38) || // home,left,up + + (nKeyCode == 40) || // down + + (nKeyCode >= 44 && nKeyCode <= 45)) { // print screen,insert + + return true; + + } + + return false; + +}; + + + +/** + + * Handles text input box receiving focus. + + * + + * @param {event} v The focus event + + * @param {object} oSelf The auto complete instance + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._onTextboxFocus = function (v,oSelf) { + + oSelf._oTextbox.setAttribute("autocomplete","off"); + + oSelf._bFocused = true; + + oSelf.textboxFocusEvent.fire(oSelf); + +}; + + + +/** + + * Handles text input box losing focus. + + * + + * @param {event} v The focus event + + * @param {object} oSelf The auto complete instance + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._onTextboxBlur = function (v,oSelf) { + + // Don't treat as a blur if it was a selection via mouse click + + if(!oSelf._bOverContainer || (oSelf._nKeyCode == 9)) { + + // Current query needs to be validated + + if(!oSelf._bItemSelected) { + + if(!oSelf._bContainerOpen || (oSelf._bContainerOpen && !oSelf._textMatchesOption())) { + + if(oSelf.forceSelection) { + + oSelf._clearSelection(); + + } + + else { + + oSelf.unmatchedItemSelectEvent.fire(oSelf, oSelf._sCurQuery); + + } + + } + + } + + + + if(oSelf._bContainerOpen) { + + oSelf._clearList(); + + } + + oSelf._bFocused = false; + + oSelf.textboxBlurEvent.fire(oSelf); + + } + +}; + + + +/** + + * Handles form submission event. + + * + + * @param {event} v The submit event + + * @param {object} oSelf The auto complete instance + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._onFormSubmit = function(v,oSelf) { + + if(oSelf.allowBrowserAutocomplete) { + + oSelf._oTextbox.setAttribute("autocomplete","on"); + + } + + else { + + oSelf._oTextbox.setAttribute("autocomplete","off"); + + } + +}; + + + +/** + + * Makes query request to the data source. + + * + + * @param {string} sQuery Query string. + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._sendQuery = function(sQuery) { + + // Delimiter has been enabled + + var aDelimChar = (this.delimChar) ? this.delimChar : null; + + if(aDelimChar) { + + // Loop through all possible delimiters and find the latest one + + // A " " may be a false positive if they are defined as delimiters AND + + // are used to separate delimited queries + + var nDelimIndex = -1; + + for(var i = aDelimChar.length-1; i >= 0; i--) { + + var nNewIndex = sQuery.lastIndexOf(aDelimChar[i]); + + if(nNewIndex > nDelimIndex) { + + nDelimIndex = nNewIndex; + + } + + } + + // If we think the last delimiter is a space (" "), make sure it is NOT + + // a false positive by also checking the char directly before it + + if(aDelimChar[i] == " ") { + + for (var j = aDelimChar.length-1; j >= 0; j--) { + + if(sQuery[nDelimIndex - 1] == aDelimChar[j]) { + + nDelimIndex--; + + break; + + } + + } + + } + + // A delimiter has been found so extract the latest query + + if (nDelimIndex > -1) { + + var nQueryStart = nDelimIndex + 1; + + // Trim any white space from the beginning... + + while(sQuery.charAt(nQueryStart) == " ") { + + nQueryStart += 1; + + } + + // ...and save the rest of the string for later + + this._sSavedQuery = sQuery.substring(0,nQueryStart); + + // Here is the query itself + + sQuery = sQuery.substr(nQueryStart); + + } + + else if(sQuery.indexOf(this._sSavedQuery) < 0){ + + this._sSavedQuery = null; + + } + + } + + + + // Don't search queries that are too short + + if (sQuery.length < this.minQueryLength) { + + if (this._nDelayID != -1) { + + clearTimeout(this._nDelayID); + + } + + this._clearList(); + + return; + + } + + + + sQuery = encodeURIComponent(sQuery); + + this._nDelayID = -1; // Reset timeout ID because request has been made + + this.dataRequestEvent.fire(this, sQuery); + + this.dataSource.getResults(this._populateList, sQuery, this); + +}; + + + +/** + + * Hides all visuals related to the array of <li> elements in the container. + + * + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._clearList = function() { + + this._oContainer._oContent.scrollTop = 0; + + var aItems = this._aListItems; + + + + if(aItems && (aItems.length > 0)) { + + for(var i = aItems.length-1; i >= 0 ; i--) { + + aItems[i].style.display = "none"; + + } + + } + + + + if (this._oCurItem) { + + this._toggleHighlight(this._oCurItem,"from"); + + } + + + + this._oCurItem = null; + + this._nDisplayedItems = 0; + + this._sCurQuery = null; + + this._toggleContainer(false); + +}; + + + +/** + + * Populates the array of <li> elements in the container with query + + * results. This method is passed to YAHOO.widget.DataSource#getResults as a + + * callback function so results from the datasource are returned to the + + * auto complete instance. + + * + + * @param {string} sQuery The query string + + * @param {object} aResults An array of query result objects from the data source + + * @param {string} oSelf The auto complete instance + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._populateList = function(sQuery, aResults, oSelf) { + + if(aResults === null) { + + oSelf.dataErrorEvent.fire(oSelf, sQuery); + + } + + if (!oSelf._bFocused || !aResults) { + + return; + + } + + + + var isOpera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1); + + var contentStyle = oSelf._oContainer._oContent.style; + + contentStyle.width = (!isOpera) ? null : ""; + + contentStyle.height = (!isOpera) ? null : ""; + + + + var sCurQuery = decodeURIComponent(sQuery); + + oSelf._sCurQuery = sCurQuery; + + oSelf._bItemSelected = false; + + + + if(oSelf._maxResultsDisplayed != oSelf.maxResultsDisplayed) { + + oSelf._initList(); + + } + + + + var nItems = Math.min(aResults.length,oSelf.maxResultsDisplayed); + + oSelf._nDisplayedItems = nItems; + + if (nItems > 0) { + + oSelf._initContainerHelpers(); + + var aItems = oSelf._aListItems; + + + + // Fill items with data + + for(var i = nItems-1; i >= 0; i--) { + + var oItemi = aItems[i]; + + var oResultItemi = aResults[i]; + + oItemi.innerHTML = oSelf.formatResult(oResultItemi, sCurQuery); + + oItemi.style.display = "list-item"; + + oItemi._sResultKey = oResultItemi[0]; + + oItemi._oResultData = oResultItemi; + + + + } + + + + // Empty out remaining items if any + + for(var j = aItems.length-1; j >= nItems ; j--) { + + var oItemj = aItems[j]; + + oItemj.innerHTML = null; + + oItemj.style.display = "none"; + + oItemj._sResultKey = null; + + oItemj._oResultData = null; + + } + + + + if(oSelf.autoHighlight) { + + // Go to the first item + + var oFirstItem = aItems[0]; + + oSelf._toggleHighlight(oFirstItem,"to"); + + oSelf.itemArrowToEvent.fire(oSelf, oFirstItem); + + oSelf._typeAhead(oFirstItem,sQuery); + + } + + else { + + oSelf._oCurItem = null; + + } + + + + // Expand the container + + oSelf._toggleContainer(true); + + } + + else { + + oSelf._clearList(); + + } + + oSelf.dataReturnEvent.fire(oSelf, sQuery, aResults); + +}; + + + +/** + + * When YAHOO.widget.AutoComplete#bForceSelection is true and the user attempts + + * leave the text input box without selecting an item from the query results, + + * the user selection is cleared. + + * + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._clearSelection = function() { + + var sValue = this._oTextbox.value; + + var sChar = (this.delimChar) ? this.delimChar[0] : null; + + var nIndex = (sChar) ? sValue.lastIndexOf(sChar, sValue.length-2) : -1; + + if(nIndex > -1) { + + this._oTextbox.value = sValue.substring(0,nIndex); + + } + + else { + + this._oTextbox.value = ""; + + } + + this._sSavedQuery = this._oTextbox.value; + + + + // Fire custom event + + this.selectionEnforceEvent.fire(this); + +}; + + + +/** + + * Whether or not user-typed value in the text input box matches any of the + + * query results. + + * + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._textMatchesOption = function() { + + var foundMatch = false; + + + + for(var i = this._nDisplayedItems-1; i >= 0 ; i--) { + + var oItem = this._aListItems[i]; + + var sMatch = oItem._sResultKey.toLowerCase(); + + if (sMatch == this._sCurQuery.toLowerCase()) { + + foundMatch = true; + + break; + + } + + } + + return(foundMatch); + +}; + + + +/** + + * Updates in the text input box with the first query result as the user types, + + * selecting the substring that the user has not typed. + + * + + * @param {object} oItem The <li> element item whose data populates the input field + + * @param {string} sQuery Query string + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._typeAhead = function(oItem, sQuery) { + + // Don't update if turned off + + if (!this.typeAhead) { + + return; + + } + + + + var oTextbox = this._oTextbox; + + var sValue = this._oTextbox.value; // any saved queries plus what user has typed + + + + // Don't update with type-ahead if text selection is not supported + + if(!oTextbox.setSelectionRange && !oTextbox.createTextRange) { + + return; + + } + + + + // Select the portion of text that the user has not typed + + var nStart = sValue.length; + + this._updateValue(oItem); + + var nEnd = oTextbox.value.length; + + this._selectText(oTextbox,nStart,nEnd); + + var sPrefill = oTextbox.value.substr(nStart,nEnd); + + this.typeAheadEvent.fire(this,sQuery,sPrefill); + +}; + + + +/** + + * Selects text in a text input box. + + * + + * @param {object} oTextbox Text input box element in which to select text + + * @param {number} nStart Starting index of text string to select + + * @param {number} nEnd Ending index of text selection + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._selectText = function(oTextbox, nStart, nEnd) { + + if (oTextbox.setSelectionRange) { // For Mozilla + + oTextbox.setSelectionRange(nStart,nEnd); + + } + + else if (oTextbox.createTextRange) { // For IE + + var oTextRange = oTextbox.createTextRange(); + + oTextRange.moveStart("character", nStart); + + oTextRange.moveEnd("character", nEnd-oTextbox.value.length); + + oTextRange.select(); + + } + + else { + + oTextbox.select(); + + } + +}; + + + +/** + + * Syncs auto complete container with its helpers. + + * + + * @param {boolean} bShow True if container is expanded, false if collapsed + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._toggleContainerHelpers = function(bShow) { + + var bFireEvent = false; + + var width = this._oContainer._oContent.offsetWidth + "px"; + + var height = this._oContainer._oContent.offsetHeight + "px"; + + + + if(this.useIFrame && this._oContainer._oIFrame) { + + bFireEvent = true; + + if(this.alwaysShowContainer || bShow) { + + this._oContainer._oIFrame.style.width = width; + + this._oContainer._oIFrame.style.height = height; + + } + + else { + + this._oContainer._oIFrame.style.width = 0; + + this._oContainer._oIFrame.style.height = 0; + + } + + } + + if(this.useShadow && this._oContainer._oShadow) { + + bFireEvent = true; + + if(this.alwaysShowContainer || bShow) { + + this._oContainer._oShadow.style.width = width; + + this._oContainer._oShadow.style.height = height; + + } + + else { + + this._oContainer._oShadow.style.width = 0; + + this._oContainer._oShadow.style.height = 0; + + } + + } + +}; + + + +/** + + * Animates expansion or collapse of the container. + + * + + * @param {boolean} bShow True if container should be expanded, false if + + * container should be collapsed + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._toggleContainer = function(bShow) { + + // Implementer has container always open so don't mess with it + + if(this.alwaysShowContainer) { + + // Fire these events to give implementers a hook into the container + + // being populated and being emptied + + if(bShow) { + + this.containerExpandEvent.fire(this); + + } + + else { + + this.containerCollapseEvent.fire(this); + + } + + this._bContainerOpen = bShow; + + return; + + } + + + + var oContainer = this._oContainer; + + // Container is already closed + + if (!bShow && !this._bContainerOpen) { + + oContainer._oContent.style.display = "none"; + + return; + + } + + + + // If animation is enabled... + + var oAnim = this._oAnim; + + if (oAnim && oAnim.getEl() && (this.animHoriz || this.animVert)) { + + // If helpers need to be collapsed, do it right away... + + // but if helpers need to be expanded, wait until after the container expands + + if(!bShow) { + + this._toggleContainerHelpers(bShow); + + } + + + + if(oAnim.isAnimated()) { + + oAnim.stop(); + + } + + + + // Clone container to grab current size offscreen + + var oClone = oContainer._oContent.cloneNode(true); + + oContainer.appendChild(oClone); + + oClone.style.top = "-9000px"; + + oClone.style.display = "block"; + + + + // Current size of the container is the EXPANDED size + + var wExp = oClone.offsetWidth; + + var hExp = oClone.offsetHeight; + + + + // Calculate COLLAPSED sizes based on horiz and vert anim + + var wColl = (this.animHoriz) ? 0 : wExp; + + var hColl = (this.animVert) ? 0 : hExp; + + + + // Set animation sizes + + oAnim.attributes = (bShow) ? + + {width: { to: wExp }, height: { to: hExp }} : + + {width: { to: wColl}, height: { to: hColl }}; + + + + // If opening anew, set to a collapsed size... + + if(bShow && !this._bContainerOpen) { + + oContainer._oContent.style.width = wColl+"px"; + + oContainer._oContent.style.height = hColl+"px"; + + } + + // Else, set it to its last known size. + + else { + + oContainer._oContent.style.width = wExp+"px"; + + oContainer._oContent.style.height = hExp+"px"; + + } + + + + oContainer.removeChild(oClone); + + oClone = null; + + + + var oSelf = this; + + var onAnimComplete = function() { + + // Finish the collapse + + oAnim.onComplete.unsubscribeAll(); + + + + if(bShow) { + + oSelf.containerExpandEvent.fire(oSelf); + + } + + else { + + oContainer._oContent.style.display = "none"; + + oSelf.containerCollapseEvent.fire(oSelf); + + } + + oSelf._toggleContainerHelpers(bShow); + + }; + + + + // Display container and animate it + + oContainer._oContent.style.display = "block"; + + oAnim.onComplete.subscribe(onAnimComplete); + + oAnim.animate(); + + this._bContainerOpen = bShow; + + } + + // Else don't animate, just show or hide + + else { + + if(bShow) { + + oContainer._oContent.style.display = "block"; + + this.containerExpandEvent.fire(this); + + } + + else { + + oContainer._oContent.style.display = "none"; + + this.containerCollapseEvent.fire(this); + + } + + this._toggleContainerHelpers(bShow); + + this._bContainerOpen = bShow; + + } + + + +}; + + + +/** + + * Toggles the highlight on or off for an item in the container, and also cleans + + * up highlighting of any previous item. + + * + + * @param {object} oNewItem New The <li> element item to receive highlight + + * behavior + + * @param {string} sType "mouseover" will toggle highlight on, and "mouseout" + + * will toggle highlight off. + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._toggleHighlight = function(oNewItem, sType) { + + var sHighlight = this.highlightClassName; + + if(this._oCurItem) { + + // Remove highlight from old item + + YAHOO.util.Dom.removeClass(this._oCurItem, sHighlight); + + } + + + + if((sType == "to") && sHighlight) { + + // Apply highlight to new item + + YAHOO.util.Dom.addClass(oNewItem, sHighlight); + + this._oCurItem = oNewItem; + + } + +}; + + + +/** + + * Toggles the pre-highlight on or off for an item in the container. + + * + + * @param {object} oNewItem New The <li> element item to receive highlight + + * behavior + + * @param {string} sType "mouseover" will toggle highlight on, and "mouseout" + + * will toggle highlight off. + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._togglePrehighlight = function(oNewItem, sType) { + + if(oNewItem == this._oCurItem) { + + return; + + } + + + + var sPrehighlight = this.prehighlightClassName; + + if((sType == "mouseover") && sPrehighlight) { + + // Apply prehighlight to new item + + YAHOO.util.Dom.addClass(oNewItem, sPrehighlight); + + } + + else { + + // Remove prehighlight from old item + + YAHOO.util.Dom.removeClass(oNewItem, sPrehighlight); + + } + +}; + + + +/** + + * Updates the text input box value with selected query result. If a delimiter + + * has been defined, then the value gets appended with the delimiter. + + * + + * @param {object} oItem The <li> element item with which to update the value + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._updateValue = function(oItem) { + + var oTextbox = this._oTextbox; + + var sDelimChar = (this.delimChar) ? this.delimChar[0] : null; + + var sSavedQuery = this._sSavedQuery; + + var sResultKey = oItem._sResultKey; + + oTextbox.focus(); + + + + // First clear text field + + oTextbox.value = ""; + + // Grab data to put into text field + + if(sDelimChar) { + + if(sSavedQuery) { + + oTextbox.value = sSavedQuery; + + } + + oTextbox.value += sResultKey + sDelimChar; + + if(sDelimChar != " ") { + + oTextbox.value += " "; + + } + + } + + else { oTextbox.value = sResultKey; } + + + + // scroll to bottom of textarea if necessary + + if(oTextbox.type == "textarea") { + + oTextbox.scrollTop = oTextbox.scrollHeight; + + } + + + + // move cursor to end + + var end = oTextbox.value.length; + + this._selectText(oTextbox,end,end); + + + + this._oCurItem = oItem; + +}; + + + +/** + + * Selects a result item from the container + + * + + * @param {object} oItem The selected <li> element item + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._selectItem = function(oItem) { + + this._bItemSelected = true; + + this._updateValue(oItem); + + this.itemSelectEvent.fire(this, oItem, oItem._oResultData); + + this._clearList(); + +}; + + + +/** + + * For values updated by type-ahead, the right arrow key jumps to the end + + * of the textbox, otherwise the container is closed. + + * + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._jumpSelection = function() { + + if(!this.typeAhead) { + + return; + + } + + else { + + this._clearList(); + + } + +}; + + + +/** + + * Triggered by up and down arrow keys, changes the current highlighted + + * <li> element item. Scrolls container if necessary. + + * + + * @param {number} nKeyCode Code of key pressed + + * @private + + */ + +YAHOO.widget.AutoComplete.prototype._moveSelection = function(nKeyCode) { + + if(this._bContainerOpen) { + + // Determine current item's id number + + var oCurItem = this._oCurItem; + + var nCurItemIndex = -1; + + + + if (oCurItem) { + + nCurItemIndex = oCurItem._nItemIndex; + + } + + + + var nNewItemIndex = (nKeyCode == 40) ? + + (nCurItemIndex + 1) : (nCurItemIndex - 1); + + + + // Out of bounds + + if (nNewItemIndex < -2 || nNewItemIndex >= this._nDisplayedItems) { + + return; + + } + + + + if (oCurItem) { + + // Unhighlight current item + + this._toggleHighlight(oCurItem, "from"); + + this.itemArrowFromEvent.fire(this, oCurItem); + + } + + if (nNewItemIndex == -1) { + + // Go back to query (remove type-ahead string) + + if(this.delimChar && this._sSavedQuery) { + + if (!this._textMatchesOption()) { + + this._oTextbox.value = this._sSavedQuery; + + } + + else { + + this._oTextbox.value = this._sSavedQuery + this._sCurQuery; + + } + + } + + else { + + this._oTextbox.value = this._sCurQuery; + + } + + this._oCurItem = null; + + return; + + } + + if (nNewItemIndex == -2) { + + // Close container + + this._clearList(); + + return; + + } + + + + var oNewItem = this._aListItems[nNewItemIndex]; + + + + // Scroll the container if necessary + + if((YAHOO.util.Dom.getStyle(this._oContainer._oContent,"overflow") == "auto") && + + (nNewItemIndex > -1) && (nNewItemIndex < this._nDisplayedItems)) { + + // User is keying down + + if(nKeyCode == 40) { + + // Bottom of selected item is below scroll area... + + if((oNewItem.offsetTop+oNewItem.offsetHeight) > (this._oContainer._oContent.scrollTop + this._oContainer._oContent.offsetHeight)) { + + // Set bottom of scroll area to bottom of selected item + + this._oContainer._oContent.scrollTop = (oNewItem.offsetTop+oNewItem.offsetHeight) - this._oContainer._oContent.offsetHeight; + + } + + // Bottom of selected item is above scroll area... + + else if((oNewItem.offsetTop+oNewItem.offsetHeight) < this._oContainer._oContent.scrollTop) { + + // Set top of selected item to top of scroll area + + this._oContainer._oContent.scrollTop = oNewItem.offsetTop; + + + + } + + } + + // User is keying up + + else { + + // Top of selected item is above scroll area + + if(oNewItem.offsetTop < this._oContainer._oContent.scrollTop) { + + // Set top of scroll area to top of selected item + + this._oContainer._oContent.scrollTop = oNewItem.offsetTop; + + } + + // Top of selected item is below scroll area + + else if(oNewItem.offsetTop > (this._oContainer._oContent.scrollTop + this._oContainer._oContent.offsetHeight)) { + + // Set bottom of selected item to bottom of scroll area + + this._oContainer._oContent.scrollTop = (oNewItem.offsetTop+oNewItem.offsetHeight) - this._oContainer._oContent.offsetHeight; + + } + + } + + } + + + + this._toggleHighlight(oNewItem, "to"); + + this.itemArrowToEvent.fire(this, oNewItem); + + if(this.typeAhead) { + + this._updateValue(oNewItem); + + } + + } + +}; + + + +/****************************************************************************/ + +/****************************************************************************/ + +/****************************************************************************/ + + + +/** + + * Class providing encapsulation of a data source. + + * + + * @constructor + + * + + */ + +YAHOO.widget.DataSource = function() { + + /* abstract class */ + +}; + + + + + +/*************************************************************************** + + * Public constants + + ***************************************************************************/ + +/** + + * Error message for null data responses. + + * + + * @type constant + + * @final + + */ + +YAHOO.widget.DataSource.prototype.ERROR_DATANULL = "Response data was null"; + + + +/** + + * Error message for data responses with parsing errors. + + * + + * @type constant + + * @final + + */ + +YAHOO.widget.DataSource.prototype.ERROR_DATAPARSE = "Response data could not be parsed"; + + + + + +/*************************************************************************** + + * Public member variables + + ***************************************************************************/ + +/** + + * Max size of the local cache. Set to 0 to turn off caching. Caching is + + * useful to reduce the number of server connections. Recommended only for data + + * sources that return comprehensive results for queries or when stale data is + + * not an issue. Default: 15. + + * + + * @type number + + */ + +YAHOO.widget.DataSource.prototype.maxCacheEntries = 15; + + + +/** + + * Use this to equate cache matching with the type of matching done by your live + + * data source. If caching is on and queryMatchContains is true, the cache + + * returns results that "contain" the query string. By default, + + * queryMatchContains is set to false, meaning the cache only returns results + + * that "start with" the query string. Default: false. + + * + + * @type boolean + + */ + +YAHOO.widget.DataSource.prototype.queryMatchContains = false; + + + +/** + + * Data source query subset matching. If caching is on and queryMatchSubset is + + * true, substrings of queries will return matching cached results. For + + * instance, if the first query is for "abc" susequent queries that start with + + * "abc", like "abcd", will be queried against the cache, and not the live data + + * source. Recommended only for data sources that return comprehensive results + + * for queries with very few characters. Default: false. + + * + + * @type boolean + + */ + +YAHOO.widget.DataSource.prototype.queryMatchSubset = false; + + + +/** + + * Data source query case-sensitivity matching. If caching is on and + + * queryMatchCase is true, queries will only return results for case-sensitive + + * matches. Default: false. + + * + + * @type boolean + + */ + +YAHOO.widget.DataSource.prototype.queryMatchCase = false; + + + + + +/*************************************************************************** + + * Public methods + + ***************************************************************************/ + + /** + + * Public accessor to the unique name of the data source instance. + + * + + * @return {string} Unique name of the data source instance + + */ + +YAHOO.widget.DataSource.prototype.getName = function() { + + return this._sName; + +}; + + + + /** + + * Public accessor to the unique name of the data source instance. + + * + + * @return {string} Unique name of the data source instance + + */ + +YAHOO.widget.DataSource.prototype.toString = function() { + + return "DataSource " + this._sName; + +}; + + + +/** + + * Retrieves query results, first checking the local cache, then making the + + * query request to the live data source as defined by the function doQuery. + + * + + * @param {object} oCallbackFn Callback function defined by oParent object to + + * which to return results + + * @param {string} sQuery Query string + + * @param {object} oParent The object instance that has requested data + + */ + +YAHOO.widget.DataSource.prototype.getResults = function(oCallbackFn, sQuery, oParent) { + + + + // First look in cache + + var aResults = this._doQueryCache(oCallbackFn,sQuery,oParent); + + + + // Not in cache, so get results from server + + if(aResults.length === 0) { + + this.queryEvent.fire(this, oParent, sQuery); + + this.doQuery(oCallbackFn, sQuery, oParent); + + } + +}; + + + +/** + + * Abstract method implemented by subclasses to make a query to the live data + + * source. Must call the callback function with the response returned from the + + * query. Populates cache (if enabled). + + * + + * @param {object} oCallbackFn Callback function implemented by oParent to + + * which to return results + + * @param {string} sQuery Query string + + * @param {object} oParent The object instance that has requested data + + */ + +YAHOO.widget.DataSource.prototype.doQuery = function(oCallbackFn, sQuery, oParent) { + + /* override this */ + +}; + + + +/** + + * Flushes cache. + + */ + +YAHOO.widget.DataSource.prototype.flushCache = function() { + + if(this._aCache) { + + this._aCache = []; + + } + + if(this._aCacheHelper) { + + this._aCacheHelper = []; + + } + + this.cacheFlushEvent.fire(this); + +}; + + + +/*************************************************************************** + + * Events + + ***************************************************************************/ + +/** + + * Fired when a query is made to the live data source. Subscribers receive the + + * following array:
    + + * - args[0] The data source instance + + * - args[1] The requesting object + + * - args[2] The query string + + */ + +YAHOO.widget.DataSource.prototype.queryEvent = null; + + + +/** + + * Fired when a query is made to the local cache. Subscribers receive the + + * following array:
    + + * - args[0] The data source instance + + * - args[1] The requesting object + + * - args[2] The query string + + */ + +YAHOO.widget.DataSource.prototype.cacheQueryEvent = null; + + + +/** + + * Fired when data is retrieved from the live data source. Subscribers receive + + * the following array:
    + + * - args[0] The data source instance + + * - args[1] The requesting object + + * - args[2] The query string + + * - args[3] Array of result objects + + */ + +YAHOO.widget.DataSource.prototype.getResultsEvent = null; + + + +/** + + * Fired when data is retrieved from the local cache. Subscribers receive the + + * following array :
    + + * - args[0] The data source instance + + * - args[1] The requesting object + + * - args[2] The query string + + * - args[3] Array of result objects + + */ + +YAHOO.widget.DataSource.prototype.getCachedResultsEvent = null; + + + +/** + + * Fired when an error is encountered with the live data source. Subscribers + + * receive the following array:
    + + * - args[0] The data source instance + + * - args[1] The requesting object + + * - args[2] The query string + + * - args[3] Error message string + + */ + +YAHOO.widget.DataSource.prototype.dataErrorEvent = null; + + + +/** + + * Fired when the local cache is flushed. Subscribers receive the following + + * array :
    + + * - args[0] The data source instance + + */ + +YAHOO.widget.DataSource.prototype.cacheFlushEvent = null; + + + +/*************************************************************************** + + * Private member variables + + ***************************************************************************/ + +/** + + * Internal class variable to index multiple data source instances. + + * + + * @type number + + * @private + + */ + +YAHOO.widget.DataSource._nIndex = 0; + + + +/** + + * Name of data source instance. + + * + + * @type string + + * @private + + */ + +YAHOO.widget.DataSource.prototype._sName = null; + + + +/** + + * Local cache of data result objects indexed chronologically. + + * + + * @type array + + * @private + + */ + +YAHOO.widget.DataSource.prototype._aCache = null; + + + + + +/*************************************************************************** + + * Private methods + + ***************************************************************************/ + +/** + + * Initializes data source instance. + + * + + * @private + + */ + +YAHOO.widget.DataSource.prototype._init = function() { + + // Validate and initialize public configs + + var maxCacheEntries = this.maxCacheEntries; + + if(isNaN(maxCacheEntries) || (maxCacheEntries < 0)) { + + maxCacheEntries = 0; + + } + + // Initialize local cache + + if(maxCacheEntries > 0 && !this._aCache) { + + this._aCache = []; + + } + + + + this._sName = "instance" + YAHOO.widget.DataSource._nIndex; + + YAHOO.widget.DataSource._nIndex++; + + + + this.queryEvent = new YAHOO.util.CustomEvent("query", this); + + this.cacheQueryEvent = new YAHOO.util.CustomEvent("cacheQuery", this); + + this.getResultsEvent = new YAHOO.util.CustomEvent("getResults", this); + + this.getCachedResultsEvent = new YAHOO.util.CustomEvent("getCachedResults", this); + + this.dataErrorEvent = new YAHOO.util.CustomEvent("dataError", this); + + this.cacheFlushEvent = new YAHOO.util.CustomEvent("cacheFlush", this); + +}; + + + +/** + + * Adds a result object to the local cache, evicting the oldest element if the + + * cache is full. Newer items will have higher indexes, the oldest item will have + + * index of 0. + + * + + * @param {object} resultObj Object literal of data results, including internal + + * properties and an array of result objects + + * @private + + */ + +YAHOO.widget.DataSource.prototype._addCacheElem = function(resultObj) { + + var aCache = this._aCache; + + // Don't add if anything important is missing. + + if(!aCache || !resultObj || !resultObj.query || !resultObj.results) { + + return; + + } + + + + // If the cache is full, make room by removing from index=0 + + if(aCache.length >= this.maxCacheEntries) { + + aCache.shift(); + + } + + + + // Add to cache, at the end of the array + + aCache.push(resultObj); + +}; + + + +/** + + * Queries the local cache for results. If query has been cached, the callback + + * function is called with the results, and the cached is refreshed so that it + + * is now the newest element. + + * + + * @param {object} oCallbackFn Callback function defined by oParent object to + + * which to return results + + * @param {string} sQuery Query string + + * @param {object} oParent The object instance that has requested data + + * @return {array} aResults Result object from local cache if found, otherwise + + * null + + * @private + + */ + +YAHOO.widget.DataSource.prototype._doQueryCache = function(oCallbackFn, sQuery, oParent) { + + var aResults = []; + + var bMatchFound = false; + + var aCache = this._aCache; + + var nCacheLength = (aCache) ? aCache.length : 0; + + var bMatchContains = this.queryMatchContains; + + + + // If cache is enabled... + + if((this.maxCacheEntries > 0) && aCache && (nCacheLength > 0)) { + + this.cacheQueryEvent.fire(this, oParent, sQuery); + + // If case is unimportant, normalize query now instead of in loops + + if(!this.queryMatchCase) { + + var sOrigQuery = sQuery; + + sQuery = sQuery.toLowerCase(); + + } + + + + // Loop through each cached element's query property... + + for(var i = nCacheLength-1; i >= 0; i--) { + + var resultObj = aCache[i]; + + var aAllResultItems = resultObj.results; + + // If case is unimportant, normalize match key for comparison + + var matchKey = (!this.queryMatchCase) ? + + encodeURIComponent(resultObj.query.toLowerCase()): + + encodeURIComponent(resultObj.query); + + + + // If a cached match key exactly matches the query... + + if(matchKey == sQuery) { + + // Stash all result objects into aResult[] and stop looping through the cache. + + bMatchFound = true; + + aResults = aAllResultItems; + + + + // The matching cache element was not the most recent, + + // so now we need to refresh the cache. + + if(i != nCacheLength-1) { + + // Remove element from its original location + + aCache.splice(i,1); + + // Add element as newest + + this._addCacheElem(resultObj); + + } + + break; + + } + + // Else if this query is not an exact match and subset matching is enabled... + + else if(this.queryMatchSubset) { + + // Loop through substrings of each cached element's query property... + + for(var j = sQuery.length-1; j >= 0 ; j--) { + + var subQuery = sQuery.substr(0,j); + + + + // If a substring of a cached sQuery exactly matches the query... + + if(matchKey == subQuery) { + + bMatchFound = true; + + + + // Go through each cached result object to match against the query... + + for(var k = aAllResultItems.length-1; k >= 0; k--) { + + var aRecord = aAllResultItems[k]; + + var sKeyIndex = (this.queryMatchCase) ? + + encodeURIComponent(aRecord[0]).indexOf(sQuery): + + encodeURIComponent(aRecord[0]).toLowerCase().indexOf(sQuery); + + + + // A STARTSWITH match is when the query is found at the beginning of the key string... + + if((!bMatchContains && (sKeyIndex === 0)) || + + // A CONTAINS match is when the query is found anywhere within the key string... + + (bMatchContains && (sKeyIndex > -1))) { + + // Stash a match into aResults[]. + + aResults.unshift(aRecord); + + } + + } + + + + // Add the subset match result set object as the newest element to cache, + + // and stop looping through the cache. + + resultObj = {}; + + resultObj.query = sQuery; + + resultObj.results = aResults; + + this._addCacheElem(resultObj); + + break; + + } + + } + + if(bMatchFound) { + + break; + + } + + } + + } + + + + // If there was a match, send along the results. + + if(bMatchFound) { + + this.getCachedResultsEvent.fire(this, oParent, sOrigQuery, aResults); + + oCallbackFn(sOrigQuery, aResults, oParent); + + } + + } + + return aResults; + +}; + + + + + +/****************************************************************************/ + +/****************************************************************************/ + +/****************************************************************************/ + + + +/** + + * Implementation of YAHOO.widget.DataSource using XML HTTP requests that return + + * query results. + + * requires YAHOO.util.Connect XMLHTTPRequest library + + * extends YAHOO.widget.DataSource + + * + + * @constructor + + * @param {string} sScriptURI Absolute or relative URI to script that returns + + * query results as JSON, XML, or delimited flat data + + * @param {array} aSchema Data schema definition of results + + * @param {object} oConfigs Optional object literal of config params + + */ + +YAHOO.widget.DS_XHR = function(sScriptURI, aSchema, oConfigs) { + + // Set any config params passed in to override defaults + + if(typeof oConfigs == "object") { + + for(var sConfig in oConfigs) { + + this[sConfig] = oConfigs[sConfig]; + + } + + } + + + + // Initialization sequence + + if(!aSchema || (aSchema.constructor != Array)) { + + YAHOO.log("Could not instantiate XHR DataSource due to invalid arguments", "error", this.toString()); + + return; + + } + + else { + + this.schema = aSchema; + + } + + this.scriptURI = sScriptURI; + + this._init(); + + YAHOO.log("XHR DataSource initialized","info",this.toString()); + +}; + + + +YAHOO.widget.DS_XHR.prototype = new YAHOO.widget.DataSource(); + + + +/*************************************************************************** + + * Public constants + + ***************************************************************************/ + +/** + + * JSON data type + + * + + * @type constant + + * @final + + */ + +YAHOO.widget.DS_XHR.prototype.TYPE_JSON = 0; + + + +/** + + * XML data type + + * + + * @type constant + + * @final + + */ + +YAHOO.widget.DS_XHR.prototype.TYPE_XML = 1; + + + +/** + + * Flat file data type + + * + + * @type constant + + * @final + + */ + +YAHOO.widget.DS_XHR.prototype.TYPE_FLAT = 2; + + + +/** + + * Error message for XHR failure. + + * + + * @type constant + + * @final + + */ + +YAHOO.widget.DS_XHR.prototype.ERROR_DATAXHR = "XHR response failed"; + + + +/*************************************************************************** + + * Public member variables + + ***************************************************************************/ + +/** + + * Number of milliseconds the XHR connection will wait for a server response. A + + * a value of zero indicates the XHR connection will wait forever. Any value + + * greater than zero will use the Connection utility's Auto-Abort feature. + + * Default: 0. + + * + + * @type number + + */ + +YAHOO.widget.DS_XHR.prototype.connTimeout = 0; + + + + + +/** + + * Absolute or relative URI to script that returns query results. For instance, + + * queries will be sent to + + * ?=userinput + + * + + * @type string + + */ + +YAHOO.widget.DS_XHR.prototype.scriptURI = null; + + + +/** + + * Query string parameter name sent to scriptURI. For instance, queries will be + + * sent to + + * ?=userinput + + * Default: "query". + + * + + * @type string + + */ + +YAHOO.widget.DS_XHR.prototype.scriptQueryParam = "query"; + + + +/** + + * String of key/value pairs to append to requests made to scriptURI. Define + + * this string when you want to send additional query parameters to your script. + + * When defined, queries will be sent to + + * ?=userinput& + + * Default: "". + + * + + * @type string + + */ + +YAHOO.widget.DS_XHR.prototype.scriptQueryAppend = ""; + + + +/** + + * XHR response data type. Other types that may be defined are TYPE_XML and + + * TYPE_FLAT. Default: TYPE_JSON. + + * + + * @type type + + */ + +YAHOO.widget.DS_XHR.prototype.responseType = YAHOO.widget.DS_XHR.prototype.TYPE_JSON; + + + +/** + + * String after which to strip results. If the results from the XHR are sent + + * back as HTML, the gzip HTML comment appears at the end of the data and should + + * be ignored. Default: "\n<!--" + + * + + * @type string + + */ + +YAHOO.widget.DS_XHR.prototype.responseStripAfter = "\n