You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1018 lines
32 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. /*!
  2. * # Semantic UI 1.10.3 - Visibility
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2014 Contributors
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. ;(function ( $, window, document, undefined ) {
  12. "use strict";
  13. $.fn.visibility = function(parameters) {
  14. var
  15. $allModules = $(this),
  16. moduleSelector = $allModules.selector || '',
  17. time = new Date().getTime(),
  18. performance = [],
  19. query = arguments[0],
  20. methodInvoked = (typeof query == 'string'),
  21. queryArguments = [].slice.call(arguments, 1),
  22. returnedValue
  23. ;
  24. $allModules
  25. .each(function() {
  26. var
  27. settings = $.extend(true, {}, $.fn.visibility.settings, parameters),
  28. className = settings.className,
  29. namespace = settings.namespace,
  30. error = settings.error,
  31. eventNamespace = '.' + namespace,
  32. moduleNamespace = 'module-' + namespace,
  33. $window = $(window),
  34. $module = $(this),
  35. $context = $(settings.context),
  36. $container = $module.offsetParent(),
  37. selector = $module.selector || '',
  38. instance = $module.data(moduleNamespace),
  39. requestAnimationFrame = window.requestAnimationFrame
  40. || window.mozRequestAnimationFrame
  41. || window.webkitRequestAnimationFrame
  42. || window.msRequestAnimationFrame
  43. || function(callback) { setTimeout(callback, 0); },
  44. element = this,
  45. observer,
  46. module
  47. ;
  48. module = {
  49. initialize: function() {
  50. module.verbose('Initializing visibility', settings);
  51. module.setup.cache();
  52. module.save.position();
  53. if( module.should.trackChanges() ) {
  54. module.bindEvents();
  55. if(settings.type == 'image') {
  56. module.setup.image();
  57. }
  58. if(settings.type == 'fixed') {
  59. module.setup.fixed();
  60. }
  61. }
  62. if(settings.initialCheck) {
  63. module.checkVisibility();
  64. }
  65. if(settings.observeChanges) {
  66. module.observeChanges();
  67. }
  68. module.instantiate();
  69. },
  70. instantiate: function() {
  71. module.verbose('Storing instance of module', module);
  72. instance = module;
  73. $module
  74. .data(moduleNamespace, module)
  75. ;
  76. },
  77. destroy: function() {
  78. module.verbose('Destroying previous module');
  79. $module
  80. .off(eventNamespace)
  81. .removeData(moduleNamespace)
  82. ;
  83. },
  84. observeChanges: function() {
  85. var
  86. context = $context[0]
  87. ;
  88. if('MutationObserver' in window) {
  89. observer = new MutationObserver(function(mutations) {
  90. module.verbose('DOM tree modified, updating visibility calculations');
  91. module.refresh();
  92. });
  93. observer.observe(element, {
  94. childList : true,
  95. subtree : true
  96. });
  97. module.debug('Setting up mutation observer', observer);
  98. }
  99. },
  100. bindEvents: function() {
  101. module.verbose('Binding visibility events to scroll and resize');
  102. $window
  103. .on('resize' + eventNamespace, module.event.refresh)
  104. ;
  105. $context
  106. .on('scroll' + eventNamespace, module.event.scroll)
  107. ;
  108. },
  109. event: {
  110. refresh: function() {
  111. requestAnimationFrame(module.refresh);
  112. },
  113. scroll: function() {
  114. module.verbose('Scroll position changed');
  115. if(settings.throttle) {
  116. clearTimeout(module.timer);
  117. module.timer = setTimeout(module.checkVisibility, settings.throttle);
  118. }
  119. else {
  120. requestAnimationFrame(module.checkVisibility);
  121. }
  122. }
  123. },
  124. precache: function(images, callback) {
  125. if (!(images instanceof Array)) {
  126. images = [images];
  127. }
  128. var
  129. imagesLength = images.length,
  130. loadedCounter = 0,
  131. cache = [],
  132. cacheImage = document.createElement('img'),
  133. handleLoad = function() {
  134. loadedCounter++;
  135. if (loadedCounter >= images.length) {
  136. if ($.isFunction(callback)) {
  137. callback();
  138. }
  139. }
  140. }
  141. ;
  142. while (imagesLength--) {
  143. cacheImage = document.createElement('img');
  144. cacheImage.onload = handleLoad;
  145. cacheImage.onerror = handleLoad;
  146. cacheImage.src = images[imagesLength];
  147. cache.push(cacheImage);
  148. }
  149. },
  150. should: {
  151. trackChanges: function() {
  152. if(methodInvoked && queryArguments.length > 0) {
  153. module.debug('One time query, no need to bind events');
  154. return false;
  155. }
  156. module.debug('Query is attaching callbacks, watching for changes with scroll');
  157. return true;
  158. }
  159. },
  160. setup: {
  161. cache: function() {
  162. module.cache = {
  163. occurred : {},
  164. screen : {},
  165. element : {},
  166. };
  167. },
  168. image: function() {
  169. var
  170. src = $module.data('src')
  171. ;
  172. if(src) {
  173. module.verbose('Lazy loading image', src);
  174. // show when top visible
  175. module.topVisible(function() {
  176. module.debug('Image top visible', element);
  177. module.precache(src, function() {
  178. module.set.image(src);
  179. settings.onTopVisible = false;
  180. });
  181. });
  182. }
  183. },
  184. fixed: function() {
  185. module.verbose('Setting up fixed on element pass');
  186. $module
  187. .visibility({
  188. once: false,
  189. continuous: false,
  190. onTopPassed: function() {
  191. $module
  192. .addClass(className.fixed)
  193. .css({
  194. position: 'fixed',
  195. top: settings.offset + 'px'
  196. })
  197. ;
  198. if(settings.transition) {
  199. if($.fn.transition !== undefined) {
  200. $module.transition(settings.transition, settings.duration);
  201. }
  202. }
  203. },
  204. onTopPassedReverse: function() {
  205. $module
  206. .removeClass(className.fixed)
  207. .css({
  208. position: '',
  209. top: ''
  210. })
  211. ;
  212. }
  213. })
  214. ;
  215. }
  216. },
  217. set: {
  218. image: function(src) {
  219. var
  220. offScreen = (module.cache.screen.bottom < module.cache.element.top)
  221. ;
  222. $module
  223. .attr('src', src)
  224. ;
  225. if(offScreen) {
  226. module.verbose('Image outside browser, no show animation');
  227. $module.show();
  228. }
  229. else {
  230. if(settings.transition) {
  231. if( $.fn.transition !== undefined ) {
  232. $module.transition(settings.transition, settings.duration);
  233. }
  234. else {
  235. $module.fadeIn(settings.duration);
  236. }
  237. }
  238. else {
  239. $module.show();
  240. }
  241. }
  242. }
  243. },
  244. is: {
  245. visible: function() {
  246. if(module.cache && module.cache.element) {
  247. return (module.cache.element.height > 0 && module.cache.element.width > 0);
  248. }
  249. return false;
  250. }
  251. },
  252. refresh: function() {
  253. module.debug('Refreshing constants (element width/height)');
  254. module.reset();
  255. module.save.position();
  256. module.checkVisibility();
  257. settings.onRefresh.call(element);
  258. },
  259. reset: function() {
  260. module.verbose('Reseting all cached values');
  261. if( $.isPlainObject(module.cache) ) {
  262. module.cache.screen = {};
  263. module.cache.element = {};
  264. }
  265. },
  266. checkVisibility: function() {
  267. module.verbose('Checking visibility of element', module.cache.element);
  268. module.save.calculations();
  269. if( module.is.visible() ) {
  270. // percentage
  271. module.passed();
  272. // reverse (must be first)
  273. module.passingReverse();
  274. module.topVisibleReverse();
  275. module.bottomVisibleReverse();
  276. module.topPassedReverse();
  277. module.bottomPassedReverse();
  278. // one time
  279. module.passing();
  280. module.topVisible();
  281. module.bottomVisible();
  282. module.topPassed();
  283. module.bottomPassed();
  284. }
  285. },
  286. passed: function(amount, newCallback) {
  287. var
  288. calculations = module.get.elementCalculations(),
  289. amountInPixels
  290. ;
  291. // assign callback
  292. if(amount !== undefined && newCallback !== undefined) {
  293. settings.onPassed[amount] = newCallback;
  294. }
  295. else if(amount !== undefined) {
  296. return (module.get.pixelsPassed(amount) > calculations.pixelsPassed);
  297. }
  298. else if(calculations.passing) {
  299. $.each(settings.onPassed, function(amount, callback) {
  300. if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) {
  301. module.execute(callback, amount);
  302. }
  303. else if(!settings.once) {
  304. module.remove.occurred(callback);
  305. }
  306. });
  307. }
  308. },
  309. passing: function(newCallback) {
  310. var
  311. calculations = module.get.elementCalculations(),
  312. callback = newCallback || settings.onPassing,
  313. callbackName = 'passing'
  314. ;
  315. if(newCallback) {
  316. module.debug('Adding callback for passing', newCallback);
  317. settings.onPassing = newCallback;
  318. }
  319. if(calculations.passing) {
  320. module.execute(callback, callbackName);
  321. }
  322. else if(!settings.once) {
  323. module.remove.occurred(callbackName);
  324. }
  325. if(newCallback !== undefined) {
  326. return calculations.passing;
  327. }
  328. },
  329. topVisible: function(newCallback) {
  330. var
  331. calculations = module.get.elementCalculations(),
  332. callback = newCallback || settings.onTopVisible,
  333. callbackName = 'topVisible'
  334. ;
  335. if(newCallback) {
  336. module.debug('Adding callback for top visible', newCallback);
  337. settings.onTopVisible = newCallback;
  338. }
  339. if(calculations.topVisible) {
  340. module.execute(callback, callbackName);
  341. }
  342. else if(!settings.once) {
  343. module.remove.occurred(callbackName);
  344. }
  345. if(newCallback === undefined) {
  346. return calculations.topVisible;
  347. }
  348. },
  349. bottomVisible: function(newCallback) {
  350. var
  351. calculations = module.get.elementCalculations(),
  352. callback = newCallback || settings.onBottomVisible,
  353. callbackName = 'bottomVisible'
  354. ;
  355. if(newCallback) {
  356. module.debug('Adding callback for bottom visible', newCallback);
  357. settings.onBottomVisible = newCallback;
  358. }
  359. if(calculations.bottomVisible) {
  360. module.execute(callback, callbackName);
  361. }
  362. else if(!settings.once) {
  363. module.remove.occurred(callbackName);
  364. }
  365. if(newCallback === undefined) {
  366. return calculations.bottomVisible;
  367. }
  368. },
  369. topPassed: function(newCallback) {
  370. var
  371. calculations = module.get.elementCalculations(),
  372. callback = newCallback || settings.onTopPassed,
  373. callbackName = 'topPassed'
  374. ;
  375. if(newCallback) {
  376. module.debug('Adding callback for top passed', newCallback);
  377. settings.onTopPassed = newCallback;
  378. }
  379. if(calculations.topPassed) {
  380. module.execute(callback, callbackName);
  381. }
  382. else if(!settings.once) {
  383. module.remove.occurred(callbackName);
  384. }
  385. if(newCallback === undefined) {
  386. return calculations.topPassed;
  387. }
  388. },
  389. bottomPassed: function(newCallback) {
  390. var
  391. calculations = module.get.elementCalculations(),
  392. callback = newCallback || settings.onBottomPassed,
  393. callbackName = 'bottomPassed'
  394. ;
  395. if(newCallback) {
  396. module.debug('Adding callback for bottom passed', newCallback);
  397. settings.onBottomPassed = newCallback;
  398. }
  399. if(calculations.bottomPassed) {
  400. module.execute(callback, callbackName);
  401. }
  402. else if(!settings.once) {
  403. module.remove.occurred(callbackName);
  404. }
  405. if(newCallback === undefined) {
  406. return calculations.bottomPassed;
  407. }
  408. },
  409. passingReverse: function(newCallback) {
  410. var
  411. calculations = module.get.elementCalculations(),
  412. callback = newCallback || settings.onPassingReverse,
  413. callbackName = 'passingReverse'
  414. ;
  415. if(newCallback) {
  416. module.debug('Adding callback for passing reverse', newCallback);
  417. settings.onPassingReverse = newCallback;
  418. }
  419. if(!calculations.passing) {
  420. if(module.get.occurred('passing')) {
  421. module.execute(callback, callbackName);
  422. }
  423. }
  424. else if(!settings.once) {
  425. module.remove.occurred(callbackName);
  426. }
  427. if(newCallback !== undefined) {
  428. return !calculations.passing;
  429. }
  430. },
  431. topVisibleReverse: function(newCallback) {
  432. var
  433. calculations = module.get.elementCalculations(),
  434. callback = newCallback || settings.onTopVisibleReverse,
  435. callbackName = 'topVisibleReverse'
  436. ;
  437. if(newCallback) {
  438. module.debug('Adding callback for top visible reverse', newCallback);
  439. settings.onTopVisibleReverse = newCallback;
  440. }
  441. if(!calculations.topVisible) {
  442. if(module.get.occurred('topVisible')) {
  443. module.execute(callback, callbackName);
  444. }
  445. }
  446. else if(!settings.once) {
  447. module.remove.occurred(callbackName);
  448. }
  449. if(newCallback === undefined) {
  450. return !calculations.topVisible;
  451. }
  452. },
  453. bottomVisibleReverse: function(newCallback) {
  454. var
  455. calculations = module.get.elementCalculations(),
  456. callback = newCallback || settings.onBottomVisibleReverse,
  457. callbackName = 'bottomVisibleReverse'
  458. ;
  459. if(newCallback) {
  460. module.debug('Adding callback for bottom visible reverse', newCallback);
  461. settings.onBottomVisibleReverse = newCallback;
  462. }
  463. if(!calculations.bottomVisible) {
  464. if(module.get.occurred('bottomVisible')) {
  465. module.execute(callback, callbackName);
  466. }
  467. }
  468. else if(!settings.once) {
  469. module.remove.occurred(callbackName);
  470. }
  471. if(newCallback === undefined) {
  472. return !calculations.bottomVisible;
  473. }
  474. },
  475. topPassedReverse: function(newCallback) {
  476. var
  477. calculations = module.get.elementCalculations(),
  478. callback = newCallback || settings.onTopPassedReverse,
  479. callbackName = 'topPassedReverse'
  480. ;
  481. if(newCallback) {
  482. module.debug('Adding callback for top passed reverse', newCallback);
  483. settings.onTopPassedReverse = newCallback;
  484. }
  485. if(!calculations.topPassed) {
  486. if(module.get.occurred('topPassed')) {
  487. module.execute(callback, callbackName);
  488. }
  489. }
  490. else if(!settings.once) {
  491. module.remove.occurred(callbackName);
  492. }
  493. if(newCallback === undefined) {
  494. return !calculations.onTopPassed;
  495. }
  496. },
  497. bottomPassedReverse: function(newCallback) {
  498. var
  499. calculations = module.get.elementCalculations(),
  500. callback = newCallback || settings.onBottomPassedReverse,
  501. callbackName = 'bottomPassedReverse'
  502. ;
  503. if(newCallback) {
  504. module.debug('Adding callback for bottom passed reverse', newCallback);
  505. settings.onBottomPassedReverse = newCallback;
  506. }
  507. if(!calculations.bottomPassed) {
  508. if(module.get.occurred('bottomPassed')) {
  509. module.execute(callback, callbackName);
  510. }
  511. }
  512. else if(!settings.once) {
  513. module.remove.occurred(callbackName);
  514. }
  515. if(newCallback === undefined) {
  516. return !calculations.bottomPassed;
  517. }
  518. },
  519. execute: function(callback, callbackName) {
  520. var
  521. calculations = module.get.elementCalculations(),
  522. screen = module.get.screenCalculations()
  523. ;
  524. callback = callback || false;
  525. if(callback) {
  526. if(settings.continuous) {
  527. module.debug('Callback being called continuously', callbackName, calculations);
  528. callback.call(element, calculations, screen);
  529. }
  530. else if(!module.get.occurred(callbackName)) {
  531. module.debug('Conditions met', callbackName, calculations);
  532. callback.call(element, calculations, screen);
  533. }
  534. }
  535. module.save.occurred(callbackName);
  536. },
  537. remove: {
  538. occurred: function(callback) {
  539. if(callback) {
  540. if(module.cache.occurred[callback] !== undefined && module.cache.occurred[callback] === true) {
  541. module.debug('Callback can now be called again', callback);
  542. module.cache.occurred[callback] = false;
  543. }
  544. }
  545. else {
  546. module.cache.occurred = {};
  547. }
  548. }
  549. },
  550. save: {
  551. calculations: function() {
  552. module.verbose('Saving all calculations necessary to determine positioning');
  553. module.save.scroll();
  554. module.save.direction();
  555. module.save.screenCalculations();
  556. module.save.elementCalculations();
  557. },
  558. occurred: function(callback) {
  559. if(callback) {
  560. if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) {
  561. module.verbose('Saving callback occurred', callback);
  562. module.cache.occurred[callback] = true;
  563. }
  564. }
  565. },
  566. scroll: function() {
  567. module.cache.scroll = $context.scrollTop() + settings.offset;
  568. },
  569. direction: function() {
  570. var
  571. scroll = module.get.scroll(),
  572. lastScroll = module.get.lastScroll(),
  573. direction
  574. ;
  575. if(scroll > lastScroll && lastScroll) {
  576. direction = 'down';
  577. }
  578. else if(scroll < lastScroll && lastScroll) {
  579. direction = 'up';
  580. }
  581. else {
  582. direction = 'static';
  583. }
  584. module.cache.direction = direction;
  585. return module.cache.direction;
  586. },
  587. elementPosition: function() {
  588. var
  589. element = module.cache.element,
  590. screen = module.get.screenSize()
  591. ;
  592. module.verbose('Saving element position');
  593. // (quicker than $.extend)
  594. element.margin = {};
  595. element.margin.top = parseInt($module.css('margin-top'), 10);
  596. element.margin.bottom = parseInt($module.css('margin-bottom'), 10);
  597. element.fits = (element.height < screen.height);
  598. element.offset = $module.offset();
  599. element.width = $module.outerWidth();
  600. element.height = $module.outerHeight();
  601. // store
  602. module.cache.element = element;
  603. return element;
  604. },
  605. elementCalculations: function() {
  606. var
  607. screen = module.get.screenCalculations(),
  608. element = module.get.elementPosition()
  609. ;
  610. // offset
  611. if(settings.includeMargin) {
  612. element.top = element.offset.top - element.margin.top;
  613. element.bottom = element.offset.top + element.height + element.margin.bottom;
  614. }
  615. else {
  616. element.top = element.offset.top;
  617. element.bottom = element.offset.top + element.height;
  618. }
  619. // visibility
  620. element.topVisible = (screen.bottom >= element.top);
  621. element.topPassed = (screen.top >= element.top);
  622. element.bottomVisible = (screen.bottom >= element.bottom);
  623. element.bottomPassed = (screen.top >= element.bottom);
  624. element.pixelsPassed = 0;
  625. element.percentagePassed = 0;
  626. // meta calculations
  627. element.visible = (element.topVisible || element.bottomVisible);
  628. element.passing = (element.topPassed && !element.bottomPassed);
  629. element.hidden = (!element.topVisible && !element.bottomVisible);
  630. // passing calculations
  631. if(element.passing) {
  632. element.pixelsPassed = (screen.top - element.top);
  633. element.percentagePassed = (screen.top - element.top) / element.height;
  634. }
  635. module.cache.element = element;
  636. module.verbose('Updated element calculations', element);
  637. return element;
  638. },
  639. screenCalculations: function() {
  640. var
  641. scroll = $context.scrollTop() + settings.offset
  642. ;
  643. if(module.cache.scroll === undefined) {
  644. module.cache.scroll = $context.scrollTop() + settings.offset;
  645. }
  646. module.save.direction();
  647. $.extend(module.cache.screen, {
  648. top : scroll,
  649. bottom : scroll + module.cache.screen.height
  650. });
  651. return module.cache.screen;
  652. },
  653. screenSize: function() {
  654. module.verbose('Saving window position');
  655. module.cache.screen = {
  656. height: $context.height()
  657. };
  658. },
  659. position: function() {
  660. module.save.screenSize();
  661. module.save.elementPosition();
  662. }
  663. },
  664. get: {
  665. pixelsPassed: function(amount) {
  666. var
  667. element = module.get.elementCalculations()
  668. ;
  669. if(amount.search('%') > -1) {
  670. return ( element.height * (parseInt(amount, 10) / 100) );
  671. }
  672. return parseInt(amount, 10);
  673. },
  674. occurred: function(callback) {
  675. return (module.cache.occurred !== undefined)
  676. ? module.cache.occurred[callback] || false
  677. : false
  678. ;
  679. },
  680. direction: function() {
  681. if(module.cache.direction === undefined) {
  682. module.save.direction();
  683. }
  684. return module.cache.direction;
  685. },
  686. elementPosition: function() {
  687. if(module.cache.element === undefined) {
  688. module.save.elementPosition();
  689. }
  690. return module.cache.element;
  691. },
  692. elementCalculations: function() {
  693. if(module.cache.element === undefined) {
  694. module.save.elementCalculations();
  695. }
  696. return module.cache.element;
  697. },
  698. screenCalculations: function() {
  699. if(module.cache.screen === undefined) {
  700. module.save.screenCalculations();
  701. }
  702. return module.cache.screen;
  703. },
  704. screenSize: function() {
  705. if(module.cache.screen === undefined) {
  706. module.save.screenSize();
  707. }
  708. return module.cache.screen;
  709. },
  710. scroll: function() {
  711. if(module.cache.scroll === undefined) {
  712. module.save.scroll();
  713. }
  714. return module.cache.scroll;
  715. },
  716. lastScroll: function() {
  717. if(module.cache.screen === undefined) {
  718. module.debug('First scroll event, no last scroll could be found');
  719. return false;
  720. }
  721. return module.cache.screen.top;
  722. }
  723. },
  724. setting: function(name, value) {
  725. if( $.isPlainObject(name) ) {
  726. $.extend(true, settings, name);
  727. }
  728. else if(value !== undefined) {
  729. settings[name] = value;
  730. }
  731. else {
  732. return settings[name];
  733. }
  734. },
  735. internal: function(name, value) {
  736. if( $.isPlainObject(name) ) {
  737. $.extend(true, module, name);
  738. }
  739. else if(value !== undefined) {
  740. module[name] = value;
  741. }
  742. else {
  743. return module[name];
  744. }
  745. },
  746. debug: function() {
  747. if(settings.debug) {
  748. if(settings.performance) {
  749. module.performance.log(arguments);
  750. }
  751. else {
  752. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  753. module.debug.apply(console, arguments);
  754. }
  755. }
  756. },
  757. verbose: function() {
  758. if(settings.verbose && settings.debug) {
  759. if(settings.performance) {
  760. module.performance.log(arguments);
  761. }
  762. else {
  763. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  764. module.verbose.apply(console, arguments);
  765. }
  766. }
  767. },
  768. error: function() {
  769. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  770. module.error.apply(console, arguments);
  771. },
  772. performance: {
  773. log: function(message) {
  774. var
  775. currentTime,
  776. executionTime,
  777. previousTime
  778. ;
  779. if(settings.performance) {
  780. currentTime = new Date().getTime();
  781. previousTime = time || currentTime;
  782. executionTime = currentTime - previousTime;
  783. time = currentTime;
  784. performance.push({
  785. 'Name' : message[0],
  786. 'Arguments' : [].slice.call(message, 1) || '',
  787. 'Element' : element,
  788. 'Execution Time' : executionTime
  789. });
  790. }
  791. clearTimeout(module.performance.timer);
  792. module.performance.timer = setTimeout(module.performance.display, 100);
  793. },
  794. display: function() {
  795. var
  796. title = settings.name + ':',
  797. totalTime = 0
  798. ;
  799. time = false;
  800. clearTimeout(module.performance.timer);
  801. $.each(performance, function(index, data) {
  802. totalTime += data['Execution Time'];
  803. });
  804. title += ' ' + totalTime + 'ms';
  805. if(moduleSelector) {
  806. title += ' \'' + moduleSelector + '\'';
  807. }
  808. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  809. console.groupCollapsed(title);
  810. if(console.table) {
  811. console.table(performance);
  812. }
  813. else {
  814. $.each(performance, function(index, data) {
  815. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  816. });
  817. }
  818. console.groupEnd();
  819. }
  820. performance = [];
  821. }
  822. },
  823. invoke: function(query, passedArguments, context) {
  824. var
  825. object = instance,
  826. maxDepth,
  827. found,
  828. response
  829. ;
  830. passedArguments = passedArguments || queryArguments;
  831. context = element || context;
  832. if(typeof query == 'string' && object !== undefined) {
  833. query = query.split(/[\. ]/);
  834. maxDepth = query.length - 1;
  835. $.each(query, function(depth, value) {
  836. var camelCaseValue = (depth != maxDepth)
  837. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  838. : query
  839. ;
  840. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  841. object = object[camelCaseValue];
  842. }
  843. else if( object[camelCaseValue] !== undefined ) {
  844. found = object[camelCaseValue];
  845. return false;
  846. }
  847. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  848. object = object[value];
  849. }
  850. else if( object[value] !== undefined ) {
  851. found = object[value];
  852. return false;
  853. }
  854. else {
  855. module.error(error.method, query);
  856. return false;
  857. }
  858. });
  859. }
  860. if ( $.isFunction( found ) ) {
  861. response = found.apply(context, passedArguments);
  862. }
  863. else if(found !== undefined) {
  864. response = found;
  865. }
  866. if($.isArray(returnedValue)) {
  867. returnedValue.push(response);
  868. }
  869. else if(returnedValue !== undefined) {
  870. returnedValue = [returnedValue, response];
  871. }
  872. else if(response !== undefined) {
  873. returnedValue = response;
  874. }
  875. return found;
  876. }
  877. };
  878. if(methodInvoked) {
  879. if(instance === undefined) {
  880. module.initialize();
  881. }
  882. module.invoke(query);
  883. }
  884. else {
  885. if(instance !== undefined) {
  886. instance.invoke('destroy');
  887. }
  888. module.initialize();
  889. }
  890. })
  891. ;
  892. return (returnedValue !== undefined)
  893. ? returnedValue
  894. : this
  895. ;
  896. };
  897. $.fn.visibility.settings = {
  898. name : 'Visibility',
  899. namespace : 'visibility',
  900. className: {
  901. fixed: 'fixed'
  902. },
  903. observeChanges : true,
  904. debug : false,
  905. verbose : false,
  906. performance : true,
  907. offset : 0,
  908. includeMargin : false,
  909. context : window,
  910. // check position immediately on init
  911. initialCheck : true,
  912. // visibility check delay in ms (defaults to animationFrame)
  913. throttle : false,
  914. // special visibility type (image, fixed)
  915. type : false,
  916. // image only animation settings
  917. transition : false,
  918. duration : 1000,
  919. // array of callbacks for percentage
  920. onPassed : {},
  921. // standard callbacks
  922. onPassing : false,
  923. onTopVisible : false,
  924. onBottomVisible : false,
  925. onTopPassed : false,
  926. onBottomPassed : false,
  927. // reverse callbacks
  928. onPassingReverse : false,
  929. onTopVisibleReverse : false,
  930. onBottomVisibleReverse : false,
  931. onTopPassedReverse : false,
  932. onBottomPassedReverse : false,
  933. once : true,
  934. continuous : false,
  935. // utility callbacks
  936. onRefresh : function(){},
  937. onScroll : function(){},
  938. error : {
  939. method : 'The method you called is not defined.'
  940. }
  941. };
  942. })( jQuery, window , document );