/* Copyright (c) 2006-2010, ePages GmbH All Rights Reserved. epages.widget.LocalizedWidget $Revision: 1.39 $ */ dojo.provide("epages.widget.WizardController"); dojo.require("epages.widget.LocalizedWidget"); dojo.require("epages.io.json"); dojo.require('epages.uimessagehandler'); dojo.require('epages.string'); dojo.require('epages.browser'); dojo.require('dojo.number'); dojo.declare("epages.widget.WizardController",[epages.widget.LocalizedWidget],{ /** * public properties */ currentLanguageId : undefined, // integer - id of current language controllerName : '', // string - name of controller url : '?', // string - request url saveOnNext : false, // boolean - flag that indicates weather the wizards saves after every step or not showQuickFinish : false, // boolean - flag that indicates weather the show link to finish page will be displayed or not debugMode : false, // boolean - flag to run the wizard in debug mode finishButtonLabel : "", // string - label of finish button node finishRedirectURL : "", // string - this url is called after the finish step cancelRedirectURL : "", // string - this url is called after clicking the cancel button /** * private properties */ _steps : undefined, // array - array with step data objects _objects : undefined, // hash - contains epages objects: <objectId> : { saveValues: [], saveNames: [], changeActions: []) } _jsonHandler : undefined, // epages.io.Json - communication _initialized : undefined, // boolean - you can not add steps after the wizard is initialized _activeStep : undefined, // integer - index of current step _stepNavigation : undefined, // array - array with navigation { node : stepNode, bubbleNode : bubbleNode, stepNumber : i } _defaultChangeAction : 'Save', // string - default save action for objects (_objects) _stepStates : [ 'Active','Disabled','Done' ], // array - navigation states (css classes) _hideBubbleTimeout : undefined, // timeout reference HIDEBUBBLE_TIMEOUT : 800, // integer - navigation bubble timeout value in ms /** * dojo widget properties */ templatePath : dojo.moduleUrl('epages.widget','templates/WizardController.html'), translationName : dojo.moduleUrl('epages.widget','templates/translation'), widgetsInTemplate:true, postMixInProperties: function(){ //summary: initialize all necessary objects and arrays, convert flags to real boolean this.inherited("postMixInProperties", arguments); if(this.finishButtonLabel == "") { this.finishButtonLabel = this.translate("Finish"); } this._jsonHandler = new epages.io.Json(); this._steps = []; this._objects = undefined; this._stepNavigation = []; this._initialized = false; this.showQuickFinish = epages.string.toBoolean(this.showQuickFinish); this.saveOnNext = epages.string.toBoolean(this.saveOnNext); //if(epages.vars.DebugLevel && epages.vars.DebugLevel != 0){ this.debugMode = true; //} if(epages.Browser.engine == "MSIE") { var htmlTag = document.getElementsByTagName("html")[0]; htmlTag.style.overflow="visible"; } }, postCreate: function(){ this.inherited("postCreate", arguments); if(this.cancelRedirectURL) { this.closeButtonNode.style.display=""; } }, startup: function(){ //summary: make all event connects and connect to Switch to Edit Mode topic this.inherited("startup", arguments); dojo.body().appendChild(this.domNode); //attach events //catch all events that happen inside the domNode this.connect(this.domNode,'onclick', '_onDomNodeEvent'); this.connect(this.domNode,'onkeyup', '_onDomNodeEvent'); this.connect(this.domNode,'onchange', '_onDomNodeEvent'); //connect all buttons this.connect(this.NextButton.domNode,'onclick', '_onNextButtonClick'); this.connect(this.BackButton.domNode,'onclick', '_onBackButtonClick'); this.connect(this.SaveButton.domNode,'onclick', '_onSaveButtonClick'); // bubble events this.connect(this.StepNavigationBubble.domNode,'onmouseleave', '_hideStepNavigationBubble'); //hide stepNavigationBubble on mouse leave of the bubble this.connect(this.StepNavigationNode, 'onmouseleave', '_hideStepNavigationBubble'); //hide stepNavigationBubble on mouse leave of the bubble this.connect(this.StepNavigationBubble.domNode,'onmouseenter', '_dontHideStepNavigationBubble'); //clear timeout if(this.showQuickFinish){ this.connect(this.QuickFinish,'onclick', '_onQuickFinishClick'); } else{ dojo.addClass(this.QuickFinish,'HideElement'); } //do subscribes dojo.subscribe(this.id+'/SwitchToEditMode',this,'_onSwitchToEditMode'); dojo.subscribe(this.id+'/switchToStep',this,'_onSwitchToStep'); }, start: function(){ //summary: this function has to be called when all steps are added with publishthe add steps method //this function starts the wizard and shows the first step //steps inside the _steps Array are processed in there normal order this._toggleLoaderOverlay(true); this._initialized = true; this._activeStep = 0; this._initialize(); //load template of fist step this._loadStep(0); }, addStep: function(stepData){ //summary: add step to wizard with this function is only working before wizard is started //example: // |myWizard.addStep({ // | Name : '{Video}', - required // | ViewAction : 'JSONSnippet', - required // | TemplateAction : 'MBO-ViewBookingsystemWizardSteps', - required // | TemplateName : 'Content-Video', - required // | ObjectID : '#Shop.ID', - required // | NotInNavigation : true, - optional // | NoPreload : true - optional // | NoButtons : true, - optional // | ShowAllStepsOnFinish : true, - optional // | IsFinishStep : false - optional // |}); if(stepData){ if(this._initialized){ console.warn(this.id,'unable to add step wizard is already started'); return; } //every step is disabled on start stepData.state = "Disabled"; this._steps.push(stepData); } }, _preloadSteps:function(){ //summary: load template of every defined step only loads one step at the same time no multiple simultan loading //checks if step is loaded, step is loaded when template is set //load next step where template is not defined for( var i=0,iLength=this._steps.length ; i<iLength ; i++ ){ var stepData = this._steps[i]; if(stepData.template == undefined && !stepData.errorOnLoad){ this._loadStep(i); break; } } }, _loadStep: function(stepNumber){ //summary: load data of step defined by given stepNumber with async json request //when step is loaded call redStepResponse with given data //loads given step asynchronous from server var stepData = this._steps[stepNumber]; stepData.TemplateLanguageID = this.currentLanguageId; if(epages.vars[this.id+'TemplateObjectID']) { stepData.TemplateObjectID = epages.vars[this.id+'TemplateObjectID']; } if(stepData && stepData.ObjectID) { this._jsonHandler.loadAsync(this.url,dojo.hitch(this,function(response){ this._readStepResponse(response,stepNumber); }),stepData); } else { this._showErrorMessage(this.translate('WizardStepError'),this.translate('WizardStepErrorDesciption')); } }, _loadStepSync: function(stepNumber){ //summary: loads given step synchronous from server //is needed when preloading is disabled and next step has to be loaded on next Button click //checks if epages.vars[this.id+'TemplateObjectID'] is defined and adds it to request is //neccassary if steps are influenced by each other var stepData = this._steps[stepNumber]; stepData.TemplateLanguageID = this.currentLanguageId; if(epages.vars[this.id+'TemplateObjectID']) { stepData.TemplateObjectID = epages.vars[this.id+'TemplateObjectID']; } if(stepData && stepData.ObjectID) { var response = this._jsonHandler.loadSync(this.url,stepData); this._readStepResponse(response,stepNumber); } }, _readStepResponse: function(response,stepNumber){ //summary: read response from server and load next step if preloading is enabled var stepData = this._steps[stepNumber]; //check if step response is okay if(response && response.data && response.data.snippet){ stepData.template = response.data.snippet; if(stepNumber == this._activeStep){ //build step and step navigation if activeStep was loaded, happens on first step stepData.state = 'Active'; this._changeNavigationNodeState(stepNumber,'Active'); this._buildStep(stepNumber); } } else{ //set step on error to avoid preload step from loading it again and again stepData.errorOnLoad = true; } if(stepData){ //is preload is enabled load next step if(!stepData.NoPreload){ this._preloadSteps(); } } }, _buildStep: function(stepNumber){ //summary: build template of given step and add it to the container //step with flag IsFinishStep is added as first element on container for summary mode of this step var stepData = this._steps[stepNumber]; //check if template ist loaded if not load template if(stepData.template && stepData.templateNode == undefined){ //dojo.addClass(this.ContainerNode, "HideElement"); //create step node and insert loaded template var stepNode = document.createElement('div'); dojo.addClass(stepNode,"Step"); dojo.addClass(stepNode,"HideElement"); stepNode.id = stepData.TemplateName; stepData.template = stepData.template.replace(/<!--.*-->/g, ""); // remove comments from pagetype stepNode.innerHTML = stepData.template; //finish step has to be first step in container for design reasons if(stepData.IsFinishStep){ this.ContainerNode.insertBefore(stepNode,this.ContainerNode.firstChild); } else{ this.ContainerNode.appendChild(stepNode); } // no need for extra eval of the script tags on Fx, but on all other browsers if(epages.Browser.engine != "Gecko" || (epages.Browser.engine == "Gecko" && epages.Browser.version >= 4)) { //evalute script-tags inside content var scripts = stepNode.getElementsByTagName('script'); for( var i=0,iLength=scripts.length ; i<iLength ; i++ ) { window.eval(scripts[i].innerHTML); } } //start dojo parser to parse all dojo widgets inside the template dojo.parser.parse(stepNode); stepData.templateNode = stepNode; //dojo.removeClass(this.ContainerNode, "HideElement"); } //show all steps in SummaryMode if FinishStep is shown dojo.addClass(this.ContentPlaceHolder,"HideElement"); // unshow any visible loader overlay this._toggleLoaderOverlay(false); for( var i=0,iLength=this._steps.length ; i<iLength ; i++ ){ var currentStep = this._steps[i]; if(stepData.IsFinishStep && (stepData.ShowAllStepsOnFinish === undefined || stepData.ShowAllStepsOnFinish)){ if(currentStep && currentStep.templateNode && currentStep != stepData){ dojo.addClass(currentStep.templateNode,'SummaryMode'); dojo.removeClass(currentStep.templateNode,"HideElement"); } } else{ if(currentStep.templateNode){ dojo.removeClass(currentStep.templateNode,'SummaryMode'); dojo.addClass(currentStep.templateNode,"HideElement"); } } } if(stepData.template && stepData.templateNode){ dojo.removeClass(stepData.templateNode,"HideElement"); } }, _closeLastInlineTinyMCE:function(){ //summary: close last instance of inline tinyMCE //Inline tinyMCE is still not working correct //TODO: still in progress if(epages.vars.currentInlineTinyMCE){ tinyMCE.execCommand('mceRemoveControl', true,epages.vars.currentInlineTinyMCE); } }, _getSaveData:function(stepNumber){ //summary: this function collects all data from the given step template which has to be send to the server //input for saving must have a name attribute like name="ObjectId:attributeAlias:LanguageId" //languageId ist optional //this function although collects hidden inputs with ChangeActions they must have name="ObjectId:ChangeAction" var node; if(typeof stepNumber != "undefined"){ if(!this._steps[stepNumber] && !this._steps[stepNumber].templateNode){ return; } node = this._steps[stepNumber].templateNode; // possibility to add a hidden input to the step template which tells the wizard NOT to perform a save action for the step var doNotSaveOnNextNode = $("DoNotSaveOnNext_" + this._steps[stepNumber].TemplateName); if(doNotSaveOnNextNode && doNotSaveOnNextNode.value == "true") { return; } } else{ node = this.ContainerNode; } //get all named elemnts with name like ObjectId:attributeAlias:LanguageId or ObjectId:attributeAlias var allNamedElements = dojo.query("[name*=':']", node); if(!this._objects) { this._objects = {}; } for( var i=0,iLength=allNamedElements.length ; i<iLength ; i++ ){ var elm = allNamedElements[i]; //ignore disabled inputs if(elm.disabled && elm.disabled == true){ continue; } //special treatment for radio buttons if( elm.checked === false && (elm.type.toLowerCase() === 'radio' || dojo.hasClass(elm, 'Radio')) ){ continue; } //split name into objectId, atrributeAlias and LanguageID - optional if(elm.name){ var nameValues = elm.name.split(':'); } else if(elm.id){ var nameValues = elm.id.split(':'); } else{ return; } var objectId = nameValues[0]; if(isNaN(objectId)) { // only perform object ids .. continue; } var attributeAlias = nameValues[1]; var languageId = nameValues[2]; var languageFieldName = nameValues[3]; var currentValue = this._objects[objectId] ? this._objects[objectId] : {}; if(!currentValue.saveNames){ currentValue.saveNames = []; } if(!currentValue.saveValues){ currentValue.saveValues = []; } if(objectId && attributeAlias){ // hack for multiple select: if elm is a widget of class type dijit.form.MultiSelect if(dijit.registry.byId(elm.id) && $$(elm.id).declaredClass == "dijit.form.MultiSelect") { var multiSelectValues = $$(elm.id).attr('value'); // add all selected values seperately if(multiSelectValues && multiSelectValues.length > 0) { for( var j=0,jLength=multiSelectValues.length ; j<jLength ; j++ ) { currentValue.saveNames.push(attributeAlias); currentValue.saveValues.push(multiSelectValues[j]); } } } else if(elm.innerHTML && !elm.value){ currentValue.saveNames.push(attributeAlias); currentValue.saveValues.push(elm.innerHTML); if(languageId){ //if object has languages we need other methode to write them currentValue.saveNames.push(languageFieldName ? languageFieldName : 'LanguageID'); currentValue.saveValues.push(languageId); } } else { currentValue.saveNames.push(attributeAlias); currentValue.saveValues.push(elm.value); if(languageId){ //if object has languages we need other methode to write them currentValue.saveNames.push(languageFieldName ? languageFieldName : 'LanguageID'); currentValue.saveValues.push(languageId); } } } this._objects[objectId] = currentValue; } //get all inputs with name ChangeAction, they must have objectId in name and changeAction name in value var allChangeActions = dojo.query("[name='ChangeAction']", node); for( var j=0,jLength=allChangeActions.length ; j<jLength ; j++ ){ var currentAction = allChangeActions[j]; var splitValues = currentAction.value.split(':'); if(splitValues.length > 0){ objectId = splitValues[0]; var actionName = splitValues[1]; currentValue = this._objects[objectId] ? this._objects[objectId] : {}; if(!currentValue.changeActions){ currentValue.changeActions = []; } currentValue.changeActions.push(actionName); } this._objects[objectId] = currentValue; } }, saveData:function(){ //summary: save all data that is inside _objects to the server //after successfull save _objects get cleared to allow override of data if user goes back to an already saved step //when debugMode is true than saveData sends every object in a own request to the server if(!this._objects) { return true; } var result; if(!this.debugMode){ var params = {}; params['ViewAction'] = 'JSONViewResponse'; params['ObjectID'] = []; params['Value'] = []; params['ChangeAction'] = []; } //add parameters of every object to json request for(var key in this._objects){ if(isNaN(dojo.number.parse(key))) { // only valid objectids.. continue; } if(this.debugMode){ var params = {}; params['ViewAction'] = 'JSONViewResponse'; params['ObjectID'] = []; params['Value'] = []; params['ChangeAction'] = []; } var currentObject = this._objects[key]; if(!currentObject.saveNames){ continue; } for( var j=0,jLength=currentObject.saveNames.length ; j<jLength ; j++ ){ if(!params[currentObject.saveNames[j]]){ params[currentObject.saveNames[j]] = []; } params[currentObject.saveNames[j]].push(currentObject.saveValues[j]); } //add changeActions for Object if(currentObject.changeActions){ for( var i=0,iLength=currentObject.changeActions.length ; i<iLength ; i++ ){ params['ObjectID'].push(key); params['ChangeAction'].push(currentObject.changeActions[i]); } } else{ params['ObjectID'].push(key); params['ChangeAction'].push(this._defaultChangeAction); } if(this.debugMode){ result = this._jsonHandler.loadSync(this.url,params); } } if(!this.debugMode){ result = this._jsonHandler.loadSync(this.url,params); } //clear _objects on error to but show error to customer so that he can correct it and save again if(result && result.error && result.error.data){ console.warn("error in wizardcontroller saveData, result=", result); this._showErrors(result.error.data.Errors); this._objects = undefined; return false; } else{ //if everything was saved we can clear the saveData object if(result && result.data){ dojo.publish(this.id+'/saveFinished', [ result.data ]); } else{ dojo.publish(this.id+'/saveFinished', []); } this._objects = undefined; return true; } }, _showErrors:function(errors){ //summary: show given errors to customer with an error message for( var i=0,iLength=errors.length ; i<iLength ; i++ ){ var currentError = errors[i]; if(currentError.LoopName && currentError.Index && currentError.Name){ var errorClass = currentError.LoopName + currentError.Index; for( var j=0,jLength=this._steps.length ; j<jLength ; j++ ){ var stepData = this._steps[j]; if(stepData.templateNode){ var errorNodeContainer = dojo.query("."+errorClass, stepData.templateNode); if(errorNodeContainer && errorNodeContainer.length == 1){ errorNodeContainer = errorNodeContainer[0]; var errorNode = dojo.query("[name*="+currentError.Name+"]", errorNodeContainer); if(errorNode && errorNode.length == 1){ dojo.addClass(errorNode[0],'DialogError'); if(this._steps[this._activeStep].IsFinishStep){ dojo.removeClass(stepData.templateNode, "SummaryMode"); dojo.addClass(stepData.templateNode, "EditMode"); } this._showErrorMessage(this.translate('WizardSaveError'),this.translate('WizardSaveErrorDesciption')); } } } } } else if(currentError.Reason && currentError.Reason == 'FeatureMaxValueReached'){ var me = this; dojo.publish("uimessage/show", [ "", 'The maximum number of services for this website type has been reached.', 'Dialog', { titleBar: this._steps[this._activeStep].Name, typeClass: 'Warning', buttons: [{ label: '{Close}', cssClass: 'Active', onclick: function() { me._closeWizard(); this._modalDialogWidget.hide(); } }] } ]); } else if(currentError.Reason && currentError.Reason == 'OBJECT_EXISTS'){ dojo.publish("uimessage/show", [ "", this.translate('ServiceNoExists'), 'Dialog', { titleBar: this._steps[this._activeStep].Name, typeClass: 'Warning' }]); } else if(currentError.Reason && currentError.Message){ dojo.publish("uimessage/show", [ "", currentError.Message, 'Dialog', { titleBar: this._steps[this._activeStep].Name, typeClass: 'Warning' }]); } else if(currentError.Name){ for( var j=0,jLength=this._steps.length ; j<jLength ; j++ ){ var stepData = this._steps[j]; if(stepData.templateNode){ var errorNode = dojo.query("[name*="+currentError.Name+"]", stepData.templateNode); if(errorNode && errorNode.length == 1){ dojo.addClass(errorNode[0],'DialogError'); if(this._steps[this._activeStep].IsFinishStep){ dojo.removeClass(stepData.templateNode, "SummaryMode"); dojo.addClass(stepData.templateNode, "EditMode"); } } } } } } // remove any loader overlays this._toggleLoaderOverlay(false); }, activateStep: function(nextStepNumber){ //summary: activate given step //change to next step is only possible if next step is already loaded var nextStepData = this._steps[nextStepNumber]; if(nextStepData){ //check if next step is loaded, if not load it sync to avoid error while user have to wait if(!nextStepData.template){ this._loadStepSync(nextStepNumber); } //update stepNavigation this._changeNavigationNodeState(this._activeStep,'Done'); this._changeNavigationNodeState(nextStepNumber,'Active'); nextStepData.state = 'Active'; this._activeStep = nextStepNumber; //check if there is a step before the step we now want to activeate //disable all buttons if NoButtons flag is set used for last step if(nextStepData.NoButtons){ dojo.addClass(this.ButtonBarNode,'HideElement'); dojo.addClass(this.StepNavigationNode,'HideElement'); dojo.addClass(this.QuickFinish,'HideElement'); } else{ dojo.removeClass(this.ButtonBarNode,'HideElement'); dojo.removeClass(this.StepNavigationNode,'HideElement'); if(this.showQuickFinish){ dojo.removeClass(this.QuickFinish,'HideElement'); } } //on IsFinishStep we need the save button not the next button if(nextStepData.IsFinishStep){ this.NextButton.hide(); this.SaveButton.show(); dojo.addClass(this.QuickFinish,'HideElement'); } else{ this.NextButton.show(); this.SaveButton.hide(); if(this.showQuickFinish){ dojo.removeClass(this.QuickFinish,'HideElement'); } } //hide BackButton if next step is first step if(nextStepNumber == 0){ this.BackButton.hide(); } else{ this.BackButton.show(); } var stepdata = this._steps[this._activeStep]; var templateName= stepdata['TemplateName']; //start building next step this._buildStep(nextStepNumber); // publish step message by templateName dojo.publish(this.id+'/stepActivated/'+templateName, []); //publish general step change message dojo.publish(this.id+'/activateStep', [ { 'stepNumber' : this._activeStep, 'stepData' : this._steps[this._activeStep] }]); if(epages.Browser.engine == "MSIE") { var domNode = this.domNode; dojo.removeClass(domNode, "WizardController"); window.setTimeout(function() { dojo.addClass(domNode, "WizardController"); }, 1); } } else{ //show error to user if we had problems this._showErrorMessage(this.translate('WizardStepError'),this.translate('WizardStepErrorDesciption')); } }, _calculateRestrictorOverlay : function(){ var suspendPosition = new epages.html.Element(this.ContainerNode).getAbsolutePosition(dojo.body()); var aw = dojo.style(this.ContainerNode,"marginLeft"); aw += dojo.style(this.ContainerNode,"paddingLeft"); var l = suspendPosition.x - aw; aw += dojo.style(this.ContainerNode,"marginRight"); aw += dojo.style(this.ContainerNode,"paddingRight"); var w = this.ContainerNode.offsetWidth + aw; var ah = dojo.style(this.ContainerNode,"marginTop"); ah += dojo.style(this.ContainerNode,"paddingTop"); var t = suspendPosition.y - ah; ah += dojo.style(this.ContainerNode,"marginBottom"); ah += dojo.style(this.ContainerNode,"paddingBottom"); var h = this.ContainerNode.offsetHeight + ah; return { Width : w, Height : h, Left : l, Top : t }; }, _toggleLoaderOverlay : function(/*boolean*/toggleState){ if(toggleState){ dojo.publish("interactionRestrictor/suspend", ["ContainerNodeLoading", this.ContainerNode,false,this._calculateRestrictorOverlay()]); } else { dojo.publish("interactionRestrictor/permit", ["ContainerNodeLoading"]); } }, _onNextButtonClick: function(){ //summary: got to next step and save if saveOnNext is defined dojo.publish(this.id+'/nextButtonClick', []); this._toggleLoaderOverlay(true); this._closeLastInlineTinyMCE(); if(this.saveOnNext){ this._getSaveData(this._activeStep); if(!this.saveData()) { return; } } this.activateStep(this._activeStep + 1); }, _onBackButtonClick: function(){ //summary: go to prevoius step this._toggleLoaderOverlay(true); this.activateStep(this._activeStep - 1); }, _onSaveButtonClick:function(){ //summary: collect save data and send it to the server //go to last step this is always the quickStart step this._closeLastInlineTinyMCE(); if(this.saveOnNext) { this._getSaveData(this._activeStep); } else { this._getSaveData(); } if(this.saveData()){ var stepdata = this._steps[this._activeStep]; if(this.finishRedirectURL && stepdata.IsFinishStep) { epages.locationHref(this.finishRedirectURL); } else { this.activateStep(this._steps.length - 1); } } }, _onQuickFinishClick:function(){ //summary: save data and go to last step this._toggleLoaderOverlay(true); this._closeLastInlineTinyMCE(); this._getSaveData(); if(this.saveData()){ this.activateStep(this._steps.length - 1); } }, _activateNextButton: function(){ //summary: activate the next Button dojo.addClass(this.NextButton, 'Active'); }, _disableNextButton: function(){ //summary: disable the next Button dojo.addClass(this.NextButton, 'Disabled'); }, _closeWizard:function(){ //summary: activates the last step without saving necessary for errors location.href = epages.vars.BaseUrl; }, _changeNavigationNodeState: function(stepNumber,state){ //summary: change states of nextNavigationNodes //only steps with state done can be clicked var stepNavigationNode; for( var j=0,jLength=this._stepNavigation.length ; j<jLength ; j++ ){ var currentNode = this._stepNavigation[j]; if(stepNumber == currentNode.stepNumber){ stepNavigationNode = currentNode; } } //change stepNavigationNode to active and remove all other states on this step only no multiple states possible if(stepNavigationNode){ for( var i=0,iLength=this._stepStates.length ; i<iLength ; i++ ){ var currentState = this._stepStates[i]; if(state == currentState){ dojo.addClass(stepNavigationNode.node,currentState); dojo.addClass(stepNavigationNode.bubbleNode,currentState); } else{ dojo.removeClass(stepNavigationNode.node,currentState); dojo.removeClass(stepNavigationNode.bubbleNode,currentState); } } } }, checkChanges:function(){ //TODO: diese funktion soll überprüfen, ob es noch ungespeicherte Änderungen gibt und bei Bedarf warnen /*this._getSaveData(); console.debug('check changes',this._objects); var unsavedData = false; for(var key in this._objects){ if(this._objects[key]){ unsavedData = true; break; } } if(unsavedData){ return true; } else{ return false; }*/ return false; }, _initialize: function(){ //summary:make necessary first values to start wizard //show step jump list //register on onbeforeunload epages.onUnloadFunctions.push(dojo.hitch(this,function() { return this.checkChanges(); })); this._buildStepNavigation(); this.BackButton.hide(); this.SaveButton.hide(); }, _buildStepNavigation: function(){ //summary: build step navigation and stepNavigation Bubble this.BubbleContentNode.innerHTML='<div class="Headline">'+this.controllerName+'</div>'; var visibleStepNumber = 1; for( var i=0,iLength=this._steps.length ; i<iLength ; i++ ){ var stepData = this._steps[i]; if(stepData.NotInNavigation){ continue; } // create step node var stepNode = document.createElement('a'); stepNode.innerHTML = visibleStepNumber; dojo.addClass(stepNode, "Step"); dojo.addClass(stepNode, stepData.state); this.connect(stepNode,'onclick', '_onStepNumberClick'); this.connect(stepNode,'onmouseover', '_onStepNumberHover'); this.StepNavigationNode.appendChild(stepNode); // create step node in bubble var bubbleNode = document.createElement('div'); bubbleNode.innerHTML = visibleStepNumber+'. '+stepData.Name; dojo.addClass(bubbleNode, stepData.state); dojo.addClass(bubbleNode, "Step"); this.connect(bubbleNode,'onclick', '_onStepNumberClick'); this.BubbleContentNode.appendChild(bubbleNode); // register nodes var stepNavigationNode = { node : stepNode, bubbleNode : bubbleNode, stepNumber : i }; this._stepNavigation.push(stepNavigationNode); visibleStepNumber++; } // fill in bubble this.StepNavigationBubble.setupContent({ content: this.BubbleContentNode, orientation : 'top-right' }); // show bubble dojo.removeClass(this.BubbleContentNode,'HideElement'); }, _onStepNumberClick: function(evt){ //summary: change to clicked step currentNode = evt.currentTarget; for( var i=0,iLength=this._stepNavigation.length ; i<iLength ; i++ ){ var stepNavigationNode = this._stepNavigation[i]; if(currentNode == stepNavigationNode.node ||currentNode == stepNavigationNode.bubbleNode){ var stepData = this._steps[stepNavigationNode.stepNumber]; if(stepData.state != 'Disabled'){ this._toggleLoaderOverlay(true); this.activateStep(stepNavigationNode.stepNumber); } } } }, _onStepNumberHover: function(evt){ //summary: show stepBubble on hover of stepNumbers var currentNode = evt.currentTarget; var absPos = $E(currentNode).getRelativePosition(); this.StepNavigationBubble.setupContent({ x : absPos.x - 15, y : absPos.y + 20, orientation : 'top-right' }); this.StepNavigationBubble.show(); }, _hideStepNavigationBubble: function(evt){ //summary: hide step navigation bubble var _this = this; window.clearTimeout(this._hideBubbleTimeout); this._hideBubbleTimeout = window.setTimeout(function() { _this.StepNavigationBubble.hide(); }, this.HIDEBUBBLE_TIMEOUT); }, _dontHideStepNavigationBubble: function(evt){ //summary: clear hide bubble window.clearTimeout(this._hideBubbleTimeout); }, _showErrorMessage: function(messageTitle,messageText){ //summary: show given error message dojo.publish("uimessage/show", [messageTitle, messageText, 'Dialog',{ titleBar: this._steps[this._activeStep].Name, typeClass: 'Warning' }]); }, //Eventhandling for changes and updates to Previews _onDomNodeEvent:function(evt){ //summary: collect all events that happen on the domNode of this widget to update preview nodes if input nodes were changed if(evt.target.nodeName == "INPUT" || evt.target.nodeName == "SELECT" || evt.target.nodeName == "TEXTAREA") { var sourceNode = evt.target; var epUpdateName = (sourceNode.getAttribute('ep_updatename')) ? sourceNode.getAttribute('ep_updatename') : sourceNode.name; // update known elements var updateNodes = dojo.query("[ep_updatesource="+epUpdateName+"]", this.ContainerNode); var updateValue = sourceNode.value; if(sourceNode.nodeName == "SELECT") { updateValue = sourceNode[sourceNode.selectedIndex].innerHTML; } else if(sourceNode.type == "radio" || sourceNode.className.match("Radio")) { var aRadioLabel = dojo.query('[for='+sourceNode.id+']', sourceNode.parentNode.parentNode); if(aRadioLabel[0]) { updateValue = aRadioLabel[0].innerHTML; } } for( var i=0,iLength=updateNodes.length ; i<iLength ; i++ ){ var currentNode = updateNodes[i]; var updateTask = currentNode.getAttribute("ep_updatetask"); var emptyDefault = currentNode.getAttribute("ep_emptyDefault"); if(updateValue == "" && emptyDefault) { updateValue = emptyDefault; } this._updatePreview(currentNode, updateTask, updateValue); } } }, _updatePreview: function(/* dom node*/updateNode, /* string */ updateTask, /* string */ updateValue ) { //summary: insert new value to preview dom node if(!updateTask){ return; } if(updateTask.match("setHTML")) { if(updateValue == "") { updateValue= " "; // avoid empty tags which are not displayed (e.g. business hours table) } if(updateNode.innerHTML == updateValue) { return; } updateNode.innerHTML = updateValue; } if(updateTask.match("setText")) { updateValue = epages.string.escapeXml(updateValue); if(updateNode.innerHTML == updateValue) { return; } updateNode.innerHTML = updateValue; } if(updateTask.match("setValue")) { if(updateNode.value == updateValue) { return; } updateNode.value = updateValue; } if(updateTask.match("emphasize")) { updateNode.style.fontWeight = "bold"; } }, _onSwitchToEditMode: function(templateName){ //summary: switch given step to editmode find step with given templateName if(!templateName){ return; } for( var i=0,iLength=this._steps.length ; i<iLength ; i++ ){ var currentStep = this._steps[i]; if(currentStep.TemplateName == templateName){ dojo.addClass(currentStep.templateNode, "EditMode"); dojo.removeClass(currentStep.templateNode, "SummaryMode"); break; } } }, _onSwitchToStep: function(templateName) { // summary: message function var foundTemplate = false; for( var i=0,iLength=this._steps.length ; i<iLength ; i++ ){ var currentStep = this._steps[i]; if(currentStep.TemplateName == templateName){ this._toggleLoaderOverlay(true); this.activateStep(i); foundTemplate= true; break; } } if(!foundTemplate) { console.warn('Template '+templateName+' not found in _onSwitchToStep() / '+this.declaredClass); } }, _onCancel : function() { // summary: event function - redirect to cancel page if(this.cancelRedirectURL != "") { epages.locationHref(this.cancelRedirectURL ); } } } );