diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index f672510f..41d2b80e 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -129,7 +129,7 @@ class ProjectsController < ApplicationController @hidden_projects_count = current_user.projects.hidden.count @completed_projects_count = current_user.projects.completed.count init_data_for_sidebar - render :template => 'projects/update.js.rjs' + render :template => 'projects/update.js.erb' return elsif boolean_param('update_status') render :template => 'projects/update_status.js.rjs' @@ -151,10 +151,10 @@ class ProjectsController < ApplicationController end else init_data_for_sidebar - render :template => 'projects/update.js.rjs' + render :template => 'projects/update.js.erb' return end - render :template => 'projects/update.js.rjs' + render :template => 'projects/update.js.erb' end def edit diff --git a/app/views/layouts/standard.html.erb b/app/views/layouts/standard.html.erb index bd5b4a82..1297df84 100644 --- a/app/views/layouts/standard.html.erb +++ b/app/views/layouts/standard.html.erb @@ -5,7 +5,7 @@ <%= stylesheet_link_tag 'standard','superfish','niftyCorners', 'jquery-ui-1.8.5.custom', :cache => true %> <%= stylesheet_link_tag "print", :media => "print" %> <%= javascript_include_tag 'jquery-1.4.2.min', 'jquery-ui-1.8.5.custom.min', 'jquery.truncator', - 'jquery.jeditable.mini', 'jquery.cookie', 'jquery.blockUI', :cache => 'jquery-all' %> + 'jquery.jeditable.mini', 'jquery.cookie', 'jquery.blockUI', 'jquery.form', :cache => 'jquery-all' %> <%= javascript_include_tag 'hoverIntent','superfish','application', 'accesskey-hints','niftycube','swfobject', :cache => 'tracks' %> <%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %> diff --git a/app/views/projects/_project_form.rhtml b/app/views/projects/_project_form.rhtml index 177f6102..7b409023 100644 --- a/app/views/projects/_project_form.rhtml +++ b/app/views/projects/_project_form.rhtml @@ -2,7 +2,11 @@ project = project_form %> -<%# form_remote_tag(:url => project_path(project), :html => { :id => dom_id(project, 'edit_form'), :class => "inline-form "+dom_id(project, 'edit_form')+"-edit-project-form", :method => :put }) do -%> +<% form_for(project, :html => { + :id => dom_id(project, 'edit_form'), + :class => "inline-form edit-project-form", + :method => :put }) do + -%>
<%= error_messages_for("project") %>
<%= source_view_tag( @source_view ) -%> @@ -39,6 +43,6 @@ project = project_form

- -<%# end -%> - +<% +end +-%> \ No newline at end of file diff --git a/app/views/projects/edit.js.erb b/app/views/projects/edit.js.erb index 1e92b09a..2d2e7cd2 100644 --- a/app/views/projects/edit.js.erb +++ b/app/views/projects/edit.js.erb @@ -2,10 +2,4 @@ newHtml = "<%= escape_javascript(render(:partial => 'project_form', :locals => { $('div#<%=dom_id(@project, 'edit')%>').html(newHtml); $('div#<%=dom_id(@project)%>').hide(); $('div#<%=dom_id(@project, 'edit')%>').show(); - $('input.project-name').focus(); - -<%#*page[dom_id(@project, 'edit')].replace_html :partial => 'project_form', :locals => { :project_form => @project }%> -<%#*page[@project].hide%> -<%#*page[dom_id(@project, 'edit')].show%> -<%#*page[dom_id(@project, 'edit_form')].find('input.project-name').focus%> diff --git a/app/views/projects/update.js.erb b/app/views/projects/update.js.erb new file mode 100644 index 00000000..f8390175 --- /dev/null +++ b/app/views/projects/update.js.erb @@ -0,0 +1,69 @@ +<% if @saved -%> + pageNotify('notice', '<%=t('projects.project_saved_status')%>', 5); + <% if source_view_is :project_list -%> + <% if @state_changed -%> + <% else -%> + <% end -%> + <% else # source_view must be :project %> + $('#<%=dom_id(@project, 'edit')%>').hide(); + $('#<%=dom_id(@project, 'container')%>').html("<%= escape_javascript(render(:partial => 'project_settings', :locals => { :project => @project })) %> "); + $('#<%=dom_id(@project)%>').show(); + $('input#todo_project_name').val("<%= escape_javascript(@project.name)%>"); + <% if @project.default_context %> + $('input#todo_context_name').val("<%= escape_javascript(@project.default_context.name)%>"); + $('input[name=default_context_name]').val('<%= escape_javascript(@project.default_context.name)%>'); + <% end %> + <% if @project.default_tags %> + $('input#tag_list').val("<%= escape_javascript(@project.default_tags)%>"); + <% end %> + <% end %> + $('#default_project_name_id').val('<%= escape_javascript(@project.name)%>'); + $('input#todo_project_name').val("<%= escape_javascript(@project.name)%>"); + $('#project_name').html("<%= escape_javascript(@project.name)%>"); + $('#sidebar').html("<%= escape_javascript(render(:file => 'sidebar/sidebar.html.erb')) %>"); +<% else -%> + $('div#error_status').html("<%= escape_javascript(error_messages_for('project')) %>"); + $('div#error_status').show(); +<% end %> +enable_rich_interaction(); + +<%# *page << "console.log(\"hello\");"%> +<%# *if @saved%> +<%# *status_message = 'Project saved'%> +<%# *page.notify :notice, status_message, 5.0%> +<%# *if source_view_is :project_list%> +<%# *if @state_changed%> +<%#*page[dom_id(@project, 'container')].remove%> +<%#*page.insert_html :bottom, "list-#{@project.state}-projects", :partial => 'project_listing', :object => @project%> +<%# *else%> +<%#*page.replace_html dom_id(@project, 'container'), :partial => 'project_listing', :object => @project%> +<%# *end%> +<%#*page.sortable "list-#{@project.state}-projects", get_listing_sortable_options("list-#{@project.state}-projects")%> +<%#*page.replace_html "active-projects-count", @active_projects_count%> +<%#*page.replace_html "hidden-projects-count", @hidden_projects_count%> +<%#*page.replace_html "completed-projects-count", @completed_projects_count%> + +<%#*page.set_element_visible("list-hidden-projects-container", @hidden_projects_count > 0)%> +<%#*page.set_element_visible("list-active-projects-container", @active_projects_count > 0)%> +<%#*page.set_element_visible("list-completed-projects-container", @completed_projects_count > 0)%> +<%# *else%> +<%# *page[dom_id(@project, 'edit')].hide%> +<%# *page.replace_html dom_id(@project, 'container'), :partial => 'project_settings', :locals => { :project => @project }%> +<%# *page[dom_id(@project)].show%> + +<%# *page['todo_context_name'].value = @project.default_context.name if @project.default_context%> +<%# *page['#todo_project_name'].value = @project.name%> +<%# *page['tag_list'].value = @project.default_tags if @project.default_tags%> +<%# *page << "$('input[name=default_context_name]').val('#{@project.default_context.name}');" if @project.default_context%> +<%# *end%> + +<%# *page['default_project_name_id'].value = @project.name%> +<%# *page['todo_project_name'].value = @project.name%> +<%# *page.replace_html "project_name", @project.name%> + +<%# *page.replace_html "sidebar", :file => 'sidebar/sidebar.html.erb'%> +<%# *else%> +<%# *page.show 'error_status'%> +<%# *page.replace_html 'error_status', "#{error_messages_for('project')}"%> +<%# *end%> +<%# *page << "enable_rich_interaction();"%> diff --git a/app/views/projects/update.js.rjs b/app/views/projects/update.js.rjs deleted file mode 100644 index 5ab8d0e6..00000000 --- a/app/views/projects/update.js.rjs +++ /dev/null @@ -1,39 +0,0 @@ -if @saved - status_message = t('projects.project_saved_status') - page.notify :notice, status_message, 5.0 - if source_view_is :project_list - if @state_changed - page[dom_id(@project, 'container')].remove - page.insert_html :bottom, "list-#{@project.state}-projects", :partial => 'project_listing', :object => @project - else - page.replace_html dom_id(@project, 'container'), :partial => 'project_listing', :object => @project - end - page.sortable "list-#{@project.state}-projects", get_listing_sortable_options("list-#{@project.state}-projects") - page.replace_html "active-projects-count", @active_projects_count - page.replace_html "hidden-projects-count", @hidden_projects_count - page.replace_html "completed-projects-count", @completed_projects_count - - page.set_element_visible("list-hidden-projects-container", @hidden_projects_count > 0) - page.set_element_visible("list-active-projects-container", @active_projects_count > 0) - page.set_element_visible("list-completed-projects-container", @completed_projects_count > 0) - else - page[dom_id(@project, 'edit')].hide - page.replace_html dom_id(@project, 'container'), :partial => 'project_settings', :locals => { :project => @project } - page[dom_id(@project)].show - - page['todo_context_name'].value = @project.default_context.name if @project.default_context - page['#todo_project_name'].value = @project.name - page['tag_list'].value = @project.default_tags if @project.default_tags - page << "$('input[name=default_context_name]').val('#{@project.default_context.name}');" if @project.default_context - end - - page['default_project_name_id'].value = @project.name - page['todo_project_name'].value = @project.name - page.replace_html "project_name", @project.name - - page.replace_html "sidebar", :file => 'sidebar/sidebar.html.erb' -else - page.show 'error_status' - page.replace_html 'error_status', "#{error_messages_for('project')}" -end -page << "enable_rich_interaction();" diff --git a/public/javascripts/application.js b/public/javascripts/application.js index 4ac18818..c5f2334b 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -281,6 +281,20 @@ function enable_rich_interaction(){ field_touched = false; $('h2#project_name').editable(save_project_name, {style: 'padding:0px', submit: "OK"}); + + /* set behavior for edit project settings link */ + $("a.project_edit_settings").live('click', function (ev) { + $.ajax({ + url: this.href, + project_dom_id: 'project_'+this.id, + dataType: 'script', + beforeSend: function() {$(this.project_dom_id).block({message: null});}, + complete:function() {$(this.project_dom_id).unblock(); enable_rich_interaction();} + }); + return false; + }); + + $("form.edit-project-form button.positive").live('click', function (ev) { $('form.edit-project-form').ajaxSubmit({type: 'POST', async: false}); return false; }); } /* Auto-refresh */ @@ -300,6 +314,14 @@ function setup_auto_refresh(interval){ }); } +function pageNotify(type, message, fade_duration_in_sec) { + flash = $('h4#flash'); + flash.html("

"+message+"

"); + flash = $('h4#flash'); + flash.show(); + flash.fadeOut(fade_duration_in_sec*1000); +} + function setup_periodic_check(url_for_check, interval_in_sec, method) { ajaxMethod = "GET" if (method) { ajaxMethod = method; } @@ -390,19 +412,6 @@ $(document).ready(function() { return false; }); - /* set behavior for edit project settings link */ - $("a.project_edit_settings").live('click', function (ev) { - $.ajax({ - url: this.href, - async: false, - project_dom_id: 'project_'+this.id, - dataType: 'script', - beforeSend: function() {$(this.project_dom_id).block({message: null});}, - complete:function() {$(this.project_dom_id).unblock();; enable_rich_interaction();} - }); - return false; - }); - setup_container_toggles(); $('#toggle_action_new').click(function(){ diff --git a/public/javascripts/jquery.form.js b/public/javascripts/jquery.form.js new file mode 100644 index 00000000..2f165464 --- /dev/null +++ b/public/javascripts/jquery.form.js @@ -0,0 +1,781 @@ +/*! + * jQuery Form Plugin + * version: 2.47 (04-SEP-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 + */ +;(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. +*/ + +/** + * 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 }; + } + + 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(true, { + 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 n,v,a = this.formToArray(options.semantic); + if (options.data) { + options.extraData = options.data; + for (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 { + v = options.data[n]; + v = $.isFunction(v) ? v() : v; // if value is fn, invoke it + a.push( { name: n, value: v } ); + } + } + } + + // 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) { + var fn = options.replaceTarget ? 'replaceWith' : 'html'; + $(options.target)[fn](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 + var context = options.context || options; // jQuery 1.4+ supports scope context + for (var i=0, max=callbacks.length; i < max; i++) { + callbacks[i].apply(context, [data, status, xhr || $form, $form]); + } + }; + + // are there files to upload? + var fileInputs = $('input:file', this).length > 0; + var mp = 'multipart/form-data'; + var 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 (options.iframe !== false && (fileInputs || options.iframe || 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],:input[id=submit]', form).length) { + // if there is an input with a name or id of 'submit' then we won't be + // able to invoke the submit fn on the form (at least not x-browser) + alert('Error: Form elements must not have name or id of "submit".'); + return; + } + + var s = $.extend(true, {}, $.ajaxSettings, options); + s.context = s.context || s; + var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id; + window[fn] = function() { + var f = $io.data('form-plugin-onload'); + if (f) { + f(); + window[fn] = undefined; + try { delete window[fn]; } catch(e){} + } + } + var $io = $('