您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

3033 行
65 KiB

  1. /*
  2. Accordion Tool
  3. http://imperavi.com/kube/
  4. Copyright (c) 2009-2014, Imperavi LLC.
  5. */
  6. (function($)
  7. {
  8. // Plugin
  9. $.fn.accordion = function(options)
  10. {
  11. return this.each(function()
  12. {
  13. $.data(this, 'accordion', {});
  14. $.data(this, 'accordion', Accordion(this, options));
  15. });
  16. };
  17. // Initialization
  18. function Accordion(el, options)
  19. {
  20. return new Accordion.prototype.init(el, options);
  21. }
  22. $.Accordion = Accordion;
  23. $.Accordion.NAME = 'accordion';
  24. $.Accordion.VERSION = '1.0';
  25. $.Accordion.opts = {
  26. scroll: false,
  27. collapse: true,
  28. toggle: true,
  29. titleClass: '.accordion-title',
  30. panelClass: '.accordion-panel'
  31. };
  32. // Functionality
  33. Accordion.fn = $.Accordion.prototype = {
  34. // Initialization
  35. init: function(el, options)
  36. {
  37. this.$element = el !== false ? $(el) : false;
  38. this.loadOptions(options);
  39. this.build();
  40. if (this.opts.collapse)
  41. {
  42. this.closeAll();
  43. }
  44. else
  45. {
  46. this.openAll();
  47. }
  48. this.loadFromHash();
  49. },
  50. loadOptions: function(options)
  51. {
  52. this.opts = $.extend(
  53. {},
  54. $.extend(true, {}, $.Accordion.opts),
  55. this.$element.data(),
  56. options
  57. );
  58. },
  59. setCallback: function(type, e, data)
  60. {
  61. var events = $._data(this.$element[0], 'events');
  62. if (events && typeof events[type] != 'undefined')
  63. {
  64. var value = [];
  65. var len = events[type].length;
  66. for (var i = 0; i < len; i++)
  67. {
  68. var namespace = events[type][i].namespace;
  69. if (namespace == 'tools.' + $.Accordion.NAME || namespace == $.Accordion.NAME + '.tools')
  70. {
  71. var callback = events[type][i].handler;
  72. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  73. }
  74. }
  75. if (value.length == 1) return value[0];
  76. else return value;
  77. }
  78. return (typeof data == 'undefined') ? e : data;
  79. },
  80. getTitles: function()
  81. {
  82. this.titles = this.$element.find(this.opts.titleClass);
  83. this.titles.append($('<span />').addClass('accordion-toggle'));
  84. this.titles.each(function()
  85. {
  86. var $el = $(this);
  87. $el.attr('rel', $el.attr('href'));
  88. });
  89. },
  90. getPanels: function()
  91. {
  92. this.panels = this.$element.find(this.opts.panelClass);
  93. },
  94. build: function()
  95. {
  96. this.getTitles();
  97. this.getPanels();
  98. this.titles.on('click', $.proxy(this.toggle, this));
  99. },
  100. loadFromHash: function()
  101. {
  102. if (top.location.hash === '') return;
  103. if (!this.opts.scroll) return;
  104. if (this.$element.find('[rel=' + top.location.hash +']').size() === 0) return;
  105. this.open(top.location.hash);
  106. this.scrollTo(top.location.hash);
  107. },
  108. toggle: function(e)
  109. {
  110. e.preventDefault();
  111. e.stopPropagation();
  112. var hash = $(e.target).attr('rel');
  113. if (this.opts.toggle)
  114. {
  115. var $target = $(e.target);
  116. var $title = $target.closest(this.opts.titleClass);
  117. var opened = $title.hasClass('accordion-title-opened');
  118. this.closeAll();
  119. if (!opened) this.open(hash);
  120. }
  121. else
  122. {
  123. if ($('[rel=' + hash + ']').hasClass('accordion-title-opened'))
  124. {
  125. this.close(hash);
  126. }
  127. else
  128. {
  129. this.open(hash);
  130. }
  131. }
  132. },
  133. open: function(hash)
  134. {
  135. this.$title = $('[rel=' + hash + ']');
  136. this.$panel = $(hash);
  137. top.location.hash = hash;
  138. this.setStatus('open');
  139. this.$panel.show();
  140. this.setCallback('opened', this.$title, this.$panel);
  141. },
  142. close: function(hash)
  143. {
  144. this.$title = $('[rel=' + hash + ']');
  145. this.$panel = $(hash);
  146. this.setStatus('close');
  147. this.$panel.hide();
  148. this.setCallback('closed', this.$title, this.$panel);
  149. },
  150. setStatus: function(command)
  151. {
  152. var items = { toggle: this.$title.find('span.accordion-toggle'), title: this.$title, panel: this.$panel };
  153. $.each(items, function(i, s)
  154. {
  155. if (command == 'close')
  156. {
  157. s.removeClass('accordion-' + i + '-opened').addClass('accordion-' + i + '-closed');
  158. }
  159. else
  160. {
  161. s.removeClass('accordion-' + i + '-closed').addClass('accordion-' + i + '-opened');
  162. }
  163. });
  164. },
  165. openAll: function()
  166. {
  167. this.titles.each($.proxy(function(i, s)
  168. {
  169. this.open($(s).attr('rel'));
  170. }, this));
  171. },
  172. closeAll: function()
  173. {
  174. this.titles.each($.proxy(function(i, s)
  175. {
  176. this.close($(s).attr('rel'));
  177. }, this));
  178. },
  179. scrollTo: function(id)
  180. {
  181. $('html, body').animate(
  182. {
  183. scrollTop: $(id).offset().top - 50
  184. }, 500);
  185. }
  186. };
  187. $(window).on('load.tools.accordion', function()
  188. {
  189. $('[data-tools="accordion"]').accordion();
  190. });
  191. // constructor
  192. Accordion.prototype.init.prototype = Accordion.prototype;
  193. })(jQuery);
  194. /*
  195. Autocomplete Tool
  196. http://imperavi.com/kube/
  197. Copyright (c) 2009-2014, Imperavi LLC.
  198. */
  199. (function($)
  200. {
  201. // Plugin
  202. $.fn.autocomplete = function(options)
  203. {
  204. return this.each(function()
  205. {
  206. $.data(this, 'autocomplete', {});
  207. $.data(this, 'autocomplete', Autocomplete(this, options));
  208. });
  209. };
  210. // Initialization
  211. function Autocomplete(el, options)
  212. {
  213. return new Autocomplete.prototype.init(el, options);
  214. }
  215. $.Autocomplete = Autocomplete;
  216. $.Autocomplete.NAME = 'autocomplete';
  217. $.Autocomplete.VERSION = '1.0';
  218. $.Autocomplete.opts = {
  219. url: false,
  220. min: 2,
  221. set: 'value' // value or id
  222. };
  223. // Functionality
  224. Autocomplete.fn = $.Autocomplete.prototype = {
  225. // Initialization
  226. init: function(el, options)
  227. {
  228. this.$element = el !== false ? $(el) : false;
  229. this.loadOptions(options);
  230. this.build();
  231. },
  232. loadOptions: function(options)
  233. {
  234. this.opts = $.extend(
  235. {},
  236. $.extend(true, {}, $.Autocomplete.opts),
  237. this.$element.data(),
  238. options
  239. );
  240. },
  241. setCallback: function(type, e, data)
  242. {
  243. var events = $._data(this.$element[0], 'events');
  244. if (events && typeof events[type] != 'undefined')
  245. {
  246. var value = [];
  247. var len = events[type].length;
  248. for (var i = 0; i < len; i++)
  249. {
  250. var namespace = events[type][i].namespace;
  251. if (namespace == 'tools.' + $.Autocomplete.NAME || namespace == $.Autocomplete.NAME + '.tools')
  252. {
  253. var callback = events[type][i].handler;
  254. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  255. }
  256. }
  257. if (value.length == 1) return value[0];
  258. else return value;
  259. }
  260. return (typeof data == 'undefined') ? e : data;
  261. },
  262. build: function()
  263. {
  264. this.result = $('<ul class="autocomplete">').hide();
  265. this.pos = this.$element.offset();
  266. this.elementHeight = this.$element.innerHeight();
  267. $('body').append(this.result);
  268. this.placement = (($(document).height() - (this.pos.top + this.elementHeight)) < this.result.height()) ? 'top' : 'bottom';
  269. $(document).on('click', $.proxy(this.hide, this));
  270. this.$element.on('keyup', $.proxy(function(e)
  271. {
  272. var value = this.$element.val();
  273. if (value.length >= this.opts.min)
  274. {
  275. this.$element.addClass('autocomplete-in');
  276. this.result.addClass('autocomplete-open');
  277. this.listen(e);
  278. }
  279. else
  280. {
  281. this.hide();
  282. }
  283. }, this));
  284. },
  285. lookup: function()
  286. {
  287. $.ajax({
  288. url: this.opts.url,
  289. type: 'post',
  290. data: this.$element.attr('name') + '=' + this.$element.val(),
  291. success: $.proxy(function(json)
  292. {
  293. var data = $.parseJSON(json);
  294. this.result.html('');
  295. $.each(data, $.proxy(function(i,s)
  296. {
  297. var li = $('<li>');
  298. var a = $('<a href="#" rel="' + s.id + '">').html(s.value).on('click', $.proxy(this.set, this));
  299. li.append(a);
  300. this.result.append(li);
  301. }, this));
  302. var top = (this.placement === 'top') ? (this.pos.top - this.result.height() - this.elementHeight) : (this.pos.top + this.elementHeight);
  303. this.result.css({ top: top + 'px', left: this.pos.left + 'px' });
  304. this.result.show();
  305. this.active = false;
  306. }, this)
  307. });
  308. },
  309. listen: function(e)
  310. {
  311. if (!this.$element.hasClass('autocomplete-in')) return;
  312. e.stopPropagation();
  313. e.preventDefault();
  314. switch(e.keyCode)
  315. {
  316. case 40: // down arrow
  317. this.select('next');
  318. break;
  319. case 38: // up arrow
  320. this.select('prev');
  321. break;
  322. case 13: // enter
  323. this.set();
  324. break;
  325. case 27: // escape
  326. this.hide();
  327. break;
  328. default:
  329. this.lookup();
  330. break;
  331. }
  332. },
  333. select: function(type)
  334. {
  335. var $links = this.result.find('a');
  336. var size = $links.size();
  337. var $active = this.result.find('a.active');
  338. $active.removeClass('active');
  339. var $item = (type === 'next') ? $active.parent().next().children('a') : $active.parent().prev().children('a');
  340. if ($item.size() === 0)
  341. {
  342. $item = (type === 'next') ? $links.eq(0) : $links.eq(size-1);
  343. }
  344. $item.addClass('active');
  345. this.active = $item;
  346. },
  347. set: function(e)
  348. {
  349. var $el = $(this.active);
  350. if (e)
  351. {
  352. e.preventDefault();
  353. $el = $(e.target);
  354. }
  355. var id = $el.attr('rel');
  356. var value = $el.html();
  357. if (this.opts.set == 'value')
  358. {
  359. this.$element.val(value);
  360. }
  361. else
  362. {
  363. this.$element.val(id);
  364. }
  365. this.setCallback('set', id, value);
  366. this.hide();
  367. },
  368. hide: function(e)
  369. {
  370. if (e && ($(e.target).hasClass('autocomplete-in') || $(e.target).hasClass('autocomplete-open') || $(e.target).parents().hasClass('autocomplete-open')))
  371. {
  372. return;
  373. }
  374. this.$element.removeClass('autocomplete-in');
  375. this.result.removeClass('autocomplete-open');
  376. this.result.hide();
  377. }
  378. };
  379. $(window).on('load.tools.autocomplete', function()
  380. {
  381. $('[data-tools="autocomplete"]').autocomplete();
  382. });
  383. // constructor
  384. Autocomplete.prototype.init.prototype = Autocomplete.prototype;
  385. })(jQuery);
  386. /*
  387. Buttons Tool
  388. http://imperavi.com/kube/
  389. Copyright (c) 2009-2014, Imperavi LLC.
  390. */
  391. (function($)
  392. {
  393. // Plugin
  394. $.fn.buttons = function(options)
  395. {
  396. return this.each(function()
  397. {
  398. $.data(this, 'buttons', {});
  399. $.data(this, 'buttons', Buttons(this, options));
  400. });
  401. };
  402. // Initialization
  403. function Buttons(el, options)
  404. {
  405. return new Buttons.prototype.init(el, options);
  406. }
  407. $.Buttons = Buttons;
  408. $.Buttons.NAME = 'buttons';
  409. $.Buttons.VERSION = '1.0';
  410. $.Buttons.opts = {
  411. className: 'btn',
  412. activeClassName: 'btn-active',
  413. target: false,
  414. type: 'switch' // switch, toggle, segmented
  415. };
  416. // Functionality
  417. Buttons.fn = $.Buttons.prototype = {
  418. // Initialization
  419. init: function(el, options)
  420. {
  421. this.$element = el !== false ? $(el) : false;
  422. this.loadOptions(options);
  423. this.buttons = this.getButtons();
  424. this.value = this.getValue();
  425. this.buttons.each($.proxy(function(i,s)
  426. {
  427. var $s = $(s);
  428. this.setDefault($s);
  429. $s.click($.proxy(function(e)
  430. {
  431. e.preventDefault();
  432. if (this.opts.type === 'segmented') this.setSegmented($s);
  433. else if (this.opts.type === 'toggle') this.setToggle($s);
  434. else this.setBasic($s);
  435. }, this));
  436. }, this));
  437. },
  438. loadOptions: function(options)
  439. {
  440. this.opts = $.extend(
  441. {},
  442. $.extend(true, {}, $.Buttons.opts),
  443. this.$element.data(),
  444. options
  445. );
  446. },
  447. getButtons: function()
  448. {
  449. return (this.opts.type === 'toggle') ? this.$element : this.$element.find('.' + this.opts.className);
  450. },
  451. getValue: function()
  452. {
  453. return (this.opts.type === 'segmented') ? $(this.opts.target).val().split(',') : $(this.opts.target).val();
  454. },
  455. setDefault: function($el)
  456. {
  457. if (this.opts.type === 'segmented' && $.inArray($el.val(), this.value) !== -1)
  458. {
  459. this.setActive($el);
  460. }
  461. else if ((this.opts.type === 'toggle' && this.value === 1) || this.value === $el.val())
  462. {
  463. this.setActive($el);
  464. }
  465. },
  466. setBasic: function($el)
  467. {
  468. this.setInActive(this.buttons);
  469. this.setActive($el);
  470. $(this.opts.target).val($el.val());
  471. },
  472. setSegmented: function($el)
  473. {
  474. var $target = $(this.opts.target);
  475. this.value = $target.val().split(',');
  476. if (!$el.hasClass(this.opts.activeClassName))
  477. {
  478. this.setActive($el);
  479. this.value.push($el.val());
  480. }
  481. else
  482. {
  483. this.setInActive($el);
  484. this.value.splice(this.value.indexOf($el.val()), 1);
  485. }
  486. $target.val(this.value.join(',').replace(/^,/, ''));
  487. },
  488. setToggle: function($el)
  489. {
  490. if ($el.hasClass(this.opts.activeClassName))
  491. {
  492. this.setInActive($el);
  493. $(this.opts.target).val(0);
  494. }
  495. else
  496. {
  497. this.setActive($el);
  498. $(this.opts.target).val(1);
  499. }
  500. },
  501. setActive: function($el)
  502. {
  503. $el.addClass(this.opts.activeClassName);
  504. },
  505. setInActive: function($el)
  506. {
  507. $el.removeClass(this.opts.activeClassName);
  508. }
  509. };
  510. $(window).on('load.tools.buttons', function()
  511. {
  512. $('[data-tools="buttons"]').buttons();
  513. });
  514. // constructor
  515. Buttons.prototype.init.prototype = Buttons.prototype;
  516. })(jQuery);
  517. /*
  518. CheckAll Tool
  519. http://imperavi.com/kube/
  520. Copyright (c) 2009-2014, Imperavi LLC.
  521. */
  522. (function($)
  523. {
  524. // Plugin
  525. $.fn.checkAll = function(options)
  526. {
  527. return this.each(function()
  528. {
  529. $.data(this, 'checkAll', {});
  530. $.data(this, 'checkAll', CheckAll(this, options));
  531. });
  532. };
  533. // Initialization
  534. function CheckAll(el, options)
  535. {
  536. return new CheckAll.prototype.init(el, options);
  537. }
  538. $.CheckAll = CheckAll;
  539. $.CheckAll.opts = {
  540. classname: false,
  541. parent: false,
  542. highlight: 'highlight',
  543. target: false
  544. };
  545. // Functionality
  546. CheckAll.fn = $.CheckAll.prototype = {
  547. // Initialization
  548. init: function(el, options)
  549. {
  550. this.$element = el !== false ? $(el) : false;
  551. this.loadOptions(options);
  552. this.$elements = $('.' + this.opts.classname);
  553. this.$target = $(this.opts.target);
  554. // load
  555. this.$element.on('click', $.proxy(this.load, this));
  556. this.setter = (this.opts.target) ? this.$target.val().split(',') : [];
  557. this.$elements.each($.proxy(this.setOnStart, this));
  558. },
  559. loadOptions: function(options)
  560. {
  561. this.opts = $.extend(
  562. {},
  563. $.extend(true, {}, $.CheckAll.opts),
  564. this.$element.data(),
  565. options
  566. );
  567. },
  568. load: function()
  569. {
  570. if (this.$element.prop('checked'))
  571. {
  572. this.$elements.prop('checked', true);
  573. if (this.opts.parent || this.opts.target)
  574. {
  575. this.$elements.each($.proxy(function(i,s)
  576. {
  577. var $s = $(s);
  578. this.setHighlight($s);
  579. this.setValue($s.val());
  580. }, this));
  581. }
  582. }
  583. else
  584. {
  585. this.$elements.prop('checked', false);
  586. if (this.opts.parent) this.$elements.each($.proxy(this.removeHighlight, this));
  587. if (this.opts.target) this.$target.val('');
  588. }
  589. },
  590. setOnStart: function(i, el)
  591. {
  592. var $el = $(el);
  593. if (this.$element.prop('checked') || (this.setter && ($.inArray($el.val(), this.setter) !== -1)))
  594. {
  595. $el.prop('checked', true);
  596. this.setHighlight($el);
  597. }
  598. $el.on('click', $.proxy(function()
  599. {
  600. var checkedSize = this.$elements.filter(':checked').size();
  601. if ($el.prop('checked'))
  602. {
  603. this.setValue($el.val());
  604. this.setHighlight($el);
  605. }
  606. else
  607. {
  608. this.removeValue($el.val());
  609. this.removeHighlight($el);
  610. }
  611. var prop = (checkedSize !== this.$elements.size()) ? false : true;
  612. this.$element.prop('checked', prop);
  613. }, this));
  614. },
  615. setHighlight: function($el)
  616. {
  617. if (!this.opts.parent) return;
  618. $el.closest(this.opts.parent).addClass(this.opts.highlight);
  619. },
  620. removeHighlight: function(i, $el)
  621. {
  622. if (!this.opts.parent) return;
  623. $($el).closest(this.opts.parent).removeClass(this.opts.highlight);
  624. },
  625. setValue: function(value)
  626. {
  627. if (!this.opts.target) return;
  628. var str = this.$target.val();
  629. var arr = str.split(',');
  630. arr.push(value);
  631. if (str === '')
  632. {
  633. arr = [value];
  634. }
  635. this.$target.val(arr.join(','));
  636. },
  637. removeValue: function(value)
  638. {
  639. if (!this.opts.target) return;
  640. var arr = this.$target.val().split(',');
  641. var index = arr.indexOf(value);
  642. arr.splice(index, 1);
  643. this.$target.val(arr.join(','));
  644. }
  645. };
  646. $(window).on('load.tools.buttons', function()
  647. {
  648. $('[data-tools="check-all"]').checkAll();
  649. });
  650. // constructor
  651. CheckAll.prototype.init.prototype = CheckAll.prototype;
  652. })(jQuery);
  653. /*
  654. Dropdown Tool
  655. http://imperavi.com/kube/
  656. Copyright (c) 2009-2014, Imperavi LLC.
  657. */
  658. (function($)
  659. {
  660. // Plugin
  661. $.fn.dropdown = function(options)
  662. {
  663. return this.each(function()
  664. {
  665. $.data(this, 'dropdown', {});
  666. $.data(this, 'dropdown', Dropdown(this, options));
  667. });
  668. };
  669. // Initialization
  670. function Dropdown(el, options)
  671. {
  672. return new Dropdown.prototype.init(el, options);
  673. }
  674. $.Dropdown = Dropdown;
  675. $.Dropdown.NAME = 'dropdown';
  676. $.Dropdown.VERSION = '1.0';
  677. $.Dropdown.opts = {
  678. target: false,
  679. targetClose: false,
  680. height: false, // number
  681. width: false // number
  682. };
  683. // Functionality
  684. Dropdown.fn = $.Dropdown.prototype = {
  685. // Initialization
  686. init: function(el, options)
  687. {
  688. this.$element = el !== false ? $(el) : false;
  689. this.loadOptions(options);
  690. this.build();
  691. },
  692. loadOptions: function(options)
  693. {
  694. this.opts = $.extend(
  695. {},
  696. $.extend(true, {}, $.Dropdown.opts),
  697. this.$element.data(),
  698. options
  699. );
  700. },
  701. setCallback: function(type, e, data)
  702. {
  703. var events = $._data(this.$element[0], 'events');
  704. if (events && typeof events[type] != 'undefined')
  705. {
  706. var value = [];
  707. var len = events[type].length;
  708. for (var i = 0; i < len; i++)
  709. {
  710. var namespace = events[type][i].namespace;
  711. if (namespace == 'tools.' + $.Dropdown.NAME || namespace == $.Dropdown.NAME + '.tools')
  712. {
  713. var callback = events[type][i].handler;
  714. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  715. }
  716. }
  717. if (value.length == 1) return value[0];
  718. else return value;
  719. }
  720. return (typeof data == 'undefined') ? e : data;
  721. },
  722. build: function()
  723. {
  724. this.$dropdown = $(this.opts.target);
  725. this.$dropdown.hide();
  726. this.$caret = $('<b class="caret"></b>');
  727. this.$element.append(this.$caret);
  728. this.setCaretUp();
  729. this.preventBodyScroll();
  730. this.$element.click($.proxy(this.toggle, this));
  731. },
  732. setCaretUp: function()
  733. {
  734. var height = this.$element.offset().top + this.$element.innerHeight() + this.$dropdown.innerHeight();
  735. if ($(document).height() > height) return;
  736. this.$caret.addClass('caret-up');
  737. },
  738. toggle: function(e)
  739. {
  740. e.preventDefault();
  741. if (this.$element.hasClass('dropdown-in'))
  742. {
  743. this.hide();
  744. }
  745. else
  746. {
  747. this.show();
  748. }
  749. },
  750. getPlacement: function(height)
  751. {
  752. return ($(document).height() < height) ? 'top' : 'bottom';
  753. },
  754. getPosition: function()
  755. {
  756. return (this.$element.closest('.navigation-fixed').size() !== 0) ? 'fixed' : 'absolute';
  757. },
  758. setPosition: function()
  759. {
  760. var pos = this.$element.position();
  761. var elementHeight = this.$element.innerHeight();
  762. var elementWidth = this.$element.innerWidth();
  763. var height = this.$dropdown.innerHeight();
  764. var width = this.$dropdown.innerWidth();
  765. var position = this.getPosition();
  766. var placement = this.getPlacement(pos.top + height + elementHeight);
  767. var leftFix = 0;
  768. if ($(window).width() < (pos.left + width))
  769. {
  770. leftFix = (width - elementWidth);
  771. }
  772. var top;
  773. var left = pos.left - leftFix;
  774. if (placement == 'bottom')
  775. {
  776. this.$caret.removeClass('caret-up');
  777. top = (position == 'fixed') ? elementHeight : pos.top + elementHeight;
  778. }
  779. else
  780. {
  781. this.$caret.addClass('caret-up');
  782. top = (position == 'fixed') ? height : pos.top - height;
  783. }
  784. this.$dropdown.css({ position: position, top: top + 'px', left: left + 'px' });
  785. },
  786. show: function()
  787. {
  788. $('.dropdown-in').removeClass('dropdown-in');
  789. $('.dropdown').removeClass('dropdown-open').hide();
  790. if (this.opts.height) this.$dropdown.css('min-height', this.opts.height + 'px');
  791. if (this.opts.width) this.$dropdown.width(this.opts.width);
  792. this.setPosition();
  793. this.$dropdown.addClass('dropdown-open').show();
  794. this.$element.addClass('dropdown-in');
  795. $(document).on('scroll.tools.dropdown', $.proxy(this.setPosition, this));
  796. $(window).on('resize.tools.dropdown', $.proxy(this.setPosition, this));
  797. $(document).on('click.tools.dropdown touchstart.tools.dropdown', $.proxy(this.hide, this));
  798. if (this.opts.targetClose)
  799. {
  800. $(this.opts.targetClose).on('click.tools.dropdown', $.proxy(function(e)
  801. {
  802. e.preventDefault();
  803. this.hide(false);
  804. }, this));
  805. }
  806. $(document).on('keydown.tools.dropdown', $.proxy(function(e)
  807. {
  808. // esc
  809. if (e.which === 27) this.hide();
  810. }, this));
  811. this.setCallback('opened', this.$dropdown, this.$element);
  812. },
  813. preventBodyScroll: function()
  814. {
  815. this.$dropdown.on('mouseover', function() { $('html').css('overflow', 'hidden'); });
  816. this.$dropdown.on('mouseout', function() { $('html').css('overflow', ''); });
  817. },
  818. hide: function(e)
  819. {
  820. if (e)
  821. {
  822. e = e.originalEvent || e;
  823. var $target = $(e.target);
  824. if ($target.hasClass('caret') || $target.hasClass('dropdown-in') || $target.closest('.dropdown-open').size() !== 0)
  825. {
  826. return;
  827. }
  828. }
  829. this.$dropdown.removeClass('dropdown-open').hide();
  830. this.$element.removeClass('dropdown-in');
  831. $(document).off('.tools.dropdown');
  832. $(window).off('.tools.dropdown');
  833. this.setCallback('closed', this.$dropdown, this.$element);
  834. }
  835. };
  836. $(window).on('load.tools.dropdown', function()
  837. {
  838. $('[data-tools="dropdown"]').dropdown();
  839. });
  840. // constructor
  841. Dropdown.prototype.init.prototype = Dropdown.prototype;
  842. })(jQuery);
  843. /*
  844. FilterBox Tool
  845. http://imperavi.com/kube/
  846. Copyright (c) 2009-2014, Imperavi LLC.
  847. */
  848. (function($)
  849. {
  850. // Plugin
  851. $.fn.filterbox = function(options)
  852. {
  853. return this.each(function()
  854. {
  855. $.data(this, 'filterbox', {});
  856. $.data(this, 'filterbox', Filterbox(this, options));
  857. });
  858. };
  859. // Initialization
  860. function Filterbox(el, options)
  861. {
  862. return new Filterbox.prototype.init(el, options);
  863. }
  864. $.Filterbox = Filterbox;
  865. $.Filterbox.NAME = 'filterbox';
  866. $.Filterbox.VERSION = '1.0';
  867. $.Filterbox.opts = {
  868. // settings
  869. placeholder: false
  870. };
  871. // Functionality
  872. Filterbox.fn = $.Filterbox.prototype = {
  873. // Initialization
  874. init: function(el, options)
  875. {
  876. this.$element = el !== false ? $(el) : false;
  877. this.loadOptions(options);
  878. this.build();
  879. },
  880. loadOptions: function(options)
  881. {
  882. this.opts = $.extend(
  883. {},
  884. $.extend(true, {}, $.Filterbox.opts),
  885. this.$element.data(),
  886. options
  887. );
  888. },
  889. setCallback: function(type, e, data)
  890. {
  891. var events = $._data(this.$element[0], 'events');
  892. if (events && typeof events[type] != 'undefined')
  893. {
  894. var value = [];
  895. var len = events[type].length;
  896. for (var i = 0; i < len; i++)
  897. {
  898. var namespace = events[type][i].namespace;
  899. if (namespace == 'tools.' + $.Filterbox.NAME || namespace == $.Filterbox.NAME + '.tools')
  900. {
  901. var callback = events[type][i].handler;
  902. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  903. }
  904. }
  905. if (value.length == 1) return value[0];
  906. else return value;
  907. }
  908. return (typeof data == 'undefined') ? e : data;
  909. },
  910. build: function()
  911. {
  912. this.$sourceBox = $('<div class="filterbox" />');
  913. this.$sourceSelect = $('<span class="filterbox-toggle" />');
  914. this.$sourceLayer = $('<ul class="filterbox-list hide" />');
  915. this.$source = $('<input type="text" id="' + this.$element.attr('id') + '-input" class="' + this.$element.attr('class') + '" />');
  916. this.$sourceBox.append(this.$source);
  917. this.$sourceBox.append(this.$sourceSelect);
  918. this.$sourceBox.append(this.$sourceLayer);
  919. this.setPlaceholder();
  920. this.$element.hide().after(this.$sourceBox);
  921. this.$element.find('option').each($.proxy(this.buildListItemsFromOptions, this));
  922. this.$source.on('keyup', $.proxy(this.clearSelected, this));
  923. this.$sourceSelect.on('click', $.proxy(this.load, this));
  924. this.preventBodyScroll();
  925. },
  926. load: function(e)
  927. {
  928. e.preventDefault();
  929. if (this.$sourceLayer.hasClass('open'))
  930. {
  931. this.close();
  932. return;
  933. }
  934. var value = this.$element.val();
  935. this.$sourceLayer.addClass('open').show();
  936. var items = this.$sourceLayer.find('li').removeClass('active');
  937. this.setSelectedItem(items, value);
  938. $(document).on('click.tools.filterbox', $.proxy(this.close, this));
  939. $(document).on('keydown.tools.filterbox', $.proxy(function(e)
  940. {
  941. var key = e.which;
  942. var $el;
  943. var item;
  944. if (key === 38) // up
  945. {
  946. e.preventDefault();
  947. if (items.hasClass('active'))
  948. {
  949. item = items.filter('li.active');
  950. item.removeClass('active');
  951. var prev = item.prev();
  952. $el = (prev.size() !== 0) ? $el = prev : items.last();
  953. }
  954. else
  955. {
  956. $el = items.last();
  957. }
  958. $el.addClass('active');
  959. this.setScrollTop($el);
  960. }
  961. else if (key === 40) // down
  962. {
  963. e.preventDefault();
  964. if (items.hasClass('active'))
  965. {
  966. item = items.filter('li.active');
  967. item.removeClass('active');
  968. var next = item.next();
  969. $el = (next.size() !== 0) ? next : items.first();
  970. }
  971. else
  972. {
  973. $el = items.first();
  974. }
  975. $el.addClass('active');
  976. this.setScrollTop($el);
  977. }
  978. else if (key === 13) // enter
  979. {
  980. if (!items.hasClass('active')) return;
  981. item = items.filter('li.active');
  982. this.onItemClick(e, item);
  983. }
  984. else if (key === 27) // esc
  985. {
  986. this.close();
  987. }
  988. }, this));
  989. },
  990. clearSelected: function()
  991. {
  992. if (this.$source.val().length === 0) this.$element.val(0);
  993. },
  994. setSelectedItem: function(items, value)
  995. {
  996. var selectEl = items.filter('[rel=' + value + ']');
  997. if (selectEl.size() === 0)
  998. {
  999. selectEl = false;
  1000. // if user typed value
  1001. var sourceValue = this.$source.val();
  1002. $.each(items, function(i,s)
  1003. {
  1004. var $s = $(s);
  1005. if ($s.text() == sourceValue)
  1006. {
  1007. selectEl = $s;
  1008. }
  1009. });
  1010. if (selectEl === false) return;
  1011. }
  1012. selectEl.addClass('active');
  1013. this.setScrollTop(selectEl);
  1014. },
  1015. setScrollTop: function($el)
  1016. {
  1017. this.$sourceLayer.scrollTop(this.$sourceLayer.scrollTop() + $el.position().top - 40);
  1018. },
  1019. buildListItemsFromOptions: function(i,s)
  1020. {
  1021. var $el = $(s);
  1022. var val = $el.val();
  1023. if (val === 0) return;
  1024. var item = $('<li />');
  1025. item.attr('rel', val).text($el.html());
  1026. item.on('click', $.proxy(this.onItemClick, this));
  1027. this.$sourceLayer.append(item);
  1028. },
  1029. onItemClick: function(e, item)
  1030. {
  1031. e.preventDefault();
  1032. var $el = $(item || e.target);
  1033. var rel = $el.attr('rel');
  1034. var text = $el.text();
  1035. this.$source.val(text);
  1036. this.$element.val(rel);
  1037. this.close();
  1038. this.setCallback('select', { id: rel, value: text });
  1039. },
  1040. preventBodyScroll: function()
  1041. {
  1042. this.$sourceLayer.on('mouseover', function() { $('html').css('overflow', 'hidden'); });
  1043. this.$sourceLayer.on('mouseout', function() { $('html').css('overflow', ''); });
  1044. },
  1045. setPlaceholder: function()
  1046. {
  1047. if (!this.opts.placeholder) return;
  1048. this.$source.attr('placeholder', this.opts.placeholder);
  1049. },
  1050. close: function(e)
  1051. {
  1052. if (e && ($(e.target).hasClass('filterbox-toggle') || $(e.target).closest('div.filterbox').size() == 1))
  1053. {
  1054. return;
  1055. }
  1056. this.$sourceLayer.removeClass('open').hide();
  1057. $(document).off('.tools.filterbox');
  1058. }
  1059. };
  1060. $(window).on('load.tools.filterbox', function()
  1061. {
  1062. $('[data-tools="filterbox"]').filterbox();
  1063. });
  1064. // constructor
  1065. Filterbox.prototype.init.prototype = Filterbox.prototype;
  1066. })(jQuery);
  1067. /*
  1068. Infinity Scroll Tool
  1069. http://imperavi.com/kube/
  1070. Copyright (c) 2009-2014, Imperavi LLC.
  1071. */
  1072. (function($)
  1073. {
  1074. // Plugin
  1075. $.fn.infinityScroll = function(options)
  1076. {
  1077. return this.each(function()
  1078. {
  1079. $.data(this, 'infinity-scroll', {});
  1080. $.data(this, 'infinity-scroll', InfinityScroll(this, options));
  1081. });
  1082. };
  1083. // Initialization
  1084. function InfinityScroll(el, options)
  1085. {
  1086. return new InfinityScroll.prototype.init(el, options);
  1087. }
  1088. $.InfinityScroll = InfinityScroll;
  1089. $.InfinityScroll.NAME = 'infinity-scroll';
  1090. $.InfinityScroll.VERSION = '1.0';
  1091. $.InfinityScroll.opts = {
  1092. url: false,
  1093. offset: 0,
  1094. limit: 20,
  1095. tolerance: 50,
  1096. pagination: false
  1097. };
  1098. // Functionality
  1099. InfinityScroll.fn = $.InfinityScroll.prototype = {
  1100. // Initialization
  1101. init: function(el, options)
  1102. {
  1103. this.$element = el !== false ? $(el) : false;
  1104. this.loadOptions(options);
  1105. this.hidePagination();
  1106. this.build();
  1107. },
  1108. loadOptions: function(options)
  1109. {
  1110. this.opts = $.extend(
  1111. {},
  1112. $.extend(true, {}, $.InfinityScroll.opts),
  1113. this.$element.data(),
  1114. options
  1115. );
  1116. },
  1117. setCallback: function(type, e, data)
  1118. {
  1119. var events = $._data(this.$element[0], 'events');
  1120. if (events && typeof events[type] != 'undefined')
  1121. {
  1122. var value = [];
  1123. var len = events[type].length;
  1124. for (var i = 0; i < len; i++)
  1125. {
  1126. var namespace = events[type][i].namespace;
  1127. if (namespace == 'tools.' + $.InfinityScroll.NAME || namespace == $.InfinityScroll.NAME + '.tools')
  1128. {
  1129. var callback = events[type][i].handler;
  1130. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  1131. }
  1132. }
  1133. if (value.length == 1) return value[0];
  1134. else return value;
  1135. }
  1136. return (typeof data == 'undefined') ? e : data;
  1137. },
  1138. build: function()
  1139. {
  1140. $(window).on('DOMContentLoaded.tools.infinite-scroll load.tools.infinite-scroll resize.tools.infinite-scroll scroll.tools.infinite-scroll', $.proxy(function()
  1141. {
  1142. var $last = this.$element.children().last();
  1143. if (this.isElementInViewport($last[0]))
  1144. {
  1145. this.getData();
  1146. }
  1147. }, this));
  1148. },
  1149. getData: function()
  1150. {
  1151. $.ajax({
  1152. url: this.opts.url,
  1153. type: 'post',
  1154. data: 'limit=' + this.opts.limit + '&offset=' + this.opts.offset,
  1155. success: $.proxy(function(data)
  1156. {
  1157. if (data === '')
  1158. {
  1159. $(window).off('.tools.infinite-scroll');
  1160. return;
  1161. }
  1162. this.opts.offset = this.opts.offset + this.opts.limit;
  1163. this.$element.append(data);
  1164. this.setCallback('loaded', data);
  1165. }, this)
  1166. });
  1167. },
  1168. hidePagination: function()
  1169. {
  1170. if (!this.opts.pagination) return;
  1171. $(this.opts.pagination).hide();
  1172. },
  1173. isElementInViewport: function(el)
  1174. {
  1175. var rect = el.getBoundingClientRect();
  1176. return (
  1177. rect.top >= 0 &&
  1178. rect.left >= 0 &&
  1179. rect.bottom <= $(window).height() + this.opts.tolerance &&
  1180. rect.right <= $(window).width()
  1181. );
  1182. }
  1183. };
  1184. $(window).on('load.tools.infinity-scroll', function()
  1185. {
  1186. $('[data-tools="infinity-scroll"]').infinityScroll();
  1187. });
  1188. // constructor
  1189. InfinityScroll.prototype.init.prototype = InfinityScroll.prototype;
  1190. })(jQuery);
  1191. /*
  1192. Livesearch Tool
  1193. http://imperavi.com/kube/
  1194. Copyright (c) 2009-2014, Imperavi LLC.
  1195. */
  1196. (function($)
  1197. {
  1198. // Plugin
  1199. $.fn.livesearch = function(options)
  1200. {
  1201. return this.each(function()
  1202. {
  1203. $.data(this, 'livesearch', {});
  1204. $.data(this, 'livesearch', Livesearch(this, options));
  1205. });
  1206. };
  1207. // Initialization
  1208. function Livesearch(el, options)
  1209. {
  1210. return new Livesearch.prototype.init(el, options);
  1211. }
  1212. $.Livesearch = Livesearch;
  1213. $.Livesearch.NAME = 'livesearch';
  1214. $.Livesearch.VERSION = '1.0';
  1215. $.Livesearch.opts = {
  1216. // settings
  1217. url: false,
  1218. target: false,
  1219. min: 2,
  1220. params: false,
  1221. appendForms: false
  1222. };
  1223. // Functionality
  1224. Livesearch.fn = $.Livesearch.prototype = {
  1225. // Initialization
  1226. init: function(el, options)
  1227. {
  1228. this.$element = el !== false ? $(el) : false;
  1229. this.loadOptions(options);
  1230. this.build();
  1231. },
  1232. loadOptions: function(options)
  1233. {
  1234. this.opts = $.extend(
  1235. {},
  1236. $.extend(true, {}, $.Livesearch.opts),
  1237. this.$element.data(),
  1238. options
  1239. );
  1240. },
  1241. setCallback: function(type, e, data)
  1242. {
  1243. var events = $._data(this.$element[0], 'events');
  1244. if (events && typeof events[type] != 'undefined')
  1245. {
  1246. var value = [];
  1247. var len = events[type].length;
  1248. for (var i = 0; i < len; i++)
  1249. {
  1250. var namespace = events[type][i].namespace;
  1251. if (namespace == 'tools.' + $.Livesearch.NAME || namespace == $.Livesearch.NAME + '.tools')
  1252. {
  1253. var callback = events[type][i].handler;
  1254. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  1255. }
  1256. }
  1257. if (value.length == 1) return value[0];
  1258. else return value;
  1259. }
  1260. return (typeof data == 'undefined') ? e : data;
  1261. },
  1262. build: function()
  1263. {
  1264. this.$box = $('<span class="livesearch-box" />');
  1265. this.$element.after(this.$box);
  1266. this.$box.append(this.$element);
  1267. this.$element.off('keyup.tools.livesearch');
  1268. this.$element.on('keyup.tools.livesearch', $.proxy(this.load, this));
  1269. this.$icon = $('<span class="livesearch-icon" />');
  1270. this.$box.append(this.$icon);
  1271. this.$close = $('<span class="close" />').hide();
  1272. this.$box.append(this.$close);
  1273. this.$close.off('click.tools.livesearch');
  1274. this.$close.on('click.tools.livesearch', $.proxy(function()
  1275. {
  1276. this.search();
  1277. this.$element.val('').focus();
  1278. this.$close.hide();
  1279. }, this));
  1280. },
  1281. toggleClose: function(length)
  1282. {
  1283. if (length === 0) this.$close.hide();
  1284. else this.$close.show();
  1285. },
  1286. load: function()
  1287. {
  1288. var value = this.$element.val();
  1289. var data = '';
  1290. if (value.length > this.opts.min)
  1291. {
  1292. var name = 'q';
  1293. if (typeof this.$element.attr('name') != 'undefined') name = this.$element.attr('name');
  1294. data += '&' + name + '=' + value;
  1295. data = this.appendForms(data);
  1296. var str = '';
  1297. if (this.opts.params)
  1298. {
  1299. this.opts.params = $.trim(this.opts.params.replace('{', '').replace('}', ''))
  1300. var properties = this.opts.params.split(',');
  1301. var obj = {};
  1302. $.each(properties, function(k, v)
  1303. {
  1304. var tup = v.split(':');
  1305. obj[$.trim(tup[0])] = $.trim(tup[1]);
  1306. });
  1307. str = [];
  1308. $.each(obj, $.proxy(function(k, v)
  1309. {
  1310. str.push(k + "=" + v);
  1311. }, this));
  1312. str = str.join("&");
  1313. data += '&' + str;
  1314. }
  1315. }
  1316. this.toggleClose(value.length);
  1317. this.search(data);
  1318. },
  1319. appendForms: function(data)
  1320. {
  1321. if (!this.opts.appendForms) return data;
  1322. $.each(this.opts.appendForms, function(i, s)
  1323. {
  1324. data += '&' + $(s).serialize();
  1325. });
  1326. return data;
  1327. },
  1328. search: function(data)
  1329. {
  1330. $.ajax({
  1331. url: this.opts.url,
  1332. type: 'post',
  1333. data: data,
  1334. success: $.proxy(function(result)
  1335. {
  1336. $(this.opts.target).html(result);
  1337. this.setCallback('result', result);
  1338. }, this)
  1339. });
  1340. }
  1341. };
  1342. $(window).on('load.tools.livesearch', function()
  1343. {
  1344. $('[data-tools="livesearch"]').livesearch();
  1345. });
  1346. // constructor
  1347. Livesearch.prototype.init.prototype = Livesearch.prototype;
  1348. })(jQuery);
  1349. /*
  1350. Tabs Tool
  1351. http://imperavi.com/kube/
  1352. Copyright (c) 2009-2014, Imperavi LLC.
  1353. */
  1354. (function($)
  1355. {
  1356. // Plugin
  1357. $.fn.message = function(options)
  1358. {
  1359. var val = [];
  1360. var args = Array.prototype.slice.call(arguments, 1);
  1361. if (typeof options === 'string')
  1362. {
  1363. this.each(function()
  1364. {
  1365. var instance = $.data(this, 'message');
  1366. if (typeof instance !== 'undefined' && $.isFunction(instance[options]))
  1367. {
  1368. var methodVal = instance[options].apply(instance, args);
  1369. if (methodVal !== undefined && methodVal !== instance) val.push(methodVal);
  1370. }
  1371. else return $.error('No such method "' + options + '" for Message');
  1372. });
  1373. }
  1374. else
  1375. {
  1376. this.each(function()
  1377. {
  1378. $.data(this, 'message', {});
  1379. $.data(this, 'message', Message(this, options));
  1380. });
  1381. }
  1382. if (val.length === 0) return this;
  1383. else if (val.length === 1) return val[0];
  1384. else return val;
  1385. };
  1386. // Initialization
  1387. function Message(el, options)
  1388. {
  1389. return new Message.prototype.init(el, options);
  1390. }
  1391. $.Message = Message;
  1392. $.Message.NAME = 'message';
  1393. $.Message.VERSION = '1.0';
  1394. $.Message.opts = {
  1395. target: false,
  1396. delay: 10 // message delay - seconds or false
  1397. };
  1398. // Functionality
  1399. Message.fn = $.Message.prototype = {
  1400. // Initialization
  1401. init: function(el, options)
  1402. {
  1403. this.$element = el !== false ? $(el) : false;
  1404. this.loadOptions(options);
  1405. this.build();
  1406. },
  1407. loadOptions: function(options)
  1408. {
  1409. this.opts = $.extend(
  1410. {},
  1411. $.extend(true, {}, $.Message.opts),
  1412. this.$element.data(),
  1413. options
  1414. );
  1415. },
  1416. setCallback: function(type, e, data)
  1417. {
  1418. var events = $._data(this.$message[0], 'events');
  1419. if (events && typeof events[type] != 'undefined')
  1420. {
  1421. var value = [];
  1422. var len = events[type].length;
  1423. for (var i = 0; i < len; i++)
  1424. {
  1425. var namespace = events[type][i].namespace;
  1426. if (namespace == 'tools.' + $.Message.NAME || namespace == $.Message.NAME + '.tools')
  1427. {
  1428. var callback = events[type][i].handler;
  1429. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  1430. }
  1431. }
  1432. if (value.length == 1) return value[0];
  1433. else return value;
  1434. }
  1435. return (typeof data == 'undefined') ? e : data;
  1436. },
  1437. build: function()
  1438. {
  1439. if (!this.opts.target)
  1440. {
  1441. this.$message = this.$element;
  1442. this.show();
  1443. }
  1444. else
  1445. {
  1446. this.$message = $(this.opts.target);
  1447. this.$message.data('message', '');
  1448. this.$message.data('message', this);
  1449. this.$element.on('click', $.proxy(this.show, this));
  1450. }
  1451. },
  1452. show: function()
  1453. {
  1454. if (this.$message.hasClass('open'))
  1455. {
  1456. this.hide();
  1457. return;
  1458. }
  1459. $('.tools-message').hide().removeClass('open');
  1460. this.$message.addClass('open').fadeIn('fast').on('click.tools.message', $.proxy(this.hide, this));
  1461. $(document).on('keyup.tools.message', $.proxy(this.hideHandler, this));
  1462. if (this.opts.delay)
  1463. {
  1464. setTimeout($.proxy(this.hide, this), this.opts.delay * 1000);
  1465. }
  1466. this.setCallback('opened');
  1467. },
  1468. hideHandler: function(e)
  1469. {
  1470. if (e.which != 27) return;
  1471. this.hide();
  1472. },
  1473. hide: function()
  1474. {
  1475. if (!this.$message.hasClass('open')) return;
  1476. this.$message.off('click.tools.message');
  1477. $(document).off('keyup.tools.message');
  1478. this.$message.fadeOut('fast', $.proxy(function()
  1479. {
  1480. this.$message.removeClass('open');
  1481. this.setCallback('closed');
  1482. }, this));
  1483. }
  1484. };
  1485. // Constructor
  1486. Message.prototype.init.prototype = Message.prototype;
  1487. $(function()
  1488. {
  1489. $('[data-tools="message"]').message();
  1490. });
  1491. })(jQuery);
  1492. /*
  1493. Modal Tool
  1494. http://imperavi.com/kube/
  1495. Copyright (c) 2009-2014, Imperavi LLC.
  1496. */
  1497. (function($)
  1498. {
  1499. // Plugin
  1500. $.fn.modal = function(options)
  1501. {
  1502. var val = [];
  1503. var args = Array.prototype.slice.call(arguments, 1);
  1504. if (typeof options === 'string')
  1505. {
  1506. this.each(function()
  1507. {
  1508. var instance = $.data(this, 'modal');
  1509. if (typeof instance !== 'undefined' && $.isFunction(instance[options]))
  1510. {
  1511. var methodVal = instance[options].apply(instance, args);
  1512. if (methodVal !== undefined && methodVal !== instance) val.push(methodVal);
  1513. }
  1514. else return $.error('No such method "' + options + '" for Modal');
  1515. });
  1516. }
  1517. else
  1518. {
  1519. this.each(function()
  1520. {
  1521. $.data(this, 'modal', {});
  1522. $.data(this, 'modal', Modal(this, options));
  1523. });
  1524. }
  1525. if (val.length === 0) return this;
  1526. else if (val.length === 1) return val[0];
  1527. else return val;
  1528. };
  1529. // Initialization
  1530. function Modal(el, options)
  1531. {
  1532. return new Modal.prototype.init(el, options);
  1533. }
  1534. $.Modal = Modal;
  1535. $.Modal.NAME = 'modal';
  1536. $.Modal.VERSION = '1.0';
  1537. $.Modal.opts = {
  1538. title: '',
  1539. width: 500,
  1540. blur: false
  1541. };
  1542. // Functionality
  1543. Modal.fn = $.Modal.prototype = {
  1544. // Initialization
  1545. init: function(el, options)
  1546. {
  1547. this.$element = el !== false ? $(el) : false;
  1548. this.loadOptions(options);
  1549. this.$element.on('click.tools.modal', $.proxy(this.load, this));
  1550. },
  1551. loadOptions: function(options)
  1552. {
  1553. this.opts = $.extend(
  1554. {},
  1555. $.extend(true, {}, $.Modal.opts),
  1556. this.$element.data(),
  1557. options
  1558. );
  1559. },
  1560. setCallback: function(type, e, data)
  1561. {
  1562. var events = $._data(this.$element[0], 'events');
  1563. if (events && typeof events[type] != 'undefined')
  1564. {
  1565. var value = [];
  1566. var len = events[type].length;
  1567. for (var i = 0; i < len; i++)
  1568. {
  1569. var namespace = events[type][i].namespace;
  1570. if (namespace == 'tools.' + $.Modal.NAME || namespace == $.Modal.NAME + '.tools')
  1571. {
  1572. var callback = events[type][i].handler;
  1573. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  1574. }
  1575. }
  1576. if (value.length == 1) return value[0];
  1577. else return value;
  1578. }
  1579. return (typeof data == 'undefined') ? e : data;
  1580. },
  1581. load: function()
  1582. {
  1583. this.build();
  1584. this.enableEvents();
  1585. this.setTitle();
  1586. this.setDraggable();
  1587. this.setContent();
  1588. },
  1589. build: function()
  1590. {
  1591. this.buildOverlay();
  1592. this.$modalBox = $('<div class="modal-box" />').hide();
  1593. this.$modal = $('<div class="modal" />');
  1594. this.$modalHeader = $('<header />');
  1595. this.$modalClose = $('<span class="modal-close" />').html('&times;');
  1596. this.$modalBody = $('<section />');
  1597. this.$modalFooter = $('<footer />');
  1598. this.$modal.append(this.$modalHeader);
  1599. this.$modal.append(this.$modalClose);
  1600. this.$modal.append(this.$modalBody);
  1601. this.$modal.append(this.$modalFooter);
  1602. this.$modalBox.append(this.$modal);
  1603. this.$modalBox.appendTo(document.body);
  1604. },
  1605. buildOverlay: function()
  1606. {
  1607. this.$modalOverlay = $('<div id="modal-overlay">').hide();
  1608. $('body').prepend(this.$modalOverlay);
  1609. if (this.opts.blur)
  1610. {
  1611. this.blurredElements = $('body').children('div, section, header, article, pre, aside, table').not('.modal, .modal-box, #modal-overlay');
  1612. this.blurredElements.addClass('modal-blur');
  1613. }
  1614. },
  1615. show: function()
  1616. {
  1617. // modal loading callback
  1618. this.setCallback('loading', this.$modal);
  1619. this.bodyOveflow = $(document.body).css('overflow');
  1620. $(document.body).css('overflow', 'hidden');
  1621. if (this.isMobile())
  1622. {
  1623. this.showOnMobile();
  1624. }
  1625. else
  1626. {
  1627. this.showOnDesktop();
  1628. }
  1629. this.$modalOverlay.show();
  1630. this.$modalBox.show();
  1631. this.setButtonsWidth();
  1632. // resize
  1633. if (!this.isMobile())
  1634. {
  1635. setTimeout($.proxy(this.showOnDesktop, this), 0);
  1636. $(window).on('resize.tools.modal', $.proxy(this.resize, this));
  1637. }
  1638. // modal shown callback
  1639. this.setCallback('opened', this.$modal);
  1640. // fix bootstrap modal focus
  1641. $(document).off('focusin.modal');
  1642. },
  1643. showOnDesktop: function()
  1644. {
  1645. var height = this.$modal.outerHeight();
  1646. var windowHeight = $(window).height();
  1647. var windowWidth = $(window).width();
  1648. if (this.opts.width > windowWidth)
  1649. {
  1650. this.$modal.css({
  1651. width: '96%',
  1652. marginTop: (windowHeight/2 - height/2) + 'px'
  1653. });
  1654. return;
  1655. }
  1656. if (height > windowHeight)
  1657. {
  1658. this.$modal.css({
  1659. width: this.opts.width + 'px',
  1660. marginTop: '20px'
  1661. });
  1662. }
  1663. else
  1664. {
  1665. this.$modal.css({
  1666. width: this.opts.width + 'px',
  1667. marginTop: (windowHeight/2 - height/2) + 'px'
  1668. });
  1669. }
  1670. },
  1671. showOnMobile: function()
  1672. {
  1673. this.$modal.css({
  1674. width: '96%',
  1675. marginTop: '2%'
  1676. });
  1677. },
  1678. resize: function()
  1679. {
  1680. if (this.isMobile())
  1681. {
  1682. this.showOnMobile();
  1683. }
  1684. else
  1685. {
  1686. this.showOnDesktop();
  1687. }
  1688. },
  1689. setTitle: function()
  1690. {
  1691. this.$modalHeader.html(this.opts.title);
  1692. },
  1693. setContent: function()
  1694. {
  1695. if (typeof this.opts.content == 'object' || this.opts.content.search('#') === 0)
  1696. {
  1697. this.type = 'html';
  1698. this.$modalBody.html($(this.opts.content).html());
  1699. this.show();
  1700. }
  1701. else
  1702. {
  1703. $.ajax({
  1704. url: this.opts.content,
  1705. cache: false,
  1706. success: $.proxy(function(data)
  1707. {
  1708. this.$modalBody.html(data);
  1709. this.show();
  1710. }, this)
  1711. });
  1712. }
  1713. },
  1714. setDraggable: function()
  1715. {
  1716. if (typeof $.fn.draggable === 'undefined') return;
  1717. this.$modal.draggable({ handle: this.$modalHeader });
  1718. this.$modalHeader.css('cursor', 'move');
  1719. },
  1720. createCancelButton: function(label)
  1721. {
  1722. if (typeof label == 'undefined') label = 'Cancel';
  1723. var button = $('<button>').addClass('btn modal-close-btn').html(label);
  1724. button.on('click', $.proxy(this.close, this));
  1725. this.$modalFooter.append(button);
  1726. },
  1727. createDeleteButton: function(label)
  1728. {
  1729. if (typeof label == 'undefined') label = 'Delete';
  1730. return this.createButton(label, 'red');
  1731. },
  1732. createActionButton: function(label)
  1733. {
  1734. if (typeof label == 'undefined') label = 'Ok';
  1735. return this.createButton(label, 'blue');
  1736. },
  1737. createButton: function(label, className)
  1738. {
  1739. var button = $('<button>').addClass('btn').addClass('btn-' + className).html(label);
  1740. this.$modalFooter.append(button);
  1741. return button;
  1742. },
  1743. setButtonsWidth: function()
  1744. {
  1745. var buttons = this.$modalFooter.find('button');
  1746. var buttonsSize = buttons.size();
  1747. if (buttonsSize === 0) return;
  1748. buttons.css('width', (100/buttonsSize) + '%');
  1749. },
  1750. enableEvents: function()
  1751. {
  1752. this.$modalClose.on('click.tools.modal', $.proxy(this.close, this));
  1753. $(document).on('keyup.tools.modal', $.proxy(this.closeHandler, this));
  1754. this.$modalBox.on('click.tools.modal', $.proxy(this.close, this));
  1755. },
  1756. disableEvents: function()
  1757. {
  1758. this.$modalClose.off('click.tools.modal');
  1759. $(document).off('keyup.tools.modal');
  1760. this.$modalBox.off('click.tools.modal');
  1761. $(window).off('resize.tools.modal');
  1762. },
  1763. closeHandler: function(e)
  1764. {
  1765. if (e.which != 27) return;
  1766. this.close();
  1767. },
  1768. close: function(e)
  1769. {
  1770. if (e)
  1771. {
  1772. if (!$(e.target).hasClass('modal-close-btn') && e.target != this.$modalClose[0] && e.target != this.$modalBox[0])
  1773. {
  1774. return;
  1775. }
  1776. e.preventDefault();
  1777. }
  1778. if (!this.$modalBox) return;
  1779. this.disableEvents();
  1780. this.$modalOverlay.remove();
  1781. this.$modalBox.fadeOut('fast', $.proxy(function()
  1782. {
  1783. this.$modalBox.remove();
  1784. $(document.body).css('overflow', this.bodyOveflow);
  1785. // remove blur
  1786. if (this.opts.blur && typeof this.blurredElements != 'undefined')
  1787. {
  1788. this.blurredElements.removeClass('modal-blur');
  1789. }
  1790. this.setCallback('closed');
  1791. }, this));
  1792. },
  1793. isMobile: function()
  1794. {
  1795. var mq = window.matchMedia("(max-width: 767px)");
  1796. return (mq.matches) ? true : false;
  1797. }
  1798. };
  1799. $(window).on('load.tools.modal', function()
  1800. {
  1801. $('[data-tools="modal"]').modal();
  1802. });
  1803. // constructor
  1804. Modal.prototype.init.prototype = Modal.prototype;
  1805. })(jQuery);
  1806. /*
  1807. Navigation Fixed Tool
  1808. http://imperavi.com/kube/
  1809. Copyright (c) 2009-2014, Imperavi LLC.
  1810. */
  1811. (function($)
  1812. {
  1813. // Plugin
  1814. $.fn.navigationFixed = function(options)
  1815. {
  1816. return this.each(function()
  1817. {
  1818. $.data(this, 'navigationFixed', {});
  1819. $.data(this, 'navigationFixed', NavigationFixed(this, options));
  1820. });
  1821. };
  1822. // Initialization
  1823. function NavigationFixed(el, options)
  1824. {
  1825. return new NavigationFixed.prototype.init(el, options);
  1826. }
  1827. $.NavigationFixed = NavigationFixed;
  1828. $.NavigationFixed.NAME = 'navigation-fixed';
  1829. $.NavigationFixed.VERSION = '1.0';
  1830. $.NavigationFixed.opts = {
  1831. // settings
  1832. };
  1833. // Functionality
  1834. NavigationFixed.fn = $.NavigationFixed.prototype = {
  1835. // Initialization
  1836. init: function(el, options)
  1837. {
  1838. var mq = window.matchMedia("(max-width: 767px)");
  1839. if (mq.matches) return;
  1840. this.$element = el !== false ? $(el) : false;
  1841. this.loadOptions(options);
  1842. this.navBoxOffsetTop = this.$element.offset().top;
  1843. this.build();
  1844. $(window).scroll($.proxy(this.build, this));
  1845. },
  1846. loadOptions: function(options)
  1847. {
  1848. this.opts = $.extend(
  1849. {},
  1850. $.extend(true, {}, $.NavigationFixed.opts),
  1851. this.$element.data(),
  1852. options
  1853. );
  1854. },
  1855. setCallback: function(type, e, data)
  1856. {
  1857. var events = $._data(this.$element[0], 'events');
  1858. if (events && typeof events[type] != 'undefined')
  1859. {
  1860. var value = [];
  1861. var len = events[type].length;
  1862. for (var i = 0; i < len; i++)
  1863. {
  1864. var namespace = events[type][i].namespace;
  1865. if (namespace == 'tools.' + $.NavigationFixed.NAME || namespace == $.NavigationFixed.NAME + '.tools')
  1866. {
  1867. var callback = events[type][i].handler;
  1868. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  1869. }
  1870. }
  1871. if (value.length == 1) return value[0];
  1872. else return value;
  1873. }
  1874. return (typeof data == 'undefined') ? e : data;
  1875. },
  1876. build: function()
  1877. {
  1878. if ($(window).scrollTop() > this.navBoxOffsetTop)
  1879. {
  1880. this.$element.addClass('navigation-fixed');
  1881. this.setCallback('fixed');
  1882. }
  1883. else
  1884. {
  1885. this.$element.removeClass('navigation-fixed');
  1886. this.setCallback('unfixed');
  1887. }
  1888. }
  1889. };
  1890. $(window).on('load.tools.navigation-fixed', function()
  1891. {
  1892. $('[data-tools="navigation-fixed"]').navigationFixed();
  1893. });
  1894. // constructor
  1895. NavigationFixed.prototype.init.prototype = NavigationFixed.prototype;
  1896. })(jQuery);
  1897. /*
  1898. Navigation Toggle Tool
  1899. http://imperavi.com/kube/
  1900. Copyright (c) 2009-2014, Imperavi LLC.
  1901. */
  1902. (function($)
  1903. {
  1904. // Plugin
  1905. $.fn.navigationToggle = function(options)
  1906. {
  1907. return this.each(function()
  1908. {
  1909. $.data(this, 'navigationToggle', {});
  1910. $.data(this, 'navigationToggle', NavigationToggle(this, options));
  1911. });
  1912. };
  1913. // Initialization
  1914. function NavigationToggle(el, options)
  1915. {
  1916. return new NavigationToggle.prototype.init(el, options);
  1917. }
  1918. $.NavigationToggle = NavigationToggle;
  1919. $.NavigationToggle.NAME = 'navigation-toggle';
  1920. $.NavigationToggle.VERSION = '1.0';
  1921. $.NavigationToggle.opts = {
  1922. target: false
  1923. };
  1924. // Functionality
  1925. NavigationToggle.fn = $.NavigationToggle.prototype = {
  1926. // Initialization
  1927. init: function(el, options)
  1928. {
  1929. this.$element = el !== false ? $(el) : false;
  1930. this.loadOptions(options);
  1931. this.$target = $(this.opts.target);
  1932. this.$toggle = this.$element.find('span');
  1933. this.$toggle.on('click', $.proxy(this.onClick, this));
  1934. this.build();
  1935. $(window).resize($.proxy(this.build, this));
  1936. },
  1937. loadOptions: function(options)
  1938. {
  1939. this.opts = $.extend(
  1940. {},
  1941. $.extend(true, {}, $.NavigationToggle.opts),
  1942. this.$element.data(),
  1943. options
  1944. );
  1945. },
  1946. setCallback: function(type, e, data)
  1947. {
  1948. var events = $._data(this.$element[0], 'events');
  1949. if (events && typeof events[type] != 'undefined')
  1950. {
  1951. var value = [];
  1952. var len = events[type].length;
  1953. for (var i = 0; i < len; i++)
  1954. {
  1955. var namespace = events[type][i].namespace;
  1956. if (namespace == 'tools.' + $.NavigationToggle.NAME || namespace == $.NavigationToggle.NAME + '.tools')
  1957. {
  1958. var callback = events[type][i].handler;
  1959. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  1960. }
  1961. }
  1962. if (value.length == 1) return value[0];
  1963. else return value;
  1964. }
  1965. return (typeof data == 'undefined') ? e : data;
  1966. },
  1967. build: function()
  1968. {
  1969. var mq = window.matchMedia("(max-width: 767px)");
  1970. if (mq.matches)
  1971. {
  1972. // hide
  1973. if (!this.$target.hasClass('navigation-target-show'))
  1974. {
  1975. this.$element.addClass('navigation-toggle-show').show();
  1976. this.$target.addClass('navigation-target-show').hide();
  1977. }
  1978. }
  1979. else
  1980. {
  1981. // show
  1982. this.$element.removeClass('navigation-toggle-show').hide();
  1983. this.$target.removeClass('navigation-target-show').show();
  1984. }
  1985. },
  1986. onClick: function(e)
  1987. {
  1988. e.stopPropagation();
  1989. e.preventDefault();
  1990. if (this.isTargetHide())
  1991. {
  1992. this.$element.addClass('navigation-toggle-show');
  1993. this.$target.show();
  1994. this.setCallback('show', this.$target);
  1995. }
  1996. else
  1997. {
  1998. this.$element.removeClass('navigation-toggle-show');
  1999. this.$target.hide();
  2000. this.setCallback('hide', this.$target);
  2001. }
  2002. },
  2003. isTargetHide: function()
  2004. {
  2005. return (this.$target[0].style.display == 'none') ? true : false;
  2006. }
  2007. };
  2008. $(window).on('load.tools.navigation-toggle', function()
  2009. {
  2010. $('[data-tools="navigation-toggle"]').navigationToggle();
  2011. });
  2012. // constructor
  2013. NavigationToggle.prototype.init.prototype = NavigationToggle.prototype;
  2014. })(jQuery);
  2015. /*
  2016. Progress Tool
  2017. http://imperavi.com/kube/
  2018. Copyright (c) 2009-2014, Imperavi LLC.
  2019. */
  2020. (function($)
  2021. {
  2022. $.progress = {
  2023. show: function()
  2024. {
  2025. if ($('#tools-progress').length !== 0)
  2026. {
  2027. $('#tools-progress').fadeIn();
  2028. }
  2029. else
  2030. {
  2031. var $progress = $('<div id="tools-progress"><span></span></div>').hide();
  2032. $(document.body).append($progress);
  2033. $('#tools-progress').fadeIn();
  2034. }
  2035. },
  2036. update: function(value)
  2037. {
  2038. this.show();
  2039. $('#tools-progress').find('span').css('width', value + '%');
  2040. },
  2041. hide: function()
  2042. {
  2043. $('#tools-progress').fadeOut(1500);
  2044. }
  2045. };
  2046. })(jQuery);
  2047. /*
  2048. Tabs Tool
  2049. http://imperavi.com/kube/
  2050. Copyright (c) 2009-2014, Imperavi LLC.
  2051. */
  2052. (function($)
  2053. {
  2054. // Plugin
  2055. $.fn.tabs = function(options)
  2056. {
  2057. var val = [];
  2058. var args = Array.prototype.slice.call(arguments, 1);
  2059. if (typeof options === 'string')
  2060. {
  2061. this.each(function()
  2062. {
  2063. var instance = $.data(this, 'tabs');
  2064. if (typeof instance !== 'undefined' && $.isFunction(instance[options]))
  2065. {
  2066. var methodVal = instance[options].apply(instance, args);
  2067. if (methodVal !== undefined && methodVal !== instance) val.push(methodVal);
  2068. }
  2069. else return $.error('No such method "' + options + '" for Tabs');
  2070. });
  2071. }
  2072. else
  2073. {
  2074. this.each(function()
  2075. {
  2076. $.data(this, 'tabs', {});
  2077. $.data(this, 'tabs', Tabs(this, options));
  2078. });
  2079. }
  2080. if (val.length === 0) return this;
  2081. else if (val.length === 1) return val[0];
  2082. else return val;
  2083. };
  2084. // Initialization
  2085. function Tabs(el, options)
  2086. {
  2087. return new Tabs.prototype.init(el, options);
  2088. }
  2089. $.Tabs = Tabs;
  2090. $.Tabs.NAME = 'tabs';
  2091. $.Tabs.VERSION = '1.0';
  2092. $.Tabs.opts = {
  2093. equals: false,
  2094. active: false
  2095. };
  2096. // Functionality
  2097. Tabs.fn = $.Tabs.prototype = {
  2098. // Initialization
  2099. init: function(el, options)
  2100. {
  2101. this.$element = el !== false ? $(el) : false;
  2102. this.loadOptions(options);
  2103. this.links = this.$element.find('a');
  2104. this.tabs = [];
  2105. this.links.each($.proxy(this.load, this));
  2106. this.setEquals();
  2107. this.setCallback('init');
  2108. },
  2109. loadOptions: function(options)
  2110. {
  2111. this.opts = $.extend(
  2112. {},
  2113. $.extend(true, {}, $.Tabs.opts),
  2114. this.$element.data(),
  2115. options
  2116. );
  2117. },
  2118. setCallback: function(type, e, data)
  2119. {
  2120. var events = $._data(this.$element[0], 'events');
  2121. if (events && typeof events[type] != 'undefined')
  2122. {
  2123. var value = [];
  2124. var len = events[type].length;
  2125. for (var i = 0; i < len; i++)
  2126. {
  2127. var namespace = events[type][i].namespace;
  2128. if (namespace == 'tools.' + $.Tabs.NAME || namespace == $.Tabs.NAME + '.tools')
  2129. {
  2130. var callback = events[type][i].handler;
  2131. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  2132. }
  2133. }
  2134. if (value.length == 1) return value[0];
  2135. else return value;
  2136. }
  2137. return (typeof data == 'undefined') ? e : data;
  2138. },
  2139. load: function(i, el)
  2140. {
  2141. var $el = $(el);
  2142. var hash = $el.attr('href');
  2143. $el.attr('rel', hash);
  2144. this.tabs.push($(hash));
  2145. if (!$el.parent().hasClass('active'))
  2146. {
  2147. $(hash).hide();
  2148. }
  2149. // is hash in url
  2150. this.readLocationHash(hash);
  2151. // is active
  2152. if (this.opts.active !== false && this.opts.active === hash)
  2153. {
  2154. this.show(hash);
  2155. }
  2156. $el.on('click', $.proxy(this.onClick, this));
  2157. },
  2158. onClick: function(e)
  2159. {
  2160. e.preventDefault();
  2161. var hash = $(e.target).attr('rel');
  2162. top.location.hash = hash;
  2163. this.show(hash);
  2164. },
  2165. readLocationHash: function(hash)
  2166. {
  2167. if (top.location.hash === '' || top.location.hash != hash) return;
  2168. this.opts.active = top.location.hash;
  2169. },
  2170. setActive: function(hash)
  2171. {
  2172. this.activeHash = hash;
  2173. this.activeTab = $('[rel=' + hash + ']');
  2174. this.links.parent().removeClass('active');
  2175. this.activeTab.parent().addClass('active');
  2176. },
  2177. getActiveHash: function()
  2178. {
  2179. return this.activeHash;
  2180. },
  2181. getActiveTab: function()
  2182. {
  2183. return this.activeTab;
  2184. },
  2185. show: function(hash)
  2186. {
  2187. this.hideAll();
  2188. $(hash).show();
  2189. this.setActive(hash);
  2190. this.setCallback('show', $('[rel=' + hash + ']'), hash);
  2191. },
  2192. hideAll: function()
  2193. {
  2194. $.each(this.tabs, function()
  2195. {
  2196. $(this).hide();
  2197. });
  2198. },
  2199. setEquals: function()
  2200. {
  2201. if (!this.opts.equals) return;
  2202. this.setMaxHeight(this.getMaxHeight());
  2203. },
  2204. setMaxHeight: function(height)
  2205. {
  2206. $.each(this.tabs, function()
  2207. {
  2208. $(this).css('min-height', height + 'px');
  2209. });
  2210. },
  2211. getMaxHeight: function()
  2212. {
  2213. var max = 0;
  2214. $.each(this.tabs, function()
  2215. {
  2216. var h = $(this).height();
  2217. max = h > max ? h : max;
  2218. });
  2219. return max;
  2220. }
  2221. };
  2222. $(window).on('load.tools.tabs', function()
  2223. {
  2224. $('[data-tools="tabs"]').tabs();
  2225. });
  2226. // constructor
  2227. Tabs.prototype.init.prototype = Tabs.prototype;
  2228. })(jQuery);
  2229. /*
  2230. TextFit Tool
  2231. http://imperavi.com/kube/
  2232. Copyright (c) 2009-2014, Imperavi LLC.
  2233. */
  2234. (function($)
  2235. {
  2236. // Plugin
  2237. $.fn.textfit = function(options)
  2238. {
  2239. return this.each(function()
  2240. {
  2241. $.data(this, 'textfit', {});
  2242. $.data(this, 'textfit', Textfit(this, options));
  2243. });
  2244. };
  2245. // Initialization
  2246. function Textfit(el, options)
  2247. {
  2248. return new Textfit.prototype.init(el, options);
  2249. }
  2250. $.Textfit = Textfit;
  2251. $.Textfit.NAME = 'textfit';
  2252. $.Textfit.VERSION = '1.0';
  2253. $.Textfit.opts = {
  2254. min: '10px',
  2255. max: '100px',
  2256. compressor: 1
  2257. };
  2258. // Functionality
  2259. Textfit.fn = $.Textfit.prototype = {
  2260. // Initialization
  2261. init: function(el, options)
  2262. {
  2263. this.$element = el !== false ? $(el) : false;
  2264. this.loadOptions(options);
  2265. this.$element.css('font-size', Math.max(Math.min(this.$element.width() / (this.opts.compressor*10), parseFloat(this.opts.max)), parseFloat(this.opts.min)));
  2266. },
  2267. loadOptions: function(options)
  2268. {
  2269. this.opts = $.extend(
  2270. {},
  2271. $.extend(true, {}, $.Textfit.opts),
  2272. this.$element.data(),
  2273. options
  2274. );
  2275. }
  2276. };
  2277. $(window).on('load.tools.textfit', function()
  2278. {
  2279. $('[data-tools="textfit"]').textfit();
  2280. });
  2281. // constructor
  2282. Textfit.prototype.init.prototype = Textfit.prototype;
  2283. })(jQuery);
  2284. /*
  2285. Tooltip Tool
  2286. http://imperavi.com/kube/
  2287. Copyright (c) 2009-2014, Imperavi LLC.
  2288. */
  2289. (function($)
  2290. {
  2291. // Plugin
  2292. $.fn.tooltip = function(options)
  2293. {
  2294. return this.each(function()
  2295. {
  2296. $.data(this, 'tooltip', {});
  2297. $.data(this, 'tooltip', Tooltip(this, options));
  2298. });
  2299. };
  2300. // Initialization
  2301. function Tooltip(el, options)
  2302. {
  2303. return new Tooltip.prototype.init(el, options);
  2304. }
  2305. $.Tooltip = Tooltip;
  2306. $.Tooltip.NAME = 'tooltip';
  2307. $.Tooltip.VERSION = '1.0';
  2308. $.Tooltip.opts = {
  2309. theme: false
  2310. };
  2311. // Functionality
  2312. Tooltip.fn = $.Tooltip.prototype = {
  2313. // Initialization
  2314. init: function(el, options)
  2315. {
  2316. this.$element = el !== false ? $(el) : false;
  2317. this.loadOptions(options);
  2318. this.$element.on('mouseover', $.proxy(this.show, this));
  2319. this.$element.on('mouseout', $.proxy(this.hide, this));
  2320. },
  2321. loadOptions: function(options)
  2322. {
  2323. this.opts = $.extend(
  2324. {},
  2325. $.extend(true, {}, $.Tooltip.opts),
  2326. this.$element.data(),
  2327. options
  2328. );
  2329. },
  2330. show: function()
  2331. {
  2332. $('.tooltip').hide();
  2333. var text = this.$element.attr('title');
  2334. this.$element.data('cached-title', text);
  2335. this.$element.attr('title', '');
  2336. this.tooltip = $('<div class="tooltip" />').html(text).hide();
  2337. if (this.opts.theme !== false)
  2338. {
  2339. this.tooltip.addClass('tooltip-theme-' + this.opts.theme);
  2340. }
  2341. this.tooltip.css({
  2342. top: (this.$element.offset().top + this.$element.innerHeight()) + 'px',
  2343. left: this.$element.offset().left + 'px'
  2344. });
  2345. $('body').append(this.tooltip);
  2346. this.tooltip.show();
  2347. },
  2348. hide: function()
  2349. {
  2350. this.tooltip.fadeOut('fast', $.proxy(function()
  2351. {
  2352. this.tooltip.remove();
  2353. }, this));
  2354. this.$element.attr('title', this.$element.data('cached-title'));
  2355. this.$element.data('cached-title', '');
  2356. }
  2357. };
  2358. // Constructor
  2359. Tooltip.prototype.init.prototype = Tooltip.prototype;
  2360. $(function()
  2361. {
  2362. $('[data-tools="tooltip"]').tooltip();
  2363. });
  2364. })(jQuery);
  2365. /*
  2366. Upload Tool
  2367. http://imperavi.com/kube/
  2368. Copyright (c) 2009-2014, Imperavi LLC.
  2369. */
  2370. (function($)
  2371. {
  2372. // Plugin
  2373. $.fn.upload = function(options)
  2374. {
  2375. return this.each(function()
  2376. {
  2377. $.data(this, 'upload', {});
  2378. $.data(this, 'upload', Upload(this, options));
  2379. });
  2380. };
  2381. // Initialization
  2382. function Upload(el, options)
  2383. {
  2384. return new Upload.prototype.init(el, options);
  2385. }
  2386. $.Upload = Upload;
  2387. $.Upload.NAME = 'upload';
  2388. $.Upload.VERSION = '1.0';
  2389. $.Upload.opts = {
  2390. url: false,
  2391. placeholder: 'Drop file here or ',
  2392. param: 'file'
  2393. };
  2394. // Functionality
  2395. Upload.fn = $.Upload.prototype = {
  2396. // Initialization
  2397. init: function(el, options)
  2398. {
  2399. this.$element = el !== false ? $(el) : false;
  2400. this.loadOptions(options);
  2401. this.load();
  2402. },
  2403. loadOptions: function(options)
  2404. {
  2405. this.opts = $.extend(
  2406. {},
  2407. $.extend(true, {}, $.Upload.opts),
  2408. this.$element.data(),
  2409. options
  2410. );
  2411. },
  2412. setCallback: function(type, e, data)
  2413. {
  2414. var events = $._data(this.$element[0], 'events');
  2415. if (events && typeof events[type] != 'undefined')
  2416. {
  2417. var value = [];
  2418. var len = events[type].length;
  2419. for (var i = 0; i < len; i++)
  2420. {
  2421. var namespace = events[type][i].namespace;
  2422. if (namespace == 'tools.' + $.Upload.NAME || namespace == $.Upload.NAME + '.tools')
  2423. {
  2424. var callback = events[type][i].handler;
  2425. value.push((typeof data == 'undefined') ? callback.call(this, e) : callback.call(this, e, data));
  2426. }
  2427. }
  2428. if (value.length == 1) return value[0];
  2429. else return value;
  2430. }
  2431. return (typeof data == 'undefined') ? e : data;
  2432. },
  2433. load: function()
  2434. {
  2435. this.$droparea = $('<div class="tools-droparea" />');
  2436. this.$placeholdler = $('<div class="tools-droparea-placeholder" />').text(this.opts.placeholder);
  2437. this.$droparea.append(this.$placeholdler);
  2438. this.$element.after(this.$droparea);
  2439. this.$placeholdler.append(this.$element);
  2440. this.$droparea.off('.tools.upload');
  2441. this.$element.off('.tools.upload');
  2442. this.$droparea.on('dragover.tools.upload', $.proxy(this.onDrag, this));
  2443. this.$droparea.on('dragleave.tools.upload', $.proxy(this.onDragLeave, this));
  2444. // change
  2445. this.$element.on('change.tools.upload', $.proxy(function(e)
  2446. {
  2447. e = e.originalEvent || e;
  2448. this.traverseFile(this.$element[0].files[0], e);
  2449. }, this));
  2450. // drop
  2451. this.$droparea.on('drop.tools.upload', $.proxy(function(e)
  2452. {
  2453. e.preventDefault();
  2454. this.$droparea.removeClass('drag-hover').addClass('drag-drop');
  2455. this.onDrop(e);
  2456. }, this));
  2457. },
  2458. onDrop: function(e)
  2459. {
  2460. e = e.originalEvent || e;
  2461. var files = e.dataTransfer.files;
  2462. this.traverseFile(files[0], e);
  2463. },
  2464. traverseFile: function(file, e)
  2465. {
  2466. var formData = !!window.FormData ? new FormData() : null;
  2467. if (window.FormData)
  2468. {
  2469. formData.append(this.opts.param, file);
  2470. }
  2471. if ($.progress) $.progress.show();
  2472. this.sendData(formData, e);
  2473. },
  2474. sendData: function(formData, e)
  2475. {
  2476. var xhr = new XMLHttpRequest();
  2477. xhr.open('POST', this.opts.url);
  2478. // complete
  2479. xhr.onreadystatechange = $.proxy(function()
  2480. {
  2481. if (xhr.readyState == 4)
  2482. {
  2483. var data = xhr.responseText;
  2484. data = data.replace(/^\[/, '');
  2485. data = data.replace(/\]$/, '');
  2486. var json = (typeof data === 'string' ? $.parseJSON(data) : data);
  2487. if ($.progress) $.progress.hide();
  2488. this.$droparea.removeClass('drag-drop');
  2489. this.setCallback('success', json);
  2490. }
  2491. }, this);
  2492. xhr.send(formData);
  2493. },
  2494. onDrag: function(e)
  2495. {
  2496. e.preventDefault();
  2497. this.$droparea.addClass('drag-hover');
  2498. },
  2499. onDragLeave: function(e)
  2500. {
  2501. e.preventDefault();
  2502. this.$droparea.removeClass('drag-hover');
  2503. }
  2504. };
  2505. // Constructor
  2506. Upload.prototype.init.prototype = Upload.prototype;
  2507. $(function()
  2508. {
  2509. $('[data-tools="upload"]').upload();
  2510. });
  2511. })(jQuery);