]> git.ipfire.org Git - thirdparty/foundation/foundation-sites.git/commitdiff
Use pull request #11530 from ncoden/fix/tabs-accordion-deep-linking-11527 for v6.5.0
authorNicolas Coden <nicolas@ncoden.fr>
Thu, 11 Oct 2018 20:49:56 +0000 (22:49 +0200)
committerNicolas Coden <nicolas@ncoden.fr>
Thu, 11 Oct 2018 20:49:56 +0000 (22:49 +0200)
33c55db80 fix: fix scroll to deep-linking default anchor on initialization in Tabs/Accordion
8d4a13ead fix: prevent Tabs/Accordion to scroll to others components' anchors
7bccec66f fix: ensure Tab deep-linking to redirect to hash with #
9fbc2eeb5 test: add visual test for Tabs deep-linking

Signed-off-by: Nicolas Coden <nicolas@ncoden.fr>
js/foundation.accordion.js
js/foundation.tabs.js
test/visual/tabs/deep-linking.html [new file with mode: 0644]

index 311a5df96edcbafe7f6354b60b498cd89969d41d..b30ca15a2debf8d1f3ca4ed36b542f5eef8d0b6e 100644 (file)
@@ -40,6 +40,8 @@ class Accordion extends Plugin {
    * @private
    */
   _init() {
+    this._isInitializing = true;
+
     this.$element.attr('role', 'tablist');
     this.$tabs = this.$element.children('[data-accordion-item]');
 
@@ -70,13 +72,17 @@ class Accordion extends Plugin {
     this._checkDeepLink = () => {
       var anchor = window.location.hash;
 
-      // If there is no anchor, return to the initial panel
-      if (!anchor.length && this._initialAnchor) {
-        anchor = this._initialAnchor;
+      if (!anchor.length) {
+        // If we are still initializing and there is no anchor, then there is nothing to do
+        if (this._isInitializing) return;
+        // Otherwise, move to the initial anchor
+        if (this._initialAnchor) anchor = this._initialAnchor;
       }
 
       var $anchor = anchor && $(anchor);
       var $link = anchor && this.$element.find(`[href$="${anchor}"]`);
+      // Whether the anchor element that has been found is part of this element
+      var isOwnAnchor = !!($anchor.length && $link.length);
 
       // If there is an anchor for the hash, open it (if not already active)
       if ($anchor && $link && $link.length) {
@@ -89,15 +95,15 @@ class Accordion extends Plugin {
         this._closeAllTabs();
       }
 
-      // Roll up a little to show the titles
-      if (this.options.deepLinkSmudge) {
-        onLoad($(window), () => {
-          var offset = this.$element.offset();
-          $('html, body').animate({ scrollTop: offset.top }, this.options.deepLinkSmudgeDelay);
-        });
-      }
+      if (isOwnAnchor) {
+        // Roll up a little to show the titles
+        if (this.options.deepLinkSmudge) {
+          onLoad($(window), () => {
+            var offset = this.$element.offset();
+            $('html, body').animate({ scrollTop: offset.top }, this.options.deepLinkSmudgeDelay);
+          });
+        }
 
-      if ($anchor && $link) {
         /**
          * Fires when the plugin has deeplinked at pageload
          * @event Accordion#deeplink
@@ -112,6 +118,8 @@ class Accordion extends Plugin {
     }
 
     this._events();
+
+    this._isInitializing = false;
   }
 
   /**
index 489640e5305c22c68e9356d574706220443ab7b7..4febb1cc35177f044fdc2b7983fb930d6d0bd525 100644 (file)
@@ -45,6 +45,7 @@ class Tabs extends Plugin {
    */
   _init() {
     var _this = this;
+    this._isInitializing = true;
 
     this.$element.attr({'role': 'tablist'});
     this.$tabTitles = this.$element.find(`.${this.options.linkClass}`);
@@ -105,13 +106,17 @@ class Tabs extends Plugin {
     this._checkDeepLink = () => {
       var anchor = window.location.hash;
 
-      // If there is no anchor, return to the initial panel
-      if (!anchor.length && this._initialAnchor) {
-        anchor = this._initialAnchor;
+      if (!anchor.length) {
+        // If we are still initializing and there is no anchor, then there is nothing to do
+        if (this._isInitializing) return;
+        // Otherwise, move to the initial anchor
+        if (this._initialAnchor) anchor = this._initialAnchor;
       }
 
       var $anchor = anchor && $(anchor);
       var $link = anchor && this.$element.find('[href$="'+anchor+'"]');
+      // Whether the anchor element that has been found is part of this element
+      var isOwnAnchor = !!($anchor.length && $link.length);
 
       // If there is an anchor for the hash, select it
       if ($anchor && $anchor.length && $link && $link.length) {
@@ -122,13 +127,13 @@ class Tabs extends Plugin {
         this._collapse();
       }
 
-      // Roll up a little to show the titles
-      if (this.options.deepLinkSmudge) {
-        var offset = this.$element.offset();
-        $('html, body').animate({ scrollTop: offset.top }, this.options.deepLinkSmudgeDelay);
-      }
+      if (isOwnAnchor) {
+        // Roll up a little to show the titles
+        if (this.options.deepLinkSmudge) {
+          var offset = this.$element.offset();
+          $('html, body').animate({ scrollTop: offset.top }, this.options.deepLinkSmudgeDelay);
+        }
 
-      if ($anchor && $link) {
         /**
          * Fires when the plugin has deeplinked at pageload
          * @event Tabs#deeplink
@@ -143,6 +148,8 @@ class Tabs extends Plugin {
     }
 
     this._events();
+
+    this._isInitializing = false;
   }
 
   /**
@@ -252,8 +259,9 @@ class Tabs extends Plugin {
     var $oldTab = this.$element.
           find(`.${this.options.linkClass}.${this.options.linkActiveClass}`),
           $tabLink = $target.find('[role="tab"]'),
-          hash = $tabLink.attr('data-tabs-target') || $tabLink[0].hash.slice(1),
-          $targetContent = this.$tabContent.find(`#${hash}`);
+          target = $tabLink.attr('data-tabs-target'),
+          anchor = target && target.length ? `#${target}` : $tabLink[0].hash,
+          $targetContent = this.$tabContent.find(anchor);
 
     //close old tab
     this._collapseTab($oldTab);
@@ -264,9 +272,9 @@ class Tabs extends Plugin {
     //either replace or update browser history
     if (this.options.deepLink && !historyHandled) {
       if (this.options.updateHistory) {
-        history.pushState({}, '', hash);
+        history.pushState({}, '', anchor);
       } else {
-        history.replaceState({}, '', hash);
+        history.replaceState({}, '', anchor);
       }
     }
 
diff --git a/test/visual/tabs/deep-linking.html b/test/visual/tabs/deep-linking.html
new file mode 100644 (file)
index 0000000..e2d908c
--- /dev/null
@@ -0,0 +1,86 @@
+<!doctype html>
+<!--[if IE 9]><html class="lt-ie10" lang="en" > <![endif]-->
+<html class="no-js" lang="en" dir="ltr">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
+  <title>Tabs Deep Linking</title>
+  <link href="../assets/css/foundation.css" rel="stylesheet" />
+</head>
+<body>
+<div class="grid-container">
+  <div class="grid-x grid-padding-x">
+    <div class="cell">
+
+      <h1>Tabs Deep Linking</h1>
+
+      <p>
+        <li>When a tab is set as active, <code>#panel...</code> should be set in the url.
+        <li>Refresing the page should make it scroll down to the active tab</li>
+        <li>Going back in history should restore the previous state (even if no all tabs were active before).</li>
+      </p>
+
+      <div style="height: 1024px; background: #ddd;">
+        Placeholder
+      </div>
+
+      <ul class="tabs" data-deep-link="true" data-update-history="true" data-deep-link-smudge="true" data-deep-link-smudge-delay="500" data-tabs id="deeplinked-tabs-1">
+        <li class="tabs-title is-active"><a href="#panel1d">Tab 1</a></li>
+        <li class="tabs-title"><a href="#panel2d">Tab 2</a></li>
+        <li class="tabs-title"><a href="#panel3d">Tab 3</a></li>
+        <li class="tabs-title"><a href="#panel4d">Tab 4</a></li>
+      </ul>
+
+      <div class="tabs-content" data-tabs-content="deeplinked-tabs-1">
+        <div class="tabs-panel is-active" id="panel1d">
+          <p>Content for #panel1. I should be active by default.</p>
+        </div>
+        <div class="tabs-panel" id="panel2d">
+          <p>Content for #panel2</p>
+        </div>
+        <div class="tabs-panel" id="panel3d">
+          <p>Content for #panel3</p>
+        </div>
+        <div class="tabs-panel" id="panel4d">
+          <p>Content for #panel4</p>
+        </div>
+      </div>
+
+      <div style="height: 1024px; background: #ddd;">
+        Placeholder
+      </div>
+
+      <ul class="tabs" data-active-collapse="true" data-deep-link="true" data-update-history="true" data-deep-link-smudge="true" data-deep-link-smudge-delay="500" data-tabs id="deeplinked-tabs-2">
+        <li class="tabs-title"><a href="#panel5d">Tab 5</a></li>
+        <li class="tabs-title"><a href="#panel6d">Tab 6</a></li>
+        <li class="tabs-title"><a href="#panel7d">Tab 7</a></li>
+        <li class="tabs-title"><a href="#panel8d">Tab 8</a></li>
+      </ul>
+
+      <div class="tabs-content" data-tabs-content="deeplinked-tabs-2">
+        <div class="tabs-panel active" id="panel5d">
+          <p>Content for #panel5. I can collapse.</p>
+        </div>
+        <div class="tabs-panel" id="panel6d">
+          <p>Content for #panel6. I can collapse.</p>
+        </div>
+        <div class="tabs-panel" id="panel7d">
+          <p>Content for #panel7. I can collapse.</p>
+        </div>
+        <div class="tabs-panel" id="panel8d">
+          <p>Content for #panel8. I can collapse.</p>
+        </div>
+      </div>
+
+    </div>
+  </div>
+</div>
+
+<script src="../assets/js/vendor.js"></script>
+<script src="../assets/js/foundation.js"></script>
+<script>
+  $(document).foundation();
+</script>
+</body>
+</html>