import each from 'lodash-es/each.js'
import map from 'lodash-es/map.js'
import join from 'lodash-es/join.js'
import isarr from './isarr.mjs'
import isstr from './isstr.mjs'
import isfun from './isfun.mjs'
import genPm from './genPm.mjs'
import pmSeries from './pmSeries.mjs'
import waitFun from './waitFun.mjs'
import strright from './strright.mjs'
import delay from './delay.mjs'
let _paths = {}
let _pathItems = {}
function importResource({ tagName, path, attributes = {}, func }) {
//pm
let pm = genPm()
//check
if (_paths[path] === 'done') {
pm.resolve('loaded')
return pm
}
else if (_paths[path] === 'loading') {
waitFun(() => {
return _paths[path] === 'done'
})
.then(function() {
pm.resolve('loaded')
})
return pm
}
//loading
_paths[path] = 'loading'
//ele attrs
let ele = document.createElement(tagName)
each(attributes, (v, k) => {
ele.setAttribute(k, v)
})
//ele type
if (attributes.rel && attributes.rel === 'stylesheet') {
ele.setAttribute('href', path)
setTimeout(() => {
//resolve
pm.resolve(ele)
//done
_paths[path] = 'done'
}, 1)
}
else {
ele.src = path
ele.addEventListener('load', () => {
let wf
if (isfun(func)) {
wf = waitFun(func)
}
else {
wf = genPm()
wf.resolve()
}
wf
.then(() => {
return delay(500) //無縫載入頁面會無法更新, 強制delay 0.5s使頁面可更新
})
.then(function() {
//resolve
pm.resolve(ele)
//done
_paths[path] = 'done'
})
})
ele.addEventListener('error', () => {
//reject
pm.reject(ele)
//done
_paths[path] = 'done'
})
}
//appendChild
let head = document.getElementsByTagName('head')[0]
head.appendChild(ele)
return pm
}
/**
* 前端動態引入資源如Javascript或CSS檔案
*
* Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/importResources.test.mjs Github}
* @memberOf wsemi
* @param {String|Object|Array} pathItems 輸入資源字串、字串陣列、物件、物件陣列
* @returns {Promise} 回傳Promise,resolve回傳注入成功的HtmlElement,reject回傳錯誤訊息
* @example
* //need test in browser
*
* let pathItems
*
* pathItems = [
* 'https://cdn.jsdelivr.net/npm/ag-grid-community@22.0.0/dist/ag-grid-community.noStyle.js',
* 'https://cdn.jsdelivr.net/npm/ag-grid-vue@22.0.0/dist/ag-grid-vue.umd.js',
* 'https://cdn.jsdelivr.net/npm/w-aggrid-vue@1.0.28/dist/w-aggrid-vue.umd.js',
* ]
* importResources(pathItems)
* .then((res)=>{
* console.log(res)
* })
*
* pathItems = [
* {
* path: 'https://cdn.jsdelivr.net/npm/ag-grid-community@22.0.0/dist/ag-grid-community.noStyle.js',
* type: 'js',
* },
* {
* path: 'https://cdn.jsdelivr.net/npm/ag-grid-vue@22.0.0/dist/ag-grid-vue.umd.js',
* type: 'js',
* },
* {
* path: 'https://cdn.jsdelivr.net/npm/w-aggrid-vue@1.0.28/dist/w-aggrid-vue.umd.js',
* type: 'js',
* },
* ]
* importResources(pathItems)
* .then((res)=>{
* console.log(res)
* })
*
*/
function importResources(pathItems) {
//pm
let pm = genPm()
//check
if (!isarr(pathItems)) {
pathItems = [pathItems]
}
//check string
each(pathItems, (v, k) => {
if (isstr(v)) {
pathItems[k] = {
path: v
}
}
})
//key
let key = join(map(pathItems, 'path'), '|')
//check
if (_pathItems[key] === 'done') {
pm.resolve('loaded')
return pm
}
else if (_pathItems[key] === 'loading') {
waitFun(() => {
return _pathItems[key] === 'done'
})
.then(function() {
pm.resolve('loaded')
})
return pm
}
//loading
_pathItems[key] = 'loading'
//judge type
each(pathItems, (v, k) => {
if (!v.type) {
if (strright(v.path, 3) === '.js') {
v.type = 'js'
}
else if (strright(v.path, 4) === '.css') {
v.type = 'css'
}
else {
v.type = 'unknow'
}
}
})
//pmSeries
return pmSeries(pathItems, (pathItem) => {
let pm = genPm()
if (pathItem.type === 'js') {
pm = importResource({
tagName: 'script',
path: pathItem.path,
attributes: { type: 'text/javascript' },
func: pathItem.func,
})
}
else if (pathItem.type === 'css') {
pm = importResource({
tagName: 'link',
path: pathItem.path,
attributes: { rel: 'stylesheet' },
})
}
else {
let err = 'invalid pathItem.type: ' + pathItem.type
console.log(err)
pm.reject(err)
}
return pm
})
.finally(() => {
//done
_pathItems[key] = 'done'
})
}
export default importResources