Basic PHP document management system, including automatic detection of corporate logos in letters
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

lightbox.js 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. // -----------------------------------------------------------------------------------
  2. //
  3. // Lightbox v2.04
  4. // by Lokesh Dhakar - http://www.lokeshdhakar.com
  5. // Last Modification: 2/9/08
  6. //
  7. // For more information, visit:
  8. // http://lokeshdhakar.com/projects/lightbox2/
  9. //
  10. // Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
  11. // - Free for use in both personal and commercial projects
  12. // - Attribution requires leaving author name, author link, and the license info intact.
  13. //
  14. // Thanks: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.com), and Thomas Fuchs(mir.aculo.us) for ideas, libs, and snippets.
  15. // Artemy Tregubenko (arty.name) for cleanup and help in updating to latest ver of proto-aculous.
  16. //
  17. // -----------------------------------------------------------------------------------
  18. /*
  19. Table of Contents
  20. -----------------
  21. Configuration
  22. Lightbox Class Declaration
  23. - initialize()
  24. - updateImageList()
  25. - start()
  26. - changeImage()
  27. - resizeImageContainer()
  28. - showImage()
  29. - updateDetails()
  30. - updateNav()
  31. - enableKeyboardNav()
  32. - disableKeyboardNav()
  33. - keyboardAction()
  34. - preloadNeighborImages()
  35. - end()
  36. Function Calls
  37. - document.observe()
  38. */
  39. // -----------------------------------------------------------------------------------
  40. //
  41. // Configurationl
  42. //
  43. LightboxOptions = Object.extend({
  44. fileLoadingImage: 'images/loading.gif',
  45. fileBottomNavCloseImage: 'images/closelabel.gif',
  46. overlayOpacity: 0.8, // controls transparency of shadow overlay
  47. animate: true, // toggles resizing animations
  48. resizeSpeed: 7, // controls the speed of the image resizing animations (1=slowest and 10=fastest)
  49. borderSize: 10, //if you adjust the padding in the CSS, you will need to update this variable
  50. // When grouping images this is used to write: Image # of #.
  51. // Change it for non-english localization
  52. labelImage: "Image",
  53. labelOf: "of"
  54. }, window.LightboxOptions || {});
  55. // -----------------------------------------------------------------------------------
  56. var Lightbox = Class.create();
  57. Lightbox.prototype = {
  58. imageArray: [],
  59. activeImage: undefined,
  60. // initialize()
  61. // Constructor runs on completion of the DOM loading. Calls updateImageList and then
  62. // the function inserts html at the bottom of the page which is used to display the shadow
  63. // overlay and the image container.
  64. //
  65. initialize: function() {
  66. this.updateImageList();
  67. this.keyboardAction = this.keyboardAction.bindAsEventListener(this);
  68. if (LightboxOptions.resizeSpeed > 10) LightboxOptions.resizeSpeed = 10;
  69. if (LightboxOptions.resizeSpeed < 1) LightboxOptions.resizeSpeed = 1;
  70. this.resizeDuration = LightboxOptions.animate ? ((11 - LightboxOptions.resizeSpeed) * 0.15) : 0;
  71. this.overlayDuration = LightboxOptions.animate ? 0.2 : 0; // shadow fade in/out duration
  72. // When Lightbox starts it will resize itself from 250 by 250 to the current image dimension.
  73. // If animations are turned off, it will be hidden as to prevent a flicker of a
  74. // white 250 by 250 box.
  75. var size = (LightboxOptions.animate ? 250 : 1) + 'px';
  76. // Code inserts html at the bottom of the page that looks similar to this:
  77. //
  78. // <div id="overlay"></div>
  79. // <div id="lightbox">
  80. // <div id="outerImageContainer">
  81. // <div id="imageContainer">
  82. // <img id="lightboxImage">
  83. // <div style="" id="hoverNav">
  84. // <a href="#" id="prevLink"></a>
  85. // <a href="#" id="nextLink"></a>
  86. // </div>
  87. // <div id="loading">
  88. // <a href="#" id="loadingLink">
  89. // <img src="images/loading.gif">
  90. // </a>
  91. // </div>
  92. // </div>
  93. // </div>
  94. // <div id="imageDataContainer">
  95. // <div id="imageData">
  96. // <div id="imageDetails">
  97. // <span id="caption"></span>
  98. // <span id="numberDisplay"></span>
  99. // </div>
  100. // <div id="bottomNav">
  101. // <a href="#" id="bottomNavClose">
  102. // <img src="images/close.gif">
  103. // </a>
  104. // </div>
  105. // </div>
  106. // </div>
  107. // </div>
  108. var objBody = $$('body')[0];
  109. objBody.appendChild(Builder.node('div',{id:'overlay'}));
  110. objBody.appendChild(Builder.node('div',{id:'lightbox'}, [
  111. Builder.node('div',{id:'outerImageContainer'},
  112. Builder.node('div',{id:'imageContainer'}, [
  113. Builder.node('img',{id:'lightboxImage'}),
  114. Builder.node('div',{id:'hoverNav'}, [
  115. Builder.node('a',{id:'prevLink', href: '#' }),
  116. Builder.node('a',{id:'nextLink', href: '#' })
  117. ]),
  118. Builder.node('div',{id:'loading'},
  119. Builder.node('a',{id:'loadingLink', href: '#' },
  120. Builder.node('img', {src: LightboxOptions.fileLoadingImage})
  121. )
  122. )
  123. ])
  124. ),
  125. Builder.node('div', {id:'imageDataContainer'},
  126. Builder.node('div',{id:'imageData'}, [
  127. Builder.node('div',{id:'imageDetails'}, [
  128. Builder.node('span',{id:'caption'}),
  129. Builder.node('span',{id:'numberDisplay'})
  130. ]),
  131. Builder.node('div',{id:'bottomNav'},
  132. Builder.node('a',{id:'bottomNavClose', href: '#' },
  133. Builder.node('img', { src: LightboxOptions.fileBottomNavCloseImage })
  134. )
  135. )
  136. ])
  137. )
  138. ]));
  139. $('overlay').hide().observe('click', (function() { this.end(); }).bind(this));
  140. $('lightbox').hide().observe('click', (function(event) { if (event.element().id == 'lightbox') this.end(); }).bind(this));
  141. $('outerImageContainer').setStyle({ width: size, height: size });
  142. $('prevLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage - 1); }).bindAsEventListener(this));
  143. $('nextLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage + 1); }).bindAsEventListener(this));
  144. $('loadingLink').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
  145. $('bottomNavClose').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
  146. var th = this;
  147. (function(){
  148. var ids =
  149. 'overlay lightbox outerImageContainer imageContainer lightboxImage hoverNav prevLink nextLink loading loadingLink ' +
  150. 'imageDataContainer imageData imageDetails caption numberDisplay bottomNav bottomNavClose';
  151. $w(ids).each(function(id){ th[id] = $(id); });
  152. }).defer();
  153. },
  154. //
  155. // updateImageList()
  156. // Loops through anchor tags looking for 'lightbox' references and applies onclick
  157. // events to appropriate links. You can rerun after dynamically adding images w/ajax.
  158. //
  159. updateImageList: function() {
  160. this.updateImageList = Prototype.emptyFunction;
  161. document.observe('click', (function(event){
  162. var target = event.findElement('a[rel^=lightbox]') || event.findElement('area[rel^=lightbox]');
  163. if (target) {
  164. event.stop();
  165. this.start(target);
  166. }
  167. }).bind(this));
  168. },
  169. //
  170. // start()
  171. // Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
  172. //
  173. start: function(imageLink) {
  174. $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'hidden' });
  175. // stretch overlay to fill page and fade in
  176. var arrayPageSize = this.getPageSize();
  177. $('overlay').setStyle({ width: arrayPageSize[0] + 'px', height: arrayPageSize[1] + 'px' });
  178. new Effect.Appear(this.overlay, { duration: this.overlayDuration, from: 0.0, to: LightboxOptions.overlayOpacity });
  179. this.imageArray = [];
  180. var imageNum = 0;
  181. if ((imageLink.rel == 'lightbox')){
  182. // if image is NOT part of a set, add single image to imageArray
  183. this.imageArray.push([imageLink.href, imageLink.title]);
  184. } else {
  185. // if image is part of a set..
  186. this.imageArray =
  187. $$(imageLink.tagName + '[href][rel="' + imageLink.rel + '"]').
  188. collect(function(anchor){ return [anchor.href, anchor.title]; }).
  189. uniq();
  190. while (this.imageArray[imageNum][0] != imageLink.href) { imageNum++; }
  191. }
  192. // calculate top and left offset for the lightbox
  193. var arrayPageScroll = document.viewport.getScrollOffsets();
  194. var lightboxTop = arrayPageScroll[1] + (document.viewport.getHeight() / 10);
  195. var lightboxLeft = arrayPageScroll[0];
  196. this.lightbox.setStyle({ top: lightboxTop + 'px', left: lightboxLeft + 'px' }).show();
  197. this.changeImage(imageNum);
  198. },
  199. //
  200. // changeImage()
  201. // Hide most elements and preload image in preparation for resizing image container.
  202. //
  203. changeImage: function(imageNum) {
  204. this.activeImage = imageNum; // update global var
  205. // hide elements during transition
  206. if (LightboxOptions.animate) this.loading.show();
  207. this.lightboxImage.hide();
  208. this.hoverNav.hide();
  209. this.prevLink.hide();
  210. this.nextLink.hide();
  211. // HACK: Opera9 does not currently support scriptaculous opacity and appear fx
  212. this.imageDataContainer.setStyle({opacity: .0001});
  213. this.numberDisplay.hide();
  214. var imgPreloader = new Image();
  215. // once image is preloaded, resize image container
  216. imgPreloader.onload = (function(){
  217. this.lightboxImage.src = this.imageArray[this.activeImage][0];
  218. this.resizeImageContainer(imgPreloader.width, imgPreloader.height);
  219. }).bind(this);
  220. imgPreloader.src = this.imageArray[this.activeImage][0];
  221. },
  222. //
  223. // resizeImageContainer()
  224. //
  225. resizeImageContainer: function(imgWidth, imgHeight) {
  226. // get current width and height
  227. var widthCurrent = this.outerImageContainer.getWidth();
  228. var heightCurrent = this.outerImageContainer.getHeight();
  229. // get new width and height
  230. var widthNew = (imgWidth + LightboxOptions.borderSize * 2);
  231. var heightNew = (imgHeight + LightboxOptions.borderSize * 2);
  232. // scalars based on change from old to new
  233. var xScale = (widthNew / widthCurrent) * 100;
  234. var yScale = (heightNew / heightCurrent) * 100;
  235. // calculate size difference between new and old image, and resize if necessary
  236. var wDiff = widthCurrent - widthNew;
  237. var hDiff = heightCurrent - heightNew;
  238. if (hDiff != 0) new Effect.Scale(this.outerImageContainer, yScale, {scaleX: false, duration: this.resizeDuration, queue: 'front'});
  239. if (wDiff != 0) new Effect.Scale(this.outerImageContainer, xScale, {scaleY: false, duration: this.resizeDuration, delay: this.resizeDuration});
  240. // if new and old image are same size and no scaling transition is necessary,
  241. // do a quick pause to prevent image flicker.
  242. var timeout = 0;
  243. if ((hDiff == 0) && (wDiff == 0)){
  244. timeout = 100;
  245. if (Prototype.Browser.IE) timeout = 250;
  246. }
  247. (function(){
  248. this.prevLink.setStyle({ height: imgHeight + 'px' });
  249. this.nextLink.setStyle({ height: imgHeight + 'px' });
  250. this.imageDataContainer.setStyle({ width: widthNew + 'px' });
  251. this.showImage();
  252. }).bind(this).delay(timeout / 1000);
  253. },
  254. //
  255. // showImage()
  256. // Display image and begin preloading neighbors.
  257. //
  258. showImage: function(){
  259. this.loading.hide();
  260. new Effect.Appear(this.lightboxImage, {
  261. duration: this.resizeDuration,
  262. queue: 'end',
  263. afterFinish: (function(){ this.updateDetails(); }).bind(this)
  264. });
  265. this.preloadNeighborImages();
  266. },
  267. //
  268. // updateDetails()
  269. // Display caption, image number, and bottom nav.
  270. //
  271. updateDetails: function() {
  272. // if caption is not null
  273. if (this.imageArray[this.activeImage][1] != ""){
  274. this.caption.update(this.imageArray[this.activeImage][1]).show();
  275. }
  276. // if image is part of set display 'Image x of x'
  277. if (this.imageArray.length > 1){
  278. this.numberDisplay.update( LightboxOptions.labelImage + ' ' + (this.activeImage + 1) + ' ' + LightboxOptions.labelOf + ' ' + this.imageArray.length).show();
  279. }
  280. new Effect.Parallel(
  281. [
  282. new Effect.SlideDown(this.imageDataContainer, { sync: true, duration: this.resizeDuration, from: 0.0, to: 1.0 }),
  283. new Effect.Appear(this.imageDataContainer, { sync: true, duration: this.resizeDuration })
  284. ],
  285. {
  286. duration: this.resizeDuration,
  287. afterFinish: (function() {
  288. // update overlay size and update nav
  289. var arrayPageSize = this.getPageSize();
  290. this.overlay.setStyle({ height: arrayPageSize[1] + 'px' });
  291. this.updateNav();
  292. }).bind(this)
  293. }
  294. );
  295. },
  296. //
  297. // updateNav()
  298. // Display appropriate previous and next hover navigation.
  299. //
  300. updateNav: function() {
  301. this.hoverNav.show();
  302. // if not first image in set, display prev image button
  303. if (this.activeImage > 0) this.prevLink.show();
  304. // if not last image in set, display next image button
  305. if (this.activeImage < (this.imageArray.length - 1)) this.nextLink.show();
  306. this.enableKeyboardNav();
  307. },
  308. //
  309. // enableKeyboardNav()
  310. //
  311. enableKeyboardNav: function() {
  312. document.observe('keydown', this.keyboardAction);
  313. },
  314. //
  315. // disableKeyboardNav()
  316. //
  317. disableKeyboardNav: function() {
  318. document.stopObserving('keydown', this.keyboardAction);
  319. },
  320. //
  321. // keyboardAction()
  322. //
  323. keyboardAction: function(event) {
  324. var keycode = event.keyCode;
  325. var escapeKey;
  326. if (event.DOM_VK_ESCAPE) { // mozilla
  327. escapeKey = event.DOM_VK_ESCAPE;
  328. } else { // ie
  329. escapeKey = 27;
  330. }
  331. var key = String.fromCharCode(keycode).toLowerCase();
  332. if (key.match(/x|o|c/) || (keycode == escapeKey)){ // close lightbox
  333. this.end();
  334. } else if ((key == 'p') || (keycode == 37)){ // display previous image
  335. if (this.activeImage != 0){
  336. this.disableKeyboardNav();
  337. this.changeImage(this.activeImage - 1);
  338. }
  339. } else if ((key == 'n') || (keycode == 39)){ // display next image
  340. if (this.activeImage != (this.imageArray.length - 1)){
  341. this.disableKeyboardNav();
  342. this.changeImage(this.activeImage + 1);
  343. }
  344. }
  345. },
  346. //
  347. // preloadNeighborImages()
  348. // Preload previous and next images.
  349. //
  350. preloadNeighborImages: function(){
  351. var preloadNextImage, preloadPrevImage;
  352. if (this.imageArray.length > this.activeImage + 1){
  353. preloadNextImage = new Image();
  354. preloadNextImage.src = this.imageArray[this.activeImage + 1][0];
  355. }
  356. if (this.activeImage > 0){
  357. preloadPrevImage = new Image();
  358. preloadPrevImage.src = this.imageArray[this.activeImage - 1][0];
  359. }
  360. },
  361. //
  362. // end()
  363. //
  364. end: function() {
  365. this.disableKeyboardNav();
  366. this.lightbox.hide();
  367. new Effect.Fade(this.overlay, { duration: this.overlayDuration });
  368. $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'visible' });
  369. },
  370. //
  371. // getPageSize()
  372. //
  373. getPageSize: function() {
  374. var xScroll, yScroll;
  375. if (window.innerHeight && window.scrollMaxY) {
  376. xScroll = window.innerWidth + window.scrollMaxX;
  377. yScroll = window.innerHeight + window.scrollMaxY;
  378. } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
  379. xScroll = document.body.scrollWidth;
  380. yScroll = document.body.scrollHeight;
  381. } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
  382. xScroll = document.body.offsetWidth;
  383. yScroll = document.body.offsetHeight;
  384. }
  385. var windowWidth, windowHeight;
  386. if (self.innerHeight) { // all except Explorer
  387. if(document.documentElement.clientWidth){
  388. windowWidth = document.documentElement.clientWidth;
  389. } else {
  390. windowWidth = self.innerWidth;
  391. }
  392. windowHeight = self.innerHeight;
  393. } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
  394. windowWidth = document.documentElement.clientWidth;
  395. windowHeight = document.documentElement.clientHeight;
  396. } else if (document.body) { // other Explorers
  397. windowWidth = document.body.clientWidth;
  398. windowHeight = document.body.clientHeight;
  399. }
  400. // for small pages with total height less then height of the viewport
  401. if(yScroll < windowHeight){
  402. pageHeight = windowHeight;
  403. } else {
  404. pageHeight = yScroll;
  405. }
  406. // for small pages with total width less then width of the viewport
  407. if(xScroll < windowWidth){
  408. pageWidth = xScroll;
  409. } else {
  410. pageWidth = windowWidth;
  411. }
  412. return [pageWidth,pageHeight];
  413. }
  414. }
  415. document.observe('dom:loaded', function () { new Lightbox(); });