Search code examples
javascriptjquerytumblr

Is there a way to target a specific Tumblr post?


I am attempting to add an animated scroll to my Tumblr and I have found one in this question: Smooth scroll to div id jQuery. But the trick is, I need the button to jump to a specific post on the Tumblr.

I have found that each post has a specific id called PostID, and I have located the specific PostID I need. What I cannot find is an actual use of the PostID in the HTML, so I do not know how to target it. I tried:

$("#button").click(function() {
    $('html, body').animate({
        scrollTop: $("post-{130746374784}").offset().top
    }, 2000);
});

But I am sure I am calling it wrong. Can anyone tell me how to target it?


Solution

  • The simple preamble

    As pointed out by @approxiblue in this comment, Tumblr offers a variety of variables that can be used in a theme, including PostID.

    It would therefore be possible to replace something like this:

    <div class="post photo">
        <!-- more HTML here -->
    </div>
    

    With something like this:

    <div class="post photo" id="myPost_{PostID}">
        <!-- more HTML here -->
    </div>
    

    Allowing a more direct targeting of the post, as such:

    var post = $('#myPost_129129898812');
    

    The long answer

    Observing a Tumblr page, it seems the PostID is only available in links. This means we have to find the link including the PostID, then go back up to its container div.

    This is an example of a Tumblr post on a homepage:

    <!-- PHOTO POST 
    ///////////////////////////////////////////////////////-->
    <div class="post photo">
        <div class="wide">
            <a href="http://stolenjokescomic.tumblr.com/image/129129898812">
            <img src="http://41.media.tumblr.com/16c2f56a9f739889fbd4896f8524907c/tumblr_nupf28wgLl1toph1no1_1280.png" alt="" />
            </a>
        </div>
        <div class="narrow">
            <div class="metadata">
                <div class="date">
                    <a href="http://stolenjokescomic.tumblr.com/post/129129898812">Sep. 15 2015</a>
                </div>
            </div> <!-- metadata end -->
        </div> <!-- narrow end -->
    </div> <!-- post end -->
    

    We will:

    1. Target the element with class post
    2. Target the child with class date
    3. Target the child link with attribute href containing post/129129898812, which is the PostID used in this example
    4. Go back up by targeting the parent with class post using parents()
    5. Get the position

    Code:

    $("#button").click(function() {
        var position = $('.post .date a[href*="post/129129898812"]')
            .parents('.post')
            .offset().top;
    
        $('html, body').animate({
            scrollTop: position
        }, 2000);
    });
    

    You can try it out by:

    1. Going to stolenjokescomic
    2. Opening a scratchpad (SHIFT+F4 in Firefox)
    3. Pasting this code:

      $('html, body').animate({
          scrollTop: $('.post .date a[href*="post/129129898812"]')
              .parents('.post').offset().top
      }, 2000);
      
    4. Running it (CTRL+R in Firefox)

    The page should scroll down to the post. Unless you read this in a few months and the post is not on the homepage anymore.

    Alternative for the OKMove theme

    1. Get the target element using the PostID.
    2. Get the index of the target within the list of posts.
    3. Get the element to which the zoomIn function is attached.
    4. Trigger the click event to call the zoomIn function as many times as necessary to reach the target.

    Code:

    var zoomIn = $('.zoom-in');
    var target = $('#content section .about a[href*="post/18629325910"]').parents('section');
    var id     = $('#content section').index(target[0]);
    
    for(var i=0; i<id; ++i) {
        zoomIn.click();
    }
    

    You can try out this code on OKMove using a scratchpad.

    If this goes too fast, we can adjust using a a recursive setTimeout:

    var zoomIn = $('.zoom-in');
    var target = $('#content section .about a[href*="post/18629325910"]').parents('section');
    var index  = $('#content section').index(target[0]);
    
    var count = 0;
    var weNeedToGoDeeper = function() {
    
        if(count < index) {
           zoomIn.click();
           setTimeout(weNeedToGoDeeper, 400);
        }
    
        ++count;
    };
    
    weNeedToGoDeeper();
    

    We can expand this further to work from any position, analyzing the current position by parsing the transform property and then decide which way to zoom and how many times to do so by calculating the relative position between where we are and where we want to go:

    function parseMatrix(s) {
        return (
            s.match(/^matrix3d.(.*).$/) || ['', '0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0']
        )[1].split(', ');
    }
    
    var zoomIn  = $('.zoom-in');
    var zoomOut = $('.zoom-out');
    var content = $('#content');
    var target  = $('#content section .about a[href*="post/18629325910"]').parents('section');
    var index   = $('#content section').index(target[0]);
    
    var pos = parseMatrix(pos = content.css('transform'))[14];
    
    pos = Math.round(pos/1000);
    pos = index - pos;
    
    var zoomElem = pos <= 0 ? zoomOut : zoomIn;
    
    pos = Math.abs(pos);
    
    for(var i=0; i<pos; ++i) {
        zoomElem.click();
    }