wrjs.state = wrjs.state || {}; // *********************************************************** // MODAL // *********************************************************** wrjs.state.modalcount = 1; wrjs.View.Modal = function(options) { // ********************************************************************************** // CHECK FOR DUPLICATES // IF MODAL ALREADY EXISTS, BLOCK CREATION // ********************************************************************************** if(options && options.id) { var modal = $('#wrjs_modal_' + options.id); if(modal.length > 0) { return false; } }; // ********************************************************************************** // PRIVATE VARS // ********************************************************************************** var _defaults = { animate: true, // WHETHER TO SLIDE THE MODAL IN FROM THE TOP - NOW DEFAULTED TO TRUE body: 'Body content', // Description goes here... bodyAlign: 'center', // Description goes here... buttoncolor: 'green', // Description goes here... buttons: false, // Description goes here... canceltext: ls.text_cancel, // Description goes here... cancelCallback: false, // Description goes here... cls: '', // Description goes here... confirmtext: ls.text_confirm, // Description goes here... confirmCallback: false, // Description goes here... dontshowagain: false, // Description goes here... helpFunction: false, // Description goes here... id: wrjs.state.modalcount, // Description goes here... listeners: false, // Description goes here... maskCls: '', // Description goes here... preRenderer: false, // PRE RENDERERS ARE FOR THE SITUATION WHERE YOU MIGHT WANT TO RUN SOME FUNCTIONALITY AFTER BEING ADDED TO THE DOM, BUT BEFORE BEING MADE VISIBLE (e.g. set form defaults / show hide certain tabs, etc) renderTo: 'body', // Description goes here... speed: 500, // Description goes here... style: '', // Description goes here... title: 'Title', // Description goes here... width: false, // Description goes here... padding: 12 }; options = options || {}; // TEMPORARY FIX WHILST "additionalClasses" IS BEING DEPRECATED if(options.additionalClasses) { options.cls = options.additionalClasses; delete options.additionalClasses; }; var _config = $.extend(_defaults, options); // ********************************************************************************** // PRIVATE FUNCTIONS // ********************************************************************************** var _registerListeners = function() { if (_config.listeners != false) { wrjs.Event.eventManager.registerListeners(_config); } $('body').on('keyup', _keypress); $('body').on('click', '#wrjs_modal_' + _config.id + ' .tabs:not(.disabled) li:not(.selected) a', _pixelFix); }; var _buildView = function() { //console.log('_buildView - GRID') var html = ''; var textalign = ''; switch (_config.bodyAlign) { case 'left': textalign = 'textalign_left'; break; case 'right': textalign = 'textalign_right'; break; default: // DO NOTHING - ALREADY CENTERED } _config.cls += ' ' + textalign; // APPEND WIDTH INTO STYLE if(_config.width) { var widthunit = _config.width.toString().indexOf('%') > -1 ? '%' : 'px'; var wid = _config.width.toString().split('%')[0]; _config.style += ' width:' + wid + widthunit + ';' }; if (_config.cls.indexOf('red') != -1) { _config.buttoncolor = 'red'; }; if (_config.cls.indexOf('blue') != -1) { _config.buttoncolor = 'blue'; }; // ALLOW FOR GREY BUTTON BY PASSING 'none' if(_config.buttoncolor != 'none') { _config.buttoncolor += ' inverse' }; var dontshow = _config.dontshowagain ? ' ' : ''; var confirmbutton = '' + _config.confirmtext + ''; var cancelbutton = _config.canceltext != false ? '' + _config.canceltext + '' : ''; var helpbutton = _config.helpFunction != false ? '' : ''; var footerbuttons = confirmbutton + cancelbutton; if (_config.buttons != false) { var b = ''; $.each(_config.buttons, function (i, but) { // CREATE BUTTON var butid = but.id || 'button_text' + i; var style = but.style || ''; var buttoncls = but.cls || ''; b += '' + but.text + ''; // BIND HANDLER $(document).off('click', '#' + butid + ':not(.disabled)'); $(document).on('click', '#' + butid + ':not(.disabled)', function (e) { if (but.handler) { but.handler(this, modal, e); } else { modal.remove(); }; }); }) footerbuttons = b; } // *********************************************************************************** // BUILD POPUP // *********************************************************************************** if(_config.animate) { _config.cls += ' animate'; _config.maskCls += ' animate'; } var padding = 'style="padding:' + _config.padding + 'px;"'; var html = '
' + '

' + _config.title + '' + '' + helpbutton + '' + '

' + '
' + _config.body + '
' + ''; // *********************************************************************************** // BUILD MASK // *********************************************************************************** var maskCls = _config.maskCls ? _config.maskCls : ''; var m = '
'; // *********************************************************************************** // APPEND MASK AND POPUP // *********************************************************************************** $(_config.renderTo).append(m + html); $('html,body').addClass('has-modal'); var p = $('#wrjs_modal_' + _config.id); var msk = $('#wrjs_mask_' + _config.id); // ADD ON PIXEL IF HEIGHT IS ODD, DUE TO SUB-PIXEL RENDERING ISSUES _pixelFix() // Click the active tab to trigger the height check listener $('#usertabs .selected a', p).trigger('click'); // *********************************************************************************** // RUN ANY PRE-RENDER FUNCTION // *********************************************************************************** if (_config.preRenderer !== false) { _config.preRenderer(modal); } // *********************************************************************************** // POSITION AND DISPLAY POPUP // *********************************************************************************** if(_config.rapid) { p.show().css('opacity',1); msk.show().css('opacity',0.7); } else { if (_config.animate) { p.addClass('slideIn'); setTimeout(function(){ p.addClass('animated'); p.removeClass('slideIn animate'); }, 500); } else { setTimeout(function(){ p.addClass('fadeIn'); setTimeout(function(){ p.addClass('animated'); p.removeClass('fadeIn animated'); }, 500); }, 10); }; setTimeout(function(){ msk.addClass('fadeIn'); }, 10); }; // Focus the modal. But if there's an achor button then focus that, otherwise focus the first visible text field p.focus(); $('a.button:visible:first', p).focus(); $('input:visible:first', p).focus(); // *********************************************************************************** // CONFIRMCLICK // *********************************************************************************** $('body').on('click', '#wrjs_modal_' + _config.id + ' .confirmclick:not(.disabled)', function(e) { if (_config.confirmCallback) { _config.confirmCallback(this, modal, e) } else { modal.remove(); } }); // *********************************************************************************** // CANCELCLICK // *********************************************************************************** $('.cancelclick:not(.disabled)', p).bind('click', function (e) { if (_config.cancelCallback) { _config.cancelCallback(this, modal, e) } else { modal.remove(); } }); // *********************************************************************************** // HELP CLICK // *********************************************************************************** if (_config.helpFunction) { $('.helpclick', p).bind('click', function (e) { _config.helpFunction(this, modal, e); }); } // *********************************************************************************** // INCNREMENT ID // *********************************************************************************** //wrjs.state.modalcount++ return html }; // *********************************************************************************** // REMOVEMODAL FROM DOM AND VIEW AMANGER // *********************************************************************************** var _removeModal = function(fn) { var callback = typeof fn == 'function'; // A FUNCTION HAS BEEN PASSED INSTEAD OF EL var p = _config.id == false ? $('.wrjs_modal') : $('#wrjs_modal_' + _config.id); var mask = _config.id == false ? $('.wrjs_mask') : $('#wrjs_mask_' + _config.id); function performDestroy() { p.remove(); mask.remove(); if(_config.removeCallback) { _config.removeCallback(); } if(callback) { fn(); } }; if(_config.animate) { p.addClass('slideOut'); mask.removeClass('fadeIn').addClass('fadeOut'); // WAIT FOR ANIMATION TO COMPLETE BEFORE REMOVING FROM DOM setTimeout(function() { performDestroy() },1000) } else { performDestroy(); }; // REMOVE FROM VIEWMANAGER delete wrjs.View.viewManager[_config.id]; }; var _keypress = function(e) { if (e.keyCode === 27) { if (_config.cancelCallback) { _config.cancelCallback(this, modal, e) } else { modal.remove(); } } }; var _pixelFix = function() { setTimeout(function() { // DIRTY FIX FOR SUB PIXEL RENDERING // IF MODAL IS AN ODD NUMBER IN HEIGHT, THEN BLURRY BORDERS ARE RENDERED IN BROWSER // THEREFORE ALWAYS ENSURE MODAL IS AN EVEN NUMBER AND THIS IS RESOLVED var parent = $('#wrjs_modal_' + _config.id); var h1 = $('h1', parent); // RESET h1.css({ 'paddingBottom': '13px' }); var h = parent.outerHeight(); var even = h % 2 == 0; if(!even) { h1.css('paddingBottom', '14px'); }; //var w = parent.outerWidth(); //parent.width(w + 1); },10); return modal; }; var _displayMessage = function(options) { $('.modalmessage').remove(); $('#wrjs_modal_' + _config.id + ' .inner').prepend(wrjs.Message({cls: options.cls + ' modalmessage', msg: options.msg, icon: options.icon})); return modal; }; // ********************************************************************************** // PUBLIC FUNCTIONS // ********************************************************************************** var publicFunctions = { loadMask: _config.loadMask, renderTo: _config.renderTo, rendered: false, remove: function(el, e) { // TRIGGER CLOSE var hash = '#wrjs_modal_' + _config.id; $(hash).trigger('close'); if (_config.listeners != false) { wrjs.Event.eventManager.unregisterListeners(_config); } $('body').off('keyup', _keypress); $('body').off('click', '#wrjs_modal_' + _config.id + ' .tabs:not(.disabled) li:not(.selected) a', _pixelFix); $('body').off('click', '#wrjs_modal_' + _config.id + ' .confirmclick:not(.disabled)'); $('html,body').removeClass('has-modal'); //console.log('WRJS REMOVE MODAL', el ,e); _removeModal(el, e); }, update: function(records) { //console.log('GRID UPDATE', grid, records) // mondal.render(); // UNMASK if(_config.loadMask) { if(_config.renderTo) { $(_config.renderTo).unmask() } } }, setHeader: function(val) { _config.header = val; }, render: function(options) { //console.log('MODAL RENDER') // CALL RENDER FUNCTION function callRender() { if(typeof _config.listeners.render == 'function') { var modal = $('#' + _config.id); modal.trigger('render'); } } // ONLY REGISTER LISTENERS ON INITIAL RENDER if(!_config.rendered) { //console.log('REGISTER LISTENERS') _registerListeners(); } // BEFORERENDER - CALL THIS FIRST if(typeof _config.listeners.beforerender == 'function') { //console.log('CALL BEFORERENDER', _config) _config.listeners.beforerender(_config); } // BUILD MODAL VIEW var html = _buildView(); // IF NO RENDERTO CONFIG IS PROVIDED, SIMPLY RETURN THE BUILD HTML STRING // ELSE, APPEND THE CREATED HTML TO THE PASSED RENDERTO ELEMENT if(html) { if(!_config.renderTo) { return html } else { if(!_config.rendered) { // RENDERING IS CURRENTLY HAPPENING IN BUILDVIEW //var renderto = $(_config.renderTo); //var parent = renderto.parent().parent(); //renderto.prepend(html); callRender(); } } } _config.rendered = true; this.rendered = true; }, mask: function(str, maskstyle) { str = str || false; maskstyle = maskstyle || ''; $('#wrjs_modal_' + _config.id).mask(str, maskstyle); }, unmask: function() { $('#wrjs_modal_' + _config.id).unmask(); }, pixelFix: _pixelFix, displayMessage: _displayMessage, setRapid: function(bool) { var flag = typeof bool != undefined ? bool : false; _config.rapid = flag; }, updateBody: function(str) { str = str || ''; $('#wrjs_modal_' + _config.id + ' .inner').html(str); } } // ********************************************************************************** // CONSTRUCTOR // ********************************************************************************** var modal = { id: _config.id }; $.extend(modal, publicFunctions) modal.render(); wrjs.View.viewManager = wrjs.View.viewManager || {}; wrjs.View.viewManager[_config.id] = modal; wrjs.state.modalcount++; //console.log('WRJS MODAL CREATE'); return modal; // ********************************************************************************** // END // ********************************************************************************** }; wrjs.View.removeAllModals = function(callback) { var modals = $('.wrjs_modal'); $.each(modals, function(i, modal) { var id = modal.id.split('wrjs_modal_')[1]; var wrjsmodal = wrjs.get(id); if(wrjsmodal) { wrjsmodal.remove(); }; }); if(callback) { //setTimeout(function() { callback(); //},100) }; }