summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/helpers/application_helper.rb9
-rw-r--r--app/models/user_preference.rb3
-rw-r--r--app/views/layouts/base.rhtml2
-rw-r--r--app/views/users/_preferences.html.erb1
-rw-r--r--config/locales/en.yml2
-rw-r--r--config/locales/fr.yml2
-rw-r--r--public/javascripts/application.js43
-rw-r--r--test/functional/welcome_controller_test.rb24
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