Closed centratelemedia closed 1 year ago
pm.js is just a small tool to help create SPA. pm.js aims to gain high performance of vanila js, not designed to be a fully UI framework, because I'm just a newbie in frontend:joy:. You can easily use other UI frameworks like Jeasyui or bootstrap/jquery/angular together with pm.js.
Recently I'm trying to simplify the source code, then any other can easily modify the source code:
// Copyright 2020 lesismal. All rights reserved.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
let _evts = {}
function pub(event, data) {
let eMap = _evts[event]
for (let k in eMap) {
let h = eMap[k]
h && h.handler({ 'tag': h.tag, 'event': event, 'data': data })
}
}
function sub(tag, event, handler) {
let eMap = _evts[event]
if (!eMap) {
eMap = {}
_evts[event] = eMap
}
eMap[tag] = { tag: tag, event: event, handler: handler }
}
function unsub(tag, event) {
let eMap = _evts[event]
if (!eMap) {
return
}
if (eMap[tag]) {
delete eMap[tag]
}
}
function elem(id) {
return document.getElementById(id)
}
function onload(f) {
if (f && (typeof window !== "undefined")) {
window.onload == f;
}
}
function request(method, url, data, cb) {
let resolve
let p = new Promise(function (res) {
resolve = res
if (typeof (cb) == 'function') {
resolve = function (ret) {
res(ret)
cb(ret)
}
}
let r = new XMLHttpRequest()
r.open(method, url, true)
r.onreadystatechange = function () {
if (r.readyState != 4) {
return
}
if (r.status != 200) {
resolve({ code: r.status, data: null, err: `request "${url}" failed with status code ${r.status}` })
return
}
resolve({ code: r.status, data: r.responseText, err: null })
}
r.send(data)
})
return p
}
let _jsLoaded = {}
function loadJS(url, cb) {
let id = _jsLoaded[url]
if (id && elem(id)) {
return
}
if (this.idCnt) {
this.idCnt++
} else {
this.idCnt = 1
}
id = `$van_js_elem_` + this.idCnt
let jsElem = document.createElement("script")
jsElem.id = id
jsElem.type = 'text/javascript'
jsElem.src = url
jsElem.async = true
jsElem.onload = cb
document.getElementsByTagName("body")[0].appendChild(jsElem)
_jsLoaded[url] = jsElem.id
}
function loadHTML(id, url, cb) {
let self = this
return request("GET", url, null, function (res) {
if (res.code == 200) {
elem(id).innerHTML = res.data
}
(typeof (cb) == "function") && cb(res)
})
}
function setRouter(router) {
window.location.href = '#' + router;
}
function parseUrl() {
let detail = location.hash.split("?")
let path = detail[0].split("#")
let router = path[1]
let values = {}
let params = detail[1] ? detail[1].split("&") : []
for (let i = 0; i < params.length; i++) {
let kv = params[i].split("=")
values[kv[0]] = kv[1]
}
return {
path: path[0],
router: router,
values: values
}
}
let mainInited = false
class SPA {
constructor(rootId, layers, isMain) {
this.rootId = rootId
this.layers = []
this.routers = {}
this.addLayers(layers)
this.isMain = isMain
if (isMain) {
if (mainInited) {
throw ("Only one main group can be created")
}
mainInited = true
this.refresh()
}
this.select(null)
}
addLayer(layer) {
this.addLayers(layer)
}
addLayers(layers) {
if (!layers) return
if (!(layers instanceof Array)) {
layers = [layers]
}
for (let i = 0; i < layers.length; i++) {
let layer = layers[i]
if (!layer.id) {
throw ("Invalid layers config: no id")
}
if (!layer.router) {
throw ("Invalid layers config: no router and id")
}
this.routers[layer.router] = true
this.layers.push(layer)
}
}
addNode(node) {
this.addLayer(layer)
}
addNodes(nodes) {
this.addLayers(nodes)
}
select(router, isRefresh) {
let layers = this.layers
if (!router && !!layers && layers.length > 0) {
router = layers[0].router
}
if (!this.routers[router]) {
return
}
if (this.selected == router) {
return
}
for (let i = 0; i < layers.length; i++) {
let layer = layers[i]
let id = layer.id
if (layer.router != router) {
if (layer.inited) {
elem(id) && (elem(id).style.display = 'none')
layer.onhide && layer.onhide()
}
} else {
if (!elem(id)) {
let e = document.createElement("div")
e.id = id
elem(this.rootId).appendChild(e)
}
elem(id).style.display = 'block'
if (!layer.inited) {
layer.inited = true
layer.oninit && layer.oninit(layer)
if (layer.source) {
if (!layer.loaded && !layer.loading) {
layer.loading = true
loadHTML(id, layer.source, function () {
layer.loading = false
if (layer.inited) {
layer.loaded = true
layer.onload && layer.onload(layer)
layer.onshow && layer.onshow(layer)
} else {
this.release(layer)
}
})
}
} else {
layer.onshow && layer.onshow(layer)
}
} else {
!layer.loading && layer.onshow && layer.onshow(layer)
}
}
}
if (!isRefresh) {
setRouter(router);
}
this.selected = router
}
refresh() {
let self = this
let fn = function () {
let url = parseUrl()
self.select(url.router, true)
}
if (!window["$van_refresh_inited"]) {
window["$van_refresh_inited"] = true
// window.addEventListener('load', fn)
window.addEventListener('hashchange', fn)
}
}
release(id) {
if (!id) return
let layers = this.layers
for (let i = 0; i < layers.length; i++) {
let layer = layers[i]
if (id == layer.id) {
elem(id).innerHTML = ""
layer.inited = false
layer.loaded = false
return
}
}
}
}
function newSPA(rootId, layers, isMain) {
return new SPA(rootId, layers, isMain)
}
if ((typeof window !== "undefined") && !window["$van"]) {
window["$van"] = {
'pub': pub,
'sub': sub,
'unsub': unsub,
'elem': elem,
'onload': onload,
'parseUrl': parseUrl,
'request': request,
'loadJS': loadJS,
'loadHTML': loadHTML,
'setRouter': setRouter,
'newSPA': newSPA,
}
}
Well, I misunderstood in the previous reply. Would you please provide your full code that can reproduce this? including Jeasyui src or link
@lesismal i just upload to https://github.com/centratelemedia/webgpsdemo.git
try it please
I tried. It seems the style/css does not work when using jeasyui and pm.loadHTML(element.innerHTML="...") together. But it works fine when using bootstrap. I am not skilled with frontend, can't find the reason by now.
Even if the elements seem all right, it doesn't work:
so confused.
@lesismal
i have found solution, jeasyui have function:
$.parser.parse(); // parse all the page
$.parser.parse('#cc'); // parse the specified node
Jeasyui have smart feature, by define class in div tag component automatic renderer, for example:
but in pmjs above script doesnot automatic renderer to datagrid component, mybe pmjs can make this automatic renderer?
TIA