Преглед изворни кода

Add an unsaved changes alert on config pages

Before, you could leave a configuration page without knowing if you saved your changes or not.
Now, there is an alert poping up if you have unsaved changes. It will ask you if you want to stay on the page and save your changes or leave the page and loose your changes.

See #739
Alexis Degrugillier пре 11 година
родитељ
комит
dd4fb519be

+ 6 - 6
app/views/auth/index.phtml

@@ -9,7 +9,7 @@
 		<div class="form-group">
 			<label class="group-name" for="auth_type"><?php echo _t('admin.auth.type'); ?></label>
 			<div class="group-controls">
-				<select id="auth_type" name="auth_type" required="required">
+				<select id="auth_type" name="auth_type" required="required" data-leave-validation="<?php echo FreshRSS_Context::$system_conf->auth_type; ?>">
 					<?php if (!in_array(FreshRSS_Context::$system_conf->auth_type, array('form', 'persona', 'http_auth', 'none'))) { ?>
 						<option selected="selected"></option>
 					<?php } ?>
@@ -25,7 +25,7 @@
 			<div class="group-controls">
 				<label class="checkbox" for="anon_access">
 					<input type="checkbox" name="anon_access" id="anon_access" value="1"<?php echo FreshRSS_Context::$system_conf->allow_anonymous ? ' checked="checked"' : '',
-						FreshRSS_Auth::accessNeedsAction() ? '' : ' disabled="disabled"'; ?> />
+						FreshRSS_Auth::accessNeedsAction() ? '' : ' disabled="disabled"'; ?> data-leave-validation="<?php echo FreshRSS_Context::$system_conf->allow_anonymous; ?>"/>
 					<?php echo _t('admin.auth.allow_anonymous', FreshRSS_Context::$system_conf->default_user); ?>
 				</label>
 			</div>
@@ -35,7 +35,7 @@
 			<div class="group-controls">
 				<label class="checkbox" for="anon_refresh">
 					<input type="checkbox" name="anon_refresh" id="anon_refresh" value="1"<?php echo FreshRSS_Context::$system_conf->allow_anonymous_refresh ? ' checked="checked"' : '',
-						FreshRSS_Auth::accessNeedsAction() ? '' : ' disabled="disabled"'; ?> />
+						FreshRSS_Auth::accessNeedsAction() ? '' : ' disabled="disabled"'; ?> data-leave-validation="<?php echo FreshRSS_Context::$system_conf->allow_anonymous_refresh; ?>"/>
 					<?php echo _t('admin.auth.allow_anonymous_refresh'); ?>
 				</label>
 			</div>
@@ -45,7 +45,7 @@
 			<div class="group-controls">
 				<label class="checkbox" for="unsafe_autologin">
 					<input type="checkbox" name="unsafe_autologin" id="unsafe_autologin" value="1"<?php echo FreshRSS_Context::$system_conf->unsafe_autologin_enabled ? ' checked="checked"' : '',
-						FreshRSS_Auth::accessNeedsAction() ? '' : ' disabled="disabled"'; ?> />
+						FreshRSS_Auth::accessNeedsAction() ? '' : ' disabled="disabled"'; ?> data-leave-validation="<?php echo FreshRSS_Context::$system_conf->unsafe_autologin_enabled; ?>"/>
 					<?php echo _t('admin.auth.unsafe_autologin'); ?>
 					<kbd><?php echo Minz_Url::display(array('c' => 'auth', 'a' => 'login', 'params' => array('u' => 'alice', 'p' => '1234')), 'html', true); ?></kbd>
 				</label>
@@ -58,7 +58,7 @@
 			<?php $token = FreshRSS_Context::$user_conf->token; ?>
 			<div class="group-controls">
 				<input type="text" id="token" name="token" value="<?php echo $token; ?>" placeholder="<?php echo _t('gen.short.blank_to_disable'); ?>"<?php
-					echo FreshRSS_Auth::accessNeedsAction() ? '' : ' disabled="disabled"'; ?> />
+					echo FreshRSS_Auth::accessNeedsAction() ? '' : ' disabled="disabled"'; ?> data-leave-validation="<?php echo $token; ?>"/>
 				<?php echo _i('help'); ?> <?php echo _t('admin.auth.token_help'); ?>
 				<kbd><?php echo Minz_Url::display(array('params' => array('output' => 'rss', 'token' => $token)), 'html', true); ?></kbd>
 			</div>
@@ -69,7 +69,7 @@
 			<div class="group-controls">
 				<label class="checkbox" for="api_enabled">
 					<input type="checkbox" name="api_enabled" id="api_enabled" value="1"<?php echo FreshRSS_Context::$system_conf->api_enabled ? ' checked="checked"' : '',
-						FreshRSS_Auth::accessNeedsLogin() ? '' : ' disabled="disabled"'; ?> />
+						FreshRSS_Auth::accessNeedsLogin() ? '' : ' disabled="disabled"'; ?> data-leave-validation="<?php echo FreshRSS_Context::$system_conf->api_enabled; ?>"/>
 					<?php echo _t('admin.auth.api_enabled'); ?>
 				</label>
 			</div>

+ 3 - 3
app/views/configure/archiving.phtml

@@ -10,14 +10,14 @@
 		<div class="form-group">
 			<label class="group-name" for="old_entries"><?php echo _t('conf.archiving.delete_after'); ?></label>
 			<div class="group-controls">
-				<input type="number" id="old_entries" name="old_entries" min="1" max="1200" value="<?php echo FreshRSS_Context::$user_conf->old_entries; ?>" /> <?php echo _t('gen.date.month'); ?>
+				<input type="number" id="old_entries" name="old_entries" min="1" max="1200" value="<?php echo FreshRSS_Context::$user_conf->old_entries; ?>" data-leave-validation="<?php echo FreshRSS_Context::$user_conf->old_entries; ?>"/> <?php echo _t('gen.date.month'); ?>
 				  <a class="btn confirm" href="<?php echo _url('entry', 'purge'); ?>"><?php echo _t('conf.archiving.purge_now'); ?></a>
 			</div>
 		</div>
 		<div class="form-group">
 			<label class="group-name" for="keep_history_default"><?php echo _t('conf.archiving.keep_history_by_feed'); ?></label>
 			<div class="group-controls">
-				<select class="number" name="keep_history_default" id="keep_history_default" required="required"><?php
+				<select class="number" name="keep_history_default" id="keep_history_default" required="required" data-leave-validation="<?php echo FreshRSS_Context::$user_conf->keep_history_default; ?>"><?php
 					foreach (array('' => '', 0 => '0', 10 => '10', 50 => '50', 100 => '100', 500 => '500', 1000 => '1 000', 5000 => '5 000', 10000 => '10 000', -1 => '∞') as $v => $t) {
 						echo '<option value="' . $v . (FreshRSS_Context::$user_conf->keep_history_default == $v ? '" selected="selected' : '') . '">' . $t . ' </option>';
 					}
@@ -27,7 +27,7 @@
 		<div class="form-group">
 			<label class="group-name" for="ttl_default"><?php echo _t('conf.archiving.ttl'); ?></label>
 			<div class="group-controls">
-				<select class="number" name="ttl_default" id="ttl_default" required="required"><?php
+				<select class="number" name="ttl_default" id="ttl_default" required="required" data-leave-validation="<?php echo FreshRSS_Context::$user_conf->ttl_default; ?>"><?php
 					$found = false;
 					foreach (array(1200 => '20min', 1500 => '25min', 1800 => '30min', 2700 => '45min',
 					                3600 => '1h', 5400 => '1.5h', 7200 => '2h', 10800 => '3h', 14400 => '4h', 18800 => '5h', 21600 => '6h', 25200 => '7h', 28800 => '8h',

+ 14 - 14
app/views/configure/display.phtml

@@ -9,7 +9,7 @@
 		<div class="form-group">
 			<label class="group-name" for="language"><?php echo _t('conf.display.language'); ?></label>
 			<div class="group-controls">
-				<select name="language" id="language">
+				<select name="language" id="language" data-leave-validation="<?php echo FreshRSS_Context::$user_conf->language; ?>">
 				<?php $languages = Minz_Translate::availableLanguages(); ?>
 				<?php foreach ($languages as $lang) { ?>
 				<option value="<?php echo $lang; ?>"<?php echo FreshRSS_Context::$user_conf->language === $lang ? ' selected="selected"' : ''; ?>><?php echo _t('gen.lang.' . $lang); ?></option>
@@ -24,7 +24,7 @@
 				<ul class="slides">
 					<?php $slides = count($this->themes); $i = 1; ?>
 					<?php foreach($this->themes as $theme) { ?>
-						<input type="radio" name="theme" id="img-<?php echo $i ?>" <?php if (FreshRSS_Context::$user_conf->theme === $theme['id']) {echo "checked";}?> value="<?php echo $theme['id'] ?>"/>
+						<input type="radio" name="theme" id="img-<?php echo $i ?>" <?php if (FreshRSS_Context::$user_conf->theme === $theme['id']) {echo "checked";}?> value="<?php echo $theme['id'] ?>" data-leave-validation="<?php echo (FreshRSS_Context::$user_conf->theme === $theme['id']) ? 1 : 0; ?>"/>
 						<li class="slide-container">
 							<div class="slide">
 								<img src="<?php echo Minz_Url::display('/themes/' . $theme['id'] . '/thumbs/original.png')?>"/>
@@ -53,7 +53,7 @@
 		<div class="form-group">
 			<label class="group-name" for="content_width"><?php echo _t('conf.display.width.content'); ?></label>
 			<div class="group-controls">
-				<select name="content_width" id="content_width" required="">
+				<select name="content_width" id="content_width" required="" data-leave-validation="<?php echo $width; ?>">
 					<option value="thin" <?php echo $width === 'thin'? 'selected="selected"' : ''; ?>>
 						<?php echo _t('conf.display.width.thin'); ?>
 					</option>
@@ -87,20 +87,20 @@
 				<tbody>
 					<tr>
 						<th><?php echo _t('conf.display.icon.top_line'); ?></th>
-						<td><input type="checkbox" name="topline_read" value="1"<?php echo FreshRSS_Context::$user_conf->topline_read ? ' checked="checked"' : ''; ?> /></td>
-						<td><input type="checkbox" name="topline_favorite" value="1"<?php echo FreshRSS_Context::$user_conf->topline_favorite ? ' checked="checked"' : ''; ?> /></td>
+						<td><input type="checkbox" name="topline_read" value="1"<?php echo FreshRSS_Context::$user_conf->topline_read ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->topline_read; ?>"/></td>
+						<td><input type="checkbox" name="topline_favorite" value="1"<?php echo FreshRSS_Context::$user_conf->topline_favorite ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->topline_favorite; ?>"/></td>
 						<td><input type="checkbox" disabled="disabled" /></td>
 						<td><input type="checkbox" disabled="disabled" /></td>
-						<td><input type="checkbox" name="topline_date" value="1"<?php echo FreshRSS_Context::$user_conf->topline_date ? ' checked="checked"' : ''; ?> /></td>
-						<td><input type="checkbox" name="topline_link" value="1"<?php echo FreshRSS_Context::$user_conf->topline_link ? ' checked="checked"' : ''; ?> /></td>
+						<td><input type="checkbox" name="topline_date" value="1"<?php echo FreshRSS_Context::$user_conf->topline_date ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->topline_date; ?>"/></td>
+						<td><input type="checkbox" name="topline_link" value="1"<?php echo FreshRSS_Context::$user_conf->topline_link ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->topline_link; ?>"/></td>
 					</tr><tr>
 						<th><?php echo _t('conf.display.icon.bottom_line'); ?></th>
-						<td><input type="checkbox" name="bottomline_read" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_read ? ' checked="checked"' : ''; ?> /></td>
-						<td><input type="checkbox" name="bottomline_favorite" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_favorite ? ' checked="checked"' : ''; ?> /></td>
-						<td><input type="checkbox" name="bottomline_sharing" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_sharing ? ' checked="checked"' : ''; ?> /></td>
-						<td><input type="checkbox" name="bottomline_tags" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_tags ? ' checked="checked"' : ''; ?> /></td>
-						<td><input type="checkbox" name="bottomline_date" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_date ? ' checked="checked"' : ''; ?> /></td>
-						<td><input type="checkbox" name="bottomline_link" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_link ? ' checked="checked"' : ''; ?> /></td>
+						<td><input type="checkbox" name="bottomline_read" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_read ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_read; ?>"/></td>
+						<td><input type="checkbox" name="bottomline_favorite" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_favorite ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_favorite; ?>"/></td>
+						<td><input type="checkbox" name="bottomline_sharing" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_sharing ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_sharing; ?>"/></td>
+						<td><input type="checkbox" name="bottomline_tags" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_tags ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_tags; ?>"/></td>
+						<td><input type="checkbox" name="bottomline_date" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_date ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_date; ?>"/></td>
+						<td><input type="checkbox" name="bottomline_link" value="1"<?php echo FreshRSS_Context::$user_conf->bottomline_link ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->bottomline_link; ?>"/></td>
 					</tr>
 				</tbody>
 			</table><br />
@@ -109,7 +109,7 @@
 		<div class="form-group">
 			<label class="group-name" for="posts_per_page"><?php echo _t('conf.display.notif_html5.timeout'); ?></label>
 			<div class="group-controls">
-				<input type="number" id="html5_notif_timeout" name="html5_notif_timeout" value="<?php echo FreshRSS_Context::$user_conf->html5_notif_timeout; ?>" /> <?php echo _t('conf.display.notif_html5.seconds'); ?>
+				<input type="number" id="html5_notif_timeout" name="html5_notif_timeout" value="<?php echo FreshRSS_Context::$user_conf->html5_notif_timeout; ?>" data-leave-validation="<?php echo FreshRSS_Context::$user_conf->html5_notif_timeout; ?>"/> <?php echo _t('conf.display.notif_html5.seconds'); ?>
 			</div>
 		</div>
 

+ 1 - 0
app/views/configure/queries.phtml

@@ -25,6 +25,7 @@
 					       id="queries_<?php echo $key; ?>_name"
 					       name="queries[<?php echo $key; ?>][name]"
 					       value="<?php echo $query->getName(); ?>"
+					       data-leave-validation="<?php echo $query->getName(); ?>"
 					/>
 
 					<a class="btn" href="<?php echo $query->getUrl(); ?>">

+ 17 - 17
app/views/configure/reading.phtml

@@ -9,7 +9,7 @@
 		<div class="form-group">
 			<label class="group-name" for="posts_per_page"><?php echo _t('conf.reading.articles_per_page'); ?></label>
 			<div class="group-controls">
-				<input type="number" id="posts_per_page" name="posts_per_page" value="<?php echo FreshRSS_Context::$user_conf->posts_per_page; ?>" min="5" max="50" />
+				<input type="number" id="posts_per_page" name="posts_per_page" value="<?php echo FreshRSS_Context::$user_conf->posts_per_page; ?>" min="5" max="50" data-leave-validation="<?php echo FreshRSS_Context::$user_conf->posts_per_page; ?>"/>
 				<?php echo _i('help'); ?> <?php echo _t('conf.reading.number_divided_when_reader'); ?>
 			</div>
 		</div>
@@ -17,7 +17,7 @@
 		<div class="form-group">
 			<label class="group-name" for="sort_order"><?php echo _t('conf.reading.sort'); ?></label>
 			<div class="group-controls">
-				<select name="sort_order" id="sort_order">
+				<select name="sort_order" id="sort_order" data-leave-validation="<?php echo FreshRSS_Context::$user_conf->sort_order; ?>">
 					<option value="DESC"<?php echo FreshRSS_Context::$user_conf->sort_order === 'DESC' ? ' selected="selected"' : ''; ?>><?php echo _t('conf.reading.sort.newer_first'); ?></option>
 					<option value="ASC"<?php echo FreshRSS_Context::$user_conf->sort_order === 'ASC' ? ' selected="selected"' : ''; ?>><?php echo _t('conf.reading.sort.older_first'); ?></option>
 				</select>
@@ -27,7 +27,7 @@
 		<div class="form-group">
 			<label class="group-name" for="view_mode"><?php echo _t('conf.reading.view.default'); ?></label>
 			<div class="group-controls">
-				<select name="view_mode" id="view_mode">
+				<select name="view_mode" id="view_mode" data-leave-validation="<?php echo FreshRSS_Context::$user_conf->view_mode; ?>">
 					<option value="normal"<?php echo FreshRSS_Context::$user_conf->view_mode === 'normal' ? ' selected="selected"' : ''; ?>><?php echo _t('conf.reading.view.normal'); ?></option>
 					<option value="reader"<?php echo FreshRSS_Context::$user_conf->view_mode === 'reader' ? ' selected="selected"' : ''; ?>><?php echo _t('conf.reading.view.reader'); ?></option>
 					<option value="global"<?php echo FreshRSS_Context::$user_conf->view_mode === 'global' ? ' selected="selected"' : ''; ?>><?php echo _t('conf.reading.view.global'); ?></option>
@@ -38,7 +38,7 @@
 		<div class="form-group">
 			<label class="group-name" for="view_mode"><?php echo _t('conf.reading.show'); ?></label>
 			<div class="group-controls">
-				<select name="default_view" id="default_view">
+				<select name="default_view" id="default_view" data-leave-validation="<?php echo FreshRSS_Context::$user_conf->default_view; ?>">
 					<option value="adaptive"<?php echo FreshRSS_Context::$user_conf->default_view === 'adaptive' ? ' selected="selected"' : ''; ?>><?php echo _t('conf.reading.show.adaptive'); ?></option>
 					<option value="all"<?php echo FreshRSS_Context::$user_conf->default_view === 'all' ? ' selected="selected"' : ''; ?>><?php echo _t('conf.reading.show.all_articles'); ?></option>
 					<option value="unread"<?php echo FreshRSS_Context::$user_conf->default_view === 'unread' ? ' selected="selected"' : ''; ?>><?php echo _t('conf.reading.show.unread'); ?></option>
@@ -49,7 +49,7 @@
 		<div class="form-group">
 			<div class="group-controls">
 				<label class="checkbox" for="hide_read_feeds">
-					<input type="checkbox" name="hide_read_feeds" id="hide_read_feeds" value="1"<?php echo FreshRSS_Context::$user_conf->hide_read_feeds ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="hide_read_feeds" id="hide_read_feeds" value="1"<?php echo FreshRSS_Context::$user_conf->hide_read_feeds ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->hide_read_feeds; ?>"/>
 					<?php echo _t('conf.reading.hide_read_feeds'); ?>
 				</label>
 			</div>
@@ -58,7 +58,7 @@
 		<div class="form-group">
 			<div class="group-controls">
 				<label class="checkbox" for="display_posts">
-					<input type="checkbox" name="display_posts" id="display_posts" value="1"<?php echo FreshRSS_Context::$user_conf->display_posts ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="display_posts" id="display_posts" value="1"<?php echo FreshRSS_Context::$user_conf->display_posts ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->display_posts; ?>"/>
 					<?php echo _t('conf.reading.display_articles_unfolded'); ?>
 					<noscript> — <strong><?php echo _t('gen.js.should_be_activated'); ?></strong></noscript>
 				</label>
@@ -68,7 +68,7 @@
 		<div class="form-group">
 			<div class="group-controls">
 				<label class="checkbox" for="display_categories">
-					<input type="checkbox" name="display_categories" id="display_categories" value="1"<?php echo FreshRSS_Context::$user_conf->display_categories ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="display_categories" id="display_categories" value="1"<?php echo FreshRSS_Context::$user_conf->display_categories ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->display_categories; ?>"/>
 					<?php echo _t('conf.reading.display_categories_unfolded'); ?>
 					<noscript> — <strong><?php echo _t('gen.js.should_be_activated'); ?></strong></noscript>
 				</label>
@@ -78,7 +78,7 @@
 		<div class="form-group">
 			<div class="group-controls">
 				<label class="checkbox" for="sticky_post">
-					<input type="checkbox" name="sticky_post" id="sticky_post" value="1"<?php echo FreshRSS_Context::$user_conf->sticky_post ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="sticky_post" id="sticky_post" value="1"<?php echo FreshRSS_Context::$user_conf->sticky_post ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->sticky_post; ?>"/>
 					<?php echo _t('conf.reading.sticky_post'); ?>
 					<noscript> — <strong><?php echo _t('gen.js.should_be_activated'); ?></strong></noscript>
 				</label>
@@ -88,7 +88,7 @@
 		<div class="form-group">
 			<div class="group-controls">
 				<label class="checkbox" for="auto_load_more">
-					<input type="checkbox" name="auto_load_more" id="auto_load_more" value="1"<?php echo FreshRSS_Context::$user_conf->auto_load_more ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="auto_load_more" id="auto_load_more" value="1"<?php echo FreshRSS_Context::$user_conf->auto_load_more ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->auto_load_more; ?>"/>
 					<?php echo _t('conf.reading.auto_load_more'); ?>
 					<noscript> — <strong><?php echo _t('gen.js.should_be_activated'); ?></strong></noscript>
 				</label>
@@ -98,7 +98,7 @@
 		<div class="form-group">
 			<div class="group-controls">
 				<label class="checkbox" for="lazyload">
-					<input type="checkbox" name="lazyload" id="lazyload" value="1"<?php echo FreshRSS_Context::$user_conf->lazyload ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="lazyload" id="lazyload" value="1"<?php echo FreshRSS_Context::$user_conf->lazyload ? ' checked="checked"' : ''; ?>  data-leave-validation="<?php echo FreshRSS_Context::$user_conf->lazyload; ?>"/>
 					<?php echo _t('conf.reading.img_with_lazyload'); ?>
 					<noscript> — <strong><?php echo _t('gen.js.should_be_activated'); ?></strong></noscript>
 				</label>
@@ -108,7 +108,7 @@
 		<div class="form-group">
 			<div class="group-controls">
 				<label class="checkbox" for="reading_confirm">
-					<input type="checkbox" name="reading_confirm" id="reading_confirm" value="1"<?php echo FreshRSS_Context::$user_conf->reading_confirm ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="reading_confirm" id="reading_confirm" value="1"<?php echo FreshRSS_Context::$user_conf->reading_confirm ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->reading_confirm; ?>"/>
 					<?php echo _t('conf.reading.confirm_enabled'); ?>
 					<noscript> — <strong><?php echo _t('gen.js.should_be_activated'); ?></strong></noscript>
 				</label>
@@ -118,7 +118,7 @@
 		<div class="form-group">
 			<div class="group-controls">
 				<label class="checkbox" for="auto_remove_article">
-					<input type="checkbox" name="auto_remove_article" id="auto_remove_article" value="1"<?php echo FreshRSS_Context::$user_conf->auto_remove_article ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="auto_remove_article" id="auto_remove_article" value="1"<?php echo FreshRSS_Context::$user_conf->auto_remove_article ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->auto_remove_article; ?>"/>
 					<?php echo _t('conf.reading.auto_remove_article'); ?>
 					<noscript> — <strong><?php echo _t('gen.js.should_be_activated'); ?></strong></noscript>
 				</label>
@@ -129,19 +129,19 @@
 			<label class="group-name"><?php echo _t('conf.reading.read.when'); ?></label>
 			<div class="group-controls">
 				<label class="checkbox" for="check_open_article">
-					<input type="checkbox" name="mark_open_article" id="check_open_article" value="1"<?php echo FreshRSS_Context::$user_conf->mark_when['article'] ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="mark_open_article" id="check_open_article" value="1"<?php echo FreshRSS_Context::$user_conf->mark_when['article'] ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->mark_when['article']; ?>"/>
 					<?php echo _t('conf.reading.read.article_viewed'); ?>
 				</label>
 				<label class="checkbox" for="check_open_site">
-					<input type="checkbox" name="mark_open_site" id="check_open_site" value="1"<?php echo FreshRSS_Context::$user_conf->mark_when['site'] ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="mark_open_site" id="check_open_site" value="1"<?php echo FreshRSS_Context::$user_conf->mark_when['site'] ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->mark_when['site']; ?>"/>
 					<?php echo _t('conf.reading.read.article_open_on_website'); ?>
 				</label>
 				<label class="checkbox" for="check_scroll">
-					<input type="checkbox" name="mark_scroll" id="check_scroll" value="1"<?php echo FreshRSS_Context::$user_conf->mark_when['scroll'] ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="mark_scroll" id="check_scroll" value="1"<?php echo FreshRSS_Context::$user_conf->mark_when['scroll'] ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->mark_when['scroll']; ?>"/>
 					<?php echo _t('conf.reading.read.scroll'); ?>
 				</label>
 				<label class="checkbox" for="check_reception">
-					<input type="checkbox" name="mark_upon_reception" id="check_reception" value="1"<?php echo FreshRSS_Context::$user_conf->mark_when['reception'] ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="mark_upon_reception" id="check_reception" value="1"<?php echo FreshRSS_Context::$user_conf->mark_when['reception'] ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->mark_when['reception']; ?>"/>
 					<?php echo _t('conf.reading.read.upon_reception'); ?>
 				</label>
 			</div>
@@ -151,7 +151,7 @@
 			<label class="group-name"><?php echo _t('conf.reading.after_onread'); ?></label>
 			<div class="group-controls">
 				<label class="checkbox" for="onread_jump_next">
-					<input type="checkbox" name="onread_jump_next" id="onread_jump_next" value="1"<?php echo FreshRSS_Context::$user_conf->onread_jump_next ? ' checked="checked"' : ''; ?> />
+					<input type="checkbox" name="onread_jump_next" id="onread_jump_next" value="1"<?php echo FreshRSS_Context::$user_conf->onread_jump_next ? ' checked="checked"' : ''; ?> data-leave-validation="<?php echo FreshRSS_Context::$user_conf->onread_jump_next; ?>"/>
 					<?php echo _t('conf.reading.jump_next'); ?>
 				</label>
 			</div>

+ 2 - 2
app/views/configure/sharing.phtml

@@ -28,9 +28,9 @@
 				<div class="group-controls">
 					<input type='hidden' id='share_<?php echo $key; ?>_type' name="share[<?php echo $key; ?>][type]" value='<?php echo $share->type(); ?>' />
 					<div class="stick">
-						<input type="text" id="share_<?php echo $key; ?>_name" name="share[<?php echo $key; ?>][name]" class="extend" value="<?php echo $share->name(); ?>" placeholder="<?php echo _t('conf.sharing.share_name'); ?>" size="64" />
+						<input type="text" id="share_<?php echo $key; ?>_name" name="share[<?php echo $key; ?>][name]" class="extend" value="<?php echo $share->name(); ?>" placeholder="<?php echo _t('conf.sharing.share_name'); ?>" size="64" data-leave-validation="<?php echo $share->name(); ?>"/>
 					<?php if ($share->formType() === 'advanced') { ?>
-						<input type="url" id="share_<?php echo $key; ?>_url" name="share[<?php echo $key; ?>][url]" class="extend" value="<?php echo $share->baseUrl(); ?>" placeholder="<?php echo _t('conf.sharing.share_url'); ?>" size="64" />
+						<input type="url" id="share_<?php echo $key; ?>_url" name="share[<?php echo $key; ?>][url]" class="extend" value="<?php echo $share->baseUrl(); ?>" placeholder="<?php echo _t('conf.sharing.share_url'); ?>" size="64" data-leave-validation="<?php echo $share->baseUrl(); ?>"/>
 					<?php } else { ?>
 						<input type="url" id="share_<?php echo $key; ?>_url" name="share[<?php echo $key; ?>][url]" class="extend" value="<?php echo $share->baseUrl(); ?>" placeholder="<?php echo _t('gen.short.not_applicable'); ?>" size="64" disabled/>
 					<?php } ?>

+ 14 - 14
app/views/configure/shortcut.phtml

@@ -23,28 +23,28 @@
 		<div class="form-group">
 			<label class="group-name" for="next_entry"><?php echo _t('conf.shortcut.next_article'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="next_entry" name="shortcuts[next_entry]" list="keys" value="<?php echo $s['next_entry']; ?>" />
+				<input type="text" id="next_entry" name="shortcuts[next_entry]" list="keys" value="<?php echo $s['next_entry']; ?>" data-leave-validation="<?php echo $s['next_entry']; ?>"/>
 			</div>
 		</div>
 
 		<div class="form-group">
 			<label class="group-name" for="prev_entry"><?php echo _t('conf.shortcut.previous_article'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="prev_entry" name="shortcuts[prev_entry]" list="keys" value="<?php echo $s['prev_entry']; ?>" />
+				<input type="text" id="prev_entry" name="shortcuts[prev_entry]" list="keys" value="<?php echo $s['prev_entry']; ?>" data-leave-validation="<?php echo $s['prev_entry']; ?>"/>
 			</div>
 		</div>
 
 		<div class="form-group">
 			<label class="group-name" for="first_entry"><?php echo _t('conf.shortcut.first_article'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="first_entry" name="shortcuts[first_entry]" list="keys" value="<?php echo $s['first_entry']; ?>" />
+				<input type="text" id="first_entry" name="shortcuts[first_entry]" list="keys" value="<?php echo $s['first_entry']; ?>" data-leave-validation="<?php echo $s['first_entry']; ?>"/>
 			</div>
 		</div>
 
 		<div class="form-group">
 			<label class="group-name" for="last_entry"><?php echo _t('conf.shortcut.last_article'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="last_entry" name="shortcuts[last_entry]" list="keys" value="<?php echo $s['last_entry']; ?>" />
+				<input type="text" id="last_entry" name="shortcuts[last_entry]" list="keys" value="<?php echo $s['last_entry']; ?>" data-leave-validation="<?php echo $s['last_entry']; ?>"/>
 			</div>
 		</div>
 
@@ -53,7 +53,7 @@
 		<div class="form-group">
 			<label class="group-name" for="mark_read"><?php echo _t('conf.shortcut.mark_read'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="mark_read" name="shortcuts[mark_read]" list="keys" value="<?php echo $s['mark_read']; ?>" />
+				<input type="text" id="mark_read" name="shortcuts[mark_read]" list="keys" value="<?php echo $s['mark_read']; ?>" data-leave-validation="<?php echo $s['mark_read']; ?>"/>
 				<?php echo _t('conf.shortcut.shift_for_all_read'); ?>
 			</div>
 		</div>
@@ -61,21 +61,21 @@
 		<div class="form-group">
 			<label class="group-name" for="mark_favorite"><?php echo _t('conf.shortcut.mark_favorite'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="mark_favorite" name="shortcuts[mark_favorite]" list="keys" value="<?php echo $s['mark_favorite']; ?>" />
+				<input type="text" id="mark_favorite" name="shortcuts[mark_favorite]" list="keys" value="<?php echo $s['mark_favorite']; ?>" data-leave-validation="<?php echo $s['mark_favorite']; ?>"/>
 			</div>
 		</div>
 
 		<div class="form-group">
 			<label class="group-name" for="go_website"><?php echo _t('conf.shortcut.see_on_website'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="go_website" name="shortcuts[go_website]" list="keys" value="<?php echo $s['go_website']; ?>" />
+				<input type="text" id="go_website" name="shortcuts[go_website]" list="keys" value="<?php echo $s['go_website']; ?>" data-leave-validation="<?php echo $s['go_website']; ?>"/>
 			</div>
 		</div>
 
 		<div class="form-group">
 			<label class="group-name" for="auto_share_shortcut"><?php echo _t('conf.shortcut.auto_share'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="auto_share_shortcut" name="shortcuts[auto_share]" list="keys" value="<?php echo $s['auto_share']; ?>" />
+				<input type="text" id="auto_share_shortcut" name="shortcuts[auto_share]" list="keys" value="<?php echo $s['auto_share']; ?>" data-leave-validation="<?php echo $s['auto_share']; ?>"/>
 				<?php echo _t('conf.shortcut.auto_share_help'); ?>
 			</div>
 		</div>
@@ -83,7 +83,7 @@
 		<div class="form-group">
 			<label class="group-name" for="collapse_entry"><?php echo _t('conf.shortcut.collapse_article'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="collapse_entry" name="shortcuts[collapse_entry]" list="keys" value="<?php echo $s['collapse_entry']; ?>" />
+				<input type="text" id="collapse_entry" name="shortcuts[collapse_entry]" list="keys" value="<?php echo $s['collapse_entry']; ?>" data-leave-validation="<?php echo $s['collapse_entry']; ?>"/>
 			</div>
 		</div>
 
@@ -92,21 +92,21 @@
 		<div class="form-group">
 			<label class="group-name" for="load_more_shortcut"><?php echo _t('conf.shortcut.load_more'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="load_more_shortcut" name="shortcuts[load_more]" list="keys" value="<?php echo $s['load_more']; ?>" />
+				<input type="text" id="load_more_shortcut" name="shortcuts[load_more]" list="keys" value="<?php echo $s['load_more']; ?>" data-leave-validation="<?php echo $s['load_more']; ?>"/>
 			</div>
 		</div>
 
 		<div class="form-group">
 			<label class="group-name" for="focus_search_shortcut"><?php echo _t('conf.shortcut.focus_search'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="focus_search_shortcut" name="shortcuts[focus_search]" list="keys" value="<?php echo $s['focus_search']; ?>" />
+				<input type="text" id="focus_search_shortcut" name="shortcuts[focus_search]" list="keys" value="<?php echo $s['focus_search']; ?>" data-leave-validation="<?php echo $s['focus_search']; ?>"/>
 			</div>
 		</div>
 
 		<div class="form-group">
 			<label class="group-name" for="user_filter_shortcut"><?php echo _t('conf.shortcut.user_filter'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="user_filter_shortcut" name="shortcuts[user_filter]" list="keys" value="<?php echo $s['user_filter']; ?>" />
+				<input type="text" id="user_filter_shortcut" name="shortcuts[user_filter]" list="keys" value="<?php echo $s['user_filter']; ?>" data-leave-validation="<?php echo $s['user_filter']; ?>"/>
 				<?php echo _t('conf.shortcut.user_filter_help'); ?>
 			</div>
 		</div>
@@ -114,14 +114,14 @@
 		<div class="form-group">
 			<label class="group-name" for="close_dropdown_shortcut"><?php echo _t('conf.shortcut.close_dropdown'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="close_dropdown" name="shortcuts[close_dropdown]" list="keys" value="<?php echo $s['close_dropdown']; ?>" />
+				<input type="text" id="close_dropdown" name="shortcuts[close_dropdown]" list="keys" value="<?php echo $s['close_dropdown']; ?>" data-leave-validation="<?php echo $s['close_dropdown']; ?>"/>
 			</div>
 		</div>
 
 		<div class="form-group">
 			<label class="group-name" for="help_shortcut"><?php echo _t('conf.shortcut.help'); ?></label>
 			<div class="group-controls">
-				<input type="text" id="help_shortcut" name="shortcuts[help]" list="keys" value="<?php echo $s['help']; ?>" />
+				<input type="text" id="help_shortcut" name="shortcuts[help]" list="keys" value="<?php echo $s['help']; ?>" data-leave-validation="<?php echo $s['help']; ?>"/>
 			</div>
 		</div>
 

+ 28 - 0
p/scripts/main.js

@@ -1229,6 +1229,33 @@ function init_slider_observers() {
 	});
 }
 
+function init_configuration_alert() {
+	$(window).on('beforeunload', function(e){
+		if (e.originalEvent.explicitOriginalTarget.type === 'submit') {
+			// we don't want an alert when submitting the form with the submit button
+			return;
+		}
+		if ($(e.originalEvent.explicitOriginalTarget).attr('data-leave-validation') !== undefined) {
+			// we don't want an alert when submitting the form by pressing the enter key
+			return;
+		}
+		var fields = $("[data-leave-validation]");
+		for (var i = 0; i < fields.length; i++) {
+			if ($(fields[i]).attr('type') === 'checkbox' || $(fields[i]).attr('type') === 'radio') {
+				// The use of != is done on purpose to check boolean against integer
+				if ($(fields[i]).is(':checked') != $(fields[i]).attr('data-leave-validation')) {
+					return false;
+				}
+			} else {
+				if ($(fields[i]).attr('data-leave-validation') !== $(fields[i]).val()) {
+					return false;
+				}
+			}
+		}
+		return;
+	});
+}
+
 function init_all() {
 	if (!(window.$ && window.context)) {
 		if (window.console) {
@@ -1260,6 +1287,7 @@ function init_all() {
 		init_password_observers();
 		init_stats_observers();
 		init_slider_observers();
+		init_configuration_alert();
 	}
 
 	if (window.console) {