1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315 |
- /*
- ---
- description: mBox is a powerful library, helping you to easily create tooltips, modal windows, notice messages and more.
- authors: Stephan Wagner
- license: MIT-style
- requires:
- - core/1.4.5: '*'
- - more/Element.Measure
- provides: [mBox]
- documentation: http://htmltweaks.com/mBox/Documentation
- ...
- */
- var mBox = new Class({
- Implements: [Options,Events],
- options: {
- id: '', // id of the mBox wrapper (defaults to mBox_1, mBox_2, mBox_3...)
- theme: '', // themes can be defined by css, e.g. in assets/themes/mBoxMyTheme.css
- addClass: { // add additional classes to wrapper, container, title and/or footer
- wrapper: '',
- container: '',
- content: '',
- title: '',
- footer: ''
- },
- setStyles: { // set additional styles to wrapper, container, title and/or footer
- wrapper: {},
- container: {},
- content: {},
- title: {},
- footer: {}
- },
- target: $(window), // element reference or element-id where the mBox will be opened (use 'mouse' to show mBox on mouse-position)
- attach: null, // element reference or element-id or element-classes of the elements which will open / close the mBox
- event: 'click', // the event which will trigger the mBox to show (can be: 'click' || 'mouseover' (= 'mouseenter'))
- preventDefault: false, // prevents the default action when clicking on attached item (e.g. prevents to follow a link when clicking on a link)
- //inject: null, // TODO element to inject the wrapper to (open and close will be disabled)
- width: 'auto', // width of the content area
- height: 'auto', // height of the content area
- zIndex: 8000, // z-index of wrapper
- content: null, // element reference or element-id or element classes to inject into the content, use a string to set a string as content
- setContent:
- 'data-setContent', // if the attached element has the attribute data-setContent it's value will be set as new content on open
- load: null, // set to ajax to load the content from url
- url: '', // the url to load the content from if load is set to ajax or iframe
- reload: false, // reloads the content each time the mBox is opened
- title: null, // adds a title (element reference, element-id or string)
- footer: null, // adds a footer (element reference, element-id or string)
- draggable: false, // mBox can be dragged when clicking on title
- position: {
- x: 'center', // horizontal position (use array to define outside or inside positions e.g. ['right', 'inside'] or ['left', 'center'])
- y: 'center' // vertical position (use array to define outside or inside positions e.g. ['top', 'inside'] or ['bottom', 'center'])
- }, // 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']
- fixed: null, // set to false to force mBox to be absolute or true to force mBox to be fixed
- offset: { // offsets to be added to position
- x: 0,
- y: 0
- },
- pointer: false, // set to true to show a pointer (at least one position value needs to be 'outside')
- // set to 'right', 'left', 'top', 'bottom' to adjust the pointers position
- // if you want to add an offset to the pointer, provide an array, e.g. ['left', 10]
- fade: { // set to false or 0 if you want to open/close the tooltip instantly (fade: false will open and close tooltip instantly)
- open: true,
- close: true
- },
- fadeDuration: { // default fade duration when opening or closing (set fadeDuration: 250 to use it for open and close)
- open: 200,
- close: 300
- },
- fadeWhenOpen: false, // set to true if you want to fade the mBox on open even if it's already open
- overlay: false, // adds a overlay just underneath the mBox to prevent clicks on body
- overlayStyles: { // set the color and the opacity of the overlay
- color: 'black',
- opacity: 0.75
- },
- overlayFadeDuration: 100, // default fade duration for the overlay
- transition: { // adds a transition when mBox is opened or closed, following shortcuts are availible:
- // transition: ['flyin', 'flyout', 'flyinout', 'flyoutin', 'bounce', 'bouncefly']
- open: null, // you can also define your own transitions by using mootools transitions:
- close: null // transition: {open: {transition: 'bounce:in', property: 'top', duration: 400, difference_start: 50, difference_end: 0}
- },
- closeOnEsc: true, // close mBox when pressing esc
- closeOnClick: false, // close mBox when clicking anywhere
- closeOnBoxClick: false, // close mBox when clicking on the mBox
- closeOnWrapperClick: false, // close mBox when clicking on the Wrapper of the mBox (wont close when clicking on children of mBox like title, content etc.)
- closeOnBodyClick: true, // close mBox when clicking anywhere except the mBox itself
- closeOnMouseleave: false, // close mBox when the mouse leaves the mBox area or the attached area
- closeInTitle: false, // adds a close button in the title area // TODO won't work in tooltip title yet
- //closeInContainer: false, // TODO add a close button to the container
- //closeInWindow: false, // TODO add a close button to the window
- delayOpen: 0, // delay opening the mBox in ms
- delayClose: 0, // delay closing the mBox in ms
- delayOpenOnce: true, // set to true if you want the delay to be ignored when the mBox didnt finish closing yet
- constructOnInit: true, // true will construct the mBox once its finished initializing
- openOnInit: false // true will construct (if it hasbn't been) and open the mBox once its finished initializing
- // Events:
- // onInit: function() {},
- // onOpen: function() {},
- // onOpenComplete: function() {},
- // onClose: function() {},
- // onCloseComplete: function() {}
- // onBoxReady: function() {}
- // onAjaxComplete: function() {}
- },
- // initialize
- initialize: function(options) {
- // set global vars
- this.block = false; // set this.block to true so the mBox wont be opened until set to false again
- this.ignoreDelay = false; // set this.ignoreDelay to true if you want to ignore the delays until set to false again
- this.ignoreDelayOnce = false; // set this.ignoreDelayOnce to true if you want to ignore the delay only for one closing / opening
- // set the options
- this.setOptions(options);
- // fix options addClass, setStyles, fade, fadeDuration
- this.fixOptions();
- this.getPosition();
- // save current target in this.target
- this.target = this.getTarget();
- // set fixed to true or false depending on target
- if (this.options.fixed == null) {
- this.options.fixed = [$(window), $(document), $(document.body)].contains(this.target);
- }
- // no pointer if target == 'mouse'
- if (this.target == 'mouse') { this.options.pointer = false; }
- // targets will be saved in this.targets
- this.targets = [];
- // get mBox id
- this.id = (this.options.id || 'mBox' + (++mBox.currentId));
- // add listeners to elements
- this.addListeners();
- // construct the mBox
- if(this.options.constructOnInit) {
- this.construct();
- }
- // fire onInit events
- this.fireEvent('init').fireEvent('systemInit');
- // open mBox on init
- if(this.options.openOnInit) {
- this.open();
- }
- // add this instance to global collector
- mBox.instances.push(this);
- },
- // re-initialize mBox (e.g. after an ajax call)
- reInit: function() {
- // add listeners to new elements
- this.addListeners();
- },
- // fix options
- fixOptions: function() {
- if(typeof this.options.addClass == 'string') {
- this.options.addClass = {
- wrapper: this.options.addClass
- };
- }
- 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) {
- this.options.setStyles = {
- wrapper: this.options.setStyles
- };
- }
- this.options.fade = {
- open: this.options.fade.open || (this.options.fade == true),
- close: this.options.fade.close || (this.options.fade == true)
- };
- this.options.fadeDuration = {
- open: this.options.fadeDuration.open || this.options.fadeDuration,
- close: this.options.fadeDuration.close || this.options.fadeDuration
- };
- },
- // contruct the mBox
- construct: function() {
- if(this.wrapper) {
- return null;
- }
- // create wrapper
- this.wrapper = new Element('div', {
- id: this.id,
- 'class': 'mBox ' + (this.defaultTheme || 'Core') + (this.options.theme ? '-' + this.options.theme : '') + ' ' + (this.options.addClass.wrapper || ''),
- styles: {
- zIndex: this.options.zIndex,
- position: (this.options.fixed == false || Browser.ie6 || Browser.ie7) ? 'absolute' : 'fixed',
- display: 'none',
- opacity: 0.00001,
- top: -12000,
- left: -12000,
- zoom: 1
- }
- //}).setStyles(this.options.setStyles.wrapper || {}).inject(document.body, 'bottom');
- }).setStyles(this.options.setStyles.wrapper || {});
- var target = $(target) || target || this.target || $(this.options.target) || this.options.target || $(this.options.attach);
- if (target && typeOf(target)==="element"){
- this.wrapper.inject(target, "after");
- }else{
- this.wrapper.inject(document.body, 'bottom');
- }
- // add mouse events to wrapper
- if(this.options.closeOnMouseleave) {
- this.wrapper.addEvents({
- mouseenter: function(ev) {
- this.open();
- }.bind(this),
- mouseleave: function(ev) {
- this.close();
- }.bind(this)
- });
- }
- // create container (contains content, title, footer)
- this.container = new Element('div', {
- 'class': 'mBoxContainer' + ' ' + (this.options.addClass.container || '')
- }).setStyles(this.options.setStyles.container || {}).inject(this.wrapper);
- // create content
- this.content = new Element('div', {
- 'class': 'mBoxContent' + ' ' + (this.options.addClass.content || ''),
- styles: {
- width: this.options.width,
- height: this.options.height
- }
- }).setStyles(this.options.setStyles.content || {}).inject(this.container);
- // load content into mBox
- this.load(this.options.content, this.options.title, this.options.footer, true); // TODO whats the true for?
- // fire boxReady events
- this.fireEvent('systemBoxReady').fireEvent('boxReady');
- },
- // add event listerners to elements
- addListeners: function(el) {
- // get elements to add events to, if none given use this.options.attach
- el = el || this.options.attach;
- elements = Array.convert($(el)).combine(Array.convert($$('.' + el))).combine(Array.convert($$(el))).clean();
- if(!elements || elements.length == 0) return this;
- // add elements to this.targets
- this.targets.combine(elements);
- // create click or mouseenter/mouseleave events
- switch(this.options.event) {
- case 'mouseenter':
- case 'mouseover':
- var events = {
- mouseenter: function(ev) {
- this.target = this.getTargetFromEvent(ev);
- this.source = this.getTargetElementFromEvent(ev);
- this.open();
- }.bind(this),
- mouseleave: function(ev) {
- this.close();
- }.bind(this)
- };
- break;
- default:
- var events = {
- click: function(ev) {
- if(this.options.preventDefault) {
- ev.preventDefault();
- }
- if(this.isOpen) {
- this.close();
- } else {
- this.target = this.getTargetFromEvent(ev);
- this.source = this.getTargetElementFromEvent(ev);
- this.open();
- }
- }.bind(this)
- };
- }
- // add events if not already added
- $$(elements).each(function(el) {
- if(!el.retrieve('mBoxElementEventsAdded' + this.id)) {
- el.addEvents(events).store('mBoxElementEventsAdded' + this.id, true);
- }
- }.bind(this));
- },
- // load content with ajax into mBox
- loadAjax: function(sendObj) {
- if(!this.ajaxRequest) {
- this.ajaxRequest = new Request.HTML({
- link: 'cancel',
- update: this.content,
- onRequest: function() {
- this.setContent('');
- this.wrapper.addClass('mBoxLoading');
- }.bind(this),
- onComplete: function() {
- this.wrapper.removeClass('mBoxLoading');
- if(this.options.width == 'auto' || this.options.height == 'auto') {
- this.setPosition();
- }
- this.fireEvent('ajaxComplete');
- }.bind(this)
- }).send();
- }
- this.ajaxRequest.send(sendObj);
- this.ajaxLoaded = true;
- },
- // open / show the mBox
- open: function(options) {
- if(!this.wrapper) {
- // construct the mBox
- this.construct();
- }
- if(typeof options != 'object') options = {};
- clearTimeout(this.timer);
- if(!this.isOpen && !this.block) {
- var complete = function() {
- this.ignoreDelayOnce = false;
- this.fireEvent('systemOpenComplete').fireEvent('openComplete');
- }.bind(this);
- var open = function(complete) {
- this.isOpen = true;
- // load content from ajax
- if(this.options.load == 'ajax' && this.options.url && (!this.ajaxLoaded || this.options.reload)) {
- this.loadAjax({url: this.options.url});
- }
- // set target
- this.target = this.getTarget(options.target || null);
- // set new content
- if (this.options.setContent && this.source && this.source.getAttribute(this.options.setContent)) {
- if ($(this.source.getAttribute(this.options.setContent))) {
- this.content.getChildren().setStyle('display', 'none');
- $(this.source.getAttribute(this.options.setContent)).setStyle('display', '');
- } else {
- var attribute_array = this.source.getAttribute(this.options.setContent).split('|'),
- content = attribute_array[0] || null,
- title = attribute_array[1] || null,
- footer = attribute_array[2] || null;
- this.load(content, title, footer);
- }
- }
- if (this.wrapper) this.wrapper.inject(document.body, 'bottom');
- // set new position
- this.setPosition(null, options.position || null, options.offset || null);
- // fire open events
- this.fireEvent('systemOpen').fireEvent('open');
- // fade mBox
- if(this.fx) { this.fx.cancel(); }
- this.wrapper.setStyles({
- display: ''
- });
- if(this.options.fadeWhenOpen) {
- this.wrapper.setStyle('opacity', 0);
- }
- this.fx = new Fx.Tween(this.wrapper, {
- property: 'opacity',
- duration: this.options.fadeDuration.open,
- link: 'cancel',
- onComplete: complete
- })[(options.instant || !this.options.fade.open) ? 'set' : 'start'](1);
- // call complete function when showing instantly
- if(options.instant || !this.options.fade.open) {
- complete();
- }
- // start additional transition
- var transition = this.getTransition();
- if(transition.open) {
- var fx = new Fx.Tween(this.wrapper, {
- property: transition.open.property || 'top',
- duration: transition.open.duration || this.options.fadeDuration.open,
- transition: transition.open.transition || null,
- onStart: transition.open.onStart || null,
- onComplete: transition.open.onComplete || null
- });
- fx.start((transition.open.start || (this.wrapper.getStyle(transition.open.property || 'top').toInt() + (transition.open.difference_start || 0))),
- (transition.open.end || (this.wrapper.getStyle(transition.open.property || 'top').toInt() + (transition.open.difference_end || 0))));
- }
- // attach events to document and window
- this.attachEvents();
- // add overlay
- if(this.options.overlay) {
- this.addOverlay((options.instant || !this.options.fade.open));
- }
- // set delay open once to true, set to false again when closing is finished
- if(this.options.delayOpenOnce) {
- this.delayOpenOnce = true;
- }
- }.bind(this);
- // delay open or close instantly
- if(this.options.delayOpen > 0 && !this.ignoreDelay && !this.ignoreDelayOnce && !this.delayOpenOnce) {
- this.timer = open.delay(this.options.delayOpen, this, complete);
- } else {
- open(complete);
- }
- }
- return this;
- },
- // close / hide the mBox
- close: function(options) {
- if(typeof options != 'object') options = {};
- clearTimeout(this.timer);
- if(this.isOpen && !this.block) {
- var complete = function() {
- this.delayOpenOnce = false;
- this.ignoreDelayOnce = false;
- this.wrapper.setStyle('display', 'none');
- this.fireEvent('systemCloseComplete').fireEvent('closeComplete');
- if (this.wrapper){
- var target = this.target || $(this.options.target) || this.options.target || $(this.options.attach);
- if (target && typeOf(target)==="element"){
- this.wrapper.inject(target);
- }
- }
- }.bind(this);
- var close = function(complete) {
- this.isOpen = false;
- // fire close events
- this.fireEvent('systemClose').fireEvent('close');
- // detach document and window events
- this.detachEvents();
- // remove overlay
- if(this.options.overlay) {
- this.removeOverlay((options.instant || !this.options.fade.close));
- }
- // fade mBox
- if(this.fx) { this.fx.cancel(); }
- this.fx = new Fx.Tween(this.wrapper, {
- property: 'opacity',
- duration: this.options.fadeDuration.close,
- link: 'cancel',
- onComplete: complete
- })[(options.instant || !this.options.fade.close) ? 'set' : 'start'](0);
- // call complete function when hiding instantly
- if(options.instant || !this.options.fade.close) {
- complete();
- }
- // start additionel transition
- var transition = this.getTransition();
- if(transition.close) {
- var fx = new Fx.Tween(this.wrapper, {
- property: transition.close.property || 'top',
- duration: transition.close.duration || this.options.fadeDuration.close,
- transition: transition.close.transition || null,
- onStart: transition.open.onStart || null,
- onComplete: transition.open.onComplete || null
- });
- fx.start((transition.close.start || (this.wrapper.getStyle(transition.close.property || 'top').toInt() + (transition.close.difference_start || 0))),
- (transition.close.end || (this.wrapper.getStyle(transition.close.property || 'top').toInt() + (transition.close.difference_end || 0))));
- }
- }.bind(this);
- // delay close or close instantly
- if(this.options.delayClose > 0 && !this.ignoreDelay && !this.ignoreDelayOnce) {
- this.timer = close.delay(this.options.delayClose, this, complete);
- } else {
- close(complete);
- }
- }
- return this;
- },
- // adds a overlay just beneath the mBox to prevent clicks on body
- addOverlay: function(instant) {
- if(!this.overlay) {
- this.overlay = new Element('div', { styles: {
- position: 'fixed',
- top: 0,
- left: 0,
- width: '100%',
- height: '100%',
- zIndex: (this.wrapper.getStyle('zIndex') - 1),
- background: this.options.overlayStyles.color || 'white',
- opacity: 0.001,
- display: 'none'
- }}).set('tween', {
- duration: this.options.overlayFadeDuration,
- link: 'cancel'
- }).inject($(document.body), 'bottom');
- }
- this.overlay.setStyle('display', 'block')[instant ? 'set' : 'tween']('opacity', (this.options.overlayStyles.opacity || 0.001));
- return this;
- },
- // remove the overlay
- removeOverlay: function(instant) {
- if(this.overlay) {
- this.overlay[instant ? 'set' : 'tween']('opacity', 0).get('tween').chain(function() {
- this.overlay.setStyle('display', 'none');
- }.bind(this));
- }
- return this;
- },
- // get the current or given target
- getTarget: function(target) {
- var target = $(target) || target || this.target || $(this.options.target) || this.options.target || $(this.options.attach);
- return target == 'mouse' ? 'mouse' : this.fixOperaPositioning($(target));
- },
- // get the target element from event target
- getTargetFromEvent: function(ev) {
- if(this.options.target) return this.fixOperaPositioning($(this.options.target));
- return this.getTargetElementFromEvent(ev);
- },
- // get the attached element from event
- getTargetElementFromEvent: function(ev) {
- if(ev && ev.target) {
- if(this.targets.contains(ev.target)) return this.fixOperaPositioning(ev.target);
- var parent_element = ev.target.getParent();
- while(parent_element != null) {
- if(this.targets.contains(parent_element)) {
- return this.fixOperaPositioning(parent_element);
- }
- parent_element = parent_element.getParent();
- }
- }
- return null;
- },
- // TEMP: This function fixes temporarily the mootools 1.4.5 positioning bug in opera
- fixOperaPositioning: function(el) {
- if($(el) && !$(el).retrieve('OperaBugFixed') && el != window) {
- try {
- 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())) {
- $(el).setStyle('border', 0);
- }
- }
- catch(e) {}
- $(el).store('OperaBugFixed');
- }
- return el;
- },
- // get cached variable position or get a clean position variable
- getPosition: function(position) {
- if(!position && this.position) return this.position;
- position = position || this.options.position;
- this.position = {};
- // TODO shortcuts 'top' 'topRight' 'bottomLeft' etc.
- // get a clean x-position
- this.position.x = (typeof position == 'object' && typeof position.x == 'number') ?
- [position.x.toInt(), null] : ((typeof position != 'object' || !position.x || position.x == 'center' || (typeof position.x == 'object' && position.x[0] == 'center')) ?
- ['center', null] : (['right', 'left'].contains(position.x) ?
- [position.x, (this.defaultInOut || 'inside')] : ((typeof position.x == 'object' && ['right', 'left'].contains(position.x[0])) ?
- [position.x[0], (['inside', 'center', 'outside'].contains(position.x[1]) ? position.x[1] : (this.defaultInOut || 'inside'))] : ['center', null])));
- this.position.xAttribute = (this.position.x[3] == 'right' || (this.position.x[1] == 'inside' && this.position.x[0] == 'right')) ? 'right' : 'left';
- // get a clean y-position
- this.position.y = (typeof position == 'object' && typeof position.y == 'number') ?
- [position.y.toInt(), null] : ((typeof position != 'object' || !position.y || position.y == 'center' || (typeof position.y == 'object' && position.y[0] == 'center')) ?
- ['center', null] : (['top', 'bottom'].contains(position.y) ?
- [position.y, (this.defaultInOut || 'inside')] : ((typeof position.y == 'object' && ['top', 'bottom'].contains(position.y[0])) ?
- [position.y[0], (['inside', 'center', 'outside'].contains(position.y[1]) ? position.y[1] : (this.defaultInOut || 'inside'))] : ['center', null])));
- this.position.yAttribute = (this.position.x[3] == 'bottom' || (this.position.y[1] == 'inside' && this.position.y[0] == 'bottom')) ? 'bottom' : 'top';
- return this.position;
- },
- // get cached offset variable or get a clean one
- getOffset: function(offset) {
- if(!offset && this.offset) return this.offset;
- offset = offset || this.options.offset;
- this.offset = {};
- this.offset.x = (typeof offset == 'number') ? offset : (!offset.x ? 0 : (offset.x.toInt() >= 0 || offset.x.toInt() < 0) ? offset.x.toInt() : 0);
- this.offset.y = (typeof offset == 'number') ? offset : (!offset.y ? 0 : (offset.y.toInt() >= 0 || offset.y.toInt() < 0) ? offset.y.toInt() : 0);
- return this.offset;
- },
- // get cached pointer variable or get a clean one
- getPointer: function(pointer) {
- if(!pointer && this.pointer) return this.pointer;
- pointer = pointer || this.options.pointer;
- if(!pointer) return false;
- var position = this.getPosition();
- this.pointer = {};
- if(position.y[1] == 'outside') {
- this.pointer.position = (position.y[0] == 'bottom') ? 'top' : 'bottom';
- this.pointer.adjustment = (typeof pointer == 'object' && ['center', 'right', 'left'].contains(pointer[0])) ? pointer[0] : (['center', 'right', 'left'].contains(pointer) ? pointer : 'center');
- } else if(position.x[1] == 'outside') {
- this.pointer.position = (position.x[0] == 'left') ? 'right' : 'left';
- this.pointer.adjustment = (typeof pointer == 'object' && ['center', 'top', 'bottom'].contains(pointer[0])) ? pointer[0] : (['center', 'top', 'bottom'].contains(pointer) ? pointer : 'center');
- } else {
- return null;
- }
- this.pointer.offset = (typeof pointer == 'object' && pointer[1] && typeof(pointer[1].toInt()) == 'number') ? pointer[1].toInt() : 0;
- // TODO pointer with inside && inside should be possible
- // TODO minimum offset if the container has a border-radius (this.container.getStyle('border-top-left-radius');
- this.pointer.offset = this.pointer.offset < 0 ? this.pointer.offset * (-1) : this.pointer.offset;
- this.pointer.offset = (this.pointer.adjustment == 'right' || this.pointer.adjustment == 'bottom') ? this.pointer.offset * (-1) : this.pointer.offset;
- return this.pointer;
- },
- // get cached transition variable or get a clean one
- getTransition: function() {
- if(this.transition) return this.transition;
- if(this.options.transition && ['flyin', 'flyout', 'flyinout', 'flyoutin', 'bounce', 'bouncein', 'bounceout', 'bounceinout', 'bouncefly'].contains(this.options.transition)) {
- this.transition = {};
- this.transition.open = {
- property: (this.position.yAttribute == 'top' || this.position.yAttribute == 'bottom') ? this.position.yAttribute : this.position.xAttribute,
- transition: 'quad:out',
- duration: 300
- }
- this.transition.close = Object.clone(this.transition.open);
- var distance = (20 * (this.position.yAttribute == 'bottom' || this.position.xAttribute == 'right' ? -1 : 1));
- switch(this.options.transition) {
- case 'flyin': // TODO flyin should only flyin
- case 'flyout':
- this.transition.open.difference_start = this.transition.close.difference_end = distance * (this.options.transition == 'flyin' ? (-1) : 1);
- break;
- case 'flyinout':
- case 'flyoutin':
- distance = (distance * (this.options.transition == 'flyinout' ? 1 : (-1)));
- this.transition.open.difference_start = distance * (-1);
- this.transition.close.difference_end = distance;
- break;
- case 'bounce':
- case 'bouncefly':
- case 'bouncein':
- case 'bounceout':
- case 'bounceinout':
- this.transition.open.transition = 'bounce:out';
- this.transition.open.duration = 450;
- this.transition.open.difference_start = distance * (-1);
- if(this.options.transition == 'bounceinout' || this.options.transition == 'bounceout' || this.options.transition == 'bouncefly') {
- this.transition.close.difference_end = distance * (-1);
- }
- break;
- }
- } else {
- this.transition = {};
- this.transition.open = typeof this.options.transition.open != undefined ? this.options.transition.open : this.options.transition;
- this.transition.close = typeof this.options.transition.close != undefined ? this.options.transition.close : this.options.transition;
- }
- return this.transition;
- },
- // position the mBox
- setPosition: function(target, position, offset) {
- // get variables
- target = this.getTarget(target);
- position = this.getPosition(position);
- offset = this.getOffset(offset);
- pointer = this.getPointer();
- // attach to mouse if target == 'mouse'
- if(target == 'mouse') {
- posX = ((this.mouseX || 0) + 15 + offset.x);
- posY = ((this.mouseY || 0) + 15 + offset.y);
- this.wrapper.setStyles({
- 'left': Math.floor(posX),
- 'top': Math.floor(posY)
- });
- return this;
- }
- // get dimensions and coordinates
- if(!target || [$(window), $(document), $(document.body)].contains(target)) {
- var windowScroll = this.wrapper.getStyle('position') == 'fixed' ? {x: 0, y: 0} : $(window).getScroll(),
- targetDimensions = $(window).getSize();
- targetDimensions.width = targetDimensions.totalWidth = targetDimensions.x;
- targetDimensions.height = targetDimensions.totalHeight = targetDimensions.y;
- var targetCoordinates = {
- top: windowScroll.y,
- left: windowScroll.x,
- right: windowScroll.x + targetDimensions.width,
- bottom: windowScroll.y + targetDimensions.height
- };
- } else {
- if(!this.options.fixed != true) {
- this.wrapper.setStyle('position', 'absolute');
- }
- var targetDimensions = target.getDimensions({computeSize: true});
- var targetCoordinates = target.getCoordinates();
- if(targetDimensions.totalWidth == 0) {
- targetDimensions.width = targetDimensions.totalWidth = targetCoordinates.width;
- targetDimensions.height = targetDimensions.totalHeight = targetCoordinates.height;
- }
- }
- // set position to current position of target
- var posX = targetCoordinates.left || 0,
- posY = targetCoordinates.top || 0;
- var wrapperDimensions = this.wrapper.getDimensions({computeSize: true});
- // create pointer if not already created
- if(pointer && !this.pointerElement) {
- this.pointerElement = new Element('div', {
- 'class': 'mBoxPointer ' + 'mBoxPointer' + pointer.position.capitalize(),
- styles: {position: 'absolute'}
- }).setStyle(pointer.position, 0).inject(this.wrapper, 'top');
- // opera wont calculate the size of the pointer correctly, needs to get fixed properly
- if(Browser.opera) {
- var tempContainer = new Element('div', {'class': 'mBox ' + (this.defaultTheme || 'Core') + (this.options.theme ? '-' + this.options.theme : '')}).inject(document.body).grab(this.pointerElement);
- this.pointerDimensions = this.pointerElement.getDimensions({computeSize: true});
- this.pointerElement.inject(this.wrapper, 'top');
- tempContainer.destroy();
- } else {
- this.pointerDimensions = this.pointerElement.getDimensions({computeSize: true});
- }
- this.container.setStyle('margin-' + pointer.position,
- (pointer.position == 'left' || pointer.position == 'right') ?
- (this.pointerDimensions.width - this.container.getStyle('border-' + pointer.position).toInt()) :
- (this.pointerDimensions.height - this.container.getStyle('border-' + pointer.position).toInt()));
- }
- // adjust wrapper to pointer position
- if(pointer && this.pointerElement) {
- // if position x and position y is outside, fix pointer position
- if(position.x[1] == 'outside' && position.y[1] == 'outside' && pointer.adjustment == 'center') {
- pointer.adjustment = (position.x[0] == 'left') ? 'right' : 'left';
- switch(position.x[0]) {
- case 'left':
- posX += wrapperDimensions.totalWidth - (this.pointerDimensions.width / 2);
- break;
- case 'right':
- posX -= (this.pointerDimensions.width / 2);
- break;
- }
- }
- // calculate pointer margin and extra offset
- var wrapperOffset = 0, pointerMargin = 0, offsetPointerX = 0, offsetPointerY = 0;
- switch(pointer.adjustment) {
- case 'center':
- pointerMargin = (pointer.position == 'top' || pointer.position == 'bottom') ? ((wrapperDimensions.totalWidth / 2) - (this.pointerDimensions.width / 2)) : ((wrapperDimensions.totalHeight / 2) - (this.pointerDimensions.height / 2));
- break;
- case 'left':
- case 'right':
- switch(position.x[1]) {
- case 'inside':
- offsetPointerX += ((this.pointerDimensions.width / 2) * -1) + ((position.x[0] == 'right') ? wrapperDimensions.totalWidth : 0);
- break;
- default:
- if(position.x[0] == 'center') {
- offsetPointerX += (wrapperDimensions.totalWidth / 2) - (this.pointerDimensions.width / 2);
- }
- }
- posX += offsetPointerX - ((pointer.adjustment == 'right') ? (wrapperDimensions.totalWidth - this.pointerDimensions.width) : 0);
- pointerMargin = (pointer.adjustment == 'right') ? (wrapperDimensions.totalWidth - this.pointerDimensions.width) : 0;
- break;
- case 'top':
- case 'bottom':
- switch(position.y[1]) {
- case 'inside':
- offsetPointerY += ((this.pointerDimensions.height / 2) * -1) + ((position.y[0] == 'bottom') ? wrapperDimensions.totalHeight : 0);
- break;
- default:
- if(position.y[0] == 'center') {
- offsetPointerY += (wrapperDimensions.totalHeight / 2) - (this.pointerDimensions.height / 2);
- }
- }
- posY += offsetPointerY - ((pointer.adjustment == 'bottom') ? (wrapperDimensions.totalHeight - this.pointerDimensions.height) : 0);
- pointerMargin = (pointer.adjustment == 'bottom') ? (wrapperDimensions.totalHeight - this.pointerDimensions.height) : 0;
- break;
- }
- switch(pointer.position) {
- case 'top':
- case 'bottom':
- posX += (pointer.offset * (-1));
- break;
- case 'left':
- case 'right':
- posY += (pointer.offset * (-1));
- break;
- }
- this.pointerElement.setStyle((pointer.position == 'top' || pointer.position == 'bottom') ? 'left' : 'top', pointerMargin + pointer.offset);
- }
- // get wrapper dimensions including pointer
- wrapperDimensions = this.wrapper.getDimensions({computeSize: true});
- // calculate position
- switch(position.x[0]) {
- case 'center':
- posX += (targetDimensions.totalWidth / 2) - (wrapperDimensions.totalWidth / 2);
- break;
- case 'right':
- posX += targetDimensions.totalWidth - (position.x[1] == 'inside' ? wrapperDimensions.totalWidth : (position.x[1] == 'center' ? (wrapperDimensions.totalWidth / 2) : 0));
- break;
- case 'left':
- posX -= (position.x[1] == 'outside' ? wrapperDimensions.totalWidth : (position.x[1] == 'center' ? (wrapperDimensions.totalWidth / 2) : 0));
- break;
- default:
- posX = position.x;
- }
- switch(position.y[0]) {
- case 'center':
- posY += (targetDimensions.totalHeight / 2) - (wrapperDimensions.totalHeight / 2);
- break;
- case 'bottom':
- posY += targetDimensions.totalHeight - (position.y[1] == 'inside' ? wrapperDimensions.totalHeight : (position.y[1] == 'center' ? (wrapperDimensions.totalHeight / 2) : 0));
- break;
- case 'top':
- posY -= (position.y[1] == 'outside' ? wrapperDimensions.totalHeight : (position.y[1] == 'center' ? (wrapperDimensions.totalHeight / 2) : 0));
- break;
- default:
- posX = position.y;
- }
- // reset wrapper positions
- this.wrapper.setStyles({top: null, right: null, bottom: null, left: null});
- // calculate 'bottom' or 'right' positions if needed
- var windowDimensions = $(window).getSize();
- if(position.xAttribute == 'right') {
- posX = windowDimensions.x - (posX + wrapperDimensions.totalWidth);
- }
- if(position.yAttribute == 'bottom') {
- posY = windowDimensions.y - (posY + wrapperDimensions.totalHeight);
- }
- // add global offsets and set positions
- posX = posX || 0;
- posX += offset.x;
- posY += offset.y;
- this.wrapper.setStyle(position.xAttribute, posX.floor());
- this.wrapper.setStyle(position.yAttribute, posY.floor());
- return this;
- },
- // set up content
- setContent: function(content, where) {
- if(content != null) {
- if($(content) || $$('.' + content).length > 0) {
- this[where || 'content'].grab($(content) || $$('.' + content));
- if($(content)) $(content).setStyle('display', '');
- } else if(content != null) {
- content = content.replace(/(?:<script[\s\S]*?)(?:(?:<\/script>)|(?:\/>))/gmi, '')
- content = content.replace(/<[^>]+/gmi, function(match){
- return match.replace(/ on\w+=[\"\'\S][^"]*[\"\'\S]/gmi, '').replace(/javascript/gmi, '');
- });
- this[where || 'content'].set('html', content);
- }
- }
- return this;
- },
- // set up title
- setTitle: function(content) {
- if(content != null && !this.titleContainer) {
- this.titleContainer = new Element('div', {
- 'class': 'mBoxTitleContainer'
- }).inject(this.container, 'top');
- this.title = new Element('div', {
- 'class': 'mBoxTitle ' + (this.options.addClass.title || ''),
- styles: (this.options.setStyles.title || {})
- }).inject(this.titleContainer);
- this.wrapper.addClass('hasTitle');
- if(this.options.draggable && window['Drag'] != null) {
- new Drag(this.wrapper, { handle: this.titleContainer});
- this.titleContainer.addClass('mBoxDraggable');
- }
- if(this.options.closeInTitle) {
- new Element('div', {
- 'class': 'mBoxClose',
- events: {
- click: function() {
- this.close();
- }.bind(this)
- }
- }).grab(new Element('div')).inject(this.titleContainer);
- }
- }
- if(content != null) {
- this.setContent(content, 'title');
- }
- return this;
- },
- // set up footer
- setFooter: function(content) {
- if(content != null && !this.footerContainer) {
- this.footerContainer = new Element('div', {
- 'class': 'mBoxFooterContainer'
- }).inject(this.container, 'bottom');
- this.footer = new Element('div', {
- 'class': 'mBoxFooter ' + (this.options.addClass.footer || ''),
- styles: (this.options.setStyles.footer || {})
- }).inject(this.footerContainer);
- this.wrapper.addClass('hasFooter');
- }
- if(content != null) {
- this.setContent(content, 'footer');
- }
- return this;
- },
- // set up content, title and/or footer
- load: function(content, title, footer) {
- this.setContent(content);
- this.setTitle(title);
- this.setFooter(footer);
- return this;
- },
- // return the mBox as html
- getHTML: function(content, title, footer) {
- this.load(content, title, footer);
- return '<div>' + this.wrapper.get('html') + '</div>';
- },
- // attach events to document and window
- attachEvents: function() {
- // event: close mBox when clicking esc
- this.escEvent = function(ev) {
- if(ev.key == 'esc') {
- this.ignoreDelayOnce = true;
- this.close();
- }
- }.bind(this);
- if(this.options.closeOnEsc) {
- $(window).addEvent('keyup', this.escEvent);
- }
- // event: reposition mBox on window resize or scroll
- this.resizeEvent = function(ev) {
- this.setPosition();
- }.bind(this);
- $(window).addEvent('resize', this.resizeEvent);
- if(this.options.fixed && (Browser.ie6 || Browser.ie7)) {
- $(window).addEvent('scroll', this.resizeEvent);
- }
- // event: close mBox when clicking anywhere
- this.closeOnClickEvent = function(ev) {
- if(this.isOpen && ($(this.options.attach) != ev.target && !$$('.' + this.options.attach).contains(ev.target))) {
- this.ignoreDelayOnce = true;
- this.close();
- }
- }.bind(this);
- if(this.options.closeOnClick) {
- $(document).addEvent('mouseup', this.closeOnClickEvent);
- }
- // event: close mBox when clicking on wrapper or it's children
- this.closeOnBoxClickEvent = function(ev) {
- if(this.isOpen && (this.wrapper == ev.target || this.wrapper.contains(ev.target))) {
- this.ignoreDelayOnce = true;
- this.close();
- }
- }.bind(this);
- if(this.options.closeOnBoxClick) {
- $(document).addEvent('mouseup', this.closeOnBoxClickEvent);
- }
- // event: close mBox when clicking on wrapper directly
- this.closeOnWrapperClickEvent = function(ev) {
- if(this.isOpen && this.wrapper == ev.target) {
- this.ignoreDelayOnce = true;
- this.close();
- }
- }.bind(this);
- if(this.options.closeOnWrapperClick) {
- $(document).addEvent('mouseup', this.closeOnWrapperClickEvent);
- }
- // event: close mBox when clicking on body
- this.closeOnBodyClickEvent = function(ev) {
- if(this.isOpen && ($(this.options.attach) != ev.target && !$$('.' + this.options.attach).contains(ev.target)) && ev.target != this.wrapper && !this.wrapper.contains(ev.target)) {
- this.ignoreDelayOnce = true;
- this.close();
- }
- }.bind(this);
- if(this.options.closeOnBodyClick) {
- $(document).addEvent('mouseup', this.closeOnBodyClickEvent);
- }
- // event: attach mBox to mouse position
- this.mouseMoveEvent = function(ev) {
- this.mouseX = ev.page.x;
- this.mouseY = ev.page.y;
- this.setPosition('mouse');
- }.bind(this);
- if(this.target == 'mouse') {
- $(document).addEvent('mousemove', this.mouseMoveEvent);
- }
- },
- // remove events from document or window
- detachEvents: function() {
- if(this.options.fixed && (Browser.ie6 || Browser.ie7)) {
- $(window).removeEvent('scroll', this.resizeEvent);
- }
- $(window).removeEvent('keyup', this.keyEvent);
- $(window).removeEvent('resize', this.resizeEvent);
- $(document).removeEvent('mouseup', this.closeOnClickEvent);
- $(document).removeEvent('mouseup', this.closeOnBoxClickEvent);
- $(document).removeEvent('mouseup', this.closeOnWrapperClickEvent);
- $(document).removeEvent('mouseup', this.closeOnBodyClickEvent);
- $(document).removeEvent('mousemove', this.mouseMoveEvent);
- },
- // dispose of wrapper and remove it from DOM
- destroy: function() {
- mBox.instances.erase(this);
- this.detachEvents();
- this.wrapper.dispose();
- delete this.wrapper;
- }
- });
- // store global mBox instances
- mBox.instances = [];
- // use global mBox ids
- mBox.currentId = 0;
- // reinit mBoxes (e.g. once an ajax has been called)
- mBox.reInit = function() {
- if(mBox.addConfirmEvents) {
- mBox.addConfirmEvents();
- }
- mBox.instances.each(function(instance) {
- try {
- instance.reInit();
- }
- catch(e) {}
- });
- };
- /*
- ---
- description: With mBox.Notice you can show little notices to your visitors.
- authors: Stephan Wagner
- license: MIT-style
- requires:
- - mBox
- - core/1.4.5: '*'
- - more/Element.Measure
- provides: [mBox.Notice]
- documentation: http://htmltweaks.com/mBox/Documentation/Notice
- ...
- */
- mBox.Notice = new Class({
- Extends: mBox,
- options: {
- type: 'Default', // the type of the notice (defaults to 'default'), possible types are: 'ok', 'error', 'info', 'notice'
- position: { // to use the move tween (see below), position.y has to be 'bottom' or 'top' and both positions need to be 'inside'
- x: ['left', 'inside'],
- y: ['bottom', 'inside']
- },
- offset: {
- x: 30,
- y: 30
- },
- fixed: true,
- move: true, // true will move the notice box from a window edge to its position instead of fading it (when opening)
- moveDuration: 500, // duration of the move-tween
- delayClose: 4000, // duration the notice will be visible
- fade: true,
- fadeDuration: {
- open: 250,
- close: 400
- },
- target: $(window),
- zIndex: 1000000,
- closeOnEsc: false,
- closeOnBoxClick: true,
- closeOnBodyClick: false,
- openOnInit: true
- },
- // initialize parent
- initialize: function(options) {
- this.defaultInOut = 'inside';
- this.defaultTheme = 'Notice';
- // add move events / options when initializing parent
- options.onSystemBoxReady = function() {
- this.container.addClass('mBoxNotice' + (this.options.type.capitalize() || 'Default'));
- 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')) {
- var wrapper_dimensions = this.wrapper.getDimensions({computeSize: true});
- this.container.setStyle('position', 'absolute');
- this.container.setStyle((this.position.y[0] == 'top' ? 'bottom' : 'top'), 0);
- this.wrapper.setStyles({
- height: 0,
- width: wrapper_dimensions.totalWidth,
- overflowY: 'hidden'
- });
- this.options.transition = {
- open: {
- transition: 'linear',
- property: 'height',
- duration: this.options.moveDuration,
- start: 0,
- end: wrapper_dimensions.totalHeight + this.options.offset.y
- }
- };
- this.options.offset.y = 0;
- this.options.delayClose += this.options.moveDuration;
- }
- };
- // close stored notice and save new one in window
- options.onSystemOpen = function() {
- if($(window).retrieve('mBoxNotice')) {
- $(window).retrieve('mBoxNotice').ignoreDelay = true;
- $(window).retrieve('mBoxNotice').close();
- }
- $(window).store('mBoxNotice', this);
- };
- // close notice automatically
- options.onSystemOpenComplete = function() {
- this.close();
- };
- // destroy notice when close is complete
- options.onSystemCloseComplete = function() {
- this.destroy();
- };
- // init parent
- this.parent(options);
- }
- });
- /*
- ---
- description: The mBox.Tooltip class extends mBox.Core, helping you to attach tooltips to any DOM element.
- authors: Stephan Wagner
- license: MIT-style
- requires:
- - mBox
- - core/1.4.5: '*'
- - more/Element.Measure
- provides: [mBox.Tooltip]
- documentation: http://htmltweaks.com/mBox/Documentation/Tooltip
- ...
- */
- mBox.Tooltip = new Class({
- Extends: mBox,
- options: {
- target: null,
- event: 'mouseenter',
- position: {
- x: ['center'],
- y: ['top', 'outside']
- },
- pointer: 'center',
- fixed: false,
- delayOpenOnce: true
- },
- // initialize parent
- initialize: function(options) {
- this.defaultInOut = 'outside';
- this.defaultTheme = 'Tooltip';
- this.parent(options);
- }
- });
|