2008-10-13 24 views
14

Tôi có một thẻ img trong webapp của tôi có sử dụng các handler onload thay đổi kích thước hình ảnh:img onload không hoạt động tốt trong IE7

<img onLoad="SizeImage(this);" src="foo" > 

này hoạt động tốt trong Firefox 3, nhưng thất bại trong IE7 vì đối tượng hình ảnh được chuyển đến hàm SizeImage() có chiều rộng và chiều cao bằng 0 vì một số lý do - có thể IE gọi hàm trước khi nó tải xong ?. Trong nghiên cứu này, tôi đã phát hiện ra rằng những người khác đã có cùng một vấn đề với IE. Tôi cũng đã phát hiện ra rằng đây không phải là HTML hợp lệ 4. Đây là loại tài liệu của chúng tôi, vì vậy tôi không biết nếu nó là hợp lệ hay không:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

Có một giải pháp hợp lý cho thay đổi kích thước một hình ảnh khi nó được tải tốt nhất là phù hợp với tiêu chuẩn? Hình ảnh đang được sử dụng để người dùng tải lên ảnh của chính họ, có thể có kích thước gần như bất kỳ và chúng tôi muốn hiển thị hình ảnh ở mức tối đa 150x150. Nếu giải pháp của bạn là thay đổi kích thước hình ảnh phía máy chủ khi tải lên, tôi biết đó là giải pháp đúng, nhưng tôi bị cấm thực hiện nó: (Phải được thực hiện phía máy khách và phải được thực hiện trên màn hình.

Chỉnh sửa: Do cấu trúc của ứng dụng của chúng tôi, không thực tế (có thể xảy ra tiếp cận) để chạy tập lệnh này trong tài liệu đang tải. Tôi chỉ có thể chỉnh sửa hợp lý thẻ hình ảnh và mã gần đó (cho Ví dụ, tôi có thể thêm một <script> ngay bên dưới nó) Ngoài ra, chúng tôi đã có Prototype và EXT JS thư viện ... quản lý sẽ không muốn thêm khác (một số câu trả lời đã đề nghị jQuery) .Nếu điều này có thể được giải quyết bằng cách sử dụng những khuôn khổ, điều đó thật tuyệt vời.

Chỉnh sửa 2: Thật không may, chúng tôi phải hỗ trợ Firefox 3, IE 6 và IE 7. Mong muốn hỗ trợ tất cả các trình duyệt dựa trên Webkit, nhưng trang web của chúng tôi hiện không hỗ trợ chúng, chúng tôi có thể dung thứ các giải pháp chỉ hoạt động trong Big 3.

+0

Câu hỏi: được SizeImage() chỉ đơn giản là thay đổi kích thước hình ảnh để 150x150? Tôi có các giải pháp khác nhau, tốt hơn cả những giải pháp dưới đây, nhưng nó phụ thuộc vào những gì bạn cần SizeImage() để làm. –

+0

@Eric: không, nó nên giữ tỷ lệ khung hình của hình ảnh. ngoài ra, nếu hình ảnh ban đầu nhỏ hơn 150x150, không có thay đổi kích thước nào được thực hiện (tôi không bao giờ muốn kéo dài và hình ảnh). – rmeador

Trả lời

6

IE7 đang cố định lại kích thước hình ảnh trước khi cây DOM được hiển thị hoàn toàn. Bạn cần phải chạy nó trên document.onload ... bạn sẽ chỉ cần đảm bảo rằng hàm của bạn có thể xử lý được truyền tham chiếu đến phần tử không phải là "this".

Cách khác ... và tôi hy vọng đây không phải là hành vi phạm tội dễ cháy ... jQuery làm cho những thứ như thế này thực sự, thực sự dễ dàng.

EDIT để đáp ứng với SỬA 1:

Bạn có thể đặt document.onload(runFunction); trong bất kỳ thẻ kịch bản, bất cứ nơi nào trong cơ thể. nó sẽ vẫn đợi cho đến khi tài liệu được nạp để chạy hàm.

+0

thường cố gắng sửa đổi một phần của phần trước khi được tải sẽ gây ra thông báo "hoạt động bị hủy bỏ" đáng sợ. – StingyJack

+0

@Steve, làm thế nào là nó 'thực sự dễ dàng' để làm với jQuery?Tôi đang sử dụng jQuery trong dự án của tôi, nhưng điều này không dễ dàng hơn chút nào! Tài liệu của jQuery đồng ý rằng IE không xử lý onLoad một cách chính xác ngay cả với sự kiện tải jQuery/Xem [link] (http://api.jquery.com/load-event/) - đoạn "Cẩn thận của sự kiện tải khi được sử dụng với hình ảnh ". Tôi đã sử dụng jQuery nhưng vẫn phải viết cả một đoạn mã dài để hỗ trợ IE. – Fred

2

Con đường tôi sẽ làm điều đó là sử dụng jQuery để làm điều gì đó như:

$(document).load(function(){ 
    // applies to all images, could be replaced 
    //by img.resize to resize all images with class="resize" 
    $('img').each(function(){ 
     // sizing code here 
    }); 
}); 

Nhưng tôi không có chuyên môn javascript;)

7

Nếu bạn không phải hỗ trợ IE 6, bạn chỉ có thể sử dụng CSS này.

yourImageSelector { 
    max-width: 150px; 
    max-height: 150px; 
} 
+0

Đó là một ý tưởng thực sự hay ... Tôi thậm chí không biết đó là một tùy chọn CSS có sẵn. Thật không may, chúng tôi cần hỗ trợ IE6. Tôi đã cập nhật câu hỏi để đề cập đến điều đó. – rmeador

+4

Đây là cách hỗ trợ IE6: casey

1

setTimeout() có thể là một giải pháp nếu bạn thực sự bị kẹt. Chỉ cần đặt nó trong 2 hoặc 3 giây - hoặc sau khi trang được dự kiến ​​sẽ tải.

EDIT: Bạn có thể muốn xem this article - tất cả các cách ở dưới cùng về rò rỉ mem IE ...

4

Tôi đã nhận thấy rằng Firefox và Safari đều kích hoạt các sự kiện "tải" trên hình ảnh mới, nhưng IE 6 & 7 chỉ kích hoạt "tải" nếu chúng thực sự có được hình ảnh từ máy chủ - chúng không nếu hình ảnh đã có trong bộ nhớ cache cục bộ. Tôi chơi với hai giải pháp:

1) Cho hình ảnh một cuộc tranh luận http độc đáo mọi thời gian, mà máy chủ web bỏ qua, như

<img src="mypicture.jpg?keepfresh=12345" /> 

này có nhược điểm là nó thực sự đánh bại bộ nhớ đệm, vì vậy bạn lãng phí băng thông. Nhưng nó có thể giải quyết vấn đề mà không cần phải vặn với JavaScript của bạn.

2) Trong ứng dụng của tôi, hình ảnh cần xử lý tải đang được chèn động bởi JavaScript. Thay vì chỉ phụ thêm hình ảnh, sau đó xây dựng một handler, tôi sử dụng mã này, đã được kiểm nghiệm tốt trong Safari, FF, và IE6 & 7.

document.body.appendChild(newPicture); 
if(newPicture.complete){ 
    doStuff.apply(newPicture); 
}else{ 
    YAHOO.util.Event.addListener(newPicture, "load", doStuff); 
} 

Tôi đang sử dụng YUI (rõ ràng) nhưng bạn có thể tùy viên trình xử lý sử dụng bất kỳ thứ gì hoạt động trong khung công tác của bạn. Hàm doStuff hy vọng sẽ chạy với này gắn liền với phần tử IMG bị ảnh hưởng, đó là lý do tại sao tôi gọi nó theo kiểu .apply, số dặm của bạn có thể thay đổi.

+0

Cảm ơn bạn rất nhiều vì trả lời này! Tôi sẽ không bao giờ nghĩ về điều này bản thân mình! –

+0

Cảm ơn bạn. Đã gặp sự cố kích thích với trình tải tài nguyên trong trò chơi HTML5 ... (độ cao được kiểm tra> 0 thay vì hoàn thành, nhưng cùng một ý tưởng) –

1

Edit: Do cấu trúc của ứng dụng của chúng tôi, nó là không thực tế (giáp không thể) để chạy kịch bản này trong onload tài liệu của.

Bạn luôn có thể thêm trình xử lý vào window.onload (hoặc bất kỳ sự kiện nào thực sự), ngay cả khi các khung công tác khác, thư viện hoặc mã đính kèm với sự kiện đó.

<script type="text/javascript"> 
function addOnloadHandler(func) { 
    if (window.onload) { 
     var windowOnload = window.onload; 
     window.onload = function(evt) { 
      windowOnload(evt); 
      func(evt); 
     } 
    } else { 
     window.onload = function(evt) { 
      func(evt); 
     } 
    } 
} 

// attach a handler to window.onload as you normally might 
window.onload = function() { alert('Watch'); }; 

// demonstrate that you can now attach as many other handlers 
// to the onload event as you want 
addOnloadHandler(function() { alert('as'); }); 
addOnloadHandler(function() { alert('window.onload'); }); 
addOnloadHandler(function() { alert('runs'); }); 
addOnloadHandler(function() { alert('as'); }); 
addOnloadHandler(function() { alert('many'); }); 
addOnloadHandler(function() { alert('handlers'); }); 
addOnloadHandler(function() { alert('as'); }); 
addOnloadHandler(function() { alert('you'); }); 
addOnloadHandler(function() { alert('want.'); }); 
</script> 

This answer có một phiên bản hơi khác nhau của addOnloadHandler() mã của tôi sử dụng attachEvent. Nhưng tôi phát hiện ra trong thử nghiệm rằng attachEvent dường như không đảm bảo xử lý cháy theo thứ tự bạn đã thêm chúng, điều này có thể quan trọng. Chức năng như trình xử lý đảm bảo được kích hoạt theo thứ tự được thêm vào.

Lưu ý rằng tôi vượt qua evt vào trình xử lý sự kiện đã thêm. Điều này là không cần thiết và mã nên làm việc mà không có nó, nhưng tôi làm việc với một thư viện hy vọng sự kiện được chuyển đến trình xử lý onload và mã đó không thành công trừ khi tôi đưa nó vào chức năng của mình.

3

Mã cho jQuery. Nhưng thật dễ dàng để quay số với các khung công tác khác. Thực sự hữu ích.

var onload = function(){ /** your awesome onload method **/ }; 
var img = new Image(); 
img.src = 'test.png'; 

// IE 7 workarond 
if($.browser.version.substr(0,1) == 7){ 
    function testImg(){ 
     if(img.complete != null && img.complete == true){ 
      onload(); 
      return; 
     } 
     setTimeout(testImg, 1000); 
    } 
    setTimeout(testImg, 1000); 
}else{ 
    img.onload = onload 
} 
0

Bạn có thể làm một cái gì đó như:

var img = new Image(); 
img.src = '/output/preview_image.jpg' + '?' + Math.random(); 
img.onload = function() { 
    alert('pass') 
} 
Các vấn đề liên quan