问题
I'm developing a tumblr theme for my personal portfolio, but I'm encountering a serious problem in my work section, I want to create an horizontal slider effect, when I click next to see older posts,
like this:
http://tympanus.net/Tutorials/WebsiteScrolling/
I have this to define my nextPage, #section4 is where I have the posts of my work:
<!-- Next Page -->
{block:NextPage}
<div>
<a id="next-button" href="{NextPage}#section4" class="next panel" style="position:relative; top:630px; left:1550px;">next</a>
</div>
{/block:NextPage}
<!-- / Next Page -->
Well, this is defined to open an other page:
"indexPage".tumblr.com#section4
when I click next it goes to:
"indexPage".tumblr.com/page/2#section4
Is there a way I can do this slide effect on my index page or at least give the illusion, that I'm making slide effect, when moving to other page?
回答1:
If I understand your question correctly, it is as serakfalcon mentioned but I'll add in tumblr specific points. You need to do three things specifically. I won't go into too much tumblr template codes and styling it and stick to these
- Loading the data dynamically
- Dynamically creating a new section/page
- Getting the navigation to work with new sections
Loading the data
This is actually the easy bit. For tumblr, as you mentioned, we can manually go to the next page by clicking the "next page" link. In tumblr this will look something like
{block:NextPage}
<li></li><a href="{NextPage}" class="next-page static">{lang:Next page}</a></li>
{/block:NextPage}
Since the pages are on the same domain, we can override the link to get the page using AJAX. We will be getting the raw HTML for this page. Which will include all the other parts of the page like the three other sections. There may be some tumblr template magic that we can do to limit this, but I'll consider that outside the scope. So how do we get the content specifically? We can feed the raw HTML into jquery for it to build document objects, and we can then select the content that has the post from there. So something like.
$(document.body).on('click',".static",function(e){ //delegated
var xhr=$.get($(this).attr("href"),function(a){ //a is next page's HTML
$loaded=$(a); //loaded now has a temporary object with next page's objects
var postsHTML=$loaded.find("#posts").html() //contains posts we can embed
//what to find depends on your template. I used the default id="posts"
})
})
Creating a new section/page
Once we have the data, we now need to put the data into a new page. There's many ways on doing this but here's how I did it. First of all, I had a template for the new section. I put it in a script tag like so. I kind of like the semantics of doing it like this.
<script type="text/x-template" id="section-template">
<div class="section">
<div class="posts"></div>
<ul class="nav">
<li><a href="#section1">1</a></li>
<li><a href="#section2">2</a></li>
<li><a href="#section2">3</a></li>
<li><a href="#section4">4</a></li>
<li><a href="#" class="last-page">Back</a></li>
<li><a href="#" class="next-page static">Next</a></li>
</ul>
</div>
</script>
With that done, whenever the data is loaded we can get the raw HTML from this, and create a the new elements by feeding it to jQuery again. We then append the posts to the div
with class posts
. We also get the next page link from the data to attach to the next-page link so that the earlier ajax call will work. If we can't find the next-page link, that means there's no more posts. So we can hide the next-page link. We'll also stop the existing link to load data through ajax and do the normal slidey thing. Finally we'll append the new section to the parent div of the sections, fix it's width and then transition to the new section.
$(document.body).on('click',".static",function(e){ //deferred
e.preventDefault();
var that=this //to refer inside $.get callback
var xhr=$.get($(this).attr("href"),function(a){
$(that).removeClass('static') //stop this link from loading again
var $loaded=$(a)
var next_section=$($("#section-template").html()); //make the new section
var num_sections=$(".section").length + 1 //number of sections
next_section.addClass(num_sections%2 ? "white" : "black") //consistency
//find .posts in the new section and put the tumblr data in it
next_section.find(".posts").html($loaded.find("#posts").html())
//tumblr next page link. change according to template
var next_link=$loaded.find(".static")
if(next_link.length){ //if next link exists
//attach href to next page link in new section
next_section.find(".static").attr("href",next_link.attr("href"))
} else { //no next
//hide the next page link in new section
next_section.find(".static").hide()
}
$("#horizontal-scroller").append(next_section); //append to body
$("#horizontal-scroller").width(4000*num_sections); //resize body
$('html, body').stop().animate({ //to the new section
scrollLeft: $(next_section).offset().left
}, 1000);
}) //$.get
}) //click
Getting the navigation to work
I probably should append new links to the nav, but I guess to make it easier (and imagine how it look like with 40 pages) I decided to just use a "next page" and "last page" for the loaded content. The code is simple. For next page, if it's not .static
, move to the next section and ditto last page. we'll delegate (technically, I'm using .on()
but the docs on .delegate
seemed easier to understand) it to the document body so that it works for all the new links.
So as a whole javascript/jquery will look something like
$(document.body)
.on('click','ul.nav a:not(.next-page):not(.last-page)',function(e){
var $anchor = $(this);
$('html, body').stop().animate({
scrollLeft: $($anchor.attr('href')).offset().left
}, 1000);
e.preventDefault();
})
.on('click',".next-page:not(.static)",function(e){ //next page not static
e.preventDefault()
$('html, body').stop().animate({
scrollLeft: $(this).closest(".section").nextAll(".section").offset().left
}, 1000);
})
.on('click',".last-page",function(e){ //last page
e.preventDefault()
$('html, body').stop().animate({
scrollLeft: $(this).closest(".section").prevAll(".section").offset().left
}, 1000);
})
.on('click',".static",function(e){
e.preventDefault();
var that=this
var xhr=$.get($(this).attr("href"),function(a){
$(that).removeClass('static')
var $loaded=$(a)
var next_section=$($("#section-template").html());
var num_sections=$(".section").length + 1
next_section.addClass(num_sections%2 ? "white" : "black")
next_section.find(".posts").html($loaded.find("#posts").html())
var next_link=$loaded.find(".static")
if(next_link.length){
next_section.find(".static").attr("href",next_link.attr("href"))
} else {
next_section.find(".static").hide()
}
$("#horizontal-scroller").append(next_section); //append to body
$("#horizontal-scroller").width(4000*num_sections); //resize body
$('html, body').stop().animate({
scrollLeft: $(next_section).offset().left
}, 1000);
}) //$.get
}) //click
Here's a live demo of it working. Didn't really bother with making the slides look nice but hopefully you found this helpful.
回答2:
Of course, everything has to happen on one page, or you can't exactly have the transition. So, either you load everything at run time, or you 'cheat' using AJAX.
alter the in-page javascript to the following:
function bindAnimation(event) {
var $anchor = $(this);
/*
if you want to use one of the easing effects:
$('html, body').stop().animate({
scrollLeft: $($anchor.attr('href')).offset().left
}, 1500,'easeInOutExpo');
*/
$('html, body').stop().animate({
scrollLeft: $($anchor.attr('href')).offset().left
}, 1000);
event.preventDefault();
}
$(function() {
$('ul.nav').on('click','.getNew',getNewSection);
$('ul.nav').on('click','a',bindAnimation);
});
This allows you to add a elements dynamically to the navs, and will attach an event listener to a new element we will use to get new content. Modify the nav menu so that the last element is something like:
<li class="getNew">New</li>
There. now clicking on that will load the new content. add this javascript code to your site above the previous javascript code:
window.newSectionBlack = false;
window.SectionID = 4;
function displaySection(data,textStatus, jqXHR) {
$('#section3').after(data.html); //add the new section
$('#'+data.id).addClass(newSectionBlack ? 'black' : 'white');
newSectionBlack = !newSectionBlack; //style it consistently
$('.getNew').before('<li><a href="#'+data.id+'">'+data.name+'</li>'); //attach a link to the new section to the menu
$('body').css({width:4000*SectionID});
$('#'+data.id+' ul.nav').on('click','a',bindAnimation); //bind scripts
$('#'+data.id+' ul.nav').on('click','.getNew',getNewSection);
$('#section1 > ul li:nth-last-child(2) > a').trigger('click'); //go to new
SectionID++;
}
function getNewSection() {
$.ajax({
type: "POST",
url: 'LoadSection.php',
data: {section:SectionID},
success: displaySection,
dataType: 'json'
});
}
This javascript will POST a number corresponding to which section to load to a new file, LoadSection.php, which needs to respond with the HTML of the new section, the ID and name it should be called. loadSection.php can look like this:
<?php
header('Content-Type: application/json');
$send = array();
switch($_POST['section']) {
default:
$send['html'] = '<div class="section" id="section'.$_POST['section'] .'"><h2>Section ' . $_POST['section'] . '</h2>
<p>
This is a new section loaded via AJAX, cool huh?
</p>
<ul class="nav">
<li><a href="#section1">1</a></li>
<li><a href="#section2">2</a></li>
<li><a href="#section3">3</a></li>
<li class="getNew">New</li>
</ul>
</div>';
$send['id'] = 'section'.$_POST['section'];
$send['name'] = $_POST['section'];
}
echo json_encode($send);
Now, your page can load content dynamically! Note, the nav bar should probably be restructured to be an absolute element that there's only one of instead of repeated on every page, and there's other stuff you can clean up but that's to be expected if you're taking a codrops example.
EDIT:
tumblr doesn't let you run server-side scripts on their server (makes sense), which are required for the AJAX method described above to work. However, there are a number of options available to you. 1) redirect the tumblr page to a site you control, and use the method described above. 2) use an iframe.
The iframe method could be done directly, which requires you to specify the urls of all the pages in advance (or at least they'll need to follow a predictable pattern), or indirectly using a AJAX script similar to the one above. I will demonstrate loading a direct iframe, I'm sure you can figure out the rest.
window.newSectionBlack = false;
window.newSectionID = 4;
function getNewSection() {
$('#section3').after('<div class="section" id="section'+newSectionID+'"><h2>New Section</h2>
<iframe src="yourtumbrsite.com></iframe>
<ul class="nav">
<li><a href="#section1">1</a></li>
<li><a href="#section2">2</a></li>
<li><a href="#section3">3</a></li>
<li class="getNew">New</li>
</ul>
</div>
'); //add the new section
$('#section'+newSectionID).addClass(newSectionBlack ? 'black' : 'white');
newSectionBlack = !newSectionBlack; //style it consistently
$('.getNew').before('<li><a href="#section'+newSectionID+'">'+newSectionID+</li>'); //attach a link to the new section to the menu
$('body').css({width:4000*newSectionID});
$('#'+data.id+' ul.nav').on('click','a',bindAnimation); //bind scripts
$('#'+data.id+' ul.nav').on('click','.getNew',getNewSection);
$('#section1 > ul li:nth-last-child(2) > a').trigger('click'); //go to new
newSectionID++;
}
来源:https://stackoverflow.com/questions/23722958/how-can-i-load-the-content-of-tumblr-nextpage-on-indexpage