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.

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