diff --git a/dist/angular-wizard.js b/dist/angular-wizard.js index dd7c148..9444cee 100644 --- a/dist/angular-wizard.js +++ b/dist/angular-wizard.js @@ -1,6 +1,6 @@ /** * Easy to use Wizard library for AngularJS - * @version v0.4.2 - 2015-01-01 * @link https://github.com/mgonto/angular-wizard + * @version v0.4.2 - 2015-03-27 * @link https://github.com/mgonto/angular-wizard * @author Martin Gontovnikas * @license MIT License, http://www.opensource.org/licenses/MIT */ @@ -17,7 +17,7 @@ angular.module("wizard.html", []).run(["$templateCache", function($templateCache "
\n" + "
\n" + " \n" + @@ -27,7 +27,7 @@ angular.module("wizard.html", []).run(["$templateCache", function($templateCache angular.module('mgo-angular-wizard', ['templates-angularwizard']); -angular.module('mgo-angular-wizard').directive('wzStep', function() { +angular.module('mgo-angular-wizard').directive('wzStep', ['$rootScope', function($rootScope) { return { restrict: 'EA', replace: true, @@ -36,7 +36,8 @@ angular.module('mgo-angular-wizard').directive('wzStep', function() { wzTitle: '@', title: '@', canenter : '=', - canexit : '=' + canexit : '=', + orderIndex:'@' }, require: '^wizard', templateUrl: function(element, attributes) { @@ -44,13 +45,22 @@ angular.module('mgo-angular-wizard').directive('wzStep', function() { }, link: function($scope, $element, $attrs, wizard) { $scope.title = $scope.title || $scope.wzTitle; - wizard.addStep($scope); + + //for nested wizards. Add step when tempate for wizard is ready. + if (wizard.transcluded){ + wizard.addStep($scope); + } + else { + $rootScope.$on('mgo-angular-wizard.transcluded', function($event, wzName){ + if (wizard.name==wzName) wizard.addStep($scope); + }); + } } }; -}); +}]); //wizard directive -angular.module('mgo-angular-wizard').directive('wizard', function() { +angular.module('mgo-angular-wizard').directive('wizard',['$rootScope', function($rootScope) { return { restrict: 'EA', replace: true, @@ -66,19 +76,63 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { return attributes.template || "wizard.html"; }, + link: function($scope, $element, $attributes){ + + var get_stepnodes = function (parent) + { + var matchingElements = []; + var allElements = parent[0].getElementsByTagName('*'); + for (var i = 0, n = allElements.length; i < n; i++) + { + var current = allElements[i], + $current = angular.element(current); + + if (!_.isUndefined($current.attr('wz-step')) || current.nodeName.toLowerCase()=='wz-step' || $current.hasClass('step')) + { + // Element exists with attribute. Add to array. + matchingElements.push($current.attr('title') || $current.attr('wz-title')); + } + } + return matchingElements; + }; + + //Determination ordering steps from DOM + $scope.steps_ordering = get_stepnodes($element); + + $scope.steps_count = $scope.steps_ordering.length; + + //steps array where all the scopes of each step are added + $scope.steps = new Array($scope.steps_count); + + //nested wizards hack + $scope.transcluded = true; + $rootScope.$broadcast('mgo-angular-wizard.transcluded', $scope.name); + + }, //controller for wizard directive, treat this just like an angular controller controller: ['$scope', '$element', '$log', 'WizardHandler', function($scope, $element, $log, WizardHandler) { //this variable allows directive to load without having to pass any step validation var firstRun = true; + + this.name = $scope.name || WizardHandler.defaultName; + + $scope.name = this.name; + //creating instance of wizard, passing this as second argument allows access to functions attached to this via Service - WizardHandler.addWizard($scope.name || WizardHandler.defaultName, this); + WizardHandler.addWizard(this.name, this); $scope.$on('$destroy', function() { WizardHandler.removeWizard($scope.name || WizardHandler.defaultName); }); - //steps array where all the scopes of each step are added - $scope.steps = []; + //nested wizards hack + this.transcluded = $scope.transcluded || false; + + var thisModule = this; + + $scope.$watch('transcluded', function(val){ + if (val) thisModule.transcluded = true; + }); //access to context object for step validation $scope.context = {}; @@ -86,10 +140,10 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { //watching changes to currentStep $scope.$watch('currentStep', function(step) { //checking to make sure currentStep is truthy value - if (!step) return; + if (!step || _.isUndefined($scope.selectedStep)) return; //setting stepTitle equal to current step title or default title var stepTitle = $scope.selectedStep.title || $scope.selectedStep.wzTitle; - if ($scope.selectedStep && stepTitle !== $scope.currentStep) { + if (stepTitle !== $scope.currentStep) { //invoking goTo() with step title as argument $scope.goTo(_.findWhere($scope.steps, {title: $scope.currentStep})); } @@ -104,17 +158,30 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { if (editMode) { _.each($scope.steps, function(step) { - step.completed = true; + if (!_.isUndefined(step)) step.completed = true; }); } }, true); //called each time step directive is loaded this.addStep = function(step) { - //pushing the scope of directive onto step array - $scope.steps.push(step); + + step.selected = false; + //Determination of the sequence number step. + var index; + if (!_.isUndefined(step.orderIndex)) { + index = step.orderIndex; + } + else { + index = _.indexOf($scope.steps_ordering , step.title); + } + + //inserting the scope of directive onto step array in view of the order + $scope.steps[index] = step; + + //if this is first step being pushed then goTo that first step - if ($scope.steps.length === 1) { + if (index === 0) { //goTo first step $scope.goTo($scope.steps[0]); } @@ -194,7 +261,7 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { function unselectAll() { //traverse steps array and set each "selected" property to false _.each($scope.steps, function (step) { - step.selected = false; + if (step) step.selected = false; }); //set selectedStep variable to null $scope.selectedStep = null; @@ -234,7 +301,7 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { //invoking goTo() with step number next in line $scope.goTo($scope.steps[index + 1]); } - + }; //used to traverse to any step, step number placed as argument @@ -272,7 +339,7 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { }; }] }; -}); +}]); function wizardButtonDirective(action) { angular.module('mgo-angular-wizard') .directive(action, function() { diff --git a/dist/angular-wizard.min.js b/dist/angular-wizard.min.js index 24557d7..aae0645 100644 --- a/dist/angular-wizard.min.js +++ b/dist/angular-wizard.min.js @@ -1,7 +1,7 @@ /** * Easy to use Wizard library for AngularJS - * @version v0.4.2 - 2015-01-01 * @link https://github.com/mgonto/angular-wizard + * @version v0.4.2 - 2015-03-27 * @link https://github.com/mgonto/angular-wizard * @author Martin Gontovnikas * @license MIT License, http://www.opensource.org/licenses/MIT */ -function wizardButtonDirective(a){angular.module("mgo-angular-wizard").directive(a,function(){return{restrict:"A",replace:!1,require:"^wizard",link:function(b,c,d,e){c.on("click",function(c){c.preventDefault(),b.$apply(function(){b.$eval(d[a]),e[a.replace("wz","").toLowerCase()]()})})}}})}angular.module("templates-angularwizard",["step.html","wizard.html"]),angular.module("step.html",[]).run(["$templateCache",function(a){a.put("step.html",'
\n
')}]),angular.module("wizard.html",[]).run(["$templateCache",function(a){a.put("wizard.html",'
\n
\n \n
\n')}]),angular.module("mgo-angular-wizard",["templates-angularwizard"]),angular.module("mgo-angular-wizard").directive("wzStep",function(){return{restrict:"EA",replace:!0,transclude:!0,scope:{wzTitle:"@",title:"@",canenter:"=",canexit:"="},require:"^wizard",templateUrl:function(a,b){return b.template||"step.html"},link:function(a,b,c,d){a.title=a.title||a.wzTitle,d.addStep(a)}}}),angular.module("mgo-angular-wizard").directive("wizard",function(){return{restrict:"EA",replace:!0,transclude:!0,scope:{currentStep:"=",onFinish:"&",hideIndicators:"=",editMode:"=",name:"@"},templateUrl:function(a,b){return b.template||"wizard.html"},controller:["$scope","$element","$log","WizardHandler",function(a,b,c,d){function e(){_.each(a.steps,function(a){a.selected=!1}),a.selectedStep=null}var f=!0;d.addWizard(a.name||d.defaultName,this),a.$on("$destroy",function(){d.removeWizard(a.name||d.defaultName)}),a.steps=[],a.context={},a.$watch("currentStep",function(b){if(b){var c=a.selectedStep.title||a.selectedStep.wzTitle;a.selectedStep&&c!==a.currentStep&&a.goTo(_.findWhere(a.steps,{title:a.currentStep}))}}),a.$watch("[editMode, steps.length]",function(){var b=a.editMode;_.isUndefined(b)||_.isNull(b)||b&&_.each(a.steps,function(a){a.completed=!0})},!0),this.addStep=function(b){a.steps.push(b),1===a.steps.length&&a.goTo(a.steps[0])},this.context=a.context,a.getStepNumber=function(b){return _.indexOf(a.steps,b)+1},a.goTo=function(b){if(f)e(),a.selectedStep=b,_.isUndefined(a.currentStep)||(a.currentStep=b.title||b.wzTitle),b.selected=!0,a.$emit("wizard:stepChanged",{step:b,index:_.indexOf(a.steps,b)}),f=!1;else{var c,d=!1,g=!1;if(a.currentStepNumber()>0?c=a.currentStepNumber()-1:0===a.currentStepNumber()&&(c=0),("undefined"==typeof a.steps[c].canexit||a.steps[c].canexit(a.context)===!0)&&(d=!0),a.getStepNumber(b)\n')}]),angular.module("wizard.html",[]).run(["$templateCache",function(a){a.put("wizard.html",'
\n
\n \n
\n')}]),angular.module("mgo-angular-wizard",["templates-angularwizard"]),angular.module("mgo-angular-wizard").directive("wzStep",["$rootScope",function(a){return{restrict:"EA",replace:!0,transclude:!0,scope:{wzTitle:"@",title:"@",canenter:"=",canexit:"=",orderIndex:"@"},require:"^wizard",templateUrl:function(a,b){return b.template||"step.html"},link:function(b,c,d,e){b.title=b.title||b.wzTitle,e.transcluded?e.addStep(b):a.$on("mgo-angular-wizard.transcluded",function(a,c){e.name==c&&e.addStep(b)})}}}]),angular.module("mgo-angular-wizard").directive("wizard",["$rootScope",function(a){return{restrict:"EA",replace:!0,transclude:!0,scope:{currentStep:"=",onFinish:"&",hideIndicators:"=",editMode:"=",name:"@"},templateUrl:function(a,b){return b.template||"wizard.html"},link:function(b,c){var d=function(a){for(var b=[],c=a[0].getElementsByTagName("*"),d=0,e=c.length;e>d;d++){var f=c[d],g=angular.element(f);(!_.isUndefined(g.attr("wz-step"))||"wz-step"==f.nodeName.toLowerCase()||g.hasClass("step"))&&b.push(g.attr("title")||g.attr("wz-title"))}return b};b.steps_ordering=d(c),b.steps_count=b.steps_ordering.length,b.steps=new Array(b.steps_count),b.transcluded=!0,a.$broadcast("mgo-angular-wizard.transcluded",b.name)},controller:["$scope","$element","$log","WizardHandler",function(a,b,c,d){function e(){_.each(a.steps,function(a){a&&(a.selected=!1)}),a.selectedStep=null}var f=!0;this.name=a.name||d.defaultName,a.name=this.name,d.addWizard(this.name,this),a.$on("$destroy",function(){d.removeWizard(a.name||d.defaultName)}),this.transcluded=a.transcluded||!1;var g=this;a.$watch("transcluded",function(a){a&&(g.transcluded=!0)}),a.context={},a.$watch("currentStep",function(b){if(b&&!_.isUndefined(a.selectedStep)){var c=a.selectedStep.title||a.selectedStep.wzTitle;c!==a.currentStep&&a.goTo(_.findWhere(a.steps,{title:a.currentStep}))}}),a.$watch("[editMode, steps.length]",function(){var b=a.editMode;_.isUndefined(b)||_.isNull(b)||b&&_.each(a.steps,function(a){_.isUndefined(a)||(a.completed=!0)})},!0),this.addStep=function(b){b.selected=!1;var c;c=_.isUndefined(b.orderIndex)?_.indexOf(a.steps_ordering,b.title):b.orderIndex,a.steps[c]=b,0===c&&a.goTo(a.steps[0])},this.context=a.context,a.getStepNumber=function(b){return _.indexOf(a.steps,b)+1},a.goTo=function(b){if(f)e(),a.selectedStep=b,_.isUndefined(a.currentStep)||(a.currentStep=b.title||b.wzTitle),b.selected=!0,a.$emit("wizard:stepChanged",{step:b,index:_.indexOf(a.steps,b)}),f=!1;else{var c,d=!1,g=!1;if(a.currentStepNumber()>0?c=a.currentStepNumber()-1:0===a.currentStepNumber()&&(c=0),("undefined"==typeof a.steps[c].canexit||a.steps[c].canexit(a.context)===!0)&&(d=!0),a.getStepNumber(b)
diff --git a/src/wizard.js b/src/wizard.js index 3109cba..c9a807a 100644 --- a/src/wizard.js +++ b/src/wizard.js @@ -1,5 +1,5 @@ //wizard directive -angular.module('mgo-angular-wizard').directive('wizard', function() { +angular.module('mgo-angular-wizard').directive('wizard',['$rootScope', function($rootScope) { return { restrict: 'EA', replace: true, @@ -15,19 +15,63 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { return attributes.template || "wizard.html"; }, + link: function($scope, $element, $attributes){ + + var get_stepnodes = function (parent) + { + var matchingElements = []; + var allElements = parent[0].getElementsByTagName('*'); + for (var i = 0, n = allElements.length; i < n; i++) + { + var current = allElements[i], + $current = angular.element(current); + + if (!_.isUndefined($current.attr('wz-step')) || current.nodeName.toLowerCase()=='wz-step' || $current.hasClass('step')) + { + // Element exists with attribute. Add to array. + matchingElements.push($current.attr('title') || $current.attr('wz-title')); + } + } + return matchingElements; + }; + + //Determination ordering steps from DOM + $scope.steps_ordering = get_stepnodes($element); + + $scope.steps_count = $scope.steps_ordering.length; + + //steps array where all the scopes of each step are added + $scope.steps = new Array($scope.steps_count); + + //nested wizards hack + $scope.transcluded = true; + $rootScope.$broadcast('mgo-angular-wizard.transcluded', $scope.name); + + }, //controller for wizard directive, treat this just like an angular controller controller: ['$scope', '$element', '$log', 'WizardHandler', function($scope, $element, $log, WizardHandler) { //this variable allows directive to load without having to pass any step validation var firstRun = true; + + this.name = $scope.name || WizardHandler.defaultName; + + $scope.name = this.name; + //creating instance of wizard, passing this as second argument allows access to functions attached to this via Service - WizardHandler.addWizard($scope.name || WizardHandler.defaultName, this); + WizardHandler.addWizard(this.name, this); $scope.$on('$destroy', function() { WizardHandler.removeWizard($scope.name || WizardHandler.defaultName); }); - //steps array where all the scopes of each step are added - $scope.steps = []; + //nested wizards hack + this.transcluded = $scope.transcluded || false; + + var thisModule = this; + + $scope.$watch('transcluded', function(val){ + if (val) thisModule.transcluded = true; + }); //access to context object for step validation $scope.context = {}; @@ -35,10 +79,10 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { //watching changes to currentStep $scope.$watch('currentStep', function(step) { //checking to make sure currentStep is truthy value - if (!step) return; + if (!step || _.isUndefined($scope.selectedStep)) return; //setting stepTitle equal to current step title or default title var stepTitle = $scope.selectedStep.title || $scope.selectedStep.wzTitle; - if ($scope.selectedStep && stepTitle !== $scope.currentStep) { + if (stepTitle !== $scope.currentStep) { //invoking goTo() with step title as argument $scope.goTo(_.findWhere($scope.steps, {title: $scope.currentStep})); } @@ -53,17 +97,30 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { if (editMode) { _.each($scope.steps, function(step) { - step.completed = true; + if (!_.isUndefined(step)) step.completed = true; }); } }, true); //called each time step directive is loaded this.addStep = function(step) { - //pushing the scope of directive onto step array - $scope.steps.push(step); + + step.selected = false; + //Determination of the sequence number step. + var index; + if (!_.isUndefined(step.orderIndex)) { + index = step.orderIndex; + } + else { + index = _.indexOf($scope.steps_ordering , step.title); + } + + //inserting the scope of directive onto step array in view of the order + $scope.steps[index] = step; + + //if this is first step being pushed then goTo that first step - if ($scope.steps.length === 1) { + if (index === 0) { //goTo first step $scope.goTo($scope.steps[0]); } @@ -143,7 +200,7 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { function unselectAll() { //traverse steps array and set each "selected" property to false _.each($scope.steps, function (step) { - step.selected = false; + if (step) step.selected = false; }); //set selectedStep variable to null $scope.selectedStep = null; @@ -183,7 +240,7 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { //invoking goTo() with step number next in line $scope.goTo($scope.steps[index + 1]); } - + }; //used to traverse to any step, step number placed as argument @@ -221,4 +278,4 @@ angular.module('mgo-angular-wizard').directive('wizard', function() { }; }] }; -}); +}]); \ No newline at end of file