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.

917 lines
29 KiB

9 years ago
8 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
  1. /*!
  2. * # Semantic UI 2.2.0 - Sticky
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2015 Contributors
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. ;(function ($, window, document, undefined) {
  12. "use strict";
  13. window = (typeof window != 'undefined' && window.Math == Math)
  14. ? window
  15. : (typeof self != 'undefined' && self.Math == Math)
  16. ? self
  17. : Function('return this')()
  18. ;
  19. $.fn.sticky = function(parameters) {
  20. var
  21. $allModules = $(this),
  22. moduleSelector = $allModules.selector || '',
  23. time = new Date().getTime(),
  24. performance = [],
  25. query = arguments[0],
  26. methodInvoked = (typeof query == 'string'),
  27. queryArguments = [].slice.call(arguments, 1),
  28. returnedValue
  29. ;
  30. $allModules
  31. .each(function() {
  32. var
  33. settings = ( $.isPlainObject(parameters) )
  34. ? $.extend(true, {}, $.fn.sticky.settings, parameters)
  35. : $.extend({}, $.fn.sticky.settings),
  36. className = settings.className,
  37. namespace = settings.namespace,
  38. error = settings.error,
  39. eventNamespace = '.' + namespace,
  40. moduleNamespace = 'module-' + namespace,
  41. $module = $(this),
  42. $window = $(window),
  43. $scroll = $(settings.scrollContext),
  44. $container,
  45. $context,
  46. selector = $module.selector || '',
  47. instance = $module.data(moduleNamespace),
  48. requestAnimationFrame = window.requestAnimationFrame
  49. || window.mozRequestAnimationFrame
  50. || window.webkitRequestAnimationFrame
  51. || window.msRequestAnimationFrame
  52. || function(callback) { setTimeout(callback, 0); },
  53. element = this,
  54. observer,
  55. module
  56. ;
  57. module = {
  58. initialize: function() {
  59. module.determineContainer();
  60. module.determineContext();
  61. module.verbose('Initializing sticky', settings, $container);
  62. module.save.positions();
  63. module.checkErrors();
  64. module.bind.events();
  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 instance');
  79. module.reset();
  80. if(observer) {
  81. observer.disconnect();
  82. }
  83. $window
  84. .off('load' + eventNamespace, module.event.load)
  85. .off('resize' + eventNamespace, module.event.resize)
  86. ;
  87. $scroll
  88. .off('scrollchange' + eventNamespace, module.event.scrollchange)
  89. ;
  90. $module.removeData(moduleNamespace);
  91. },
  92. observeChanges: function() {
  93. var
  94. context = $context[0]
  95. ;
  96. if('MutationObserver' in window) {
  97. observer = new MutationObserver(function(mutations) {
  98. clearTimeout(module.timer);
  99. module.timer = setTimeout(function() {
  100. module.verbose('DOM tree modified, updating sticky menu', mutations);
  101. module.refresh();
  102. }, 100);
  103. });
  104. observer.observe(element, {
  105. childList : true,
  106. subtree : true
  107. });
  108. observer.observe(context, {
  109. childList : true,
  110. subtree : true
  111. });
  112. module.debug('Setting up mutation observer', observer);
  113. }
  114. },
  115. determineContainer: function() {
  116. $container = $module.offsetParent();
  117. },
  118. determineContext: function() {
  119. if(settings.context) {
  120. $context = $(settings.context);
  121. }
  122. else {
  123. $context = $container;
  124. }
  125. if($context.length === 0) {
  126. module.error(error.invalidContext, settings.context, $module);
  127. return;
  128. }
  129. },
  130. checkErrors: function() {
  131. if( module.is.hidden() ) {
  132. module.error(error.visible, $module);
  133. }
  134. if(module.cache.element.height > module.cache.context.height) {
  135. module.reset();
  136. module.error(error.elementSize, $module);
  137. return;
  138. }
  139. },
  140. bind: {
  141. events: function() {
  142. $window
  143. .on('load' + eventNamespace, module.event.load)
  144. .on('resize' + eventNamespace, module.event.resize)
  145. ;
  146. // pub/sub pattern
  147. $scroll
  148. .off('scroll' + eventNamespace)
  149. .on('scroll' + eventNamespace, module.event.scroll)
  150. .on('scrollchange' + eventNamespace, module.event.scrollchange)
  151. ;
  152. }
  153. },
  154. event: {
  155. load: function() {
  156. module.verbose('Page contents finished loading');
  157. requestAnimationFrame(module.refresh);
  158. },
  159. resize: function() {
  160. module.verbose('Window resized');
  161. requestAnimationFrame(module.refresh);
  162. },
  163. scroll: function() {
  164. requestAnimationFrame(function() {
  165. $scroll.triggerHandler('scrollchange' + eventNamespace, $scroll.scrollTop() );
  166. });
  167. },
  168. scrollchange: function(event, scrollPosition) {
  169. module.stick(scrollPosition);
  170. settings.onScroll.call(element);
  171. }
  172. },
  173. refresh: function(hardRefresh) {
  174. module.reset();
  175. if(!settings.context) {
  176. module.determineContext();
  177. }
  178. if(hardRefresh) {
  179. module.determineContainer();
  180. }
  181. module.save.positions();
  182. module.stick();
  183. settings.onReposition.call(element);
  184. },
  185. supports: {
  186. sticky: function() {
  187. var
  188. $element = $('<div/>'),
  189. element = $element[0]
  190. ;
  191. $element.addClass(className.supported);
  192. return($element.css('position').match('sticky'));
  193. }
  194. },
  195. save: {
  196. lastScroll: function(scroll) {
  197. module.lastScroll = scroll;
  198. },
  199. elementScroll: function(scroll) {
  200. module.elementScroll = scroll;
  201. },
  202. positions: function() {
  203. var
  204. scrollContext = {
  205. height : $scroll.height()
  206. },
  207. element = {
  208. margin: {
  209. top : parseInt($module.css('margin-top'), 10),
  210. bottom : parseInt($module.css('margin-bottom'), 10),
  211. },
  212. offset : $module.offset(),
  213. width : $module.outerWidth(),
  214. height : $module.outerHeight()
  215. },
  216. context = {
  217. offset : $context.offset(),
  218. height : $context.outerHeight()
  219. },
  220. container = {
  221. height: $container.outerHeight()
  222. }
  223. ;
  224. if( !module.is.standardScroll() ) {
  225. module.debug('Non-standard scroll. Removing scroll offset from element offset');
  226. scrollContext.top = $scroll.scrollTop();
  227. scrollContext.left = $scroll.scrollLeft();
  228. element.offset.top += scrollContext.top;
  229. context.offset.top += scrollContext.top;
  230. element.offset.left += scrollContext.left;
  231. context.offset.left += scrollContext.left;
  232. }
  233. module.cache = {
  234. fits : ( element.height < scrollContext.height ),
  235. scrollContext : {
  236. height : scrollContext.height
  237. },
  238. element: {
  239. margin : element.margin,
  240. top : element.offset.top - element.margin.top,
  241. left : element.offset.left,
  242. width : element.width,
  243. height : element.height,
  244. bottom : element.offset.top + element.height
  245. },
  246. context: {
  247. top : context.offset.top,
  248. height : context.height,
  249. bottom : context.offset.top + context.height
  250. }
  251. };
  252. module.set.containerSize();
  253. module.set.size();
  254. module.stick();
  255. module.debug('Caching element positions', module.cache);
  256. }
  257. },
  258. get: {
  259. direction: function(scroll) {
  260. var
  261. direction = 'down'
  262. ;
  263. scroll = scroll || $scroll.scrollTop();
  264. if(module.lastScroll !== undefined) {
  265. if(module.lastScroll < scroll) {
  266. direction = 'down';
  267. }
  268. else if(module.lastScroll > scroll) {
  269. direction = 'up';
  270. }
  271. }
  272. return direction;
  273. },
  274. scrollChange: function(scroll) {
  275. scroll = scroll || $scroll.scrollTop();
  276. return (module.lastScroll)
  277. ? (scroll - module.lastScroll)
  278. : 0
  279. ;
  280. },
  281. currentElementScroll: function() {
  282. if(module.elementScroll) {
  283. return module.elementScroll;
  284. }
  285. return ( module.is.top() )
  286. ? Math.abs(parseInt($module.css('top'), 10)) || 0
  287. : Math.abs(parseInt($module.css('bottom'), 10)) || 0
  288. ;
  289. },
  290. elementScroll: function(scroll) {
  291. scroll = scroll || $scroll.scrollTop();
  292. var
  293. element = module.cache.element,
  294. scrollContext = module.cache.scrollContext,
  295. delta = module.get.scrollChange(scroll),
  296. maxScroll = (element.height - scrollContext.height + settings.offset),
  297. elementScroll = module.get.currentElementScroll(),
  298. possibleScroll = (elementScroll + delta)
  299. ;
  300. if(module.cache.fits || possibleScroll < 0) {
  301. elementScroll = 0;
  302. }
  303. else if(possibleScroll > maxScroll ) {
  304. elementScroll = maxScroll;
  305. }
  306. else {
  307. elementScroll = possibleScroll;
  308. }
  309. return elementScroll;
  310. }
  311. },
  312. remove: {
  313. lastScroll: function() {
  314. delete module.lastScroll;
  315. },
  316. elementScroll: function(scroll) {
  317. delete module.elementScroll;
  318. },
  319. offset: function() {
  320. $module.css('margin-top', '');
  321. }
  322. },
  323. set: {
  324. offset: function() {
  325. module.verbose('Setting offset on element', settings.offset);
  326. $module
  327. .css('margin-top', settings.offset)
  328. ;
  329. },
  330. containerSize: function() {
  331. var
  332. tagName = $container.get(0).tagName
  333. ;
  334. if(tagName === 'HTML' || tagName == 'body') {
  335. // this can trigger for too many reasons
  336. //module.error(error.container, tagName, $module);
  337. module.determineContainer();
  338. }
  339. else {
  340. if( Math.abs($container.outerHeight() - module.cache.context.height) > settings.jitter) {
  341. module.debug('Context has padding, specifying exact height for container', module.cache.context.height);
  342. $container.css({
  343. height: module.cache.context.height
  344. });
  345. }
  346. }
  347. },
  348. minimumSize: function() {
  349. var
  350. element = module.cache.element
  351. ;
  352. $container
  353. .css('min-height', element.height)
  354. ;
  355. },
  356. scroll: function(scroll) {
  357. module.debug('Setting scroll on element', scroll);
  358. if(module.elementScroll == scroll) {
  359. return;
  360. }
  361. if( module.is.top() ) {
  362. $module
  363. .css('bottom', '')
  364. .css('top', -scroll)
  365. ;
  366. }
  367. if( module.is.bottom() ) {
  368. $module
  369. .css('top', '')
  370. .css('bottom', scroll)
  371. ;
  372. }
  373. },
  374. size: function() {
  375. if(module.cache.element.height !== 0 && module.cache.element.width !== 0) {
  376. element.style.setProperty('width', module.cache.element.width + 'px', 'important');
  377. element.style.setProperty('height', module.cache.element.height + 'px', 'important');
  378. }
  379. }
  380. },
  381. is: {
  382. standardScroll: function() {
  383. return ($scroll[0] == window);
  384. },
  385. top: function() {
  386. return $module.hasClass(className.top);
  387. },
  388. bottom: function() {
  389. return $module.hasClass(className.bottom);
  390. },
  391. initialPosition: function() {
  392. return (!module.is.fixed() && !module.is.bound());
  393. },
  394. hidden: function() {
  395. return (!$module.is(':visible'));
  396. },
  397. bound: function() {
  398. return $module.hasClass(className.bound);
  399. },
  400. fixed: function() {
  401. return $module.hasClass(className.fixed);
  402. }
  403. },
  404. stick: function(scroll) {
  405. var
  406. cachedPosition = scroll || $scroll.scrollTop(),
  407. cache = module.cache,
  408. fits = cache.fits,
  409. element = cache.element,
  410. scrollContext = cache.scrollContext,
  411. context = cache.context,
  412. offset = (module.is.bottom() && settings.pushing)
  413. ? settings.bottomOffset
  414. : settings.offset,
  415. scroll = {
  416. top : cachedPosition + offset,
  417. bottom : cachedPosition + offset + scrollContext.height
  418. },
  419. direction = module.get.direction(scroll.top),
  420. elementScroll = (fits)
  421. ? 0
  422. : module.get.elementScroll(scroll.top),
  423. // shorthand
  424. doesntFit = !fits,
  425. elementVisible = (element.height !== 0)
  426. ;
  427. if(elementVisible) {
  428. if( module.is.initialPosition() ) {
  429. if(scroll.top >= context.bottom) {
  430. module.debug('Initial element position is bottom of container');
  431. module.bindBottom();
  432. }
  433. else if(scroll.top > element.top) {
  434. if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  435. module.debug('Initial element position is bottom of container');
  436. module.bindBottom();
  437. }
  438. else {
  439. module.debug('Initial element position is fixed');
  440. module.fixTop();
  441. }
  442. }
  443. }
  444. else if( module.is.fixed() ) {
  445. // currently fixed top
  446. if( module.is.top() ) {
  447. if( scroll.top <= element.top ) {
  448. module.debug('Fixed element reached top of container');
  449. module.setInitialPosition();
  450. }
  451. else if( (element.height + scroll.top - elementScroll) >= context.bottom ) {
  452. module.debug('Fixed element reached bottom of container');
  453. module.bindBottom();
  454. }
  455. // scroll element if larger than screen
  456. else if(doesntFit) {
  457. module.set.scroll(elementScroll);
  458. module.save.lastScroll(scroll.top);
  459. module.save.elementScroll(elementScroll);
  460. }
  461. }
  462. // currently fixed bottom
  463. else if(module.is.bottom() ) {
  464. // top edge
  465. if( (scroll.bottom - element.height) <= element.top) {
  466. module.debug('Bottom fixed rail has reached top of container');
  467. module.setInitialPosition();
  468. }
  469. // bottom edge
  470. else if(scroll.bottom >= context.bottom) {
  471. module.debug('Bottom fixed rail has reached bottom of container');
  472. module.bindBottom();
  473. }
  474. // scroll element if larger than screen
  475. else if(doesntFit) {
  476. module.set.scroll(elementScroll);
  477. module.save.lastScroll(scroll.top);
  478. module.save.elementScroll(elementScroll);
  479. }
  480. }
  481. }
  482. else if( module.is.bottom() ) {
  483. if( scroll.top <= element.top ) {
  484. module.debug('Jumped from bottom fixed to top fixed, most likely used home/end button');
  485. module.setInitialPosition();
  486. }
  487. else {
  488. if(settings.pushing) {
  489. if(module.is.bound() && scroll.bottom <= context.bottom ) {
  490. module.debug('Fixing bottom attached element to bottom of browser.');
  491. module.fixBottom();
  492. }
  493. }
  494. else {
  495. if(module.is.bound() && (scroll.top <= context.bottom - element.height) ) {
  496. module.debug('Fixing bottom attached element to top of browser.');
  497. module.fixTop();
  498. }
  499. }
  500. }
  501. }
  502. }
  503. },
  504. bindTop: function() {
  505. module.debug('Binding element to top of parent container');
  506. module.remove.offset();
  507. $module
  508. .css({
  509. left : '',
  510. top : '',
  511. marginBottom : ''
  512. })
  513. .removeClass(className.fixed)
  514. .removeClass(className.bottom)
  515. .addClass(className.bound)
  516. .addClass(className.top)
  517. ;
  518. settings.onTop.call(element);
  519. settings.onUnstick.call(element);
  520. },
  521. bindBottom: function() {
  522. module.debug('Binding element to bottom of parent container');
  523. module.remove.offset();
  524. $module
  525. .css({
  526. left : '',
  527. top : ''
  528. })
  529. .removeClass(className.fixed)
  530. .removeClass(className.top)
  531. .addClass(className.bound)
  532. .addClass(className.bottom)
  533. ;
  534. settings.onBottom.call(element);
  535. settings.onUnstick.call(element);
  536. },
  537. setInitialPosition: function() {
  538. module.debug('Returning to initial position');
  539. module.unfix();
  540. module.unbind();
  541. },
  542. fixTop: function() {
  543. module.debug('Fixing element to top of page');
  544. module.set.minimumSize();
  545. module.set.offset();
  546. $module
  547. .css({
  548. left : module.cache.element.left,
  549. bottom : '',
  550. marginBottom : ''
  551. })
  552. .removeClass(className.bound)
  553. .removeClass(className.bottom)
  554. .addClass(className.fixed)
  555. .addClass(className.top)
  556. ;
  557. settings.onStick.call(element);
  558. },
  559. fixBottom: function() {
  560. module.debug('Sticking element to bottom of page');
  561. module.set.minimumSize();
  562. module.set.offset();
  563. $module
  564. .css({
  565. left : module.cache.element.left,
  566. bottom : '',
  567. marginBottom : ''
  568. })
  569. .removeClass(className.bound)
  570. .removeClass(className.top)
  571. .addClass(className.fixed)
  572. .addClass(className.bottom)
  573. ;
  574. settings.onStick.call(element);
  575. },
  576. unbind: function() {
  577. if( module.is.bound() ) {
  578. module.debug('Removing container bound position on element');
  579. module.remove.offset();
  580. $module
  581. .removeClass(className.bound)
  582. .removeClass(className.top)
  583. .removeClass(className.bottom)
  584. ;
  585. }
  586. },
  587. unfix: function() {
  588. if( module.is.fixed() ) {
  589. module.debug('Removing fixed position on element');
  590. module.remove.offset();
  591. $module
  592. .removeClass(className.fixed)
  593. .removeClass(className.top)
  594. .removeClass(className.bottom)
  595. ;
  596. settings.onUnstick.call(element);
  597. }
  598. },
  599. reset: function() {
  600. module.debug('Reseting elements position');
  601. module.unbind();
  602. module.unfix();
  603. module.resetCSS();
  604. module.remove.offset();
  605. module.remove.lastScroll();
  606. },
  607. resetCSS: function() {
  608. $module
  609. .css({
  610. width : '',
  611. height : ''
  612. })
  613. ;
  614. $container
  615. .css({
  616. height: ''
  617. })
  618. ;
  619. },
  620. setting: function(name, value) {
  621. if( $.isPlainObject(name) ) {
  622. $.extend(true, settings, name);
  623. }
  624. else if(value !== undefined) {
  625. settings[name] = value;
  626. }
  627. else {
  628. return settings[name];
  629. }
  630. },
  631. internal: function(name, value) {
  632. if( $.isPlainObject(name) ) {
  633. $.extend(true, module, name);
  634. }
  635. else if(value !== undefined) {
  636. module[name] = value;
  637. }
  638. else {
  639. return module[name];
  640. }
  641. },
  642. debug: function() {
  643. if(!settings.silent && settings.debug) {
  644. if(settings.performance) {
  645. module.performance.log(arguments);
  646. }
  647. else {
  648. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  649. module.debug.apply(console, arguments);
  650. }
  651. }
  652. },
  653. verbose: function() {
  654. if(!settings.silent && settings.verbose && settings.debug) {
  655. if(settings.performance) {
  656. module.performance.log(arguments);
  657. }
  658. else {
  659. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  660. module.verbose.apply(console, arguments);
  661. }
  662. }
  663. },
  664. error: function() {
  665. if(!settings.silent) {
  666. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  667. module.error.apply(console, arguments);
  668. }
  669. },
  670. performance: {
  671. log: function(message) {
  672. var
  673. currentTime,
  674. executionTime,
  675. previousTime
  676. ;
  677. if(settings.performance) {
  678. currentTime = new Date().getTime();
  679. previousTime = time || currentTime;
  680. executionTime = currentTime - previousTime;
  681. time = currentTime;
  682. performance.push({
  683. 'Name' : message[0],
  684. 'Arguments' : [].slice.call(message, 1) || '',
  685. 'Element' : element,
  686. 'Execution Time' : executionTime
  687. });
  688. }
  689. clearTimeout(module.performance.timer);
  690. module.performance.timer = setTimeout(module.performance.display, 0);
  691. },
  692. display: function() {
  693. var
  694. title = settings.name + ':',
  695. totalTime = 0
  696. ;
  697. time = false;
  698. clearTimeout(module.performance.timer);
  699. $.each(performance, function(index, data) {
  700. totalTime += data['Execution Time'];
  701. });
  702. title += ' ' + totalTime + 'ms';
  703. if(moduleSelector) {
  704. title += ' \'' + moduleSelector + '\'';
  705. }
  706. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  707. console.groupCollapsed(title);
  708. if(console.table) {
  709. console.table(performance);
  710. }
  711. else {
  712. $.each(performance, function(index, data) {
  713. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  714. });
  715. }
  716. console.groupEnd();
  717. }
  718. performance = [];
  719. }
  720. },
  721. invoke: function(query, passedArguments, context) {
  722. var
  723. object = instance,
  724. maxDepth,
  725. found,
  726. response
  727. ;
  728. passedArguments = passedArguments || queryArguments;
  729. context = element || context;
  730. if(typeof query == 'string' && object !== undefined) {
  731. query = query.split(/[\. ]/);
  732. maxDepth = query.length - 1;
  733. $.each(query, function(depth, value) {
  734. var camelCaseValue = (depth != maxDepth)
  735. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  736. : query
  737. ;
  738. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  739. object = object[camelCaseValue];
  740. }
  741. else if( object[camelCaseValue] !== undefined ) {
  742. found = object[camelCaseValue];
  743. return false;
  744. }
  745. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  746. object = object[value];
  747. }
  748. else if( object[value] !== undefined ) {
  749. found = object[value];
  750. return false;
  751. }
  752. else {
  753. return false;
  754. }
  755. });
  756. }
  757. if ( $.isFunction( found ) ) {
  758. response = found.apply(context, passedArguments);
  759. }
  760. else if(found !== undefined) {
  761. response = found;
  762. }
  763. if($.isArray(returnedValue)) {
  764. returnedValue.push(response);
  765. }
  766. else if(returnedValue !== undefined) {
  767. returnedValue = [returnedValue, response];
  768. }
  769. else if(response !== undefined) {
  770. returnedValue = response;
  771. }
  772. return found;
  773. }
  774. };
  775. if(methodInvoked) {
  776. if(instance === undefined) {
  777. module.initialize();
  778. }
  779. module.invoke(query);
  780. }
  781. else {
  782. if(instance !== undefined) {
  783. instance.invoke('destroy');
  784. }
  785. module.initialize();
  786. }
  787. })
  788. ;
  789. return (returnedValue !== undefined)
  790. ? returnedValue
  791. : this
  792. ;
  793. };
  794. $.fn.sticky.settings = {
  795. name : 'Sticky',
  796. namespace : 'sticky',
  797. silent : false,
  798. debug : false,
  799. verbose : true,
  800. performance : true,
  801. // whether to stick in the opposite direction on scroll up
  802. pushing : false,
  803. context : false,
  804. // Context to watch scroll events
  805. scrollContext : window,
  806. // Offset to adjust scroll
  807. offset : 0,
  808. // Offset to adjust scroll when attached to bottom of screen
  809. bottomOffset : 0,
  810. jitter : 5, // will only set container height if difference between context and container is larger than this number
  811. // Whether to automatically observe changes with Mutation Observers
  812. observeChanges : false,
  813. // Called when position is recalculated
  814. onReposition : function(){},
  815. // Called on each scroll
  816. onScroll : function(){},
  817. // Called when element is stuck to viewport
  818. onStick : function(){},
  819. // Called when element is unstuck from viewport
  820. onUnstick : function(){},
  821. // Called when element reaches top of context
  822. onTop : function(){},
  823. // Called when element reaches bottom of context
  824. onBottom : function(){},
  825. error : {
  826. container : 'Sticky element must be inside a relative container',
  827. visible : 'Element is hidden, you must call refresh after element becomes visible',
  828. method : 'The method you called is not defined.',
  829. invalidContext : 'Context specified does not exist',
  830. elementSize : 'Sticky element is larger than its container, cannot create sticky.'
  831. },
  832. className : {
  833. bound : 'bound',
  834. fixed : 'fixed',
  835. supported : 'native',
  836. top : 'top',
  837. bottom : 'bottom'
  838. }
  839. };
  840. })( jQuery, window, document );