Warning on leaving a page with unsaved content in textarea (#2910).
The warning can be turned off in the user's preference. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4900 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
11c72f2823
commit
17591a3ea5
|
@ -894,6 +894,15 @@ module ApplicationHelper
|
||||||
''
|
''
|
||||||
end
|
end
|
||||||
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
|
def favicon
|
||||||
"<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />"
|
"<link rel='shortcut icon' href='#{image_path('/favicon.ico')}' />"
|
||||||
|
|
|
@ -51,4 +51,7 @@ class UserPreference < ActiveRecord::Base
|
||||||
|
|
||||||
def comments_sorting; self[:comments_sorting] end
|
def comments_sorting; self[:comments_sorting] end
|
||||||
def comments_sorting=(order); self[:comments_sorting]=order 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
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<%= favicon %>
|
<%= favicon %>
|
||||||
<%= stylesheet_link_tag 'application', :media => 'all' %>
|
<%= stylesheet_link_tag 'application', :media => 'all' %>
|
||||||
<%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %>
|
<%= stylesheet_link_tag 'rtl', :media => 'all' if l(:direction) == 'rtl' %>
|
||||||
<%= javascript_include_tag :defaults %>
|
<%= javascript_heads %>
|
||||||
<%= heads_for_theme %>
|
<%= heads_for_theme %>
|
||||||
<%= heads_for_wiki_formatter %>
|
<%= heads_for_wiki_formatter %>
|
||||||
<!--[if IE 6]>
|
<!--[if IE 6]>
|
||||||
|
|
|
@ -2,5 +2,6 @@
|
||||||
<p><%= pref_fields.check_box :hide_mail %></p>
|
<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 :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.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 %>
|
<% end %>
|
||||||
|
|
||||||
|
|
|
@ -303,6 +303,7 @@ en:
|
||||||
field_assigned_to_role: "Assignee's role"
|
field_assigned_to_role: "Assignee's role"
|
||||||
field_text: Text field
|
field_text: Text field
|
||||||
field_visible: Visible
|
field_visible: Visible
|
||||||
|
field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text"
|
||||||
|
|
||||||
setting_app_title: Application title
|
setting_app_title: Application title
|
||||||
setting_app_subtitle: Application subtitle
|
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_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_in: Zoom in
|
||||||
text_zoom_out: Zoom out
|
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_manager: Manager
|
||||||
default_role_developer: Developer
|
default_role_developer: Developer
|
||||||
|
|
|
@ -307,6 +307,7 @@ fr:
|
||||||
field_active: Actif
|
field_active: Actif
|
||||||
field_parent_issue: Tâche parente
|
field_parent_issue: Tâche parente
|
||||||
field_visible: Visible
|
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_title: Titre de l'application
|
||||||
setting_app_subtitle: Sous-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_destroy_children: "Supprimer les sous-pages et toutes leurs descedantes"
|
||||||
text_wiki_page_reassign_children: "Réaffecter les sous-pages à cette page"
|
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_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_manager: "Manager "
|
||||||
default_role_developer: "Développeur "
|
default_role_developer: "Développeur "
|
||||||
|
|
|
@ -255,6 +255,49 @@ function observeProjectModules() {
|
||||||
Event.observe('project_enabled_module_names_issue_tracking', 'change', f);
|
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 */
|
/* shows and hides ajax indicator */
|
||||||
Ajax.Responders.register({
|
Ajax.Responders.register({
|
||||||
|
|
|
@ -67,4 +67,28 @@ class WelcomeControllerTest < ActionController::TestCase
|
||||||
assert_equal 'text/plain', @response.content_type
|
assert_equal 'text/plain', @response.content_type
|
||||||
assert @response.body.match(%r{^Disallow: /projects/ecookbook/issues\r?$})
|
assert @response.body.match(%r{^Disallow: /projects/ecookbook/issues\r?$})
|
||||||
end
|
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
|
end
|
||||||
|
|
Loading…
Reference in New Issue