0.8.4 • Published 1 year ago

fxdom v0.8.4

Weekly downloads
131
License
MIT
Repository
github
Last release
1 year ago

FxDOM

HTML DOM Bindings for the FxJS

Selector

<div class="container div1" active="true">
  <ul class="list1">
    <li class="item1">1</li>
    <li class="item2">2</li>
    <li class="item3">3</li>
  </ul>
  <div class="div2" active="true">
    <ul class="list2">
      <li class="item4">4</li>
      <li class="item5">5</li>
    </ul>
  </div>
</div>

$, $.all

$document.querySelector를 사용하고 $.alldocument.querySelectorAll을 사용합니다.

console.log($(".container li"));
// li.item1

console.log($.all(".container li"));
// NodeList(5) [li.item1, li.item2, li.item3, li.item4, li.item5]

$.find, $.findAll

$.findel.querySelector를 사용하고 $.findAllel.querySelectorAll을 사용합니다.

console.log($.find("li", $(".container div")));
// li.item4

console.log($.findAll("li", $(".container div")));
// NodeList(2) [li.item4, li.item5]

console.log($.find("li", $(".container")));
// li.item1

console.log($.findAll("li", $(".container")));
// NodeList(5) [li.item1, li.item2, li.item3, li.item4, li.item5]

console.log($.findAll("ul li", $(".container")));
// NodeList(5) [li.item1, li.item2, li.item3, li.item4, li.item5]

el.querySelectorel.querySelectorAll의 아쉬운점

el.querySelectorel.querySelectorAll의 경우는 셀렉터의 시작으로 >를 사용할 수 없습니다.

try {
  document.querySelector(".container").querySelectorAll("> ul li");
} catch (e) {
  console.log(e);
  // DOMException: Failed to execute 'querySelectorAll' on 'Element': '> ul li' is not a valid selector.
}

el.querySelectorel.querySelectorAll의 경우는 셀렉터의 시작이 부모도 포함하고, 자식요소도 포함한다는 점을 유의해야합니다.

console.log(
  document.querySelector(".container").querySelectorAll("[active=true] > ul li")
);
// NodeList(5) [li.item1, li.item2, li.item3, li.item4, li.item5]

with >, with &

아래 예제는 $.find, $.findAllel.querySelectorel.querySelectorAll의 차이를 보여줍니다.

  • $.find, $.findAll>를 셀렉터의 시작으로 사용할 수 있습니다.
  • &를 통해 부모 element에 대해서만 추가 조건을 붙일 수 있습니다.
console.log($.findAll("> ul li", $(".container")));
// NodeList(5) [li.item1, li.item2, li.item3]

console.log($.findAll('&[active="true"] li', $(".container")));
// NodeList(5) [li.item1, li.item2, li.item3, li.item4, li.item5]

console.log($.findAll('&[active="true"] > ul li', $(".container")));
// NodeList(5) [li.item1, li.item2, li.item3]

console.log($.findAll('&[active="false"] li', $(".container")));
// NodeList() []

\$.closest

자신을 포함하여 셀렉터와 매칭되는 부모 엘리먼트를 찾습니다.

console.log($.closest("li", $(".item4")));
// li.item4

console.log($.closest("ul", $(".item4")));
// ul.list2

console.log($.closest("div", $(".item4")));
// div.div2

console.log($.closest("div.container", $(".item4")));
// div.container.div1

\$.children

\$.prevAll

\$.nextAll

\$.prev

\$.next

\$.siblings

\$.is

첫 번째 인자에 전달된 셀렉터와 매칭이 되는지 확인합니다.

console.log($.is(".item1", $("li:nth-child(1)")));
// true

console.log($.is(".item1", $("li:nth-child(2)")));
// true

\$.contains

Create

\$.els

console.log($.els('<span class="s1">1</span>'));
// HTMLCollection(2) [span.s1]

console.log($.els('<span class="s1">1</span><span class="s2">2</span>'));
// HTMLCollection(2) [span.s1, span.s2]

\$.el

console.log($.el('<span class="s1">1</span>'));
// span.s1

console.log($.el('<span class="s1">1</span><span class="s2">2</span>'));
// span.s1

Manipulation

\$.appendTo

$.appendTo($(".comments"), $.el('<div class="comment">새 댓글</div>'));

\$.prependTo

$.prependTo($(".posts"), $.el('<div class="post">새 글</div>'));

\$.append

$.append($.el('<div class="comment">새 댓글</div>'), $(".comments"));

\$.prepend

$.prepend($.el('<div class="post">새 글</div>'), $(".posts"));

\$.before

\$.insertBefore

\$.after

\$.insertAfter

\$.replaceAll

\$.replaceWith

\$.remove

$.remove($(".post"));

\$.text

console.log($.text($.el("<div>hi</div>")));
// "hi"

\$.setText

console.log($.setText("ho", $.el("<div></div>")));
// HTMLDivElement <div>ho</div>

\$.html

console.log($.html($.el("<div><span>hi</span></div>")));
// "<span>hi</span>"

\$.setHTML

console.log($.setHTML("<span>ho</span>", $.el("<div></div>")));
// HTMLDivElement <div><span>ho</span></div>

\$.outerHTML

console.log($.outerHTML($.el("<div><span>hi</span></div>")));
// "<div><span>hi</span></div>"

\$.setOuterHTML

let el = $("#div1");
$.setOuterHTML('<div id="div1" class="hi2"></div>', el);
console.log($("#div1"));
// HTMLDivElement <div id="div1" class="hi2"></div>

\$.val

console.log($.val($.el('<input type="text" value="hoho">')));
// "hoho"

\$.setVal

console.log($.setVal("hoho", $.el('<input type="text">')).value);
// "hoho"

\$.attr

console.log($.attr("type", $.el('<input type="text" value="hoho">')));
// "text"

\$.setAttr

console.log($.setAttr({ status: "ho" }, $.el('<div status="hi">')));
// HTMLDivElement <div status="ho"></div>
console.log(
  $.setAttr({ status: "ho", class: "ye" }, $.el('<div status="hi">'))
);
// HTMLDivElement <div status="ho" class="ye"></div>
console.log($.setAttr(["status", "ho"], $.el('<div status="hi">')));
// HTMLDivElement <div status="ho"></div>
console.log($.setAttr({ status: "" }, $.el('<div status="hi">')));
// HTMLDivElement <div status></div>

\$.removeAttr

console.log($.removeAttr("status", $.el('<div status="hi">')));
// HTMLDivElement <div></div>

\$.prop

\$.setProp

\$.removeProp

CSS

\$.addClass

console.log($.addClass("selected", $.el("div")));
// HTMLDivElement <div class="selected"></div>
console.log($.addClass("hi ho", $.el("div")));
// HTMLDivElement <div class="hi ho"></div>
console.log($.addClass("hi", $.el('<div class="ye">')));
// HTMLDivElement <div class="ye hi"></div>

\$.removeClass

console.log($.removeClass("selected", $.el('<div class="selected"></div>')));
// HTMLDivElement <div class></div>
console.log($.removeClass("hi ho", $.el('<div class="hi ho"></div>')));
// HTMLDivElement <div class></div>
console.log($.removeClass("hi", $.el('<div class="ye hi">')));
// HTMLDivElement <div class="ye"></div>

\$.toggleClass

console.log($.toggleClass("selected", $.el('<div class="selected"></div>')));
// HTMLDivElement <div class></div>

console.log($.toggleClass("selected", $.el("<div></div>")));
// HTMLDivElement <div class="selected"></div>

\$.hasClass

console.log($.hasClass("selected", $.el('<div class="selected"></div>')));
// true

console.log($.hasClass("a", $.el('<div class="b"></div>')));
// false

\$.css

\$.setCss

\$.show

\$.hide

\$.toggle

\$.offset

console.log(
  $.offset(
    $.append(
      $("body"),
      $.setCss(
        {
          position: "absolute",
          top: "20px",
          left: "30px",
          "margin-top": "50px",
        },
        $.el("div")
      )
    )
  )
);
// { top: 70, left: 30 }

\$.offsetParent

\$.position

\$.width

width

\$.height

height

\$.innerWidth

width + paddingLeft + paddingRight + borderLeft + borderRight

\$.innerHeight

height + paddingTop + paddingBottom + borderTop + borderBottom

\$.outerWidth

innerWidth + marginLeft + marginRight

\$.outerHeight

innerHeight + marginTop + marginBottom

\$.scrollTop

\$.scrollLeft

\$.setScrollTop

\$.setScrollLeft

Event

\$.on

$.onel.addEventListener를 대신합니다. $.on은 이벤트를 등록할 함수를 리턴하며, 커링 방식으로만 사용할 수 있습니다.

  • 인자로 받은 함수를 조작하지 않고 el.addEventListener에 그대로 적용하여, 같은 엘리먼트에 같은 이벤트와 같은 함수를 등록이 되지 않는 el.addEventListener의 특징을 그대로 유지했습니다.
  • el.addEventListenercapture, passive 등의 옵션을 사용할 수 있습니다.
  • e.preventDefault, e.stopPropagation을 사용할 수 있습니다.
  • el.removeEventListener$.off를 사용할 수 있습니다.
<button type="button" id="btn1">
  <span>btn1</span>
</button>
const addClickEvent = $.on("click", function (e) {
  console.log(e.currentTarget); // #btn1
  console.log(e.target); // span
});

addClickEvent($("#btn1"));
addClickEvent($("#btn1")); // 두 번 등록해도 추가로 등록되지 않음.
$.trigger("click", $("#btn1 span"));
// #btn1
// span

$.on의 두 번째 인자에 셀렉터를 전달하면 매칭되는 자식요소에 이벤트를 등록합니다. 이 방식은 위임 방식이 아니며, 역시 el.addEventListener의 주요 특징과 기능을 모두 사용할 수 있습니다.

<div class="articles">
  <div class="article">
    <button type="button" class="remove"><span>삭제</span></button>
  </div>
  <div class="article">
    <button type="button" class="remove"><span>삭제</span></button>
  </div>
</div>
const Articles = {
  addEvents: pipe(
    $.on("click", ".article:nth-child(1)", function (e) {
      console.log(e.currentTarget);
    }),
    $.on(
      "click",
      ".article",
      function (e) {
        console.log(e.currentTarget);
      },
      { capture: true }
    ),
    $.on("click", ".remove", function (e) {
      console.log("other_data:", e.other_data);
      console.log(e.currentTarget);
    })
  ),
};

Articles.addEvents($(".articles"));

$.trigger("click", $(".articles .article:nth-child(1) .remove")); // 한 번만 실행
// other_data: undefined
// button.remove
// div.article

$.trigger("click", $(".articles .article:nth-child(2) .remove"));
// div.article
// other_data: undefined
// button.remove

$.append(
  $(".articles"),
  $.el(`
  <div class="article new">
    <button type="button" class="remove"><span>삭제</span></button>
  </div>
`)
);

Articles.addEvents($(".articles"));

$.trigger("click", $(".articles .article:nth-child(1) .remove")); // 한 번만 실행
// other_data: undefined
// button.remove
// div.article

$.trigger("click", $(".articles .article:nth-child(3) .remove"));
// div.article.new
// other_data: undefined
// button.remove

$.trigger(
  "click",
  { other_data: "hi" },
  $(".articles .article:nth-child(3) .remove")
);
// div.article.new
// other_data: hi
// button.remove

\$.off

$.on에 전달한 모든 인자를 동일하게 전달하여 이벤트를 지울 수 있습니다.

<button type="button" id="btn2"></button>
const eventArgs = [
  "click",
  function () {
    console.log("hi~");
  },
];
$.on(...eventArgs)($("#btn2"));
$.off(...eventArgs)($("#btn2"));
$.trigger("click", $("#btn2"));
// nothing

\$.delegate

이벤트 위임 방식으로 이벤트를 등록합니다. 이벤트를 등록하고자 하는 엘리먼트가 동적으로 간편하게 이벤트를 등록해둘 수 있습니다.

<div class="users"></div>
go(
  $(".users"),
  $.delegate("click", ".remove", function () {
    console.log("remove user");
  })
);

$.append(
  $(".users"),
  $.el(`
  <div class="user new">
    <button type="button" class="remove"><span>삭제</span></button>
  </div>
`)
);

$.trigger("click", $(".users .remove"));
// remove user

이벤트 위임 방식은 아래와 같은 옵션들을 사용할 필요가 없는 상황에 한하여 사용하는 것을 권장합니다.

  • el.addEventListenercapture, passive 등의 옵션을 사용할 수 없습니다.
  • e.preventDefault, e.stopPropagation을 사용할 수 없습니다.
  • el.removeEventListener$.off를 사용할 수 없습니다.
  • mouseleave, mouseenter는 정상 동작하지 않습니다.

don.js에서는 이벤트 위임 방식에서 위 기능들을 모두 구현하여 제공했지만, 사실상 브라우저의 이벤트에 대한 모든 동작을 라이브러리 위에 다시 구현하는 장황한 코드들이 필요하며, 경험상 그 실용성이 떨어진다고 생각하여 FxDOM은 해당 기능을 구현하지 않는 컨셉으로 가고자 합니다.

\$.delegate + & 응용

<div class="signup" agree="false">
  <input type="checkbox" />
  <button type="button">가입</button>
</div>
go(
  $(".signup"),
  $.delegate("change", "input", function (e) {
    $.setAttr({ agree: e.currentTarget.checked }, e.delegateTarget);
  }),
  $.delegate("click", '&[agree="false"] button', function () {
    console.log("동의해주세요!");
  }),
  $.delegate("click", '&[agree="true"] button', function () {
    console.log("감사합니다!");
  })
);

$.trigger("click", $(".signup button"));
// 동의해주세요!
$.trigger("click", $(".signup input"));
$.trigger("click", $(".signup button"));
// 감사합니다!

\$.ready

Data

$.data, $.setData

<div class="item" data-fx-json='{"id": 1, "active": true}'></div>
<div class="item2"></div>
const { id, active } = $.data($(".item"));
console.log(id, active);
// 1 true

const data = $.data($.setData({ id: 1, active: false }, $(".item")));
console.log(data.active);
// false
data.active = true;
console.log($.data($(".item")).active);
// true

\$.dataStr

const data = { id: 1, active: true };
const item = document.createElement(
  `<div class="item" data-fx-json="${$.dataStr(data)}">`
);

const { id, active } = $.data(item);
console.log(id, active);
// 1 true

Fetch

$.get, $.post, $.put, $.deleteContent-Typeapplication/json으로 설정되어있으며 응답이 오면 JSON 객체를 반환합니다. 4개 함수 모두 필요 인자는 2개 이상이며, 인자를 1개만 전달하면 함수를 리턴합니다.

\$.get

$.get("/api/posts", { offset: 0, limit: 10 }); // GET '/api/posts?offset=0&limit10'
// Promise [{id: 1, ...}, {id: 2, ...}, ...]

\$.post

$.post("/api/posts", { content: "ho~" }); // POST /api/posts, BODY { content: 'ho~' }
// Promise {id:1, content: 'ho', created_at: ... }

\$.put

$.put(`/api/posts/${post.id}`, post); // PUT /api/posts/1, BODY { id: 1, ... }
// Promise {id:1, content: 'ho', updated_at: ... }

\$.delete

$.delete(`/api/posts/${post.id}`, undefined); // DELETE /api/posts/1
0.8.4

1 year ago

0.8.3

4 years ago

0.8.2

4 years ago

0.8.1

4 years ago

0.8.0

4 years ago

0.7.3

4 years ago

0.7.2

4 years ago

0.7.1

4 years ago

0.7.0

4 years ago

0.6.5

4 years ago

0.6.4

4 years ago

0.6.3

4 years ago

0.6.2

4 years ago

0.6.1

4 years ago

0.6.0

4 years ago

0.5.4

5 years ago

0.5.3

5 years ago

0.5.2

5 years ago

0.5.1

5 years ago

0.5.0

5 years ago

0.4.1

5 years ago

0.4.0

5 years ago

0.3.0

5 years ago

0.3.1

5 years ago

0.2.1

5 years ago

0.2.0

6 years ago

0.1.0

6 years ago

0.0.17

6 years ago

0.0.16

6 years ago