From d420b5fff9bc0df8c86ae6fb89c4d688e77e8370 Mon Sep 17 00:00:00 2001 From: Erik Michaels-Ober Date: Sun, 25 Dec 2011 08:53:03 -0800 Subject: [PATCH] Use Boostrap alerts --- app/assets/javascripts/bootstrap-alerts.js | 113 ++++++++ app/assets/javascripts/bootstrap-twipsy.js | 321 +++++++++++++++++++++ app/assets/javascripts/main.js.erb | 25 +- app/assets/stylesheets/screen.css | 22 +- app/views/layouts/application.html.haml | 2 + app/views/layouts/info_window.html.haml | 12 +- app/views/layouts/sidebar.html.haml | 12 +- 7 files changed, 456 insertions(+), 51 deletions(-) create mode 100644 app/assets/javascripts/bootstrap-alerts.js create mode 100644 app/assets/javascripts/bootstrap-twipsy.js diff --git a/app/assets/javascripts/bootstrap-alerts.js b/app/assets/javascripts/bootstrap-alerts.js new file mode 100644 index 0000000..37bb430 --- /dev/null +++ b/app/assets/javascripts/bootstrap-alerts.js @@ -0,0 +1,113 @@ +/* ========================================================== + * bootstrap-alerts.js v1.4.0 + * http://twitter.github.com/bootstrap/javascript.html#alerts + * ========================================================== + * Copyright 2011 Twitter, Inc. + * + * 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. + * ========================================================== */ + + +!function( $ ){ + + "use strict" + + /* CSS TRANSITION SUPPORT (https://gist.github.com/373874) + * ======================================================= */ + + var transitionEnd + + $(document).ready(function () { + + $.support.transition = (function () { + var thisBody = document.body || document.documentElement + , thisStyle = thisBody.style + , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined + return support + })() + + // set CSS transition event type + if ( $.support.transition ) { + transitionEnd = "TransitionEnd" + if ( $.browser.webkit ) { + transitionEnd = "webkitTransitionEnd" + } else if ( $.browser.mozilla ) { + transitionEnd = "transitionend" + } else if ( $.browser.opera ) { + transitionEnd = "oTransitionEnd" + } + } + + }) + + /* ALERT CLASS DEFINITION + * ====================== */ + + var Alert = function ( content, options ) { + this.settings = $.extend({}, $.fn.alert.defaults, options) + this.$element = $(content) + .delegate(this.settings.selector, 'click', this.close) + } + + Alert.prototype = { + + close: function (e) { + var $element = $(this).parent('.alert-message') + + e && e.preventDefault() + $element.removeClass('in') + + function removeElement () { + $element.remove() + } + + $.support.transition && $element.hasClass('fade') ? + $element.bind(transitionEnd, removeElement) : + removeElement() + } + + } + + + /* ALERT PLUGIN DEFINITION + * ======================= */ + + $.fn.alert = function ( options ) { + + if ( options === true ) { + return this.data('alert') + } + + return this.each(function () { + var $this = $(this) + + if ( typeof options == 'string' ) { + return $this.data('alert')[options]() + } + + $(this).data('alert', new Alert( this, options )) + + }) + } + + $.fn.alert.defaults = { + selector: '.close' + } + + $(document).ready(function () { + new Alert($('body'), { + selector: '.alert-message[data-alert] .close' + }) + }) + +}( window.jQuery || window.ender ); \ No newline at end of file diff --git a/app/assets/javascripts/bootstrap-twipsy.js b/app/assets/javascripts/bootstrap-twipsy.js new file mode 100644 index 0000000..5ebbddd --- /dev/null +++ b/app/assets/javascripts/bootstrap-twipsy.js @@ -0,0 +1,321 @@ +/* ========================================================== + * bootstrap-twipsy.js v1.4.0 + * http://twitter.github.com/bootstrap/javascript.html#twipsy + * Adapted from the original jQuery.tipsy by Jason Frame + * ========================================================== + * Copyright 2011 Twitter, Inc. + * + * 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. + * ========================================================== */ + + +!function( $ ) { + + "use strict" + + /* CSS TRANSITION SUPPORT (https://gist.github.com/373874) + * ======================================================= */ + + var transitionEnd + + $(document).ready(function () { + + $.support.transition = (function () { + var thisBody = document.body || document.documentElement + , thisStyle = thisBody.style + , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined + return support + })() + + // set CSS transition event type + if ( $.support.transition ) { + transitionEnd = "TransitionEnd" + if ( $.browser.webkit ) { + transitionEnd = "webkitTransitionEnd" + } else if ( $.browser.mozilla ) { + transitionEnd = "transitionend" + } else if ( $.browser.opera ) { + transitionEnd = "oTransitionEnd" + } + } + + }) + + + /* TWIPSY PUBLIC CLASS DEFINITION + * ============================== */ + + var Twipsy = function ( element, options ) { + this.$element = $(element) + this.options = options + this.enabled = true + this.fixTitle() + } + + Twipsy.prototype = { + + show: function() { + var pos + , actualWidth + , actualHeight + , placement + , $tip + , tp + + if (this.hasContent() && this.enabled) { + $tip = this.tip() + this.setContent() + + if (this.options.animate) { + $tip.addClass('fade') + } + + $tip + .remove() + .css({ top: 0, left: 0, display: 'block' }) + .prependTo(document.body) + + pos = $.extend({}, this.$element.offset(), { + width: this.$element[0].offsetWidth + , height: this.$element[0].offsetHeight + }) + + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + + placement = maybeCall(this.options.placement, this, [ $tip[0], this.$element[0] ]) + + switch (placement) { + case 'below': + tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'above': + tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'left': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset} + break + case 'right': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset} + break + } + + $tip + .css(tp) + .addClass(placement) + .addClass('in') + } + } + + , setContent: function () { + var $tip = this.tip() + $tip.find('.twipsy-inner')[this.options.html ? 'html' : 'text'](this.getTitle()) + $tip[0].className = 'twipsy' + } + + , hide: function() { + var that = this + , $tip = this.tip() + + $tip.removeClass('in') + + function removeElement () { + $tip.remove() + } + + $.support.transition && this.$tip.hasClass('fade') ? + $tip.bind(transitionEnd, removeElement) : + removeElement() + } + + , fixTitle: function() { + var $e = this.$element + if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title') + } + } + + , hasContent: function () { + return this.getTitle() + } + + , getTitle: function() { + var title + , $e = this.$element + , o = this.options + + this.fixTitle() + + if (typeof o.title == 'string') { + title = $e.attr(o.title == 'title' ? 'data-original-title' : o.title) + } else if (typeof o.title == 'function') { + title = o.title.call($e[0]) + } + + title = ('' + title).replace(/(^\s*|\s*$)/, "") + + return title || o.fallback + } + + , tip: function() { + return this.$tip = this.$tip || $('
').html(this.options.template) + } + + , validate: function() { + if (!this.$element[0].parentNode) { + this.hide() + this.$element = null + this.options = null + } + } + + , enable: function() { + this.enabled = true + } + + , disable: function() { + this.enabled = false + } + + , toggleEnabled: function() { + this.enabled = !this.enabled + } + + , toggle: function () { + this[this.tip().hasClass('in') ? 'hide' : 'show']() + } + + } + + + /* TWIPSY PRIVATE METHODS + * ====================== */ + + function maybeCall ( thing, ctx, args ) { + return typeof thing == 'function' ? thing.apply(ctx, args) : thing + } + + /* TWIPSY PLUGIN DEFINITION + * ======================== */ + + $.fn.twipsy = function (options) { + $.fn.twipsy.initWith.call(this, options, Twipsy, 'twipsy') + return this + } + + $.fn.twipsy.initWith = function (options, Constructor, name) { + var twipsy + , binder + , eventIn + , eventOut + + if (options === true) { + return this.data(name) + } else if (typeof options == 'string') { + twipsy = this.data(name) + if (twipsy) { + twipsy[options]() + } + return this + } + + options = $.extend({}, $.fn[name].defaults, options) + + function get(ele) { + var twipsy = $.data(ele, name) + + if (!twipsy) { + twipsy = new Constructor(ele, $.fn.twipsy.elementOptions(ele, options)) + $.data(ele, name, twipsy) + } + + return twipsy + } + + function enter() { + var twipsy = get(this) + twipsy.hoverState = 'in' + + if (options.delayIn == 0) { + twipsy.show() + } else { + twipsy.fixTitle() + setTimeout(function() { + if (twipsy.hoverState == 'in') { + twipsy.show() + } + }, options.delayIn) + } + } + + function leave() { + var twipsy = get(this) + twipsy.hoverState = 'out' + if (options.delayOut == 0) { + twipsy.hide() + } else { + setTimeout(function() { + if (twipsy.hoverState == 'out') { + twipsy.hide() + } + }, options.delayOut) + } + } + + if (!options.live) { + this.each(function() { + get(this) + }) + } + + if (options.trigger != 'manual') { + binder = options.live ? 'live' : 'bind' + eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus' + eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur' + this[binder](eventIn, enter)[binder](eventOut, leave) + } + + return this + } + + $.fn.twipsy.Twipsy = Twipsy + + $.fn.twipsy.defaults = { + animate: true + , delayIn: 0 + , delayOut: 0 + , fallback: '' + , placement: 'above' + , html: false + , live: false + , offset: 0 + , title: 'title' + , trigger: 'hover' + , template: '
' + } + + $.fn.twipsy.rejectAttrOptions = [ 'title' ] + + $.fn.twipsy.elementOptions = function(ele, options) { + var data = $(ele).data() + , rejects = $.fn.twipsy.rejectAttrOptions + , i = rejects.length + + while (i--) { + delete data[rejects[i]] + } + + return $.extend({}, options, data) + } + +}( window.jQuery || window.ender ); \ No newline at end of file diff --git a/app/assets/javascripts/main.js.erb b/app/assets/javascripts/main.js.erb index e046df8..e94289a 100644 --- a/app/assets/javascripts/main.js.erb +++ b/app/assets/javascripts/main.js.erb @@ -711,28 +711,5 @@ $(function() { }); return false; }); - $('#tos_link').live('click', function() { - $.ajax({ - type: 'GET', - url: '/tos', - beforeSend: function() { - $('#info_window').hide(); - $('#loader').show(); - }, - error: function(jqXHR) { - $('#loader').hide(); - $('#info_window').show(); - }, - success: function(data) { - activeInfoWindow.setContent(data); - } - }); - return false; - }); - $('#notice').live('click', function() { - $(this).fadeOut('slow'); - }); - $('#error').live('click', function() { - $(this).fadeOut('slow'); - }); + $('.alert-message').alert() }); diff --git a/app/assets/stylesheets/screen.css b/app/assets/stylesheets/screen.css index be61636..53ff937 100644 --- a/app/assets/stylesheets/screen.css +++ b/app/assets/stylesheets/screen.css @@ -86,7 +86,7 @@ form input.error:focus, form textarea.error:focus { -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; - text-align: center; + text-align: left; margin-bottom: 10px; } @@ -136,26 +136,6 @@ form input.error:focus, form textarea.error:focus { width: 100%; } -#error, #notice, #warning { - margin: auto; - padding: 5px 10px; -} - -#error { - background-color: #ff7373; - border: 1px solid #c07373; -} - -#notice { - background-color: #8fe38f; - border: 1px solid #82b082; -} - -#warning { - background-color: #fff773; - border: 1px solid #c0bb73; -} - .upcase { text-transform: uppercase; } diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 78cd2ae..5ebb966 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -8,6 +8,8 @@ = javascript_include_tag "http://maps.google.com/maps/api/js?sensor=false" = javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" = javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js" + = javascript_include_tag "bootstrap-twipsy" + = javascript_include_tag "bootstrap-alerts" = javascript_include_tag "main" = csrf_meta_tag %meta{:name => "viewport", :content => "initial-scale=1.0, user-scalable=no"} diff --git a/app/views/layouts/info_window.html.haml b/app/views/layouts/info_window.html.haml index 57bd104..793e1da 100644 --- a/app/views/layouts/info_window.html.haml +++ b/app/views/layouts/info_window.html.haml @@ -2,15 +2,21 @@ = image_tag "ajax-loader.gif" #info_window - if flash[:notice] - .alert-message.success + .alert-message.success{:"data-alert" => true} + %a{:class => "close", :href => "#"} + × %p = flash[:notice] - if flash[:warning] - .alert-message.warning + .alert-message.warning{:"data-alert" => true} + %a{:class => "close", :href => "#"} + × %p = flash[:warning] - if flash[:error] - .alert-message.error + .alert-message.error{:"data-alert" => true} + %a{:class => "close", :href => "#"} + × %p = flash[:error] = yield diff --git a/app/views/layouts/sidebar.html.haml b/app/views/layouts/sidebar.html.haml index a1ce87e..f17adff 100644 --- a/app/views/layouts/sidebar.html.haml +++ b/app/views/layouts/sidebar.html.haml @@ -1,13 +1,19 @@ - if flash[:notice] - .alert-message.success + .alert-message.success{:"data-alert" => true} + %a{:class => "close", :href => "#"} + × %p = flash[:notice] - if flash[:warning] - .alert-message.warning + .alert-message.warning{:"data-alert" => true} + %a{:class => "close", :href => "#"} + × %p = flash[:warning] - if flash[:error] - .alert-message.error + .alert-message.error{:"data-alert" => true} + %a{:class => "close", :href => "#"} + × %p = flash[:error] = yield