pnotify.nonblock.js 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Nonblock
  2. // Uses AMD or browser globals for jQuery.
  3. (function (factory) {
  4. if (typeof define === 'function' && define.amd) {
  5. // AMD. Register as a module.
  6. define('pnotify.nonblock', ['jquery', 'pnotify'], factory);
  7. } else {
  8. // Browser globals
  9. factory(jQuery, PNotify);
  10. }
  11. }(function($, PNotify){
  12. // Some useful regexes.
  13. var re_on = /^on/,
  14. re_mouse_events = /^(dbl)?click$|^mouse(move|down|up|over|out|enter|leave)$|^contextmenu$/,
  15. re_ui_events = /^(focus|blur|select|change|reset)$|^key(press|down|up)$/,
  16. re_html_events = /^(scroll|resize|(un)?load|abort|error)$/;
  17. // Fire a DOM event.
  18. var dom_event = function(e, orig_e){
  19. var event_object;
  20. e = e.toLowerCase();
  21. if (document.createEvent && this.dispatchEvent) {
  22. // FireFox, Opera, Safari, Chrome
  23. e = e.replace(re_on, '');
  24. if (e.match(re_mouse_events)) {
  25. // This allows the click event to fire on the notice. There is
  26. // probably a much better way to do it.
  27. $(this).offset();
  28. event_object = document.createEvent("MouseEvents");
  29. event_object.initMouseEvent(
  30. e, orig_e.bubbles, orig_e.cancelable, orig_e.view, orig_e.detail,
  31. orig_e.screenX, orig_e.screenY, orig_e.clientX, orig_e.clientY,
  32. orig_e.ctrlKey, orig_e.altKey, orig_e.shiftKey, orig_e.metaKey, orig_e.button, orig_e.relatedTarget
  33. );
  34. } else if (e.match(re_ui_events)) {
  35. event_object = document.createEvent("UIEvents");
  36. event_object.initUIEvent(e, orig_e.bubbles, orig_e.cancelable, orig_e.view, orig_e.detail);
  37. } else if (e.match(re_html_events)) {
  38. event_object = document.createEvent("HTMLEvents");
  39. event_object.initEvent(e, orig_e.bubbles, orig_e.cancelable);
  40. }
  41. if (!event_object) return;
  42. this.dispatchEvent(event_object);
  43. } else {
  44. // Internet Explorer
  45. if (!e.match(re_on)) e = "on"+e;
  46. event_object = document.createEventObject(orig_e);
  47. this.fireEvent(e, event_object);
  48. }
  49. };
  50. // This keeps track of the last element the mouse was over, so
  51. // mouseleave, mouseenter, etc can be called.
  52. var nonblock_last_elem;
  53. // This is used to pass events through the notice if it is non-blocking.
  54. var nonblock_pass = function(notice, e, e_name){
  55. notice.elem.css("display", "none");
  56. var element_below = document.elementFromPoint(e.clientX, e.clientY);
  57. notice.elem.css("display", "block");
  58. var jelement_below = $(element_below);
  59. var cursor_style = jelement_below.css("cursor");
  60. notice.elem.css("cursor", cursor_style !== "auto" ? cursor_style : "default");
  61. // If the element changed, call mouseenter, mouseleave, etc.
  62. if (!nonblock_last_elem || nonblock_last_elem.get(0) != element_below) {
  63. if (nonblock_last_elem) {
  64. dom_event.call(nonblock_last_elem.get(0), "mouseleave", e.originalEvent);
  65. dom_event.call(nonblock_last_elem.get(0), "mouseout", e.originalEvent);
  66. }
  67. dom_event.call(element_below, "mouseenter", e.originalEvent);
  68. dom_event.call(element_below, "mouseover", e.originalEvent);
  69. }
  70. dom_event.call(element_below, e_name, e.originalEvent);
  71. // Remember the latest element the mouse was over.
  72. nonblock_last_elem = jelement_below;
  73. };
  74. PNotify.prototype.options.nonblock = {
  75. // Create a non-blocking notice. It lets the user click elements underneath it.
  76. nonblock: false,
  77. // The opacity of the notice (if it's non-blocking) when the mouse is over it.
  78. nonblock_opacity: .2
  79. };
  80. PNotify.prototype.modules.nonblock = {
  81. // This lets us update the options available in the closures.
  82. myOptions: null,
  83. init: function(notice, options){
  84. var that = this;
  85. this.myOptions = options;
  86. notice.elem.on({
  87. "mouseenter": function(e){
  88. if (that.myOptions.nonblock) e.stopPropagation();
  89. if (that.myOptions.nonblock) {
  90. // If it's non-blocking, animate to the other opacity.
  91. notice.elem.stop().animate({"opacity": that.myOptions.nonblock_opacity}, "fast");
  92. }
  93. },
  94. "mouseleave": function(e){
  95. if (that.myOptions.nonblock) e.stopPropagation();
  96. nonblock_last_elem = null;
  97. notice.elem.css("cursor", "auto");
  98. // Animate back to the normal opacity.
  99. if (that.myOptions.nonblock && notice.animating !== "out")
  100. notice.elem.stop().animate({"opacity": notice.options.opacity}, "fast");
  101. },
  102. "mouseover": function(e){
  103. if (that.myOptions.nonblock) e.stopPropagation();
  104. },
  105. "mouseout": function(e){
  106. if (that.myOptions.nonblock) e.stopPropagation();
  107. },
  108. "mousemove": function(e){
  109. if (that.myOptions.nonblock) {
  110. e.stopPropagation();
  111. nonblock_pass(notice, e, "onmousemove");
  112. }
  113. },
  114. "mousedown": function(e){
  115. if (that.myOptions.nonblock) {
  116. e.stopPropagation();
  117. e.preventDefault();
  118. nonblock_pass(notice, e, "onmousedown");
  119. }
  120. },
  121. "mouseup": function(e){
  122. if (that.myOptions.nonblock) {
  123. e.stopPropagation();
  124. e.preventDefault();
  125. nonblock_pass(notice, e, "onmouseup");
  126. }
  127. },
  128. "click": function(e){
  129. if (that.myOptions.nonblock) {
  130. e.stopPropagation();
  131. nonblock_pass(notice, e, "onclick");
  132. }
  133. },
  134. "dblclick": function(e){
  135. if (that.myOptions.nonblock) {
  136. e.stopPropagation();
  137. nonblock_pass(notice, e, "ondblclick");
  138. }
  139. }
  140. });
  141. },
  142. update: function(notice, options){
  143. this.myOptions = options;
  144. }
  145. };
  146. }));