npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

fxdom-test

v0.7.0

Published

HTML DOM Bindings for the [FxJS](https://github.com/marpple/FxJS)

Downloads

7

Readme

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