var _AJAX_LOADING = false; // Resize the tabs once the document is properly loaded // @todo most of this file needs to be tidied up using jQuery if(typeof(jQuery) != 'undefined') { (function($) { $(document).ready(function() { window.onresize(true); }); })(jQuery); } /** * Code for the separator bar between the two panes */ function DraggableSeparator() { this.onmousedown = this.onmousedown.bindAsEventListener(this); // this.onselectstart = this.onselectstart.bindAsEventListener(this); } DraggableSeparator.prototype = { onmousedown : function(event) { this.leftBase = $('left').offsetWidth - Event.pointerX(event); this.separatorBase = getDimension($('separator'),'left') - Event.pointerX(event); this.rightBase = getDimension($('right'),'left') - Event.pointerX(event); document.onmousemove = this.document_mousemove.bindAsEventListener(this); document.onmouseup = this.document_mouseup.bindAsEventListener(this); document.body.onselectstart = this.body_selectstart.bindAsEventListener(this); }, document_mousemove : function(event) { $('left').style.width = (this.leftBase + Event.pointerX(event)) + 'px'; fixRightWidth(); }, document_mouseup : function(e) { document.onmousemove = null; }, body_selectstart : function(event) { Event.stop(event); return false; } } function fixRightWidth() { if(!$('right')) return; // Absolutely position all the elements var sep = getDimension($('left'),'width') + getDimension($('left'),'left'); $('separator').style.left = (sep + 2) + 'px'; $('right').style.left = (sep + 6) + 'px'; // Give the remaining space to right var bodyWidth = parseInt(document.body.offsetWidth); var leftWidth = parseInt($('left').offsetWidth); var sepWidth = parseInt($('separator').offsetWidth - 8); var rightWidth = bodyWidth - leftWidth - sepWidth -18; // Extra pane in right for insert image/flash/link things if($('contentPanel') && $('contentPanel').style.display != "none") { rightWidth -= 210; $('contentPanel').style.left = leftWidth + sepWidth + rightWidth + sepWidth + 23 + 'px'; } if(rightWidth >= 0) $('right').style.width = rightWidth + 'px'; } Behaviour.register({ '#separator' : DraggableSeparator, '#left' : { hide : function() { if(!this.hidden) { this.hidden = true; this.style.width = null; Element.addClassName(this,'hidden'); Element.addClassName('separator','hidden'); fixRightWidth(); } }, show : function() { if(this.hidden) { this.hidden = false; Element.removeClassName(this,'hidden'); Element.removeClassName('separator','hidden'); fixRightWidth(); } } }, '#MainMenu li' : { onclick : function(event) { return LeftAndMain_window_unload(); // Confirm if there are unsaved changes window.location.href = this.getElementsByTagName('a')[0].href; Event.stop(event); } }, '#Menu-help' : { onclick : function() { var w = window.open(this.getElementsByTagName('a')[0].href, 'help'); w.focus(); return false; } }, '#Logo' : { onclick : function() { var w = window.open(this.getElementsByTagName('a')[0].href); w.focus(); return false; } }, '#EditMemberProfile': { onclick: function(e) { var el = Event.element(e); GB_show('Edit Profile', el.attributes.href.value, 390, 560); Event.stop(e); } } }); window.ontabschanged = function() { var formEl = $('Form_EditForm'); if( !formEl ) return; var fs = formEl.getElementsByTagName('fieldset')[0]; if(fs) fs.style.height = formEl.style.height; // var divs = document.getElementsBySelector('#Form_EditForm div'); /*for(i=0;i_right" if(window[this.name + '_' + tabName]) { window[this.name + '_' + tabName](e); } else { statusMessage('...'); Ajax.SubmitForm(this.ownerForm, this.name, { onSuccess: Ajax.Evaluator, onFailure: ajaxErrorHandler }); } return false; } // behaveAs(button, StatusTitle); } } /** * @deprecated 2.3 Please use ss.i18n */ function ingize(val) { var ingWord, suffix; if(!val) val = "process"; if(val.match(/^([^ ]+) +(.*)$/)) { ingWord = RegExp.$1; suffix = ' ' + RegExp.$2 + '...'; } else { ingWord = val; suffix = '...'; } if(ingWord.match(/^(.*)e$/)) return RegExp.$1 + 'ing' + suffix; else return ingWord + 'ing' + suffix; } /** * Submit the given form and evaluate the Ajax response. * Needs to be bound to an object with the following parameters to work: * - form * - action * - verb * * The bound function can then be called, with the arguments passed */ function ajaxSubmitForm(automated, callAfter, form, action, verb) { var alreadySaved = false; if($(form).elements.length < 2) alreadySaved = true; if(alreadySaved) { if(callAfter) callAfter(); } else { statusMessage(verb + '...', '', true); var success = function(response) { Ajax.Evaluator(response); if(callAfter) callAfter(); } if(callAfter) success = success.bind({callAfter : callAfter}); Ajax.SubmitForm(form, action, { onSuccess : success, onFailure : function(response) { errorMessage('Error ' + verb, response); } }); } return false; }; /** * Post the given fields to the given url */ function ajaxSubmitFieldSet(href, fieldSet, extraData) { // Build data var i,field,data = "ajax=1"; for(i=0;field=fieldSet[i];i++) { data += '&' + Form.Element.serialize(field); } if(extraData){ data += '&'+extraData; } // Send request new Ajax.Request(href, { method : 'post', postBody : data, onSuccess : function(response) { //alert(response.responseText); Ajax.Evaluator(response); }, onFailure : function(response) { alert(response.responseText); //errorMessage('Error: ', response); } }); } /** * Post the given fields to the given url */ function ajaxLink(href) { // Send request new Ajax.Request(href + (href.indexOf("?") == -1 ? "?" : "&") + "ajax=1", { method : 'get', onSuccess : Ajax.Evaluator, onFailure : ajaxErrorHandler }); } /** * Load a URL into the given form */ function ajaxLoadPage() { statusMessage('loading...', 2, true); new Ajax.Request(this.URL + '&ajax=1', { method : 'get', onSuccess : ajaxLoadPage_success.bind(this) }); } function ajaxLoadPage_success(response) { statusMessage('loaded'); $(this.form).loadNewPage(response.responseText); } /** * Behaviour of the statuts message. */ Behaviour.register({ '#statusMessage' : { showMessage : function(message, type, waitTime, clearManually) { if(this.fadeTimer) { clearTimeout(this.fadeTimer); this.fadeTimer = null; } if(this.currentEffect) { this.currentEffect.cancel(); this.currentEffect = null; } this.innerHTML = message; this.className = type; Element.setOpacity(this, 1); //this.style.position = 'absolute'; this.style.display = ''; this.style.visibility = ''; if(!clearManually) { this.fade(0.5,waitTime ? waitTime : 5); } }, clearMessage : function(waitTime) { this.fade(0.5, waitTime); }, fade: function(fadeTime, waitTime) { if(!fadeTime) fadeTime = 0.5; // Wait a bit before fading if(waitTime) { this.fadeTimer = setTimeout((function() { this.fade(fadeTime); }).bind(this), waitTime * 1000); // Fade straight away } else { this.currentEffect = new Effect.Opacity(this, { duration: 0.5, transition: Effect.Transitions.linear, from: 1.0, to: 0.0, afterFinish : this.afterFade.bind(this) }); } }, afterFade : function() { this.style.visibility = 'hidden'; this.style.display = 'none'; this.innerHTML = ''; } } }); /** * Show a status message. * * @param msg String * @param type String (optional) can be 'good' or 'bad' * @param clearManually boolean Don't automatically fade message. * @param container custom #statusMessage element to show message. */ function statusMessage(msg, type, clearManually, container) { var statusMessageEl = $('statusMessage'); if(container != null) statusMessageEl = container; if(statusMessageEl) { if(msg) { statusMessageEl.showMessage(msg, type, msg.length / 20, clearManually); } else { statusMessageEl.clearMessage(); } } } function clearStatusMessage() { $('statusMessage').clearMessage(); } /** * Called when something goes wrong */ function errorMessage(msg, fullMessage) { // Show complex error for developers in the console if(fullMessage) { // Get the message from an Ajax response object try { if(typeof fullMessage == 'object') fullMessage = fullMessage.status + '//' + fullMessage.responseText; } catch(er) { fullMessage = ""; } console.error(fullMessage); } msg = msg.replace(/\n/g,'
'); $('statusMessage').showMessage(msg,'bad'); } function ajaxErrorHandler(response) { errorMessage('Server Error', response); } /** * Applying StatusTitle to an element will mean that the title attribute is shown as a statusmessage * upon hover */ /* Commenting out because on IE6, IE7, and Safari 3, the statusmessage becomes * 'null' on 2nd hover and because there is not room for long titles when * action buttons are on the same line. StatusTitle = Class.create(); StatusTitle.prototype = { onmouseover : function() { if(this.title) { this.message = this.title; this.title = null; } if(this.message) { $('statusMessage').showMessage(this.message); } }, onmouseout : function() { if(this.message) { $('statusMessage').fade(0.3,1); } } } */ /** * BaseForm is the base form class used in the CMS. */ BaseForm = Class.create(); BaseForm.prototype = { intitialize: function() { this.visible = this.style.display == 'none' ? false : true; // Collect all the buttons and attach handlers this.buttons = []; var i,input,allInputs = this.getElementsByTagName('input'); for(i=0;input=allInputs[i];i++) { if(input.type == 'button' || input.type == 'submit') { this.buttons.push(input); input.holder = this; input.onclick = function() { return this.holder.buttonClicked(this); } } } }, show: function() { this.visible = true; Element.hide(show); }, hide: function() { this.visible = false; Element.hide(this); }, isVisible: function() { return this.visible; }, buttonClicked: function(button) { return true; } } /** * ChangeTracker is a class that can be applied to forms to support change tracking on forms. */ ChangeTracker = Class.create(); ChangeTracker.prototype = { initialize: function() { this.resetElements(); }, /** * Reset all the 'changed field' data. */ resetElements: function(debug) { var elements = Form.getElements(this); var i, element; for(i=0;element=elements[i];i++) { // Initialise each element if(element.resetChanged) { element.resetChanged(); } else { element.originalSerialized = Form.Element.serialize(element); } } }, field_changed: function() { return this.originalSerialized != Form.Element.serialize(this); }, /** * Returns true if something in the form has been changed */ isChanged: function() { var elements = Form.getElements(this); var i, element; for(i=0;element=elements[i];i++) { if(!element.isChanged) element.isChanged = this.field_changed; if(!this.changeDetection_fieldsToIgnore[element.name] && element.isChanged()) { //if( window.location.href.match( /^https?:\/\/dev/ ) ) // Debug.log('Changed:'+ element.id + '(' + this.originalSerialized +')->('+Form.Element.serialize(element)+')' ); return true; } } return false; }, changeDetection_fieldsToIgnore : { 'Sort' : true }, /** * Serialize only the fields to change. * You can specify the names of fields that must be included as arguments */ serializeChangedFields: function() { var elements = Form.getElements(this); var queryComponent, queryComponents = new Array(); var i, element; var forceFields = {}; if(arguments) {for(var i=0;i method; context-menu operations to get called */ function createContextMenu(event, owner, menuItems) { if(_CURRENT_CONTEXT_MENU) { document.body.removeChild(_CURRENT_CONTEXT_MENU); _CURRENT_CONTEXT_MENU = null; } var menu = document.createElement("ul"); menu.className = 'contextMenu'; menu.style.position = 'absolute'; menu.style.left = event.clientX + 'px'; menu.style.top = event.clientY + 'px'; var menuItemName, menuItemTag, menuATag; for(menuItemName in menuItems) { menuItemTag = document.createElement("li"); menuATag = document.createElement("a"); menuATag.href = "#"; menuATag.onclick = menuATag.oncontextmenu = contextmenu_onclick; menuATag.innerHTML = menuItemName; menuATag.handler = menuItems[menuItemName]; menuATag.owner = owner; menuItemTag.appendChild(menuATag); menu.appendChild(menuItemTag); } document.body.appendChild(menu); document.body.onclick = contextmenu_close; _CURRENT_CONTEXT_MENU = menu; return menu; } function contextmenu_close() { if(_CURRENT_CONTEXT_MENU) { document.body.removeChild(_CURRENT_CONTEXT_MENU); _CURRENT_CONTEXT_MENU = null; } } function contextmenu_onclick() { this.handler(this.owner); contextmenu_close(); return false; } /** * Shows an ajax loading indicator. * * @param id String Identifier for the newly created image * @param container ID/DOM Element * @param imgSrc String (optional) * @param insertionType Object (optional) Prototype-style insertion-classes, defaults to Insertion.Bottom * @param displayType String (optional) "inline" or "block" */ function showIndicator(id, container, imgSrc, insertionType, displayType) { if(!id || !$(container)) return false; if(!imgSrc) imgSrc = "cms/images/network-save.gif"; if(!displayType) displayType = "inline"; if(!insertionType) insertionType = Insertion.Bottom; if(!$(id)) { var html = ''; new insertionType(container, html); } Effect.Appear(id); } function hideIndicator(id) { Effect.Fade(id, {duration: 0.3}); } setInterval(function() { new Ajax.Request("Security/ping"); }, 5*60*1000);