Javascript — manipulating attributes of dynamically loaded (or autopaged) content
Mega Edit — I have tried to explain my issue as clearly as possible.
My goal: to set the height of newly loaded images to the same size of the browser if their height is taller than开发者_运维百科 the browser.
Best way i can do this is via commented code i think. It's currently live on http://syndex.me.
The complete js file that the below transcript was taken from can be reached at http://marckremers.com/syndex/js/jquery.infinitescrollfortumblr.js
//Gets the computed style of the image rather than the specified.
//This was supplied very kindly by @RobG
//The problem is that on first load, the height for the image is showing as 0 for the larger images.
//Once it's cached, the functions shows the correct height.
//I have no idea how to make this function work on a "on Ready" or "On Loaded"?
function getComputedStyle(el, styleProperty) {
if (document && document.defaultView && document.defaultView.getComputedStyle) {
var styleObj = document.defaultView.getComputedStyle(el, null);
var floatStyle = (typeof document.body.style.cssFloat == 'string')?'cssFloat':'styleFloat';
if (styleProperty == 'float') styleProperty = floatStyle;
return styleObj && styleObj[styleProperty];
}
}
function addNextPage(oj) {
if (oj.status == 404) {
tAP.remainFlg = false;
return;
}
var d = document.createElement("div");
d.innerHTML = oj.responseText;
var posts = tAP.gP(d.getElementsByTagName("*"));
if (posts.length < 2) {
tAP.rF = false;
return;
}
d = document.createElement("div");
d.className = "tumblrAutoPager_page_info";
tAP.pp.appendChild(d);
for (var i = 0; i < posts.length; i++) {
//Goal: Set newly loaded images via this autopager script for tumblr
// to the height of the browser
// (So... IF the image is taller than the browser
// Make the image as tall as the browser)
// In effect I'm trying to make a dynamic image max-height based on the browser
// This is loading the new posts (part of the autopager script, not my code)
tAP.pp.appendChild(posts[i]);
//Over here I'm trying to reference the newly loaded imgs
//BUT this is a horrible way of getting them, apprently.
//It gets all the imgs in the entire document.
//But it seems to work for my array below, anyhow
//I really just need to deal with the new ones loaded in.
var myDivs = tAP.pp.getElementsByTagName("img");
}
var myHeights = [];
for (var n=0, iLen=myDivs.length; n<iLen; n++) {
myHeights.push(getComputedStyle(myDivs[n], 'height'));
}
console.log(myHeights)
//= I get an array of image heights, however the newly loaded imgs often show up as 0
// so the "getcomputedstyle" script is not working as it should yet.
//once the page is cached, it works as it should
//you can see the console logs here http://syndex.me
//Over here would go:
//"for each image
// if my height is taller then the window
// make me as tall as the window"
//Finally, I have this working PERFECTLY in the jquery code
//you can see it at http://syndex.me on the first page load.
//since you can't bind .live or .delegate to events that don't "bubble"
//up the DOM tree, i.e. ".load", I can't get it to recognise
//newly loaded images from this script
//thats why i'm having to hack this file
var footer = $("footer");
footer ? footer.parentNode.appendChild(footer) : null;
tAP.rF = true;
}
Thanks in advance.
Probably because myDivs
contains a NodeList
, an array like object which contains indexed references to the matched elements, which does not have a getAttribute()
member.
Instead, subscript the individual elements (either with [n]
or item(n)
), which will have a getAttribute()
method. Or just use the width
property.
Your code is faulty:
> myDivs = tAP.pp.getElementsByTagName("img");
getElementsByTagName returns a live NodeList.
> myWidths = myDivs.getAttribute("width");
NodeLists don't have a getAttribute method, DOM elements do.
In any case, it is much more efficient to access the property, so:
var myWidths = [];
for (var i=0, iLen=myDivs.length; i<iLen; i++) {
myWidths.push(myDivs[i].width);
}
However, elements other than images usually only have a width property if it has been set as an attribute or property. You may be after the computed style, e.g.
<script type="text/javascript">
function getActualWidth(el, styleProperty) {
if (document && document.defaultView && document.defaultView.getComputedStyle) {
var styleObj = document.defaultView.getComputedStyle(el, null);
var floatStyle = (typeof document.body.style.cssFloat == 'string')?'cssFloat':'styleFloat';
if (styleProperty == 'float') styleProperty = floatStyle;
return styleObj && styleObj[styleProperty];
}
}
</script>
<div onclick="alert(getActualWidth(this, 'width'));">div</div>
That gets you with width. To change the width, just set it directly:
element.style.width = '500px';
Admittedly I never knew about computed styles until I read this post, so unfortunately I can't really comment on what else has been said here. (going to read up on it after — I promise).
You're right about event delegation in that you can't bind a jQuery live() (or equivalent) to img load events as it's a 'simple' event and doesn't bubble. So afaik you do have to manually add the load event to each individual image.
The only real tricky part is making sure that you account for already cached images. Here's one approach.
I've recreated a stripped down, static version of your tumblr page with a button that appends another image, which is basically your addNextPage()
call. Hope it helps.
http://dl.dropbox.com/u/15924676/syndex/index.html
<!DOCTYPE html>
<html>
<head>
<title>Syndex</title>
<script type="text/javascript" src="./Syndex_files/jquery-latest.min.js"></script>
<link rel="stylesheet" type="text/css" href="./Syndex_files/style.css" media="screen">
</head>
<body>
<div>
<input type="button" value="add image" />
</div>
<div id="posts">
<div class="autopagerize_page_element">
</div>
</div>
</body>
<script>
var $window = $(window);
var $pageImages;
var images = [
'<div id="10823012653" rel="http://www.tumblr.com/reblog/10823012653/ymaZUCKg" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb37adUwD1r4306n" alt="Olaf Breuning"><div class="kremers">original height 701</div></div></div>',
'<div id="10822915844" rel="http://www.tumblr.com/reblog/10822915844/JknV8s3a" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb33m4S7j1r4306no1_400.png" alt="Jacqueline Casey, Graphic Designer for MIT 1963 - 1990"><div class="kremers">original height 500</div></div></div>',
'<div id="10822870581" rel="http://www.tumblr.com/reblog/10822870581/oJMKWl9k" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb31sUYvQ1r4306n" alt="Vanessa Veasley x Supreme x Terry Richardson"><div class="kremers">original height 1280</div></div></div>',
'<div id="10822380405" rel="http://www.tumblr.com/reblog/10822380405/AwsPNE5L" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb2ivLTWQ1r4306n" alt="Xavier Delory - Habitat"><div class="kremers">original height 857</div></div></div>',
'<div id="10822233573" rel="http://www.tumblr.com/reblog/10822233573/9OTI6gLl" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb2d6sESW1r4306n" alt="Yellow Smoke Bomb"><div class="kremers">original height 900</div></div></div>',
'<div id="10822153538" rel="http://www.tumblr.com/reblog/10822153538/GhQQOncG" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb2a3Gh2L1r4306n" alt="Karl Gerstner - Colour Sounds"><div class="kremers">original height 1024</div></div></div>',
'<div id="10822119380" rel="http://www.tumblr.com/reblog/10822119380/mTyZ3yoh" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb28q4g7p1r4306n" alt="Karl Gerstner - Colour Sounds"><div class="kremers">original height 1024</div></div></div>',
'<div id="10822031937" rel="http://www.tumblr.com/reblog/10822031937/OoqboZsY" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb258iApO1r4306n" alt="Cindy Sherman - Untitled Film Still #45"><div class="kremers">original height 920</div></div></div>',
'<div id="10821751285" rel="http://www.tumblr.com/reblog/10821751285/LlXg7AsU" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb1u2045A1r4306n" alt="Jeff Koons - Rabbit (1986)"><div class="kremers">original height 1280</div></div></div>',
'<div id="10821655695" rel="http://www.tumblr.com/reblog/10821655695/RBKyq24s" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb1q8whpQ1r4306n" alt="Disabled Car Access"><div class="kremers">original height 757</div>/div></div>',
'<div id="10821572995" rel="http://www.tumblr.com/reblog/10821572995/JYWoYWR6" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb1mw5IU11r4306n" alt="Bin Bags"><div class="kremers">original height 725</div></div></div>',
'<div id="10821503505" rel="http://www.tumblr.com/reblog/10821503505/hVLYhypW" class="post photo"><div class="theImage"><img src="./Syndex_files/tumblr_lsb1k3yEsf1r4306no1_400.png" alt="Untitled"><div class="kremers">original height 326</div></div></div>'
];
$(document).ready(function() {
$('input').click(function(e){
e.preventDefault();
if (images.length > 0) {
// append first image in array to DOM
$(images[0])
.appendTo('.autopagerize_page_element')
// select img elements from appended items
.find('img').each(function(e) {
// lets hide the description as well while we're at it
$(this).parent().find('.kremers').hide();
// hide image from the DOM
$(this).hide();
// check to see if our image has been cached
// source: https://stackoverflow.com/questions/3877027/jquery-callback-on-image-load-even-when-the-image-is-cached
$(this).one('load', function() {
imageLoadHandler($(this));
}).each(function() {
if(this.complete) {
// (image is cached)
// console.log("cached");
$(this).load();
}
});
}
);
// remove first element from array
images.shift();
// update our reference to all nested images
$pageImages = $('.autopagerize_page_element img');
} else {
// disable input (jQuery 1.6+)
$(this).prop('disabled', true);
}
});
$(window).resize(function(e){
// TODO: look into throttling these calls as it doesn't need to be called so often
// potentially with the use of something like jQuery throttle / debounce
// http://benalman.com/projects/jquery-throttle-debounce-plugin/
// add your resize code here
$pageImages.each(function(){
// resize all images to browser height
$(this).height($window.height());
});
});
});
function imageLoadHandler($img){
// resize to browser window height, even images that are initially smaller than browser window height
$img.height($window.height());
/*
// OR...
// check if this image is taller than our browser window
if ($img.height() > $window.height()) {
// resize to browser window height
$img.height($window.height());
} else {
// our image is smaller than the browser height, we don't need to do anything
}
*/
// reveal the image in the DOM
// (fade in, animate in, do whatever else you want here)
$img.show();
// finally show our description again
$img.parent().find('.kremers').show();
}
</script>
</html>
精彩评论