[ Index ]
 

Code source de PRADO 3.0.6

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/framework/Web/Javascripts/rico/ -> rico.js (source)

   1  /**
   2    *
   3    *  Copyright 2005 Sabre Airline Solutions
   4    *
   5    *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
   6    *  file except in compliance with the License. You may obtain a copy of the License at
   7    *
   8    *         http://www.apache.org/licenses/LICENSE-2.0
   9    *
  10    *  Unless required by applicable law or agreed to in writing, software distributed under the
  11    *  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  12    *  either express or implied. See the License for the specific language governing permissions
  13    *  and limitations under the License.
  14    **/
  15  
  16  
  17  //-------------------- rico.js
  18  var Rico = {
  19    Version: '1.1rc1',
  20    prototypeVersion: parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1])
  21  }
  22  
  23  /*
  24  if((typeof Prototype=='undefined') || Rico.prototypeVersion < 1.3)
  25        throw("Rico requires the Prototype JavaScript framework >= 1.3");
  26  */
  27  Rico.ArrayExtensions = new Array();
  28  
  29  if (Object.prototype.extend) {
  30     Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
  31  }else{
  32    Object.prototype.extend = function(object) {
  33      return Object.extend.apply(this, [this, object]);
  34    }
  35    Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
  36  }
  37  
  38  if (Array.prototype.push) {
  39     Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.push;
  40  }
  41  
  42  if (!Array.prototype.remove) {
  43     Array.prototype.remove = function(dx) {
  44        if( isNaN(dx) || dx > this.length )
  45           return false;
  46        for( var i=0,n=0; i<this.length; i++ )
  47           if( i != dx )
  48              this[n++]=this[i];
  49        this.length-=1;
  50     };
  51    Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.remove;
  52  }
  53  
  54  if (!Array.prototype.removeItem) {
  55     Array.prototype.removeItem = function(item) {
  56        for ( var i = 0 ; i < this.length ; i++ )
  57           if ( this[i] == item ) {
  58              this.remove(i);
  59              break;
  60           }
  61     };
  62    Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.removeItem;
  63  }
  64  
  65  if (!Array.prototype.indices) {
  66     Array.prototype.indices = function() {
  67        var indexArray = new Array();
  68        for ( index in this ) {
  69           var ignoreThis = false;
  70           for ( var i = 0 ; i < Rico.ArrayExtensions.length ; i++ ) {
  71              if ( this[index] == Rico.ArrayExtensions[i] ) {
  72                 ignoreThis = true;
  73                 break;
  74              }
  75           }
  76           if ( !ignoreThis )
  77              indexArray[ indexArray.length ] = index;
  78        }
  79        return indexArray;
  80     }
  81    Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.indices;
  82  }
  83  
  84  // Create the loadXML method and xml getter for Mozilla
  85  if ( window.DOMParser &&
  86        window.XMLSerializer &&
  87        window.Node && Node.prototype && Node.prototype.__defineGetter__ ) {
  88  
  89     if (!Document.prototype.loadXML) {
  90        Document.prototype.loadXML = function (s) {
  91           var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
  92           while (this.hasChildNodes())
  93              this.removeChild(this.lastChild);
  94  
  95           for (var i = 0; i < doc2.childNodes.length; i++) {
  96              this.appendChild(this.importNode(doc2.childNodes[i], true));
  97           }
  98        };
  99      }
 100  
 101      Document.prototype.__defineGetter__( "xml",
 102         function () {
 103             return (new XMLSerializer()).serializeToString(this);
 104         }
 105       );
 106  }
 107  
 108  document.getElementsByTagAndClassName = function(tagName, className) {
 109    if ( tagName == null )
 110       tagName = '*';
 111  
 112    var children = document.getElementsByTagName(tagName) || document.all;
 113    var elements = new Array();
 114  
 115    if ( className == null )
 116      return children;
 117  
 118    for (var i = 0; i < children.length; i++) {
 119      var child = children[i];
 120      var classNames = child.className.split(' ');
 121      for (var j = 0; j < classNames.length; j++) {
 122        if (classNames[j] == className) {
 123          elements.push(child);
 124          break;
 125        }
 126      }
 127    }
 128  
 129    return elements;
 130  }
 131  
 132  
 133  //-------------------- ricoAccordion.js
 134  Rico.Accordion = Class.create();
 135  
 136  Rico.Accordion.prototype = {
 137  
 138     initialize: function(container, options) {
 139        this.container            = $(container);
 140        this.lastExpandedTab      = null;
 141        this.accordionTabs        = new Array();
 142        this.setOptions(options);
 143        this._attachBehaviors();
 144        if(!container) return;
 145  
 146        this.container.style.borderBottom = '1px solid ' + this.options.borderColor;
 147        // validate onloadShowTab
 148         if (this.options.onLoadShowTab >= this.accordionTabs.length)
 149          this.options.onLoadShowTab = 0;
 150  
 151        // set the initial visual state...
 152        for ( var i=0 ; i < this.accordionTabs.length ; i++ )
 153        {
 154          if (i != this.options.onLoadShowTab){
 155           this.accordionTabs[i].collapse();
 156           this.accordionTabs[i].content.style.display = 'none';
 157          }
 158        }
 159        this.lastExpandedTab = this.accordionTabs[this.options.onLoadShowTab];
 160        if (this.options.panelHeight == 'auto'){
 161            var tabToCheck = (this.options.onloadShowTab === 0)? 1 : 0;
 162            var titleBarSize = parseInt(RicoUtil.getElementsComputedStyle(this.accordionTabs[tabToCheck].titleBar, 'height'));
 163            if (isNaN(titleBarSize))
 164              titleBarSize = this.accordionTabs[tabToCheck].titleBar.offsetHeight;
 165  
 166            var totalTitleBarSize = this.accordionTabs.length * titleBarSize;
 167            var parentHeight = parseInt(RicoUtil.getElementsComputedStyle(this.container.parentNode, 'height'));
 168            if (isNaN(parentHeight))
 169              parentHeight = this.container.parentNode.offsetHeight;
 170  
 171            this.options.panelHeight = parentHeight - totalTitleBarSize-2;
 172        }
 173  
 174        this.lastExpandedTab.content.style.height = this.options.panelHeight + "px";
 175        this.lastExpandedTab.showExpanded();
 176        this.lastExpandedTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
 177  
 178     },
 179  
 180     setOptions: function(options) {
 181        this.options = {
 182           expandedBg          : '#63699c',
 183           hoverBg             : '#63699c',
 184           collapsedBg         : '#6b79a5',
 185           expandedTextColor   : '#ffffff',
 186           expandedFontWeight  : 'bold',
 187           hoverTextColor      : '#ffffff',
 188           collapsedTextColor  : '#ced7ef',
 189           collapsedFontWeight : 'normal',
 190           hoverTextColor      : '#ffffff',
 191           borderColor         : '#1f669b',
 192           panelHeight         : 200,
 193           onHideTab           : null,
 194           onShowTab           : null,
 195           onLoadShowTab       : 0
 196        }
 197        Object.extend(this.options, options || {});
 198     },
 199  
 200     showTabByIndex: function( anIndex, animate ) {
 201        var doAnimate = arguments.length == 1 ? true : animate;
 202        this.showTab( this.accordionTabs[anIndex], doAnimate );
 203     },
 204  
 205     showTab: function( accordionTab, animate ) {
 206  
 207        var doAnimate = arguments.length == 1 ? true : animate;
 208  
 209        if ( this.options.onHideTab )
 210           this.options.onHideTab(this.lastExpandedTab);
 211  
 212        this.lastExpandedTab.showCollapsed();
 213        var accordion = this;
 214        var lastExpandedTab = this.lastExpandedTab;
 215  
 216        this.lastExpandedTab.content.style.height = (this.options.panelHeight - 1) + 'px';
 217        accordionTab.content.style.display = '';
 218  
 219        accordionTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
 220  
 221        if ( doAnimate ) {
 222           new Effect.AccordionSize( this.lastExpandedTab.content,
 223                                     accordionTab.content,
 224                                     1,
 225                                     this.options.panelHeight,
 226                                     100, 10,
 227                                     { complete: function() {accordion.showTabDone(lastExpandedTab)} } );
 228           this.lastExpandedTab = accordionTab;
 229        }
 230        else {
 231           this.lastExpandedTab.content.style.height = "1px";
 232           accordionTab.content.style.height = this.options.panelHeight + "px";
 233           this.lastExpandedTab = accordionTab;
 234           this.showTabDone(lastExpandedTab);
 235        }
 236     },
 237  
 238     showTabDone: function(collapsedTab) {
 239        collapsedTab.content.style.display = 'none';
 240        this.lastExpandedTab.showExpanded();
 241        if ( this.options.onShowTab )
 242           this.options.onShowTab(this.lastExpandedTab);
 243     },
 244  
 245     _attachBehaviors: function() {
 246        var panels = this._getDirectChildrenByTag(this.container, 'DIV');
 247        for ( var i = 0 ; i < panels.length ; i++ ) {
 248  
 249           var tabChildren = this._getDirectChildrenByTag(panels[i],'DIV');
 250           if ( tabChildren.length != 2 )
 251              continue; // unexpected
 252  
 253           var tabTitleBar   = tabChildren[0];
 254           var tabContentBox = tabChildren[1];
 255           this.accordionTabs.push( new Rico.Accordion.Tab(this,tabTitleBar,tabContentBox) );
 256        }
 257     },
 258  
 259     _getDirectChildrenByTag: function(e, tagName) {
 260        var kids = new Array();
 261        var allKids = e.childNodes;
 262        for( var i = 0 ; i < allKids.length ; i++ )
 263           if ( allKids[i] && allKids[i].tagName && allKids[i].tagName == tagName )
 264              kids.push(allKids[i]);
 265        return kids;
 266     }
 267  
 268  };
 269  
 270  Rico.Accordion.Tab = Class.create();
 271  
 272  Rico.Accordion.Tab.prototype = {
 273  
 274     initialize: function(accordion, titleBar, content) {
 275        this.accordion = accordion;
 276        this.titleBar  = titleBar;
 277        this.content   = content;
 278        this._attachBehaviors();
 279     },
 280  
 281     collapse: function() {
 282        this.showCollapsed();
 283        this.content.style.height = "1px";
 284     },
 285  
 286     showCollapsed: function() {
 287        this.expanded = false;
 288        this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
 289        this.titleBar.style.color           = this.accordion.options.collapsedTextColor;
 290        this.titleBar.style.fontWeight      = this.accordion.options.collapsedFontWeight;
 291        this.content.style.overflow = "hidden";
 292     },
 293  
 294     showExpanded: function() {
 295        this.expanded = true;
 296        this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
 297        this.titleBar.style.color           = this.accordion.options.expandedTextColor;
 298        this.content.style.overflow         = "visible";
 299     },
 300  
 301     titleBarClicked: function(e) {
 302        if ( this.accordion.lastExpandedTab == this )
 303           return;
 304        this.accordion.showTab(this);
 305     },
 306  
 307     hover: function(e) {
 308          this.titleBar.style.backgroundColor = this.accordion.options.hoverBg;
 309          this.titleBar.style.color           = this.accordion.options.hoverTextColor;
 310     },
 311  
 312     unhover: function(e) {
 313        if ( this.expanded ) {
 314           this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
 315           this.titleBar.style.color           = this.accordion.options.expandedTextColor;
 316        }
 317        else {
 318           this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
 319           this.titleBar.style.color           = this.accordion.options.collapsedTextColor;
 320        }
 321     },
 322  
 323     _attachBehaviors: function() {
 324        this.content.style.border = "1px solid " + this.accordion.options.borderColor;
 325        this.content.style.borderTopWidth    = "0px";
 326        this.content.style.borderBottomWidth = "0px";
 327        this.content.style.margin            = "0px";
 328  
 329        this.titleBar.onclick     = this.titleBarClicked.bindAsEventListener(this);
 330        this.titleBar.onmouseover = this.hover.bindAsEventListener(this);
 331        this.titleBar.onmouseout  = this.unhover.bindAsEventListener(this);
 332     }
 333  
 334  };
 335  
 336  
 337  //-------------------- ricoAjaxEngine.js
 338  /*
 339  Rico.AjaxEngine = Class.create();
 340  
 341  Rico.AjaxEngine.prototype = {
 342  
 343     initialize: function() {
 344        this.ajaxElements = new Array();
 345        this.ajaxObjects  = new Array();
 346        this.requestURLS  = new Array();
 347        this.options = {};
 348     },
 349  
 350     registerAjaxElement: function( anId, anElement ) {
 351        if ( !anElement )
 352           anElement = $(anId);
 353        this.ajaxElements[anId] = anElement;
 354     },
 355  
 356     registerAjaxObject: function( anId, anObject ) {
 357        this.ajaxObjects[anId] = anObject;
 358     },
 359  
 360     registerRequest: function (requestLogicalName, requestURL) {
 361        this.requestURLS[requestLogicalName] = requestURL;
 362     },
 363  
 364     sendRequest: function(requestName, options) {
 365        // Allow for backwards Compatibility
 366        if ( arguments.length >= 2 )
 367         if (typeof arguments[1] == 'string')
 368           options = {parameters: this._createQueryString(arguments, 1)};
 369        this.sendRequestWithData(requestName, null, options);
 370     },
 371  
 372     sendRequestWithData: function(requestName, xmlDocument, options) {
 373        var requestURL = this.requestURLS[requestName];
 374        if ( requestURL == null )
 375           return;
 376  
 377        // Allow for backwards Compatibility
 378        if ( arguments.length >= 3 )
 379          if (typeof arguments[2] == 'string')
 380            options.parameters = this._createQueryString(arguments, 2);
 381  
 382        new Ajax.Request(requestURL, this._requestOptions(options,xmlDocument));
 383     },
 384  
 385     sendRequestAndUpdate: function(requestName,container,options) {
 386        // Allow for backwards Compatibility
 387        if ( arguments.length >= 3 )
 388          if (typeof arguments[2] == 'string')
 389            options.parameters = this._createQueryString(arguments, 2);
 390  
 391        this.sendRequestWithDataAndUpdate(requestName, null, container, options);
 392     },
 393  
 394     sendRequestWithDataAndUpdate: function(requestName,xmlDocument,container,options) {
 395        var requestURL = this.requestURLS[requestName];
 396        if ( requestURL == null )
 397           return;
 398  
 399        // Allow for backwards Compatibility
 400        if ( arguments.length >= 4 )
 401          if (typeof arguments[3] == 'string')
 402            options.parameters = this._createQueryString(arguments, 3);
 403  
 404        var updaterOptions = this._requestOptions(options,xmlDocument);
 405        // Turn off onComplete
 406        //updaterOptions.onComplete = null;
 407  
 408        new Ajax.Updater(container, requestURL, updaterOptions);
 409     },
 410  
 411     // Private -- not part of intended engine API --------------------------------------------------------------------
 412  
 413     _requestOptions: function(options,xmlDoc) {
 414        var requestHeaders = ['X-Rico-Version', Rico.Version ];
 415        var sendMethod = 'post';
 416        if ( xmlDoc == null )
 417          if (Rico.prototypeVersion < 1.4)
 418          requestHeaders.push( 'Content-type', 'text/xml' );
 419        else
 420            sendMethod = 'get';
 421        (!options) ? options = {} : '';
 422  
 423        // Check and keep any user onComplete functions
 424        if (options.onComplete)
 425             options.onRicoComplete = options.onComplete;
 426        // Fix onComplete
 427        if (options.overrideOnComplete)
 428          options.onComplete = options.overrideOnComplete;
 429        else
 430          options.onComplete = this._onRequestComplete.bind(this);
 431  
 432       // Set the default options and extend with any user options
 433       this.options = {
 434                       requestHeaders: requestHeaders,
 435                       parameters:     options.parameters,
 436                       postBody:       xmlDoc,
 437                       method:         sendMethod,
 438                       onComplete:     options.onComplete
 439                      };
 440       // Set any user options:
 441       Object.extend(this.options, options);
 442       return this.options;
 443     },
 444  
 445     _createQueryString: function( theArgs, offset ) {
 446        var queryString = ""
 447        for ( var i = offset ; i < theArgs.length ; i++ ) {
 448            if ( i != offset )
 449              queryString += "&";
 450  
 451            var anArg = theArgs[i];
 452  
 453            if ( anArg.name != undefined && anArg.value != undefined ) {
 454              queryString += anArg.name +  "=" + escape(anArg.value);
 455            }
 456            else {
 457               var ePos  = anArg.indexOf('=');
 458               var argName  = anArg.substring( 0, ePos );
 459               var argValue = anArg.substring( ePos + 1 );
 460               queryString += argName + "=" + escape(argValue);
 461            }
 462        }
 463        return queryString;
 464     },
 465  
 466     _onRequestComplete : function(request) {
 467        if(!request)
 468            return;
 469        // User can set an onFailure option - which will be called by prototype
 470        if (request.status != 200)
 471          return;
 472  
 473        var response = request.responseXML.getElementsByTagName("ajax-response");
 474        if (response == null || response.length != 1)
 475           return;
 476        this._processAjaxResponse( response[0].childNodes );
 477  
 478        // Check if user has set a onComplete function
 479        var onRicoComplete = this.options.onRicoComplete;
 480        if (onRicoComplete != null)
 481            onRicoComplete();
 482     },
 483  
 484     _processAjaxResponse: function( xmlResponseElements ) {
 485        for ( var i = 0 ; i < xmlResponseElements.length ; i++ ) {
 486           var responseElement = xmlResponseElements[i];
 487  
 488           // only process nodes of type element.....
 489           if ( responseElement.nodeType != 1 )
 490              continue;
 491  
 492           var responseType = responseElement.getAttribute("type");
 493           var responseId   = responseElement.getAttribute("id");
 494  
 495           if ( responseType == "object" )
 496              this._processAjaxObjectUpdate( this.ajaxObjects[ responseId ], responseElement );
 497           else if ( responseType == "element" )
 498              this._processAjaxElementUpdate( this.ajaxElements[ responseId ], responseElement );
 499           else
 500              alert('unrecognized AjaxResponse type : ' + responseType );
 501        }
 502     },
 503  
 504     _processAjaxObjectUpdate: function( ajaxObject, responseElement ) {
 505        ajaxObject.ajaxUpdate( responseElement );
 506     },
 507  
 508     _processAjaxElementUpdate: function( ajaxElement, responseElement ) {
 509        ajaxElement.innerHTML = RicoUtil.getContentAsString(responseElement);
 510     }
 511  
 512  }
 513  
 514  var ajaxEngine = new Rico.AjaxEngine();
 515  */
 516  
 517  //-------------------- ricoColor.js
 518  /*Rico.Color = Class.create();
 519  
 520  Rico.Color.prototype = {
 521  
 522     initialize: function(red, green, blue) {
 523        this.rgb = { r: red, g : green, b : blue };
 524     },
 525  
 526     setRed: function(r) {
 527        this.rgb.r = r;
 528     },
 529  
 530     setGreen: function(g) {
 531        this.rgb.g = g;
 532     },
 533  
 534     setBlue: function(b) {
 535        this.rgb.b = b;
 536     },
 537  
 538     setHue: function(h) {
 539  
 540        // get an HSB model, and set the new hue...
 541        var hsb = this.asHSB();
 542        hsb.h = h;
 543  
 544        // convert back to RGB...
 545        this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
 546     },
 547  
 548     setSaturation: function(s) {
 549        // get an HSB model, and set the new hue...
 550        var hsb = this.asHSB();
 551        hsb.s = s;
 552  
 553        // convert back to RGB and set values...
 554        this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
 555     },
 556  
 557     setBrightness: function(b) {
 558        // get an HSB model, and set the new hue...
 559        var hsb = this.asHSB();
 560        hsb.b = b;
 561  
 562        // convert back to RGB and set values...
 563        this.rgb = Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b );
 564     },
 565  
 566     darken: function(percent) {
 567        var hsb  = this.asHSB();
 568        this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0));
 569     },
 570  
 571     brighten: function(percent) {
 572        var hsb  = this.asHSB();
 573        this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1));
 574     },
 575  
 576     blend: function(other) {
 577        this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2);
 578        this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2);
 579        this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2);
 580     },
 581  
 582     isBright: function() {
 583        var hsb = this.asHSB();
 584        return this.asHSB().b > 0.5;
 585     },
 586  
 587     isDark: function() {
 588        return ! this.isBright();
 589     },
 590  
 591     asRGB: function() {
 592        return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")";
 593     },
 594  
 595     asHex: function() {
 596        return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart();
 597     },
 598  
 599     asHSB: function() {
 600        return Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b);
 601     },
 602  
 603     toString: function() {
 604        return this.asHex();
 605     }
 606  
 607  };
 608  
 609  Rico.Color.createFromHex = function(hexCode) {
 610  
 611     if ( hexCode.indexOf('#') == 0 )
 612        hexCode = hexCode.substring(1);
 613     var red   = hexCode.substring(0,2);
 614     var green = hexCode.substring(2,4);
 615     var blue  = hexCode.substring(4,6);
 616     return new Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) );
 617  }
 618  
 619  /**
 620   * Factory method for creating a color from the background of
 621   * an HTML element.
 622   *
 623  Rico.Color.createColorFromBackground = function(elem) {
 624  
 625     var actualColor = RicoUtil.getElementsComputedStyle($(elem), "backgroundColor", "background-color");
 626  
 627     if ( actualColor == "transparent" && elem.parent )
 628        return Rico.Color.createColorFromBackground(elem.parent);
 629  
 630     if ( actualColor == null )
 631        return new Rico.Color(255,255,255);
 632  
 633     if ( actualColor.indexOf("rgb(") == 0 ) {
 634        var colors = actualColor.substring(4, actualColor.length - 1 );
 635        var colorArray = colors.split(",");
 636        return new Rico.Color( parseInt( colorArray[0] ),
 637                              parseInt( colorArray[1] ),
 638                              parseInt( colorArray[2] )  );
 639  
 640     }
 641     else if ( actualColor.indexOf("#") == 0 ) {
 642        var redPart   = parseInt(actualColor.substring(1,3), 16);
 643        var greenPart = parseInt(actualColor.substring(3,5), 16);
 644        var bluePart  = parseInt(actualColor.substring(5), 16);
 645        return new Rico.Color( redPart, greenPart, bluePart );
 646     }
 647     else
 648        return new Rico.Color(255,255,255);
 649  }
 650  
 651  Rico.Color.HSBtoRGB = function(hue, saturation, brightness) {
 652  
 653     var red   = 0;
 654      var green = 0;
 655      var blue  = 0;
 656  
 657     if (saturation == 0) {
 658        red = parseInt(brightness * 255.0 + 0.5);
 659         green = red;
 660         blue = red;
 661      }
 662      else {
 663        var h = (hue - Math.floor(hue)) * 6.0;
 664        var f = h - Math.floor(h);
 665        var p = brightness * (1.0 - saturation);
 666        var q = brightness * (1.0 - saturation * f);
 667        var t = brightness * (1.0 - (saturation * (1.0 - f)));
 668  
 669        switch (parseInt(h)) {
 670           case 0:
 671              red   = (brightness * 255.0 + 0.5);
 672              green = (t * 255.0 + 0.5);
 673              blue  = (p * 255.0 + 0.5);
 674              break;
 675           case 1:
 676              red   = (q * 255.0 + 0.5);
 677              green = (brightness * 255.0 + 0.5);
 678              blue  = (p * 255.0 + 0.5);
 679              break;
 680           case 2:
 681              red   = (p * 255.0 + 0.5);
 682              green = (brightness * 255.0 + 0.5);
 683              blue  = (t * 255.0 + 0.5);
 684              break;
 685           case 3:
 686              red   = (p * 255.0 + 0.5);
 687              green = (q * 255.0 + 0.5);
 688              blue  = (brightness * 255.0 + 0.5);
 689              break;
 690           case 4:
 691              red   = (t * 255.0 + 0.5);
 692              green = (p * 255.0 + 0.5);
 693              blue  = (brightness * 255.0 + 0.5);
 694              break;
 695            case 5:
 696              red   = (brightness * 255.0 + 0.5);
 697              green = (p * 255.0 + 0.5);
 698              blue  = (q * 255.0 + 0.5);
 699              break;
 700          }
 701      }
 702  
 703     return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) };
 704  }
 705  
 706  Rico.Color.RGBtoHSB = function(r, g, b) {
 707  
 708     var hue;
 709     var saturaton;
 710     var brightness;
 711  
 712     var cmax = (r > g) ? r : g;
 713     if (b > cmax)
 714        cmax = b;
 715  
 716     var cmin = (r < g) ? r : g;
 717     if (b < cmin)
 718        cmin = b;
 719  
 720     brightness = cmax / 255.0;
 721     if (cmax != 0)
 722        saturation = (cmax - cmin)/cmax;
 723     else
 724        saturation = 0;
 725  
 726     if (saturation == 0)
 727        hue = 0;
 728     else {
 729        var redc   = (cmax - r)/(cmax - cmin);
 730          var greenc = (cmax - g)/(cmax - cmin);
 731          var bluec  = (cmax - b)/(cmax - cmin);
 732  
 733          if (r == cmax)
 734             hue = bluec - greenc;
 735          else if (g == cmax)
 736             hue = 2.0 + redc - bluec;
 737        else
 738             hue = 4.0 + greenc - redc;
 739  
 740          hue = hue / 6.0;
 741          if (hue < 0)
 742             hue = hue + 1.0;
 743     }
 744  
 745     return { h : hue, s : saturation, b : brightness };
 746  }
 747  */
 748  
 749  //-------------------- ricoCorner.js
 750  Rico.Corner = {
 751  
 752     round: function(e, options) {
 753        var e = $(e);
 754        this._setOptions(options);
 755  
 756        var color = this.options.color;
 757        if ( this.options.color == "fromElement" )
 758           color = this._background(e);
 759  
 760        var bgColor = this.options.bgColor;
 761        if ( this.options.bgColor == "fromParent" )
 762           bgColor = this._background(e.offsetParent);
 763  
 764        this._roundCornersImpl(e, color, bgColor);
 765     },
 766  
 767     _roundCornersImpl: function(e, color, bgColor) {
 768        if(this.options.border)
 769           this._renderBorder(e,bgColor);
 770        if(this._isTopRounded())
 771           this._roundTopCorners(e,color,bgColor);
 772        if(this._isBottomRounded())
 773           this._roundBottomCorners(e,color,bgColor);
 774     },
 775  
 776     _renderBorder: function(el,bgColor) {
 777        var borderValue = "1px solid " + this._borderColor(bgColor);
 778        var borderL = "border-left: "  + borderValue;
 779        var borderR = "border-right: " + borderValue;
 780        var style   = "style='" + borderL + ";" + borderR +  "'";
 781        el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>"
 782     },
 783  
 784     _roundTopCorners: function(el, color, bgColor) {
 785        var corner = this._createCorner(bgColor);
 786        for(var i=0 ; i < this.options.numSlices ; i++ )
 787           corner.appendChild(this._createCornerSlice(color,bgColor,i,"top"));
 788        el.style.paddingTop = 0;
 789        el.insertBefore(corner,el.firstChild);
 790     },
 791  
 792     _roundBottomCorners: function(el, color, bgColor) {
 793        var corner = this._createCorner(bgColor);
 794        for(var i=(this.options.numSlices-1) ; i >= 0 ; i-- )
 795           corner.appendChild(this._createCornerSlice(color,bgColor,i,"bottom"));
 796        el.style.paddingBottom = 0;
 797        el.appendChild(corner);
 798     },
 799  
 800     _createCorner: function(bgColor) {
 801        var corner = document.createElement("div");
 802        corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor);
 803        return corner;
 804     },
 805  
 806     _createCornerSlice: function(color,bgColor, n, position) {
 807        var slice = document.createElement("span");
 808  
 809        var inStyle = slice.style;
 810        inStyle.backgroundColor = color;
 811        inStyle.display  = "block";
 812        inStyle.height   = "1px";
 813        inStyle.overflow = "hidden";
 814        inStyle.fontSize = "1px";
 815  
 816        var borderColor = this._borderColor(color,bgColor);
 817        if ( this.options.border && n == 0 ) {
 818           inStyle.borderTopStyle    = "solid";
 819           inStyle.borderTopWidth    = "1px";
 820           inStyle.borderLeftWidth   = "0px";
 821           inStyle.borderRightWidth  = "0px";
 822           inStyle.borderBottomWidth = "0px";
 823           inStyle.height            = "0px"; // assumes css compliant box model
 824           inStyle.borderColor       = borderColor;
 825        }
 826        else if(borderColor) {
 827           inStyle.borderColor = borderColor;
 828           inStyle.borderStyle = "solid";
 829           inStyle.borderWidth = "0px 1px";
 830        }
 831  
 832        if ( !this.options.compact && (n == (this.options.numSlices-1)) )
 833           inStyle.height = "2px";
 834  
 835        this._setMargin(slice, n, position);
 836        this._setBorder(slice, n, position);
 837        return slice;
 838     },
 839  
 840     _setOptions: function(options) {
 841        this.options = {
 842           corners : "all",
 843           color   : "fromElement",
 844           bgColor : "fromParent",
 845           blend   : true,
 846           border  : false,
 847           compact : false
 848        }
 849        Object.extend(this.options, options || {});
 850  
 851        this.options.numSlices = this.options.compact ? 2 : 4;
 852        if ( this._isTransparent() )
 853           this.options.blend = false;
 854     },
 855  
 856     _whichSideTop: function() {
 857        if ( this._hasString(this.options.corners, "all", "top") )
 858           return "";
 859  
 860        if ( this.options.corners.indexOf("tl") >= 0 && this.options.corners.indexOf("tr") >= 0 )
 861           return "";
 862  
 863        if (this.options.corners.indexOf("tl") >= 0)
 864           return "left";
 865        else if (this.options.corners.indexOf("tr") >= 0)
 866            return "right";
 867        return "";
 868     },
 869  
 870     _whichSideBottom: function() {
 871        if ( this._hasString(this.options.corners, "all", "bottom") )
 872           return "";
 873  
 874        if ( this.options.corners.indexOf("bl")>=0 && this.options.corners.indexOf("br")>=0 )
 875           return "";
 876  
 877        if(this.options.corners.indexOf("bl") >=0)
 878           return "left";
 879        else if(this.options.corners.indexOf("br")>=0)
 880           return "right";
 881        return "";
 882     },
 883  
 884     _borderColor : function(color,bgColor) {
 885        if ( color == "transparent" )
 886           return bgColor;
 887        else if ( this.options.border )
 888           return this.options.border;
 889        else if ( this.options.blend )
 890           return this._blend( bgColor, color );
 891        else
 892           return "";
 893     },
 894  
 895  
 896     _setMargin: function(el, n, corners) {
 897        var marginSize = this._marginSize(n);
 898        var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
 899  
 900        if ( whichSide == "left" ) {
 901           el.style.marginLeft = marginSize + "px"; el.style.marginRight = "0px";
 902        }
 903        else if ( whichSide == "right" ) {
 904           el.style.marginRight = marginSize + "px"; el.style.marginLeft  = "0px";
 905        }
 906        else {
 907           el.style.marginLeft = marginSize + "px"; el.style.marginRight = marginSize + "px";
 908        }
 909     },
 910  
 911     _setBorder: function(el,n,corners) {
 912        var borderSize = this._borderSize(n);
 913        var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
 914        if ( whichSide == "left" ) {
 915           el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = "0px";
 916        }
 917        else if ( whichSide == "right" ) {
 918           el.style.borderRightWidth = borderSize + "px"; el.style.borderLeftWidth  = "0px";
 919        }
 920        else {
 921           el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
 922        }
 923        if (this.options.border != false)
 924          el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
 925     },
 926  
 927     _marginSize: function(n) {
 928        if ( this._isTransparent() )
 929           return 0;
 930  
 931        var marginSizes          = [ 5, 3, 2, 1 ];
 932        var blendedMarginSizes   = [ 3, 2, 1, 0 ];
 933        var compactMarginSizes   = [ 2, 1 ];
 934        var smBlendedMarginSizes = [ 1, 0 ];
 935  
 936        if ( this.options.compact && this.options.blend )
 937           return smBlendedMarginSizes[n];
 938        else if ( this.options.compact )
 939           return compactMarginSizes[n];
 940        else if ( this.options.blend )
 941           return blendedMarginSizes[n];
 942        else
 943           return marginSizes[n];
 944     },
 945  
 946     _borderSize: function(n) {
 947        var transparentBorderSizes = [ 5, 3, 2, 1 ];
 948        var blendedBorderSizes     = [ 2, 1, 1, 1 ];
 949        var compactBorderSizes     = [ 1, 0 ];
 950        var actualBorderSizes      = [ 0, 2, 0, 0 ];
 951  
 952        if ( this.options.compact && (this.options.blend || this._isTransparent()) )
 953           return 1;
 954        else if ( this.options.compact )
 955           return compactBorderSizes[n];
 956        else if ( this.options.blend )
 957           return blendedBorderSizes[n];
 958        else if ( this.options.border )
 959           return actualBorderSizes[n];
 960        else if ( this._isTransparent() )
 961           return transparentBorderSizes[n];
 962        return 0;
 963     },
 964  
 965     _hasString: function(str) { for(var i=1 ; i<arguments.length ; i++) if (str.indexOf(arguments[i]) >= 0) return true; return false; },
 966     _blend: function(c1, c2) { var cc1 = Rico.Color.createFromHex(c1); cc1.blend(Rico.Color.createFromHex(c2)); return cc1; },
 967     _background: function(el) { try { return Rico.Color.createColorFromBackground(el).asHex(); } catch(err) { return "#ffffff"; } },
 968     _isTransparent: function() { return this.options.color == "transparent"; },
 969     _isTopRounded: function() { return this._hasString(this.options.corners, "all", "top", "tl", "tr"); },
 970     _isBottomRounded: function() { return this._hasString(this.options.corners, "all", "bottom", "bl", "br"); },
 971     _hasSingleTextChild: function(el) { return el.childNodes.length == 1 && el.childNodes[0].nodeType == 3; }
 972  }
 973  
 974  
 975  //-------------------- ricoDragAndDrop.js
 976  /*
 977  Rico.DragAndDrop = Class.create();
 978  
 979  Rico.DragAndDrop.prototype = {
 980  
 981     initialize: function() {
 982        this.dropZones                = new Array();
 983        this.draggables               = new Array();
 984        this.currentDragObjects       = new Array();
 985        this.dragElement              = null;
 986        this.lastSelectedDraggable    = null;
 987        this.currentDragObjectVisible = false;
 988        this.interestedInMotionEvents = false;
 989        this._mouseDown = this._mouseDownHandler.bindAsEventListener(this);
 990        this._mouseMove = this._mouseMoveHandler.bindAsEventListener(this);
 991        this._mouseUp = this._mouseUpHandler.bindAsEventListener(this);
 992     },
 993  
 994     registerDropZone: function(aDropZone) {
 995        this.dropZones[ this.dropZones.length ] = aDropZone;
 996     },
 997  
 998     deregisterDropZone: function(aDropZone) {
 999        var newDropZones = new Array();
1000        var j = 0;
1001        for ( var i = 0 ; i < this.dropZones.length ; i++ ) {
1002           if ( this.dropZones[i] != aDropZone )
1003              newDropZones[j++] = this.dropZones[i];
1004        }
1005  
1006        this.dropZones = newDropZones;
1007     },
1008  
1009     clearDropZones: function() {
1010        this.dropZones = new Array();
1011     },
1012  
1013     registerDraggable: function( aDraggable ) {
1014        this.draggables[ this.draggables.length ] = aDraggable;
1015        this._addMouseDownHandler( aDraggable );
1016     },
1017  
1018     clearSelection: function() {
1019        for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
1020           this.currentDragObjects[i].deselect();
1021        this.currentDragObjects = new Array();
1022        this.lastSelectedDraggable = null;
1023     },
1024  
1025     hasSelection: function() {
1026        return this.currentDragObjects.length > 0;
1027     },
1028  
1029     setStartDragFromElement: function( e, mouseDownElement ) {
1030        this.origPos = RicoUtil.toDocumentPosition(mouseDownElement);
1031        this.startx = e.screenX - this.origPos.x
1032        this.starty = e.screenY - this.origPos.y
1033        //this.startComponentX = e.layerX ? e.layerX : e.offsetX;
1034        //this.startComponentY = e.layerY ? e.layerY : e.offsetY;
1035        //this.adjustedForDraggableSize = false;
1036  
1037        this.interestedInMotionEvents = this.hasSelection();
1038        this._terminateEvent(e);
1039     },
1040  
1041     updateSelection: function( draggable, extendSelection ) {
1042        if ( ! extendSelection )
1043           this.clearSelection();
1044  
1045        if ( draggable.isSelected() ) {
1046           this.currentDragObjects.removeItem(draggable);
1047           draggable.deselect();
1048           if ( draggable == this.lastSelectedDraggable )
1049              this.lastSelectedDraggable = null;
1050        }
1051        else {
1052           this.currentDragObjects[ this.currentDragObjects.length ] = draggable;
1053           draggable.select();
1054           this.lastSelectedDraggable = draggable;
1055        }
1056     },
1057  
1058     _mouseDownHandler: function(e) {
1059        if ( arguments.length == 0 )
1060           e = event;
1061  
1062        // if not button 1 ignore it...
1063        var nsEvent = e.which != undefined;
1064        if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
1065           return;
1066  
1067        var eventTarget      = e.target ? e.target : e.srcElement;
1068        var draggableObject  = eventTarget.draggable;
1069  
1070        var candidate = eventTarget;
1071        while (draggableObject == null && candidate.parentNode) {
1072           candidate = candidate.parentNode;
1073           draggableObject = candidate.draggable;
1074        }
1075  
1076        if ( draggableObject == null )
1077           return;
1078  
1079        this.updateSelection( draggableObject, e.ctrlKey );
1080  
1081        // clear the drop zones postion cache...
1082        if ( this.hasSelection() )
1083           for ( var i = 0 ; i < this.dropZones.length ; i++ )
1084              this.dropZones[i].clearPositionCache();
1085  
1086        this.setStartDragFromElement( e, draggableObject.getMouseDownHTMLElement() );
1087     },
1088  
1089  
1090     _mouseMoveHandler: function(e) {
1091        var nsEvent = e.which != undefined;
1092        if ( !this.interestedInMotionEvents ) {
1093           //this._terminateEvent(e);
1094           return;
1095        }
1096  
1097        if ( ! this.hasSelection() )
1098           return;
1099  
1100        if ( ! this.currentDragObjectVisible )
1101           this._startDrag(e);
1102  
1103        if ( !this.activatedDropZones )
1104           this._activateRegisteredDropZones();
1105  
1106        //if ( !this.adjustedForDraggableSize )
1107        //   this._adjustForDraggableSize(e);
1108  
1109        this._updateDraggableLocation(e);
1110        this._updateDropZonesHover(e);
1111  
1112        this._terminateEvent(e);
1113     },
1114  
1115     _makeDraggableObjectVisible: function(e)
1116     {
1117        if ( !this.hasSelection() )
1118           return;
1119  
1120        var dragElement;
1121        if ( this.currentDragObjects.length > 1 )
1122           dragElement = this.currentDragObjects[0].getMultiObjectDragGUI(this.currentDragObjects);
1123        else
1124           dragElement = this.currentDragObjects[0].getSingleObjectDragGUI();
1125  
1126        // go ahead and absolute position it...
1127        if ( RicoUtil.getElementsComputedStyle(dragElement, "position")  != "absolute" )
1128           dragElement.style.position = "absolute";
1129  
1130        // need to parent him into the document...
1131        if ( dragElement.parentNode == null || dragElement.parentNode.nodeType == 11 )
1132           document.body.appendChild(dragElement);
1133  
1134        this.dragElement = dragElement;
1135        this._updateDraggableLocation(e);
1136  
1137        this.currentDragObjectVisible = true;
1138     },
1139  
1140     /**
1141     _adjustForDraggableSize: function(e) {
1142        var dragElementWidth  = this.dragElement.offsetWidth;
1143        var dragElementHeight = this.dragElement.offsetHeight;
1144        if ( this.startComponentX > dragElementWidth )
1145           this.startx -= this.startComponentX - dragElementWidth + 2;
1146        if ( e.offsetY ) {
1147           if ( this.startComponentY > dragElementHeight )
1148              this.starty -= this.startComponentY - dragElementHeight + 2;
1149        }
1150        this.adjustedForDraggableSize = true;
1151     },
1152     **/
1153  /*
1154     _updateDraggableLocation: function(e) {
1155        var dragObjectStyle = this.dragElement.style;
1156        dragObjectStyle.left = (e.screenX - this.startx) + "px"
1157        dragObjectStyle.top  = (e.screenY - this.starty) + "px";
1158     },
1159  
1160     _updateDropZonesHover: function(e) {
1161        var n = this.dropZones.length;
1162        for ( var i = 0 ; i < n ; i++ ) {
1163           if ( ! this._mousePointInDropZone( e, this.dropZones[i] ) )
1164              this.dropZones[i].hideHover();
1165        }
1166  
1167        for ( var i = 0 ; i < n ; i++ ) {
1168           if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
1169              if ( this.dropZones[i].canAccept(this.currentDragObjects) )
1170                 this.dropZones[i].showHover();
1171           }
1172        }
1173     },
1174  
1175     _startDrag: function(e) {
1176        for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
1177           this.currentDragObjects[i].startDrag();
1178  
1179        this._makeDraggableObjectVisible(e);
1180     },
1181  
1182     _mouseUpHandler: function(e) {
1183        if ( ! this.hasSelection() )
1184           return;
1185  
1186        var nsEvent = e.which != undefined;
1187        if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
1188           return;
1189  
1190        this.interestedInMotionEvents = false;
1191  
1192        if ( this.dragElement == null ) {
1193           this._terminateEvent(e);
1194           return;
1195        }
1196  
1197        if ( this._placeDraggableInDropZone(e) )
1198           this._completeDropOperation(e);
1199        else {
1200           this._terminateEvent(e);
1201           new Effect.Position( this.dragElement,
1202                                this.origPos.x,
1203                                this.origPos.y,
1204                                200,
1205                                20,
1206                                { complete : this._doCancelDragProcessing.bind(this) } );
1207        }
1208  
1209       Event.stopObserving(document.body, "mousemove", this._mouseMove);
1210       Event.stopObserving(document.body, "mouseup",  this._mouseUp);
1211     },
1212  
1213     _retTrue: function () {
1214        return true;
1215     },
1216  
1217     _completeDropOperation: function(e) {
1218        if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() ) {
1219           if ( this.dragElement.parentNode != null )
1220              this.dragElement.parentNode.removeChild(this.dragElement);
1221        }
1222  
1223        this._deactivateRegisteredDropZones();
1224        this._endDrag();
1225        this.clearSelection();
1226        this.dragElement = null;
1227        this.currentDragObjectVisible = false;
1228        this._terminateEvent(e);
1229     },
1230  
1231     _doCancelDragProcessing: function() {
1232        this._cancelDrag();
1233  
1234          if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() && this.dragElement)
1235             if ( this.dragElement.parentNode != null )
1236                this.dragElement.parentNode.removeChild(this.dragElement);
1237  
1238  
1239        this._deactivateRegisteredDropZones();
1240        this.dragElement = null;
1241        this.currentDragObjectVisible = false;
1242     },
1243  
1244     _placeDraggableInDropZone: function(e) {
1245        var foundDropZone = false;
1246        var n = this.dropZones.length;
1247        for ( var i = 0 ; i < n ; i++ ) {
1248           if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
1249              if ( this.dropZones[i].canAccept(this.currentDragObjects) ) {
1250                 this.dropZones[i].hideHover();
1251                 this.dropZones[i].accept(this.currentDragObjects);
1252                 foundDropZone = true;
1253                 break;
1254              }
1255           }
1256        }
1257  
1258        return foundDropZone;
1259     },
1260  
1261     _cancelDrag: function() {
1262        for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
1263           this.currentDragObjects[i].cancelDrag();
1264     },
1265  
1266     _endDrag: function() {
1267        for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
1268           this.currentDragObjects[i].endDrag();
1269     },
1270  
1271     _mousePointInDropZone: function( e, dropZone ) {
1272  
1273        var absoluteRect = dropZone.getAbsoluteRect();
1274  
1275        return e.clientX  > absoluteRect.left  &&
1276               e.clientX  < absoluteRect.right &&
1277               e.clientY  > absoluteRect.top   &&
1278               e.clientY  < absoluteRect.bottom;
1279     },
1280  
1281     _addMouseDownHandler: function( aDraggable )
1282     {
1283         htmlElement  = aDraggable.getMouseDownHTMLElement();
1284        if ( htmlElement  != null ) {
1285           htmlElement.draggable = aDraggable;
1286           Event.observe(htmlElement , "mousedown", this._onmousedown.bindAsEventListener(this));
1287           Event.observe(htmlElement, "mousedown", this._mouseDown);
1288        }
1289     },
1290  
1291     _activateRegisteredDropZones: function() {
1292        var n = this.dropZones.length;
1293        for ( var i = 0 ; i < n ; i++ ) {
1294           var dropZone = this.dropZones[i];
1295           if ( dropZone.canAccept(this.currentDragObjects) )
1296              dropZone.activate();
1297        }
1298  
1299        this.activatedDropZones = true;
1300     },
1301  
1302     _deactivateRegisteredDropZones: function() {
1303        var n = this.dropZones.length;
1304        for ( var i = 0 ; i < n ; i++ )
1305           this.dropZones[i].deactivate();
1306        this.activatedDropZones = false;
1307     },
1308  
1309     _onmousedown: function () {
1310       Event.observe(document.body, "mousemove", this._mouseMove);
1311       Event.observe(document.body, "mouseup",  this._mouseUp);
1312     },
1313  
1314     _terminateEvent: function(e) {
1315        if ( e.stopPropagation != undefined )
1316           e.stopPropagation();
1317        else if ( e.cancelBubble != undefined )
1318           e.cancelBubble = true;
1319  
1320        if ( e.preventDefault != undefined )
1321           e.preventDefault();
1322        else
1323           e.returnValue = false;
1324     }
1325  
1326  }
1327  
1328  Rico.Draggable = Class.create();
1329  
1330  Rico.Draggable.prototype = {
1331  
1332     initialize: function( type, htmlElement ) {
1333        this.type          = type;
1334        this.htmlElement   = $(htmlElement);
1335        this.selected      = false;
1336     },
1337  
1338     /**
1339      *   Returns the HTML element that should have a mouse down event
1340      *   added to it in order to initiate a drag operation
1341      *
1342      **//*
1343     getMouseDownHTMLElement: function() {
1344        return this.htmlElement;
1345     },
1346  
1347     select: function() {
1348        this.selected = true;
1349  
1350        if ( this.showingSelected )
1351           return;
1352  
1353        var htmlElement = this.getMouseDownHTMLElement();
1354  
1355        var color = Rico.Color.createColorFromBackground(htmlElement);
1356        color.isBright() ? color.darken(0.033) : color.brighten(0.033);
1357  
1358        this.saveBackground = RicoUtil.getElementsComputedStyle(htmlElement, "backgroundColor", "background-color");
1359        htmlElement.style.backgroundColor = color.asHex();
1360        this.showingSelected = true;
1361     },
1362  
1363     deselect: function() {
1364        this.selected = false;
1365        if ( !this.showingSelected )
1366           return;
1367  
1368        var htmlElement = this.getMouseDownHTMLElement();
1369  
1370        htmlElement.style.backgroundColor = this.saveBackground;
1371        this.showingSelected = false;
1372     },
1373  
1374     isSelected: function() {
1375        return this.selected;
1376     },
1377  
1378     startDrag: function() {
1379     },
1380  
1381     cancelDrag: function() {
1382     },
1383  
1384     endDrag: function() {
1385     },
1386  
1387     getSingleObjectDragGUI: function() {
1388        return this.htmlElement;
1389     },
1390  
1391     getMultiObjectDragGUI: function( draggables ) {
1392        return this.htmlElement;
1393     },
1394  
1395     getDroppedGUI: function() {
1396        return this.htmlElement;
1397     },
1398  
1399     toString: function() {
1400        return this.type + ":" + this.htmlElement + ":";
1401     }
1402  
1403  }
1404  
1405  Rico.Dropzone = Class.create();
1406  
1407  Rico.Dropzone.prototype = {
1408  
1409     initialize: function( htmlElement ) {
1410        this.htmlElement  = $(htmlElement);
1411        this.absoluteRect = null;
1412     },
1413  
1414     getHTMLElement: function() {
1415        return this.htmlElement;
1416     },
1417  
1418     clearPositionCache: function() {
1419        this.absoluteRect = null;
1420     },
1421  
1422     getAbsoluteRect: function() {
1423        if ( this.absoluteRect == null ) {
1424           var htmlElement = this.getHTMLElement();
1425           var pos = RicoUtil.toViewportPosition(htmlElement);
1426  
1427           this.absoluteRect = {
1428              top:    pos.y,
1429              left:   pos.x,
1430              bottom: pos.y + htmlElement.offsetHeight,
1431              right:  pos.x + htmlElement.offsetWidth
1432           };
1433        }
1434        return this.absoluteRect;
1435     },
1436  
1437     activate: function() {
1438        var htmlElement = this.getHTMLElement();
1439        if (htmlElement == null  || this.showingActive)
1440           return;
1441  
1442        this.showingActive = true;
1443        this.saveBackgroundColor = htmlElement.style.backgroundColor;
1444  
1445        var fallbackColor = "#ffea84";
1446        var currentColor = Rico.Color.createColorFromBackground(htmlElement);
1447        if ( currentColor == null )
1448           htmlElement.style.backgroundColor = fallbackColor;
1449        else {
1450           currentColor.isBright() ? currentColor.darken(0.2) : currentColor.brighten(0.2);
1451           htmlElement.style.backgroundColor = currentColor.asHex();
1452        }
1453     },
1454  
1455     deactivate: function() {
1456        var htmlElement = this.getHTMLElement();
1457        if (htmlElement == null || !this.showingActive)
1458           return;
1459  
1460        htmlElement.style.backgroundColor = this.saveBackgroundColor;
1461        this.showingActive = false;
1462        this.saveBackgroundColor = null;
1463     },
1464  
1465     showHover: function() {
1466        var htmlElement = this.getHTMLElement();
1467        if ( htmlElement == null || this.showingHover )
1468           return;
1469  
1470        this.saveBorderWidth = htmlElement.style.borderWidth;
1471        this.saveBorderStyle = htmlElement.style.borderStyle;
1472        this.saveBorderColor = htmlElement.style.borderColor;
1473  
1474        this.showingHover = true;
1475        htmlElement.style.borderWidth = "1px";
1476        htmlElement.style.borderStyle = "solid";
1477        //htmlElement.style.borderColor = "#ff9900";
1478        htmlElement.style.borderColor = "#ffff00";
1479     },
1480  
1481     hideHover: function() {
1482        var htmlElement = this.getHTMLElement();
1483        if ( htmlElement == null || !this.showingHover )
1484           return;
1485  
1486        htmlElement.style.borderWidth = this.saveBorderWidth;
1487        htmlElement.style.borderStyle = this.saveBorderStyle;
1488        htmlElement.style.borderColor = this.saveBorderColor;
1489        this.showingHover = false;
1490     },
1491  
1492     canAccept: function(draggableObjects) {
1493        return true;
1494     },
1495  
1496     accept: function(draggableObjects) {
1497        var htmlElement = this.getHTMLElement();
1498        if ( htmlElement == null )
1499           return;
1500  
1501        n = draggableObjects.length;
1502        for ( var i = 0 ; i < n ; i++ )
1503        {
1504           var theGUI = draggableObjects[i].getDroppedGUI();
1505           if ( RicoUtil.getElementsComputedStyle( theGUI, "position" ) == "absolute" )
1506           {
1507              theGUI.style.position = "static";
1508              theGUI.style.top = "";
1509              theGUI.style.top = "";
1510           }
1511           htmlElement.appendChild(theGUI);
1512        }
1513     }
1514  }
1515  
1516  var dndMgr = new Rico.DragAndDrop();
1517  
1518  
1519  
1520  //-------------------- ricoDraggable.js
1521  Rico.Draggable = Class.create();
1522  
1523  Rico.Draggable.prototype = {
1524  
1525     initialize: function( type, htmlElement ) {
1526        this.type          = type;
1527        this.htmlElement   = $(htmlElement);
1528        this.selected      = false;
1529     },
1530  
1531     /**
1532      *   Returns the HTML element that should have a mouse down event
1533      *   added to it in order to initiate a drag operation
1534      *
1535      **//*
1536     getMouseDownHTMLElement: function() {
1537        return this.htmlElement;
1538     },
1539  
1540     select: function() {
1541        this.selected = true;
1542  
1543        if ( this.showingSelected )
1544           return;
1545  
1546        var htmlElement = this.getMouseDownHTMLElement();
1547  
1548        var color = Rico.Color.createColorFromBackground(htmlElement);
1549        color.isBright() ? color.darken(0.033) : color.brighten(0.033);
1550  
1551        this.saveBackground = RicoUtil.getElementsComputedStyle(htmlElement, "backgroundColor", "background-color");
1552        htmlElement.style.backgroundColor = color.asHex();
1553        this.showingSelected = true;
1554     },
1555  
1556     deselect: function() {
1557        this.selected = false;
1558        if ( !this.showingSelected )
1559           return;
1560  
1561        var htmlElement = this.getMouseDownHTMLElement();
1562  
1563        htmlElement.style.backgroundColor = this.saveBackground;
1564        this.showingSelected = false;
1565     },
1566  
1567     isSelected: function() {
1568        return this.selected;
1569     },
1570  
1571     startDrag: function() {
1572     },
1573  
1574     cancelDrag: function() {
1575     },
1576  
1577     endDrag: function() {
1578     },
1579  
1580     getSingleObjectDragGUI: function() {
1581        return this.htmlElement;
1582     },
1583  
1584     getMultiObjectDragGUI: function( draggables ) {
1585        return this.htmlElement;
1586     },
1587  
1588     getDroppedGUI: function() {
1589        return this.htmlElement;
1590     },
1591  
1592     toString: function() {
1593        return this.type + ":" + this.htmlElement + ":";
1594     }
1595  
1596  }
1597  
1598  
1599  //-------------------- ricoDropzone.js
1600  Rico.Dropzone = Class.create();
1601  
1602  Rico.Dropzone.prototype = {
1603  
1604     initialize: function( htmlElement ) {
1605        this.htmlElement  = $(htmlElement);
1606        this.absoluteRect = null;
1607     },
1608  
1609     getHTMLElement: function() {
1610        return this.htmlElement;
1611     },
1612  
1613     clearPositionCache: function() {
1614        this.absoluteRect = null;
1615     },
1616  
1617     getAbsoluteRect: function() {
1618        if ( this.absoluteRect == null ) {
1619           var htmlElement = this.getHTMLElement();
1620           var pos = RicoUtil.toViewportPosition(htmlElement);
1621  
1622           this.absoluteRect = {
1623              top:    pos.y,
1624              left:   pos.x,
1625              bottom: pos.y + htmlElement.offsetHeight,
1626              right:  pos.x + htmlElement.offsetWidth
1627           };
1628        }
1629        return this.absoluteRect;
1630     },
1631  
1632     activate: function() {
1633        var htmlElement = this.getHTMLElement();
1634        if (htmlElement == null  || this.showingActive)
1635           return;
1636  
1637        this.showingActive = true;
1638        this.saveBackgroundColor = htmlElement.style.backgroundColor;
1639  
1640        var fallbackColor = "#ffea84";
1641        var currentColor = Rico.Color.createColorFromBackground(htmlElement);
1642        if ( currentColor == null )
1643           htmlElement.style.backgroundColor = fallbackColor;
1644        else {
1645           currentColor.isBright() ? currentColor.darken(0.2) : currentColor.brighten(0.2);
1646           htmlElement.style.backgroundColor = currentColor.asHex();
1647        }
1648     },
1649  
1650     deactivate: function() {
1651        var htmlElement = this.getHTMLElement();
1652        if (htmlElement == null || !this.showingActive)
1653           return;
1654  
1655        htmlElement.style.backgroundColor = this.saveBackgroundColor;
1656        this.showingActive = false;
1657        this.saveBackgroundColor = null;
1658     },
1659  
1660     showHover: function() {
1661        var htmlElement = this.getHTMLElement();
1662        if ( htmlElement == null || this.showingHover )
1663           return;
1664  
1665        this.saveBorderWidth = htmlElement.style.borderWidth;
1666        this.saveBorderStyle = htmlElement.style.borderStyle;
1667        this.saveBorderColor = htmlElement.style.borderColor;
1668  
1669        this.showingHover = true;
1670        htmlElement.style.borderWidth = "1px";
1671        htmlElement.style.borderStyle = "solid";
1672        //htmlElement.style.borderColor = "#ff9900";
1673        htmlElement.style.borderColor = "#ffff00";
1674     },
1675  
1676     hideHover: function() {
1677        var htmlElement = this.getHTMLElement();
1678        if ( htmlElement == null || !this.showingHover )
1679           return;
1680  
1681        htmlElement.style.borderWidth = this.saveBorderWidth;
1682        htmlElement.style.borderStyle = this.saveBorderStyle;
1683        htmlElement.style.borderColor = this.saveBorderColor;
1684        this.showingHover = false;
1685     },
1686  
1687     canAccept: function(draggableObjects) {
1688        return true;
1689     },
1690  
1691     accept: function(draggableObjects) {
1692        var htmlElement = this.getHTMLElement();
1693        if ( htmlElement == null )
1694           return;
1695  
1696        n = draggableObjects.length;
1697        for ( var i = 0 ; i < n ; i++ )
1698        {
1699           var theGUI = draggableObjects[i].getDroppedGUI();
1700           if ( RicoUtil.getElementsComputedStyle( theGUI, "position" ) == "absolute" )
1701           {
1702              theGUI.style.position = "static";
1703              theGUI.style.top = "";
1704              theGUI.style.top = "";
1705           }
1706           htmlElement.appendChild(theGUI);
1707        }
1708     }
1709  }
1710  */
1711  
1712  
1713  //-------------------- ricoEffect.js
1714  
1715  /**
1716    *  Use the Effect namespace for effects.  If using scriptaculous effects
1717    *  this will already be defined, otherwise we'll just create an empty
1718    *  object for it...
1719   **/
1720  if ( window.Effect == undefined )
1721     Effect = {};
1722  
1723  Effect.SizeAndPosition = Class.create();
1724  Effect.SizeAndPosition.prototype = {
1725  
1726     initialize: function(element, x, y, w, h, duration, steps, options) {
1727        this.element = $(element);
1728        this.x = x;
1729        this.y = y;
1730        this.w = w;
1731        this.h = h;
1732        this.duration = duration;
1733        this.steps    = steps;
1734        this.options  = arguments[7] || {};
1735  
1736        this.sizeAndPosition();
1737     },
1738  
1739     sizeAndPosition: function() {
1740        if (this.isFinished()) {
1741           if(this.options.complete) this.options.complete(this);
1742           return;
1743        }
1744  
1745        if (this.timer)
1746           clearTimeout(this.timer);
1747  
1748        var stepDuration = Math.round(this.duration/this.steps) ;
1749  
1750        // Get original values: x,y = top left corner;  w,h = width height
1751        var currentX = this.element.offsetLeft;
1752        var currentY = this.element.offsetTop;
1753        var currentW = this.element.offsetWidth;
1754        var currentH = this.element.offsetHeight;
1755  
1756        // If values not set, or zero, we do not modify them, and take original as final as well
1757        this.x = (this.x) ? this.x : currentX;
1758        this.y = (this.y) ? this.y : currentY;
1759        this.w = (this.w) ? this.w : currentW;
1760        this.h = (this.h) ? this.h : currentH;
1761  
1762        // how much do we need to modify our values for each step?
1763        var difX = this.steps >  0 ? (this.x - currentX)/this.steps : 0;
1764        var difY = this.steps >  0 ? (this.y - currentY)/this.steps : 0;
1765        var difW = this.steps >  0 ? (this.w - currentW)/this.steps : 0;
1766        var difH = this.steps >  0 ? (this.h - currentH)/this.steps : 0;
1767  
1768        this.moveBy(difX, difY);
1769        this.resizeBy(difW, difH);
1770  
1771        this.duration -= stepDuration;
1772        this.steps--;
1773  
1774        this.timer = setTimeout(this.sizeAndPosition.bind(this), stepDuration);
1775     },
1776  
1777     isFinished: function() {
1778        return this.steps <= 0;
1779     },
1780  
1781     moveBy: function( difX, difY ) {
1782        var currentLeft = this.element.offsetLeft;
1783        var currentTop  = this.element.offsetTop;
1784        var intDifX     = parseInt(difX);
1785        var intDifY     = parseInt(difY);
1786  
1787        var style = this.element.style;
1788        if ( intDifX != 0 )
1789           style.left = (currentLeft + intDifX) + "px";
1790        if ( intDifY != 0 )
1791           style.top  = (currentTop + intDifY) + "px";
1792     },
1793  
1794     resizeBy: function( difW, difH ) {
1795        var currentWidth  = this.element.offsetWidth;
1796        var currentHeight = this.element.offsetHeight;
1797        var intDifW       = parseInt(difW);
1798        var intDifH       = parseInt(difH);
1799  
1800        var style = this.element.style;
1801        if ( intDifW != 0 )
1802           style.width   = (currentWidth  + intDifW) + "px";
1803        if ( intDifH != 0 )
1804           style.height  = (currentHeight + intDifH) + "px";
1805     }
1806  }
1807  
1808  Effect.Size = Class.create();
1809  Effect.Size.prototype = {
1810  
1811     initialize: function(element, w, h, duration, steps, options) {
1812        new Effect.SizeAndPosition(element, null, null, w, h, duration, steps, options);
1813    }
1814  }
1815  
1816  Effect.Position = Class.create();
1817  Effect.Position.prototype = {
1818  
1819     initialize: function(element, x, y, duration, steps, options) {
1820        new Effect.SizeAndPosition(element, x, y, null, null, duration, steps, options);
1821    }
1822  }
1823  
1824  Effect.Round = Class.create();
1825  Effect.Round.prototype = {
1826  
1827     initialize: function(tagName, className, options) {
1828        var elements = document.getElementsByTagAndClassName(tagName,className);
1829        for ( var i = 0 ; i < elements.length ; i++ )
1830           Rico.Corner.round( elements[i], options );
1831     }
1832  };
1833  
1834  Effect.FadeTo = Class.create();
1835  Effect.FadeTo.prototype = {
1836  
1837     initialize: function( element, opacity, duration, steps, options) {
1838        this.element  = $(element);
1839        this.opacity  = opacity;
1840        this.duration = duration;
1841        this.steps    = steps;
1842        this.options  = arguments[4] || {};
1843        this.fadeTo();
1844     },
1845  
1846     fadeTo: function() {
1847        if (this.isFinished()) {
1848           if(this.options.complete) this.options.complete(this);
1849           return;
1850        }
1851  
1852        if (this.timer)
1853           clearTimeout(this.timer);
1854  
1855        var stepDuration = Math.round(this.duration/this.steps) ;
1856        var currentOpacity = this.getElementOpacity();
1857        var delta = this.steps > 0 ? (this.opacity - currentOpacity)/this.steps : 0;
1858  
1859        this.changeOpacityBy(delta);
1860        this.duration -= stepDuration;
1861        this.steps--;
1862  
1863        this.timer = setTimeout(this.fadeTo.bind(this), stepDuration);
1864     },
1865  
1866     changeOpacityBy: function(v) {
1867        var currentOpacity = this.getElementOpacity();
1868        var newOpacity = Math.max(0, Math.min(currentOpacity+v, 1));
1869        this.element.ricoOpacity = newOpacity;
1870  
1871        this.element.style.filter = "alpha(opacity:"+Math.round(newOpacity*100)+")";
1872        this.element.style.opacity = newOpacity; /*//*/;
1873     },
1874  
1875     isFinished: function() {
1876        return this.steps <= 0;
1877     },
1878  
1879     getElementOpacity: function() {
1880        if ( this.element.ricoOpacity == undefined ) {
1881           var opacity = RicoUtil.getElementsComputedStyle(this.element, 'opacity');
1882           this.element.ricoOpacity = opacity != undefined ? opacity : 1.0;
1883        }
1884        return parseFloat(this.element.ricoOpacity);
1885     }
1886  }
1887  
1888  Effect.AccordionSize = Class.create();
1889  
1890  Effect.AccordionSize.prototype = {
1891  
1892     initialize: function(e1, e2, start, end, duration, steps, options) {
1893        this.e1       = $(e1);
1894        this.e2       = $(e2);
1895        this.start    = start;
1896        this.end      = end;
1897        this.duration = duration;
1898        this.steps    = steps;
1899        this.options  = arguments[6] || {};
1900  
1901        this.accordionSize();
1902     },
1903  
1904     accordionSize: function() {
1905  
1906        if (this.isFinished()) {
1907           // just in case there are round errors or such...
1908           this.e1.style.height = this.start + "px";
1909           this.e2.style.height = this.end + "px";
1910  
1911           if(this.options.complete)
1912              this.options.complete(this);
1913           return;
1914        }
1915  
1916        if (this.timer)
1917           clearTimeout(this.timer);
1918  
1919        var stepDuration = Math.round(this.duration/this.steps) ;
1920  
1921        var diff = this.steps > 0 ? (parseInt(this.e1.offsetHeight) - this.start)/this.steps : 0;
1922        this.resizeBy(diff);
1923  
1924        this.duration -= stepDuration;
1925        this.steps--;
1926  
1927        this.timer = setTimeout(this.accordionSize.bind(this), stepDuration);
1928     },
1929  
1930     isFinished: function() {
1931        return this.steps <= 0;
1932     },
1933  
1934     resizeBy: function(diff) {
1935        var h1Height = this.e1.offsetHeight;
1936        var h2Height = this.e2.offsetHeight;
1937        var intDiff = parseInt(diff);
1938        if ( diff != 0 ) {
1939           this.e1.style.height = (h1Height - intDiff) + "px";
1940           this.e2.style.height = (h2Height + intDiff) + "px";
1941        }
1942     }
1943  
1944  };
1945  
1946  
1947  //-------------------- ricoEffects.js
1948  
1949  /**
1950    *  Use the Effect namespace for effects.  If using scriptaculous effects
1951    *  this will already be defined, otherwise we'll just create an empty
1952    *  object for it...
1953   **/
1954  if ( window.Effect == undefined )
1955     Effect = {};
1956  
1957  Effect.SizeAndPosition = Class.create();
1958  Effect.SizeAndPosition.prototype = {
1959  
1960     initialize: function(element, x, y, w, h, duration, steps, options) {
1961        this.element = $(element);
1962        this.x = x;
1963        this.y = y;
1964        this.w = w;
1965        this.h = h;
1966        this.duration = duration;
1967        this.steps    = steps;
1968        this.options  = arguments[7] || {};
1969  
1970        this.sizeAndPosition();
1971     },
1972  
1973     sizeAndPosition: function() {
1974        if (this.isFinished()) {
1975           if(this.options.complete) this.options.complete(this);
1976           return;
1977        }
1978  
1979        if (this.timer)
1980           clearTimeout(this.timer);
1981  
1982        var stepDuration = Math.round(this.duration/this.steps) ;
1983  
1984        // Get original values: x,y = top left corner;  w,h = width height
1985        var currentX = this.element.offsetLeft;
1986        var currentY = this.element.offsetTop;
1987        var currentW = this.element.offsetWidth;
1988        var currentH = this.element.offsetHeight;
1989  
1990        // If values not set, or zero, we do not modify them, and take original as final as well
1991        this.x = (this.x) ? this.x : currentX;
1992        this.y = (this.y) ? this.y : currentY;
1993        this.w = (this.w) ? this.w : currentW;
1994        this.h = (this.h) ? this.h : currentH;
1995  
1996        // how much do we need to modify our values for each step?
1997        var difX = this.steps >  0 ? (this.x - currentX)/this.steps : 0;
1998        var difY = this.steps >  0 ? (this.y - currentY)/this.steps : 0;
1999        var difW = this.steps >  0 ? (this.w - currentW)/this.steps : 0;
2000        var difH = this.steps >  0 ? (this.h - currentH)/this.steps : 0;
2001  
2002        this.moveBy(difX, difY);
2003        this.resizeBy(difW, difH);
2004  
2005        this.duration -= stepDuration;
2006        this.steps--;
2007  
2008        this.timer = setTimeout(this.sizeAndPosition.bind(this), stepDuration);
2009     },
2010  
2011     isFinished: function() {
2012        return this.steps <= 0;
2013     },
2014  
2015     moveBy: function( difX, difY ) {
2016        var currentLeft = this.element.offsetLeft;
2017        var currentTop  = this.element.offsetTop;
2018        var intDifX     = parseInt(difX);
2019        var intDifY     = parseInt(difY);
2020  
2021        var style = this.element.style;
2022        if ( intDifX != 0 )
2023           style.left = (currentLeft + intDifX) + "px";
2024        if ( intDifY != 0 )
2025           style.top  = (currentTop + intDifY) + "px";
2026     },
2027  
2028     resizeBy: function( difW, difH ) {
2029        var currentWidth  = this.element.offsetWidth;
2030        var currentHeight = this.element.offsetHeight;
2031        var intDifW       = parseInt(difW);
2032        var intDifH       = parseInt(difH);
2033  
2034        var style = this.element.style;
2035        if ( intDifW != 0 )
2036           style.width   = (currentWidth  + intDifW) + "px";
2037        if ( intDifH != 0 )
2038           style.height  = (currentHeight + intDifH) + "px";
2039     }
2040  }
2041  
2042  Effect.Size = Class.create();
2043  Effect.Size.prototype = {
2044  
2045     initialize: function(element, w, h, duration, steps, options) {
2046        new Effect.SizeAndPosition(element, null, null, w, h, duration, steps, options);
2047    }
2048  }
2049  
2050  Effect.Position = Class.create();
2051  Effect.Position.prototype = {
2052  
2053     initialize: function(element, x, y, duration, steps, options) {
2054        new Effect.SizeAndPosition(element, x, y, null, null, duration, steps, options);
2055    }
2056  }
2057  
2058  Effect.Round = Class.create();
2059  Effect.Round.prototype = {
2060  
2061     initialize: function(tagName, className, options) {
2062        var elements = document.getElementsByTagAndClassName(tagName,className);
2063        for ( var i = 0 ; i < elements.length ; i++ )
2064           Rico.Corner.round( elements[i], options );
2065     }
2066  };
2067  
2068  Effect.FadeTo = Class.create();
2069  Effect.FadeTo.prototype = {
2070  
2071     initialize: function( element, opacity, duration, steps, options) {
2072        this.element  = $(element);
2073        this.opacity  = opacity;
2074        this.duration = duration;
2075        this.steps    = steps;
2076        this.options  = arguments[4] || {};
2077        this.fadeTo();
2078     },
2079  
2080     fadeTo: function() {
2081        if (this.isFinished()) {
2082           if(this.options.complete) this.options.complete(this);
2083           return;
2084        }
2085  
2086        if (this.timer)
2087           clearTimeout(this.timer);
2088  
2089        var stepDuration = Math.round(this.duration/this.steps) ;
2090        var currentOpacity = this.getElementOpacity();
2091        var delta = this.steps > 0 ? (this.opacity - currentOpacity)/this.steps : 0;
2092  
2093        this.changeOpacityBy(delta);
2094        this.duration -= stepDuration;
2095        this.steps--;
2096  
2097        this.timer = setTimeout(this.fadeTo.bind(this), stepDuration);
2098     },
2099  
2100     changeOpacityBy: function(v) {
2101        var currentOpacity = this.getElementOpacity();
2102        var newOpacity = Math.max(0, Math.min(currentOpacity+v, 1));
2103        this.element.ricoOpacity = newOpacity;
2104  
2105        this.element.style.filter = "alpha(opacity:"+Math.round(newOpacity*100)+")";
2106        this.element.style.opacity = newOpacity; /*//*/;
2107     },
2108  
2109     isFinished: function() {
2110        return this.steps <= 0;
2111     },
2112  
2113     getElementOpacity: function() {
2114        if ( this.element.ricoOpacity == undefined ) {
2115           var opacity = RicoUtil.getElementsComputedStyle(this.element, 'opacity');
2116           this.element.ricoOpacity = opacity != undefined ? opacity : 1.0;
2117        }
2118        return parseFloat(this.element.ricoOpacity);
2119     }
2120  }
2121  
2122  Effect.AccordionSize = Class.create();
2123  
2124  Effect.AccordionSize.prototype = {
2125  
2126     initialize: function(e1, e2, start, end, duration, steps, options) {
2127        this.e1       = $(e1);
2128        this.e2       = $(e2);
2129        this.start    = start;
2130        this.end      = end;
2131        this.duration = duration;
2132        this.steps    = steps;
2133        this.options  = arguments[6] || {};
2134  
2135        this.accordionSize();
2136     },
2137  
2138     accordionSize: function() {
2139  
2140        if (this.isFinished()) {
2141           // just in case there are round errors or such...
2142           this.e1.style.height = this.start + "px";
2143           this.e2.style.height = this.end + "px";
2144  
2145           if(this.options.complete)
2146              this.options.complete(this);
2147           return;
2148        }
2149  
2150        if (this.timer)
2151           clearTimeout(this.timer);
2152  
2153        var stepDuration = Math.round(this.duration/this.steps) ;
2154  
2155        var diff = this.steps > 0 ? (parseInt(this.e1.offsetHeight) - this.start)/this.steps : 0;
2156        this.resizeBy(diff);
2157  
2158        this.duration -= stepDuration;
2159        this.steps--;
2160  
2161        this.timer = setTimeout(this.accordionSize.bind(this), stepDuration);
2162     },
2163  
2164     isFinished: function() {
2165        return this.steps <= 0;
2166     },
2167  
2168     resizeBy: function(diff) {
2169        var h1Height = this.e1.offsetHeight;
2170        var h2Height = this.e2.offsetHeight;
2171        var intDiff = parseInt(diff);
2172        if ( diff != 0 ) {
2173           this.e1.style.height = (h1Height - intDiff) + "px";
2174           this.e2.style.height = (h2Height + intDiff) + "px";
2175        }
2176     }
2177  
2178  };
2179  
2180  
2181  //-------------------- ricoLiveGrid.js
2182  // Rico.LiveGridMetaData -----------------------------------------------------
2183  
2184  Rico.LiveGridMetaData = Class.create();
2185  
2186  Rico.LiveGridMetaData.prototype = {
2187  
2188     initialize: function( pageSize, totalRows, columnCount, options ) {
2189        this.pageSize  = pageSize;
2190        this.totalRows = totalRows;
2191        this.setOptions(options);
2192        this.ArrowHeight = 16;
2193        this.columnCount = columnCount;
2194     },
2195  
2196     setOptions: function(options) {
2197        this.options = {
2198           largeBufferSize    : 7.0,   // 7 pages
2199           nearLimitFactor    : 0.2    // 20% of buffer
2200        };
2201        Object.extend(this.options, options || {});
2202     },
2203  
2204     getPageSize: function() {
2205        return this.pageSize;
2206     },
2207  
2208     getTotalRows: function() {
2209        return this.totalRows;
2210     },
2211  
2212     setTotalRows: function(n) {
2213        this.totalRows = n;
2214     },
2215  
2216     getLargeBufferSize: function() {
2217        return parseInt(this.options.largeBufferSize * this.pageSize);
2218     },
2219  
2220     getLimitTolerance: function() {
2221        return parseInt(this.getLargeBufferSize() * this.options.nearLimitFactor);
2222     }
2223  };
2224  
2225  // Rico.LiveGridScroller -----------------------------------------------------
2226  
2227  Rico.LiveGridScroller = Class.create();
2228  
2229  Rico.LiveGridScroller.prototype = {
2230  
2231     initialize: function(liveGrid, viewPort) {
2232        this.isIE = navigator.userAgent.toLowerCase().indexOf("msie") >= 0;
2233        this.liveGrid = liveGrid;
2234        this.metaData = liveGrid.metaData;
2235        this.createScrollBar();
2236        this.scrollTimeout = null;
2237        this.lastScrollPos = 0;
2238        this.viewPort = viewPort;
2239        this.rows = new Array();
2240     },
2241  
2242     isUnPlugged: function() {
2243        return this.scrollerDiv.onscroll == null;
2244     },
2245  
2246     plugin: function() {
2247        this.scrollerDiv.onscroll = this.handleScroll.bindAsEventListener(this);
2248     },
2249  
2250     unplug: function() {
2251        this.scrollerDiv.onscroll = null;
2252     },
2253  
2254     sizeIEHeaderHack: function() {
2255        if ( !this.isIE ) return;
2256        var headerTable = $(this.liveGrid.tableId + "_header");
2257        if ( headerTable )
2258           headerTable.rows[0].cells[0].style.width =
2259              (headerTable.rows[0].cells[0].offsetWidth + 1) + "px";
2260     },
2261  
2262     createScrollBar: function() {
2263        var visibleHeight = this.liveGrid.viewPort.visibleHeight();
2264        // create the outer div...
2265        this.scrollerDiv  = document.createElement("div");
2266        var scrollerStyle = this.scrollerDiv.style;
2267        scrollerStyle.borderRight = this.liveGrid.options.scrollerBorderRight;
2268        scrollerStyle.position    = "relative";
2269        scrollerStyle.left        = this.isIE ? "-6px" : "-3px";
2270        scrollerStyle.width       = "19px";
2271        scrollerStyle.height      = visibleHeight + "px";
2272        scrollerStyle.overflow    = "auto";
2273  
2274        // create the inner div...
2275        this.heightDiv = document.createElement("div");
2276        this.heightDiv.style.width  = "1px";
2277  
2278        this.heightDiv.style.height = parseInt(visibleHeight *
2279                          this.metaData.getTotalRows()/this.metaData.getPageSize()) + "px" ;
2280        this.scrollerDiv.appendChild(this.heightDiv);
2281        this.scrollerDiv.onscroll = this.handleScroll.bindAsEventListener(this);
2282  
2283       var table = this.liveGrid.table;
2284       table.parentNode.parentNode.insertBefore( this.scrollerDiv, table.parentNode.nextSibling );
2285          var eventName = this.isIE ? "mousewheel" : "DOMMouseScroll";
2286        Event.observe(table, eventName,
2287                      function(evt) {
2288                         if (evt.wheelDelta>=0 || evt.detail < 0) //wheel-up
2289                            this.scrollerDiv.scrollTop -= (2*this.viewPort.rowHeight);
2290                         else
2291                            this.scrollerDiv.scrollTop += (2*this.viewPort.rowHeight);
2292                         this.handleScroll(false);
2293                      }.bindAsEventListener(this),
2294                      false);
2295       },
2296  
2297     updateSize: function() {
2298        var table = this.liveGrid.table;
2299        var visibleHeight = this.viewPort.visibleHeight();
2300        this.heightDiv.style.height = parseInt(visibleHeight *
2301                                    this.metaData.getTotalRows()/this.metaData.getPageSize()) + "px";
2302     },
2303  
2304     rowToPixel: function(rowOffset) {
2305        return (rowOffset / this.metaData.getTotalRows()) * this.heightDiv.offsetHeight
2306     },
2307  
2308     moveScroll: function(rowOffset) {
2309        this.scrollerDiv.scrollTop = this.rowToPixel(rowOffset);
2310        if ( this.metaData.options.onscroll )
2311           this.metaData.options.onscroll( this.liveGrid, rowOffset );
2312     },
2313  
2314     handleScroll: function() {
2315       if ( this.scrollTimeout )
2316           clearTimeout( this.scrollTimeout );
2317  
2318      var scrollDiff = this.lastScrollPos-this.scrollerDiv.scrollTop;
2319      if (scrollDiff != 0.00) {
2320         var r = this.scrollerDiv.scrollTop % this.viewPort.rowHeight;
2321         if (r != 0) {
2322            this.unplug();
2323            if ( scrollDiff < 0 ) {
2324               this.scrollerDiv.scrollTop += (this.viewPort.rowHeight-r);
2325            } else {
2326               this.scrollerDiv.scrollTop -= r;
2327            }
2328            this.plugin();
2329         }
2330      }
2331      var contentOffset = parseInt(this.scrollerDiv.scrollTop / this.viewPort.rowHeight);
2332      this.liveGrid.requestContentRefresh(contentOffset);
2333      this.viewPort.scrollTo(this.scrollerDiv.scrollTop);
2334  
2335      if ( this.metaData.options.onscroll )
2336         this.metaData.options.onscroll( this.liveGrid, contentOffset );
2337  
2338      this.scrollTimeout = setTimeout(this.scrollIdle.bind(this), 1200 );
2339      this.lastScrollPos = this.scrollerDiv.scrollTop;
2340  
2341     },
2342  
2343     scrollIdle: function() {
2344        if ( this.metaData.options.onscrollidle )
2345           this.metaData.options.onscrollidle();
2346     }
2347  };
2348  
2349  // Rico.LiveGridBuffer -----------------------------------------------------
2350  
2351  Rico.LiveGridBuffer = Class.create();
2352  
2353  Rico.LiveGridBuffer.prototype = {
2354  
2355     initialize: function(metaData, viewPort) {
2356        this.startPos = 0;
2357        this.size     = 0;
2358        this.metaData = metaData;
2359        this.rows     = new Array();
2360        this.updateInProgress = false;
2361        this.viewPort = viewPort;
2362        this.maxBufferSize = metaData.getLargeBufferSize() * 2;
2363        this.maxFetchSize = metaData.getLargeBufferSize();
2364        this.lastOffset = 0;
2365     },
2366  
2367     getBlankRow: function() {
2368        if (!this.blankRow ) {
2369           this.blankRow = new Array();
2370           for ( var i=0; i < this.metaData.columnCount ; i++ )
2371              this.blankRow[i] = "&nbsp;";
2372       }
2373       return this.blankRow;
2374     },
2375  
2376     loadRows: function(ajaxResponse) {
2377        var rowsElement = ajaxResponse.getElementsByTagName('rows')[0];
2378        this.updateUI = rowsElement.getAttribute("update_ui") == "true"
2379        var newRows = new Array()
2380        var trs = rowsElement.getElementsByTagName("tr");
2381        for ( var i=0 ; i < trs.length; i++ ) {
2382           var row = newRows[i] = new Array();
2383           var cells = trs[i].getElementsByTagName("td");
2384           for ( var j=0; j < cells.length ; j++ ) {
2385              var cell = cells[j];
2386              var convertSpaces = cell.getAttribute("convert_spaces") == "true";
2387              var cellContent = RicoUtil.getContentAsString(cell);
2388              row[j] = convertSpaces ? this.convertSpaces(cellContent) : cellContent;
2389              if (!row[j])
2390                 row[j] = '&nbsp;';
2391           }
2392        }
2393        return newRows;
2394     },
2395  
2396     update: function(ajaxResponse, start) {
2397       var newRows = this.loadRows(ajaxResponse);
2398        if (this.rows.length == 0) { // initial load
2399           this.rows = newRows;
2400           this.size = this.rows.length;
2401           this.startPos = start;
2402           return;
2403        }
2404        if (start > this.startPos) { //appending
2405           if (this.startPos + this.rows.length < start) {
2406              this.rows =  newRows;
2407              this.startPos = start;//
2408           } else {
2409                this.rows = this.rows.concat( newRows.slice(0, newRows.length));
2410              if (this.rows.length > this.maxBufferSize) {
2411                 var fullSize = this.rows.length;
2412                 this.rows = this.rows.slice(this.rows.length - this.maxBufferSize, this.rows.length)
2413                 this.startPos = this.startPos +  (fullSize - this.rows.length);
2414              }
2415           }
2416        } else { //prepending
2417           if (start + newRows.length < this.startPos) {
2418              this.rows =  newRows;
2419           } else {
2420              this.rows = newRows.slice(0, this.startPos).concat(this.rows);
2421              if (this.rows.length > this.maxBufferSize)
2422                 this.rows = this.rows.slice(0, this.maxBufferSize)
2423           }
2424           this.startPos =  start;
2425        }
2426        this.size = this.rows.length;
2427     },
2428  
2429     clear: function() {
2430        this.rows = new Array();
2431        this.startPos = 0;
2432        this.size = 0;
2433     },
2434  
2435     isOverlapping: function(start, size) {
2436        return ((start < this.endPos()) && (this.startPos < start + size)) || (this.endPos() == 0)
2437     },
2438  
2439     isInRange: function(position) {
2440        return (position >= this.startPos) && (position + this.metaData.getPageSize() <= this.endPos());
2441               //&& this.size()  != 0;
2442     },
2443  
2444     isNearingTopLimit: function(position) {
2445        return position - this.startPos < this.metaData.getLimitTolerance();
2446     },
2447  
2448     endPos: function() {
2449        return this.startPos + this.rows.length;
2450     },
2451  
2452     isNearingBottomLimit: function(position) {
2453        return this.endPos() - (position + this.metaData.getPageSize()) < this.metaData.getLimitTolerance();
2454     },
2455  
2456     isAtTop: function() {
2457        return this.startPos == 0;
2458     },
2459  
2460     isAtBottom: function() {
2461        return this.endPos() == this.metaData.getTotalRows();
2462     },
2463  
2464     isNearingLimit: function(position) {
2465        return ( !this.isAtTop()    && this.isNearingTopLimit(position)) ||
2466               ( !this.isAtBottom() && this.isNearingBottomLimit(position) )
2467     },
2468  
2469     getFetchSize: function(offset) {
2470        var adjustedOffset = this.getFetchOffset(offset);
2471        var adjustedSize = 0;
2472        if (adjustedOffset >= this.startPos) { //apending
2473           var endFetchOffset = this.maxFetchSize  + adjustedOffset;
2474           if (endFetchOffset > this.metaData.totalRows)
2475              endFetchOffset = this.metaData.totalRows;
2476           adjustedSize = endFetchOffset - adjustedOffset;
2477              if(adjustedOffset == 0 && adjustedSize < this.maxFetchSize){
2478                 adjustedSize = this.maxFetchSize;
2479              }
2480        } else {//prepending
2481           var adjustedSize = this.startPos - adjustedOffset;
2482           if (adjustedSize > this.maxFetchSize)
2483              adjustedSize = this.maxFetchSize;
2484        }
2485        return adjustedSize;
2486     },
2487  
2488     getFetchOffset: function(offset) {
2489        var adjustedOffset = offset;
2490        if (offset > this.startPos)  //apending
2491           adjustedOffset = (offset > this.endPos()) ? offset :  this.endPos();
2492        else { //prepending
2493           if (offset + this.maxFetchSize >= this.startPos) {
2494              var adjustedOffset = this.startPos - this.maxFetchSize;
2495              if (adjustedOffset < 0)
2496                 adjustedOffset = 0;
2497           }
2498        }
2499        this.lastOffset = adjustedOffset;
2500        return adjustedOffset;
2501     },
2502  
2503     getRows: function(start, count) {
2504        var begPos = start - this.startPos
2505        var endPos = begPos + count
2506  
2507        // er? need more data...
2508        if ( endPos > this.size )
2509           endPos = this.size
2510  
2511        var results = new Array()
2512        var index = 0;
2513        for ( var i=begPos ; i < endPos; i++ ) {
2514           results[index++] = this.rows[i]
2515        }
2516        return results
2517     },
2518  
2519     convertSpaces: function(s) {
2520        return s.split(" ").join("&nbsp;");
2521     }
2522  
2523  };
2524  
2525  
2526  //Rico.GridViewPort --------------------------------------------------
2527  Rico.GridViewPort = Class.create();
2528  
2529  Rico.GridViewPort.prototype = {
2530  
2531     initialize: function(table, rowHeight, visibleRows, buffer, liveGrid) {
2532        this.lastDisplayedStartPos = 0;
2533        this.div = table.parentNode;
2534        this.table = table
2535        this.rowHeight = rowHeight;
2536        this.div.style.height = this.rowHeight * visibleRows;
2537        this.div.style.overflow = "hidden";
2538        this.buffer = buffer;
2539        this.liveGrid = liveGrid;
2540        this.visibleRows = visibleRows + 1;
2541        this.lastPixelOffset = 0;
2542        this.startPos = 0;
2543     },
2544  
2545     populateRow: function(htmlRow, row) {
2546        for (var j=0; j < row.length; j++) {
2547           htmlRow.cells[j].innerHTML = row[j]
2548        }
2549     },
2550  
2551     bufferChanged: function() {
2552        this.refreshContents( parseInt(this.lastPixelOffset / this.rowHeight));
2553     },
2554  
2555     clearRows: function() {
2556        if (!this.isBlank) {
2557           this.liveGrid.table.className = this.liveGrid.options.loadingClass;
2558           for (var i=0; i < this.visibleRows; i++)
2559              this.populateRow(this.table.rows[i], this.buffer.getBlankRow());
2560           this.isBlank = true;
2561        }
2562     },
2563  
2564     clearContents: function() {
2565        this.clearRows();
2566        this.scrollTo(0);
2567        this.startPos = 0;
2568        this.lastStartPos = -1;
2569     },
2570  
2571     refreshContents: function(startPos) {
2572        if (startPos == this.lastRowPos && !this.isPartialBlank && !this.isBlank) {
2573           return;
2574        }
2575        if ((startPos + this.visibleRows < this.buffer.startPos)
2576            || (this.buffer.startPos + this.buffer.size < startPos)
2577            || (this.buffer.size == 0)) {
2578           this.clearRows();
2579           return;
2580        }
2581        this.isBlank = false;
2582        var viewPrecedesBuffer = this.buffer.startPos > startPos
2583        var contentStartPos = viewPrecedesBuffer ? this.buffer.startPos: startPos;
2584        var contentEndPos = (this.buffer.startPos + this.buffer.size < startPos + this.visibleRows)
2585                                   ? this.buffer.startPos + this.buffer.size
2586                                   : startPos + this.visibleRows;
2587        var rowSize = contentEndPos - contentStartPos;
2588        var rows = this.buffer.getRows(contentStartPos, rowSize );
2589        var blankSize = this.visibleRows - rowSize;
2590        var blankOffset = viewPrecedesBuffer ? 0: rowSize;
2591        var contentOffset = viewPrecedesBuffer ? blankSize: 0;
2592  
2593        for (var i=0; i < rows.length; i++) {//initialize what we have
2594          this.populateRow(this.table.rows[i + contentOffset], rows[i]);
2595        }
2596        for (var i=0; i < blankSize; i++) {// blank out the rest
2597          this.populateRow(this.table.rows[i + blankOffset], this.buffer.getBlankRow());
2598        }
2599        this.isPartialBlank = blankSize > 0;
2600        this.lastRowPos = startPos;
2601  
2602         this.liveGrid.table.className = this.liveGrid.options.tableClass;
2603         // Check if user has set a onRefreshComplete function
2604         var onRefreshComplete = this.liveGrid.options.onRefreshComplete;
2605         if (onRefreshComplete != null)
2606             onRefreshComplete();
2607     },
2608  
2609     scrollTo: function(pixelOffset) {
2610        if (this.lastPixelOffset == pixelOffset)
2611           return;
2612  
2613        this.refreshContents(parseInt(pixelOffset / this.rowHeight))
2614        this.div.scrollTop = pixelOffset % this.rowHeight
2615  
2616        this.lastPixelOffset = pixelOffset;
2617     },
2618  
2619     visibleHeight: function() {
2620        return parseInt(RicoUtil.getElementsComputedStyle(this.div, 'height'));
2621     }
2622  
2623  };
2624  
2625  
2626  Rico.LiveGridRequest = Class.create();
2627  Rico.LiveGridRequest.prototype = {
2628     initialize: function( requestOffset, options ) {
2629        this.requestOffset = requestOffset;
2630     }
2631  };
2632  
2633  // Rico.LiveGrid -----------------------------------------------------
2634  
2635  Rico.LiveGrid = Class.create();
2636  
2637  Rico.LiveGrid.prototype = {
2638  
2639     initialize: function( tableId, visibleRows, totalRows, url, options, ajaxOptions ) {
2640  
2641       this.options = {
2642                  tableClass:           $(tableId).className,
2643                  loadingClass:         $(tableId).className,
2644                  scrollerBorderRight: '1px solid #ababab',
2645                  bufferTimeout:        20000,
2646                  sortAscendImg:        'images/sort_asc.gif',
2647                  sortDescendImg:       'images/sort_desc.gif',
2648                  sortImageWidth:       9,
2649                  sortImageHeight:      5,
2650                  ajaxSortURLParms:     [],
2651                  onRefreshComplete:    null,
2652                  requestParameters:    null,
2653                  inlineStyles:         true
2654                  };
2655        Object.extend(this.options, options || {});
2656  
2657        this.ajaxOptions = {parameters: null};
2658        Object.extend(this.ajaxOptions, ajaxOptions || {});
2659  
2660        this.tableId     = tableId;
2661        this.table       = $(tableId);
2662  
2663        this.addLiveGridHtml();
2664  
2665        var columnCount  = this.table.rows[0].cells.length;
2666        this.metaData    = new Rico.LiveGridMetaData(visibleRows, totalRows, columnCount, options);
2667        this.buffer      = new Rico.LiveGridBuffer(this.metaData);
2668  
2669        var rowCount = this.table.rows.length;
2670        this.viewPort =  new Rico.GridViewPort(this.table,
2671                                              this.table.offsetHeight/rowCount,
2672                                              visibleRows,
2673                                              this.buffer, this);
2674        this.scroller    = new Rico.LiveGridScroller(this,this.viewPort);
2675        this.options.sortHandler = this.sortHandler.bind(this);
2676  
2677        if ( $(tableId + '_header') )
2678           this.sort = new Rico.LiveGridSort(tableId + '_header', this.options)
2679  
2680        this.processingRequest = null;
2681        this.unprocessedRequest = null;
2682  
2683        this.initAjax(url);
2684        if ( this.options.prefetchBuffer || this.options.prefetchOffset > 0) {
2685           var offset = 0;
2686           if (this.options.offset ) {
2687              offset = this.options.offset;
2688              this.scroller.moveScroll(offset);
2689              this.viewPort.scrollTo(this.scroller.rowToPixel(offset));
2690           }
2691           if (this.options.sortCol) {
2692               this.sortCol = options.sortCol;
2693               this.sortDir = options.sortDir;
2694           }
2695           this.requestContentRefresh(offset);
2696        }
2697     },
2698  
2699     addLiveGridHtml: function() {
2700       // Check to see if need to create a header table.
2701       if (this.table.getElementsByTagName("thead").length > 0){
2702         // Create Table this.tableId+'_header'
2703         var tableHeader = this.table.cloneNode(true);
2704         tableHeader.setAttribute('id', this.tableId+'_header');
2705         tableHeader.setAttribute('class', this.table.className+'_header');
2706  
2707         // Clean up and insert
2708         for( var i = 0; i < tableHeader.tBodies.length; i++ )
2709         tableHeader.removeChild(tableHeader.tBodies[i]);
2710         this.table.deleteTHead();
2711         this.table.parentNode.insertBefore(tableHeader,this.table);
2712       }
2713  
2714      new Insertion.Before(this.table, "<div id='"+this.tableId+"_container'></div>");
2715      this.table.previousSibling.appendChild(this.table);
2716      new Insertion.Before(this.table,"<div id='"+this.tableId+"_viewport' style='float:left;'></div>");
2717      this.table.previousSibling.appendChild(this.table);
2718     },
2719  
2720     resetContents: function() {
2721        this.scroller.moveScroll(0);
2722        this.buffer.clear();
2723        this.viewPort.clearContents();
2724     },
2725  
2726     sortHandler: function(column) {
2727        this.sortCol = column.name;
2728        this.sortDir = column.currentSort;
2729  
2730        this.resetContents();
2731        this.requestContentRefresh(0)
2732     },
2733  
2734     setTotalRows: function( newTotalRows ) {
2735        this.resetContents();
2736        this.metaData.setTotalRows(newTotalRows);
2737        this.scroller.updateSize();
2738     },
2739  
2740     initAjax: function(url) {
2741        ajaxEngine.registerRequest( this.tableId + '_request', url );
2742        ajaxEngine.registerAjaxObject( this.tableId + '_updater', this );
2743     },
2744  
2745     invokeAjax: function() {
2746     },
2747  
2748     handleTimedOut: function() {
2749        //server did not respond in 4 seconds... assume that there could have been
2750        //an error or something, and allow requests to be processed again...
2751        this.processingRequest = null;
2752        this.processQueuedRequest();
2753     },
2754  
2755     fetchBuffer: function(offset) {
2756        if ( this.buffer.isInRange(offset) &&
2757           !this.buffer.isNearingLimit(offset)) {
2758           return;
2759           }
2760        if (this.processingRequest) {
2761            this.unprocessedRequest = new Rico.LiveGridRequest(offset);
2762           return;
2763        }
2764        var bufferStartPos = this.buffer.getFetchOffset(offset);
2765        this.processingRequest = new Rico.LiveGridRequest(offset);
2766        this.processingRequest.bufferOffset = bufferStartPos;
2767        var fetchSize = this.buffer.getFetchSize(offset);
2768        var partialLoaded = false;
2769  
2770        var queryString
2771        if (this.options.requestParameters)
2772           queryString = this._createQueryString(this.options.requestParameters, 0);
2773  
2774          queryString = (queryString == null) ? '' : queryString+'&';
2775          queryString  = queryString+'id='+this.tableId+'&page_size='+fetchSize+'&offset='+bufferStartPos;
2776          if (this.sortCol)
2777              queryString = queryString+'&sort_col='+escape(this.sortCol)+'&sort_dir='+this.sortDir;
2778  
2779          this.ajaxOptions.parameters = queryString;
2780  
2781         ajaxEngine.sendRequest( this.tableId + '_request', this.ajaxOptions );
2782  
2783         this.timeoutHandler = setTimeout( this.handleTimedOut.bind(this), this.options.bufferTimeout);
2784  
2785     },
2786  
2787     setRequestParams: function() {
2788        this.options.requestParameters = [];
2789        for ( var i=0 ; i < arguments.length ; i++ )
2790           this.options.requestParameters[i] = arguments[i];
2791     },
2792  
2793     requestContentRefresh: function(contentOffset) {
2794        this.fetchBuffer(contentOffset);
2795     },
2796  
2797     ajaxUpdate: function(ajaxResponse) {
2798        try {
2799           clearTimeout( this.timeoutHandler );
2800           this.buffer.update(ajaxResponse,this.processingRequest.bufferOffset);
2801           this.viewPort.bufferChanged();
2802        }
2803        catch(err) {}
2804        finally {this.processingRequest = null; }
2805        this.processQueuedRequest();
2806     },
2807  
2808     _createQueryString: function( theArgs, offset ) {
2809        var queryString = ""
2810        if (!theArgs)
2811            return queryString;
2812  
2813        for ( var i = offset ; i < theArgs.length ; i++ ) {
2814            if ( i != offset )
2815              queryString += "&";
2816  
2817            var anArg = theArgs[i];
2818  
2819            if ( anArg.name != undefined && anArg.value != undefined ) {
2820              queryString += anArg.name +  "=" + escape(anArg.value);
2821            }
2822            else {
2823               var ePos  = anArg.indexOf('=');
2824               var argName  = anArg.substring( 0, ePos );
2825               var argValue = anArg.substring( ePos + 1 );
2826               queryString += argName + "=" + escape(argValue);
2827            }
2828        }
2829        return queryString;
2830     },
2831  
2832     processQueuedRequest: function() {
2833        if (this.unprocessedRequest != null) {
2834           this.requestContentRefresh(this.unprocessedRequest.requestOffset);
2835           this.unprocessedRequest = null
2836        }
2837     }
2838  };
2839  
2840  
2841  //-------------------- ricoLiveGridSort.js
2842  Rico.LiveGridSort = Class.create();
2843  
2844  Rico.LiveGridSort.prototype = {
2845  
2846     initialize: function(headerTableId, options) {
2847        this.headerTableId = headerTableId;
2848        this.headerTable   = $(headerTableId);
2849        this.options = options;
2850        this.setOptions();
2851        this.applySortBehavior();
2852  
2853        if ( this.options.sortCol ) {
2854           this.setSortUI( this.options.sortCol, this.options.sortDir );
2855        }
2856     },
2857  
2858     setSortUI: function( columnName, sortDirection ) {
2859        var cols = this.options.columns;
2860        for ( var i = 0 ; i < cols.length ; i++ ) {
2861           if ( cols[i].name == columnName ) {
2862              this.setColumnSort(i, sortDirection);
2863              break;
2864           }
2865        }
2866     },
2867  
2868     setOptions: function() {
2869        // preload the images...
2870        new Image().src = this.options.sortAscendImg;
2871        new Image().src = this.options.sortDescendImg;
2872  
2873        this.sort = this.options.sortHandler;
2874        if ( !this.options.columns )
2875           this.options.columns = this.introspectForColumnInfo();
2876        else {
2877           // allow client to pass { columns: [ ["a", true], ["b", false] ] }
2878           // and convert to an array of Rico.TableColumn objs...
2879           this.options.columns = this.convertToTableColumns(this.options.columns);
2880        }
2881     },
2882  
2883     applySortBehavior: function() {
2884        var headerRow   = this.headerTable.rows[0];
2885        var headerCells = headerRow.cells;
2886        for ( var i = 0 ; i < headerCells.length ; i++ ) {
2887           this.addSortBehaviorToColumn( i, headerCells[i] );
2888        }
2889     },
2890  
2891     addSortBehaviorToColumn: function( n, cell ) {
2892        if ( this.options.columns[n].isSortable() ) {
2893           cell.id            = this.headerTableId + '_' + n;
2894           cell.style.cursor  = 'pointer';
2895           cell.onclick       = this.headerCellClicked.bindAsEventListener(this);
2896           cell.innerHTML     = cell.innerHTML + '<span id="' + this.headerTableId + '_img_' + n + '">'
2897                             + '&nbsp;&nbsp;&nbsp;</span>';
2898        }
2899     },
2900  
2901     // event handler....
2902     headerCellClicked: function(evt) {
2903        var eventTarget = evt.target ? evt.target : evt.srcElement;
2904        var cellId = eventTarget.id;
2905        var columnNumber = parseInt(cellId.substring( cellId.lastIndexOf('_') + 1 ));
2906        var sortedColumnIndex = this.getSortedColumnIndex();
2907        if ( sortedColumnIndex != -1 ) {
2908           if ( sortedColumnIndex != columnNumber ) {
2909              this.removeColumnSort(sortedColumnIndex);
2910              this.setColumnSort(columnNumber, Rico.TableColumn.SORT_ASC);
2911           }
2912           else
2913              this.toggleColumnSort(sortedColumnIndex);
2914        }
2915        else
2916           this.setColumnSort(columnNumber, Rico.TableColumn.SORT_ASC);
2917  
2918        if (this.options.sortHandler) {
2919           this.options.sortHandler(this.options.columns[columnNumber]);
2920        }
2921     },
2922  
2923     removeColumnSort: function(n) {
2924        this.options.columns[n].setUnsorted();
2925        this.setSortImage(n);
2926     },
2927  
2928     setColumnSort: function(n, direction) {
2929        this.options.columns[n].setSorted(direction);
2930        this.setSortImage(n);
2931     },
2932  
2933     toggleColumnSort: function(n) {
2934        this.options.columns[n].toggleSort();
2935        this.setSortImage(n);
2936     },
2937  
2938     setSortImage: function(n) {
2939        var sortDirection = this.options.columns[n].getSortDirection();
2940  
2941        var sortImageSpan = $( this.headerTableId + '_img_' + n );
2942        if ( sortDirection == Rico.TableColumn.UNSORTED )
2943           sortImageSpan.innerHTML = '&nbsp;&nbsp;';
2944        else if ( sortDirection == Rico.TableColumn.SORT_ASC )
2945           sortImageSpan.innerHTML = '&nbsp;&nbsp;<img width="'  + this.options.sortImageWidth    + '" ' +
2946                                                       'height="'+ this.options.sortImageHeight   + '" ' +
2947                                                       'src="'   + this.options.sortAscendImg + '"/>';
2948        else if ( sortDirection == Rico.TableColumn.SORT_DESC )
2949           sortImageSpan.innerHTML = '&nbsp;&nbsp;<img width="'  + this.options.sortImageWidth    + '" ' +
2950                                                       'height="'+ this.options.sortImageHeight   + '" ' +
2951                                                       'src="'   + this.options.sortDescendImg + '"/>';
2952     },
2953  
2954     getSortedColumnIndex: function() {
2955        var cols = this.options.columns;
2956        for ( var i = 0 ; i < cols.length ; i++ ) {
2957           if ( cols[i].isSorted() )
2958              return i;
2959        }
2960  
2961        return -1;
2962     },
2963  
2964     introspectForColumnInfo: function() {
2965        var columns = new Array();
2966        var headerRow   = this.headerTable.rows[0];
2967        var headerCells = headerRow.cells;
2968        for ( var i = 0 ; i < headerCells.length ; i++ )
2969           columns.push( new Rico.TableColumn( this.deriveColumnNameFromCell(headerCells[i],i), true ) );
2970        return columns;
2971     },
2972  
2973     convertToTableColumns: function(cols) {
2974        var columns = new Array();
2975        for ( var i = 0 ; i < cols.length ; i++ )
2976           columns.push( new Rico.TableColumn( cols[i][0], cols[i][1] ) );
2977        return columns;
2978     },
2979  
2980     deriveColumnNameFromCell: function(cell,columnNumber) {
2981        var cellContent = cell.innerText != undefined ? cell.innerText : cell.textContent;
2982        return cellContent ? cellContent.toLowerCase().split(' ').join('_') : "col_" + columnNumber;
2983     }
2984  };
2985  
2986  Rico.TableColumn = Class.create();
2987  
2988  Rico.TableColumn.UNSORTED  = 0;
2989  Rico.TableColumn.SORT_ASC  = "ASC";
2990  Rico.TableColumn.SORT_DESC = "DESC";
2991  
2992  Rico.TableColumn.prototype = {
2993     initialize: function(name, sortable) {
2994        this.name        = name;
2995        this.sortable    = sortable;
2996        this.currentSort = Rico.TableColumn.UNSORTED;
2997     },
2998  
2999     isSortable: function() {
3000        return this.sortable;
3001     },
3002  
3003     isSorted: function() {
3004        return this.currentSort != Rico.TableColumn.UNSORTED;
3005     },
3006  
3007     getSortDirection: function() {
3008        return this.currentSort;
3009     },
3010  
3011     toggleSort: function() {
3012        if ( this.currentSort == Rico.TableColumn.UNSORTED || this.currentSort == Rico.TableColumn.SORT_DESC )
3013           this.currentSort = Rico.TableColumn.SORT_ASC;
3014        else if ( this.currentSort == Rico.TableColumn.SORT_ASC )
3015           this.currentSort = Rico.TableColumn.SORT_DESC;
3016     },
3017  
3018     setUnsorted: function(direction) {
3019        this.setSorted(Rico.TableColumn.UNSORTED);
3020     },
3021  
3022     setSorted: function(direction) {
3023        // direction must by one of Rico.TableColumn.UNSORTED, .SORT_ASC, or .SORT_DESC...
3024        this.currentSort = direction;
3025     }
3026  
3027  };
3028  
3029  
3030  //-------------------- ricoUtil.js
3031  Rico.ArrayExtensions = new Array();
3032  
3033  if (Object.prototype.extend) {
3034     // in prototype.js...
3035     Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
3036  }else{
3037    Object.prototype.extend = function(object) {
3038      return Object.extend.apply(this, [this, object]);
3039    }
3040    Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
3041  }
3042  
3043  if (Array.prototype.push) {
3044     // in prototype.js...
3045     Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.push;
3046  }
3047  
3048  if (!Array.prototype.remove) {
3049     Array.prototype.remove = function(dx) {
3050        if( isNaN(dx) || dx > this.length )
3051           return false;
3052        for( var i=0,n=0; i<this.length; i++ )
3053           if( i != dx )
3054              this[n++]=this[i];
3055        this.length-=1;
3056     };
3057    Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.remove;
3058  }
3059  
3060  if (!Array.prototype.removeItem) {
3061     Array.prototype.removeItem = function(item) {
3062        for ( var i = 0 ; i < this.length ; i++ )
3063           if ( this[i] == item ) {
3064              this.remove(i);
3065              break;
3066           }
3067     };
3068    Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.removeItem;
3069  }
3070  
3071  if (!Array.prototype.indices) {
3072     Array.prototype.indices = function() {
3073        var indexArray = new Array();
3074        for ( index in this ) {
3075           var ignoreThis = false;
3076           for ( var i = 0 ; i < Rico.ArrayExtensions.length ; i++ ) {
3077              if ( this[index] == Rico.ArrayExtensions[i] ) {
3078                 ignoreThis = true;
3079                 break;
3080              }
3081           }
3082           if ( !ignoreThis )
3083              indexArray[ indexArray.length ] = index;
3084        }
3085        return indexArray;
3086     }
3087    Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.indices;
3088  }
3089  
3090    Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.unique;
3091    Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.inArray;
3092  
3093  
3094  // Create the loadXML method and xml getter for Mozilla
3095  if ( window.DOMParser &&
3096        window.XMLSerializer &&
3097        window.Node && Node.prototype && Node.prototype.__defineGetter__ ) {
3098  
3099     if (!Document.prototype.loadXML) {
3100        Document.prototype.loadXML = function (s) {
3101           var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
3102           while (this.hasChildNodes())
3103              this.removeChild(this.lastChild);
3104  
3105           for (var i = 0; i < doc2.childNodes.length; i++) {
3106              this.appendChild(this.importNode(doc2.childNodes[i], true));
3107           }
3108        };
3109      }
3110  
3111      Document.prototype.__defineGetter__( "xml",
3112         function () {
3113             return (new XMLSerializer()).serializeToString(this);
3114         }
3115       );
3116  }
3117  
3118  document.getElementsByTagAndClassName = function(tagName, className) {
3119    if ( tagName == null )
3120       tagName = '*';
3121  
3122    var children = document.getElementsByTagName(tagName) || document.all;
3123    var elements = new Array();
3124  
3125    if ( className == null )
3126      return children;
3127  
3128    for (var i = 0; i < children.length; i++) {
3129      var child = children[i];
3130      var classNames = child.className.split(' ');
3131      for (var j = 0; j < classNames.length; j++) {
3132        if (classNames[j] == className) {
3133          elements.push(child);
3134          break;
3135        }
3136      }
3137    }
3138  
3139    return elements;
3140  }
3141  
3142  var RicoUtil = {
3143  
3144     getElementsComputedStyle: function ( htmlElement, cssProperty, mozillaEquivalentCSS) {
3145        if ( arguments.length == 2 )
3146           mozillaEquivalentCSS = cssProperty;
3147  
3148        var el = $(htmlElement);
3149        if ( el.currentStyle )
3150           return el.currentStyle[cssProperty];
3151        else
3152           return document.defaultView.getComputedStyle(el, null).getPropertyValue(mozillaEquivalentCSS);
3153     },
3154  
3155     createXmlDocument : function() {
3156        if (document.implementation && document.implementation.createDocument) {
3157           var doc = document.implementation.createDocument("", "", null);
3158  
3159           if (doc.readyState == null) {
3160              doc.readyState = 1;
3161              doc.addEventListener("load", function () {
3162                 doc.readyState = 4;
3163                 if (typeof doc.onreadystatechange == "function")
3164                    doc.onreadystatechange();
3165              }, false);
3166           }
3167  
3168           return doc;
3169        }
3170  
3171        if (window.ActiveXObject)
3172            return Try.these(
3173              function() { return new ActiveXObject('MSXML2.DomDocument')   },
3174              function() { return new ActiveXObject('Microsoft.DomDocument')},
3175              function() { return new ActiveXObject('MSXML.DomDocument')    },
3176              function() { return new ActiveXObject('MSXML3.DomDocument')   }
3177            ) || false;
3178  
3179        return null;
3180     },
3181  
3182     getContentAsString: function( parentNode ) {
3183        return parentNode.xml != undefined ?
3184           this._getContentAsStringIE(parentNode) :
3185           this._getContentAsStringMozilla(parentNode);
3186     },
3187  
3188    _getContentAsStringIE: function(parentNode) {
3189       var contentStr = "";
3190       for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) {
3191           var n = parentNode.childNodes[i];
3192           if (n.nodeType == 4) {
3193               contentStr += n.nodeValue;
3194           }
3195           else {
3196             contentStr += n.xml;
3197         }
3198       }
3199       return contentStr;
3200    },
3201  
3202    _getContentAsStringMozilla: function(parentNode) {
3203       var xmlSerializer = new XMLSerializer();
3204       var contentStr = "";
3205       for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) {
3206            var n = parentNode.childNodes[i];
3207            if (n.nodeType == 4) { // CDATA node
3208                contentStr += n.nodeValue;
3209            }
3210            else {
3211              contentStr += xmlSerializer.serializeToString(n);
3212          }
3213       }
3214       return contentStr;
3215    },
3216  
3217     toViewportPosition: function(element) {
3218        return this._toAbsolute(element,true);
3219     },
3220  
3221     toDocumentPosition: function(element) {
3222        return this._toAbsolute(element,false);
3223     },
3224  
3225     /**
3226      *  Compute the elements position in terms of the window viewport
3227      *  so that it can be compared to the position of the mouse (dnd)
3228      *  This is additions of all the offsetTop,offsetLeft values up the
3229      *  offsetParent hierarchy, ...taking into account any scrollTop,
3230      *  scrollLeft values along the way...
3231      *
3232      * IE has a bug reporting a correct offsetLeft of elements within a
3233      * a relatively positioned parent!!!
3234      **/
3235     _toAbsolute: function(element,accountForDocScroll) {
3236  
3237        if ( navigator.userAgent.toLowerCase().indexOf("msie") == -1 )
3238           return this._toAbsoluteMozilla(element,accountForDocScroll);
3239  
3240        var x = 0;
3241        var y = 0;
3242        var parent = element;
3243        while ( parent ) {
3244  
3245           var borderXOffset = 0;
3246           var borderYOffset = 0;
3247           if ( parent != element ) {
3248              var borderXOffset = parseInt(this.getElementsComputedStyle(parent, "borderLeftWidth" ));
3249              var borderYOffset = parseInt(this.getElementsComputedStyle(parent, "borderTopWidth" ));
3250              borderXOffset = isNaN(borderXOffset) ? 0 : borderXOffset;
3251              borderYOffset = isNaN(borderYOffset) ? 0 : borderYOffset;
3252           }
3253  
3254           x += parent.offsetLeft - parent.scrollLeft + borderXOffset;
3255           y += parent.offsetTop - parent.scrollTop + borderYOffset;
3256           parent = parent.offsetParent;
3257        }
3258  
3259        if ( accountForDocScroll ) {
3260           x -= this.docScrollLeft();
3261           y -= this.docScrollTop();
3262        }
3263  
3264        return { x:x, y:y };
3265     },
3266  
3267     /**
3268      *  Mozilla did not report all of the parents up the hierarchy via the
3269      *  offsetParent property that IE did.  So for the calculation of the
3270      *  offsets we use the offsetParent property, but for the calculation of
3271      *  the scrollTop/scrollLeft adjustments we navigate up via the parentNode
3272      *  property instead so as to get the scroll offsets...
3273      *
3274      **/
3275     _toAbsoluteMozilla: function(element,accountForDocScroll) {
3276        var x = 0;
3277        var y = 0;
3278        var parent = element;
3279        while ( parent ) {
3280           x += parent.offsetLeft;
3281           y += parent.offsetTop;
3282           parent = parent.offsetParent;
3283        }
3284  
3285        parent = element;
3286        while ( parent &&
3287                parent != document.body &&
3288                parent != document.documentElement ) {
3289           if ( parent.scrollLeft  )
3290              x -= parent.scrollLeft;
3291           if ( parent.scrollTop )
3292              y -= parent.scrollTop;
3293           parent = parent.parentNode;
3294        }
3295  
3296        if ( accountForDocScroll ) {
3297           x -= this.docScrollLeft();
3298           y -= this.docScrollTop();
3299        }
3300  
3301        return { x:x, y:y };
3302     },
3303  
3304     docScrollLeft: function() {
3305        if ( window.pageXOffset )
3306           return window.pageXOffset;
3307        else if ( document.documentElement && document.documentElement.scrollLeft )
3308           return document.documentElement.scrollLeft;
3309        else if ( document.body )
3310           return document.body.scrollLeft;
3311        else
3312           return 0;
3313     },
3314  
3315     docScrollTop: function() {
3316        if ( window.pageYOffset )
3317           return window.pageYOffset;
3318        else if ( document.documentElement && document.documentElement.scrollTop )
3319           return document.documentElement.scrollTop;
3320        else if ( document.body )
3321           return document.body.scrollTop;
3322        else
3323           return 0;
3324     }
3325  
3326  };


Généré le : Sun Feb 25 21:07:04 2007 par Balluche grâce à PHPXref 0.7