statelessjs
Version:
Front end javascript library for building web applications
267 lines (230 loc) • 12.2 kB
HTML
<html>
<head>
<script src="stateless.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.test2-div{
display:block;
height:auto;
}
</style>
</head>
<body>
<pre style="width:100%; overflow:auto;">
ideal usage:
step 1 - register:
stateless.register (element)
stateless.register (htmlString)
stateless.register ([elements...])
step 2 - instantiate
var item = stateless.instantiate(id)
step 3 - manipulate the item
item.render() -> renders to body
item.addClass([element,] string[, multiple]) -> adds a class uniquely to the dom element, if multiple add it regardless
item.removeClass([element,] string[, multiple]) -> removes a class uniquely to the dom element, if multiple add it regardless
item.hasClass([element,] string) -> returns true/false based of if the dom element has the class
item.css([element,] string [, string]) -> query the css property or set it
item.appendChild = item.append([element,] item/domElement) -> alias for include or used to append another scope to this scope
item.unlink() -> remove this dom element from it's parent
item.on([element,] "event", callback) -> attach an event listener to the top most dom element or the selected element
item.off([element,] "event", callback) -> remove an event listener from the top most dom element or the selected element
item.once([element,] "event", callback) -> add a call once event listener to the top most dom element or the selected element
item.text([element,] [string]) -> no args = get inner string, 1 arg = replace inner string, 2 arg = replace inner string at element
item.attr([element,] string [, string]) -> get or set the attribute
item.data([element,] string [,string]) -> get or set the data- attribute
idem.property = item.define(property, options) -> define a peroperty for the object
item.element([selector]) -> gets the one dom element or the first selected match
item.elements([selector]) -> gets everything including the root or just everything that matches the selector
item.children -> read only property that returns all child scopes
item.parent -> read only property that returns the parent scope if it exists;
item.root -> returns the root scope of the chain;
item.include([element,] anotherElement) -> inclode another html node into the currnet scope
Other options:
stateless.each(callback(item, index)) -> itterate through all the templates once
instantiated_domobject.scope -> property that provides the templateInstance
stateless.watch(eventName, callback) -> standalone watch for genaric non-dom standard events (returns a function that can be called to stop watching)
stateless.emit(event, data) -> emits an event to the watchers of of that event and a data object associated with the event
stateless.plugin(name, value) -> add a plugin to stateless (can override anything)
</pre>
<div id="first-div" class="test1-div">
<strong>testing</strong>
<p>I am testing something bla bla</p>
<div class="first-div-subdiv"></div>
</div>
<div class="test2-div" style="backgrounD-color: gray">
<a href="javascript:void[0]" onclick="this.scope.fn()">Here is something to click on</a>
</div>
<div class="test2-div"></div>
<div class="test2-div"></div>
<script>
// used for mobile deving where the console doesn't exist
function mobileLog(){
var originalLog = console.log;
console.log = function(){
originalLog.apply(this, arguments)
var domLogger = document.querySelector(".console")
if (domLogger){
domLogger.scope._log.apply(this, arguments)
}
else{
alert(Array.prototype.toString.call(arguments))
}
}
}
// a dom based console module made using stateless
var cons = stateless.view("<div id='console'><pre style='width: 100%; height:8em; border: solid 1px #000; overflow:auto;'></pre><textarea rows='3' style='width:100%; margin-top:1em; margin-bottom:1em;'></textarea><button onclick='this.scope._eval(true)' style='width:50%; display:inline'>run and clear</button><button onclick='this.scope._eval()' style='width:50%; display:inline'>run</button></div>")
cons._eval = function(clear){
var string = cons.element("textarea").value
clear && (cons.element("textarea").value = "")
cons._log(eval.call(this, string))
}
cons._log = function(){
var pre = cons.element("pre")
var added = Array.prototype.splice.call(arguments, 0).map(function(item){
if (typeof item == 'object') {
var str;
if (str = JSON.stringify(item), str != "{}"){
return str
}
else {
return item.toString()
}
}
else return item
})
pre.innerHTML += added.toString().replace(/\,/g, ",\n") + "\n\n"
pre.scrollTop = pre.scrollHeight;
}
cons.render()
mobileLog()
// the actual test code here
stateless.register(document.querySelector(".test1-div"))
.register("<div id='string-div'>I was made from a string</div>")
.register(document.querySelectorAll(".test2-div"))
.each(function(item){
console.log(item)
});
var firstDiv = stateless.instantiate("first-div")
.appendChild("$.first-div-subdiv", stateless.instantiate(2))
.render()
firstDiv.fn = function(){
console.log("I got called");
};
var secondDiv = document.querySelector("a").scope//.unlink()
//.render()
.addClass("state")
.addClass("state")
.addClass("state", true)
console.log(secondDiv.attr("class"))
secondDiv.removeClass("state")
console.log(secondDiv.attr("class"))
secondDiv.addClass("state", true)
.addClass("state", true)
.addClass("state", true)
.removeClass("state", true);
console.log(secondDiv.attr("class"))
secondDiv.define("status", {asVar: 0})
console.log("secondDiv.status should be 0 has", (secondDiv.status === 0)? "passed" : `failed. secondDiv.status = ${secondDiv.status}`);
secondDiv.status = 15
console.log("secondDiv.status should now be 15 has", (secondDiv.status == 15)? "passed" : `failed. secondDiv.status = ${secondDiv.status}`);
secondDiv.define("changeStatus", {static: function(num){
secondDiv.status = num
}})
console.log("secondDiv.changeStatus should a function", (typeof secondDiv.changeStatus == "function")? "passed" : `failed. secondDiv.changeStatus = ${secondDiv.changeStatus}`);
secondDiv.changeStatus(5)
console.log("secondDiv.status should be 5 has", (secondDiv.status === 5)? "passed" : `failed. secondDiv.status = ${secondDiv.status}`);
var meow = "meow"
secondDiv.property("static", {static:meow})
console.log("secondDiv.static should be \"meow\" has", (secondDiv.static == meow)? "passed" : `failed. secondDiv.static = ${secondDiv.static}`);
secondDiv.static = "Attempt to change static"
console.log("secondDiv.static should still be \"meow\" has", (secondDiv.static == meow)? "passed" : `failed. secondDiv.static = ${secondDiv.static}`);
secondDiv.property("getSet", {
get: function(){
return secondDiv.static + secondDiv.status;
},
set: function(number){
secondDiv.status = number;
}
})
console.log("secondDiv.getSet should be \"meow5\" has", (secondDiv.getSet == secondDiv.static + secondDiv.status)? "passed" : `failed. secondDiv.getSet = ${secondDiv.getSet}`);
secondDiv.getSet = 8
console.log("secondDiv.getSet should be \"meow8\" has", (secondDiv.getSet == secondDiv.static + secondDiv.status)? "passed" : `failed. secondDiv.getSet = ${secondDiv.getSet}`);
secondDiv.property("getOnly", {
get: function(){
return secondDiv.static + secondDiv.status;
}
})
console.log("secondDiv.getOnly should be \"meow8\" has", (secondDiv.getOnly == secondDiv.static + secondDiv.status)? "passed" : `failed. secondDiv.getOnly = ${secondDiv.getOnly}`);
secondDiv.getOnly = 12
console.log("secondDiv.getOnly should still be \"meow8\" has", (secondDiv.getOnly == secondDiv.static + secondDiv.status)? "passed" : `failed. secondDiv.getOnly = ${secondDiv.getOnly}`);
secondDiv.define("hidden", {
get: function(){
return this.data1 + " " + this.data2
},
set: function(s1){
this.data1 = s1 || "string 1"
},
data1: "default string 1",
data2: "default string 2"
})
console.log("secondDiv.hidden should be \"default string 1 default string 2\" has", (secondDiv.hidden == "default string 1 default string 2")? "passed" : `failed. secondDiv.hidden = ${secondDiv.hidden}`);
secondDiv.hidden = "gibrish"
console.log("secondDiv.hidden should be \"gibrish default string 2\" has", (secondDiv.hidden == "gibrish default string 2")? "passed" : `failed. secondDiv.hidden = ${secondDiv.hidden}`);
var indexable = []
for(var key in secondDiv){
indexable.push(key)
}
console.log("secondDiv's indexable keys should be \"status\",\"changeStatus\",\"static\",\"getSet\",\"getOnly\" has", (indexable.toString == "status,changeStatus,static,getSet,getOnly")? "passed" : `failed. secondDiv.getOnly = ${indexable.toString()}`);
firstDiv.on(firstDiv.element("a"), "mouseover", function(){console.log("hovered")})
console.log("There should be a warning after this message")
secondDiv.on(secondDiv.element("a"), "mouseover", function(){console.log("hovered")})
console.log("If there was a warning before this message then the test has passed")
firstDiv.data('mess', 'abcd1234')
console.log("firstDiv.data('mess', 'abcd1234') should set data-mess to abcd1234", (firstDiv.element().getAttribute("data-mess") == 'abcd1234')? "passed" : "failed")
console.log("firstDiv.data('mess') should retur 'abcd1234'", (firstDiv.data("mess") == 'abcd1234')? "passed":"failed")
secondDiv.append("$a", `<strong>ABC</strong><em>123</em>`)
firstDiv.on("$ a", "click", function(){alert("working")})
secondDiv.off("$ a", "click", function(){alert("working")})
secondDiv.once("$ a", "click", function(){alert("working")})
firstDiv.addClass("$a", "link")
.addClass("$a", "link")
console.log("if secondDiv->a has only 1 'link' class", (firstDiv.element("a").className == "link")? "passed" : "failed")
console.log("secondDiv.attr('$a', 'class') == 'link'", (secondDiv.attr('$a', 'class') == 'link')? "passed": "failed")
console.log(`secondDiv.attr("$a", "class") == "link"`, (secondDiv.attr("$a", "class") == "link")? "passed" : "failed")
console.log(`secondDiv.hasClass("$a", "link") === true`, (secondDiv.hasClass("$a", "link") === true)? "passed" : "failed")
console.log(`secondDiv.css("display") == "block"`, (secondDiv.css("display") == "block")? "passed" : "failed")
secondDiv.css("background-color", "blue")
console.log(`secondDiv.css("background-color") == "rgb(0, 0, 255)"`, (secondDiv.css("backgroundColor") == "rgb(0, 0, 255)")? "passed" : `failed, ${secondDiv.css("background-color")}`)
secondDiv.define("color", {
get: function(){
return secondDiv.css("background-color")
},
set: function(color){
secondDiv.css("background-color", color)
}
})
secondDiv.color = "orange"
console.log(`secondDiv.color == "rgb(255, 165, 0)"`, (secondDiv.color == "rgb(255, 165, 0)")? "passed" : "failed")
stateless.watch(function(event, data){
console.log('global event watcher fired with:', event, data)
})
console.log(`stateless.watch followed by stateless.emit `)
var stop = stateless.watch("ev", function(){
console.log("passes")
stop()
})
stateless.emit("ev")
console.log(`add a plugin to stateless called log`)
stateless.plugin("log", function(data){
console.log(data)
})
stateless.log("passed")
stateless.plugin("meaningOfLife", function(){
console.log("the meaning of life is", 42)
return 42
})
stateless.register(`<div id="meaningOfLife"></div>`)
console.log(`the meaning of life should be 42 ${(stateless.plugin("meaningOfLife")() == 42)? "passed" : "failed: " + stateless.plugin("meaningOfLife")()}`)
</script>
</body>
</html>