UNPKG

@luketclancy/otterly

Version:

A javascript front end framework, Inspired by stimulus js. Like an otter its small, fast and versatile. Based around logical units attached to html nodes. Great for a backend-first approach to website creation.

158 lines (156 loc) 4.42 kB
import morphdom from 'morphdom' export default { init(baseElement, submitter, resolve, reject, isDev){ return {baseElement, submitter, resolve, reject, isDev, ...this} }, getThing(obj, optional = false, doc = document){ let el if(obj.id){ el = doc.getElementById(obj.id) if(!el && !optional && this.isDev){console.log('could not find object with id: ', obj.id)} } else if(obj.selector){ el = this.getSelector(obj.selector, doc) if(!el && !optional && this.isDev){console.log('could not find object with selector: ', obj.selector)} } else if(!optional && this.isDev) { console.log('expected a node identifier (either a "selector" field or an "id" field)') } return el }, getSelector(str, doc = document) { if(str == "submitter") { return this.submitter } else if (str == "baseElement") { return this.baseElement } else { return doc.querySelector(str) } }, log(obj){ console.log(obj) }, reload(){ Turbo.cache.clear() otty.goto(window.location.href, {reload: true}) // window.Turbo.visit(window.location.href, {action: 'replace'}) }, redirect(obj){ otty.goto(obj) }, insert(obj){ let sel = this.getThing(obj) if(!sel) { return } let pos = obj['position'] let html = obj['html'] sel.insertAdjacentHTML(pos, html) }, _morphOpts(opts) { //this is used externally let perm = opts['permanent'] let ign = opts['ignore'] if(opts == null) { return {} } if(ign != null || perm != null) { let m_parse_p = (selector, from, to) => { if(from.matches(selector) && to.matches(selector)) { return false } return true } let m_parse_i = (selector, from, to) => { if(from.matches(selector) || to.matches(selector)) { return false } return true } let m_parse = (selectors, inner_parse, from, to) => { if(!(Array.isArray(selectors))) { selectors = [selectors] } for(let y = 0; y < selectors.length; y++) { if(!inner_parse(selectors[y], from, to)){ return false } } return true } opts['onBeforeElChildrenUpdated'] = (from, to) => { if(! m_parse(ign, m_parse_i, from, to) ) { return false } if(! m_parse(perm, m_parse_p, from, to) ) { return false } return true } } return opts }, morph(opts) { let s = this.getThing(opts) if(!s) { return } morphdom(s, opts['html'], this._morphOpts(opts)) }, remove(obj) { let s = this.getThing(obj) if(!s) { return } s.parentNode.removeChild(s) }, replace(obj){ //this method needs more scrutiny //does not support baseElement or submitter selectors. Recommend using ids. let sel, parser, tempdoc, orienter, childrenOnly parser = new DOMParser(); tempdoc = parser.parseFromString(obj['html'], "text/html") orienter = this.getThing(obj, false, tempdoc) if(!orienter){return} childrenOnly = obj['childrenOnly'] sel = this.getThing(obj) if(!sel){return} if(orienter == null) { if(childrenOnly) { sel.innerHTML = obj['html'] } else { orienter = tempdoc.querySelector('body').children[0] sel.replaceWith(orienter) } } else { if(childrenOnly) { sel.innerHTML = orienter.innerHTML } else { sel.replaceWith(orienter) } } }, innerHtml(obj) { let s = this.getThing(obj) if(!s){return} s.innerHTML = obj['html'] }, eval2(data) { //anything weird? Just use this. You have access to anything in the hash. //selector input is special and will automatically be set to the variable referenced. //note it doesn't actually use eval for performance related reasons. Something about effects on minimization i believe. //is this a security risk? We check we are connecting with ourselves above. So should be fine let selector = getThing(data, true) //continue being insane lol let x = Function("data", "selector", 'baseElement', 'submitter', `"use strict"; ${data['code']};`)(data, selector, this.baseElement, this.submitter) if(x == "break") { //lil bit of extra awesome resolve(returning) return "break" } }, setData(data){ let keys, x, key, obj, attrs, attr_keys, y, attr_key keys = Object.keys(data) for(x = 0; x < keys.length; x++) { key = keys[x] obj = this.getSelector(key) attrs = data[key] attr_keys = Object.keys(attrs) for(y = 0; y < attr_keys.length; y++) { attr_key = attr_keys[y] obj.dataset[attr_key] = attrs[attr_key] } } } }