mBox.Notice.js 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244
  1. /*
  2. ---
  3. description: mBox is a powerful library, helping you to easily create tooltips, modal windows, notice messages and more.
  4. authors: Stephan Wagner
  5. license: MIT-style
  6. requires:
  7. - core/1.4.5: '*'
  8. - more/Element.Measure
  9. provides: [mBox]
  10. documentation: http://htmltweaks.com/mBox/Documentation
  11. ...
  12. */
  13. var mBox = new Class({
  14. Implements: [Options,Events],
  15. options: {
  16. id: '', // id of the mBox wrapper (defaults to mBox_1, mBox_2, mBox_3...)
  17. theme: '', // themes can be defined by css, e.g. in assets/themes/mBoxMyTheme.css
  18. addClass: { // add additional classes to wrapper, container, title and/or footer
  19. wrapper: '',
  20. container: '',
  21. content: '',
  22. title: '',
  23. footer: ''
  24. },
  25. setStyles: { // set additional styles to wrapper, container, title and/or footer
  26. wrapper: {},
  27. container: {},
  28. content: {},
  29. title: {},
  30. footer: {}
  31. },
  32. target: $(window), // element reference or element-id where the mBox will be opened (use 'mouse' to show mBox on mouse-position)
  33. attach: null, // element reference or element-id or element-classes of the elements which will open / close the mBox
  34. event: 'click', // the event which will trigger the mBox to show (can be: 'click' || 'mouseover' (= 'mouseenter'))
  35. preventDefault: false, // prevents the default action when clicking on attached item (e.g. prevents to follow a link when clicking on a link)
  36. //inject: null, // TODO element to inject the wrapper to (open and close will be disabled)
  37. width: 'auto', // width of the content area
  38. height: 'auto', // height of the content area
  39. zIndex: 8000, // z-index of wrapper
  40. content: null, // element reference or element-id or element classes to inject into the content, use a string to set a string as content
  41. setContent:
  42. 'data-setContent', // if the attached element has the attribute data-setContent it's value will be set as new content on open
  43. load: null, // set to ajax to load the content from url
  44. url: '', // the url to load the content from if load is set to ajax or iframe
  45. reload: false, // reloads the content each time the mBox is opened
  46. title: null, // adds a title (element reference, element-id or string)
  47. footer: null, // adds a footer (element reference, element-id or string)
  48. draggable: false, // mBox can be dragged when clicking on title
  49. position: {
  50. x: 'center', // horizontal position (use array to define outside or inside positions e.g. ['right', 'inside'] or ['left', 'center'])
  51. y: 'center' // vertical position (use array to define outside or inside positions e.g. ['top', 'inside'] or ['bottom', 'center'])
  52. }, // the position-attributes default to 'left' and 'top', to change them to 'right' or 'bottom', define a third value in the array e.g. ['left', 'inside', 'right']
  53. fixed: null, // set to false to force mBox to be absolute or true to force mBox to be fixed
  54. offset: { // offsets to be added to position
  55. x: 0,
  56. y: 0
  57. },
  58. pointer: false, // set to true to show a pointer (at least one position value needs to be 'outside')
  59. // set to 'right', 'left', 'top', 'bottom' to adjust the pointers position
  60. // if you want to add an offset to the pointer, provide an array, e.g. ['left', 10]
  61. fade: { // set to false or 0 if you want to open/close the tooltip instantly (fade: false will open and close tooltip instantly)
  62. open: true,
  63. close: true
  64. },
  65. fadeDuration: { // default fade duration when opening or closing (set fadeDuration: 250 to use it for open and close)
  66. open: 200,
  67. close: 300
  68. },
  69. fadeWhenOpen: false, // set to true if you want to fade the mBox on open even if it's already open
  70. overlay: false, // adds a overlay just underneath the mBox to prevent clicks on body
  71. overlayStyles: { // set the color and the opacity of the overlay
  72. color: 'black',
  73. opacity: 0.75
  74. },
  75. overlayFadeDuration: 100, // default fade duration for the overlay
  76. transition: { // adds a transition when mBox is opened or closed, following shortcuts are availible:
  77. // transition: ['flyin', 'flyout', 'flyinout', 'flyoutin', 'bounce', 'bouncefly']
  78. open: null, // you can also define your own transitions by using mootools transitions:
  79. close: null // transition: {open: {transition: 'bounce:in', property: 'top', duration: 400, difference_start: 50, difference_end: 0}
  80. },
  81. closeOnEsc: true, // close mBox when pressing esc
  82. closeOnClick: false, // close mBox when clicking anywhere
  83. closeOnBoxClick: false, // close mBox when clicking on the mBox
  84. closeOnWrapperClick: false, // close mBox when clicking on the Wrapper of the mBox (wont close when clicking on children of mBox like title, content etc.)
  85. closeOnBodyClick: true, // close mBox when clicking anywhere except the mBox itself
  86. closeOnMouseleave: false, // close mBox when the mouse leaves the mBox area or the attached area
  87. closeInTitle: false, // adds a close button in the title area // TODO won't work in tooltip title yet
  88. //closeInContainer: false, // TODO add a close button to the container
  89. //closeInWindow: false, // TODO add a close button to the window
  90. delayOpen: 0, // delay opening the mBox in ms
  91. delayClose: 0, // delay closing the mBox in ms
  92. delayOpenOnce: true, // set to true if you want the delay to be ignored when the mBox didnt finish closing yet
  93. constructOnInit: true, // true will construct the mBox once its finished initializing
  94. openOnInit: false // true will construct (if it hasbn't been) and open the mBox once its finished initializing
  95. // Events:
  96. // onInit: function() {},
  97. // onOpen: function() {},
  98. // onOpenComplete: function() {},
  99. // onClose: function() {},
  100. // onCloseComplete: function() {}
  101. // onBoxReady: function() {}
  102. // onAjaxComplete: function() {}
  103. },
  104. // initialize
  105. initialize: function(options) {
  106. // set global vars
  107. this.block = false; // set this.block to true so the mBox wont be opened until set to false again
  108. this.ignoreDelay = false; // set this.ignoreDelay to true if you want to ignore the delays until set to false again
  109. this.ignoreDelayOnce = false; // set this.ignoreDelayOnce to true if you want to ignore the delay only for one closing / opening
  110. // set the options
  111. this.setOptions(options);
  112. // fix options addClass, setStyles, fade, fadeDuration
  113. this.fixOptions();
  114. this.getPosition();
  115. // save current target in this.target
  116. this.target = this.getTarget();
  117. // set fixed to true or false depending on target
  118. if (this.options.fixed == null) {
  119. this.options.fixed = [$(window), $(document), $(document.body)].contains(this.target);
  120. }
  121. // no pointer if target == 'mouse'
  122. if (this.target == 'mouse') { this.options.pointer = false; }
  123. // targets will be saved in this.targets
  124. this.targets = [];
  125. // get mBox id
  126. this.id = (this.options.id || 'mBox' + (++mBox.currentId));
  127. // add listeners to elements
  128. this.addListeners();
  129. // construct the mBox
  130. if(this.options.constructOnInit) {
  131. this.construct();
  132. }
  133. // fire onInit events
  134. this.fireEvent('init').fireEvent('systemInit');
  135. // open mBox on init
  136. if(this.options.openOnInit) {
  137. this.open();
  138. }
  139. // add this instance to global collector
  140. mBox.instances.push(this);
  141. },
  142. // re-initialize mBox (e.g. after an ajax call)
  143. reInit: function() {
  144. // add listeners to new elements
  145. this.addListeners();
  146. },
  147. // fix options
  148. fixOptions: function() {
  149. if(typeof this.options.addClass == 'string') {
  150. this.options.addClass = {
  151. wrapper: this.options.addClass
  152. };
  153. }
  154. if(typeof this.options.setStyles == 'object' && !this.options.setStyles.wrapper && !this.options.setStyles.container && !this.options.setStyles.content && !this.options.setStyles.title && !this.options.setStyles.footer) {
  155. this.options.setStyles = {
  156. wrapper: this.options.setStyles
  157. };
  158. }
  159. this.options.fade = {
  160. open: this.options.fade.open || (this.options.fade == true),
  161. close: this.options.fade.close || (this.options.fade == true)
  162. };
  163. this.options.fadeDuration = {
  164. open: this.options.fadeDuration.open || this.options.fadeDuration,
  165. close: this.options.fadeDuration.close || this.options.fadeDuration
  166. };
  167. },
  168. // contruct the mBox
  169. construct: function() {
  170. if(this.wrapper) {
  171. return null;
  172. }
  173. // create wrapper
  174. this.wrapper = new Element('div', {
  175. id: this.id,
  176. 'class': 'mBox ' + (this.defaultTheme || 'Core') + (this.options.theme ? '-' + this.options.theme : '') + ' ' + (this.options.addClass.wrapper || ''),
  177. styles: {
  178. zIndex: this.options.zIndex,
  179. position: (this.options.fixed == false || Browser.ie6 || Browser.ie7) ? 'absolute' : 'fixed',
  180. display: 'none',
  181. opacity: 0.00001,
  182. top: -12000,
  183. left: -12000,
  184. zoom: 1
  185. }
  186. }).setStyles(this.options.setStyles.wrapper || {}).inject(document.body, 'bottom');
  187. // add mouse events to wrapper
  188. if(this.options.closeOnMouseleave) {
  189. this.wrapper.addEvents({
  190. mouseenter: function(ev) {
  191. this.open();
  192. }.bind(this),
  193. mouseleave: function(ev) {
  194. this.close();
  195. }.bind(this)
  196. });
  197. }
  198. // create container (contains content, title, footer)
  199. this.container = new Element('div', {
  200. 'class': 'mBoxContainer' + ' ' + (this.options.addClass.container || '')
  201. }).setStyles(this.options.setStyles.container || {}).inject(this.wrapper);
  202. // create content
  203. this.content = new Element('div', {
  204. 'class': 'mBoxContent' + ' ' + (this.options.addClass.content || ''),
  205. styles: {
  206. width: this.options.width,
  207. height: this.options.height
  208. }
  209. }).setStyles(this.options.setStyles.content || {}).inject(this.container);
  210. // load content into mBox
  211. this.load(this.options.content, this.options.title, this.options.footer, true); // TODO whats the true for?
  212. // fire boxReady events
  213. this.fireEvent('systemBoxReady').fireEvent('boxReady');
  214. },
  215. // add event listerners to elements
  216. addListeners: function(el) {
  217. // get elements to add events to, if none given use this.options.attach
  218. el = el || this.options.attach;
  219. elements = Array.from($(el)).combine(Array.from($$('.' + el))).combine(Array.from($$(el))).clean();
  220. if(!elements || elements.length == 0) return this;
  221. // add elements to this.targets
  222. this.targets.combine(elements);
  223. // create click or mouseenter/mouseleave events
  224. switch(this.options.event) {
  225. case 'mouseenter':
  226. case 'mouseover':
  227. var events = {
  228. mouseenter: function(ev) {
  229. this.target = this.getTargetFromEvent(ev);
  230. this.source = this.getTargetElementFromEvent(ev);
  231. this.open();
  232. }.bind(this),
  233. mouseleave: function(ev) {
  234. this.close();
  235. }.bind(this)
  236. };
  237. break;
  238. default:
  239. var events = {
  240. click: function(ev) {
  241. if(this.options.preventDefault) {
  242. ev.preventDefault();
  243. }
  244. if(this.isOpen) {
  245. this.close();
  246. } else {
  247. this.target = this.getTargetFromEvent(ev);
  248. this.source = this.getTargetElementFromEvent(ev);
  249. this.open();
  250. }
  251. }.bind(this)
  252. };
  253. }
  254. // add events if not already added
  255. $$(elements).each(function(el) {
  256. if(!el.retrieve('mBoxElementEventsAdded' + this.id)) {
  257. el.addEvents(events).store('mBoxElementEventsAdded' + this.id, true);
  258. }
  259. }.bind(this));
  260. },
  261. // load content with ajax into mBox
  262. loadAjax: function(sendObj) {
  263. if(!this.ajaxRequest) {
  264. this.ajaxRequest = new Request.HTML({
  265. link: 'cancel',
  266. update: this.content,
  267. onRequest: function() {
  268. this.setContent('');
  269. this.wrapper.addClass('mBoxLoading');
  270. }.bind(this),
  271. onComplete: function() {
  272. this.wrapper.removeClass('mBoxLoading');
  273. if(this.options.width == 'auto' || this.options.height == 'auto') {
  274. this.setPosition();
  275. }
  276. this.fireEvent('ajaxComplete');
  277. }.bind(this)
  278. }).send();
  279. }
  280. this.ajaxRequest.send(sendObj);
  281. this.ajaxLoaded = true;
  282. },
  283. // open / show the mBox
  284. open: function(options) {
  285. if(!this.wrapper) {
  286. // construct the mBox
  287. this.construct();
  288. }
  289. if(typeof options != 'object') options = {};
  290. clearTimeout(this.timer);
  291. if(!this.isOpen && !this.block) {
  292. var complete = function() {
  293. this.ignoreDelayOnce = false;
  294. this.fireEvent('systemOpenComplete').fireEvent('openComplete');
  295. }.bind(this);
  296. var open = function(complete) {
  297. this.isOpen = true;
  298. // load content from ajax
  299. if(this.options.load == 'ajax' && this.options.url && (!this.ajaxLoaded || this.options.reload)) {
  300. this.loadAjax({url: this.options.url});
  301. }
  302. // set target
  303. this.target = this.getTarget(options.target || null);
  304. // set new content
  305. if (this.options.setContent && this.source && this.source.getAttribute(this.options.setContent)) {
  306. if ($(this.source.getAttribute(this.options.setContent))) {
  307. this.content.getChildren().setStyle('display', 'none');
  308. $(this.source.getAttribute(this.options.setContent)).setStyle('display', '');
  309. } else {
  310. var attribute_array = this.source.getAttribute(this.options.setContent).split('|'),
  311. content = attribute_array[0] || null,
  312. title = attribute_array[1] || null,
  313. footer = attribute_array[2] || null;
  314. this.load(content, title, footer);
  315. }
  316. }
  317. // set new position
  318. this.setPosition(null, options.position || null, options.offset || null);
  319. // fire open events
  320. this.fireEvent('systemOpen').fireEvent('open');
  321. // fade mBox
  322. if(this.fx) { this.fx.cancel(); }
  323. this.wrapper.setStyles({
  324. display: ''
  325. });
  326. if(this.options.fadeWhenOpen) {
  327. this.wrapper.setStyle('opacity', 0);
  328. }
  329. this.fx = new Fx.Tween(this.wrapper, {
  330. property: 'opacity',
  331. duration: this.options.fadeDuration.open,
  332. link: 'cancel',
  333. onComplete: complete
  334. })[(options.instant || !this.options.fade.open) ? 'set' : 'start'](1);
  335. // call complete function when showing instantly
  336. if(options.instant || !this.options.fade.open) {
  337. complete();
  338. }
  339. // start additional transition
  340. var transition = this.getTransition();
  341. if(transition.open) {
  342. var fx = new Fx.Tween(this.wrapper, {
  343. property: transition.open.property || 'top',
  344. duration: transition.open.duration || this.options.fadeDuration.open,
  345. transition: transition.open.transition || null,
  346. onStart: transition.open.onStart || null,
  347. onComplete: transition.open.onComplete || null
  348. });
  349. fx.start((transition.open.start || (this.wrapper.getStyle(transition.open.property || 'top').toInt() + (transition.open.difference_start || 0))),
  350. (transition.open.end || (this.wrapper.getStyle(transition.open.property || 'top').toInt() + (transition.open.difference_end || 0))));
  351. }
  352. // attach events to document and window
  353. this.attachEvents();
  354. // add overlay
  355. if(this.options.overlay) {
  356. this.addOverlay((options.instant || !this.options.fade.open));
  357. }
  358. // set delay open once to true, set to false again when closing is finished
  359. if(this.options.delayOpenOnce) {
  360. this.delayOpenOnce = true;
  361. }
  362. }.bind(this);
  363. // delay open or close instantly
  364. if(this.options.delayOpen > 0 && !this.ignoreDelay && !this.ignoreDelayOnce && !this.delayOpenOnce) {
  365. this.timer = open.delay(this.options.delayOpen, this, complete);
  366. } else {
  367. open(complete);
  368. }
  369. }
  370. return this;
  371. },
  372. // close / hide the mBox
  373. close: function(options) {
  374. if(typeof options != 'object') options = {};
  375. clearTimeout(this.timer);
  376. if(this.isOpen && !this.block) {
  377. var complete = function() {
  378. this.delayOpenOnce = false;
  379. this.ignoreDelayOnce = false;
  380. this.wrapper.setStyle('display', 'none');
  381. this.fireEvent('systemCloseComplete').fireEvent('closeComplete');
  382. }.bind(this);
  383. var close = function(complete) {
  384. this.isOpen = false;
  385. // fire close events
  386. this.fireEvent('systemClose').fireEvent('close');
  387. // detach document and window events
  388. this.detachEvents();
  389. // remove overlay
  390. if(this.options.overlay) {
  391. this.removeOverlay((options.instant || !this.options.fade.close));
  392. }
  393. // fade mBox
  394. if(this.fx) { this.fx.cancel(); }
  395. this.fx = new Fx.Tween(this.wrapper, {
  396. property: 'opacity',
  397. duration: this.options.fadeDuration.close,
  398. link: 'cancel',
  399. onComplete: complete
  400. })[(options.instant || !this.options.fade.close) ? 'set' : 'start'](0);
  401. // call complete function when hiding instantly
  402. if(options.instant || !this.options.fade.close) {
  403. complete();
  404. }
  405. // start additionel transition
  406. var transition = this.getTransition();
  407. if(transition.close) {
  408. var fx = new Fx.Tween(this.wrapper, {
  409. property: transition.close.property || 'top',
  410. duration: transition.close.duration || this.options.fadeDuration.close,
  411. transition: transition.close.transition || null,
  412. onStart: transition.open.onStart || null,
  413. onComplete: transition.open.onComplete || null
  414. });
  415. fx.start((transition.close.start || (this.wrapper.getStyle(transition.close.property || 'top').toInt() + (transition.close.difference_start || 0))),
  416. (transition.close.end || (this.wrapper.getStyle(transition.close.property || 'top').toInt() + (transition.close.difference_end || 0))));
  417. }
  418. }.bind(this);
  419. // delay close or close instantly
  420. if(this.options.delayClose > 0 && !this.ignoreDelay && !this.ignoreDelayOnce) {
  421. this.timer = close.delay(this.options.delayClose, this, complete);
  422. } else {
  423. close(complete);
  424. }
  425. }
  426. return this;
  427. },
  428. // adds a overlay just beneath the mBox to prevent clicks on body
  429. addOverlay: function(instant) {
  430. if(!this.overlay) {
  431. this.overlay = new Element('div', { styles: {
  432. position: 'fixed',
  433. top: 0,
  434. left: 0,
  435. width: '100%',
  436. height: '100%',
  437. zIndex: (this.wrapper.getStyle('zIndex') - 1),
  438. background: this.options.overlayStyles.color || 'white',
  439. opacity: 0.001,
  440. display: 'none'
  441. }}).set('tween', {
  442. duration: this.options.overlayFadeDuration,
  443. link: 'cancel'
  444. }).inject($(document.body), 'bottom');
  445. }
  446. this.overlay.setStyle('display', 'block')[instant ? 'set' : 'tween']('opacity', (this.options.overlayStyles.opacity || 0.001));
  447. return this;
  448. },
  449. // remove the overlay
  450. removeOverlay: function(instant) {
  451. if(this.overlay) {
  452. this.overlay[instant ? 'set' : 'tween']('opacity', 0).get('tween').chain(function() {
  453. this.overlay.setStyle('display', 'none');
  454. }.bind(this));
  455. }
  456. return this;
  457. },
  458. // get the current or given target
  459. getTarget: function(target) {
  460. var target = $(target) || target || this.target || $(this.options.target) || this.options.target || $(this.options.attach);
  461. return target == 'mouse' ? 'mouse' : this.fixOperaPositioning($(target));
  462. },
  463. // get the target element from event target
  464. getTargetFromEvent: function(ev) {
  465. if(this.options.target) return this.fixOperaPositioning($(this.options.target));
  466. return this.getTargetElementFromEvent(ev);
  467. },
  468. // get the attached element from event
  469. getTargetElementFromEvent: function(ev) {
  470. if(ev && ev.target) {
  471. if(this.targets.contains(ev.target)) return this.fixOperaPositioning(ev.target);
  472. var parent_element = ev.target.getParent();
  473. while(parent_element != null) {
  474. if(this.targets.contains(parent_element)) {
  475. return this.fixOperaPositioning(parent_element);
  476. }
  477. parent_element = parent_element.getParent();
  478. }
  479. }
  480. return null;
  481. },
  482. // TEMP: This function fixes temporarily the mootools 1.4.5 positioning bug in opera
  483. fixOperaPositioning: function(el) {
  484. if($(el) && !$(el).retrieve('OperaBugFixed') && el != window) {
  485. try {
  486. if(!($(el).getStyle('border-top-width').toInt() + $(el).getStyle('border-right-width').toInt() + $(el).getStyle('border-bottom-width').toInt() + $(el).getStyle('border-left-width').toInt())) {
  487. $(el).setStyle('border', 0);
  488. }
  489. }
  490. catch(e) {}
  491. $(el).store('OperaBugFixed');
  492. }
  493. return el;
  494. },
  495. // get cached variable position or get a clean position variable
  496. getPosition: function(position) {
  497. if(!position && this.position) return this.position;
  498. position = position || this.options.position;
  499. this.position = {};
  500. // TODO shortcuts 'top' 'topRight' 'bottomLeft' etc.
  501. // get a clean x-position
  502. this.position.x = (typeof position == 'object' && typeof position.x == 'number') ?
  503. [position.x.toInt(), null] : ((typeof position != 'object' || !position.x || position.x == 'center' || (typeof position.x == 'object' && position.x[0] == 'center')) ?
  504. ['center', null] : (['right', 'left'].contains(position.x) ?
  505. [position.x, (this.defaultInOut || 'inside')] : ((typeof position.x == 'object' && ['right', 'left'].contains(position.x[0])) ?
  506. [position.x[0], (['inside', 'center', 'outside'].contains(position.x[1]) ? position.x[1] : (this.defaultInOut || 'inside'))] : ['center', null])));
  507. this.position.xAttribute = (this.position.x[3] == 'right' || (this.position.x[1] == 'inside' && this.position.x[0] == 'right')) ? 'right' : 'left';
  508. // get a clean y-position
  509. this.position.y = (typeof position == 'object' && typeof position.y == 'number') ?
  510. [position.y.toInt(), null] : ((typeof position != 'object' || !position.y || position.y == 'center' || (typeof position.y == 'object' && position.y[0] == 'center')) ?
  511. ['center', null] : (['top', 'bottom'].contains(position.y) ?
  512. [position.y, (this.defaultInOut || 'inside')] : ((typeof position.y == 'object' && ['top', 'bottom'].contains(position.y[0])) ?
  513. [position.y[0], (['inside', 'center', 'outside'].contains(position.y[1]) ? position.y[1] : (this.defaultInOut || 'inside'))] : ['center', null])));
  514. this.position.yAttribute = (this.position.x[3] == 'bottom' || (this.position.y[1] == 'inside' && this.position.y[0] == 'bottom')) ? 'bottom' : 'top';
  515. return this.position;
  516. },
  517. // get cached offset variable or get a clean one
  518. getOffset: function(offset) {
  519. if(!offset && this.offset) return this.offset;
  520. offset = offset || this.options.offset;
  521. this.offset = {};
  522. this.offset.x = (typeof offset == 'number') ? offset : (!offset.x ? 0 : (offset.x.toInt() >= 0 || offset.x.toInt() < 0) ? offset.x.toInt() : 0);
  523. this.offset.y = (typeof offset == 'number') ? offset : (!offset.y ? 0 : (offset.y.toInt() >= 0 || offset.y.toInt() < 0) ? offset.y.toInt() : 0);
  524. return this.offset;
  525. },
  526. // get cached pointer variable or get a clean one
  527. getPointer: function(pointer) {
  528. if(!pointer && this.pointer) return this.pointer;
  529. pointer = pointer || this.options.pointer;
  530. if(!pointer) return false;
  531. var position = this.getPosition();
  532. this.pointer = {};
  533. if(position.y[1] == 'outside') {
  534. this.pointer.position = (position.y[0] == 'bottom') ? 'top' : 'bottom';
  535. this.pointer.adjustment = (typeof pointer == 'object' && ['center', 'right', 'left'].contains(pointer[0])) ? pointer[0] : (['center', 'right', 'left'].contains(pointer) ? pointer : 'center');
  536. } else if(position.x[1] == 'outside') {
  537. this.pointer.position = (position.x[0] == 'left') ? 'right' : 'left';
  538. this.pointer.adjustment = (typeof pointer == 'object' && ['center', 'top', 'bottom'].contains(pointer[0])) ? pointer[0] : (['center', 'top', 'bottom'].contains(pointer) ? pointer : 'center');
  539. } else {
  540. return null;
  541. }
  542. this.pointer.offset = (typeof pointer == 'object' && pointer[1] && typeof(pointer[1].toInt()) == 'number') ? pointer[1].toInt() : 0;
  543. // TODO pointer with inside && inside should be possible
  544. // TODO minimum offset if the container has a border-radius (this.container.getStyle('border-top-left-radius');
  545. this.pointer.offset = this.pointer.offset < 0 ? this.pointer.offset * (-1) : this.pointer.offset;
  546. this.pointer.offset = (this.pointer.adjustment == 'right' || this.pointer.adjustment == 'bottom') ? this.pointer.offset * (-1) : this.pointer.offset;
  547. return this.pointer;
  548. },
  549. // get cached transition variable or get a clean one
  550. getTransition: function() {
  551. if(this.transition) return this.transition;
  552. if(this.options.transition && ['flyin', 'flyout', 'flyinout', 'flyoutin', 'bounce', 'bouncein', 'bounceout', 'bounceinout', 'bouncefly'].contains(this.options.transition)) {
  553. this.transition = {};
  554. this.transition.open = {
  555. property: (this.position.yAttribute == 'top' || this.position.yAttribute == 'bottom') ? this.position.yAttribute : this.position.xAttribute,
  556. transition: 'quad:out',
  557. duration: 300
  558. }
  559. this.transition.close = Object.clone(this.transition.open);
  560. var distance = (20 * (this.position.yAttribute == 'bottom' || this.position.xAttribute == 'right' ? -1 : 1));
  561. switch(this.options.transition) {
  562. case 'flyin': // TODO flyin should only flyin
  563. case 'flyout':
  564. this.transition.open.difference_start = this.transition.close.difference_end = distance * (this.options.transition == 'flyin' ? (-1) : 1);
  565. break;
  566. case 'flyinout':
  567. case 'flyoutin':
  568. distance = (distance * (this.options.transition == 'flyinout' ? 1 : (-1)));
  569. this.transition.open.difference_start = distance * (-1);
  570. this.transition.close.difference_end = distance;
  571. break;
  572. case 'bounce':
  573. case 'bouncefly':
  574. case 'bouncein':
  575. case 'bounceout':
  576. case 'bounceinout':
  577. this.transition.open.transition = 'bounce:out';
  578. this.transition.open.duration = 450;
  579. this.transition.open.difference_start = distance * (-1);
  580. if(this.options.transition == 'bounceinout' || this.options.transition == 'bounceout' || this.options.transition == 'bouncefly') {
  581. this.transition.close.difference_end = distance * (-1);
  582. }
  583. break;
  584. }
  585. } else {
  586. this.transition = {};
  587. this.transition.open = typeof this.options.transition.open != undefined ? this.options.transition.open : this.options.transition;
  588. this.transition.close = typeof this.options.transition.close != undefined ? this.options.transition.close : this.options.transition;
  589. }
  590. return this.transition;
  591. },
  592. // position the mBox
  593. setPosition: function(target, position, offset) {
  594. // get variables
  595. target = this.getTarget(target);
  596. position = this.getPosition(position);
  597. offset = this.getOffset(offset);
  598. pointer = this.getPointer();
  599. // attach to mouse if target == 'mouse'
  600. if(target == 'mouse') {
  601. posX = ((this.mouseX || 0) + 15 + offset.x);
  602. posY = ((this.mouseY || 0) + 15 + offset.y);
  603. this.wrapper.setStyles({
  604. 'left': Math.floor(posX),
  605. 'top': Math.floor(posY)
  606. });
  607. return this;
  608. }
  609. // get dimensions and coordinates
  610. if(!target || [$(window), $(document), $(document.body)].contains(target)) {
  611. var windowScroll = this.wrapper.getStyle('position') == 'fixed' ? {x: 0, y: 0} : $(window).getScroll(),
  612. targetDimensions = $(window).getSize();
  613. targetDimensions.width = targetDimensions.totalWidth = targetDimensions.x;
  614. targetDimensions.height = targetDimensions.totalHeight = targetDimensions.y;
  615. var targetCoordinates = {
  616. top: windowScroll.y,
  617. left: windowScroll.x,
  618. right: windowScroll.x + targetDimensions.width,
  619. bottom: windowScroll.y + targetDimensions.height
  620. };
  621. } else {
  622. if(!this.options.fixed != true) {
  623. this.wrapper.setStyle('position', 'absolute');
  624. }
  625. var targetDimensions = target.getDimensions({computeSize: true});
  626. var targetCoordinates = target.getCoordinates();
  627. if(targetDimensions.totalWidth == 0) {
  628. targetDimensions.width = targetDimensions.totalWidth = targetCoordinates.width;
  629. targetDimensions.height = targetDimensions.totalHeight = targetCoordinates.height;
  630. }
  631. }
  632. // set position to current position of target
  633. var posX = targetCoordinates.left || 0,
  634. posY = targetCoordinates.top || 0;
  635. var wrapperDimensions = this.wrapper.getDimensions({computeSize: true});
  636. // create pointer if not already created
  637. if(pointer && !this.pointerElement) {
  638. this.pointerElement = new Element('div', {
  639. 'class': 'mBoxPointer ' + 'mBoxPointer' + pointer.position.capitalize(),
  640. styles: {position: 'absolute'}
  641. }).setStyle(pointer.position, 0).inject(this.wrapper, 'top');
  642. // opera wont calculate the size of the pointer correctly, needs to get fixed properly
  643. if(Browser.opera) {
  644. var tempContainer = new Element('div', {'class': 'mBox ' + (this.defaultTheme || 'Core') + (this.options.theme ? '-' + this.options.theme : '')}).inject(document.body).grab(this.pointerElement);
  645. this.pointerDimensions = this.pointerElement.getDimensions({computeSize: true});
  646. this.pointerElement.inject(this.wrapper, 'top');
  647. tempContainer.destroy();
  648. } else {
  649. this.pointerDimensions = this.pointerElement.getDimensions({computeSize: true});
  650. }
  651. this.container.setStyle('margin-' + pointer.position,
  652. (pointer.position == 'left' || pointer.position == 'right') ?
  653. (this.pointerDimensions.width - this.container.getStyle('border-' + pointer.position).toInt()) :
  654. (this.pointerDimensions.height - this.container.getStyle('border-' + pointer.position).toInt()));
  655. }
  656. // adjust wrapper to pointer position
  657. if(pointer && this.pointerElement) {
  658. // if position x and position y is outside, fix pointer position
  659. if(position.x[1] == 'outside' && position.y[1] == 'outside' && pointer.adjustment == 'center') {
  660. pointer.adjustment = (position.x[0] == 'left') ? 'right' : 'left';
  661. switch(position.x[0]) {
  662. case 'left':
  663. posX += wrapperDimensions.totalWidth - (this.pointerDimensions.width / 2);
  664. break;
  665. case 'right':
  666. posX -= (this.pointerDimensions.width / 2);
  667. break;
  668. }
  669. }
  670. // calculate pointer margin and extra offset
  671. var wrapperOffset = 0, pointerMargin = 0, offsetPointerX = 0, offsetPointerY = 0;
  672. switch(pointer.adjustment) {
  673. case 'center':
  674. pointerMargin = (pointer.position == 'top' || pointer.position == 'bottom') ? ((wrapperDimensions.totalWidth / 2) - (this.pointerDimensions.width / 2)) : ((wrapperDimensions.totalHeight / 2) - (this.pointerDimensions.height / 2));
  675. break;
  676. case 'left':
  677. case 'right':
  678. switch(position.x[1]) {
  679. case 'inside':
  680. offsetPointerX += ((this.pointerDimensions.width / 2) * -1) + ((position.x[0] == 'right') ? wrapperDimensions.totalWidth : 0);
  681. break;
  682. default:
  683. if(position.x[0] == 'center') {
  684. offsetPointerX += (wrapperDimensions.totalWidth / 2) - (this.pointerDimensions.width / 2);
  685. }
  686. }
  687. posX += offsetPointerX - ((pointer.adjustment == 'right') ? (wrapperDimensions.totalWidth - this.pointerDimensions.width) : 0);
  688. pointerMargin = (pointer.adjustment == 'right') ? (wrapperDimensions.totalWidth - this.pointerDimensions.width) : 0;
  689. break;
  690. case 'top':
  691. case 'bottom':
  692. switch(position.y[1]) {
  693. case 'inside':
  694. offsetPointerY += ((this.pointerDimensions.height / 2) * -1) + ((position.y[0] == 'bottom') ? wrapperDimensions.totalHeight : 0);
  695. break;
  696. default:
  697. if(position.y[0] == 'center') {
  698. offsetPointerY += (wrapperDimensions.totalHeight / 2) - (this.pointerDimensions.height / 2);
  699. }
  700. }
  701. posY += offsetPointerY - ((pointer.adjustment == 'bottom') ? (wrapperDimensions.totalHeight - this.pointerDimensions.height) : 0);
  702. pointerMargin = (pointer.adjustment == 'bottom') ? (wrapperDimensions.totalHeight - this.pointerDimensions.height) : 0;
  703. break;
  704. }
  705. switch(pointer.position) {
  706. case 'top':
  707. case 'bottom':
  708. posX += (pointer.offset * (-1));
  709. break;
  710. case 'left':
  711. case 'right':
  712. posY += (pointer.offset * (-1));
  713. break;
  714. }
  715. this.pointerElement.setStyle((pointer.position == 'top' || pointer.position == 'bottom') ? 'left' : 'top', pointerMargin + pointer.offset);
  716. }
  717. // get wrapper dimensions including pointer
  718. wrapperDimensions = this.wrapper.getDimensions({computeSize: true});
  719. // calculate position
  720. switch(position.x[0]) {
  721. case 'center':
  722. posX += (targetDimensions.totalWidth / 2) - (wrapperDimensions.totalWidth / 2);
  723. break;
  724. case 'right':
  725. posX += targetDimensions.totalWidth - (position.x[1] == 'inside' ? wrapperDimensions.totalWidth : (position.x[1] == 'center' ? (wrapperDimensions.totalWidth / 2) : 0));
  726. break;
  727. case 'left':
  728. posX -= (position.x[1] == 'outside' ? wrapperDimensions.totalWidth : (position.x[1] == 'center' ? (wrapperDimensions.totalWidth / 2) : 0));
  729. break;
  730. default:
  731. posX = position.x;
  732. }
  733. switch(position.y[0]) {
  734. case 'center':
  735. posY += (targetDimensions.totalHeight / 2) - (wrapperDimensions.totalHeight / 2);
  736. break;
  737. case 'bottom':
  738. posY += targetDimensions.totalHeight - (position.y[1] == 'inside' ? wrapperDimensions.totalHeight : (position.y[1] == 'center' ? (wrapperDimensions.totalHeight / 2) : 0));
  739. break;
  740. case 'top':
  741. posY -= (position.y[1] == 'outside' ? wrapperDimensions.totalHeight : (position.y[1] == 'center' ? (wrapperDimensions.totalHeight / 2) : 0));
  742. break;
  743. default:
  744. posX = position.y;
  745. }
  746. // reset wrapper positions
  747. this.wrapper.setStyles({top: null, right: null, bottom: null, left: null});
  748. // calculate 'bottom' or 'right' positions if needed
  749. var windowDimensions = $(window).getSize();
  750. if(position.xAttribute == 'right') {
  751. posX = windowDimensions.x - (posX + wrapperDimensions.totalWidth);
  752. }
  753. if(position.yAttribute == 'bottom') {
  754. posY = windowDimensions.y - (posY + wrapperDimensions.totalHeight);
  755. }
  756. // add global offsets and set positions
  757. posX = posX || 0;
  758. posX += offset.x;
  759. posY += offset.y;
  760. this.wrapper.setStyle(position.xAttribute, posX.floor());
  761. this.wrapper.setStyle(position.yAttribute, posY.floor());
  762. return this;
  763. },
  764. // set up content
  765. setContent: function(content, where) {
  766. if(content != null) {
  767. if($(content) || $$('.' + content).length > 0) {
  768. this[where || 'content'].grab($(content) || $$('.' + content));
  769. if($(content)) $(content).setStyle('display', '');
  770. } else if(content != null) {
  771. this[where || 'content'].set('html', content);
  772. }
  773. }
  774. return this;
  775. },
  776. // set up title
  777. setTitle: function(content) {
  778. if(content != null && !this.titleContainer) {
  779. this.titleContainer = new Element('div', {
  780. 'class': 'mBoxTitleContainer'
  781. }).inject(this.container, 'top');
  782. this.title = new Element('div', {
  783. 'class': 'mBoxTitle ' + (this.options.addClass.title || ''),
  784. styles: (this.options.setStyles.title || {})
  785. }).inject(this.titleContainer);
  786. this.wrapper.addClass('hasTitle');
  787. if(this.options.draggable && window['Drag'] != null) {
  788. new Drag(this.wrapper, { handle: this.titleContainer});
  789. this.titleContainer.addClass('mBoxDraggable');
  790. }
  791. if(this.options.closeInTitle) {
  792. new Element('div', {
  793. 'class': 'mBoxClose',
  794. events: {
  795. click: function() {
  796. this.close();
  797. }.bind(this)
  798. }
  799. }).grab(new Element('div')).inject(this.titleContainer);
  800. }
  801. }
  802. if(content != null) {
  803. this.setContent(content, 'title');
  804. }
  805. return this;
  806. },
  807. // set up footer
  808. setFooter: function(content) {
  809. if(content != null && !this.footerContainer) {
  810. this.footerContainer = new Element('div', {
  811. 'class': 'mBoxFooterContainer'
  812. }).inject(this.container, 'bottom');
  813. this.footer = new Element('div', {
  814. 'class': 'mBoxFooter ' + (this.options.addClass.footer || ''),
  815. styles: (this.options.setStyles.footer || {})
  816. }).inject(this.footerContainer);
  817. this.wrapper.addClass('hasFooter');
  818. }
  819. if(content != null) {
  820. this.setContent(content, 'footer');
  821. }
  822. return this;
  823. },
  824. // set up content, title and/or footer
  825. load: function(content, title, footer) {
  826. this.setContent(content);
  827. this.setTitle(title);
  828. this.setFooter(footer);
  829. return this;
  830. },
  831. // return the mBox as html
  832. getHTML: function(content, title, footer) {
  833. this.load(content, title, footer);
  834. return '<div>' + this.wrapper.get('html') + '</div>';
  835. },
  836. // attach events to document and window
  837. attachEvents: function() {
  838. // event: close mBox when clicking esc
  839. this.escEvent = function(ev) {
  840. if(ev.key == 'esc') {
  841. this.ignoreDelayOnce = true;
  842. this.close();
  843. }
  844. }.bind(this);
  845. if(this.options.closeOnEsc) {
  846. $(window).addEvent('keyup', this.escEvent);
  847. }
  848. // event: reposition mBox on window resize or scroll
  849. this.resizeEvent = function(ev) {
  850. this.setPosition();
  851. }.bind(this);
  852. $(window).addEvent('resize', this.resizeEvent);
  853. if(this.options.fixed && (Browser.ie6 || Browser.ie7)) {
  854. $(window).addEvent('scroll', this.resizeEvent);
  855. }
  856. // event: close mBox when clicking anywhere
  857. this.closeOnClickEvent = function(ev) {
  858. if(this.isOpen && ($(this.options.attach) != ev.target && !$$('.' + this.options.attach).contains(ev.target))) {
  859. this.ignoreDelayOnce = true;
  860. this.close();
  861. }
  862. }.bind(this);
  863. if(this.options.closeOnClick) {
  864. $(document).addEvent('mouseup', this.closeOnClickEvent);
  865. }
  866. // event: close mBox when clicking on wrapper or it's children
  867. this.closeOnBoxClickEvent = function(ev) {
  868. if(this.isOpen && (this.wrapper == ev.target || this.wrapper.contains(ev.target))) {
  869. this.ignoreDelayOnce = true;
  870. this.close();
  871. }
  872. }.bind(this);
  873. if(this.options.closeOnBoxClick) {
  874. $(document).addEvent('mouseup', this.closeOnBoxClickEvent);
  875. }
  876. // event: close mBox when clicking on wrapper directly
  877. this.closeOnWrapperClickEvent = function(ev) {
  878. if(this.isOpen && this.wrapper == ev.target) {
  879. this.ignoreDelayOnce = true;
  880. this.close();
  881. }
  882. }.bind(this);
  883. if(this.options.closeOnWrapperClick) {
  884. $(document).addEvent('mouseup', this.closeOnWrapperClickEvent);
  885. }
  886. // event: close mBox when clicking on body
  887. this.closeOnBodyClickEvent = function(ev) {
  888. if(this.isOpen && ($(this.options.attach) != ev.target && !$$('.' + this.options.attach).contains(ev.target)) && ev.target != this.wrapper && !this.wrapper.contains(ev.target)) {
  889. this.ignoreDelayOnce = true;
  890. this.close();
  891. }
  892. }.bind(this);
  893. if(this.options.closeOnBodyClick) {
  894. $(document).addEvent('mouseup', this.closeOnBodyClickEvent);
  895. }
  896. // event: attach mBox to mouse position
  897. this.mouseMoveEvent = function(ev) {
  898. this.mouseX = ev.page.x;
  899. this.mouseY = ev.page.y;
  900. this.setPosition('mouse');
  901. }.bind(this);
  902. if(this.target == 'mouse') {
  903. $(document).addEvent('mousemove', this.mouseMoveEvent);
  904. }
  905. },
  906. // remove events from document or window
  907. detachEvents: function() {
  908. if(this.options.fixed && (Browser.ie6 || Browser.ie7)) {
  909. $(window).removeEvent('scroll', this.resizeEvent);
  910. }
  911. $(window).removeEvent('keyup', this.keyEvent);
  912. $(window).removeEvent('resize', this.resizeEvent);
  913. $(document).removeEvent('mouseup', this.closeOnClickEvent);
  914. $(document).removeEvent('mouseup', this.closeOnBoxClickEvent);
  915. $(document).removeEvent('mouseup', this.closeOnWrapperClickEvent);
  916. $(document).removeEvent('mouseup', this.closeOnBodyClickEvent);
  917. $(document).removeEvent('mousemove', this.mouseMoveEvent);
  918. },
  919. // dispose of wrapper and remove it from DOM
  920. destroy: function() {
  921. mBox.instances.erase(this);
  922. this.detachEvents();
  923. this.wrapper.dispose();
  924. delete this.wrapper;
  925. }
  926. });
  927. // store global mBox instances
  928. mBox.instances = [];
  929. // use global mBox ids
  930. mBox.currentId = 0;
  931. // reinit mBoxes (e.g. once an ajax has been called)
  932. mBox.reInit = function() {
  933. if(mBox.addConfirmEvents) {
  934. mBox.addConfirmEvents();
  935. }
  936. mBox.instances.each(function(instance) {
  937. try {
  938. instance.reInit();
  939. }
  940. catch(e) {}
  941. });
  942. };
  943. /*
  944. ---
  945. description: With mBox.Notice you can show little notices to your visitors.
  946. authors: Stephan Wagner
  947. license: MIT-style
  948. requires:
  949. - mBox
  950. - core/1.4.5: '*'
  951. - more/Element.Measure
  952. provides: [mBox.Notice]
  953. documentation: http://htmltweaks.com/mBox/Documentation/Notice
  954. ...
  955. */
  956. mBox.Notice = new Class({
  957. Extends: mBox,
  958. options: {
  959. type: 'Default', // the type of the notice (defaults to 'default'), possible types are: 'ok', 'error', 'info', 'notice'
  960. position: { // to use the move tween (see below), position.y has to be 'bottom' or 'top' and both positions need to be 'inside'
  961. x: ['left', 'inside'],
  962. y: ['bottom', 'inside']
  963. },
  964. offset: {
  965. x: 30,
  966. y: 30
  967. },
  968. fixed: true,
  969. move: true, // true will move the notice box from a window edge to its position instead of fading it (when opening)
  970. moveDuration: 500, // duration of the move-tween
  971. delayClose: 4000, // duration the notice will be visible
  972. fade: true,
  973. fadeDuration: {
  974. open: 250,
  975. close: 400
  976. },
  977. target: $(window),
  978. zIndex: 1000000,
  979. closeOnEsc: false,
  980. closeOnBoxClick: true,
  981. closeOnBodyClick: false,
  982. openOnInit: true
  983. },
  984. // initialize parent
  985. initialize: function(options) {
  986. this.defaultInOut = 'inside';
  987. this.defaultTheme = 'Notice';
  988. // add move events / options when initializing parent
  989. options.onSystemBoxReady = function() {
  990. this.container.addClass('mBoxNotice' + (this.options.type.capitalize() || 'Default'));
  991. if(this.options.move && (this.position.x[1] == 'inside' || this.position.x[0] == 'center') && this.position.y[1] == 'inside' && (this.position.y[0] == 'top' || this.position.y[0] == 'bottom')) {
  992. var wrapper_dimensions = this.wrapper.getDimensions({computeSize: true});
  993. this.container.setStyle('position', 'absolute');
  994. this.container.setStyle((this.position.y[0] == 'top' ? 'bottom' : 'top'), 0);
  995. this.wrapper.setStyles({
  996. height: 0,
  997. width: wrapper_dimensions.totalWidth,
  998. overflowY: 'hidden'
  999. });
  1000. this.options.transition = {
  1001. open: {
  1002. transition: 'linear',
  1003. property: 'height',
  1004. duration: this.options.moveDuration,
  1005. start: 0,
  1006. end: wrapper_dimensions.totalHeight + this.options.offset.y
  1007. }
  1008. };
  1009. this.options.offset.y = 0;
  1010. this.options.delayClose += this.options.moveDuration;
  1011. }
  1012. };
  1013. // close stored notice and save new one in window
  1014. options.onSystemOpen = function() {
  1015. if($(window).retrieve('mBoxNotice')) {
  1016. $(window).retrieve('mBoxNotice').ignoreDelay = true;
  1017. $(window).retrieve('mBoxNotice').close();
  1018. }
  1019. $(window).store('mBoxNotice', this);
  1020. };
  1021. // close notice automatically
  1022. options.onSystemOpenComplete = function() {
  1023. this.close();
  1024. };
  1025. // destroy notice when close is complete
  1026. options.onSystemCloseComplete = function() {
  1027. this.destroy();
  1028. };
  1029. // init parent
  1030. this.parent(options);
  1031. }
  1032. });