diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 496ee2c..6a502e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,16 @@ -.DS_Store \ No newline at end of file +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +# Ignore bundler config. +/.bundle + +# Ignore the default SQLite database. +/db/*.sqlite3 +/db/*.sqlite3-journal + +# Ignore all logfiles and tempfiles. +/log/*.log +/tmp diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..6219184 --- /dev/null +++ b/Gemfile @@ -0,0 +1,40 @@ +source 'https://rubygems.org' + + +# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' +gem 'rails', '4.1.4' +# Use sqlite3 as the database for Active Record +gem 'sqlite3' +# Use SCSS for stylesheets +gem 'sass-rails', '~> 4.0.3' +# Use Uglifier as compressor for JavaScript assets +gem 'uglifier', '>= 1.3.0' +# Use CoffeeScript for .js.coffee assets and views +gem 'coffee-rails', '~> 4.0.0' +# See https://github.com/sstephenson/execjs#readme for more supported runtimes +# gem 'therubyracer', platforms: :ruby + +# Use jquery as the JavaScript library +gem 'jquery-rails' +# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks +gem 'turbolinks' +# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder +gem 'jbuilder', '~> 2.0' +# bundle exec rake doc:rails generates the API under doc/api. +gem 'sdoc', '~> 0.4.0', group: :doc + +# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring +gem 'spring', group: :development + +# Use ActiveModel has_secure_password +# gem 'bcrypt', '~> 3.1.7' + +# Use unicorn as the app server +# gem 'unicorn' + +# Use Capistrano for deployment +# gem 'capistrano-rails', group: :development + +# Use debugger +# gem 'debugger', group: [:development, :test] + diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..68e7637 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,125 @@ +GEM + remote: https://rubygems.org/ + specs: + actionmailer (4.1.4) + actionpack (= 4.1.4) + actionview (= 4.1.4) + mail (~> 2.5.4) + actionpack (4.1.4) + actionview (= 4.1.4) + activesupport (= 4.1.4) + rack (~> 1.5.2) + rack-test (~> 0.6.2) + actionview (4.1.4) + activesupport (= 4.1.4) + builder (~> 3.1) + erubis (~> 2.7.0) + activemodel (4.1.4) + activesupport (= 4.1.4) + builder (~> 3.1) + activerecord (4.1.4) + activemodel (= 4.1.4) + activesupport (= 4.1.4) + arel (~> 5.0.0) + activesupport (4.1.4) + i18n (~> 0.6, >= 0.6.9) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.1) + tzinfo (~> 1.1) + arel (5.0.1.20140414130214) + builder (3.2.2) + coffee-rails (4.0.1) + coffee-script (>= 2.2.0) + railties (>= 4.0.0, < 5.0) + coffee-script (2.3.0) + coffee-script-source + execjs + coffee-script-source (1.7.1) + erubis (2.7.0) + execjs (2.2.1) + hike (1.2.3) + i18n (0.6.11) + jbuilder (2.1.3) + activesupport (>= 3.0.0, < 5) + multi_json (~> 1.2) + jquery-rails (3.1.1) + railties (>= 3.0, < 5.0) + thor (>= 0.14, < 2.0) + json (1.8.1) + mail (2.5.4) + mime-types (~> 1.16) + treetop (~> 1.4.8) + mime-types (1.25.1) + minitest (5.4.0) + multi_json (1.10.1) + polyglot (0.3.5) + rack (1.5.2) + rack-test (0.6.2) + rack (>= 1.0) + rails (4.1.4) + actionmailer (= 4.1.4) + actionpack (= 4.1.4) + actionview (= 4.1.4) + activemodel (= 4.1.4) + activerecord (= 4.1.4) + activesupport (= 4.1.4) + bundler (>= 1.3.0, < 2.0) + railties (= 4.1.4) + sprockets-rails (~> 2.0) + railties (4.1.4) + actionpack (= 4.1.4) + activesupport (= 4.1.4) + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (10.3.2) + rdoc (4.1.1) + json (~> 1.4) + sass (3.2.19) + sass-rails (4.0.3) + railties (>= 4.0.0, < 5.0) + sass (~> 3.2.0) + sprockets (~> 2.8, <= 2.11.0) + sprockets-rails (~> 2.0) + sdoc (0.4.0) + json (~> 1.8) + rdoc (~> 4.0, < 5.0) + spring (1.1.3) + sprockets (2.11.0) + hike (~> 1.2) + multi_json (~> 1.0) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + sprockets-rails (2.1.3) + actionpack (>= 3.0) + activesupport (>= 3.0) + sprockets (~> 2.8) + sqlite3 (1.3.9) + thor (0.19.1) + thread_safe (0.3.4) + tilt (1.4.1) + treetop (1.4.15) + polyglot + polyglot (>= 0.3.1) + turbolinks (2.2.2) + coffee-rails + tzinfo (1.2.1) + thread_safe (~> 0.1) + uglifier (2.5.3) + execjs (>= 0.3.0) + json (>= 1.8.0) + +PLATFORMS + ruby + +DEPENDENCIES + coffee-rails (~> 4.0.0) + jbuilder (~> 2.0) + jquery-rails + rails (= 4.1.4) + sass-rails (~> 4.0.3) + sdoc (~> 0.4.0) + spring + sqlite3 + turbolinks + uglifier (>= 1.3.0) diff --git a/README.rdoc b/README.rdoc new file mode 100644 index 0000000..dd4e97e --- /dev/null +++ b/README.rdoc @@ -0,0 +1,28 @@ +== README + +This README would normally document whatever steps are necessary to get the +application up and running. + +Things you may want to cover: + +* Ruby version + +* System dependencies + +* Configuration + +* Database creation + +* Database initialization + +* How to run the test suite + +* Services (job queues, cache servers, search engines, etc.) + +* Deployment instructions + +* ... + + +Please feel free to use a different markup language if you do not plan to run +rake doc:app. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..ba6b733 --- /dev/null +++ b/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +Rails.application.load_tasks diff --git a/app/assets/images/.keep b/app/assets/images/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 0000000..d6925fa --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,16 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. +// +// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require jquery +//= require jquery_ujs +//= require turbolinks +//= require_tree . diff --git a/app/assets/javascripts/forms.js b/app/assets/javascripts/forms.js new file mode 100644 index 0000000..cb0ed6f --- /dev/null +++ b/app/assets/javascripts/forms.js @@ -0,0 +1,9 @@ +$(document).ready(function() { + + $('#generate').click(function(){ + $('#command_line').val("ffmpeg" + + " -i " + $('#input_name').val() + + " -o " + $('#output_name').val()) + }); + +}); diff --git a/app/assets/javascripts/forms.js.coffee b/app/assets/javascripts/forms.js.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/forms.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/jquery.steps.js b/app/assets/javascripts/jquery.steps.js new file mode 100755 index 0000000..4eb5126 --- /dev/null +++ b/app/assets/javascripts/jquery.steps.js @@ -0,0 +1,2015 @@ +/*! + * jQuery Steps v1.0.7 - 05/07/2014 + * Copyright (c) 2014 Rafael Staib (http://www.jquery-steps.com) + * Licensed under MIT http://www.opensource.org/licenses/MIT + */ +;(function ($, undefined) +{ +$.fn.extend({ + _aria: function (name, value) + { + return this.attr("aria-" + name, value); + }, + + _removeAria: function (name) + { + return this.removeAttr("aria-" + name); + }, + + _enableAria: function (enable) + { + return (enable == null || enable) ? + this.removeClass("disabled")._aria("disabled", "false") : + this.addClass("disabled")._aria("disabled", "true"); + }, + + _showAria: function (show) + { + return (show == null || show) ? + this.show()._aria("hidden", "false") : + this.hide()._aria("hidden", "true"); + }, + + _selectAria: function (select) + { + return (select == null || select) ? + this.addClass("current")._aria("selected", "true") : + this.removeClass("current")._aria("selected", "false"); + }, + + _id: function (id) + { + return (id) ? this.attr("id", id) : this.attr("id"); + } +}); + +if (!String.prototype.format) +{ + String.prototype.format = function() + { + var args = (arguments.length === 1 && $.isArray(arguments[0])) ? arguments[0] : arguments; + var formattedString = this; + for (var i = 0; i < args.length; i++) + { + var pattern = new RegExp("\\{" + i + "\\}", "gm"); + formattedString = formattedString.replace(pattern, args[i]); + } + return formattedString; + }; +} + +/** + * A global unique id count. + * + * @static + * @private + * @property _uniqueId + * @type Integer + **/ +var _uniqueId = 0; + +/** + * The plugin prefix for cookies. + * + * @final + * @private + * @property _cookiePrefix + * @type String + **/ +var _cookiePrefix = "jQu3ry_5teps_St@te_"; + +/** + * Suffix for the unique tab id. + * + * @final + * @private + * @property _tabSuffix + * @type String + * @since 0.9.7 + **/ +var _tabSuffix = "-t-"; + +/** + * Suffix for the unique tabpanel id. + * + * @final + * @private + * @property _tabpanelSuffix + * @type String + * @since 0.9.7 + **/ +var _tabpanelSuffix = "-p-"; + +/** + * Suffix for the unique title id. + * + * @final + * @private + * @property _titleSuffix + * @type String + * @since 0.9.7 + **/ +var _titleSuffix = "-h-"; + +/** + * An error message for an "index out of range" error. + * + * @final + * @private + * @property _indexOutOfRangeErrorMessage + * @type String + **/ +var _indexOutOfRangeErrorMessage = "Index out of range."; + +/** + * An error message for an "missing corresponding element" error. + * + * @final + * @private + * @property _missingCorrespondingElementErrorMessage + * @type String + **/ +var _missingCorrespondingElementErrorMessage = "One or more corresponding step {0} are missing."; + +/** + * Adds a step to the cache. + * + * @static + * @private + * @method addStepToCache + * @param wizard {Object} A jQuery wizard object + * @param step {Object} The step object to add + **/ +function addStepToCache(wizard, step) +{ + getSteps(wizard).push(step); +} + +function analyzeData(wizard, options, state) +{ + var stepTitles = wizard.children(options.headerTag), + stepContents = wizard.children(options.bodyTag); + + // Validate content + if (stepTitles.length > stepContents.length) + { + throwError(_missingCorrespondingElementErrorMessage, "contents"); + } + else if (stepTitles.length < stepContents.length) + { + throwError(_missingCorrespondingElementErrorMessage, "titles"); + } + + var startIndex = options.startIndex; + + state.stepCount = stepTitles.length; + + // Tries to load the saved state (step position) + if (options.saveState && $.cookie) + { + var savedState = $.cookie(_cookiePrefix + getUniqueId(wizard)); + // Sets the saved position to the start index if not undefined or out of range + var savedIndex = parseInt(savedState, 0); + if (!isNaN(savedIndex) && savedIndex < state.stepCount) + { + startIndex = savedIndex; + } + } + + state.currentIndex = startIndex; + + stepTitles.each(function (index) + { + var item = $(this), // item == header + content = stepContents.eq(index), + modeData = content.data("mode"), + mode = (modeData == null) ? contentMode.html : getValidEnumValue(contentMode, + (/^\s*$/.test(modeData) || isNaN(modeData)) ? modeData : parseInt(modeData, 0)), + contentUrl = (mode === contentMode.html || content.data("url") === undefined) ? + "" : content.data("url"), + contentLoaded = (mode !== contentMode.html && content.data("loaded") === "1"), + step = $.extend({}, stepModel, { + title: item.html(), + content: (mode === contentMode.html) ? content.html() : "", + contentUrl: contentUrl, + contentMode: mode, + contentLoaded: contentLoaded + }); + + addStepToCache(wizard, step); + }); +} + +/** + * Triggers the onCanceled event. + * + * @static + * @private + * @method cancel + * @param wizard {Object} The jQuery wizard object + **/ +function cancel(wizard) +{ + wizard.triggerHandler("canceled"); +} + +function decreaseCurrentIndexBy(state, decreaseBy) +{ + return state.currentIndex - decreaseBy; +} + +/** + * Removes the control functionality completely and transforms the current state to the initial HTML structure. + * + * @static + * @private + * @method destroy + * @param wizard {Object} A jQuery wizard object + **/ +function destroy(wizard, options) +{ + var eventNamespace = getEventNamespace(wizard); + + // Remove virtual data objects from the wizard + wizard.unbind(eventNamespace).removeData("uid").removeData("options") + .removeData("state").removeData("steps").removeData("eventNamespace") + .find(".actions a").unbind(eventNamespace); + + // Remove attributes and CSS classes from the wizard + wizard.removeClass(options.clearFixCssClass + " vertical"); + + var contents = wizard.find(".content > *"); + + // Remove virtual data objects from panels and their titles + contents.removeData("loaded").removeData("mode").removeData("url"); + + // Remove attributes, CSS classes and reset inline styles on all panels and their titles + contents.removeAttr("id").removeAttr("role").removeAttr("tabindex") + .removeAttr("class").removeAttr("style")._removeAria("labelledby") + ._removeAria("hidden"); + + // Empty panels if the mode is set to 'async' or 'iframe' + wizard.find(".content > [data-mode='async'],.content > [data-mode='iframe']").empty(); + + var wizardSubstitute = $("<{0} class=\"{1}\">".format(wizard.get(0).tagName, wizard.attr("class"))); + + var wizardId = wizard._id(); + if (wizardId != null && wizardId !== "") + { + wizardSubstitute._id(wizardId); + } + + wizardSubstitute.html(wizard.find(".content").html()); + wizard.after(wizardSubstitute); + wizard.remove(); + + return wizardSubstitute; +} + +/** + * Triggers the onFinishing and onFinished event. + * + * @static + * @private + * @method finishStep + * @param wizard {Object} The jQuery wizard object + * @param state {Object} The state container of the current wizard + **/ +function finishStep(wizard, state) +{ + var currentStep = wizard.find(".steps li").eq(state.currentIndex); + + if (wizard.triggerHandler("finishing", [state.currentIndex])) + { + currentStep.addClass("done").removeClass("error"); + wizard.triggerHandler("finished", [state.currentIndex]); + } + else + { + currentStep.addClass("error"); + } +} + +/** + * Gets or creates if not exist an unique event namespace for the given wizard instance. + * + * @static + * @private + * @method getEventNamespace + * @param wizard {Object} A jQuery wizard object + * @return {String} Returns the unique event namespace for the given wizard + */ +function getEventNamespace(wizard) +{ + var eventNamespace = wizard.data("eventNamespace"); + + if (eventNamespace == null) + { + eventNamespace = "." + getUniqueId(wizard); + wizard.data("eventNamespace", eventNamespace); + } + + return eventNamespace; +} + +function getStepAnchor(wizard, index) +{ + var uniqueId = getUniqueId(wizard); + + return wizard.find("#" + uniqueId + _tabSuffix + index); +} + +function getStepPanel(wizard, index) +{ + var uniqueId = getUniqueId(wizard); + + return wizard.find("#" + uniqueId + _tabpanelSuffix + index); +} + +function getStepTitle(wizard, index) +{ + var uniqueId = getUniqueId(wizard); + + return wizard.find("#" + uniqueId + _titleSuffix + index); +} + +function getOptions(wizard) +{ + return wizard.data("options"); +} + +function getState(wizard) +{ + return wizard.data("state"); +} + +function getSteps(wizard) +{ + return wizard.data("steps"); +} + +/** + * Gets a specific step object by index. + * + * @static + * @private + * @method getStep + * @param index {Integer} An integer that belongs to the position of a step + * @return {Object} A specific step object + **/ +function getStep(wizard, index) +{ + var steps = getSteps(wizard); + + if (index < 0 || index >= steps.length) + { + throwError(_indexOutOfRangeErrorMessage); + } + + return steps[index]; +} + +/** + * Gets or creates if not exist an unique id from the given wizard instance. + * + * @static + * @private + * @method getUniqueId + * @param wizard {Object} A jQuery wizard object + * @return {String} Returns the unique id for the given wizard + */ +function getUniqueId(wizard) +{ + var uniqueId = wizard.data("uid"); + + if (uniqueId == null) + { + uniqueId = wizard._id(); + if (uniqueId == null) + { + uniqueId = "steps-uid-".concat(_uniqueId); + wizard._id(uniqueId); + } + + _uniqueId++; + wizard.data("uid", uniqueId); + } + + return uniqueId; +} + +/** + * Gets a valid enum value by checking a specific enum key or value. + * + * @static + * @private + * @method getValidEnumValue + * @param enumType {Object} Type of enum + * @param keyOrValue {Object} Key as `String` or value as `Integer` to check for + */ +function getValidEnumValue(enumType, keyOrValue) +{ + validateArgument("enumType", enumType); + validateArgument("keyOrValue", keyOrValue); + + // Is key + if (typeof keyOrValue === "string") + { + var value = enumType[keyOrValue]; + if (value === undefined) + { + throwError("The enum key '{0}' does not exist.", keyOrValue); + } + + return value; + } + // Is value + else if (typeof keyOrValue === "number") + { + for (var key in enumType) + { + if (enumType[key] === keyOrValue) + { + return keyOrValue; + } + } + + throwError("Invalid enum value '{0}'.", keyOrValue); + } + // Type is not supported + else + { + throwError("Invalid key or value type."); + } +} + +/** + * Routes to the next step. + * + * @static + * @private + * @method goToNextStep + * @param wizard {Object} The jQuery wizard object + * @param options {Object} Settings of the current wizard + * @param state {Object} The state container of the current wizard + * @return {Boolean} Indicates whether the action executed + **/ +function goToNextStep(wizard, options, state) +{ + return paginationClick(wizard, options, state, increaseCurrentIndexBy(state, 1)); +} + +/** + * Routes to the previous step. + * + * @static + * @private + * @method goToPreviousStep + * @param wizard {Object} The jQuery wizard object + * @param options {Object} Settings of the current wizard + * @param state {Object} The state container of the current wizard + * @return {Boolean} Indicates whether the action executed + **/ +function goToPreviousStep(wizard, options, state) +{ + return paginationClick(wizard, options, state, decreaseCurrentIndexBy(state, 1)); +} + +/** + * Routes to a specific step by a given index. + * + * @static + * @private + * @method goToStep + * @param wizard {Object} The jQuery wizard object + * @param options {Object} Settings of the current wizard + * @param state {Object} The state container of the current wizard + * @param index {Integer} The position (zero-based) to route to + * @return {Boolean} Indicates whether the action succeeded or failed + **/ +function goToStep(wizard, options, state, index) +{ + if (index < 0 || index >= state.stepCount) + { + throwError(_indexOutOfRangeErrorMessage); + } + + if (options.forceMoveForward && index < state.currentIndex) + { + return; + } + + var oldIndex = state.currentIndex; + if (wizard.triggerHandler("stepChanging", [state.currentIndex, index])) + { + // Save new state + state.currentIndex = index; + saveCurrentStateToCookie(wizard, options, state); + + // Change visualisation + refreshStepNavigation(wizard, options, state, oldIndex); + refreshPagination(wizard, options, state); + loadAsyncContent(wizard, options, state); + startTransitionEffect(wizard, options, state, index, oldIndex); + + wizard.triggerHandler("stepChanged", [index, oldIndex]); + } + else + { + wizard.find(".steps li").eq(oldIndex).addClass("error"); + } + + return true; +} + +function increaseCurrentIndexBy(state, increaseBy) +{ + return state.currentIndex + increaseBy; +} + +/** + * Initializes the component. + * + * @static + * @private + * @method initialize + * @param options {Object} The component settings + **/ +function initialize(options) +{ + /*jshint -W040 */ + var opts = $.extend(true, {}, defaults, options); + + return this.each(function () + { + var wizard = $(this); + var state = { + currentIndex: opts.startIndex, + currentStep: null, + stepCount: 0, + transitionElement: null + }; + + // Create data container + wizard.data("options", opts); + wizard.data("state", state); + wizard.data("steps", []); + + analyzeData(wizard, opts, state); + render(wizard, opts, state); + registerEvents(wizard, opts); + + // Trigger focus + if (opts.autoFocus && _uniqueId === 0) + { + getStepAnchor(wizard, opts.startIndex).focus(); + } + }); +} + +/** + * Inserts a new step to a specific position. + * + * @static + * @private + * @method insertStep + * @param wizard {Object} The jQuery wizard object + * @param options {Object} Settings of the current wizard + * @param state {Object} The state container of the current wizard + * @param index {Integer} The position (zero-based) to add + * @param step {Object} The step object to add + * @example + * $("#wizard").steps().insert(0, { + * title: "Title", + * content: "", // optional + * contentMode: "async", // optional + * contentUrl: "/Content/Step/1" // optional + * }); + * @chainable + **/ +function insertStep(wizard, options, state, index, step) +{ + if (index < 0 || index > state.stepCount) + { + throwError(_indexOutOfRangeErrorMessage); + } + + // TODO: Validate step object + + // Change data + step = $.extend({}, stepModel, step); + insertStepToCache(wizard, index, step); + if (state.currentIndex !== state.stepCount && state.currentIndex >= index) + { + state.currentIndex++; + saveCurrentStateToCookie(wizard, options, state); + } + state.stepCount++; + + var contentContainer = wizard.find(".content"), + header = $("<{0}>{1}".format(options.headerTag, step.title)), + body = $("<{0}>".format(options.bodyTag)); + + if (step.contentMode == null || step.contentMode === contentMode.html) + { + body.html(step.content); + } + + if (index === 0) + { + contentContainer.prepend(body).prepend(header); + } + else + { + getStepPanel(wizard, (index - 1)).after(body).after(header); + } + + renderBody(wizard, state, body, index); + renderTitle(wizard, options, state, header, index); + refreshSteps(wizard, options, state, index); + if (index === state.currentIndex) + { + refreshStepNavigation(wizard, options, state); + } + refreshPagination(wizard, options, state); + + return wizard; +} + +/** + * Inserts a step object to the cache at a specific position. + * + * @static + * @private + * @method insertStepToCache + * @param wizard {Object} A jQuery wizard object + * @param index {Integer} The position (zero-based) to add + * @param step {Object} The step object to add + **/ +function insertStepToCache(wizard, index, step) +{ + getSteps(wizard).splice(index, 0, step); +} + +/** + * Handles the keyup DOM event for pagination. + * + * @static + * @private + * @event keyup + * @param event {Object} An event object + */ +function keyUpHandler(event) +{ + var wizard = $(this), + options = getOptions(wizard), + state = getState(wizard); + + if (options.suppressPaginationOnFocus && wizard.find(":focus").is(":input")) + { + event.preventDefault(); + return false; + } + + var keyCodes = { left: 37, right: 39 }; + if (event.keyCode === keyCodes.left) + { + event.preventDefault(); + goToPreviousStep(wizard, options, state); + } + else if (event.keyCode === keyCodes.right) + { + event.preventDefault(); + goToNextStep(wizard, options, state); + } +} + +/** + * Loads and includes async content. + * + * @static + * @private + * @method loadAsyncContent + * @param wizard {Object} A jQuery wizard object + * @param options {Object} Settings of the current wizard + * @param state {Object} The state container of the current wizard + */ +function loadAsyncContent(wizard, options, state) +{ + if (state.stepCount > 0) + { + var currentStep = getStep(wizard, state.currentIndex); + + if (!options.enableContentCache || !currentStep.contentLoaded) + { + switch (getValidEnumValue(contentMode, currentStep.contentMode)) + { + case contentMode.iframe: + wizard.find(".content > .body").eq(state.currentIndex).empty() + .html("