이미지 없을 경우 대체 이미지 출력 (onerror를 쓰면서 XHTML 유효성 겁사 통과하기) > html

본문 바로가기
사이트 내 전체검색

html

이미지 없을 경우 대체 이미지 출력 (onerror를 쓰면서 XHTML 유효성 겁사 통과하기)

페이지 정보

작성자 서방님 댓글 0건 조회 152회 작성일 16-06-13 16:53

본문

출처 : http://pat.im/801


텍스트큐브에서 '블로그 아이콘 표시' 확장기능(플러그인)을 쓰면 XHTML 문법 검사에서 걸리는 항목이 생긴다. 이 확장기능이 <img> 태그에 onerror 항목을 넣어서 블로그 쪽그림(index.gif)을 찾을 수 없는 덧글에 아무개 그림을 나타내기 때문이다.

<img src="주소" alt="" width="32" height="32" onerror="this.src = '/plugins/BlogIcon/images/default.png'" /> 



  XHTML 문법은 HTML의 꾸밈 요소를 CSS나 자바스크립트에 떼어놓게 하고 있다. 텍스트큐브가 따르는XHTML 1.0 transitional 문법을 철저히 따른다면 onerror는 HTML 태그 안에 넣지 않고 자바스크립트로 넣어야 한다.

  onerror 하나 때문에 자바스크립트를 써야 하는지에 대해서는 의견이 분분하다. 텍스트큐브 게시판에서 아래 게시물을 비롯하여 onerror 문제에 관하여 논한 게시물을 볼 수 있었다.

  XHTML을 따르면 문서가 깔끔해지고 검색기가 쉽게 긁어갈 수 있는 건 좋은데, onerror 같은 항목이 하나둘이 걸린다고 큰 문제가 되지는 않는다. 그래도 웹 표준도 지키고 아무개 그림도 잘 나타내기를 바라는 이들이 꽤 있는데, 뾰족한 수는 나오지 않았나 보다.

  치프님의 텍스트큐브 onerror 로 인한 문법오류 해결처럼 <img> 안에서 onerror를 지우면 문법 검사는 통과할 수 있다. 쪽그림을 못 찾은 덧글에 X표 상자가 나오는 게 흠이다. 쪽그림이 클수록 X표 상자가 커서 보기 흉하다.

  더 찾아 보니 deute님 img에 onerror이벤트를 tag의 속성이 아닌 자바스크립트로 등록하기에 실마리가 있었다. 자바스크립트로 onerror를 끼워넣는 방법이 인터넷 탐색기(IE)와 다른 웹 탐색기가 서로 다르다. 웹 표준을 따르는 웹 탐색기들은 객체.onerror에 넣거나 addEventListener를 써서 onerror를 끼워넣을 수 있지만, IE 8 이하는 addEventListener는 쓸 수 없고 attachEvent를 쓴다. deute님의 예제를 따른다면 이런 스크립트를 붙여서 쪽그림에 onerror를 넣을 수 있을 것이다.


<script type="text/javascript">
<!--
var imgs = document.getElementsByTagName('img');
for(var i=0;i<imgs.length;++i) {
if(imgs[i].className === 'blogIcon') {
if(navigator.userAgent.indexOf("MSIE ")>-1) {
imgs[i].attachEvent("onerror",function(e) { e.srcElement.src ="/plugins/BlogIcon/images/default.png"; } // IE

} else {
imgs[i].onerror = function(e) { e.target.src = '/plugins/BlogIcon/images/default.png';}; // FireFox, chrome, Opera, ...
}
}
}
//-->
</script>



  그런데 이 스크립트를 텍스트큐브에 넣었을 때 IE에서 잘 되지 않았다. deute님의 예제에서는 스크립트가 하나만 있어서 문제가 없었지만, IE 8 이하에서 다른 자바스크립트가 함께 들어 있으면 어디서 엉키는지 몰라도 아무개 그림이 잘 나오지 않는다. 다른 웹 탐색기들은 별다른 문제가 없었다. IE 8이하에서는 <img> 안에 onerror를 넣어야 아무개 그림을 잘 나타낼 수 있었다.

  그래서 확장기능의 index.php를 아래처럼 IE 8 이하에서는 <img> 안에 onerror를 넣고, 나머지 웹 탐색기들은 addEventListener로 onerror를 넣도록 바꾸었다.

<?php
function BlogIcon_main($target, $mother) {

....

if ($mother['secret'] == 1) {
if (empty($mother['homepage'])) {
$imageStr = "<img src="\"{$pluginURL}/images/secret.png\" alt=\"\" width=\"{$ico_size}\" height=\"{$ico_size}\" />";
} else {
$slash = ($mother['homepage']{strlen($mother['homepage']) - 1} == '/' ? '' : '/');
preg_match("/(?P<name>\w+) (?P<version>\d+)/", $_SERVER['HTTP_USER_AGENT'], $browser);
if($browser['name'] == "MSIE" /*&& $browser['version'] < 9*/) $onerror = "onerror=\"this.src = '{$pluginURL}/images/secret.png'\""; else $onerror = "";
$imageStr = "<img class=\"blogIcon_secret\" src="\"{$mother['homepage']}{$slash}index.gif\" alt=\"\" width=\"{$ico_size}\" height=\"{$ico_size}\" {$onerror} />";
}
} else {
if (empty($mother['homepage'])) {
$imageStr = "<img src="\"{$pluginURL}/images/default.png\" alt=\"\" width=\"{$ico_size}\" height=\"{$ico_size}\" />";
} else {
$slash = ($mother['homepage']{strlen($mother['homepage']) - 1} == '/' ? '' : '/');
preg_match("/(?P<name>\w+) (?P<version>\d+)/", $_SERVER['HTTP_USER_AGENT'], $browser);
if($browser['name'] == "MSIE" /*&& $browser['version'] < 9*/) $onerror = "onerror=\"this.src = '{$pluginURL}/images/default.png'\""; else $onerror = "";
$imageStr = "<img class=\"blogIcon\" src="\"{$mother['homepage']}{$slash}index.gif\" alt=\"\" width=\"{$ico_size}\" height=\"{$ico_size}\" {$onerror} />";
}
}

return "{$imageStr} {$target}";
}

function BlogIcon_script($target) {
preg_match("/(?P<name>\w+) (?P<version>\d+)/", $_SERVER['HTTP_USER_AGENT'], $browser);
if($browser['name'] == "MSIE" && $browser['version'] < 9) return $target;

global $pluginURL; $script = "<script type=\"text/javascript\">".CRLF;

$script .= "<!--".CRLF;
$script .= " var imgs = document.getElementsByTagName('img');".CRLF;
$script .= " for(var i=0;i<imgs.length;++i) {".CRLF;
$script .= " if(imgs[i].className === 'blogIcon') {".CRLF;
$script .= " imgs[i].addEventListener('error', function(e) {e.target.src = '{$pluginURL}/images/default.png';}, false);".CRLF;
$script .= " }".CRLF;
$script .= " else if(imgs[i].className === 'blogIcon_secret') {".CRLF;
$script .= " imgs[i].addEventListener('error', function(e) {e.target.src = '{$pluginURL}/images/secret.png';}, false);".CRLF;
$script .= " }".CRLF;
$script .= " }".CRLF; $script .= "//-->".CRLF;
$script .= "</script>".CRLF; return $target.CRLF.$script;
}

....



  index.xml의 <binding>과 </binding> 사이에 다음 한 줄을 끼워넣어서 새로 넣은 BlogIcon_script()의 내용이 </body> 앞에 출력되게 한다.

<tag name="SKIN_body_end" handler="BlogIcon_script" />



  이렇게 하면 아무개 그림도 잘 나오고 XHTML 문법 검사도 통과할 수 있다. 그래도 IE 8 이하에서는 HTML 안에 onerror가 들어가니 이 방법은 꼼수일 수밖에 없다. 아직 눈으로 확인하지 않았지만 IE 9부터는 addEventListener를 쓸 수 있다고 하니 IE 8까지만 예외로 하면 될 것 같다.

바꾼 내역

  • 텍스트큐브 자료실에 개선판을 올렸습니다. (2011.4.28)
  • IE 9도 IE 8 이하와 다르지 않음을 뒤늦게 발견하고, IE에서 판 번호 구분 없이 동작하도록 고쳐 올립니다. (2011.10.18)
  • 여러 웹 누비개들에서 addEventListener로 넣는 방법이 통하지 않아서 객체.onerror로 넣도록 자바스크립트를 고쳤습니다. (IE만 HTML 태그로 넣음) (2013.12.14)
  • 불여우(Firefox)도 IE처럼 HTML 태그로 onerror 속성을 넣게 했습니다. (2013.12.18)
 BlogIcon_1.3.3_for_TC1.8.zip

블로그 아이콘 플러그인 수정판 1.3.3 (2013.12.18)

 index.xml.zip

텍스트큐브 1.8 이전판을 위한 index.xml 파일

댓글목록

등록된 댓글이 없습니다.

Total 323건 5 페이지
게시물 검색

회원로그인

접속자집계

오늘
79
어제
84
최대
1,347
전체
154,450
Latest Crypto Fear & Greed Index

그누보드5
Copyright © 서방님.kr All rights reserved.