diff options
-rw-r--r-- | app/helpers/application_helper.rb | 9 | ||||
-rw-r--r-- | app/models/user_preference.rb | 3 | ||||
-rw-r--r-- | app/views/layouts/base.rhtml | 2 | ||||
-rw-r--r-- | app/views/users/_preferences.html.erb | 1 | ||||
-rw-r--r-- | config/locales/en.yml | 2 | ||||
-rw-r--r-- | config/locales/fr.yml | 2 | ||||
-rw-r--r-- | public/javascripts/application.js | 43 | ||||
-rw-r--r-- | test/functional/welcome_controller_test.rb | 24 |
8 files changed, 85 insertions, 1 deletions
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index c6d88487f..be0ebaec1 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -894,6 +894,15 @@ module ApplicationHelper '' end end + + # Returns the javascript tags that are included in the html layout head + def javascript_heads + tags = javascript_include_tag(:defaults) + unless User.current.pref.warn_on_leaving_unsaved == '0' + tags << "\n" + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });") + end + tags + end def favicon "<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />" diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb index 3daa7a740..85236ff64 100644 --- a/app/models/user_preference.rb +++ b/app/models/user_preference.rb @@ -51,4 +51,7 @@ class UserPreference < ActiveRecord::Base def comments_sorting; self[:comments_sorting] end def comments_sorting=(order); self[:comments_sorting]=order end + + def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end + def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end end diff --git a/app/views/layouts/base.rhtml b/app/views/layouts/base.rhtml index b59f1e280..d6d3400aa 100644 --- a/app/views/layouts/base.rhtml +++ b/app/views/layouts/base.rhtml @@ -8,7 +8,7 @@ <%= favicon %> <%= stylesheet_link_tag 'application', :media => 'all' %> <%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %> -<%= javascript_include_tag :defaults %> +<%= javascript_heads %> <%= heads_for_theme %> <%= heads_for_wiki_formatter %> <!--[if IE 6]> diff --git a/app/views/users/_preferences.html.erb b/app/views/users/_preferences.html.erb index 85b5990e3..57f050b10 100644 --- a/app/views/users/_preferences.html.erb +++ b/app/views/users/_preferences.html.erb @@ -2,5 +2,6 @@ <p><%= pref_fields.check_box :hide_mail %></p> <p><%= pref_fields.select :time_zone, ActiveSupport::TimeZone.all.collect {|z| [ z.to_s, z.name ]}, :include_blank => true %></p> <p><%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %></p> +<p><%= pref_fields.check_box :warn_on_leaving_unsaved %></p> <% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index d32a2bdbd..1757c1517 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -303,6 +303,7 @@ en: field_assigned_to_role: "Assignee's role" field_text: Text field field_visible: Visible + field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text" setting_app_title: Application title setting_app_subtitle: Application subtitle @@ -908,6 +909,7 @@ en: text_own_membership_delete_confirmation: "You are about to remove some or all of your permissions and may no longer be able to edit this project after that.\nAre you sure you want to continue?" text_zoom_in: Zoom in text_zoom_out: Zoom out + text_warn_on_leaving_unsaved: "The current page contains unsaved text that will be lost if you leave this page." default_role_manager: Manager default_role_developer: Developer diff --git a/config/locales/fr.yml b/config/locales/fr.yml index c154dd35d..aa5815a2f 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -307,6 +307,7 @@ fr: field_active: Actif field_parent_issue: Tâche parente field_visible: Visible + field_warn_on_leaving_unsaved: "M'avertir lorsque je quitte une page contenant du texte non sauvegardé" setting_app_title: Titre de l'application setting_app_subtitle: Sous-titre de l'application @@ -889,6 +890,7 @@ fr: text_wiki_page_destroy_children: "Supprimer les sous-pages et toutes leurs descedantes" text_wiki_page_reassign_children: "Réaffecter les sous-pages à cette page" text_own_membership_delete_confirmation: "Vous allez supprimer tout ou partie de vos permissions sur ce projet et ne serez peut-être plus autorisé à modifier ce projet.\nEtes-vous sûr de vouloir continuer ?" + text_warn_on_leaving_unsaved: "Cette page contient du texte non sauvegardé qui sera perdu si vous quittez la page." default_role_manager: "Manager " default_role_developer: "Développeur " diff --git a/public/javascripts/application.js b/public/javascripts/application.js index 6cea8f3dd..a88856ea6 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -255,6 +255,49 @@ function observeProjectModules() { Event.observe('project_enabled_module_names_issue_tracking', 'change', f); } +/* + * Class used to warn user when leaving a page with unsaved textarea + * Author: mathias.fischer@berlinonline.de +*/ + +var WarnLeavingUnsaved = Class.create({ + observedForms: false, + observedElements: false, + changedForms: false, + message: null, + + initialize: function(message){ + this.observedForms = $$('form'); + this.observedElements = $$('textarea'); + this.message = message; + + this.observedElements.each(this.observeChange.bind(this)); + this.observedForms.each(this.submitAction.bind(this)); + + window.onbeforeunload = this.unload.bind(this); + }, + + unload: function(){ + if(this.changedForms) + return this.message; + }, + + setChanged: function(){ + this.changedForms = true; + }, + + setUnchanged: function(){ + this.changedForms = false; + }, + + observeChange: function(element){ + element.observe('change',this.setChanged.bindAsEventListener(this)); + }, + + submitAction: function(element){ + element.observe('submit',this.setUnchanged.bindAsEventListener(this)); + } +}); /* shows and hides ajax indicator */ Ajax.Responders.register({ diff --git a/test/functional/welcome_controller_test.rb b/test/functional/welcome_controller_test.rb index 7a53c8b6a..86542829b 100644 --- a/test/functional/welcome_controller_test.rb +++ b/test/functional/welcome_controller_test.rb @@ -67,4 +67,28 @@ class WelcomeControllerTest < ActionController::TestCase assert_equal 'text/plain', @response.content_type assert @response.body.match(%r{^Disallow: /projects/ecookbook/issues\r?$}) end + + def test_warn_on_leaving_unsaved_turn_on + user = User.find(2) + user.pref.warn_on_leaving_unsaved = '1' + user.pref.save! + @request.session[:user_id] = 2 + + get :index + assert_tag 'script', + :attributes => {:type => "text/javascript"}, + :content => %r{new WarnLeavingUnsaved} + end + + def test_warn_on_leaving_unsaved_turn_off + user = User.find(2) + user.pref.warn_on_leaving_unsaved = '0' + user.pref.save! + @request.session[:user_id] = 2 + + get :index + assert_no_tag 'script', + :attributes => {:type => "text/javascript"}, + :content => %r{new WarnLeavingUnsaved} + end end |