Browse Source

Merge pull request #117 from weseek/master

release v1.2.12
Yuki Takei 8 years ago
parent
commit
9d791c8e5d

+ 5 - 0
CHANGES.md

@@ -1,6 +1,11 @@
 CHANGES
 ========
 
+## 1.2.12
+
+* Improvement: Enabled to switch whether to push states with History API when tabs changes 
+* Fix: Layout of the Not Found page
+
 ## 1.2.11
 
 * Improvement: Enabled to open editing form from affix header

+ 2 - 1
lib/form/admin/customfeatures.js

@@ -4,6 +4,7 @@ var form = require('express-form')
   , field = form.field;
 
 module.exports = form(
-  field('settingForm[customize:isEnabledTimeline]').trim().toBooleanStrict()
+  field('settingForm[customize:isEnabledTimeline]').trim().toBooleanStrict(),
+  field('settingForm[customize:isSavedStatesOfTabChanges]').trim().toBooleanStrict()
 );
 

+ 38 - 29
lib/models/config.js

@@ -21,7 +21,7 @@ module.exports = function(crowi) {
   });
 
   /**
-   * default values when crowi-plus installed
+   * default values when crowi-plus is cleanly installed
    */
   function getArrayForInstalling() {
     let config = getDefaultCrowiConfigs();
@@ -29,6 +29,7 @@ module.exports = function(crowi) {
     // overwrite
     config['customize:behavior'] = 'crowi-plus';
     config['customize:layout'] = 'crowi-plus';
+    config['customize:isSavedStatesOfTabChanges'] = false;
 
     return config;
   }
@@ -70,6 +71,7 @@ module.exports = function(crowi) {
       'customize:behavior' : 'crowi',
       'customize:layout' : 'crowi',
       'customize:isEnabledTimeline' : true,
+      'customize:isSavedStatesOfTabChanges' : true,
     };
   }
 
@@ -80,6 +82,15 @@ module.exports = function(crowi) {
     }
   }
 
+  function getValueForCrowiNS(config, key) {
+    // return the default value if undefined
+    if (undefined === config.crowi || undefined === config.crowi[key]) {
+      return getDefaultCrowiConfigs()[key];
+    }
+
+    return config.crowi[key];
+  }
+
   configSchema.statics.getRestrictGuestModeLabels = function()
   {
     var labels = {};
@@ -248,38 +259,32 @@ module.exports = function(crowi) {
 
   configSchema.statics.isEnabledPlugins = function(config)
   {
-    var defaultValue = getDefaultCrowiConfigs()['plugin:isEnabledPlugins'];
-
-    // return defaultValue if undefined
-    if (undefined === config.crowi || undefined === config.crowi['plugin:isEnabledPlugins']) {
-      return defaultValue;
-    }
-
-    return config.crowi['plugin:isEnabledPlugins'];
+    const key = 'plugin:isEnabledPlugins';
+    return getValueForCrowiNS(config, key);
   };
 
   configSchema.statics.isEnabledLinebreaks = function(config)
   {
-    var defaultValue = getDefaultMarkdownConfigs()['markdown:isEnabledLinebreaks'];
+    const key = 'markdown:isEnabledLinebreaks';
 
-    // return defaultValue if undefined
-    if (undefined === config.markdown || undefined === config.markdown['markdown:isEnabledLinebreaks']) {
-      return defaultValue;
+    // return default value if undefined
+    if (undefined === config.markdown || undefined === config.markdown[key]) {
+      return getDefaultMarkdownConfigs[key];
     }
 
-    return config.markdown['markdown:isEnabledLinebreaks'];
+    return config.markdown[key];
   };
 
   configSchema.statics.isEnabledLinebreaksInComments = function(config)
   {
-    var defaultValue = getDefaultMarkdownConfigs()['markdown:isEnabledLinebreaksInComments'];
+    const key = 'markdown:isEnabledLinebreaksInComments';
 
-    // return defaultValue if undefined
-    if (undefined === config.markdown || undefined === config.markdown['markdown:isEnabledLinebreaksInComments']) {
-      return defaultValue;
+    // return default value if undefined
+    if (undefined === config.markdown || undefined === config.markdown[key]) {
+      return getDefaultMarkdownConfigs[key];
     }
 
-    return config.markdown['markdown:isEnabledLinebreaksInComments'];
+    return config.markdown[key];
   };
 
   /**
@@ -287,7 +292,8 @@ module.exports = function(crowi) {
    */
   configSchema.statics.generateUglifiedCustomCss = function(config)
   {
-    var rawCss = config.crowi['customize:css'] || getDefaultCrowiConfigs()['customize:css'];
+    const key = 'customize:css';
+    const rawCss = getValueForCrowiNS(config, key);
     this.uglifiedCustomCss = uglifycss.processString(rawCss);
   }
 
@@ -298,24 +304,26 @@ module.exports = function(crowi) {
 
   configSchema.statics.behaviorType = function(config)
   {
-    return config.crowi['customize:behavior'] || 'crowi';
+    const key = 'customize:behavior';
+    return getValueForCrowiNS(config, key);
   }
 
   configSchema.statics.layoutType = function(config)
   {
-    return config.crowi['customize:layout'] || 'crowi';
+    const key = 'customize:layout';
+    return getValueForCrowiNS(config, key);
   }
 
   configSchema.statics.isEnabledTimeline = function(config)
   {
-    var defaultValue = getDefaultCrowiConfigs()['customize:isEnabledTimeline'];
-
-    // return defaultValue if undefined
-    if (undefined === config.crowi || undefined === config.crowi['customize:isEnabledTimeline']) {
-      return defaultValue;
-    }
+    const key = 'customize:isEnabledTimeline';
+    return getValueForCrowiNS(config, key);
+  };
 
-    return config.crowi['customize:isEnabledTimeline'];
+  configSchema.statics.isSavedStatesOfTabChanges = function(config)
+  {
+    const key = 'customize:isSavedStatesOfTabChanges';
+    return getValueForCrowiNS(config, key);
   };
 
   configSchema.statics.fileUploadEnabled = function(config)
@@ -371,6 +379,7 @@ module.exports = function(crowi) {
       },
       behaviorType: Config.behaviorType(config),
       layoutType: Config.layoutType(config),
+      isSavedStatesOfTabChanges: Config.isSavedStatesOfTabChanges(config),
       env: {
         PLANTUML_URI: env.PLANTUML_URI || null,
         MATHJAX: env.MATHJAX || null,

+ 1 - 1
lib/routes/page.js

@@ -243,7 +243,7 @@ module.exports = function(crowi, app) {
     }).catch(function(err) {
       // page not exists
       // change template
-      pageTeamplate = 'crowi-plus/new_page';
+      pageTeamplate = 'customlayout-selector/not_found';
     }).then(function() {
       return Page.findListByStartWith(path, req.user, queryOptions)
         .then(function(pageList) {

+ 26 - 3
lib/views/admin/customize.html

@@ -150,7 +150,7 @@
         <p class="well">機能の有効/無効を選択できます。</p>
 
         <div class="form-group">
-          <label for="settingForm[customize:isEnabledTimeline]" class="col-xs-3 control-label">タイムライン表示機能</label>
+          <label for="settingForm[customize:isEnabledTimeline]" class="col-xs-3 control-label">タイムライン機能</label>
           <div class="col-xs-9">
             <div class="btn-group btn-toggle" data-toggle="buttons">
               <label class="btn btn-default {% if settingForm['customize:isEnabledTimeline'] %}active{% endif %}" data-active-class="primary">
@@ -164,11 +164,34 @@
             </div>
 
             <p class="help-block">
-              無効化することで、リストページの表示を高速化できます。<br>
-              配下ページが多い場合に効果があります。
+              配下ページのタイムラインを表示できます。
+            </p>
+            <p class="help-block">
+              配下ページが多い場合はページロード時のパフォーマンスが落ちます。<br>
+              無効化することでリストページの表示を高速化できます。
             </p>
           </div>
+        </div>
 
+        <div class="form-group">
+          <label for="settingForm[customize:isSavedStatesOfTabChanges]" class="col-xs-3 control-label">タブ変更をブラウザ履歴に保存</label>
+          <div class="col-xs-9">
+            <div class="btn-group btn-toggle" data-toggle="buttons">
+              <label class="btn btn-default {% if settingForm['customize:isSavedStatesOfTabChanges'] %}active{% endif %}" data-active-class="primary">
+                <input name="settingForm[customize:isSavedStatesOfTabChanges]" value="true" type="radio"
+                    {% if true === settingForm['customize:isSavedStatesOfTabChanges'] %}checked{% endif %}> 有効
+              </label>
+              <label class="btn btn-default {% if !settingForm['customize:isSavedStatesOfTabChanges'] %}active{% endif %}" data-active-class="primary">
+                <input name="settingForm[customize:isSavedStatesOfTabChanges]" value="false" type="radio"
+                    {% if !settingForm['customize:isSavedStatesOfTabChanges'] %}checked{% endif %}> 無効
+              </label>
+            </div>
+
+            <p class="help-block">
+              編集タブやヒストリータブ等の切り替えをブラウザ履歴に保存し、ブラウザバック操作の対象にします。<br>
+              無効化することで、ページ遷移のみをブラウザバック操作の対象にすることができます。
+            </p>
+          </div>
         </div>
 
         <div class="form-group">

+ 55 - 0
lib/views/crowi-plus/base/not_found_nosidebar.html

@@ -0,0 +1,55 @@
+{% extends '../../not_found.html' %}
+
+
+{% block layout_sidebar %}
+{% endblock %}
+
+
+{% block layout_main %}
+<div id="main" class="main col-md-12 {% if page %}{{ css.grant(page) }}{% endif %} {% block main_css_class %}{% endblock %}">
+  {% if page && page.grant != 1 %}
+  <p class="page-grant">
+    <i class="fa fa-lock"></i> {{ consts.pageGrants[page.grant] }} ({{ t('Browsing of this page is restricted') }})
+  </p>
+  {% endif %}
+  {% if page && page.grant == 2 %}
+  <p class="alert alert-info">
+    {{ t('Shareable Link') }}
+    <input type="text" class="copy-link form-control" value="{{ baseUrl }}/{{ page._id.toString() }}" readonly>
+  </p>
+  {% endif %}
+  <article>
+    {% block content_head %}
+      {% parent %}
+    {% endblock %}
+
+    {% block content_main_before %}
+    {% endblock %}
+
+    {% block content_main %}
+      {% parent %}
+    {% endblock content_main %}
+
+    {% block content_main_after %}
+    {% endblock %}
+
+    {% block content_footer %}
+      {% parent %}
+    {% endblock %}
+  </article>
+</div>
+
+{% endblock %} {# layout_main #}
+
+
+{% block footer %}
+  {% parent %}
+  <div class="system-version">
+    <span>
+      <a href="https://github.com/weseek/crowi-plus">crowi-plus</a> {{ crowiVersion() }}
+    </span>
+    <span>
+      <a href="" data-target="#help-modal" data-toggle="modal"><i class="fa fa-question-circle"></i> {{ t('Help') }}</a>
+    </span>
+  </div>
+{% endblock %}

+ 0 - 123
lib/views/crowi-plus/new_page.html

@@ -1,123 +0,0 @@
-{% extends 'base/page_nosidebar.html' %}
-
-{% block main_css_class %}
-  main-crowi-plus-customized
-  {% parent %}
-{% endblock %}
-
-{% block content_head %}
-
-  {% block content_head_before %}
-  {% endblock %}
-
-  <div class="header-wrap">
-    <header id="page-header">
-      <p class="stopper"><a href="#" data-affix-disable="#page-header"><i class="fa fa-chevron-up"></i></a></p>
-
-      <div class="flex-title-line">
-        <div>
-          <h1 class="title flex-item-title" id="revision-path"></h1>
-          <div id="revision-url" class="url-line"></div>
-        </div>
-      </div>
-
-    </header>
-  </div>
-
-  {% block content_head_after %}
-  {% endblock %}
-
-{% endblock %} {# /content_head #}
-
-{% block content_main %}
-  <div class="container-fluid">
-    <div class="row">
-
-      <div class="col-lg-10 col-md-9">
-
-        {% block content_main_before %}
-        <h2 class="text-muted">
-          <i class="fa fa-info-circle" aria-hidden="true"></i>
-          Page is not found
-        </h2>
-        {% endblock %}
-
-
-
-        <div id="content-main" class="content-main content-main-new-page page-list"
-          data-path="{{ path }}"
-          data-path-shortname="{{ path|path2name }}"
-          data-page-id="{% if page %}{{ page._id.toString() }}{% endif %}"
-          data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
-          data-current-username="{% if user %}{{ user.username }}{% endif %}"
-          data-page-revision-id="{% if revision %}{{ revision._id.toString() }}{% endif %}"
-          data-page-revision-created="{% if revision %}{{ revision.createdAt|datetz('U') }}{% endif %}"
-          data-page-is-seen="{% if page and page.isSeenUser(user) %}1{% else %}0{% endif %}"
-          data-linebreaks-enabled="{{ isEnabledLinebreaks() }}"
-          data-csrftoken="{{ csrf() }}"
-          >
-
-          <ul class="nav nav-tabs hidden-print">
-            <li class="active"><a href="#revision-body" data-toggle="tab">{{ t('List View') }}</a></li>
-
-            <li>
-              <a {% if user %}href="#edit-form" data-toggle="tab"{% endif %} class="edit-button {% if not user %}edit-button-disabled{% endif %}">
-                <i class="fa fa-pencil-square-o"></i> {{ t('Create') }}
-              </a>
-            </li>
-
-            {% if user %}
-            <li class="dropdown pull-right">
-              <a href="#" onclick="history.back();"><i class="fa fa-times"></i> {{ t('Cancel') }}</a>
-            </li>
-            {% endif %}
-          </ul>
-
-          <div class="tab-content wiki-content">
-            {% if req.query.renamed %}
-            <div class="alert alert-info alert-moved">
-              <span>
-                <strong>{{ t('Moved') }}: </strong> {{ t('page_page.notice.moved', req.query.renamed) }}
-              </span>
-            </div>
-            {% endif %}
-            {% if req.query.unlinked %}
-            <div class="alert alert-info">
-              <strong>{{ t('Unlinked') }}: </strong> {{ t('page_page.notice.unlinked') }}
-            </div>
-            {% endif %}
-
-            {# list view #}
-            <div class="active tab-pane page-list-container" id="revision-body">
-              {% if pages.length == 0 %}
-                There are no pages under <strong>{{ path }}</strong>.
-              {% endif  %}
-
-              {% include '../widget/page_list.html' with { pages: pages, pager: pager, viewConfig: viewConfig } %}
-            </div>
-
-            {# edit view #}
-            <div class="edit-form tab-pane {% if req.body.pageForm %}active{% endif %}" id="edit-form">
-              {% include '../_form.html' %}
-            </div>
-
-          </div>
-        </div>
-
-        {% block content_main_after %}
-        {% endblock %}
-
-
-
-      </div> {# /.col- #}
-
-    </div>
-  </div>
-
-{% endblock %}
-
-{% block content_main_after %}
-{% endblock %}
-
-{% block content_footer %}
-{% endblock %}

+ 34 - 0
lib/views/crowi-plus/not_found.html

@@ -0,0 +1,34 @@
+{% extends 'base/not_found_nosidebar.html' %}
+
+{% block main_css_class %}
+  main-crowi-plus-customized
+  {% parent %}
+{% endblock %}
+
+{% block content_head %}
+
+  {% block content_head_before %}
+  {% endblock %}
+
+  {% include 'widget/header.html' %}
+
+  {% block content_head_after %}
+  {% endblock %}
+
+{% endblock %} {# /content_head #}
+
+
+{% block content_main %}
+  <div class="container-fluid">
+    <div class="row">
+
+      <div class="col-lg-10 col-md-9">
+
+        {% parent %}
+
+      </div> {# /.col- #}
+
+    </div>
+
+  </div>
+{% endblock %}

+ 1 - 1
lib/views/crowi-plus/widget/header.html

@@ -53,7 +53,7 @@
       </ul>
       {% endif %}
 
-      {% if not page and not isUserPageList(path) and !isTrashPage() %}
+      {% if not page and ('crowi' === behaviorType()) and not isUserPageList(path) and !isTrashPage() %}
       <div class="portal-form-button">
         <button class="btn btn-primary" id="create-portal-button" {% if not user %}disabled{% endif %}>Create Portal</button>
         <p class="help-block"><a href="#" data-target="#help-portal" data-toggle="modal"><i class="fa fa-question-circle"></i> What is Portal?</a></p>

+ 5 - 0
lib/views/customlayout-selector/not_found.html

@@ -0,0 +1,5 @@
+{% if 'crowi-plus' === layoutType() %}
+  {% include '../crowi-plus/not_found.html' %}
+{% else %}
+  {% include '../not_found.html' %}
+{% endif %}

+ 102 - 0
lib/views/not_found.html

@@ -0,0 +1,102 @@
+{% extends 'layout/2column.html' %}
+
+{% block content_head %}
+
+  {% block content_head_before %}
+  {% endblock %}
+
+  <div class="header-wrap">
+    <header id="page-header">
+      <p class="stopper"><a href="#" data-affix-disable="#page-header"><i class="fa fa-chevron-up"></i></a></p>
+
+      <div class="flex-title-line">
+        <div>
+          <h1 class="title flex-item-title" id="revision-path"></h1>
+          <div id="revision-url" class="url-line"></div>
+        </div>
+      </div>
+
+    </header>
+  </div>
+
+  {% block content_head_after %}
+  {% endblock %}
+
+{% endblock %} {# /content_head #}
+
+{% block content_main %}
+
+{% block content_main_before %}
+  <h2 class="message-not-found text-muted">
+    <i class="fa fa-info-circle" aria-hidden="true"></i>
+    Page is not found
+  </h2>
+{% endblock %}
+
+<div id="content-main" class="content-main content-main-not-found page-list"
+  data-path="{{ path }}"
+  data-path-shortname="{{ path|path2name }}"
+  data-page-id="{% if page %}{{ page._id.toString() }}{% endif %}"
+  data-current-user="{% if user %}{{ user._id.toString() }}{% endif %}"
+  data-current-username="{% if user %}{{ user.username }}{% endif %}"
+  data-page-revision-id="{% if revision %}{{ revision._id.toString() }}{% endif %}"
+  data-page-revision-created="{% if revision %}{{ revision.createdAt|datetz('U') }}{% endif %}"
+  data-page-is-seen="{% if page and page.isSeenUser(user) %}1{% else %}0{% endif %}"
+  data-linebreaks-enabled="{{ isEnabledLinebreaks() }}"
+  data-csrftoken="{{ csrf() }}"
+  >
+
+  <ul class="nav nav-tabs hidden-print">
+    <li class="active"><a href="#revision-body" data-toggle="tab">{{ t('List View') }}</a></li>
+
+    <li>
+      <a {% if user %}href="#edit-form" data-toggle="tab"{% endif %} class="edit-button {% if not user %}edit-button-disabled{% endif %}">
+        <i class="fa fa-pencil-square-o"></i> {{ t('Create') }}
+      </a>
+    </li>
+
+    {% if user %}
+    <li class="dropdown pull-right">
+      <a href="#" onclick="history.back();"><i class="fa fa-times"></i> {{ t('Cancel') }}</a>
+    </li>
+    {% endif %}
+  </ul>
+
+  <div class="tab-content wiki-content">
+    {% if req.query.renamed %}
+    <div class="alert alert-info alert-moved">
+      <span>
+        <strong>{{ t('Moved') }}: </strong> {{ t('page_page.notice.moved', req.query.renamed) }}
+      </span>
+    </div>
+    {% endif %}
+    {% if req.query.unlinked %}
+    <div class="alert alert-info">
+      <strong>{{ t('Unlinked') }}: </strong> {{ t('page_page.notice.unlinked') }}
+    </div>
+    {% endif %}
+
+    {# list view #}
+    <div class="active tab-pane page-list-container" id="revision-body">
+      {% if pages.length == 0 %}
+        There are no pages under <strong>{{ path }}</strong>.
+      {% endif  %}
+
+      {% include 'widget/page_list.html' with { pages: pages, pager: pager, viewConfig: viewConfig } %}
+    </div>
+
+    {# edit view #}
+    <div class="edit-form tab-pane {% if req.body.pageForm %}active{% endif %}" id="edit-form">
+      {% include '_form.html' %}
+    </div>
+
+  </div>
+</div>
+
+{% block content_main_after %}
+{% endblock %}
+
+{% endblock %}
+
+{% block content_footer %}
+{% endblock %}

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "crowi-plus",
-  "version": "1.2.11-RC",
+  "version": "1.2.12-RC",
   "description": "Enhanced Crowi",
   "tags": [
     "wiki",

+ 19 - 6
resource/css/_page.scss

@@ -109,13 +109,12 @@
         font-size: 1rem;
       }
 
-      // hide .btn
-      .btn {
-        visibility: hidden;
+      // change button opacity
+      .btn.btn-muted {
+        opacity: 0.3;
       }
-      // show .btn when hover
-      &:hover .btn {
-        visibility: unset;
+      &:hover .btn.btn-muted {
+        opacity: unset;
       }
     }
 
@@ -373,3 +372,17 @@
   }
 
 } // }}}
+
+// for not_found.html
+.crowi.main-container {
+  .message-not-found {
+    margin-top: 10px;
+    margin-left: 16px;
+  }
+
+  .content-main.content-main-not-found {
+    .nav {
+      margin-top: 16px;
+    }
+  }
+}

+ 13 - 6
resource/css/_page_crowi-plus.scss

@@ -36,6 +36,19 @@
   }
 }
 
+// for not_found.html
+.crowi-plus.main-container {
+  .message-not-found {
+    margin-left: 0;
+  }
+
+  .content-main.content-main-not-found {
+    .nav {
+      margin-top: 32px;
+    }
+  }
+}
+
 .crowi-plus .crowi-plus-widget.page-list-container {
   margin-top: 30px;
 
@@ -43,9 +56,3 @@
     margin-top: 15px;
   }
 }
-
-.crowi-plus .content-main-new-page {
-  .nav {
-    margin-top: 30px;
-  }
-}

+ 2 - 2
resource/js/components/Page/RevisionPath.js

@@ -107,8 +107,8 @@ export default class RevisionPath extends React.Component {
         </span>
         {afterElements}
         <CopyButton buttonId="btnCopyRevisionPath" text={this.props.pagePath}
-            buttonClassName="btn btn-default" iconClassName="fa fa-clone text-muted" />
-        <a href="#edit-form" className="btn btn-default" style={editButtonStyle}>
+            buttonClassName="btn btn-default btn-muted" iconClassName="fa fa-clone text-muted" />
+        <a href="#edit-form" className="btn btn-default btn-muted" style={editButtonStyle}>
           <i className="fa fa-edit text-muted"></i>
         </a>
       </span>

+ 1 - 1
resource/js/components/Page/RevisionUrl.js

@@ -24,7 +24,7 @@ export default class RevisionUrl extends React.Component {
       <span>
         {url}
         <CopyButton buttonId="btnCopyRevisionUrl" text={copiedText}
-            buttonClassName="btn btn-default" buttonStyle={buttonStyle} iconClassName="fa fa-link text-muted" />
+            buttonClassName="btn btn-default btn-muted" buttonStyle={buttonStyle} iconClassName="fa fa-link text-muted" />
       </span>
     );
   }

+ 14 - 9
resource/js/legacy/crowi.js

@@ -180,6 +180,8 @@ Crowi.modifyScrollTop = function() {
 
 
 $(function() {
+  var config = JSON.parse(document.getElementById('crowi-context-hydrate').textContent || '{}');
+
   var pageId = $('#content-main').data('page-id');
   var revisionId = $('#content-main').data('page-revision-id');
   var revisionCreatedAt = $('#content-main').data('page-revision-created');
@@ -187,6 +189,7 @@ $(function() {
   var isSeen = $('#content-main').data('page-is-seen');
   var pagePath= $('#content-main').data('path');
   var isEnabledLineBreaks = $('#content-main').data('linebreaks-enabled');
+  var isSavedStatesOfTabChanges = config['isSavedStatesOfTabChanges'];
 
   // generate options obj
   var rendererOptions = {
@@ -752,15 +755,17 @@ $(function() {
   } // end if pageId
 
   // hash handling
-  $('a[data-toggle="tab"][href="#revision-history"]').on('show.bs.tab', function() {
-    window.history.pushState('', 'History', '#revision-history');
-  });
-  $('a[data-toggle="tab"][href="#edit-form"]').on('show.bs.tab', function() {
-    window.history.pushState('', 'Edit', '#edit-form');
-  });
-  $('a[data-toggle="tab"][href="#revision-body"]').on('show.bs.tab', function() {
-    window.history.pushState('', '',  location.href.replace(location.hash, ''));
-  });
+  if (isSavedStatesOfTabChanges) {
+    $('a[data-toggle="tab"][href="#revision-history"]').on('show.bs.tab', function() {
+      window.history.pushState('', 'History', '#revision-history');
+    });
+    $('a[data-toggle="tab"][href="#edit-form"]').on('show.bs.tab', function() {
+      window.history.pushState('', 'Edit', '#edit-form');
+    });
+    $('a[data-toggle="tab"][href="#revision-body"]').on('show.bs.tab', function() {
+      window.history.pushState('', '',  location.href.replace(location.hash, ''));
+    });
+  }
 });
 
 Crowi.getRevisionBodyContent = function() {