[ Index ]
 

Code source de Seagull 0.6.1

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

title

Body

[fermer]

/js/lightbox/ -> lightbox.js (source)

   1  // -----------------------------------------------------------------------------------
   2  //
   3  //    Lightbox v2.02
   4  //    by Lokesh Dhakar - http://www.huddletogether.com
   5  //    3/31/06
   6  //
   7  //    For more information on this script, visit:
   8  //    http://huddletogether.com/projects/lightbox2/
   9  //
  10  //    Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
  11  //    
  12  //    Credit also due to those who have helped, inspired, and made their code available to the public.
  13  //    Including: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.org), Thomas Fuchs(mir.aculo.us), and others.
  14  //
  15  //
  16  // -----------------------------------------------------------------------------------
  17  /*
  18  
  19      Table of Contents
  20      -----------------
  21      Configuration
  22      Global Variables
  23  
  24      Extending Built-in Objects    
  25      - Object.extend(Element)
  26      - Array.prototype.removeDuplicates()
  27      - Array.prototype.empty()
  28  
  29      Lightbox Class Declaration
  30      - initialize()
  31      - start()
  32      - changeImage()
  33      - resizeImageContainer()
  34      - showImage()
  35      - updateDetails()
  36      - updateNav()
  37      - enableKeyboardNav()
  38      - disableKeyboardNav()
  39      - keyboardAction()
  40      - preloadNeighborImages()
  41      - end()
  42      
  43      Miscellaneous Functions
  44      - getPageScroll()
  45      - getPageSize()
  46      - getKey()
  47      - listenKey()
  48      - showSelectBoxes()
  49      - hideSelectBoxes()
  50      - pause()
  51      - initLightbox()
  52      
  53      Function Calls
  54      - addLoadEvent(initLightbox)
  55      
  56  */
  57  // -----------------------------------------------------------------------------------
  58  
  59  //
  60  //    Configuration
  61  //
  62  var fileLoadingImage = "images/loading.gif";        
  63  var fileBottomNavCloseImage = "images/closelabel.gif";
  64  
  65  var resizeSpeed = 7;    // controls the speed of the image resizing (1=slowest and 10=fastest)
  66  
  67  var borderSize = 10;    //if you adjust the padding in the CSS, you will need to update this variable
  68  
  69  // -----------------------------------------------------------------------------------
  70  
  71  //
  72  //    Global Variables
  73  //
  74  var imageArray = new Array;
  75  var activeImage;
  76  
  77  if(resizeSpeed > 10){ resizeSpeed = 10;}
  78  if(resizeSpeed < 1){ resizeSpeed = 1;}
  79  resizeDuration = (11 - resizeSpeed) * 0.15;
  80  
  81  // -----------------------------------------------------------------------------------
  82  
  83  //
  84  //    Additional methods for Element added by SU, Couloir
  85  //    - further additions by Lokesh Dhakar (huddletogether.com)
  86  //
  87  Object.extend(Element, {
  88      getWidth: function(element) {
  89             element = $(element);
  90             return element.offsetWidth; 
  91      },
  92      setWidth: function(element,w) {
  93             element = $(element);
  94          element.style.width = w +"px";
  95      },
  96      setHeight: function(element,h) {
  97             element = $(element);
  98          element.style.height = h +"px";
  99      },
 100      setTop: function(element,t) {
 101             element = $(element);
 102          element.style.top = t +"px";
 103      },
 104      setSrc: function(element,src) {
 105          element = $(element);
 106          element.src = src; 
 107      },
 108      setHref: function(element,href) {
 109          element = $(element);
 110          element.href = href; 
 111      },
 112      setInnerHTML: function(element,content) {
 113          element = $(element);
 114          element.innerHTML = content;
 115      }
 116  });
 117  
 118  // -----------------------------------------------------------------------------------
 119  
 120  //
 121  //    Extending built-in Array object
 122  //    - array.removeDuplicates()
 123  //    - array.empty()
 124  //
 125  Array.prototype.removeDuplicates = function () {
 126      for(i = 1; i < this.length; i++){
 127          if(this[i][0] == this[i-1][0]){
 128              this.splice(i,1);
 129          }
 130      }
 131  }
 132  
 133  // -----------------------------------------------------------------------------------
 134  
 135  Array.prototype.empty = function () {
 136      for(i = 0; i <= this.length; i++){
 137          this.shift();
 138      }
 139  }
 140  
 141  // -----------------------------------------------------------------------------------
 142  
 143  //
 144  //    Lightbox Class Declaration
 145  //    - initialize()
 146  //    - start()
 147  //    - changeImage()
 148  //    - resizeImageContainer()
 149  //    - showImage()
 150  //    - updateDetails()
 151  //    - updateNav()
 152  //    - enableKeyboardNav()
 153  //    - disableKeyboardNav()
 154  //    - keyboardNavAction()
 155  //    - preloadNeighborImages()
 156  //    - end()
 157  //
 158  //    Structuring of code inspired by Scott Upton (http://www.uptonic.com/)
 159  //
 160  var Lightbox = Class.create();
 161  
 162  Lightbox.prototype = {
 163      
 164      // initialize()
 165      // Constructor runs on completion of the DOM loading. Loops through anchor tags looking for 
 166      // 'lightbox' references and applies onclick events to appropriate links. The 2nd section of
 167      // the function inserts html at the bottom of the page which is used to display the shadow 
 168      // overlay and the image container.
 169      //
 170      initialize: function() {    
 171          if (!document.getElementsByTagName){ return; }
 172          var anchors = document.getElementsByTagName('a');
 173  
 174          // loop through all anchor tags
 175          for (var i=0; i<anchors.length; i++){
 176              var anchor = anchors[i];
 177              
 178              var relAttribute = String(anchor.getAttribute('rel'));
 179              
 180              // use the string.match() method to catch 'lightbox' references in the rel attribute
 181              if (anchor.getAttribute('href') && (relAttribute.toLowerCase().match('lightbox'))){
 182                  anchor.onclick = function () {myLightbox.start(this); return false;}
 183              }
 184          }
 185  
 186          // The rest of this code inserts html at the bottom of the page that looks similar to this:
 187          //
 188          //    <div id="overlay"></div>
 189          //    <div id="lightbox">
 190          //        <div id="outerImageContainer">
 191          //            <div id="imageContainer">
 192          //                <img id="lightboxImage">
 193          //                <div style="" id="hoverNav">
 194          //                    <a href="#" id="prevLink"></a>
 195          //                    <a href="#" id="nextLink"></a>
 196          //                </div>
 197          //                <div id="loading">
 198          //                    <a href="#" id="loadingLink">
 199          //                        <img src="images/loading.gif">
 200          //                    </a>
 201          //                </div>
 202          //            </div>
 203          //        </div>
 204          //        <div id="imageDataContainer">
 205          //            <div id="imageData">
 206          //                <div id="imageDetails">
 207          //                    <span id="caption"></span>
 208          //                    <span id="numberDisplay"></span>
 209          //                </div>
 210          //                <div id="bottomNav">
 211          //                    <a href="#" id="bottomNavClose">
 212          //                        <img src="images/close.gif">
 213          //                    </a>
 214          //                </div>
 215          //            </div>
 216          //        </div>
 217          //    </div>
 218  
 219  
 220          var objBody = document.getElementsByTagName("body").item(0);
 221          
 222          var objOverlay = document.createElement("div");
 223          objOverlay.setAttribute('id','overlay');
 224          objOverlay.style.display = 'none';
 225          objOverlay.onclick = function() { myLightbox.end(); return false; }
 226          objBody.appendChild(objOverlay);
 227          
 228          var objLightbox = document.createElement("div");
 229          objLightbox.setAttribute('id','lightbox');
 230          objLightbox.style.display = 'none';
 231          objBody.appendChild(objLightbox);
 232      
 233          var objOuterImageContainer = document.createElement("div");
 234          objOuterImageContainer.setAttribute('id','outerImageContainer');
 235          objLightbox.appendChild(objOuterImageContainer);
 236  
 237          var objImageContainer = document.createElement("div");
 238          objImageContainer.setAttribute('id','imageContainer');
 239          objOuterImageContainer.appendChild(objImageContainer);
 240      
 241          var objLightboxImage = document.createElement("img");
 242          objLightboxImage.setAttribute('id','lightboxImage');
 243          objImageContainer.appendChild(objLightboxImage);
 244      
 245          var objHoverNav = document.createElement("div");
 246          objHoverNav.setAttribute('id','hoverNav');
 247          objImageContainer.appendChild(objHoverNav);
 248      
 249          var objPrevLink = document.createElement("a");
 250          objPrevLink.setAttribute('id','prevLink');
 251          objPrevLink.setAttribute('href','#');
 252          objHoverNav.appendChild(objPrevLink);
 253          
 254          var objNextLink = document.createElement("a");
 255          objNextLink.setAttribute('id','nextLink');
 256          objNextLink.setAttribute('href','#');
 257          objHoverNav.appendChild(objNextLink);
 258      
 259          var objLoading = document.createElement("div");
 260          objLoading.setAttribute('id','loading');
 261          objImageContainer.appendChild(objLoading);
 262      
 263          var objLoadingLink = document.createElement("a");
 264          objLoadingLink.setAttribute('id','loadingLink');
 265          objLoadingLink.setAttribute('href','#');
 266          objLoadingLink.onclick = function() { myLightbox.end(); return false; }
 267          objLoading.appendChild(objLoadingLink);
 268      
 269          var objLoadingImage = document.createElement("img");
 270          objLoadingImage.setAttribute('src', fileLoadingImage);
 271          objLoadingLink.appendChild(objLoadingImage);
 272  
 273          var objImageDataContainer = document.createElement("div");
 274          objImageDataContainer.setAttribute('id','imageDataContainer');
 275          objImageDataContainer.className = 'clearfix';
 276          objLightbox.appendChild(objImageDataContainer);
 277  
 278          var objImageData = document.createElement("div");
 279          objImageData.setAttribute('id','imageData');
 280          objImageDataContainer.appendChild(objImageData);
 281      
 282          var objImageDetails = document.createElement("div");
 283          objImageDetails.setAttribute('id','imageDetails');
 284          objImageData.appendChild(objImageDetails);
 285      
 286          var objCaption = document.createElement("span");
 287          objCaption.setAttribute('id','caption');
 288          objImageDetails.appendChild(objCaption);
 289      
 290          var objNumberDisplay = document.createElement("span");
 291          objNumberDisplay.setAttribute('id','numberDisplay');
 292          objImageDetails.appendChild(objNumberDisplay);
 293          
 294          var objBottomNav = document.createElement("div");
 295          objBottomNav.setAttribute('id','bottomNav');
 296          objImageData.appendChild(objBottomNav);
 297      
 298          var objBottomNavCloseLink = document.createElement("a");
 299          objBottomNavCloseLink.setAttribute('id','bottomNavClose');
 300          objBottomNavCloseLink.setAttribute('href','#');
 301          objBottomNavCloseLink.onclick = function() { myLightbox.end(); return false; }
 302          objBottomNav.appendChild(objBottomNavCloseLink);
 303      
 304          var objBottomNavCloseImage = document.createElement("img");
 305          objBottomNavCloseImage.setAttribute('src', fileBottomNavCloseImage);
 306          objBottomNavCloseLink.appendChild(objBottomNavCloseImage);
 307      },
 308      
 309      //
 310      //    start()
 311      //    Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
 312      //
 313      start: function(imageLink) {    
 314  
 315          hideSelectBoxes();
 316  
 317          // stretch overlay to fill page and fade in
 318          var arrayPageSize = getPageSize();
 319          Element.setHeight('overlay', arrayPageSize[1]);
 320          new Effect.Appear('overlay', { duration: 0.2, from: 0.0, to: 0.8 });
 321  
 322          imageArray = [];
 323          imageNum = 0;        
 324  
 325          if (!document.getElementsByTagName){ return; }
 326          var anchors = document.getElementsByTagName('a');
 327  
 328          // if image is NOT part of a set..
 329          if((imageLink.getAttribute('rel') == 'lightbox')){
 330              // add single image to imageArray
 331              imageArray.push(new Array(imageLink.getAttribute('href'), imageLink.getAttribute('title')));            
 332          } else {
 333          // if image is part of a set..
 334  
 335              // loop through anchors, find other images in set, and add them to imageArray
 336              for (var i=0; i<anchors.length; i++){
 337                  var anchor = anchors[i];
 338                  if (anchor.getAttribute('href') && (anchor.getAttribute('rel') == imageLink.getAttribute('rel'))){
 339                      imageArray.push(new Array(anchor.getAttribute('href'), anchor.getAttribute('title')));
 340                  }
 341              }
 342              imageArray.removeDuplicates();
 343              while(imageArray[imageNum][0] != imageLink.getAttribute('href')) { imageNum++;}
 344          }
 345  
 346          // calculate top offset for the lightbox and display 
 347          var arrayPageSize = getPageSize();
 348          var arrayPageScroll = getPageScroll();
 349          var lightboxTop = arrayPageScroll[1] + (arrayPageSize[3] / 15);
 350  
 351          Element.setTop('lightbox', lightboxTop);
 352          Element.show('lightbox');
 353          
 354          this.changeImage(imageNum);
 355      },
 356  
 357      //
 358      //    changeImage()
 359      //    Hide most elements and preload image in preparation for resizing image container.
 360      //
 361      changeImage: function(imageNum) {    
 362          
 363          activeImage = imageNum;    // update global var
 364  
 365          // hide elements during transition
 366          Element.show('loading');
 367          Element.hide('lightboxImage');
 368          Element.hide('hoverNav');
 369          Element.hide('prevLink');
 370          Element.hide('nextLink');
 371          Element.hide('imageDataContainer');
 372          Element.hide('numberDisplay');        
 373          
 374          imgPreloader = new Image();
 375          
 376          // once image is preloaded, resize image container
 377          imgPreloader.onload=function(){
 378              Element.setSrc('lightboxImage', imageArray[activeImage][0]);
 379              myLightbox.resizeImageContainer(imgPreloader.width, imgPreloader.height);
 380          }
 381          imgPreloader.src = imageArray[activeImage][0];
 382      },
 383  
 384      //
 385      //    resizeImageContainer()
 386      //
 387      resizeImageContainer: function( imgWidth, imgHeight) {
 388  
 389          // get current height and width
 390          this.wCur = Element.getWidth('outerImageContainer');
 391          this.hCur = Element.getHeight('outerImageContainer');
 392  
 393          // scalars based on change from old to new
 394          this.xScale = ((imgWidth  + (borderSize * 2)) / this.wCur) * 100;
 395          this.yScale = ((imgHeight  + (borderSize * 2)) / this.hCur) * 100;
 396  
 397          // calculate size difference between new and old image, and resize if necessary
 398          wDiff = (this.wCur - borderSize * 2) - imgWidth;
 399          hDiff = (this.hCur - borderSize * 2) - imgHeight;
 400  
 401          if(!( hDiff == 0)){ new Effect.Scale('outerImageContainer', this.yScale, {scaleX: false, duration: resizeDuration, queue: 'front'}); }
 402          if(!( wDiff == 0)){ new Effect.Scale('outerImageContainer', this.xScale, {scaleY: false, delay: resizeDuration, duration: resizeDuration}); }
 403  
 404          // if new and old image are same size and no scaling transition is necessary, 
 405          // do a quick pause to prevent image flicker.
 406          if((hDiff == 0) && (wDiff == 0)){
 407              if (navigator.appVersion.indexOf("MSIE")!=-1){ pause(250); } else { pause(100);} 
 408          }
 409  
 410          Element.setHeight('prevLink', imgHeight);
 411          Element.setHeight('nextLink', imgHeight);
 412          Element.setWidth( 'imageDataContainer', imgWidth + (borderSize * 2));
 413  
 414          this.showImage();
 415      },
 416      
 417      //
 418      //    showImage()
 419      //    Display image and begin preloading neighbors.
 420      //
 421      showImage: function(){
 422          Element.hide('loading');
 423          new Effect.Appear('lightboxImage', { duration: 0.5, queue: 'end', afterFinish: function(){    myLightbox.updateDetails(); } });
 424          this.preloadNeighborImages();
 425      },
 426  
 427      //
 428      //    updateDetails()
 429      //    Display caption, image number, and bottom nav.
 430      //
 431      updateDetails: function() {
 432      
 433          Element.show('caption');
 434          Element.setInnerHTML( 'caption', imageArray[activeImage][1]);
 435          
 436          // if image is part of set display 'Image x of x' 
 437          if(imageArray.length > 1){
 438              Element.show('numberDisplay');
 439              Element.setInnerHTML( 'numberDisplay', "Image " + eval(activeImage + 1) + " of " + imageArray.length);
 440          }
 441  
 442          new Effect.Parallel(
 443              [ new Effect.SlideDown( 'imageDataContainer', { sync: true, duration: resizeDuration + 0.25, from: 0.0, to: 1.0 }), 
 444                new Effect.Appear('imageDataContainer', { sync: true, duration: 1.0 }) ], 
 445              { duration: 0.65, afterFinish: function() { myLightbox.updateNav();} } 
 446          );
 447      },
 448  
 449      //
 450      //    updateNav()
 451      //    Display appropriate previous and next hover navigation.
 452      //
 453      updateNav: function() {
 454  
 455          Element.show('hoverNav');                
 456  
 457          // if not first image in set, display prev image button
 458          if(activeImage != 0){
 459              Element.show('prevLink');
 460              document.getElementById('prevLink').onclick = function() {
 461                  myLightbox.changeImage(activeImage - 1); return false;
 462              }
 463          }
 464  
 465          // if not last image in set, display next image button
 466          if(activeImage != (imageArray.length - 1)){
 467              Element.show('nextLink');
 468              document.getElementById('nextLink').onclick = function() {
 469                  myLightbox.changeImage(activeImage + 1); return false;
 470              }
 471          }
 472          
 473          this.enableKeyboardNav();
 474      },
 475  
 476      //
 477      //    enableKeyboardNav()
 478      //
 479      enableKeyboardNav: function() {
 480          document.onkeydown = this.keyboardAction; 
 481      },
 482  
 483      //
 484      //    disableKeyboardNav()
 485      //
 486      disableKeyboardNav: function() {
 487          document.onkeydown = '';
 488      },
 489  
 490      //
 491      //    keyboardAction()
 492      //
 493      keyboardAction: function(e) {
 494          if (e == null) { // ie
 495              keycode = event.keyCode;
 496          } else { // mozilla
 497              keycode = e.which;
 498          }
 499  
 500          key = String.fromCharCode(keycode).toLowerCase();
 501          
 502          if((key == 'x') || (key == 'o') || (key == 'c')){    // close lightbox
 503              myLightbox.end();
 504          } else if(key == 'p'){    // display previous image
 505              if(activeImage != 0){
 506                  myLightbox.disableKeyboardNav();
 507                  myLightbox.changeImage(activeImage - 1);
 508              }
 509          } else if(key == 'n'){    // display next image
 510              if(activeImage != (imageArray.length - 1)){
 511                  myLightbox.disableKeyboardNav();
 512                  myLightbox.changeImage(activeImage + 1);
 513              }
 514          }
 515  
 516  
 517      },
 518  
 519      //
 520      //    preloadNeighborImages()
 521      //    Preload previous and next images.
 522      //
 523      preloadNeighborImages: function(){
 524  
 525          if((imageArray.length - 1) > activeImage){
 526              preloadNextImage = new Image();
 527              preloadNextImage.src = imageArray[activeImage + 1][0];
 528          }
 529          if(activeImage > 0){
 530              preloadPrevImage = new Image();
 531              preloadPrevImage.src = imageArray[activeImage - 1][0];
 532          }
 533      
 534      },
 535  
 536      //
 537      //    end()
 538      //
 539      end: function() {
 540          this.disableKeyboardNav();
 541          Element.hide('lightbox');
 542          new Effect.Fade('overlay', { duration: 0.2});
 543          showSelectBoxes();
 544      }
 545  }
 546  
 547  // -----------------------------------------------------------------------------------
 548  
 549  //
 550  // getPageScroll()
 551  // Returns array with x,y page scroll values.
 552  // Core code from - quirksmode.org
 553  //
 554  function getPageScroll(){
 555  
 556      var yScroll;
 557  
 558      if (self.pageYOffset) {
 559          yScroll = self.pageYOffset;
 560      } else if (document.documentElement && document.documentElement.scrollTop){     // Explorer 6 Strict
 561          yScroll = document.documentElement.scrollTop;
 562      } else if (document.body) {// all other Explorers
 563          yScroll = document.body.scrollTop;
 564      }
 565  
 566      arrayPageScroll = new Array('',yScroll) 
 567      return arrayPageScroll;
 568  }
 569  
 570  // -----------------------------------------------------------------------------------
 571  
 572  //
 573  // getPageSize()
 574  // Returns array with page width, height and window width, height
 575  // Core code from - quirksmode.org
 576  // Edit for Firefox by pHaez
 577  //
 578  function getPageSize(){
 579      
 580      var xScroll, yScroll;
 581      
 582      if (window.innerHeight && window.scrollMaxY) {    
 583          xScroll = document.body.scrollWidth;
 584          yScroll = window.innerHeight + window.scrollMaxY;
 585      } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
 586          xScroll = document.body.scrollWidth;
 587          yScroll = document.body.scrollHeight;
 588      } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
 589          xScroll = document.body.offsetWidth;
 590          yScroll = document.body.offsetHeight;
 591      }
 592      
 593      var windowWidth, windowHeight;
 594      if (self.innerHeight) {    // all except Explorer
 595          windowWidth = self.innerWidth;
 596          windowHeight = self.innerHeight;
 597      } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
 598          windowWidth = document.documentElement.clientWidth;
 599          windowHeight = document.documentElement.clientHeight;
 600      } else if (document.body) { // other Explorers
 601          windowWidth = document.body.clientWidth;
 602          windowHeight = document.body.clientHeight;
 603      }    
 604      
 605      // for small pages with total height less then height of the viewport
 606      if(yScroll < windowHeight){
 607          pageHeight = windowHeight;
 608      } else { 
 609          pageHeight = yScroll;
 610      }
 611  
 612      // for small pages with total width less then width of the viewport
 613      if(xScroll < windowWidth){    
 614          pageWidth = windowWidth;
 615      } else {
 616          pageWidth = xScroll;
 617      }
 618  
 619  
 620      arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight) 
 621      return arrayPageSize;
 622  }
 623  
 624  // -----------------------------------------------------------------------------------
 625  
 626  //
 627  // getKey(key)
 628  // Gets keycode. If 'x' is pressed then it hides the lightbox.
 629  //
 630  function getKey(e){
 631      if (e == null) { // ie
 632          keycode = event.keyCode;
 633      } else { // mozilla
 634          keycode = e.which;
 635      }
 636      key = String.fromCharCode(keycode).toLowerCase();
 637      
 638      if(key == 'x'){
 639      }
 640  }
 641  
 642  // -----------------------------------------------------------------------------------
 643  
 644  //
 645  // listenKey()
 646  //
 647  function listenKey () {    document.onkeypress = getKey; }
 648      
 649  // ---------------------------------------------------
 650  
 651  function showSelectBoxes(){
 652      selects = document.getElementsByTagName("select");
 653      for (i = 0; i != selects.length; i++) {
 654          selects[i].style.visibility = "visible";
 655      }
 656  }
 657  
 658  // ---------------------------------------------------
 659  
 660  function hideSelectBoxes(){
 661      selects = document.getElementsByTagName("select");
 662      for (i = 0; i != selects.length; i++) {
 663          selects[i].style.visibility = "hidden";
 664      }
 665  }
 666  
 667  // ---------------------------------------------------
 668  
 669  //
 670  // pause(numberMillis)
 671  // Pauses code execution for specified time. Uses busy code, not good.
 672  // Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602
 673  //
 674  function pause(numberMillis) {
 675      var now = new Date();
 676      var exitTime = now.getTime() + numberMillis;
 677      while (true) {
 678          now = new Date();
 679          if (now.getTime() > exitTime)
 680              return;
 681      }
 682  }
 683  
 684  // ---------------------------------------------------
 685  
 686  
 687  
 688  function initLightbox() { myLightbox = new Lightbox(); }
 689  Event.observe(window, 'load', initLightbox, false);


Généré le : Fri Mar 30 01:27:52 2007 par Balluche grâce à PHPXref 0.7