author | Dan |
Tue, 14 Apr 2009 21:02:13 -0400 | |
changeset 909 | 94c1ff984286 |
parent 906 | c949e82b8f49 |
child 1091 | bb8e04f74819 |
permissions | -rw-r--r-- |
// Message box and visual effect system /** * The ultimate message box framework for Javascript * Syntax is (almost) identical to the MessageBox command in NSIS * @param int type - a bitfield consisting of the MB_* constants * @param string title - the blue text at the top of the window * @param string text - HTML for the body of the message box * Properties: * onclick - an array of functions to be called on button click events * NOTE: key names are to be strings, and they must be the value of the input, CaSe-SeNsItIvE * onbeforeclick - same as onclick but called before the messagebox div is destroyed * Methods: * destroy: kills the running message box * Example: * var my_message = new MessageBox(MB_OK|MB_ICONSTOP, 'Error logging in', 'The username and/or password is incorrect. Please check the username and retype your password'); * my_message.onclick['OK'] = function() { * document.getElementById('password').value = ''; * }; * Deps: * Modern browser that supports DOM * darken() and enlighten() (above) * opacity() - required for darken() and enlighten() * MB_* constants are defined in enano-lib-basic.js */ var mb_current_obj; var mb_previously_had_darkener = false; function MessageBox(type, title, message) { if ( !aclDisableTransitionFX ) { load_component('flyin'); } var y = getScrollOffset(); // Prevent multiple instances if ( document.getElementById('messageBox') ) return; if ( document.getElementById('specialLayer_darkener') ) if ( document.getElementById('specialLayer_darkener').style.display == 'block' ) mb_previously_had_darkener = true; if ( !mb_previously_had_darkener ) darken(true); if ( aclDisableTransitionFX ) { document.getElementById('specialLayer_darkener').style.zIndex = '5'; } var master_div = document.createElement('div'); master_div.style.zIndex = getHighestZ() + 1; var mydiv = document.createElement('div'); mydiv.style.height = '200px'; w = getWidth(); h = getHeight(); if ( aclDisableTransitionFX ) { master_div.style.left = ((w / 2) - 200)+'px'; master_div.style.top = ((h / 2) + y - 120)+'px'; master_div.style.position = 'absolute'; } else { master_div.style.top = '-10000px'; master_div.style.position = ( IE ) ? 'absolute' : 'fixed'; } z = ( aclDisableTransitionFX ) ? document.getElementById('specialLayer_darkener').style.zIndex : getHighestZ(); mydiv.style.backgroundColor = '#FFFFFF'; mydiv.style.padding = '10px'; mydiv.style.marginBottom = '1px'; mydiv.id = 'messageBox'; mydiv.style.overflow = 'auto'; var buttondiv = document.createElement('div'); mydiv.style.width = '400px'; buttondiv.style.width = '400px'; w = getWidth(); h = getHeight(); if ( aclDisableTransitionFX ) { //buttondiv.style.left = ((w / 2) - 200)+'px'; //buttondiv.style.top = ((h / 2) + y + 101)+'px'; } //buttondiv.style.position = ( IE ) ? 'absolute' : 'fixed'; z = ( aclDisableTransitionFX ) ? document.getElementById('specialLayer_darkener').style.zIndex : getHighestZ(); buttondiv.style.backgroundColor = '#C0C0C0'; buttondiv.style.padding = '10px'; buttondiv.style.textAlign = 'right'; buttondiv.style.verticalAlign = 'middle'; buttondiv.id = 'messageBoxButtons'; this.clickHandler = function() { messagebox_click(this, mb_current_obj); }; if( ( type & MB_ICONINFORMATION || type & MB_ICONSTOP || type & MB_ICONQUESTION || type & MB_ICONEXCLAMATION ) && !(type & MB_ICONLOCK) ) { mydiv.style.paddingLeft = '50px'; mydiv.style.width = '360px'; mydiv.style.backgroundRepeat = 'no-repeat'; mydiv.style.backgroundPosition = '8px 8px'; } else if ( type & MB_ICONLOCK ) { mydiv.style.paddingLeft = '50px'; mydiv.style.width = '360px'; mydiv.style.backgroundRepeat = 'no-repeat'; } if(type & MB_ICONINFORMATION) { mydiv.style.backgroundImage = 'url(\''+scriptPath+'/images/info.png\')'; } if(type & MB_ICONQUESTION) { mydiv.style.backgroundImage = 'url(\''+scriptPath+'/images/question.png\')'; } if(type & MB_ICONSTOP) { mydiv.style.backgroundImage = 'url(\''+scriptPath+'/images/error.png\')'; } if(type & MB_ICONEXCLAMATION) { mydiv.style.backgroundImage = 'url(\''+scriptPath+'/images/warning.png\')'; } if(type & MB_ICONLOCK) { mydiv.style.backgroundImage = 'url(\''+scriptPath+'/images/lock.png\')'; } if(type & MB_OK) { btn = document.createElement('input'); btn.type = 'button'; btn.value = $lang.get('etc_ok'); btn._GenericName = 'OK'; btn.onclick = this.clickHandler; btn.style.margin = '0 3px'; buttondiv.appendChild(btn); } if(type & MB_OKCANCEL) { btn = document.createElement('input'); btn.type = 'button'; btn.value = $lang.get('etc_ok'); btn._GenericName = 'OK'; btn.onclick = this.clickHandler; btn.style.margin = '0 3px'; buttondiv.appendChild(btn); btn = document.createElement('input'); btn.type = 'button'; btn.value = $lang.get('etc_cancel'); btn._GenericName = 'Cancel'; btn.onclick = this.clickHandler; btn.style.margin = '0 3px'; buttondiv.appendChild(btn); } if(type & MB_YESNO) { btn = document.createElement('input'); btn.type = 'button'; btn.value = $lang.get('etc_yes'); btn._GenericName = 'Yes'; btn.onclick = this.clickHandler; btn.style.margin = '0 3px'; buttondiv.appendChild(btn); btn = document.createElement('input'); btn.type = 'button'; btn.value = $lang.get('etc_no'); btn._GenericName = 'No'; btn.onclick = this.clickHandler; btn.style.margin = '0 3px'; buttondiv.appendChild(btn); } if(type & MB_YESNOCANCEL) { btn = document.createElement('input'); btn.type = 'button'; btn.value = $lang.get('etc_yes'); btn._GenericName = 'Yes'; btn.onclick = this.clickHandler; btn.style.margin = '0 3px'; buttondiv.appendChild(btn); btn = document.createElement('input'); btn.type = 'button'; btn.value = $lang.get('etc_no'); btn._GenericName = 'No'; btn.onclick = this.clickHandler; btn.style.margin = '0 3px'; buttondiv.appendChild(btn); btn = document.createElement('input'); btn.type = 'button'; btn.value = $lang.get('etc_cancel'); btn._GenericName = 'Cancel'; btn.onclick = this.clickHandler; btn.style.margin = '0 3px'; buttondiv.appendChild(btn); } heading = document.createElement('h2'); heading.innerHTML = title; heading.style.color = '#50A0D0'; heading.style.fontFamily = 'trebuchet ms, verdana, arial, helvetica, sans-serif'; heading.style.fontSize = '12pt'; heading.style.fontWeight = 'lighter'; heading.style.textTransform = 'lowercase'; heading.style.marginTop = '0'; mydiv.appendChild(heading); var text = document.createElement('div'); text.innerHTML = String(message); this.text_area = text; mydiv.appendChild(text); this.updateContent = function(text) { this.text_area.innerHTML = text; }; this.destroy = function() { var mbdiv = document.getElementById('messageBox'); mbdiv.parentNode.removeChild(mbdiv.nextSibling); mbdiv.parentNode.removeChild(mbdiv); if ( !mb_previously_had_darkener ) enlighten(true); }; //domObjChangeOpac(0, mydiv); //domObjChangeOpac(0, master_div); body = document.getElementsByTagName('body'); body = body[0]; master_div.appendChild(mydiv); master_div.appendChild(buttondiv); body.appendChild(master_div); if ( !aclDisableTransitionFX ) setTimeout('mb_runFlyIn();', 100); this.onclick = new Array(); this.onbeforeclick = new Array(); mb_current_obj = this; } var messagebox = MessageBox; function mb_runFlyIn() { var mydiv = document.getElementById('messageBox'); var maindiv = mydiv.parentNode; fly_in_top(maindiv, true, false); } function messagebox_click(obj, mb) { val = ( typeof ( obj._GenericName ) == 'string' ) ? obj._GenericName : obj.value; if(typeof mb.onbeforeclick[val] == 'function') { var o = mb.onbeforeclick[val]; var resp = o(); if ( resp ) return false; o = false; } var mydiv = document.getElementById('messageBox'); var maindiv = mydiv.parentNode; if ( aclDisableTransitionFX ) { var mbdiv = document.getElementById('messageBox'); mbdiv.parentNode.removeChild(mbdiv.nextSibling); mbdiv.parentNode.removeChild(mbdiv); if ( !mb_previously_had_darkener ) enlighten(true); } else { var to = fly_out_top(maindiv, true, false); setTimeout("var mbdiv = document.getElementById('messageBox'); mbdiv.parentNode.removeChild(mbdiv.nextSibling); mbdiv.parentNode.removeChild(mbdiv); if ( !mb_previously_had_darkener ) enlighten(true);", to); } if(typeof mb.onclick[val] == 'function') { (mb.onclick[val])(); } } function testMessageBox() { mb = new MessageBox(MB_OKCANCEL|MB_ICONINFORMATION, 'Javascripted dynamic message boxes', 'This is soooooo coool, now if only document.createElement() worked in IE!<br />this is some more text<br /><br /><br /><br /><br />this is some more text<br /><br /><br /><br /><br />this is some more text<br /><br /><br /><br /><br />this is some more text<br /><br /><br /><br /><br />this is some more text<br /><br /><br /><br /><br />this is some more text<br /><br /><br /><br /><br />this is some more text<br /><br /><br /><br /><br />this is some more text'); mb.onclick['OK'] = function() { alert('You clicked OK!'); } mb.onbeforeclick['Cancel'] = function() { alert('You clicked Cancel!'); } } /** * The miniPrompt function, for creating small prompts and dialogs. The window will be flown in and the window darkened with opac=0.4. * @param function Will be passed an HTMLElement that is the body of the prompt window; the function can do with this as it pleases */ function miniPrompt(call_on_create) { if ( !aclDisableTransitionFX ) { load_component(['flyin', 'jquery', 'jquery-ui', 'fadefilter']); } else { load_component(['fadefilter']); } var darkener = darken(aclDisableTransitionFX, 40, 'miniprompt_darkener'); var wrapper = document.createElement('div'); wrapper.className = 'miniprompt'; var top = document.createElement('div'); top.className = 'mp-top'; var body = document.createElement('div'); body.className = 'mp-body'; var bottom = document.createElement('div'); bottom.className = 'mp-bottom'; if ( typeof(call_on_create) == 'function' ) { call_on_create(body); } wrapper.appendChild(top); wrapper.appendChild(body); wrapper.appendChild(bottom); var left = ( getWidth() / 2 ) - ( 388 / 2 ); wrapper.style.left = left + 'px'; var top = getScrollOffset() - 27; wrapper.style.top = top + 'px'; domObjChangeOpac(0, wrapper); var realbody = document.getElementsByTagName('body')[0]; realbody.appendChild(wrapper); if ( aclDisableTransitionFX ) { domObjChangeOpac(100, wrapper); } else { fly_in_top(wrapper, true, true); setTimeout(function() { domObjChangeOpac(100, wrapper); }, 40); } // set the darkener's onclick to refocus/shake the miniprompt darkener.miniprompt = wrapper; darkener.onclick = function() { if ( !aclDisableTransitionFX ) { $(this.miniprompt).effect("pulsate", { times: 2 }, 200); } } return wrapper; } /** * For a given element, loops through the element and all of its ancestors looking for a miniPrompt div, and returns it. Returns false on failure. * @param object:HTMLElement Child node to scan * @return object */ function miniPromptGetParent(obj) { while ( true ) { // prevent infinite loops if ( !obj || obj.tagName == 'BODY' ) return false; if ( $dynano(obj).hasClass('miniprompt') ) { return obj; } obj = obj.parentNode; } return false; } /** * Destroys the first miniPrompt div encountered by recursively checking all parent nodes. * Usage: <a href="javascript:miniPromptDestroy(this);">click</a> * @param object:HTMLElement a child of the div.miniprompt * @param bool (DEPRECATED) If true, does not call enlighten(). */ function miniPromptDestroy(obj, nofade) { obj = miniPromptGetParent(obj); if ( !obj ) return false; // found it var parent = obj.parentNode; // if ( !nofade ) // enlighten(aclDisableTransitionFX); enlighten((aclDisableTransitionFX || nofade), 'miniprompt_darkener'); if ( aclDisableTransitionFX || nofade ) { parent.removeChild(obj); } else { var timeout = fly_out_top(obj, true, true); setTimeout(function() { parent.removeChild(obj); }, timeout); } } /** * Simple test case */ function miniPromptTest() { miniPrompt(function(div) { div.innerHTML = 'hello world! <a href="#" onclick="miniPromptDestroy(this); return false;">destroy me</a>'; }); } /** * Message box system for miniPrompts. Less customization but easier to scale than the regular messageBox framework. * @example <code> miniPromptMessage({ title: 'Delete page', message: 'Do you really want to delete this page? This is reversible unless you clear the page logs.', buttons: [ { text: 'Delete', color: 'red', style: { fontWeight: 'bold' }, onclick: function() { ajaxDeletePage(); miniPromptDestroy(this); } }, { text: 'cancel', onclick: function() { miniPromptDestroy(this); } } ] }); </code> */ function miniPromptMessage(parms) { if ( ( !parms.title && !parms.message ) || !parms.buttons ) return false; return miniPrompt(function(parent) { try { if ( parms.title ) { var h3 = document.createElement('h3'); h3.appendChild(document.createTextNode(parms.title)); } if ( parms.message ) { var body = document.createElement('p'); var message = parms.message.split(unescape('%0A')); for ( var i = 0; i < message.length; i++ ) { body.appendChild(document.createTextNode(message[i])); if ( i + 1 < message.length ) body.appendChild(document.createElement('br')); } } parent.style.textAlign = 'center'; if ( parms.title ) parent.appendChild(h3); if ( parms.message ) parent.appendChild(body); parent.appendChild(document.createElement('br')); // construct buttons for ( var i = 0; i < parms.buttons.length; i++ ) { var button = parms.buttons[i]; button.input = document.createElement('a'); button.input.href = '#'; button.input.clickAction = button.onclick; button.input.className = 'abutton'; if ( button.color ) { button.input.className += ' abutton_' + button.color; } button.input.appendChild(document.createTextNode(button.text)); if ( button.style ) { for ( var j in button.style ) { button.input.style[j] = button.style[j]; } } if ( button.sprite ) { var sprite = gen_sprite(button.sprite[0], button.sprite[1], button.sprite[2], button.sprite[3], button.sprite[4]); sprite.style.position = 'relative'; sprite.style.top = '3px'; button.input.insertBefore(sprite, button.input.firstChild); insertAfter(button.input, document.createTextNode(' '), sprite); } else if ( button.image ) { button.input.className += ' icon'; button.input.style.backgroundImage = 'url(' + button.image + ')'; } button.input.onclick = function(e) { try { this.clickAction(e); } catch(e) { console.error(e); } return false; } parent.appendChild(button.input); } // don't focus this in opera - it looks kinda ugly if ( parms.buttons[0] && !window.opera ) { var timeout = ( aclDisableTransitionFX ) ? 10 : 1000; setTimeout(function() { parms.buttons[0].input.focus(); }, timeout); } } catch ( e ) { console.error(e); } }); } /** * Identical to whiteOutElement(), but safe to call on miniPrompt divs. */ function whiteOutMiniPrompt(el) { var top = getScrollOffset(); var left = ( getWidth() / 2 ) - ( 320 / 2); var width = 320; var height = $dynano(el).Height() - 58; var blackout = document.createElement('div'); // using fixed here allows modal windows to be blacked out blackout.style.position = ( el.style.position == 'fixed' ) ? 'fixed' : 'absolute'; blackout.style.top = top + 'px'; blackout.style.left = left + 'px'; blackout.style.width = width + 'px'; blackout.style.height = height + 'px'; blackout.style.backgroundColor = '#FFFFFF'; domObjChangeOpac(60, blackout); var background = ( $dynano(el).Height() < 48 ) ? 'url(' + scriptPath + '/images/loading.gif)' : 'url(' + scriptPath + '/includes/clientside/tinymce/themes/advanced/skins/default/img/progress.gif)'; blackout.style.backgroundImage = background; blackout.style.backgroundPosition = 'center center'; blackout.style.backgroundRepeat = 'no-repeat'; blackout.style.zIndex = '1000'; var body = document.getElementsByTagName('body')[0]; body.appendChild(blackout); return blackout; } function testMPMessageBox() { miniPromptMessage({ title: 'The Game of LIFE question #73', message: 'You just got your girlfriend pregnant. Please select an option:', buttons: [ { text: 'Abort', color: 'red', style: { fontWeight: 'bold' }, sprite: [ cdnPath + '/images/icons/abortretryignore-sprite.png', 16, 16, 0, 0 ], onclick: function() { miniPromptDestroy(this); } }, { text: 'Retry', color: 'blue', sprite: [ cdnPath + '/images/icons/abortretryignore-sprite.png', 16, 16, 0, 16 ], onclick: function() { miniPromptDestroy(this); } }, { text: 'Ignore', color: 'green', sprite: [ cdnPath + '/images/icons/abortretryignore-sprite.png', 16, 16, 0, 32 ], onclick: function() { miniPromptDestroy(this); } } ] }); }