diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index bcb6ffa..a6bd241 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -12,7 +12,9 @@ var AUTH_TOKEN=#{form_authenticity_token.inspect}; = stylesheet_link_tag('application') = stylesheet_link_tag('print', :media => :print) - = javascript_include_tag 'jquery', 'jquery.validate', 'jquery.cookie', 'jquery.form', 'jquery.hint', 'jquery.livequery', 'ui.core', 'ui.tabs', 'jquery.jgrow', 'application', :cache => true + = javascript_include_tag 'jquery', 'jquery.validate', 'jquery.form', 'jquery.hint', 'jquery.autogrow', 'modernizr', 'application', :cache => 'all' + - if current_user + = javascript_include_tag 'jquery.cookie', 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.tabs', 'admin' - if iphone? %meta{:name => "viewport", :content => "width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"} = stylesheet_link_tag 'iphone' diff --git a/public/javascripts/admin.js b/public/javascripts/admin.js new file mode 100644 index 0000000..9c81259 --- /dev/null +++ b/public/javascripts/admin.js @@ -0,0 +1,95 @@ +$(document).ready(function(){ + // ajax delete + $('a.delete').live('click', function(){ + var elem = $(this); + if (confirm("Are you sure?")){ + $.post($(this).attr('href'), "_method=delete",function(){ + elem.closest('div').slideUp(); + }); + } + return false; + }).attr("rel", "nofollow"); + + // new post form tabs + $("#new_post").tabs({cookie: {}}); + + if ($.cookie("hide_new_post") == 'false') { + $('#new_post').show(); + $('a.open').hide(); + } + else { + $('#new_post').hide(); + $('a.open').show(); + } + + $('.ui-tabs-nav').bind('tabsselect', function(event, ui) { + $('label.error').remove(); + $('a.more').show(); + $('div.more').hide(); + $('.ui-tabs-nav').hintFields(); + }); + + $('a.open').click(function(){ + $('a.open').fadeOut(); + $('#new_post').slideDown(); + $.cookie("hide_new_post", 'false'); + return false; + }); + + $('a.close').click(function(){ + $('#new_post').slideUp(function(){ + $('a.open').fadeIn(); + }); + $.cookie("hide_new_post", 'true'); + $('.preview').remove(); + return false; + }); + + // extra post options + $('#new_post div.more').hide(); + $('#new_post a.more').click(function(){ + $('#new_post div.more').slideDown(); + $(this).hide(); + return false; + }); + + // setup validation and ajax post forms + $(".new_post").each(function(){ + $(this).validate({ + rules: { + 'video[video_embed]': { + required: "#video_link_url:blank" + } + }, + submitHandler: function(form){ + $(form).ajaxSubmit({ + beforeSubmit: function(){ + $('.new_post .submit').after(''); + $('.new_post :submit').attr('disabled', 'disabled'); + }, + complete: function(){ + $('.loading').remove(); + $('.new_post :submit').removeAttr('disabled'); + }, + success: function(data){ + $('.preview').remove(); + $('#posts').prepend(data); + if ($('.preview').size() === 0){ + $(form).resetForm(); + if ($('.pagination').size() > 0){ + $('#posts .post:last').remove(); + } + } + $(form).hintFields(); + }, + error:function(request, textStatus, errorThrown) { + var message = (request.status == 401 || request.status == 403) ? + request.responseText : "An unknown error occurred. Support has been contacted."; + alert(message); + } + + }); + } + }); + }); +}); \ No newline at end of file diff --git a/public/javascripts/application.js b/public/javascripts/application.js index bef37af..e4ada32 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -1,6 +1,6 @@ jQuery.fn.hintFields = function(){ - for (var i = 0; i < this.length; i++){ - if (!$.browser.safari){ $('input:text', this[i]).hint();} + for (var i = 0, l = this.length; i < l; i++){ + if (!Modernizr.input.placeholder){ $('input:text', this[i]).hint();} $('textarea', this[i]).hint(); } }; @@ -12,6 +12,10 @@ $(document).ready(function(){ ignoreTitle: true }); + if ($.browser.webkit){ + $('input[type="search"]').attr({autosave: location.host, results: 10}) + } + // rails ajax setup jQuery.ajaxSetup({ 'beforeSend': function(xhr){ xhr.setRequestHeader("Accept","text/javascript"); } @@ -25,117 +29,21 @@ $(document).ready(function(){ settings.data += (settings.data ? "&" : "") + "authenticity_token=" + encodeURIComponent(AUTH_TOKEN); }); - // ajax delete - $('a.delete').livequery('click', function(){ - var elem = $(this); - if (confirm("Are you sure?")){ - $.post($(this).attr('href'), "_method=delete",function(){ - elem.closest('div').slideUp(); - }); - } - return false; - }).attr("rel", "nofollow"); - // open external links in a new window $('a[rel="external"]').click( function(){ window.open($(this).attr('href')); return false; }); - // new post form tabs - $("#new_post > ul").tabs({cookie: {}}); - - if ($.cookie("hide_new_post") == 'false') { - $('#new_post').show(); - $('a.open').hide(); - } - else { - $('#new_post').hide(); - $('a.open').show(); - } - - $('.ui-tabs-nav').bind('tabsselect', function(event, ui) { - $('label.error').remove(); - $('a.more').show(); - $('div.more').hide(); - $('.ui-tabs-nav').hintFields(); - }); - - $('a.open').click(function(){ - $('a.open').fadeOut(); - $('#new_post').slideDown(); - $.cookie("hide_new_post", 'false'); - return false; - }); - - $('a.close').click(function(){ - $('#new_post').slideUp(function(){ - $('a.open').fadeIn(); - }); - $.cookie("hide_new_post", 'true'); - $('.preview').remove(); - return false; - }); - - // extra post options - $('#new_post div.more').hide(); - $('#new_post a.more').click(function(){ - $('#new_post div.more').slideDown(); - $(this).hide(); - return false; - }); - // text field hints $('form').hintFields(); - + + // slide open/closed the formatting help div $('a.help').click(function(){ $('#formatting').toggle(100); return false; }); - // expanding textareas - $('textarea').jGrow(); - - // setup validation and ajax post forms - $(".new_post").each(function(){ - $(this).validate({ - rules: { - 'video[video_embed]': { - required: "#video_link_url:blank" - } - }, - submitHandler: function(form){ - $(form).ajaxSubmit({ - beforeSubmit: function(){ - $('.new_post .submit').after(''); - $('.new_post :submit').attr('disabled', 'disabled'); - }, - complete: function(){ - $('.loading').remove(); - $('.new_post :submit').removeAttr('disabled'); - }, - success: function(data){ - $('.preview').remove(); - $('#posts').prepend(data); - if ($('.preview').size() == 0){ - $(form).resetForm(); - if ($('.pagination').size() > 0){ - $('#posts .post:last').remove(); - } - } - $(form).hintFields(); - }, - error:function(request, textStatus, errorThrown) { - var message = (request.status == 401 || request.status == 403) ? - request.responseText : "An unknown error occurred. Support has been contacted."; - alert(message); - } - - }); - } - }); - }); - // setup validation and ajax comments forms $(".new_comment").validate({ submitHandler: function(form){ @@ -148,9 +56,12 @@ $(document).ready(function(){ $(form).resetForm().hintFields(); }, error:function(request, textStatus, errorThrown) { - var message = (request.status == 401 || request.status == 403) ? + var message = (request.status == 401 || request.status == 403 || request.status == 406) ? request.responseText : "An unknown error occurred. Support has been contacted."; alert(message); + if (request.status == 406) { + $(form).resetForm().hintFields(); + } } }); } @@ -158,4 +69,5 @@ $(document).ready(function(){ // fade out flash setTimeout(function(){$(".flash").fadeOut(1000);},10000); + }); \ No newline at end of file diff --git a/public/javascripts/jquery.form.js b/public/javascripts/jquery.form.js index 2e27067..d6d28cc 100644 --- a/public/javascripts/jquery.form.js +++ b/public/javascripts/jquery.form.js @@ -1,306 +1,367 @@ /* * jQuery Form Plugin - * version: 2.12 (06/07/2008) - * @requires jQuery v1.2.2 or later + * version: 2.40 (26-FEB-2010) + * @requires jQuery v1.3.2 or later * * Examples and documentation at: http://malsup.com/jquery/form/ * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html - * - * Revision: $Id$ */ -(function($) { +;(function($) { /* - Usage Note: - ----------- - Do not use both ajaxSubmit and ajaxForm on the same form. These - functions are intended to be exclusive. Use ajaxSubmit if you want - to bind your own submit handler to the form. For example, - - $(document).ready(function() { - $('#myForm').bind('submit', function() { - $(this).ajaxSubmit({ - target: '#output' - }); - return false; // <-- important! - }); - }); - - Use ajaxForm when you want the plugin to manage all the event binding - for you. For example, - - $(document).ready(function() { - $('#myForm').ajaxForm({ - target: '#output' - }); - }); - - When using ajaxForm, the ajaxSubmit function will be invoked for you - at the appropriate time. + Usage Note: + ----------- + Do not use both ajaxSubmit and ajaxForm on the same form. These + functions are intended to be exclusive. Use ajaxSubmit if you want + to bind your own submit handler to the form. For example, + + $(document).ready(function() { + $('#myForm').bind('submit', function() { + $(this).ajaxSubmit({ + target: '#output' + }); + return false; // <-- important! + }); + }); + + Use ajaxForm when you want the plugin to manage all the event binding + for you. For example, + + $(document).ready(function() { + $('#myForm').ajaxForm({ + target: '#output' + }); + }); + + When using ajaxForm, the ajaxSubmit function will be invoked for you + at the appropriate time. */ /** - * ajaxSubmit() provides a mechanism for immediately submitting + * ajaxSubmit() provides a mechanism for immediately submitting * an HTML form using AJAX. */ $.fn.ajaxSubmit = function(options) { - // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) - if (!this.length) { - log('ajaxSubmit: skipping submit process - no element selected'); - return this; - } - - if (typeof options == 'function') - options = { success: options }; - - options = $.extend({ - url: this.attr('action') || window.location.toString(), - type: this.attr('method') || 'GET' - }, options || {}); - - // hook for manipulating the form data before it is extracted; - // convenient for use with rich editors like tinyMCE or FCKEditor - var veto = {}; - this.trigger('form-pre-serialize', [this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); - return this; - } - - var a = this.formToArray(options.semantic); - if (options.data) { - options.extraData = options.data; - for (var n in options.data) - a.push( { name: n, value: options.data[n] } ); - } - - // give pre-submit callback an opportunity to abort the submit - if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { - log('ajaxSubmit: submit aborted via beforeSubmit callback'); - return this; - } - - // fire vetoable 'validate' event - this.trigger('form-submit-validate', [a, this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); - return this; - } - - var q = $.param(a); - - if (options.type.toUpperCase() == 'GET') { - options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; - options.data = null; // data is null for 'get' - } - else - options.data = q; // data is the query string for 'post' - - var $form = this, callbacks = []; - if (options.resetForm) callbacks.push(function() { $form.resetForm(); }); - if (options.clearForm) callbacks.push(function() { $form.clearForm(); }); - - // perform a load on the target only if dataType is not provided - if (!options.dataType && options.target) { - var oldSuccess = options.success || function(){}; - callbacks.push(function(data) { - $(options.target).html(data).each(oldSuccess, arguments); - }); - } - else if (options.success) - callbacks.push(options.success); - - options.success = function(data, status) { - for (var i=0, max=callbacks.length; i < max; i++) - callbacks[i](data, status, $form); - }; - - // are there files to upload? - var files = $('input:file', this).fieldValue(); - var found = false; - for (var j=0; j < files.length; j++) - if (files[j]) - found = true; - - // options.iframe allows user to force iframe mode - if (options.iframe || found) { - // hack to fix Safari hang (thanks to Tim Molendijk for this) - // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d - if ($.browser.safari && options.closeKeepAlive) - $.get(options.closeKeepAlive, fileUpload); - else - fileUpload(); - } + // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) + if (!this.length) { + log('ajaxSubmit: skipping submit process - no element selected'); + return this; + } + + if (typeof options == 'function') + options = { success: options }; + + var url = $.trim(this.attr('action')); + if (url) { + // clean url (don't include hash vaue) + url = (url.match(/^([^#]+)/)||[])[1]; + } + url = url || window.location.href || ''; + + options = $.extend({ + url: url, + type: this.attr('method') || 'GET', + iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' + }, options || {}); + + // hook for manipulating the form data before it is extracted; + // convenient for use with rich editors like tinyMCE or FCKEditor + var veto = {}; + this.trigger('form-pre-serialize', [this, options, veto]); + if (veto.veto) { + log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); + return this; + } + + // provide opportunity to alter form data before it is serialized + if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { + log('ajaxSubmit: submit aborted via beforeSerialize callback'); + return this; + } + + var a = this.formToArray(options.semantic); + if (options.data) { + options.extraData = options.data; + for (var n in options.data) { + if(options.data[n] instanceof Array) { + for (var k in options.data[n]) + a.push( { name: n, value: options.data[n][k] } ); + } + else + a.push( { name: n, value: options.data[n] } ); + } + } + + // give pre-submit callback an opportunity to abort the submit + if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { + log('ajaxSubmit: submit aborted via beforeSubmit callback'); + return this; + } + + // fire vetoable 'validate' event + this.trigger('form-submit-validate', [a, this, options, veto]); + if (veto.veto) { + log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); + return this; + } + + var q = $.param(a); + + if (options.type.toUpperCase() == 'GET') { + options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; + options.data = null; // data is null for 'get' + } + else + options.data = q; // data is the query string for 'post' + + var $form = this, callbacks = []; + if (options.resetForm) callbacks.push(function() { $form.resetForm(); }); + if (options.clearForm) callbacks.push(function() { $form.clearForm(); }); + + // perform a load on the target only if dataType is not provided + if (!options.dataType && options.target) { + var oldSuccess = options.success || function(){}; + callbacks.push(function(data) { + $(options.target).html(data).each(oldSuccess, arguments); + }); + } + else if (options.success) + callbacks.push(options.success); + + options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg + for (var i=0, max=callbacks.length; i < max; i++) + callbacks[i].apply(options, [data, status, xhr || $form, $form]); + }; + + // are there files to upload? + var files = $('input:file', this).fieldValue(); + var found = false; + for (var j=0; j < files.length; j++) + if (files[j]) + found = true; + + var multipart = false; +// var mp = 'multipart/form-data'; +// multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); + + // options.iframe allows user to force iframe mode + // 06-NOV-09: now defaulting to iframe mode if file input is detected + if ((files.length && options.iframe !== false) || options.iframe || found || multipart) { + // hack to fix Safari hang (thanks to Tim Molendijk for this) + // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d + if (options.closeKeepAlive) + $.get(options.closeKeepAlive, fileUpload); + else + fileUpload(); + } else - $.ajax(options); - - // fire 'notify' event - this.trigger('form-submit-notify', [this, options]); - return this; - - - // private function for handling file uploads (hat tip to YAHOO!) - function fileUpload() { - var form = $form[0]; - - if ($(':input[@name=submit]', form).length) { - alert('Error: Form elements must not be named "submit".'); - return; - } - - var opts = $.extend({}, $.ajaxSettings, options); - - var id = 'jqFormIO' + (new Date().getTime()); - var $io = $('