An app for Force to build a website
This library requires Force library.
This website function cannot be called just the way it is, because the first parameter is app object from Force.app instance.
The app object must contains method init and app property, as Force’s Manual
This app will generate globals readonly object ForceWebsite, to help its plugins, themes and kitchen to relate to it.
Create tag script to store the configuration, with type application/json.
<script type="application/json" id="website-config"></script>
Don’t forget to put some ID, so that next going to be easy to get the text content.
And the sample of the text content as the following.
{
"force": {
"file": "https://9r3i.github.io/force/force.min.js",
"cache": {
"age": 2592e5,
"description": "3 days in mili second = 3*24*60*60*1000",
"default": 864e5
}
},
"data": {
"host": "https://sabunjelly.com/api/force/",
"base": "foxtrot",
"driver": "ForceData"
},
"site": {
"name": "9r3i",
"description": "The sly eagle doesn't kill at whim",
"keywords": "9r3i, Force, Foxtrot",
"robots": "follow, index",
"date": {
"year": "2022",
"full": "2022-11-13 05:35:44"
},
"data": {}
},
"kitchen": {
"namespace": "kitchen",
"host": "https://9r3i.github.io/force-kitchen",
"key": "kitchen"
},
"theme": {
"namespace": "foxtrot",
"host": "https://9r3i.github.io/foxtrot-theme",
"config": {
"data": {
"limit": 8,
"foot": 55
}
}
},
"plugins": [
["configuration",false,
"https://9r3i.github.io/force-website-plugins"
],
["menu",[
{
"href": "?home",
"text": "Home"
},
{
"href": "?p=tulisan-pertama",
"text": "Tulisan Pertama"
},
{
"href": "?search",
"text": "Search"
},
{
"href": "?kitchen",
"text": "Login"
}
],
"https://9r3i.github.io/force-website-plugins"
],
["site",false,"https://9r3i.github.io/force-website-plugins"],
["grid",false,"https://9r3i.github.io/force-website-plugins"],
["timeago","id_ID",
"https://9r3i.github.io/force-website-plugins"
],
["visitor",false,"https://9r3i.github.io/force-website-plugins"],
["locode",false,"https://9r3i.github.io/force-website-plugins"],
["arabic","arabic",
"https://9r3i.github.io/force-website-plugins"
],
["link",false,"https://9r3i.github.io/force-website-plugins"],
["social",[
"sharer",
"like",
"qrcode"
],
"https://9r3i.github.io/force-website-plugins"
],
["search",{
"id": "body",
"holder": "Search...",
"key": "search"
},
"https://9r3i.github.io/force-website-plugins"
],
["land",false,"https://9r3i.github.io/force-website-plugins"],
["slider",{
"id": "body",
"images": [56,57,58,59]
},
"https://9r3i.github.io/force-website-plugins"
]
],
"coverLoader": false
}
The config above, I use for configuration of my website, https://9r3i.web.id/, visit it if you wish.
Read more about website app configuration detail in Force’s Website Sample
Create tag script to store the configuration, without attribute src.
<script id="force-script"></script>
Don’t forget to put some ID, so that next going to be easy to get the text content.
Next is the calling of the app.
(async function(n,h,cnf,f){
var ctag=document.getElementById(c), // script tag of website configuration, see configuration section
ftag=document.getElementById(f), // script tag to load force script
fname='force/virtual/force.js', // virtual path
fscript=localStorage.getItem(fname), // get the force script if it's already stored in virtual file
cnf=JSON.parse(ctag.textContent); // parse the config
if(!fscript){ // check if it's not stored yet
fscript=await fetch(cnf.force.file).then(r=>r.text()); // fetch the force.js file
localStorage.setItem(fname,fscript); // store the force script into virtual file, so next time it won't be loaded anymore
}
ftag.textContent=fscript; // load the force script, immedietly executed by the browser
const app=(new Force).app(n,h,cnf); // prepare the app using Force app instance
await app.init(); // initialize the app
console.log("A Force app has been loaded, namespace: "
+app.namespace);
})(
'website', // website app namespace
'https://9r3i.github.io/force-website', // host of ForceWebsite
'website-config', // from configuration section
'force-script' // script tag where to store the force.js script
);
Force inherited object of Force (readonly)version string of this website app (readonly)root string of website rootconfig object of website configapp inherited object of given parameter apptheme object of prepared themekitchen object of prepared kitchenquery object of parsed url querydata object of loaded data, index to the slugsbulkRaw array of loaded raw dataplug object of registered and prepared plugins, before initplugLoaded int of number of loaded pluginspkey string of privilage keykkey string of kitchen keyThe methods below is part of the app that has auto-call to proceed on it.
init async function of initialization, this method is required by Force.app to initialize the app, auto-callloadPage async function to load a page upon popstate event, auto-callfetchConfig async function to load site.data config from server, auto-callfetchAllData async function to load all data from server without values of contents, and parsed to ForceWebsite.data, auto-call except for kitchen in the first load.themePrepare function to prepare a theme or kitchen, auto-callfinishing function to let the app finish the rest of works, including plugins initialization and anchors initialization, auto-call except when the kitchen or theme exit in the middle of processfillPageData function to fill page with data, this method is auto-call, but can be recall if necessary, parameters:
content string of content to filldata object of data inputanchorInit function to initialize all anchors, it’s called by loadPage, means it’s auto-call, but i think it won’t be conflict if it’s called twiceanchorExec function of event callback from initialization of anchorInit, means it’s auto-callkitchenSet function of kitchen set, auto-call, inner method onlyslideHeadLoader function to show progress of loading, auto-call while preparing pluginsheadLoader function of head loader, auto-call from slideHeadLoaderloadProgress function of progress callback, auto-call form fetch if turn it onThese methods are inner method but also used to be a helper
setTitle function to set title, it’s also auto-call but there won’t be conflict if it’s called again, parameters:
txt string of titleasHTML bool of put as html using innerHTML instead of innerText; default: falsesetMeta function to set html meta data, parameters:
name string of meta namecontent string of contentkey string of meta key; default: namefindDataSpace function to find chain of namespaces splitted by dot, parameters:
n string of data namespacesdata object of data spacesao bool of object as output; default: falsego function to jump the history statement where the location.href is popped in statement, it’s being auto-call by loadPage and anchorExec, but it will help much for kitchen, theme and plugins, parameters:
href string of url to attach in location.href as statement, and it’s not gonna work if href is the same as location.hreffetch function to fetch data from ForceServer using method GET, it’s been set to database name and host, parameters:
mt string of force method (NOT request method)cb function of callback, return argument of mixed datadt object of data to be merged to the url query, so DO NOT put something secret on itrequest function to fetch data from ForceServer using method POST, mostly it’s used in Kitchen page, parameters:
mt string of force method (NOT request method)cb function of callback, return argument of mixed datadt object of data to be merged into POST data queryupload function to upload TEMPORARY content to the server, parameters:
file blob of file; *requirecb function of return callback, return: string of temporary data ID or structure.ul function of upload progress callbackloadFile function to load a file path or url, from virtual file if exists or load then save into virtual file, parameters:
f string of file path or urlcb function of callback, return a string of file contentgetFileContent function to get file content from virtual file if exists or load then save into virtual file, return string of file content, parameters:
f string of file path or urll bool of force to load even it existsThese methods are used to be helper
contentURL function to generate content url of a data, parameters:
id number of data IDrand bool of use random query to prevent browser cacheimageURL function to generate image url of a data, parameters:
id number of data IDrand bool of use random query to prevent browser cachecall function to help call inner function; it’s auto-call in fillPageData, but it will be necessary for plugins to execute some operational, parameters:
fn function to applyargs array of argumentsonContentReady function of ready state of content element detected using document.getElementById('content'), return into callback function, object the content element or false if failed, parameters:
cb function of callbacki int of counter; auto-generatekitchenFormHelper function to help form on submit, parameters:
e object of submit event of thr formdata object of data, key as data.name and value as data.valuesubmitter object element of submittertarget inherited object from event.targetweb object of global ForceWebsitedisable function to disable all inputs in range of the formenable function to enable all inputs in range of the formsend function to send data to the server using ForceWebsite.request, parameters:
mtd string of force methodcb function of callback, after request sent, argument is result from the serverbb function of callback, before request, argument is this objectThis auto-call means no need to be worried, because it’s only worked inside the app, and no plugin, no theme and no kitchen will use this method.
That’s all there is to it. Alhamdulillaah…