hschoidr / vsns

Dev.Study - Official VSNS Repository since 2013.9.1
http://vsns.ror.la
0 stars 0 forks source link

WMD Editor Turbolink 문제 #1

Open junheon opened 11 years ago

junheon commented 11 years ago

안녕하세요. WMD Editor turbo link 진입시 생성이 안되는 문제에 대해 남깁니다.

우선 제가 작업해본 코드는 아래와 같습니다. 필요하다면 나중에 pull request를 해볼수도 있을거 같습니다~

// editor.js

var initializeWMDEditor = function () {
  new WMDEditor({
    input: "item_description",
    button_bar: "editor-button-bar",
    preview: "editor-preview",
    output: "editor-output"
  });

  $(".wmd-help-button").html("<a id='markdown-help-link'></a>");

  $("#markdown-help-link").click(function(){
    $("#editor-help-panel").slideToggle('fast');

    return false;
  });
};

$(function () { // dom ready
  initializeWMDEditor();
});

// Turbolink 이벤트를 통한 처리
$(document).on('page:load', initializeWMDEditor);

wmdEditor를 initialize하는 function을 별도로 분리하고 dom ready 되었을때와 turbolink의 page:load 이벤트에 둘다 걸어줬습니다.

turbolink로 화면 전환시 화면의 변경사항에 해당하는 dom만 업데이트 해주기 때문에 domready에 실행되는 자바스크립트는 실행되지 않습니다.

따라서 page:load 이벤트에 bind 시켜줘야 합니다.

// application.js

//= require jquery
//= require jquery_ujs
//= require jquery.ui.all
//= require jquery.pageless
//= require jquery.tokeninput
//= require twitter/bootstrap
//= require bootstrap
//= require bootstrap-tagsinput
//= require slimbox2.min
//= require wmd/wmd
//= require wmd/showdown
//= require items
//= require comments
//= require communities
//= require turbolinks
//= require_tree .

jQuery turbolink를 제외하고 require_tree .을 추가했습니다.

특별히 require_tree . 을 제외하고 nested layout에서 script 를 추가한 이유가 궁금합니다. 우선은 application.js 로 묶어놓고 페이지가 일반적인 request/response로 렌더링시 domready 이벤트에서 wmd editor가 생성되게 되고 turbo link page:load 발생시 또한 해당 initailzeWMDEditor가 실해되게 됩니다. 불필요한 자바스크립트 실행을 막고 싶다면 initializeWMDEditor에서 wmdEditor를 bind할 dom 존재 여부를 파악하면 될거 같습니다.

jquery turbolink를 제거한 이유는 jquery turbolink와 turbolink 두가지 모두 들어가 있어 page:load 이벤트가 double bind 되기 때문입니다.

...
 *= require_self
 *= require jquery.ui.all
 *= require slimbox2
 *= require bootstrap_and_overrides
 *= require bootstrap-tagsinput
 *= require token-input
 *= require token-input-facebook
 *= require items
 *= require comments
 *= require communities
 *= require customized
 *= require ie
 *= require screen
 *= require_tree .
...

스타일시트 역시 상기 문제와 비슷한 이유로 nested layout에서 제거하고 require_tree . 으로 묶었습니다.

그리고 views/layouts/item.html.erb를

<%= content_for :head do %>
  <%= javascript_include_tag 'editor' if action_name.in?(['new','edit']) %>
  <%= stylesheet_link_tag 'editor' if action_name.in?(['new','edit']) %>
<% end %>

<%= render template: "layouts/two_columns" %>

에서

<%= render template: "layouts/two_columns" %>

로 변경하였고요.

javascript, css는 최대한 하나로 묶이는게 좋고 한번에 로드되는게 좋습니다.

이미 한번 로드된 상태에서 turbo link의 page:load에 대해 추가적인 이벤트를 실행시켜주는것이고요. 로드 시점에 불필요한 자바스크립트 function call을 맊으려면 dom 존재 여부를 파악하면 됩니다. 예를들어

...
if ($('#selector').length) {
   // 구문 실행
}
...
hschoidr commented 11 years ago

wmd editor에서 사용하는 자바스크립트에서 에디터 생성시 연결되는 dom 객체가 없으면 스크립트 에러 발생합니다. 그래서 item 입력 폼에서만 edtor.js를 인크루드 하려는 시도를 한 것이죠. 마크다운 태그가 포함된 내용을 보여 줄때는 showdown.js 가 필요한데 이것은 application.js 에 포함시켰습니다. 이런 연유로 복잡한 작업을 했었죠. 다른 해결책이 있다면 좋겠지만 말이죠.

hschoidr commented 11 years ago

마지막에 언급해 주신 dom 객채 확인법이 해결책이 될 수 있겠네요. 그동안 turbolinks에 대한 사용법을 잘 몰라 애먹었었는데 이번에 많은 것을 배웠습니다. 감사합니다.