跳至主要內容

jjs

function createJApp(setting = {}){
    const _root = setting.root ? setting.root : document;
    const data = {};
    const registeredApps = {};
    const storagePrefix = "jData-";
    let els = prepareEls();

    function setData(key,value, toUpdateViewAndStorage = 1){
        if(getData(key) == value)return;
        data[key] = value;

        if(!toUpdateViewAndStorage)return;
        sessionStorage.setItem(storagePrefix + key,JSON.stringify(value));
        updateView(key);
    }
 
    function getData(key){
        return data[key];
    }

    function prepareEls(){
            let obj = {
                htmlEls:{},
                checkedIfEls:{},
                disabledIfEls:{},
                showIfEls:{},
                showFlexIfEls:{},
                styleEls:{},
                classEls:{},
                modelEls:{},
            };

            const htmlAttrKey = "j-html";
            const htmlEls = _root.querySelectorAll(`[${htmlAttrKey}]`);
            htmlEls.forEach(htmlEl => {
                const attributeValue = htmlEl.getAttribute(htmlAttrKey);
                obj.htmlEls[attributeValue] = _root.querySelectorAll(`[${htmlAttrKey}="${attributeValue}"]`);
            })

            const checkedIfAttrKey = "j-checked-if";
            const checkedIfEls = _root.querySelectorAll(`[${checkedIfAttrKey}]`);
            checkedIfEls.forEach(checkedIfEl => {
                const attributeValue = checkedIfEl.getAttribute(checkedIfAttrKey);
                obj.checkedIfEls[attributeValue] = _root.querySelectorAll(`[${checkedIfAttrKey}="${attributeValue}"]`);
            })

            const disabledIfAttrKey = "j-disabled-if";
            const disabledIfEls = _root.querySelectorAll(`[${disabledIfAttrKey}]`);
            disabledIfEls.forEach(disabledIfEl => {
                const attributeValue = disabledIfEl.getAttribute(disabledIfAttrKey);
                obj.disabledIfEls[attributeValue] = _root.querySelectorAll(`[${disabledIfAttrKey}="${attributeValue}"]`);
            })

           
            const showIfAttrKey = "j-show-if";
            const showIfEls = _root.querySelectorAll(`[${showIfAttrKey}]`);
            showIfEls.forEach(showIfEl => {
                const attributeValue = showIfEl.getAttribute(showIfAttrKey);
                obj.showIfEls[attributeValue] = _root.querySelectorAll(`[${showIfAttrKey}="${attributeValue}"]`);
            })

            const showFlexIfAttrKey = "j-show-Flex-if";
            const showFlexIfEls = _root.querySelectorAll(`[${showFlexIfAttrKey}]`);
            showFlexIfEls.forEach(showIfEl => {
                const attributeValue = showIfEl.getAttribute(showFlexIfAttrKey);
                obj.showFlexIfEls[attributeValue] = _root.querySelectorAll(`[${showFlexIfAttrKey}="${attributeValue}"]`);
            })

            const styleAttrKey = "j-style";
            const styleEls = _root.querySelectorAll(`[${styleAttrKey}]`);
            styleEls.forEach(styleEl => {
                const attributeValue = styleEl.getAttribute(styleAttrKey);
                obj.styleEls[attributeValue] = _root.querySelectorAll(`[${styleAttrKey}='${attributeValue}']`);
            })

            const classAttrKey = "j-class";
            const classEls = _root.querySelectorAll(`[${classAttrKey}]`);
            classEls.forEach(classEl => {
                const attributeValue = classEl.getAttribute(classAttrKey);
                obj.classEls[attributeValue] = _root.querySelectorAll(`[${classAttrKey}='${attributeValue}']`);
            })

            const modelAttrKey = "j-model";
            const modelEls = _root.querySelectorAll(`[${modelAttrKey}]`);
            modelEls.forEach(modelEl => {
                const attributeValue = modelEl.getAttribute(modelAttrKey);
                obj.modelEls[attributeValue] = _root.querySelectorAll(`[${modelAttrKey}='${attributeValue}']`);
            })

            for (const [key, app] of Object.entries(registeredApps)) {
                const attributeKey = "j-" + key;
                obj[attributeKey] = _root.querySelectorAll(`[${attributeKey}]`);
            }
            return obj;
        }
       
        function findAllIndexesOfSubstring(str, subStr) {
            const indices = [];
            let startIndex = 0;
            const subStrLength = subStr.length;

            while ((startIndex = str.indexOf(subStr, startIndex)) !== -1) {
                indices.push(startIndex);
                startIndex += subStrLength;
            }
           
            return indices;
        }

        function breakByString(s){
            let stringIndeicis = findAllIndexesOfSubstring(s,"`");
           
            const sil = stringIndeicis.length;
            if(sil % 2 != 0){
                throw new Error(s + " is missing a quote as a string!");
            }
           
            let currentIndex = 0;
            const result = [];
            for(let i = 0; i < sil; i++){
                let endIndex = stringIndeicis[i];
                let sub;
                if( i%2 == 0){
                    sub = s.substring(currentIndex,endIndex);
                    currentIndex = endIndex;
                }else{
                    sub = s.substring(currentIndex,endIndex+1);
                    currentIndex = endIndex+1;
                }
                result.push(sub);
            }
            result.push(s.substring(currentIndex));
            return result;
        }

       
        function prepareEvalStatement(s){
            const seperatedString = breakByString(s);
            for(let i = 0; i < seperatedString.length; i += 2){
               seperatedString[i] = seperatedString[i].replaceAll("#", "data.");
            }
            return seperatedString.join("");
        }

        const internalApps = {
            appHtml(){
                for (const [key, elNodes] of Object.entries(els.htmlEls)) {
                    elNodes.forEach(el => {
                        el.innerHTML = eval(prepareEvalStatement(key));                        
                    })
                }
            },
            appCheckedIf(){
                for (const [key, elNodes] of Object.entries(els.checkedIfEls)) {
                    elNodes.forEach(el => {
                        el.checked = eval(prepareEvalStatement(key));
                    })
                }
            },
            appDisabledIf(){
                for (const [key, elNodes] of Object.entries(els.disabledIfEls)) {
                    elNodes.forEach(el => {
                        el.disabled = eval(prepareEvalStatement(key));
                    })
                }
            },
            appShowIf(){
                for (const [key, elNodes] of Object.entries(els.showIfEls)) {
                    elNodes.forEach(el => {
                        el.style.display = eval(prepareEvalStatement(key)) ? "block" : "none";
                    })
                }
            },
            appShowFlexIf(){
                for (const [key, elNodes] of Object.entries(els.showFlexIfEls)) {
                    elNodes.forEach(el => {
                        el.style.display = eval(prepareEvalStatement(key)) ? "flex" : "none";
                    })
                }
            },
            appStyle(){
                for (const [key, elNodes] of Object.entries(els.styleEls)) {
                    elNodes.forEach(el => {
                        const tempArr = key.split(';');
                        const separator = "=";
                        tempArr.forEach(a => {
                            const index = a.indexOf(separator);
                            if (index !== -1) {
                                const style = a.slice(0, index).trim();
                                const rule = a.slice(index + separator.length).trim();
                                el.style.setProperty(style, eval(prepareEvalStatement(rule)));
                            }
                        })
                    })
                }
            },
            appClass(){
                for (const [key, elNodes] of Object.entries(els.classEls)) {
                    elNodes.forEach(el => {
                        const tempArr = key.split(';');
                        tempArr.forEach(a => {
                            const tempA = a.split('if');
                            const classMame = tempA[0].trim();
                            const rule = tempA[1];
                            const preparedRule = prepareEvalStatement(rule);
                            if(eval(preparedRule)){
                                el.classList.add(classMame);
                            }else{
                                el.classList.remove(classMame);
                            }
                        })
                    })
                }
            },
            appModel(){
                for (const [key, elNodes] of Object.entries(els.modelEls)) {
                    elNodes.forEach(el => {
                        const dataKey = el.getAttribute("j-model");  
                        el.value = eval(prepareEvalStatement(dataKey));
                        if(!el.hasInputListener){
                            el.addEventListener("input", function (e) {
                                setData(dataKey.replaceAll('#',''), e.target.value);
                            });
                            el.hasInputListener = true;
                        }
                    })
                }
            },
        }
       
        function updateView(dataKey){
            for (const [key, effect] of Object.entries(internalApps)) {
                effect();
            }
            for (const [key, app] of Object.entries(registeredApps)) {
                const {effect, deps} = app;
                const k = `j-${key}`;
                if(!dataKey || !Array.isArray(deps) || !deps.length || deps.includes(dataKey)){
                    const els = _root.querySelectorAll(`[${k}]`);
                    if(!els.length){
                        effect();
                    }else{
                        els.forEach(el => {
                            const prop = el.getAttribute(k);
                            if(key.includes('for')){
                                el.innerHTML = "";
                            }
                            effect(el, prop);
                        })
                    }
                }
            }
        }

        function useData(key,initialValue){
            setData(key,initialValue, 0);
            function setDataFunc(value){
                setData(key, value);
            }
            function getDataFunc(){
                return getData(key);
            }

            return [getDataFunc,setDataFunc];
        }

        function useApp(appName, effect, deps){
            registeredApps[appName] = {
                appName,effect,deps
            }
            els = prepareEls();
            updateView();
        }

        function setDataFromSessionStorage(){
            const dataKeys = Object.keys(data);
            dataKeys.forEach(k => {
                const sessionData = sessionStorage.getItem(storagePrefix + k);
                if(sessionData)setData(k, JSON.parse(sessionData), 0) ;
            })
        }

        function appDataReady(setting = {}){
            if(setting.useSessionStorage){
                setDataFromSessionStorage()
            }

            updateView();
        }

        return {useData, useApp, updateView, appDataReady};
}

留言

此網誌的熱門文章

What這個字怎麼念?

我在美國念大學的時候,有一次我說了這個字what,結果大家都笑了,並且之後有人為了揶揄我,還學我說what的方式。 我在台灣英文學到高中,大學學測英文滿級分,托福也考過了,卻連what一個字都念不好。 經過研究,多數美國人what是念whut,也就是嘴巴不用張大,輕輕的帶過搭u這個音。 這邊的u音是想說的but或是up裡面的u,輕輕短短的。 What不要念成whaaat,這邊的a不是"阿",嘴巴張大大的哦。是u像是but。

英文逐步口譯筆記經驗談

這篇文章是我自己在擔任口譯時做筆記的經驗。 逐步口譯筆記重要性 很重要,長逐步口譯,當講者語畢,實際上只能看著筆記要點翻譯,根本不可能回想,講者剛剛說了甚麼,如果筆記沒記到,很有可能會漏翻。 大量符號 長逐步口譯筆記主要使用自己習慣的符號,或是上場前準備時,就先預設一些符號。 轉折語氣別忘記 有時候講者在表述一個論點時,會先以反向論點開始說,然後才轉折語氣,進入重點。我自己是用 but 代表「但是」、「可是」、「然而」。 並列詞 美國人常常用並列詞,也就是列出許多例子來印證一件事。我筆記方式是用一個直線。 像是這個例子,我很喜歡動物,像是貓、狗、鳥類都喜歡。 數字筆記訣竅 聽到當下要用要翻成的語言做筆記,例如 130 thousand,直接記13W。 常用記號

Cors 基礎設定

建立一個 API 伺服器要設定 Access-Control-Allow-Origin,這樣別的網站才能呼叫, Koa  如果適用 Koa,只要做一個 mideleware 設定即可。 app.use(async (ctx, next) => { ctx.set('Access-Control-Allow-Origin', '*'); await next(); }); Express app.use(async (ctx, next) => { res.set('Access-Control-Allow-Origin', '*') }); 如果只允許一個網域呼叫 將 * 換成該網域即可。 如果允許多個網域呼叫 使用 Swich 的方式,先讀取前端傳來得 headers.origin 來決定設定的 access 即可。3 其他設定 另外,還有 Access-Control-Allow-Methods 跟  Access-Control-Allow-Headers 可以設定,舉例來說,最近我做了一個 Koa.js 應用程式,就要設定 Access-Control-Allow-Headers 包括 content-type 才能傳送 post 請求。