diff --git a/app/assets/images/rails.png b/app/assets/images/rails.png deleted file mode 100644 index d5edc04..0000000 Binary files a/app/assets/images/rails.png and /dev/null differ diff --git a/app/assets/images/slides/background.jpg b/app/assets/images/slides/background.jpg new file mode 100644 index 0000000..d3c9f28 Binary files /dev/null and b/app/assets/images/slides/background.jpg differ diff --git a/app/assets/images/slides/loading.gif b/app/assets/images/slides/loading.gif new file mode 100644 index 0000000..3ae595e Binary files /dev/null and b/app/assets/images/slides/loading.gif differ diff --git a/app/assets/images/slides/navigation-next.png b/app/assets/images/slides/navigation-next.png new file mode 100644 index 0000000..0858458 Binary files /dev/null and b/app/assets/images/slides/navigation-next.png differ diff --git a/app/assets/images/slides/navigation-previous.png b/app/assets/images/slides/navigation-previous.png new file mode 100644 index 0000000..4b704b6 Binary files /dev/null and b/app/assets/images/slides/navigation-previous.png differ diff --git a/app/assets/images/slides/pagination.png b/app/assets/images/slides/pagination.png new file mode 100644 index 0000000..fad3171 Binary files /dev/null and b/app/assets/images/slides/pagination.png differ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index d1bd28c..065e5d5 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -8,3 +8,5 @@ //= require jquery_ujs //= require pjax //= require active_scaffold +//= require slides +//= require_self diff --git a/app/assets/javascripts/slides.js b/app/assets/javascripts/slides.js new file mode 100644 index 0000000..ad0d0e7 --- /dev/null +++ b/app/assets/javascripts/slides.js @@ -0,0 +1,1055 @@ +/* + =========================================================== + + Note: SlidesJS version 2.0 beta 1 is not meant + for production deployment. Please download the latest + version at https://github.com/nathansearles/Slides. + + =========================================================== +*/ + +/* + + .d8888b. 888 d8b 888 888888 .d8888b. + d88P Y88b 888 Y8P 888 "88b d88P Y88b + Y88b. 888 888 888 Y88b. + "Y888b. 888 888 .d88888 .d88b. .d8888b 888 "Y888b. + "Y88b. 888 888 d88" 888 d8P Y8b 88K 888 "Y88b. + "888 888 888 888 888 88888888 "Y8888b. 888 "888 + Y88b d88P 888 888 Y88b 888 Y8b. X88 88P Y88b d88P + "Y8888P" 888 888 "Y88888 "Y8888 88888P' 888 "Y8888P" + .d88P + .d88P" + 888P" + + Created by Nathan Searles + + Documentation and examples + Support forum + + Version: 2.0 beta 1 + Updated: June 22nd, 2011 + + SlidesJS is an open source project, contribute at GitHub: + https://github.com/nathansearles/Slides + + (c) 2011 by Nathan Searles + + Thanks to: + Thomas Reynolds + Adam j. Sontag + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + Documentaion + ============================================================ + + Basic Markup Structure + ============================================================ + + For just images you can simply use: + +
+ Slide 1 + Slide 2 + Slide 3 + Slide 4 +
+ + Or you can use
s for your slides + +
+
+ Slide 1 +
+
+ Slide 2 +
+
+ Slide 3 +
+
+ Slide 4 +
+
+ + Simple as that. No extra
s, no navigation or pagination to define, it's all created for you. SlidesJS creates + two
s for the slideshow, ".slidesContainer" and ".slidesControl", both are required and can not be changed. + + Navigation classes are ".slidesPrevious" and ".slidesNext" and are created as anchor tags. These cannot be changed. + + Pagination uses an unordered list markup structure. The
    has a class of ".slidesPagination". This cannot be changed. + + You may define your own navigation or pagination, but they must use the same class names, + sorry it saves from including extraneous code. + + Basic CSS + ============================================================ + + No CSS required. Shit yeah! + + Initialize SlidesJS + ============================================================ + + + + Tip: With SidesJS 2 you need to define the width and height if it's different from the default (780px x 300px). This resolves many issues having to do with loading and makes SlidesJS 2 self contained, not requiring any CSS. + +
    + + Method Calls - The good stuff + ============================================================ + + Play: + $("#slides").slides("play"); + + Pause: + $("#slides").slides("pause"); + + Stop: + $("#slides").slides("stop"); + + Next: + $("#slides").slides("next"); + - Uses default effect + + $("#slides").slides("next","fade"); + - Define effect, "slide" or "fade" + + Previous: + $("#slides").slides("previous"); + - Uses default effect + + $("#slides").slides("previous","fade"); + - Define effect, "slide" or "fade" + + Goto a slide + $("#slides").slides("slide",2); + - Goto slide 2 using default effect + + $("#slides").slides("slide",4,"fade"); + - Define effect, "slide" or "fade" + + Update: + $("#slides").slides("update"); + - Rebuilds pagination + + Destroy: + $("#slides").slides("destroy"); + - Removes SlidesJS, returns to predefined state + + Status: + $("#slides").slides("status"); + - Returns JSON object: + { + current: 4, + state: "playing", + total: 7 + } + + $("#slides").slides("status","current"); + - Returns current slide number + + $("#slides").slides("status","state"); + - Returns playing, paused, or stopped + + $("#slides").slides("status","total"); + - Returns total slides in slideshow + + Options + ============================================================ + Check out the notes on the options below +*/ + +/* + jQuery UI Widget, skip past this for SlidesJS +*/ + +/*! + * jQuery UI Widget @VERSION + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */ +(function ($, undefined) { + var slice = Array.prototype.slice; + var _cleanData = $.cleanData; + $.cleanData = function (elems) { + for (var i = 0, elem; + (elem = elems[i]) != null; i++) { + $(elem).triggerHandler("remove"); + } + _cleanData(elems); + }; + $.widget = function (name, base, prototype) { + var namespace = name.split(".")[0], + fullName; + name = name.split(".")[1]; + fullName = namespace + "-" + name; + if (!prototype) { + prototype = base; + base = $.Widget; + } + // create selector for plugin + $.expr[":"][fullName] = function (elem) { + return !!$.data(elem, name); + }; + $[namespace] = $[namespace] || {}; + // create the constructor using $.extend() so we can carry over any + // static properties stored on the existing constructor (if there is one) + $[namespace][name] = $.extend(function (options, element) { + // allow instantiation without "new" keyword + if (!this._createWidget) { + return new $[namespace][name](options, element); + } + // allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) + if (arguments.length) { + this._createWidget(options, element); + } + }, $[namespace][name]); + var basePrototype = new base(); + // we need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from + basePrototype.options = $.widget.extend({}, basePrototype.options); + $.each(prototype, function (prop, value) { + if ($.isFunction(value)) { + prototype[prop] = (function () { + var _super = function (method) { + return base.prototype[method].apply(this, slice.call(arguments, 1)); + }; + var _superApply = function (method, args) { + return base.prototype[method].apply(this, args); + }; + return function () { + var __super = this._super, + __superApply = this._superApply, + returnValue; + this._super = _super; + this._superApply = _superApply; + returnValue = value.apply(this, arguments); + this._super = __super; + this._superApply = __superApply; + return returnValue; + }; + }()); + } + }); + $[namespace][name].prototype = $.widget.extend(basePrototype, { + namespace: namespace, + widgetName: name, + widgetEventPrefix: name, + widgetBaseClass: fullName + }, prototype); + $.widget.bridge(name, $[namespace][name]); + }; + $.widget.extend = function (target) { + var input = slice.call(arguments, 1), + inputIndex = 0, + inputLength = input.length, + key, value; + for (; inputIndex < inputLength; inputIndex++) { + for (key in input[inputIndex]) { + value = input[inputIndex][key]; + if (input[inputIndex].hasOwnProperty(key) && value !== undefined) { + target[key] = $.isPlainObject(value) ? $.widget.extend({}, target[key], value) : value; + } + } + } + return target; + }; + $.widget.bridge = function (name, object) { + $.fn[name] = function (options) { + var isMethodCall = typeof options === "string", + args = slice.call(arguments, 1), + returnValue = this; + // allow multiple hashes to be passed on init + options = !isMethodCall && args.length ? $.widget.extend.apply(null, [options].concat(args)) : options; + if (isMethodCall) { + this.each(function () { + var instance = $.data(this, name); + if (!instance) { + return $.error("cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'"); + } + if (!$.isFunction(instance[options]) || options.charAt(0) === "_") { + return $.error("no such method '" + options + "' for " + name + " widget instance"); + } + var methodValue = instance[options].apply(instance, args); + if (methodValue !== instance && methodValue !== undefined) { + returnValue = methodValue.jquery ? returnValue.pushStack(methodValue.get()) : methodValue; + return false; + } + }); + } else { + this.each(function () { + var instance = $.data(this, name); + if (instance) { + instance.option(options || {})._init(); + } else { + object(options, this); + } + }); + } + return returnValue; + }; + }; + $.Widget = function (options, element) { + // allow instantiation without "new" keyword + if (!this._createWidget) { + return new $[namespace][name](options, element); + } + // allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) + if (arguments.length) { + this._createWidget(options, element); + } + }; + $.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + defaultElement: "
    ", + options: { + disabled: false, + // callbacks + create: null + }, + _createWidget: function (options, element) { + element = $(element || this.defaultElement || this)[0]; + this.element = $(element); + this.options = $.widget.extend({}, this.options, this._getCreateOptions(), options); + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + if (element !== this) { + $.data(element, this.widgetName, this); + this._bind({ + remove: "destroy" + }); + } + this._create(); + this._trigger("create"); + this._init(); + }, + _getCreateOptions: $.noop, + _create: $.noop, + _init: $.noop, + destroy: function () { + this._destroy(); + // we can probably remove the unbind calls in version 2 + // all event bindings should go through this._bind() + this.element.unbind("." + this.widgetName).removeData(this.widgetName); + this.widget().unbind("." + this.widgetName).removeAttr("aria-disabled").removeClass( + this.widgetBaseClass + "-disabled " + "ui-state-disabled"); + // clean up events and states + this.bindings.unbind("." + this.widgetName); + this.hoverable.removeClass("ui-state-hover"); + this.focusable.removeClass("ui-state-focus"); + }, + _destroy: $.noop, + widget: function () { + return this.element; + }, + option: function (key, value) { + var options = key, + parts, curOption, i; + if (arguments.length === 0) { + // don't return a reference to the internal hash + return $.widget.extend({}, this.options); + } + if (typeof key === "string") { + if (value === undefined) { + return this.options[key]; + } + // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } + options = {}; + parts = key.split("."); + key = parts.shift(); + if (parts.length) { + curOption = options[key] = $.widget.extend({}, this.options[key]); + for (i = 0; i < parts.length - 1; i++) { + curOption[parts[i]] = curOption[parts[i]] || {}; + curOption = curOption[parts[i]]; + } + curOption[parts.pop()] = value; + } else { + options[key] = value; + } + } + this._setOptions(options); + return this; + }, + _setOptions: function (options) { + var self = this; + $.each(options, function (key, value) { + self._setOption(key, value); + }); + return this; + }, + _setOption: function (key, value) { + this.options[key] = value; + if (key === "disabled") { + this.widget().toggleClass(this.widgetBaseClass + "-disabled ui-state-disabled", !! value).attr("aria-disabled", value); + this.hoverable.removeClass("ui-state-hover"); + this.focusable.removeClass("ui-state-focus"); + } + return this; + }, + enable: function () { + return this._setOption("disabled", false); + }, + disable: function () { + return this._setOption("disabled", true); + }, + _bind: function (element, handlers) { + // no element argument, shuffle and use this.element + if (!handlers) { + handlers = element; + element = this.element; + } else { + // accept selectors, DOM elements + element = $(element); + this.bindings = this.bindings.add(element); + } + var instance = this; + $.each(handlers, function (event, handler) { + element.bind(event + "." + instance.widgetName, function () { + // allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if (instance.options.disabled === true || $(this).hasClass("ui-state-disabled")) { + return; + } + return (typeof handler === "string" ? instance[handler] : handler).apply(instance, arguments); + }); + }); + }, + _hoverable: function (element) { + this.hoverable = this.hoverable.add(element); + this._bind(element, { + mouseenter: function (event) { + $(event.currentTarget).addClass("ui-state-hover"); + }, + mouseleave: function (event) { + $(event.currentTarget).removeClass("ui-state-hover"); + } + }); + }, + _focusable: function (element) { + this.focusable = this.focusable.add(element); + this._bind(element, { + focusin: function (event) { + $(event.currentTarget).addClass("ui-state-focus"); + }, + focusout: function (event) { + $(event.currentTarget).removeClass("ui-state-focus"); + } + }); + }, + _trigger: function (type, event, data) { + var callback = this.options[type], + args; + event = $.Event(event); + event.type = (type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type).toLowerCase(); + data = data || {}; + // copy original event properties over to the new event + // this would happen if we could call $.event.fix instead of $.Event + // but we don't have a way to force an event to be fixed multiple times + if (event.originalEvent) { + for (var i = $.event.props.length, prop; i;) { + prop = $.event.props[--i]; + event[prop] = event.originalEvent[prop]; + } + } + this.element.trigger(event, data); + args = $.isArray(data) ? [event].concat(data) : [event, data]; + return !($.isFunction(callback) && callback.apply(this.element[0], args) === false || event.isDefaultPrevented()); + } + }; + $.each({ + show: "fadeIn", + hide: "fadeOut" + }, function (method, defaultEffect) { + $.Widget.prototype["_" + method] = function (element, options, callback) { + options = options || {}; + var hasOptions = !$.isEmptyObject(options), + effectName = options.effect || defaultEffect; + options.complete = callback; + if (options.delay) { + element.delay(options.delay); + } + if (hasOptions && $.effects && ($.effects.effect[effectName] || $.uiBackCompat !== false && $.effects[effectName])) { + element[method](options); + } else if (effectName !== method && element[effectName]) { + element[effectName](options.duration, options.easing, callback); + } else { + element.queue(function () { + $(this)[method](); + if (callback) { + callback.call(element[0]); + } + }); + } + }; + }); + // DEPRECATED + if ($.uiBackCompat !== false) { + $.Widget.prototype._getCreateOptions = function () { + return $.metadata && $.metadata.get(this.element[0])[this.widgetName]; + }; + } +})(jQuery); + +/* + SlidesJS, let the good times roll +*/ +(function($) { + $.widget("js.slides", { + options: { + width: 780, // [Number] Define the slide width + responsive: false, // [Boolean] slideshow will scale to its container + height: 300, // [Number] Define the slide height + navigation: true, // [Boolean] Auto generate the naviagation, next/previous buttons + pagination: true, // [Boolean] Auto generate the pagination + effects: { + navigation: "slide", // [String] Can be either "slide" or "fade" + pagination: "slide" // [String] Can be either "slide" or "fade" + }, + direction: "left", // [String] Define the slide direction: "Up", "Right", "Down", "left" + fade: { + interval: 1000, // [Number] Interval of fade in milliseconds + crossfade: false, // [Boolean] TODO: add this feature. Crossfade the slides, great for images, bad for text + easing: "" // [String] Dependency: jQuery Easing plug-in + }, + slide: { + interval: 1000, // [Number] Interval of fade in milliseconds + browserWindow: false, // [Boolean] Slide in/out from browser window, bad ass + easing: "" // [String] Dependency: jQuery Easing plug-in + }, + preload: { + active: false, // [Boolean] Preload the slides before showing them, this needs some work + image: "../img/loading.gif" // [String] Define the path to a load .gif, yes I should do something cooler + }, + startAtSlide: 1, // [Number] What should the first slide be? + playInterval: 5000, // [Number] Time spent on each slide in milliseconds + pauseInterval: 8000, // [Number] Time spent on pause, triggered on any navigation or pagination click + autoHeight: false, // [Boolean] TODO: add this feature. Auto sets height based on each slide + navigateStart: function( current ){ + // console.log( "navigateStart: ", current ); + }, + navigateEnd: function( current ){ + // console.log( "navigateEnd: ", current ); + }, + loaded: function() { + // console.log( "loaded" ); + } + }, + _create: function() { + + // Error correction for only 1 slide + if (this.element.children().length < 2) { + return; + } + + if ( this.options.slide.browserWindow ) { + this.element.css({ + width: window.innerWidth, + position: "relative", + left: - (window.innerWidth / 2) + (this.options.width / 2), + overflow: "hidden" + }); + + $(window).resize( $.proxy(function() { + this.element.css({ + width: window.innerWidth, + left: - (window.innerWidth / 2) + (this.options.width / 2) + }); + + this.slidesContainer.css({ + left: this.options.slide.browserWindow ? (window.innerWidth - this.options.width) / 2 : "" + }); + },this)); + } + + this.slidesContainer = this.element.children().not(".slidesNavigation").wrapAll( "
    " ).parent().css({ + width: this.options.responsive ? "100%" : this.options.width, + height: this.options.height, + overflow: this.options.slide.browserWindow ? "visible" : "hidden", + position: "relative", + left: this.options.slide.browserWindow ? (window.innerWidth - this.options.width) / 2 : "" + }); + + this.slidesControl = this.slidesContainer.wrapInner( "
    " ).children().css({ + display: "none" + }); + + // Define the slides + this.slides = this.slidesControl.children(); + + // Set CSS for slidesControl + this.slidesControl.css({ + position: "relative", + width: this.options.responsive ? "100%" : this.options.width, + height: this.options.height, + left: 0 + }); + + // Set CSS for each slide + this.slides.css({ + position: "absolute", + top: 0, + left: 0, + zIndex: 0, + display: "none" + }); + + // Show the starting slide with a fade in + this.slides.eq( this.options.startAtSlide - 1 ).fadeIn( this.options.fade.interval ); + + if ( this.options.preload.active ) { + +/* TODO: loading image, need to remove on load callback + + this.slidesContainer.css({ + backgroundImage: "url(" + this.options.preload.image + ")", + backgroundPosition: "50% 50%", + backgroundRepeat: "no-repeat" + }); +*/ + var preloadImage; + + if (this.slides.eq( this.options.startAtSlide - 1 ).is("img")) { + preloadImage = this.slides.eq( this.options.startAtSlide - 1 ).attr("src"); + } else { + preloadImage = this.slides.eq( this.options.startAtSlide - 1 ).find("img").attr("src"); + } + + this._loadImage( preloadImage ).then( $.proxy(function( url ) { + this.slidesControl.fadeIn( this.options.fade.interval ); + this._trigger( "loaded", this.options.startAtSlide, this ); + },this)); + } else { + this.slidesControl.fadeIn( this.options.fade.interval ); + } + + if ( this.options.navigation ) { + this.prevButton = $("",{ + "class": "slidesPrevious slidesNavigation", + href: "#", + title: "Previous", + text: "Previous" + }).appendTo( this.element ); + + this.nextButton = $("",{ + "class": "slidesNext slidesNavigation", + href: "#", + title: "Next", + text: "Next" + }).appendTo( this.element ); + } else { + this.nextButton = $(".slidesNext"); + this.prevButton = $(".slidesPrevious"); + } + + if (this.options.pagination) { + this._buildPagination(); + // add current class to first pagination + this.pagination.children().eq( this.options.startAtSlide - 1 ).addClass("slidesCurrent"); + } + + this.current = this.options.startAtSlide - 1; + + this.element.delegate( ".slidesNavigation", "click", $.proxy(this, "_navigate") ); + + this.total = this.slides.length; + }, + _loaded: function() { + if ( this.options.responsive ) { + + // TODO: cleanup and condense + this.slidesContainer.css({ + height: this.slides.height() + }); + + this.slidesControl.css({ + height: this.slides.height() + }); + + $(window).resize( $.proxy(function() { + this.slidesContainer.css({ + height: this.slides.height() + }); + this.slidesControl.css({ + height: this.slides.height() + }); + },this)); + } + }, + _buildPagination: function() { + + if (this.pagination) { + // Remove the current paginaiton + this.pagination.remove(); + // Redefine slides with new children + this.slides = this.slidesControl.children(); + } + + this.pagination = $("
      ",{ + "class": "slidesPagination" + }).appendTo(this.element); + + this.slides.each( + $.proxy(function(index, element) { + $("
    • " + ( index + 1 ) + "
    • ").appendTo(this.pagination); + },this) + ); + + }, + _loadImage: function(imageSrc) { + var deferred, preloader; + var loadImageCache = {}; + if (typeof loadImageCache[imageSrc] === "undefined") { + deferred = $.Deferred(); + + preloader = new Image(); + preloader.onload = function() { + deferred.resolve(this.src); + }; + preloader.onerror = function() { + deferred.reject(this.src); + }; + preloader.src = imageSrc; + + loadImageCache[imageSrc] = deferred; + } + + return loadImageCache[imageSrc]; + }, + next: function( effect ) { + this._navigate("next", effect); + }, + previous: function( effect ) { + this._navigate("previous", effect); + }, + slide: function( slide, effect ) { + this.element.data("goto", (slide - 1)); + this._navigate("pagination", effect); + }, + _navigate: function( event, effect ) { + var to, position, direction, next, prev, pagination, $target = $(event.target), currentSlide = this.slides.eq( this.current ); + + /* + Slide to error correction + */ + if ( this.element.data("goto") < 0 ) { + // If goto is less then 0 + this.element.data("goto",0); + } else if ( this.element.data("goto") > this.total ) { + // If goto is greater then total slides + this.element.data("goto",(this.total - 1)); + } + + /* + Check if slides is currently animating + */ + if ( this.element.data("animated") || $target.data("slidesindex") === this.current || this.element.data("goto") === this.current ) { + return false; + } + + /* + Is this event coming from a click? + */ + if (typeof(event) === "object") { + event.preventDefault(); + + // Pause on navigation item click + if ( this.state === "playing" && this.options.pauseInterval ) { + this.pause(); + } + } else { + if (event === "next") { + next = true; + } else { + prev = true; + } + } + + /* + Set to animated + */ + this.element.data("animated",true); + + if ( $target.hasClass( "slidesNext" ) ) { + // Next button clicked + next = true; + + } else if ( $target.hasClass("slidesPrevious") ) { + + // Previous button clicked + prev = true; + + } else if ( $target.hasClass("slidesPaginationItem") || event === "pagination") { + + // Paginaiton item clicked + if ( this.current > $target.data("slidesindex") || this.current > this.element.data("goto") ) { + prev = true; + } else { + next = true; + } + + pagination = true; + + effect = effect ? effect : this.options.effects.pagination; + } + + if (pagination) { + // Get next from data-slidesindex + to = this.element.data("goto") > -1 ? this.element.data("goto") : $target.data("slidesindex"); + } else { + // Get next based on curent + to = next ? (this.current + 1) : (prev ? this.current - 1 : this.current); + } + + // Pass slide from number + this._trigger("navigateStart", ( this.current + 1 ), this); + + // creat the loop + if ( to == this.slides.length && !pagination ) { + // last slide, loop to first + to = 0; + } else if ( to == -1 && !pagination ) { + // first slide, loop to last + to = this.slides.length - 1; + } + + if (this.options.pagination) { + // Change the pagination + this.pagination.children().removeClass("slidesCurrent"); + this.pagination.children().eq( to ).addClass("slidesCurrent"); + } + + // Effects methods + if (effect === "fade") { + this._fade({ + next: next, + to: to, + currentSlide: currentSlide + }); + } else { + this._slide({ + next: next, + to: to, + currentSlide: currentSlide + }); + } + }, + _slide: function (navigateData) { + /* + Thanks to Thomas Reynolds + */ + + var isFlipped = navigateData.next ? 1 : -1; + var isOpposite = this.options.direction.match(/right|down/) ? -1 : 1; + var type = this.options.direction.match(/left|right/) ? "horizontal" : "vertical"; + var vector = (type == "horizontal") ? "width" : "height"; + + vector = this.options.responsive ? this.slides.width() : this.options[vector] ; + + var position = vector * isOpposite * isFlipped; + + if (this.options.slide.browserWindow) { + if (navigateData.next) { + position = Math.abs( this.options.width - window.innerWidth - position); + } else { + position = this.options.width - window.innerWidth + position; + } + } + + var direction = position * -1; + + // Setup the "to" slide + this.slides.eq( navigateData.to ).css({ + left: type === "vertical" ? 0 : position, + top: type === "vertical" ? position : 0, + zIndex: 5, + display: "block" + }); + + // animate control + this.slidesControl.animate({ + left: type === "vertical" ? 0 : direction, + top: type === "vertical" ? direction : 0 + },this.options.slide.interval, this.options.slide.easing, $.proxy(function(){ + // after animation reset control position + this.slidesControl.css({ + top: 0, + left:0 + }); + // reset and show next + this.slides.eq( navigateData.to ).css({ + top: 0, + left:0, + zIndex: 5 + }); + + // reset previous slide + navigateData.currentSlide.css({ + top: 0, + left:0, + display: "none", + zIndex: 0 + }); + + this.current = navigateData.to; + + this._trigger("navigateEnd", ( this.current + 1 ), this); + }, this)); + }, + _fade: function (navigateData) { + + // put hidden to slide above current + this.slides.eq( navigateData.to ).css({ + zIndex: 10 + // fade in next + }).fadeIn(this.options.fade.interval, this.options.fade.easing, $.proxy(function(){ + + // hide previous + navigateData.currentSlide.css({ + display: "none", + zIndex: 0 + }); + + // reset zindex + this.slides.eq( navigateData.to ).css({ + zIndex: 0 + }); + + this.current = navigateData.to; + + this._trigger("navigateEnd", ( this.current + 1 ), this); + + }, this)); + }, + play: function( gotoNext ) { + if (gotoNext !== false) { + this._navigate("next"); + } + + var playInterval = setInterval( $.proxy(function() { + this._navigate("next"); + }, this), this.options.playInterval); + + // Set status + this.state = "playing"; + + // Store the unique interval ID + this.element.data("playIntervalId",playInterval); + }, + pause: function() { + clearTimeout( this.element.data("pauseTimeoutId") ); + + clearInterval( this.element.data("playIntervalId") ); + + var pauseTimeout = setTimeout($.proxy(function() { + this.play(); + }, this), this.options.pauseInterval); + + // Set status + this.state = "paused"; + + // Store the unique pause timeout ID + this.element.data("pauseTimeoutId",pauseTimeout); + }, + stop: function() { + clearInterval( this.element.data("playIntervalId") ); + + // Set status + this.state = "stopped"; + }, + update: function() { + this._buildPagination(); + }, + status: function( key ) { + if (key) { + return this[key] ? this[key] : false; + } else { + return { + "state": this.state, + "current": this.current, + "total": this.total + }; + } + + }, + _setOption: function(key, value) { + switch(key) { + /* + TODO: This needs work, note status function use of this[key] + $("#slides").slides("option","pagination", false); + + case "pagination": + if (value !== this.options.pagination ) { + value ? this._buildPagination() : this.pagination.remove(); + } + break; + */ + } + $.Widget.prototype._setOption.apply(this,arguments); + }, + destroy: function() { + + this.slidesContainer.contents().unwrap(); + + this.slidesControl.contents().unwrap(); + + this.element.unbind(); + + this.pagination.remove(); + + this.nextButton.remove(); + + this.prevButton.remove(); + + this.slides.attr( "style", "" ); + + $.Widget.prototype.destroy.call(this); + }, + _trigger: function( event, current ) { + if (event != "create") { + this.options[event]( current ); + } + if (event === "navigateEnd") { + this.element.data("animated",false); + } + if (event === "loaded") { + this._loaded(); + } + } + }); +})(jQuery); \ No newline at end of file diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index e246dfe..6827502 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -5,7 +5,9 @@ *= require normalize *= require theme/base *= require web-app-theme/themes/default/style.css +*= require marketing *= require active_scaffold *= require overrides +*= require slides *= require_self */ diff --git a/app/assets/stylesheets/marketing.css.scss b/app/assets/stylesheets/marketing.css.scss new file mode 100644 index 0000000..6514f24 --- /dev/null +++ b/app/assets/stylesheets/marketing.css.scss @@ -0,0 +1,85 @@ +@import "compass/css3/gradient"; +@import "compass/css3/border-radius"; +@import "compass/css3/box-shadow"; + +@mixin slick-black { + @include background( + image-url("marketing/action/slick-black.png"), + linear-gradient(top, rgba(50, 50, 50, 0.9) 0%, rgba(30, 30, 30, 0.9) 50%, rgba(20, 20, 20, 0.9) 50%, rgba(0, 0, 0, 0.9) 100%)); + border: 0; + @include border-radius(4px); + @include box-shadow(inset 1px 1px 1px 0px rgba(135, 135, 135, 0.1), inset -1px -1px 1px 0px rgba(135, 135, 135, 0.1)); + color: #fff; + line-height: 1; + padding: 8px 0; + text-shadow: 0px -1px 1px rgba(0, 0, 0, .8), 0 1px 1px rgba(255, 255, 255, 0.3); + + &:hover { + @include background( + image-url("marketing/action/slick-black-hover.png"), + linear-gradient(top, rgba(70, 70, 70, 0.9) 0%, rgba(50, 50, 50, 0.9) 50%, rgba(40, 40, 40, 0.9) 50%, rgba(20, 20, 20, 0.9) 100%)); + cursor: pointer; + } + + &:active { + @include background( + image-url("marketing/action/slick-black-hover.png"), + linear-gradient(top, rgba(30, 30, 30, 0.9) 0%, rgba(20, 20, 20, 0.9) 50%, rgba(10, 10, 10, 0.9) 50%, rgba(0, 0, 0, 0.9) 100%)); + } +} + +.marketing .header-inner { + width: 77%; + margin: auto; + position: relative; +} + +#main.marketing-main { + margin-left: auto; + margin-right: auto; + float: none; + + .block .content .marketing-inner { + padding: 0 30px 30px; + p { + line-height: 1em; + color: #555; + } + } + + .marketing-text { + padding-right: 20px; + } + .marketing-images { + padding-left: 20px; + } + + h1 { + text-transform: uppercase; + font-size: 34px; + } + + li { + font-size: 16px; + } + + .action { + padding: 0 20px 20px 20px; + button { + @include slick-black; + width: 300px; + height: 60px; + margin: auto; + display: block; + font-family: "MuseoSans500", helvetica, arial, sans-serif; + strong { + font-size: 18px; + font-weight: bold; + } + em { + font-size: 13px; + font-weight: normal; + } + } + } +} diff --git a/app/assets/stylesheets/overrides.css.erb b/app/assets/stylesheets/overrides.css.erb index a9aff7b..40cedac 100644 --- a/app/assets/stylesheets/overrides.css.erb +++ b/app/assets/stylesheets/overrides.css.erb @@ -1,3 +1,7 @@ +#main .block .content p { + font-size: 16px; +} + #main .block .content h2 { margin-left: 0; } diff --git a/app/assets/stylesheets/slides.css.erb b/app/assets/stylesheets/slides.css.erb new file mode 100644 index 0000000..c1bf0dd --- /dev/null +++ b/app/assets/stylesheets/slides.css.erb @@ -0,0 +1,85 @@ +#slidesWrapper { +width:470px; +position:relative; +margin-right: 20px; +} + +#slides { +position:relative; +} + +#slides .slidesContainer { +background:#fff; +border:8px solid #fff; +margin-left:-8px; +box-shadow: 0 2.5px 5px rgba(0,0,0,.6); +} + +/* +Next/prev buttons +*/ + +#slides .slidesNext,#slides .slidesPrevious { +position:absolute; +top:134px; +left:-40px; +width:24px; +height:0; +padding-top:32px; +display:block; +z-index:101; +overflow:hidden; +background:url(<%= image_path 'slides/navigation-previous.png' %>) no-repeat 0 0; +} + +#slides .slidesNext { +left:488px; +background:url(<%= image_path 'slides/navigation-next.png' %>) no-repeat 0 0; +} + +/* +Pagination +*/ + +.slidesPagination { +margin-top: 10px; +position: relative; +width: 100px; +margin-left: auto; +margin-right: auto; +} + +.slidesPagination li { +float:left; +margin:0 1px; +list-style:none; +} + +.slidesPagination li a { +display:block; +width:14px; +height:0; +padding-top:14px; +background-image:url(<%= image_path 'slides/pagination.png' %>); +background-position:0 0; +overflow:hidden; +} + +.slidesPagination li.slidesCurrent a { +background-position:0 -14px; +} + +.current_slide { +font:bold 10px/1.33 sans-serif; +float:left; +margin-top:12px; +} + +.controls { +display:block; +margin-top:12px; +float:left; +color:#333; +font:bold 10px/1.33 sans-serif; +margin-right:10px; +} diff --git a/app/assets/stylesheets/theme/base.css b/app/assets/stylesheets/theme/base.css index 58a3487..797085a 100644 --- a/app/assets/stylesheets/theme/base.css +++ b/app/assets/stylesheets/theme/base.css @@ -18,16 +18,16 @@ .wat-cf {display: block;} /* End hide from IE-mac */ -h1 { margin: 15px 0; font-size: 22px; font-weight: normal; } -h2 { font-size: 22px; margin: 15px 0; font-weight: normal;} -h3 { font-size: 18px; margin: 10px 0; font-weight: normal;} -h4 { font-size: 16px; margin: 10px 0; font-weight: normal;} +h1 { font-size: 30px; margin: 15px 0; font-weight: normal; } +h2 { font-size: 24px; margin: 15px 0; font-weight: normal;} +h3 { font-size: 20px; margin: 10px 0; font-weight: normal;} +h4 { font-size: 18px; margin: 10px 0; font-weight: normal;} hr {height: 1px; border: 0; } p { margin: 15px 0;} a img { border: none; } body { - font-size: 12px; + font-size: 16px; font-family: sans-serif; } diff --git a/app/controllers/domains_controller.rb b/app/controllers/domains_controller.rb index 1afc0ed..b0a8b12 100644 --- a/app/controllers/domains_controller.rb +++ b/app/controllers/domains_controller.rb @@ -1,4 +1,6 @@ class DomainsController < ApplicationController + + begin active_scaffold :domain do |conf| conf.columns = [:name, :records] conf.create.columns = [:name] @@ -6,6 +8,10 @@ class DomainsController < ApplicationController conf.actions.exclude :show conf.list.sorting = { :name => :asc } end + rescue => e + puts e.backtrace + raise e + end protected diff --git a/app/views/fragments/_top.html.erb b/app/views/fragments/_top.html.erb index cd4b79c..b2bb7f3 100644 --- a/app/views/fragments/_top.html.erb +++ b/app/views/fragments/_top.html.erb @@ -1,28 +1,32 @@