Sample Code + Screenshots

WebStorm Project Setup

Gulp file


		var gulp = require('gulp'),
		    sass = require('gulp-sass'),
		    autoprefixer = require('gulp-autoprefixer'),
		    minifyCss = require('gulp-minify-css'),
		    rename = require('gulp-rename'),
		    include = require('gulp-include'),
		    concat = require('gulp-concat'),
		    uglify = require('gulp-uglify'),
		    cp = require('child_process'),
		    spawn = cp.spawn,
		    exec = cp.exec,
		    gutil = require('gulp-util'),
		    sequence = require('run-sequence'),
		    browserSync = require('browser-sync').create(),
		    reload = browserSync.reload,
		    //ghPages = require('gulp-gh-pages'),
		    consolidate = require('gulp-consolidate'),
		    iconfont = require('gulp-iconfont'),
		    mochaSelenium = require('gulp-mocha-selenium');


		var srcDir = 'src/',
		    distDir = '_dist/',
		    docsDir = 'docs/';


		var paths = {
		    styles: {
		       src: srcDir + 'sass/main.scss',
		       dist: distDir + 'css/'
		    },
		    scripts: {
		        src: srcDir + 'js/mage-bootstrap.js',
		        dist: distDir + 'js/'
		    },
		    fonts: {
		        src: srcDir + 'fonts/**/*',
		        dist: distDir + 'fonts/'
		    },
		    icons: {
		        src: srcDir + 'icons/**/*.svg'
		    }
		};

		gulp.task('build:styles', function() {
		    return gulp.src(paths.styles.src)
		        .pipe(sass())
		        .pipe(autoprefixer())
		        .pipe(rename('mage-bootstrap.css'))
		        .pipe(gulp.dest(paths.styles.dist))
		        .pipe(minifyCss())
		        .pipe(rename('mage-bootstrap.min.css'))
		        .pipe(gulp.dest(paths.styles.dist));
		});

		gulp.task('build:doc_styles', function() {
		    return gulp.src('src/sass/docs.scss')
		        .pipe(sass())
		        .pipe(autoprefixer())
		        .pipe(minifyCss())
		        .pipe(gulp.dest(paths.styles.dist));
		});

		gulp.task('build:icons', function() {
		    gulp.src(paths.icons.src)
		        .pipe(iconfont({
		            fontName: 'mage-icons', // required
		            appendUnicode: false // recommended option
		        }))
		        .on('glyphs', function(glyphs/*, options*/) {
		            for (var i = 0; i < glyphs.length; i++) {
		                glyphs[i].cssEntity = glyphs[i].unicode[0].charCodeAt(0).toString(16).toUpperCase()
		            }
		            gulp.src(srcDir + 'sass/mage-bootstrap/_icons.scss.swig')
		            .pipe(consolidate('swig', {
		                glyphs: glyphs,
		                fontName: 'mage-icons',
		                fontPath: '../fonts/mage-icons/',
		                className: 'icon'
		            }))
		            .pipe(rename('_icons.scss'))
		            .pipe(gulp.dest(srcDir + 'sass/mage-bootstrap/'));

		            // Here we pipe our glyphicons to a json data file for jekyll to generate an icon grid in the documentation.
		            gulp.src(docsDir + '_includes/icon-data.json.swig')
		                .pipe(consolidate('swig', {
		                    glyphs: glyphs,
		                    fontName: 'mage-icons',
		                    fontPath: '../fonts/',
		                    className: 'icon'
		                }))
		                .pipe(rename('icons.json'))
		                .pipe(gulp.dest(docsDir + '_data/'));


		        })
		        .pipe(gulp.dest(paths.fonts.dist + 'mage-icons/'));
		});


		gulp.task('build:scripts', function() {
		    return gulp.src(paths.scripts.src)
		        .pipe(include())
		        .pipe(gulp.dest(paths.scripts.dist))
		        .pipe(uglify())
		        .pipe(rename('mage-bootstrap.min.js'))
		        .pipe(gulp.dest(paths.scripts.dist));
		});

		gulp.task('build:jekyll', function(done) {
		    var jekyll = exec('jekyll build', {stdio: 'inherit'}, function(error, stdout, stdin) {
		        gutil.log(error, stdout, stdin);
		        done(error == null ? null : 'ERROR: Jekyll process exited with code: '+error);
		    });

		    //jekyll.on('data', function(data) {
		    //    console.log(data);
		    //});
		    //return jekyll.on('exit', function(code) {
		    //    done(code === 0 ? null : 'ERROR: Jekyll process exited with code: '+code);
		    //});
		});

		gulp.task('build:jekyll:github', function(done) {
		    var jekyll = spawn('jekyll', ['build', '--config=_gh_pages_config.yml'], {stdio: 'inherit'});
		    return jekyll.on('exit', function(code) {
		        done(code === 0 ? null : 'ERROR: Jekyll process exited with code: ' + code);
		    });
		});

		gulp.task('sanitize:icons', function() {
		    gulp.src(paths.icons.src)
		        .pipe(rename(function (path) {
		            path.basename = path.basename.replace('-_', '');
		        }))
		        .pipe(gulp.dest(srcDir + 'icons/'));
		});

		gulp.task('build', function(done) {
		    sequence('build:styles', 'build:doc_styles', 'build:scripts', 'build:jekyll', 'copy:assets', done);
		});

		gulp.task('build:github', function(done) {
		    sequence('build:styles', 'build:doc_styles', 'build:scripts', 'build:jekyll:github', 'copy:assets', done);
		});

		gulp.task('copy:assets', function() {
		    gulp.src(distDir + '**/*')
		        //.pipe(gulp.dest(docsDir + 'assets/'))
		        .pipe(gulp.dest('_site/assets/'));

		    gulp.src(srcDir + 'img/**/*')
		        .pipe(gulp.dest(docsDir + 'assets/img/'))
		        .pipe(gulp.dest(distDir + 'img/'))
		        .pipe(gulp.dest('_site/assets/img/'))
		});

		gulp.task('build:dist', function() {
		    sequence('build', function() {
		        gulp.src(distDir + '**/*')
		            .pipe(gulp.dest('dist/'));
		    });
		});

		gulp.task('serve', function() {
		    browserSync.init({
		        server: {
		            baseDir: '_site'
		        }
		    });
		});

		gulp.task('watch', function() {

		    // Watch for SASS changes
		    gulp.watch(srcDir + 'sass/**/*.scss', function() {
		        sequence('build:styles', 'build:doc_styles', 'copy:assets', function() { reload(); });
		    });

		    // Watch for HTML changes
		    gulp.watch([docsDir + '/**/*.html', docsDir + '/**/*.md'], function() {
		        sequence('build:jekyll', 'copy:assets', function() { reload(); });
		    });

		    // Watch for Javascript Changes
		    gulp.watch(srcDir + 'js/**/*.js', function() {
		        sequence('build:scripts', 'copy:assets', function() { reload(); });
		    });
		});

		gulp.task('dev', function() {
		    return sequence('build', 'serve', 'watch');
		});

		gulp.task('run:tests', function() {
		    return gulp.src('tests/sanity.js', {read: false})
		        .pipe(mochaSelenium({
		            browserName: 'chrome',
		            reporter: 'nyan'
		        }));
		});
		
		
	

Wizard Plugin

/**
	 *
	 * The purpose of $.fn.wizard is to dynamically generate a wizard for a multi-step process.
	 *
	 */


	+function ($) {

	    'use strict';

	    $.fn.wizard = function (options, callback) {

	        var $wizard = $(this),
	            current_step,
	            next_step,
	            prev_step;


	        var defaults = {
	            nextButtonClass: "next-button",
	            prevButtonClass: "prev-button"
	        };

	        var settings = $.extend({}, defaults, options);


	        var $nextButton = $wizard.find("." + settings.nextButtonClass);
	        var $prevButton = $wizard.find("." + settings.prevButtonClass);

	        $nextButton.on("click", goToNextStep);
	        $prevButton.on("click", goToPrevStep);

	        function getCurrentStep() {
	            current_step = $nextButton.data("current-step");
	            return current_step;
	        }

	        function getNextStep() {
	            next_step = $nextButton.data("next-step");
	            return next_step;
	        }

	        function getPrevStep() {
	            prev_step = $prevButton.data("prev-step");
	            return prev_step;
	        }

	        function reorderSteps() {

	            var total_steps = $(".wizard-step").length;

	            current_step = getCurrentStep();
	            next_step = current_step + 1;
	            prev_step = current_step - 1;

	            $prevButton.data("prev-step", prev_step);
	            $nextButton.data("next-step", next_step);

	            //set the next step
	            setNextStep(current_step, total_steps);

	            //set the prev step
	            setPrevStep(current_step, prev_step);
	        }

	        function setNextStep(current, total) {
	            if (current == total) {
	                $nextButton.addClass("disabled");
	            } else {
	                $nextButton.removeClass("disabled");
	                $prevButton.removeClass("disabled");
	            }
	        }

	        function setPrevStep(current, prev) {
	            if (current == 1) {
	                $prevButton.addClass("disabled");
	            } else {
	                $prevButton.removeClass("disabled");
	                $prevButton.data("prev-step", prev);
	            }
	        }

	        function goToNextStep() {

	            var new_current = getCurrentStep() + 1;
	            $nextButton.data("current-step", new_current);

	            reorderSteps();

	            new_current = getCurrentStep();
	            var new_prev = getPrevStep();

	            toggleStepContent(new_current, new_prev);
	            updateProgressTracker(new_current);

	        }


	        function goToPrevStep() {

	            var new_current = current_step - 1;
	            $nextButton.data("current-step", new_current);

	            reorderSteps();

	            current_step = getCurrentStep();
	            var new_next = getNextStep();

	            toggleStepContent(current_step, new_next);
	            updateProgressTracker(current_step, new_next);

	        }

	        function toggleStepContent(current, former) {

	            //console.log("wizard content Id : " + settings.wizardContentId);
	            $wizard.find(".wizard-step").each(function() {
	                var step = $(this);
	                if (step.data("step") == current) {

	                    //display new current step content
	                    step.addClass("active");

	                    //hide prev step content
	                    if (former < current) {
	                        step.prev().removeClass("active");
	                    } else {
	                        step.next().removeClass("active");
	                    }
	                }
	            });
	        }

	        function updateProgressTracker(current, nextStep) {

	            $wizard.find("ul > li").each(function(){
	                var tracker = $(this);
	                if (tracker.data("tracker") == current){
	                    tracker.addClass("active");
	                    tracker.addClass("visited");

	                    if (nextStep) {

	                        var $nextTracker = tracker.next();
	                        $nextTracker.removeClass("active");
	                        $nextTracker.removeClass("visited");
	                    }
	                }
	            });

	        }
	    }

	    return this;


	}(jQuery);

	$(document).ready(function () {
	    $("#wizard").wizard();

	});

UX Design