jQuery wrapAll() 메서드가 필요한 이유 (photoswipe.js 예제)
에디터를 통해 이미지를 업로드 하면 img 태그가 생성되어 서버로 넘겨지는 내용 string 에 포함되어 넘겨집니다.
photoswipe 를 이용해 첨부된 이미지를 갤러리처럼 보여주고 싶은데 아래의 처리가 되어야 이용 가능합니다.
1) 이미지 터치(클릭)했을 때 보여줄 원본이미지 링크를 저장할 href 속성을 a 태그에 추가
2) 이미지 터치(클릭)했을 때 보여줄 원본이미지 사이즈를 저장할 data-size 속성을 a 태그에 추가
3) img 태그를 감싸는 figure 태그 추가
* photoswipe 플러그인은 기본적으로 href 와 data-size 속성을 img 부모 노드의 앵커(a) 태그에 추가합니다. 저의 경우 a 태그 없이 figure 태그안에 위의 두가지 속성을 추가해서 사용했습니다. 이러기 위해서는 아래의 펑션에서 linkEl 에 figureEl 의 첫번째 자식 태그가 아니라 figure 엘러먼트 자체가 되도록 해 주면 됩니다.
var initPhotoSwipeFromDOM = function(gallerySelector) { ..... .....
//linkEl = figureEl.children[0]; // <a> element linkEl = figureEl; // link use figure }
생성된 img 태그를 어디서 조작할까 하다 서버측보다는 jQuery를 이용해서 결과 html 을 조작하는편이 낫겠다는 판단이 들었습니다. (PHP 통해서 서버측에서 처리하려면 DOMDocument 클래스를 이용하면 된다)
jQuery 메서드인 prepend() 또는 append() 의 경우 셀렉터 앞이나 뒤에 괄호 안에 넣은 태그가 삽입됩니다.
문제는 close 태그가 존재하는 태그를 사용한 경우 자동으로 닫혀버린다는 거죠.
<figure itemprop=”associatedMedia” itemscope=”” itemtype=”http://schema.org/ImageObject”></figure>
<img src=”http://hostname/path/file.ext” title=”1548235391-38.png” width=”” style=”height: 2568px;”>
이렇게 되면 photoswipe 에서 img 에 접근하기 어렵습니다. img 를 figure 태그 자식으로 넣기 위해서는 wrapAll 이라는 jQuery 메서드를 이용하면 된다는 군요.
[jQuery 작성]
$(window).load(function () { // 이미지 사이즈를 .ready() 안에서 받으려하면 값을 못받고 0으로 들어올 수 있으므로 .load() 안에서 처리 $(".news_article img").each(function (index, item) { // img 가로와 세로 크기 확인 후 img 태그 안에 data-size 속성 추가해 주기 (원본사이즈 얻기 위해 width, height 이 아니라 naturalWidth, naturalHeight 을 사용) const imgsize = item.naturalWidth + 'x' + item.naturalHeight; const figureElem = '<figure href="' + item.src + '" data-size="' + imgsize + '">'; $(this).wrapAll('<div>'); $(this).wrapAll(figureElem); }); });
[변환된 결과 html]
<figure href=”http://hostname/path/originfile.ext” data-size=”800×1200″>
<img src=”http://hostname/path/file.ext”>
</figure>
위의 태그조합이 이미지 갯수 만큼 반복되겠죠.
[PHP 를 통해 서버측에서 처리할 경우]
$dom = new DOMDocument(); // saveHTML() 할 때 doctype 제거하기, $contents 변수에는 에디터로 넘어온 내용 html 이 text type 으로 저장되어 있습니다. $dom->loadHTML($contents, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); foreach($dom->getElementsByTagName('img') as $img) { $createDiv = $dom->createElement('div'); $cloneDiv = $createDiv->cloneNode(); $img->parentNode->replaceChild($cloneDiv, $img); $cloneDiv->appendChild($img); // 실무에서는 이미지 링크를 통해 가로값과 세로값을 얻어서 넣어줄 것 (여기는 간략히 800x1200 으로 넣음) $createFigure = $dom->createElement('figure'); $createFigure->setAttribute("href", $img->getAttribute("src")); $createFigure->setAttribute("data-size", "800x1200"); $clone = $createFigure->cloneNode(); $img->parentNode->replaceChild($clone, $img); $img->setAttribute("data-size", "800x1200"); $clone->appendChild($img); $img->parentNode->appendChild($dom->createElement('figcaption')); }; $contents = $dom->saveHTML();
[참조 jQuery ]
https://stackoverflow.com/questions/48216205/avoid-browser-auto-close-tag-when-inserting-html-tag-with-javascript-before-firs
https://sometimes-n.tistory.com/21
[참조 PHP DOMDocument]
https://stackoverflow.com/questions/7433601/php-manipulating-html-from-string
https://stackoverflow.com/questions/18316527/php-dom-wrap-image-in-link-and-add-span-before-image-tag