jquery.popover-1.1.2.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. /**
  2. * jQuery.popover plugin v1.1.2
  3. * By Davey IJzermans
  4. * See http://wp.me/p12l3P-gT for details
  5. * http://daveyyzermans.nl/
  6. *
  7. * Released under MIT License.
  8. */
  9. ;(function($) {
  10. //define some default plugin options
  11. var defaults = {
  12. verticalOffset: 10, //offset the popover by y px vertically (movement depends on position of popover. If position == 'bottom', positive numbers are down)
  13. horizontalOffset: 10, //offset the popover by x px horizontally (movement depends on position of popover. If position == 'right', positive numbers are right)
  14. title: false, //heading, false for none
  15. content: false, //content of the popover
  16. url: false, //set to an url to load content via ajax
  17. classes: '', //classes to give the popover, i.e. normal, wider or large
  18. position: 'auto', //where should the popover be placed? Auto, top, right, bottom, left or absolute (i.e. { top: 4 }, { left: 4 })
  19. fadeSpeed: 160, //how fast to fade out popovers when destroying or hiding
  20. trigger: 'click', //how to trigger the popover: click, hover or manual
  21. preventDefault: true, //preventDefault actions on the element on which the popover is called
  22. stopChildrenPropagation: true, //prevent propagation on popover children
  23. hideOnHTMLClick: true, //hides the popover when clicked outside of it
  24. animateChange: true, //animate a popover reposition
  25. autoReposition: true, //automatically reposition popover on popover change and window resize
  26. anchor: false //anchor the popover to a different element
  27. }
  28. var popovers = [];
  29. var _ = {
  30. calc_position: function(popover, position) {
  31. var data = popover.popover("getData");
  32. var options = data.options;
  33. var $anchor = options.anchor ? $(options.anchor) : popover;
  34. var el = data.popover;
  35. var coordinates = $anchor.offset();
  36. var y1, x1;
  37. if (position == 'top') {
  38. y1 = coordinates.top - el.outerHeight();
  39. x1 = coordinates.left - el.outerWidth() / 2 + $anchor.outerWidth() / 2;
  40. } else if (position == 'right') {
  41. y1 = coordinates.top + $anchor.outerHeight() / 2 - el.outerHeight() / 2;
  42. x1 = coordinates.left + $anchor.outerWidth();
  43. } else if (position == 'left') {
  44. y1 = coordinates.top + $anchor.outerHeight() / 2 - el.outerHeight() / 2;
  45. x1 = coordinates.left - el.outerWidth();
  46. } else {
  47. //bottom
  48. y1 = coordinates.top + $anchor.outerHeight();
  49. x1 = coordinates.left - el.outerWidth() / 2 + $anchor.outerWidth() / 2;
  50. }
  51. x2 = x1 + el.outerWidth();
  52. y2 = y1 + el.outerHeight();
  53. ret = {
  54. x1: x1,
  55. x2: x2,
  56. y1: y1,
  57. y2: y2
  58. };
  59. return ret;
  60. },
  61. pop_position_class: function(popover, position) {
  62. var remove = "popover-top popover-right popover-left";
  63. var arrow = "top-arrow"
  64. var arrow_remove = "right-arrow bottom-arrow left-arrow";
  65. if (position == 'top') {
  66. remove = "popover-right popover-bottom popover-left";
  67. arrow = 'bottom-arrow';
  68. arrow_remove = "top-arrow right-arrow left-arrow";
  69. } else if (position == 'right') {
  70. remove = "popover-yop popover-bottom popover-left";
  71. arrow = 'left-arrow';
  72. arrow_remove = "top-arrow right-arrow bottom-arrow";
  73. } else if (position == 'left') {
  74. remove = "popover-top popover-right popover-bottom";
  75. arrow = 'right-arrow';
  76. arrow_remove = "top-arrow bottom-arrow left-arrow";
  77. }
  78. popover
  79. .removeClass(remove)
  80. .addClass('popover-' + position)
  81. .find('.arrow')
  82. .removeClass(arrow_remove)
  83. .addClass(arrow);
  84. }
  85. };
  86. var methods = {
  87. /**
  88. * Initialization method
  89. * Merges parameters with defaults, makes the popover and saves data
  90. *
  91. * @param object
  92. * @return jQuery
  93. */
  94. init : function(params) {
  95. return this.each(function() {
  96. var options = $.extend({}, defaults, params);
  97. var $this = $(this);
  98. var data = $this.popover('getData');
  99. if ( ! data) {
  100. var popover = $('<div class="popover" />')
  101. .addClass(options.classes)
  102. .append('<div class="arrow" />')
  103. .append('<div class="wrap"></div>')
  104. .appendTo('body')
  105. .hide();
  106. if (options.stopChildrenPropagation) {
  107. popover.children().bind('click.popover', function(event) {
  108. event.stopPropagation();
  109. });
  110. }
  111. if (options.anchor) {
  112. if ( ! options.anchor instanceof jQuery) {
  113. options.anchor = $(options.anchor);
  114. }
  115. }
  116. var data = {
  117. target: $this,
  118. popover: popover,
  119. options: options
  120. };
  121. if (options.title) {
  122. $('<div class="title" />')
  123. .html(options.title instanceof jQuery ? options.title.html() : options.title)
  124. .appendTo(popover.find('.wrap'));
  125. }
  126. if (options.content) {
  127. $('<div class="content" />')
  128. .html(options.content instanceof jQuery ? options.content.html() : options.content)
  129. .appendTo(popover.find('.wrap'));
  130. }
  131. $this.data('popover', data);
  132. popovers.push($this);
  133. if (options.url) {
  134. $this.popover('ajax', options.url);
  135. }
  136. $this.popover('reposition');
  137. $this.popover('setTrigger', options.trigger);
  138. if (options.hideOnHTMLClick) {
  139. var hideEvent = "click.popover";
  140. if ("ontouchstart" in document.documentElement)
  141. hideEvent = 'touchstart.popover';
  142. $('html').unbind(hideEvent).bind(hideEvent, function(event) {
  143. $('html').popover('fadeOutAll');
  144. });
  145. }
  146. if (options.autoReposition) {
  147. var repos_function = function(event) {
  148. $this.popover('reposition');
  149. };
  150. $(window)
  151. .unbind('resize.popover').bind('resize.popover', repos_function)
  152. .unbind('scroll.popover').bind('scroll.popover', repos_function);
  153. }
  154. }
  155. });
  156. },
  157. /**
  158. * Reposition the popover
  159. *
  160. * @return jQuery
  161. */
  162. reposition: function() {
  163. return this.each(function() {
  164. var $this = $(this);
  165. var data = $this.popover('getData');
  166. if (data) {
  167. var popover = data.popover;
  168. var options = data.options;
  169. var $anchor = options.anchor ? $(options.anchor) : $this;
  170. var coordinates = $anchor.offset();
  171. var position = options.position;
  172. if ( ! (position == 'top' || position == 'right' || position == 'left' || position == 'auto')) {
  173. position = 'bottom';
  174. }
  175. var calc;
  176. if (position == 'auto') {
  177. var positions = ["bottom", "left", "top", "right"];
  178. var scrollTop = $(window).scrollTop();
  179. var scrollLeft = $(window).scrollLeft();
  180. var windowHeight = $(window).outerHeight();
  181. var windowWidth = $(window).outerWidth();
  182. $.each (positions, function(i, pos) {
  183. calc = _.calc_position($this, pos);
  184. var x1 = calc.x1 - scrollLeft;
  185. var x2 = calc.x2 - scrollLeft + options.horizontalOffset;
  186. var y1 = calc.y1 - scrollTop;
  187. var y2 = calc.y2 - scrollTop + options.verticalOffset;
  188. if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0)
  189. //popover is left off of the screen or above it
  190. return true; //continue
  191. if (y2 > windowHeight)
  192. //popover is under the window viewport
  193. return true; //continue
  194. if (x2 > windowWidth)
  195. //popover is right off of the screen
  196. return true; //continue
  197. position = pos;
  198. return false;
  199. });
  200. if (position == 'auto') {
  201. //position is still auto
  202. return;
  203. }
  204. }
  205. calc = _.calc_position($this, position);
  206. var top = calc.top;
  207. var left = calc.left;
  208. _.pop_position_class(popover, position);
  209. var marginTop = 0;
  210. var marginLeft = 0;
  211. if (position == 'bottom') {
  212. marginTop = options.verticalOffset;
  213. }
  214. if (position == 'top') {
  215. marginTop = -options.verticalOffset;
  216. }
  217. if (position == 'right') {
  218. marginLeft = options.horizontalOffset;
  219. }
  220. if (position == 'left') {
  221. marginLeft = -options.horizontalOffset;
  222. }
  223. var css = {
  224. left: calc.x1,
  225. top: calc.y1,
  226. marginTop: marginTop,
  227. marginLeft: marginLeft
  228. };
  229. if (data.initd && options.animateChange) {
  230. popover.css(css);
  231. } else {
  232. data.initd = true;
  233. popover.css(css);
  234. }
  235. $this.data('popover', data);
  236. }
  237. });
  238. },
  239. /**
  240. * Remove a popover from the DOM and clean up data associated with it.
  241. *
  242. * @return jQuery
  243. */
  244. destroy: function() {
  245. return this.each(function() {
  246. var $this = $(this);
  247. var data = $this.popover('getData');
  248. $this.unbind('.popover');
  249. $(window).unbind('.popover');
  250. data.popover.remove();
  251. $this.removeData('popover');
  252. });
  253. },
  254. /**
  255. * Show the popover
  256. *
  257. * @return jQuery
  258. */
  259. show: function() {
  260. return this.each(function() {
  261. var $this = $(this);
  262. var data = $this.popover('getData');
  263. if (data) {
  264. var popover = data.popover;
  265. $this.popover('reposition');
  266. popover.clearQueue().css({ zIndex: 950 }).show();
  267. }
  268. });
  269. },
  270. /**
  271. * Hide the popover
  272. *
  273. * @return jQuery
  274. */
  275. hide: function() {
  276. return this.each(function() {
  277. var $this = $(this);
  278. var data = $this.popover('getData');
  279. if (data) {
  280. data.popover.hide().css({ zIndex: 949 });
  281. }
  282. });
  283. },
  284. /**
  285. * Fade out the popover
  286. *
  287. * @return jQuery
  288. */
  289. fadeOut: function(ms) {
  290. return this.each(function() {
  291. var $this = $(this);
  292. var data = $this.popover('getData');
  293. if (data) {
  294. var popover = data.popover;
  295. var options = data.options;
  296. popover.delay(100).css({ zIndex: 949 }).fadeOut(ms ? ms : options.fadeSpeed);
  297. }
  298. });
  299. },
  300. /**
  301. * Hide all popovers
  302. *
  303. * @return jQuery
  304. */
  305. hideAll: function() {
  306. return $.each (popovers, function(i, pop) {
  307. var $this = $(this);
  308. var data = $this.popover('getData');
  309. if (data) {
  310. var popover = data.popover;
  311. popover.hide();
  312. }
  313. });
  314. },
  315. /**
  316. * Fade out all popovers
  317. *
  318. * @param int
  319. * @return jQuery
  320. */
  321. fadeOutAll: function(ms) {
  322. return $.each (popovers, function(i, pop) {
  323. var $this = $(this);
  324. var data = $this.popover('getData');
  325. if (data) {
  326. var popover = data.popover;
  327. var options = data.options;
  328. popover.css({ zIndex: 949 }).fadeOut(ms ? ms : options.fadeSpeed);
  329. }
  330. });
  331. },
  332. /**
  333. * Set the event trigger for the popover. Also cleans the previous binding.
  334. *
  335. * @param string
  336. * @return jQuery
  337. */
  338. setTrigger: function(trigger) {
  339. return this.each(function() {
  340. var $this = $(this);
  341. var data = $this.popover('getData');
  342. if (data) {
  343. var popover = data.popover;
  344. var options = data.options;
  345. var $anchor = options.anchor ? $(options.anchor) : $this;
  346. if (trigger === 'click') {
  347. $anchor.unbind('click.popover').bind('click.popover', function(event) {
  348. if (options.preventDefault) {
  349. event.preventDefault();
  350. }
  351. event.stopPropagation();
  352. $this.popover('show');
  353. });
  354. popover.unbind('click.popover').bind('click.popover', function(event) {
  355. event.stopPropagation();
  356. });
  357. } else {
  358. $anchor.unbind('click.popover');
  359. popover.unbind('click.popover')
  360. }
  361. if (trigger === 'hover') {
  362. $anchor.add(popover).bind('mousemove.popover', function(event) {
  363. $this.popover('show');
  364. });
  365. $anchor.add(popover).bind('mouseleave.popover', function(event) {
  366. $this.popover('fadeOut');
  367. });
  368. } else {
  369. $anchor.add(popover).unbind('mousemove.popover').unbind('mouseleave.popover');
  370. }
  371. if (trigger === 'focus') {
  372. $anchor.add(popover).bind('focus.popover', function(event) {
  373. $this.popover('show');
  374. });
  375. $anchor.add(popover).bind('blur.popover', function(event) {
  376. $this.popover('fadeOut');
  377. });
  378. $anchor.bind('click.popover', function(event) {
  379. event.stopPropagation();
  380. });
  381. } else {
  382. $anchor.add(popover).unbind('focus.popover').unbind('blur.popover').unbind('click.popover');
  383. }
  384. }
  385. });
  386. },
  387. /**
  388. * Rename the popover's title
  389. *
  390. * @param string
  391. * @return jQuery
  392. */
  393. title: function(text) {
  394. return this.each(function() {
  395. var $this = $(this);
  396. var data = $this.popover('getData');
  397. if (data) {
  398. var title = data.popover.find('.title');
  399. var wrap = data.popover.find('.wrap');
  400. if (title.length === 0) {
  401. title = $('<div class="title" />').appendTo(wrap);
  402. }
  403. title.html(text);
  404. }
  405. });
  406. },
  407. /**
  408. * Set the popover's content
  409. *
  410. * @param html
  411. * @return jQuery
  412. */
  413. content: function(html) {
  414. return this.each(function() {
  415. var $this = $(this);
  416. var data = $this.popover('getData');
  417. if (data) {
  418. var content = data.popover.find('.content');
  419. var wrap = data.popover.find('.wrap');
  420. if (content.length === 0) {
  421. content = $('<div class="content" />').appendTo(wrap);
  422. }
  423. content.html(html);
  424. }
  425. });
  426. },
  427. /**
  428. * Read content with AJAX and set popover's content.
  429. *
  430. * @param string
  431. * @param object
  432. * @return jQuery
  433. */
  434. ajax: function(url, ajax_params) {
  435. return this.each(function() {
  436. var $this = $(this);
  437. var data = $this.popover('getData');
  438. if (data) {
  439. var ajax_defaults = {
  440. url: url,
  441. success: function(ajax_data) {
  442. var content = data.popover.find('.content');
  443. var wrap = data.popover.find('.wrap');
  444. if (content.length === 0) {
  445. content = $('<div class="content" />').appendTo(wrap);
  446. }
  447. content.html(ajax_data);
  448. }
  449. }
  450. var ajax_options = $.extend({}, ajax_defaults, ajax_params);
  451. $.ajax(ajax_options);
  452. }
  453. });
  454. },
  455. setOption: function(option, value) {
  456. return this.each(function() {
  457. var $this = $(this);
  458. var data = $this.popover('getData');
  459. if (data) {
  460. data.options[option] = value;
  461. $this.data('popover', data);
  462. }
  463. });
  464. },
  465. getData: function() {
  466. var ret = [];
  467. this.each(function() {
  468. var $this = $(this);
  469. var data = $this.data('popover');
  470. if (data) ret.push(data);
  471. });
  472. if (ret.length == 0) {
  473. return;
  474. }
  475. if (ret.length == 1) {
  476. ret = ret[0];
  477. }
  478. return ret;
  479. }
  480. };
  481. $.fn.popover = function(method) {
  482. if (methods[method]) {
  483. return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
  484. } else if ( typeof method === 'object' || !method) {
  485. return methods.init.apply(this, arguments);
  486. } else {
  487. $.error('Method ' + method + ' does not exist on jQuery.popover');
  488. }
  489. }
  490. })(jQuery);