jquery.layerModel.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. * jQuery layerModel V1.0.0
  3. * Dual licensed under the MIT and GPL licenses.
  4. *
  5. * Copyright (c) 2014 (http://zk.citier.net/layerModel.html)
  6. *
  7. * Autor: zhoukun
  8. * webSite: http://zk.citier.net/layerModel.html
  9. * Date: 星期日 2014-03-30
  10. * Version: 1.0.0
  11. **********************************************************************
  12. * @example $("#example").layerModel(); 使用layerModel可以轻松的弹出各种层
  13. **********************************************************************
  14. * layerModel参数可配置项:
  15. ****************************************************************************
  16. * 配置项 * 类型 * 默认值 * 描述
  17. ****************************************************************************
  18. *
  19. * center Boolean true 弹出层是否始终居中 (浏览器大小改变居中/拖动滚动条居中)
  20. * drag Boolean true 拖拽效果 true:启用拖拽效果。false:禁用拖拽效果。
  21. * locked Boolean true 是否开启遮罩层 true:开启遮罩。false:禁用遮罩。
  22. * zIndex number 9999 弹出层的层级大小
  23. * opacity number 0.5 背景遮罩透明度 0:为完全透明 1:未完全不透明
  24. * title string 系统提示 弹出层的标题
  25. * timer Number 0 定时关闭的时间,大于0才会有效
  26. * bgColor string #fffaf6 背景遮罩的颜色 (可采用#666,#999,#e5dfda ,#e5e5e5,#ff8800)
  27. * width/height Number 0/0 设置弹出层的宽度和高度,单位为px,传参时无需带单位,建议少用,一般在样式中指定width最好。
  28. * close Function null 设置关闭弹出层后执行的回调函数,只有返回false才不会关闭。
  29. * left/top Number 350/100 设置弹出层的位置,单位为px,传参时无需带单位,要想让其生效,必须设置fixed:false和center:false。如{"fixed":false,"center":false,"left":200,"top":100}
  30. * head Boolean true 是否显示头部title
  31. * isClose Boolean true 是否出现关闭按钮
  32. * shake Boolean false 是否出现抖动效果
  33. * staySame Boolean false 是否保持弹出元素原样,也就是没有插件自己装饰的头部和边框,元素本来啥样就弹出啥样。
  34. * init function null 初始化弹出层完成后的回调函数!
  35. * blurClose Boolean false 是否点击弹出层外部空间可将其关闭。
  36. *
  37. **********************************************************************/
  38. ; (function($) {
  39. "use strict";
  40. var methods = {
  41. o: {
  42. isIe: !-[1, ] || document.documentMode >= 9,
  43. //后面的是判断IE9、IE10的
  44. ie6: !-[1, ] && !window.XMLHttpRequest,
  45. ie9_10: document.documentMode >= 9,
  46. bgLayer: "layerModel_mask",
  47. dataId: "layerModel_main",
  48. wrapper: "layerModel_wrapper",
  49. warpperContent: "layerModel_content",
  50. warpperTitle: "layerModel_title",
  51. warpperCloseBtn: "layerModel_closeBtn",
  52. warpperOwnContent: "layerModel_ownContent",
  53. replaceClose: "replaceClose",
  54. dragableClass: "dragable",
  55. defaultWidth: 300
  56. },
  57. generateId: function() {
  58. return "_" + new Date().getTime();
  59. },
  60. init: function(data, options) {
  61. var defaults = {
  62. locked: true,fixed: true,drag: true,zIndex: 9999,opacity: "0.5",title: "港口经营人",staySame: false,isLoading : false,width: 0,height: 0,timer: 0,bgColor: "#e5dfda",left: 440,top: 80,head: true,isClose: true,shake: false,blurClose: false,close: null,init: null
  63. };
  64. var settings = $.extend({},defaults, options); //将一个空对象做为第一个参数
  65. var s = this;
  66. var generateId = s.generateId();
  67. if (typeof data === 'object') {
  68. data = data instanceof $ ? data: $(data);
  69. if(settings.isLoading) {
  70. data = s.createRender(data, settings, generateId).hide();
  71. } else {
  72. data = settings.staySame ? s.createRender(data, settings, generateId).hide() : s.createContainer(data, settings, generateId).hide();
  73. }
  74. } else if (typeof data === 'string' || typeof data === 'number') {
  75. data = $("<div id='" + s.o.dataId + generateId + "'></div>").html(data).appendTo(document.body).hide();
  76. } else {
  77. alert("Layer Error : Unsupport data type :" + typeof data);
  78. return;
  79. }
  80. if (settings.locked && !s.hasBgLayer()) {
  81. var mask = $("<div class='" + s.o.bgLayer + "' id='" + s.o.bgLayer + "'></div>").appendTo(document.body).css({"background": settings.bgColor,"opacity": settings.opacity});
  82. if (s.o.ie6) {
  83. mask.html('<iframe src="about:blank" style="width:100%;height:100%;position:absolute;top:0;left:0;z-index:-1;scrolling=no;filter:alpha(opacity=' + settings.opacity * 100 + ')"></iframe>');
  84. }
  85. }
  86. data.css({
  87. "position": settings.fixed ? s.o.ie6 ? "absolute": "fixed": "absolute","z-index": settings.zIndex,"left": settings.left,"top": settings.top
  88. }).show();
  89. if (settings.center) {
  90. s.fixLayer(data);
  91. $(window).bind("resize scroll",
  92. function() {
  93. s.fixLayer(data);
  94. });
  95. }
  96. if (settings.drag) {
  97. s.dragLayer(data, settings);
  98. }
  99. if (settings.shake) {
  100. s.shakeLayer(data);
  101. }
  102. if (settings.init && typeof settings.init === "function") {
  103. settings.init();
  104. }
  105. if (settings.timer > 0) {
  106. setTimeout(function() {
  107. $("#" + s.o.replaceClose + generateId).trigger("click");
  108. },
  109. parseInt(settings.timer, 10) || 3000);
  110. }
  111. // 点击弹出层外部自动关闭弹出层,默认不关闭
  112. if (settings.blurClose) {
  113. $("#" + s.o.bgLayer).click(function(e) {
  114. s.close($("#" + s.o.wrapper + generateId), settings, generateId);
  115. e.stopPropagation();
  116. });
  117. }
  118. return data;
  119. },
  120. createContainer: function(data, settings, generateId) {
  121. var s = this;
  122. //如果context未定义,则是通过html拼接的方式追加的否则就是原本就存在的,关闭后需要返回原地方
  123. var isHtmlSlice = data.context == undefined ? true: false;
  124. var wrapperHtml = new Array();
  125. wrapperHtml.push("<div class='" + s.o.wrapper + "' id='" + s.o.wrapper + generateId + "'>");
  126. wrapperHtml.push("<div class='" + s.o.warpperContent + "' id='" + s.o.warpperContent + generateId + "'>");
  127. wrapperHtml.push("<a class='" + s.o.replaceClose + "' id='" + s.o.replaceClose + generateId + "'></a>");
  128. if (settings.head) {
  129. wrapperHtml.push("<h4 class='" + s.o.warpperTitle + " " + s.o.dragableClass + "' id='" + s.o.warpperTitle + generateId + "'>");
  130. if (settings.isClose) {
  131. wrapperHtml.push("<a href='javascript:void(0);' title='关闭' class='" + s.o.warpperCloseBtn + "' id='" + s.o.warpperCloseBtn + generateId + "'>&times;</a>");
  132. }
  133. wrapperHtml.push(settings.title + "</h4>");
  134. }
  135. wrapperHtml.push("<div id='" + s.o.warpperOwnContent + generateId + "' class='" + s.o.warpperOwnContent + "'></div></div></div>");
  136. s.container = $(wrapperHtml.join(""));
  137. s.container.appendTo(document.body);
  138. data.clone(true).appendTo("#" + s.o.warpperOwnContent + generateId).show().attr('id', data.attr('id') || s.o.dataId + generateId);
  139. //div默认宽度为100%,所以建议将所有弹出的元素设置宽度,否则弹出层宽度为100%
  140. var w = $("#" + data.attr('id')).width() || $("#" + s.o.dataId + generateId).width() || s.o.defaultWidth;
  141. //指定了高度
  142. var tempWidth = w;
  143. if (settings.height > 0) {
  144. if (settings.width > 0) {
  145. tempWidth = settings.width;
  146. if (settings.width <= w) {
  147. $("#" + s.o.warpperOwnContent + generateId).css({"width": settings.width,"overflow-x": "auto"});
  148. } else {
  149. //如果指定的宽度大于元素本身的宽度,那么需要将元素居中
  150. //让元素始终居中显示
  151. var xPadding = (settings.width - w) / 2 + 8;
  152. $("#" + s.o.warpperOwnContent + generateId).css({"padding": "4px " + xPadding + "px"});
  153. }
  154. }
  155. s.container.width(tempWidth + 32);
  156. $("#" + s.o.warpperContent + generateId).width(tempWidth + 30);
  157. $("#" + s.o.warpperOwnContent + generateId).css({"height": settings.height,"overflow-y": "auto"});
  158. } else {
  159. if (settings.width > 0) {
  160. tempWidth = settings.width;
  161. if (settings.width <= w) {
  162. $("#" + s.o.warpperOwnContent + generateId).css({"width": settings.width,"overflow-x": "auto"});
  163. }
  164. }
  165. s.container.width(tempWidth + 22);
  166. $("#" + s.o.warpperContent + generateId).width(tempWidth + 20);
  167. }
  168. $("#" + s.o.warpperCloseBtn + generateId).click(function(e) {
  169. $("#" + s.o.replaceClose + generateId).trigger("click");
  170. });
  171. $("#" + s.o.replaceClose + generateId).click(function(e) {
  172. s.close($("#" + s.o.wrapper + generateId), settings, generateId);
  173. e.stopPropagation();
  174. });
  175. if (!isHtmlSlice) {
  176. s.elemBack(data, generateId);
  177. }
  178. data.detach();
  179. return s.container;
  180. },
  181. createRender: function(data, settings, generateId) {
  182. var s = this;
  183. //如果context未定义,则是通过html拼接的方式追加的否则就是原本就存在的,关闭后需要返回原地方
  184. var style = "border:none;";
  185. if(settings.isLoading) {
  186. style +="box-shadow:none;";
  187. } else {
  188. style +="background:#fff;";
  189. }
  190. var isHtmlSlice = data.context == undefined ? true: false;
  191. s.container = $("<div class='" + s.o.wrapper + "' style=' " + style + " ' id='" + s.o.wrapper + generateId + "'><a class='" + s.o.replaceClose + "' id='" + s.o.replaceClose + generateId + "'></a></div>");
  192. s.container.appendTo(document.body);
  193. data.clone(true).appendTo(s.container).show().attr('id', data.attr('id') || s.o.dataId + generateId);
  194. $("#" + s.o.replaceClose + generateId).click(function(e) {
  195. s.close($("#" + s.o.wrapper + generateId), settings, generateId);
  196. e.stopPropagation();
  197. });
  198. if (!isHtmlSlice) {
  199. s.elemBack(data, generateId);
  200. }
  201. data.detach();
  202. return s.container;
  203. },
  204. elemBack: function(data, generateId) {
  205. var s = this;
  206. // 让传入的元素在对话框关闭后可以返回到原来的地方
  207. var display = data.css("display");
  208. var obj = data[0];
  209. var prev = obj.previousSibling;
  210. var next = obj.nextSibling;
  211. var parent = obj.parentNode;
  212. s["elemBack_" + generateId] = function() {
  213. if (prev && prev.parentNode) {
  214. prev.parentNode.insertBefore(obj, prev.nextSibling);
  215. } else if (next && next.parentNode) {
  216. next.parentNode.insertBefore(obj, next);
  217. } else if (parent) {
  218. parent.appendChild(obj);
  219. };
  220. data.css({
  221. "display": display
  222. });
  223. };
  224. },
  225. isLastLayer: function() {
  226. var s = this;
  227. return $("." + s.o.wrapper).length <= 0;
  228. },
  229. hasBgLayer: function() {
  230. var s = this;
  231. return $("." + s.o.bgLayer).length > 0;
  232. },
  233. close: function(data, settings, generateId) {
  234. var s = this;
  235. var result = true;
  236. if (settings.close) {
  237. result = settings.close();
  238. }
  239. //调用回调函数
  240. if (result == undefined || result) {
  241. data.remove();
  242. if (s.isLastLayer()) {
  243. $("#" + s.o.bgLayer).remove();
  244. }
  245. }
  246. if (s["elemBack_" + generateId]) {
  247. s["elemBack_" + generateId]();
  248. };
  249. },
  250. closeLayer: function(obj) {
  251. var s = this;
  252. var $wapper = $(obj).parents("div." + s.o.wrapper);
  253. $("." + s.o.replaceClose, $wapper).trigger("click");
  254. },
  255. fixLayer: function(data) {
  256. var s = this;
  257. var T = ($(window).height() - data.innerHeight()) / 2 + (s.o.ie6 ? $(document).scrollTop() : data.scrollTop());
  258. var L = ($(window).width() - data.width()) / 2 + (s.o.ie6 ? $(document).scrollLeft() : data.scrollLeft());
  259. // 考虑到用户体验,T不能 < 0
  260. return data.css({"left": L,"top": (T >= 0 ? T: 50)});
  261. },
  262. dragLayer: function(data, settings) {
  263. var s = this;
  264. var move = false; // 移动标记
  265. var x = 0,
  266. y = 0; // 鼠标离控件左上角的相对位置
  267. var o = data.find("." + s.o.dragableClass).css({"cursor": "move"});
  268. var a = o[0];
  269. o.mousedown(function(e) {
  270. //IE9 IE10居然把e.button改成0了,艹
  271. var isLeftClick = (s.o.isIe && e.button == 1) || (!s.o.isIe && e.button == 0) || (s.o.ie9_10 && e.button == 0);
  272. if (isLeftClick) {
  273. // data.fadeTo(20, 0.25);// 点击后开始拖动并透明显示
  274. s.o.isIe ? a.setCapture() : window.captureEvents(Event.MOUSEMOVE);
  275. move = true;
  276. x = e.pageX - parseInt(data.css("left"));
  277. y = e.pageY - parseInt(data.css("top"));
  278. $(document).mousemove(function(e) {
  279. if (move) {
  280. var sx = e.pageX - x; // 移动时根据鼠标位置计算控件左上角的绝对位置
  281. var sy = e.pageY - y;
  282. data.css({"top": sy,"left": sx});
  283. }
  284. }).mouseup(function() {
  285. // data.fadeTo("fast", 1);// 松开鼠标后停止移动并恢复成不透明
  286. move = false;
  287. x = 0;
  288. y = 0;
  289. s.o.isIe ? a.releaseCapture() : window.captureEvents(Event.MOUSEMOVE | Event.MOUSEUP);
  290. });
  291. } else {
  292. return false;
  293. }
  294. });
  295. },
  296. shakeLayer: function(data) {
  297. var ll = ($(window).width() - data.width()) / 2;
  298. var loop = 4;
  299. for (var i = 1; i <= loop; i++) {
  300. data.animate({left: ll - (loop * 10 - 10 * i)},50);
  301. data.animate({left: ll + 2 * (loop * 10 - 10 * i)},50);
  302. }
  303. }
  304. };
  305. $.fn.layerModel = function(options) {
  306. return this.each(function(idx, item) {
  307. methods.init(item, options);
  308. });
  309. };
  310. $.fn.close = function() {
  311. methods.closeLayer(this);
  312. };
  313. $.fn.fix = function() {
  314. var mn = $(this).parents("." + methods.o.wrapper);
  315. return methods.fixLayer($(mn[0]));
  316. };
  317. })(jQuery);