Guest User

Untitled

a guest
Oct 21st, 2017
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.57 KB | None | 0 0
  1. (function($) {
  2.  
  3. /**
  4. * Generate an indented list of links from a nav. Meant for use with panel().
  5. * @return {jQuery} jQuery object.
  6. */
  7. $.fn.navList = function() {
  8.  
  9. var $this = $(this);
  10. $a = $this.find('a'),
  11. b = [];
  12.  
  13. $a.each(function() {
  14.  
  15. var $this = $(this),
  16. indent = Math.max(0, $this.parents('li').length - 1),
  17. href = $this.attr('href'),
  18. target = $this.attr('target');
  19.  
  20. b.push(
  21. '<a ' +
  22. 'class="link depth-' + indent + '"' +
  23. ( (typeof target !== 'undefined' && target != '') ? ' target="' + target + '"' : '') +
  24. ( (typeof href !== 'undefined' && href != '') ? ' href="' + href + '"' : '') +
  25. '>' +
  26. '<span class="indent-' + indent + '"></span>' +
  27. $this.text() +
  28. '</a>'
  29. );
  30.  
  31. });
  32.  
  33. return b.join('');
  34.  
  35. };
  36.  
  37. /**
  38. * Panel-ify an element.
  39. * @param {object} userConfig User config.
  40. * @return {jQuery} jQuery object.
  41. */
  42. $.fn.panel = function(userConfig) {
  43.  
  44. // No elements?
  45. if (this.length == 0)
  46. return $this;
  47.  
  48. // Multiple elements?
  49. if (this.length > 1) {
  50.  
  51. for (var i=0; i < this.length; i++)
  52. $(this[i]).panel(userConfig);
  53.  
  54. return $this;
  55.  
  56. }
  57.  
  58. // Vars.
  59. var $this = $(this),
  60. $body = $('body'),
  61. $window = $(window),
  62. id = $this.attr('id'),
  63. config;
  64.  
  65. // Config.
  66. config = $.extend({
  67.  
  68. // Delay.
  69. delay: 0,
  70.  
  71. // Hide panel on link click.
  72. hideOnClick: false,
  73.  
  74. // Hide panel on escape keypress.
  75. hideOnEscape: false,
  76.  
  77. // Hide panel on swipe.
  78. hideOnSwipe: false,
  79.  
  80. // Reset scroll position on hide.
  81. resetScroll: false,
  82.  
  83. // Reset forms on hide.
  84. resetForms: false,
  85.  
  86. // Side of viewport the panel will appear.
  87. side: null,
  88.  
  89. // Target element for "class".
  90. target: $this,
  91.  
  92. // Class to toggle.
  93. visibleClass: 'visible'
  94.  
  95. }, userConfig);
  96.  
  97. // Expand "target" if it's not a jQuery object already.
  98. if (typeof config.target != 'jQuery')
  99. config.target = $(config.target);
  100.  
  101. // Panel.
  102.  
  103. // Methods.
  104. $this._hide = function(event) {
  105.  
  106. // Already hidden? Bail.
  107. if (!config.target.hasClass(config.visibleClass))
  108. return;
  109.  
  110. // If an event was provided, cancel it.
  111. if (event) {
  112.  
  113. event.preventDefault();
  114. event.stopPropagation();
  115.  
  116. }
  117.  
  118. // Hide.
  119. config.target.removeClass(config.visibleClass);
  120.  
  121. // Post-hide stuff.
  122. window.setTimeout(function() {
  123.  
  124. // Reset scroll position.
  125. if (config.resetScroll)
  126. $this.scrollTop(0);
  127.  
  128. // Reset forms.
  129. if (config.resetForms)
  130. $this.find('form').each(function() {
  131. this.reset();
  132. });
  133.  
  134. }, config.delay);
  135.  
  136. };
  137.  
  138. // Vendor fixes.
  139. $this
  140. .css('-ms-overflow-style', '-ms-autohiding-scrollbar')
  141. .css('-webkit-overflow-scrolling', 'touch');
  142.  
  143. // Hide on click.
  144. if (config.hideOnClick) {
  145.  
  146. $this.find('a')
  147. .css('-webkit-tap-highlight-color', 'rgba(0,0,0,0)');
  148.  
  149. $this
  150. .on('click', 'a', function(event) {
  151.  
  152. var $a = $(this),
  153. href = $a.attr('href'),
  154. target = $a.attr('target');
  155.  
  156. if (!href || href == '#' || href == '' || href == '#' + id)
  157. return;
  158.  
  159. // Cancel original event.
  160. event.preventDefault();
  161. event.stopPropagation();
  162.  
  163. // Hide panel.
  164. $this._hide();
  165.  
  166. // Redirect to href.
  167. window.setTimeout(function() {
  168.  
  169. if (target == '_blank')
  170. window.open(href);
  171. else
  172. window.location.href = href;
  173.  
  174. }, config.delay + 10);
  175.  
  176. });
  177.  
  178. }
  179.  
  180. // Event: Touch stuff.
  181. $this.on('touchstart', function(event) {
  182.  
  183. $this.touchPosX = event.originalEvent.touches[0].pageX;
  184. $this.touchPosY = event.originalEvent.touches[0].pageY;
  185.  
  186. })
  187.  
  188. $this.on('touchmove', function(event) {
  189.  
  190. if ($this.touchPosX === null
  191. || $this.touchPosY === null)
  192. return;
  193.  
  194. var diffX = $this.touchPosX - event.originalEvent.touches[0].pageX,
  195. diffY = $this.touchPosY - event.originalEvent.touches[0].pageY,
  196. th = $this.outerHeight(),
  197. ts = ($this.get(0).scrollHeight - $this.scrollTop());
  198.  
  199. // Hide on swipe?
  200. if (config.hideOnSwipe) {
  201.  
  202. var result = false,
  203. boundary = 20,
  204. delta = 50;
  205.  
  206. switch (config.side) {
  207.  
  208. case 'left':
  209. result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta);
  210. break;
  211.  
  212. case 'right':
  213. result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1 * delta));
  214. break;
  215.  
  216. case 'top':
  217. result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY > delta);
  218. break;
  219.  
  220. case 'bottom':
  221. result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY < (-1 * delta));
  222. break;
  223.  
  224. default:
  225. break;
  226.  
  227. }
  228.  
  229. if (result) {
  230.  
  231. $this.touchPosX = null;
  232. $this.touchPosY = null;
  233. $this._hide();
  234.  
  235. return false;
  236.  
  237. }
  238.  
  239. }
  240.  
  241. // Prevent vertical scrolling past the top or bottom.
  242. if (($this.scrollTop() < 0 && diffY < 0)
  243. || (ts > (th - 2) && ts < (th + 2) && diffY > 0)) {
  244.  
  245. event.preventDefault();
  246. event.stopPropagation();
  247.  
  248. }
  249.  
  250. });
  251.  
  252. // Event: Prevent certain events inside the panel from bubbling.
  253. $this.on('click touchend touchstart touchmove', function(event) {
  254. event.stopPropagation();
  255. });
  256.  
  257. // Event: Hide panel if a child anchor tag pointing to its ID is clicked.
  258. $this.on('click', 'a[href="#' + id + '"]', function(event) {
  259.  
  260. event.preventDefault();
  261. event.stopPropagation();
  262.  
  263. config.target.removeClass(config.visibleClass);
  264.  
  265. });
  266.  
  267. // Body.
  268.  
  269. // Event: Hide panel on body click/tap.
  270. $body.on('click touchend', function(event) {
  271. $this._hide(event);
  272. });
  273.  
  274. // Event: Toggle.
  275. $body.on('click', 'a[href="#' + id + '"]', function(event) {
  276.  
  277. event.preventDefault();
  278. event.stopPropagation();
  279.  
  280. config.target.toggleClass(config.visibleClass);
  281.  
  282. });
  283.  
  284. // Window.
  285.  
  286. // Event: Hide on ESC.
  287. if (config.hideOnEscape)
  288. $window.on('keydown', function(event) {
  289.  
  290. if (event.keyCode == 27)
  291. $this._hide(event);
  292.  
  293. });
  294.  
  295. return $this;
  296.  
  297. };
  298.  
  299. /**
  300. * Apply "placeholder" attribute polyfill to one or more forms.
  301. * @return {jQuery} jQuery object.
  302. */
  303. $.fn.placeholder = function() {
  304.  
  305. // Browser natively supports placeholders? Bail.
  306. if (typeof (document.createElement('input')).placeholder != 'undefined')
  307. return $(this);
  308.  
  309. // No elements?
  310. if (this.length == 0)
  311. return $this;
  312.  
  313. // Multiple elements?
  314. if (this.length > 1) {
  315.  
  316. for (var i=0; i < this.length; i++)
  317. $(this[i]).placeholder();
  318.  
  319. return $this;
  320.  
  321. }
  322.  
  323. // Vars.
  324. var $this = $(this);
  325.  
  326. // Text, TextArea.
  327. $this.find('input[type=text],textarea')
  328. .each(function() {
  329.  
  330. var i = $(this);
  331.  
  332. if (i.val() == ''
  333. || i.val() == i.attr('placeholder'))
  334. i
  335. .addClass('polyfill-placeholder')
  336. .val(i.attr('placeholder'));
  337.  
  338. })
  339. .on('blur', function() {
  340.  
  341. var i = $(this);
  342.  
  343. if (i.attr('name').match(/-polyfill-field$/))
  344. return;
  345.  
  346. if (i.val() == '')
  347. i
  348. .addClass('polyfill-placeholder')
  349. .val(i.attr('placeholder'));
  350.  
  351. })
  352. .on('focus', function() {
  353.  
  354. var i = $(this);
  355.  
  356. if (i.attr('name').match(/-polyfill-field$/))
  357. return;
  358.  
  359. if (i.val() == i.attr('placeholder'))
  360. i
  361. .removeClass('polyfill-placeholder')
  362. .val('');
  363.  
  364. });
  365.  
  366. // Password.
  367. $this.find('input[type=password]')
  368. .each(function() {
  369.  
  370. var i = $(this);
  371. var x = $(
  372. $('<div>')
  373. .append(i.clone())
  374. .remove()
  375. .html()
  376. .replace(/type="password"/i, 'type="text"')
  377. .replace(/type=password/i, 'type=text')
  378. );
  379.  
  380. if (i.attr('id') != '')
  381. x.attr('id', i.attr('id') + '-polyfill-field');
  382.  
  383. if (i.attr('name') != '')
  384. x.attr('name', i.attr('name') + '-polyfill-field');
  385.  
  386. x.addClass('polyfill-placeholder')
  387. .val(x.attr('placeholder')).insertAfter(i);
  388.  
  389. if (i.val() == '')
  390. i.hide();
  391. else
  392. x.hide();
  393.  
  394. i
  395. .on('blur', function(event) {
  396.  
  397. event.preventDefault();
  398.  
  399. var x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]');
  400.  
  401. if (i.val() == '') {
  402.  
  403. i.hide();
  404. x.show();
  405.  
  406. }
  407.  
  408. });
  409.  
  410. x
  411. .on('focus', function(event) {
  412.  
  413. event.preventDefault();
  414.  
  415. var i = x.parent().find('input[name=' + x.attr('name').replace('-polyfill-field', '') + ']');
  416.  
  417. x.hide();
  418.  
  419. i
  420. .show()
  421. .focus();
  422.  
  423. })
  424. .on('keypress', function(event) {
  425.  
  426. event.preventDefault();
  427. x.val('');
  428.  
  429. });
  430.  
  431. });
  432.  
  433. // Events.
  434. $this
  435. .on('submit', function() {
  436.  
  437. $this.find('input[type=text],input[type=password],textarea')
  438. .each(function(event) {
  439.  
  440. var i = $(this);
  441.  
  442. if (i.attr('name').match(/-polyfill-field$/))
  443. i.attr('name', '');
  444.  
  445. if (i.val() == i.attr('placeholder')) {
  446.  
  447. i.removeClass('polyfill-placeholder');
  448. i.val('');
  449.  
  450. }
  451.  
  452. });
  453.  
  454. })
  455. .on('reset', function(event) {
  456.  
  457. event.preventDefault();
  458.  
  459. $this.find('select')
  460. .val($('option:first').val());
  461.  
  462. $this.find('input,textarea')
  463. .each(function() {
  464.  
  465. var i = $(this),
  466. x;
  467.  
  468. i.removeClass('polyfill-placeholder');
  469.  
  470. switch (this.type) {
  471.  
  472. case 'submit':
  473. case 'reset':
  474. break;
  475.  
  476. case 'password':
  477. i.val(i.attr('defaultValue'));
  478.  
  479. x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]');
  480.  
  481. if (i.val() == '') {
  482. i.hide();
  483. x.show();
  484. }
  485. else {
  486. i.show();
  487. x.hide();
  488. }
  489.  
  490. break;
  491.  
  492. case 'checkbox':
  493. case 'radio':
  494. i.attr('checked', i.attr('defaultValue'));
  495. break;
  496.  
  497. case 'text':
  498. case 'textarea':
  499. i.val(i.attr('defaultValue'));
  500.  
  501. if (i.val() == '') {
  502. i.addClass('polyfill-placeholder');
  503. i.val(i.attr('placeholder'));
  504. }
  505.  
  506. break;
  507.  
  508. default:
  509. i.val(i.attr('defaultValue'));
  510. break;
  511.  
  512. }
  513. });
  514.  
  515. });
  516.  
  517. return $this;
  518.  
  519. };
  520.  
  521. /**
  522. * Moves elements to/from the first positions of their respective parents.
  523. * @param {jQuery} $elements Elements (or selector) to move.
  524. * @param {bool} condition If true, moves elements to the top. Otherwise, moves elements back to their original locations.
  525. */
  526. $.prioritize = function($elements, condition) {
  527.  
  528. var key = '__prioritize';
  529.  
  530. // Expand $elements if it's not already a jQuery object.
  531. if (typeof $elements != 'jQuery')
  532. $elements = $($elements);
  533.  
  534. // Step through elements.
  535. $elements.each(function() {
  536.  
  537. var $e = $(this), $p,
  538. $parent = $e.parent();
  539.  
  540. // No parent? Bail.
  541. if ($parent.length == 0)
  542. return;
  543.  
  544. // Not moved? Move it.
  545. if (!$e.data(key)) {
  546.  
  547. // Condition is false? Bail.
  548. if (!condition)
  549. return;
  550.  
  551. // Get placeholder (which will serve as our point of reference for when this element needs to move back).
  552. $p = $e.prev();
  553.  
  554. // Couldn't find anything? Means this element's already at the top, so bail.
  555. if ($p.length == 0)
  556. return;
  557.  
  558. // Move element to top of parent.
  559. $e.prependTo($parent);
  560.  
  561. // Mark element as moved.
  562. $e.data(key, $p);
  563.  
  564. }
  565.  
  566. // Moved already?
  567. else {
  568.  
  569. // Condition is true? Bail.
  570. if (condition)
  571. return;
  572.  
  573. $p = $e.data(key);
  574.  
  575. // Move element back to its original location (using our placeholder).
  576. $e.insertAfter($p);
  577.  
  578. // Unmark element as moved.
  579. $e.removeData(key);
  580.  
  581. }
  582.  
  583. });
  584.  
  585. };
  586.  
  587. })(jQuery);
Add Comment
Please, Sign In to add comment