Skip to main content
edited title
Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

jQuery plugin: custom Custom event to match CSS :target pseudo-class

added 28 characters in body
Source Link
konijn
  • 34.4k
  • 5
  • 71
  • 267
void function jQueryTargetEventClosure($){
    // Returns a 'ready' event to pass when 'target' is triggered by initial hash state on document load:
    // Prevents critical failure when attempting to invoke event methods on 'target' handlers
    var readyEventConstructor = (function readyEventConstructorClosure() {
        var history        = window.history;
        var historySupport = history.replaceState && typeof history.replaceState === 'function';
 
        return function readyEventConstructor() {
            var location = window.location;
            var readyEvent = $.Event( 'ready' );
 
            // In case of history support, allow preventDefault to remove the window location's hash
            if( historySupport && location.hash ){
                readyEvent.preventDefault = function preventDomReadyTargetDefault() {
                    history.replaceState( void 0, void 0, location.href.split( location.hash )[ 0 ] );
 
                    // ...but then hand over to jQuery's own preventDefault for internal statefulness etc
                    return ( $.Event.prototype.preventDefault || $.noop ).call( readyEvent );
                };
            }
            return readyEvent;
        };
    }());
 
    // Utility: removes the hash from any passed URI(-component)-like string
    function unHash( uriString ) {
        // String.prototype.link converts a string into an anchor, allowing us to use the DOM's URI abstraction properties
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/link
        var link = $( ''.link( uriString ))[ 0 ];
        // Splitting with an empty string (no hash) is not what we want. Replace falsy with null:
        return link.href.split( link.hash || void 0 )[ 0 ];
    }
 
    // Hashchange event handlers:
    // Alternate to prevent duplicates (otherwise a click will bubble to trigger a hashchange - creating another target)
    function filterHashChangeTarget( hashChangeEvent ) {
        var $subject = $( window.location.hash );
 
        $subject.trigger( 'target', [ hashChangeEvent ]);
    }
 
    // Bind the above handler
    function handleHashChange( hashChangeEvent ) {
        $( window )
            .off( 'hashchange.ignore' )
            .on( 'hashchange.handle', filterHashChangeTarget );
    }
 
    // Unbind the next instance
    function ignoreHashChange( hashChangeEvent ){
        $( window )
            .off( 'hashchange.handle' )
            .on( 'hashchange.ignore', handleHashChange );
    }
 
    // For link clicks
    $( 'body' ).on( 'click', 'a[href*=#]', function filterClickTarget( clickEvent ) {
        var link     = this;
        // The hash is effectively a selector for the targetted element
        var $subject = $( link.hash );
 
        void function handlePropagation(){
            // noop, in case preventDefault is not available
            var originalPreventDefault = clickEvent.preventDefault || $.noop();
 
            // Don't handle the next hash change
            ignoreHashChange();
 
            // ...Unless default's prevented
            clickEvent.preventDefault = function hashChangeInterrupt(){
                // Reinstate the hash change handler
                handleHashChange();
 
                return originalPreventDefault();
            };
        }();
 
        // Only apply to in-page links: minus the hash, link & location must match
        if ( unHash( link.href ) === unHash( window.location.href )) {
            $subject.trigger( 'target', [ clickEvent ]);
        }
    });
 
    // On DOM ready
    $(function readyTargetCheck(){
        $( window.location.hash ).trigger( 'target', readyEventConstructor() );
    });
}(jQuery);
void function jQueryTargetEventClosure($){
    // Returns a 'ready' event to pass when 'target' is triggered by initial hash state on document load:
    // Prevents critical failure when attempting to invoke event methods on 'target' handlers
    var readyEventConstructor = (function readyEventConstructorClosure() {
        var history        = window.history;
        var historySupport = history.replaceState && typeof history.replaceState === 'function';
 
        return function readyEventConstructor() {
            var location = window.location;
            var readyEvent = $.Event( 'ready' );
 
            // In case of history support, allow preventDefault to remove the window location's hash
            if( historySupport && location.hash ){
                readyEvent.preventDefault = function preventDomReadyTargetDefault() {
                    history.replaceState( void 0, void 0, location.href.split( location.hash )[ 0 ] );
 
                    // ...but then hand over to jQuery's own preventDefault for internal statefulness etc
                    return ( $.Event.prototype.preventDefault || $.noop ).call( readyEvent );
                };
            }
            return readyEvent;
        };
    }());
 
    // Utility: removes the hash from any passed URI(-component)-like string
    function unHash( uriString ) {
        // String.prototype.link converts a string into an anchor, allowing us to use the DOM's URI abstraction properties
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/link
        var link = $( ''.link( uriString ))[ 0 ];
        // Splitting with an empty string (no hash) is not what we want. Replace falsy with null:
        return link.href.split( link.hash || void 0 )[ 0 ];
    }
 
    // Hashchange event handlers:
    // Alternate to prevent duplicates (otherwise a click will bubble to trigger a hashchange - creating another target)
    function filterHashChangeTarget( hashChangeEvent ) {
        var $subject = $( window.location.hash );
 
        $subject.trigger( 'target', [ hashChangeEvent ]);
    }
 
    // Bind the above handler
    function handleHashChange( hashChangeEvent ) {
        $( window )
            .off( 'hashchange.ignore' )
            .on( 'hashchange.handle', filterHashChangeTarget );
    }
 
    // Unbind the next instance
    function ignoreHashChange( hashChangeEvent ){
        $( window )
            .off( 'hashchange.handle' )
            .on( 'hashchange.ignore', handleHashChange );
    }
 
    // For link clicks
    $( 'body' ).on( 'click', 'a[href*=#]', function filterClickTarget( clickEvent ) {
        var link     = this;
        // The hash is effectively a selector for the targetted element
        var $subject = $( link.hash );
 
        void function handlePropagation(){
            // noop, in case preventDefault is not available
            var originalPreventDefault = clickEvent.preventDefault || $.noop();
 
            // Don't handle the next hash change
            ignoreHashChange();
 
            // ...Unless default's prevented
            clickEvent.preventDefault = function hashChangeInterrupt(){
                // Reinstate the hash change handler
                handleHashChange();
 
                return originalPreventDefault();
            };
        }();
 
        // Only apply to in-page links: minus the hash, link & location must match
        if ( unHash( link.href ) === unHash( window.location.href )) {
            $subject.trigger( 'target', [ clickEvent ]);
        }
    });
 
    // On DOM ready
    $(function readyTargetCheck(){
        $( window.location.hash ).trigger( 'target', readyEventConstructor() );
    });
}(jQuery);
void function jQueryTargetEventClosure($){
    // Returns a 'ready' event to pass when 'target' is triggered by initial hash state on document load:
    // Prevents critical failure when attempting to invoke event methods on 'target' handlers
    var readyEventConstructor = (function readyEventConstructorClosure() {
        var history        = window.history;
        var historySupport = history.replaceState && typeof history.replaceState === 'function';
 
        return function readyEventConstructor() {
            var location = window.location;
            var readyEvent = $.Event( 'ready' );
 
            // In case of history support, allow preventDefault to remove the window location's hash
            if( historySupport && location.hash ){
                readyEvent.preventDefault = function preventDomReadyTargetDefault() {
                    history.replaceState( void 0, void 0, location.href.split( location.hash )[ 0 ] );
 
                    // ...but then hand over to jQuery's own preventDefault for internal statefulness etc
                    return ( $.Event.prototype.preventDefault || $.noop ).call( readyEvent );
                };
            }
            return readyEvent;
        };
    }());
 
    // Utility: removes the hash from any passed URI(-component)-like string
    function unHash( uriString ) {
        // String.prototype.link converts a string into an anchor, allowing us to use the DOM's URI abstraction properties
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/link
        var link = $( ''.link( uriString ))[ 0 ];
        // Splitting with an empty string (no hash) is not what we want. Replace falsy with null:
        return link.href.split( link.hash || void 0 )[ 0 ];
    }
 
    // Hashchange event handlers:
    // Alternate to prevent duplicates (otherwise a click will bubble to trigger a hashchange - creating another target)
    function filterHashChangeTarget( hashChangeEvent ) {
        var $subject = $( window.location.hash );
 
        $subject.trigger( 'target', [ hashChangeEvent ]);
    }
 
    // Bind the above handler
    function handleHashChange( hashChangeEvent ) {
        $( window )
            .off( 'hashchange.ignore' )
            .on( 'hashchange.handle', filterHashChangeTarget );
    }
 
    // Unbind the next instance
    function ignoreHashChange( hashChangeEvent ){
        $( window )
            .off( 'hashchange.handle' )
            .on( 'hashchange.ignore', handleHashChange );
    }
 
    // For link clicks
    $( 'body' ).on( 'click', 'a[href*=#]', function filterClickTarget( clickEvent ) {
        var link     = this;
        // The hash is effectively a selector for the targetted element
        var $subject = $( link.hash );
 
        void function handlePropagation(){
            // noop, in case preventDefault is not available
            var originalPreventDefault = clickEvent.preventDefault || $.noop();
 
            // Don't handle the next hash change
            ignoreHashChange();
 
            // ...Unless default's prevented
            clickEvent.preventDefault = function hashChangeInterrupt(){
                // Reinstate the hash change handler
                handleHashChange();
 
                return originalPreventDefault();
            };
        }();
 
        // Only apply to in-page links: minus the hash, link & location must match
        if ( unHash( link.href ) === unHash( window.location.href )) {
            $subject.trigger( 'target', [ clickEvent ]);
        }
    });
 
    // On DOM ready
    $(function readyTargetCheck(){
        $( window.location.hash ).trigger( 'target', readyEventConstructor() );
    });
}(jQuery);
void function jQueryTargetEventClosure($){
    // Returns a 'ready' event to pass when 'target' is triggered by initial hash state on document load:
    // Prevents critical failure when attempting to invoke event methods on 'target' handlers
    var readyEventConstructor = (function readyEventConstructorClosure() {
        var history        = window.history;
        var historySupport = history.replaceState && typeof history.replaceState === 'function';
 
        return function readyEventConstructor() {
            var location = window.location;
            var readyEvent = $.Event( 'ready' );
 
            // In case of history support, allow preventDefault to remove the window location's hash
            if( historySupport && location.hash ){
                readyEvent.preventDefault = function preventDomReadyTargetDefault() {
                    history.replaceState( void 0, void 0, location.href.split( location.hash )[ 0 ] );
 
                    // ...but then hand over to jQuery's own preventDefault for internal statefulness etc
                    return ( $.Event.prototype.preventDefault || $.noop ).call( readyEvent );
                };
            }
            return readyEvent;
        };
    }());
 
    // Utility: removes the hash from any passed URI(-component)-like string
    function unHash( uriString ) {
        // String.prototype.link converts a string into an anchor, allowing us to use the DOM's URI abstraction properties
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/link
        var link = $( ''.link( uriString ))[ 0 ];
        // Splitting with an empty string (no hash) is not what we want. Replace falsy with null:
        return link.href.split( link.hash || void 0 )[ 0 ];
    }
 
    // Hashchange event handlers:
    // Alternate to prevent duplicates (otherwise a click will bubble to trigger a hashchange - creating another target)
    function filterHashChangeTarget( hashChangeEvent ) {
        var $subject = $( window.location.hash );
 
        $subject.trigger( 'target', [ hashChangeEvent ]);
    }
 
    // Bind the above handler
    function handleHashChange( hashChangeEvent ) {
        $( window )
            .off( 'hashchange.ignore' )
            .on( 'hashchange.handle', filterHashChangeTarget );
    }
 
    // Unbind the next instance
    function ignoreHashChange( hashChangeEvent ){
        $( window )
            .off( 'hashchange.handle' )
            .on( 'hashchange.ignore', handleHashChange );
    }
 
    // For link clicks
    $( 'body' ).on( 'click', 'a[href*=#]', function filterClickTarget( clickEvent ) {
        var link     = this;
        // The hash is effectively a selector for the targetted element
        var $subject = $( link.hash );
 
        void function handlePropagation(){
            // noop, in case preventDefault is not available
            var originalPreventDefault = clickEvent.preventDefault || $.noop();
 
            // Don't handle the next hash change
            ignoreHashChange();
 
            // ...Unless default's prevented
            clickEvent.preventDefault = function hashChangeInterrupt(){
                // Reinstate the hash change handler
                handleHashChange();
 
                return originalPreventDefault();
            };
        }();
 
        // Only apply to in-page links: minus the hash, link & location must match
        if ( unHash( link.href ) === unHash( window.location.href )) {
            $subject.trigger( 'target', [ clickEvent ]);
        }
    });
 
    // On DOM ready
    $(function readyTargetCheck(){
        $( window.location.hash ).trigger( 'target', readyEventConstructor() );
    });
}(jQuery);
Tweeted twitter.com/#!/StackCodeReview/status/452763933045444608
edited tags
Link
Malachi
  • 29.1k
  • 11
  • 87
  • 188
Source Link
Barney
  • 131
  • 4
Loading