vladocar / femtoJS

femtoJS - Really small JavaScript (ES6) library for DOM manipulation.

Home Page:https://vladocar.github.io/femtoJS/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Idea not real issue. Feel free to close.

SaulDoesCode opened this issue · comments

Saw your project, very nice, and played with the code for a bit, I shuffled some things around and made it smaller and so there's no use of "this" (for users' convenience and preventing binding issues). Instead of checking for arrays, you can just assume a value is array like and go with it, this makes the code a bit smaller/simpler and could make it a little faster since you're not checking and converting (e.g. [...selectAll()]). Just some thoughts Good job with femto, all the best!

const func = (() => {
	const argToElements = src => {
        if (src != null) {
            if (src.isFemtoJS) return src.sel()
            if (typeof src === 'string') {
                const tagName = /^<(\w+)>$/.exec(src)
                return tagName != null
                    ? [document.createElement(tagName[1])]
                    : document.querySelectorAll(src)
            }
            if (src instanceof Element) return [src]
            if (src.length) {
                const elems = []
                for (let i = 0; i < src.length; i++) elems.push(...argToElements(src[i]))
                return elems
            }
        }

             throw new TypeError('Expected string | HTMLElement | Array | femtoJS, instead got ' + typeof src)
	}

	const $ = function () {
	const sel = argToElements(arguments)

	const iter = fn => {
            for (let i = 0; i < sel.length; i++) fn(sel[i], i)
            return O
        }

        const insertToAdjacent = s => e => iter((j, i) => i === 0 ?
            e instanceof Element ?
            e.insertAdjacentElement(s, j) :
            e.sel()[0].insertAdjacentElement(s, j) :
            sel[0].insertAdjacentElement('afterend', j))

        const insertAdjacent = s => sOrE => {
            if (typeof sOrE !== 'string') {
                if (sOrE instanceof Element) {
                    sel[0].insertAdjacentElement(s, sOrE)
                } else if (sOrE.isFemtoJS) {
                    const osel = sOrE.sel()

                    sel[0].insertAdjacentElement(s, osel[0])

                    for (let i = 1; i < osel.length; i++) {
                        osel[0].insertAdjacentElement('afterend', osel[i])
                    }
                }
            } else {
                sel[0].insertAdjacentHTML(s, sOrE)
            }

            return O
        }
    
        const O = {
			on:           (type, fn) => iter(i => i.addEventListener(type, fn)),
			off:          (type, fn) => iter(i => i.removeEventListener(type, fn)),
			css:          s => iter(i => i.style.cssText += s),
			html:         h => iter(i => i.innerHTML = h),
			text:         t => iter(i => i.innerText = t),
			addClass:     t => iter(i => i.classList.add(t)),
			toggleClass:  t => iter(i => i.classList.toggle(t)),
			removeClass:  t => iter(i => i.classList.remove(t)),
			empty:        () => iter(i => i.innerHTML = ''),
			attr:         (k, v) => iter(i => i.setAttribute(k, v)),
			removeAttr:   k => iter(i => i.removeAttribute(k)),
			parent:       () => iter((e, i) => { sel[i] = e.parentNode }),
			remove:       () => iter(i => i.remove()),

			before:       insertAdjacent('beforebegin'),
			after:        insertAdjacent('afterend'),
			first:        insertAdjacent('afterbegin'),
			last:         insertAdjacent('beforeend'),
			insertBefore: insertToAdjacent('beforebegin'),
			insertAfter:  insertToAdjacent('afterend'),
			insertFirst:  insertToAdjacent('afterbegin'),
			insertLast:   insertToAdjacent('beforeend'),

			prepend:      insertAdjacent('afterbegin'),
			append:       insertAdjacent('beforeend'),

			getAttr:      v => sel[0].getAttribute(v),
			offset:       () => sel[0].getBoundingClientRect(),
			sel:          () => sel,

			isFemtoJS: true
		}

		return O
	}

	$.fragment = () => $(document.createDocumentFragment())

	return $
})

if (typeof module === 'object' && module.exports) {
	module.exports = func()
} else if (typeof define === 'function' && define.amd) {
	const singleton = func()

	define('femtoJS', [], () => singleton)
} else {
	window.$ = func()
}

this is for convenience so you can do things like $('body').css('background-color: green;'), your code removes this functionality.

This would have been better as a pull request so I could see the changes, but nonetheless this removes the chaining functionality and features premature optimization so I'll have to reject it.

Thanks!

That's cool man, just some ideas. Wish Github had a send message/note/idea feature. Anyway, I don't think chaining is broken. $('body').css('background-color: green;') <- this should totally still work, because instead of returning this it returns the object directly (that this would have been referring to).

Sorry, maybe there was some confusion because there's no explicit return this in all the functions.
It's hidden away here:

	const iter = fn => {
            for (let i = 0; i < sel.length; i++) fn(sel[i], i)
            return O // <- object with all the methods
        }

Hmm, well it seems like I overlooked that part. Nonetheless, premature optimization isn't really the best way to go, especially when return this worked just fine. :>