2016-07-10 2 views
1

Ich versuche, ein Modul zu machen ScrollToAnchor genannt, die eine Funktion goToTarget, dass ich in der Lage zu nennen wie ScrollToAnchor.goToTarget(target);Javascript-Modul mit JQuery Modulfunktionen zu undefinierten werden

aber sie sagt, dass

ScrollToAnchor.goToTarget is not a function

genannt hat

Ich denke, ScrollToAnchor ist vom Typ jQuery, wie ich es wegen der $ habe. Hier ist der Code:

var ScrollToAnchor = $(function() { 
    var headerHeight = 70; 

    $('a[href*="#"]:not([href="#"])').click(function() { 
    if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) { 
     if (goToTarget(this.hash)) 
     return false; 
    } 
    }); 

    /*$('input[data-target]').click(function() { 
      if (gotoTarget($(this).data("target"))) 
      return false; 
    })*/ 

    var goToTarget = function(targetName) { 
    var target = $(targetName); 
    target = target.length ? target : $('[name="' + targetName.slice(1) + '"]'); 
    if (target.length) { 
     $('html,body').animate({ 
     scrollTop: target.offset().top - headerHeight 
     }, 1000); 

     return true; 
    } 
    return false; 
    } 

    return { 
    goToTarget: goToTarget 
    } 
}); 

Was mache ich falsch? Wenn ich die $ von var ScrollToAnchor = $(function() { entferne, funktioniert die jQuery innerhalb ScrollToAnchor nicht.

Aber wenn ich die $ dort lassen dann denkt, ScrollToAnchor ist Typ jQuery und ScrollToAnchor.goToTarget ist keine Funktion.

Antwort

1

Die $(function() {...}) ist eine kurze Hand von $(document).ready(handler).

Das Ergebnis von ist also ein jQuery Ergebnissatz, der die document als Element enthält.

Sie suchen Event Delegation:

$(document).on('click', 'a[href*="#"]:not([href="#"])', function() { 
    if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) { 
    if (goToTarget(this.hash)) 
     return false; 
    } 
}); 

Dadurch wird sichergestellt, dass die click Ereignis Verwendung für alle a Element sein wird, unabhängig davon, wann sie auf das DOM hinzugefügt wurden und ermöglicht Ihre Ihre goToTarget zur Verfügung stellen im globalen Umfang auf einfache Weise. Ihr endgültiger Code sieht dann so aus:

var ScrollToAnchor = (function() { 
    var headerHeight = 70; 

    // event handler with delegation 
    $(document).on('click', 'a[href*="#"]:not([href="#"])', function() { 
    if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) { 
     if (goToTarget(this.hash)) 
     return false; 
    } 
    }); 

    function goToTarget(targetName) { 
    var target = $(targetName); 
    target = target.length ? target : $('[name="' + targetName.slice(1) + '"]'); 
    if (target.length) { 
     $('html,body').animate({ 
     scrollTop: target.offset().top - headerHeight 
     }, 1000); 

     return true; 
    } 

    return false; 
    } 

    return { 
    goToTarget: goToTarget 
    } 

}()); 

Mit Ereignisse Delegation besteht keine Notwendigkeit, Ihr ganzen Code in ein $(function() {...}) zu wickeln und Ihre ScrollToAnchor sind öffentlich verfügbar.

1

Drehen Sie ScrollToAnchor in eine normale Funktion. Diese Funktion wird im globalen Bereich sein:

window.ScrollToAnchorFactory = function() { 
    var headerHeight = 70; 
    $('a[href*="#"]:not([href="#"])').click(function() { 
     if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) { 
      if (goToTarget(this.hash)) 
       return false; 
     } 
    }); 

    /*$('input[data-target]').click(function() { 
      if (gotoTarget($(this).data("target"))) 
      return false; 
    })*/ 

     var goToTarget = function (targetName) { 
      var target = $(targetName); 
      target = target.length ? target : $('[name="' + targetName.slice(1) + '"]'); 
      if (target.length) { 
       $('html,body').animate({ 
        scrollTop: target.offset().top - headerHeight 
       }, 1000); 

       return true; 
      } 

      return false; 
     } 

    return { 
     goToTarget: goToTarget 
    } 
}; 

Sie könnten auch einen module.export verwenden, anstatt diese im globalen Bereich des Setzens, wenn Sie einen Commonjs Modul aus diesem Code erstellen mögen. Dies würde es ermöglichen,() es in andere Dateien (mit Browserify zu kompilieren) erfordern.

Wenn Sie nur entscheiden zu ScrollToAnchorFactory im globalen Bereich zu halten, wo immer Sie scrollToAnchor.goToTarget (in der gleichen Datei oder einem anderen) verwenden müssen ...

$(function() { 
    var scrollToAnchor = window.ScrollToAnchorFactory(); 
    // you can now use scrollToAnchor.goToTarget(target) 
}); 

Sie wollen jQuery DOM ready-Funktion um diesen Teil gewickelt, so dass ScrollToAnchorFactory nicht versucht, init, bevor Ihre Anker im DOM vollständig gebildet sind.

+0

Danke. Wie würde ich 'ScrollToAnchor.goToTarget (Ziel)' in einer anderen Javascript-Datei nennen? Gibt es eine Art Import-Aussage? Weil ich bekomme 'bootstrap_app.js: 28 Uncaught ReferenceError: ScrollToAnchor ist nicht definiert' – BeniaminoBaggins

+0

Da Sie' ScrollToAnchor' in den Geltungsbereich des jQuery DOM-ready-Callbacks setzen würde, wird der globale Gültigkeitsbereich verlassen. Eine Option wäre, "var ScrollToAnchor" durch "window.ScrollToAnchor" zu ersetzen. Dies würde ScrollToAnchor in den globalen Bereich stellen und an anderer Stelle verfügbar machen.Dies könnte jedoch zu einer Race-Bedingung führen, wenn die andere JS-Datei versucht, 'ScrollToAnchor' aufzurufen, bevor die jQuery DOM-ready-Funktion ausgeführt wird. Ich werde meine Antwort aktualisieren, um dies zu vermeiden. – jmealy

+0

Danke. Eine gute Erklärung. – BeniaminoBaggins

Verwandte Themen