2.0.0 • Published 5 years ago

jsynk v2.0.0

Weekly downloads
2
License
MIT
Repository
github
Last release
5 years ago

jSynk.js

Description

jSynk.js is a small javascript framework the browser/node.js with functions to convert javascript objects to publish/subscribe changes, to html, to css, html to dom, string including functions and regex, testing, benchmarking, modular loader, animating, diffing, async parallel helper functions and other utilities.

js_to_html - inspired by handlebars.js, angular.js, react.js/jsx

var js_html = [
	{ tso: '!DOCTYPE', html: 0 },
	{ t: 'html', c: [
		{ t: 'head', c: [
			{ tso: 'meta', charset:'UTF-8' },
			{ t: 'link', href:'css/index.css' },
			{ t: 'script', src:'js/jsynk.js' },
		]},
		{ t: 'body', c:[
			{ t: 'div', c:[
				{ t: 'b', c: [ 'Name:' ] },
				{ tsc: 'br' },
				{ tsc: 'input', type: 'text' },
			] },
		]},
	]},
];
var html = jk.js_to_html(js_html, {beautify:true});
console.log(html);
//<!DOCTYPE html>
//<html>
// 	<head>
// 		<meta charset="UTF-8">
// 		<link href="css/index.css"></link>
// 		<script src="js/jsynk.js"></script>
// 	</head>
// 	<body>
// 		<div>
// 			<b>
// 				Name:
// 			</b>
// 			<br/>
// 			<input type="text"/>
// 		</div>
// 	</body>
//</html>

js_to_css - inspired by sass/scss, LESS and Stylus

var js_css = [
	{ s: 'html, body',
		padding: '0',
		margin: '0',
	},
	{ s: '.res_20',
		margin: '-10px',
		c: [
			{ s: ' .res_li', 
				margin: '10px'
			}
		]
	},
];
var css = jk.js_to_css(js_css, { beautify: true });
console.log(css);
//html, body{
// 	padding:0;
// 	margin:0;
// }
//.res_20{
// 	margin:-10px;
// }
//.res_20 .res_li{
// 	margin:10px;
//}
var style = document.createElement('style');
style.textContent = css;
document.head.appendChild(style);
setTimeout(function(){
	document.head.removeChild(style);
}, 5000);

html_to_dom - inspired by angular.js, react.js

document.querySelector('body').innerHTML = '';
jk.dom_modules.page = {
	html: jk.js_to_html(
		[
			{ t: 'div', class: 'header', style: 'font-size:10px;', c: [
				{ t: 'h1', class: 'title' },
			] },
			{ t: 'div', class: 'content', tabindex: '2', c: [
				{ t: 'div', jk: { p: 'list', t: 'list' } },
			] },
		]
	),
	on_init: function on_init() {
		var parent = this.parent;
		var s = this.s;
		var p = this.p;
		var bp = this.bp;
		jk.html_to_dom(parent, {s: s, p: p});
		var el = this.el = {
			title: parent.querySelector('.title'),
		};
		s.on({p:bp+'title',f:function(e) {
			var path = e.paths[0];
			var val = s.get(path);
			if(val){
				el.title.innerHTML = val;
			}
		}});
	}
};
jk.dom_modules.list = {
	html: jk.js_to_html(
		[
			{ t: 'div', class: 'title' },
			{ t: 'ul', class: 'list', style: 'font-size:10px;' },
		]
	),
	on_init: function on_init() {
		var parent = this.parent;		
		var el = this.el = {
			title: parent.querySelector('.title'),
			list: parent.querySelector('.list'),
		};
		var s = this.s;
		var p = this.p;
		var bp = this.bp;
		s.on({p:bp+'title',f:function(e) {
			var path = e.paths[0];
			var val = s.get(path);
			if(val){
				el.title.innerHTML = val;
			}
		}});
		s.on({p:new RegExp('^'+bp+'items.\\d+$','gm'),f:function(e) {
			var path = e.paths[0];
			var val = s.get(path);
			if(val){
				var li = jk.html_to_dom('<div jk="list_item"></div>', {s:s,p:path});
				var lis = li.children;
				var lis_len = lis.length;
				for(var i = 0; i < lis_len; i++){
					var item = lis[i];
					el.list.appendChild(item);
				}
			}
		}});
	}
};
jk.dom_modules.list_item = {
	html: jk.js_to_html(
		[
			{ t: 'li', class: 'item' },
		]
	),
	on_init: function on_init() {
		var parent = this.parent;		
		var el = this.el = {
			item: parent.querySelector('.item'),
		};
		var s = this.s;
		var p = this.p;
		var bp = p ? p + '.': '';
		s.on({p:bp+'text',r:1,f:function(e) {
			var val = s.get(bp+'text');
			if(val){
				el.item.innerHTML = val;
			}
		}});
	}
};
var sub = jk.sub();
var html = jk.js_to_html([
	{t:'div', jk:{t:'page'}}
]);
var parent = jk.html_to_dom(html, {s: sub});
sub.set({v:{ 
	title: 'page title', 
	list: { 
		title: 'list title', 
		items:[ 
			{ text: 'listitem text 1' }, 
			{ text: 'listitem text 2' } 
		] 
	} 
}});
document.querySelector('body').appendChild(parent);
console.log(parent.innerHTML.replace(/\"{/g,"'{").replace(/}\"/g,"}'").replace(/&quot;/g, '"'));
//<div class="header" style="font-size:10px;" jkm='{"t":"page"}'>
//    <h1 class="title">page title</h1>
//</div>
//<div class="content" tabindex="2" jkm='{"t":"page"}'>
//    <div class="title" jkm='{"p":"list","t":"list"}'>list title</div>
//    <ul class="list" style="font-size:10px;" jkm='{"p":"list","t":"list"}'>
//        <li class="item" jkm="list_item">listitem text 1</li>
//        <li class="item" jkm="list_item">listitem text 2</li>
//    </ul>
//</div>

sub - inspired by ember.js, backbone.js, redux.js

var s = jk.sub();
console.log( s.get() );
// undefined
s.set({ v: { name: 'Jay'} });
console.log( s.get() ); 
// { name: 'Jay' }
console.log( s.get('name') ); 
// 'Jay'
s.set({ p: 'name', v: 'Kay' });
console.log( s.get() ); 
// { name: 'Kay' }

console.log('>>>');
s.set({ v: undefined });
console.log( s.get() ); 
// undefined
s.on({ p: 'name', f: function() {
	console.log('Welcome '+s.get('name')+'!!!');
} });
s.set({ v: { name: 'Ray' } });
// Welcome Ray!!!
console.log( s.get() ); 
// { name: 'Ray' }
s.on({p:/^children.\d+$/gm, f:function(e) {
	var path = e.paths[0];
	var val = s.get(path);
	if(val){
		console.log('Added child '+val);
	}
	else {
		console.log('Removed child');
	}
}});
s.set({p:'children',v:[ 'Amy', 'Alex' ]});
// Added child Amy
// Added child Alex
console.log( s.get() );
// { name: 'Ray', children: [ 'Amy', 'Alex' ] }
s.set({p:'children',v:[] });
// Removed child
// Removed child
console.log( s.get() );
// { name: 'Ray', children: [] }

s.off(); // removes all s.on
console.log('>>>');
s.set({ v: undefined });
console.log( s.get() ); 

sub.debug - inspired by my struggles to debug code

var s = jk.sub();
s.debug({l:/.*/}); // will log all changes
s.set({v:{ name: 'Ray', children: [ 'Amy', 'Alex' ] }});
// ' : {}'
// 'name : "Ray"'
// 'children : []'
// 'children.0 : "Amy"'
// 'children.1 : "Alex"'
s.debug(); // will remove logging/stacktracing
s.set({v:undefined});
s.debug({s:'children : []'}); // stacktrace on match
s.set({v:{ name: 'Ray', children: [ 'Amy', 'Alex' ] }});
// watch stacktrace to see where this code was set

agent - inspired by selenium, mocha.js, puppeteer

var agent = jk.agent({
	on_start: function on_start() {
		console.log('starting missions');
	},
	on_mission_finish: function on_mission_finish(e) {
		console.log('finished mission "'+e.mission.name+'" on '+e.time+'ms');
	},
	on_mission_fail: function on_mission_fail(e) {
		console.log('failed mission "'+e.mission.name+'" on '+e.time+'ms');
	},
	on_complete: function on_complete() {
		console.log('completed missions');
	},
});

agent.add_mission({ name: 'sync', f:function() {
	console.log('sync test');
}});

agent.add_mission({ name: 'async', f:function() {
	setTimeout(function(){
		console.log('async test');
		agent.next();
	}, 1000);
}, async: true});

agent.add_mission({ name: 'add dynamic test', f:function() {
	console.log('adding dynamic test');
	agent.add_instant_missions([
		{ name: 'dynamic_test', f: function() {
			console.log('run dynamic added test');
		}}
	]);
}});

agent.run_missions();
// starting missions
// sync test
// finished mission "sync" on 2ms
// async test
// finished mission "async" on 1002ms
// adding dynamic test
// finished mission "add dynamic test" on 2ms
// run dynamic added test
// finished mission "dynamic_test" on 2ms
// completed missions

benchmark - inspired by benchmark.js

// TODO

cias - inspired by compression int and string

var cur_time = new Date().getTime();
console.log(cur_time);
// 1553598014102
var cias_str = jk.cias(cur_time);
console.log(cias_str);
// "RLowwHW"
var cias_int = jk.cias(cias_str);
console.log(cias_int);
// 1553598014102

huid - inspired by guid and high resolution timestamp

var huid = jk.huid();
console.log(huid);
// "RLoi2nQ_2JrMGP_P1x_AuUZ2S_3IAvUK"
var huid_details = jk.huid(huid);
console.log(huid_details);
//{
// 	boot_time: 1553594464224.2126,
// 	boot_time_ms: 1553594464224,
// 	boot_time_precision_decimal: 0.2125733017,
// 	elapsed_time: 96221.9996087668,
// 	elapsed_time_ms: 96221,
// 	elapsed_time_precision_decimal: 0.9996087668,
// 	final_time: 1553594560446.2122,
// 	final_time_ms: 1553594560445,
// 	final_time_precision_decimal: 1.2121820685,
// 	nums: [1553594464224, 2125733017, 96221, 9996087668, 3016976812],
// 	random_padding: 3016976812
//}

load - inspired by require.js

// TODO

register - inspired by require.js

// TODO

stringify - inspired by JSON.stringify

var obj = {
	bool: true, str: '!', num: 1,
	infinity: Infinity, nan: NaN,
	null: null, undefined: undefined,
	function: function(){}, regex: /^\d+$/gm, date: new Date()
};
var jk_str = jk.stringify(obj, {beautify:true});
console.log(jk_str);
// {
// 	"bool": true,
// 	"str": "!",
// 	"num": 1,
// 	"infinity": Infinity,
// 	"nan": NaN,
// 	"null": null,
// 	"undefined": undefined,
// 	"function": function(){},
// 	"regex": /^\d+$/gm,
// 	"date": new Date(1553998399486)
// }
var json_str = JSON.stringify(obj, null, '\t');
console.log(json_str);
// {
// 	"bool": true,
// 	"str": "!",
// 	"num": 1,
// 	"infinity": null,
// 	"nan": null,
// 	"null": null,
// 	"regex": {},
// 	"date": "2019-03-31T02:13:19.486Z"
// }
var obj_from_jk_str = jk.parse(jk_str);
// jk.parse function "DANGEROUS TO SAVE/READ - XSS/NODE EXECUTION"
console.log(obj_from_jk_str);
// {
// 	bool:true
// 	date:Sun Mar 31 2019 04:31:19 GMT+0200 (W. Europe Summer Time)
// 	function:function() {…}
// 	infinity:Infinity
// 	nan:NaN
// 	null:null
// 	num:1
// 	regex:RegExp
// 	str:"!"
// 	undefined:undefined
// }
var jk_str_from_obj_from_jk_str = jk.stringify(obj_from_jk_str, {beautify:true});
var jk_str_equals_jk_str_to_obj_to_str = jk_str == jk_str_from_obj_from_jk_str;
console.log(jk_str_equals_jk_str_to_obj_to_str);
// true

animate - inspired by jQuery.js, raphael.js, velocity.js

var ani_obj = jk.animate({from: 100, to: 0, duration: 300, f:log_cur_val});
console.log(jk.stringify(ani_obj.vals,{beautify:true}));
// {
// 	"from": 100,
// 	"to": 0,
// 	"f": function log_cur_val(obj) {
// 		console.log(obj.vals.cur_val);
// 	},
// 	"duration": 300,
// 	"n": "",
// 	"start_time": 1553996074631,
// 	"diff_time": 0,
// 	"abs_percent": 0,
// 	"percent": 0,
// 	"anim_percent": 0,
// 	"cur_val": 0
// }
function log_cur_val(obj) {
	console.log(obj.vals.cur_val);
}
// 98.42926826881794
// 91.63221566676845
// 83.32312532838978
// 74.62420554151944
// 66.12620797547086
// 58.371920773959886
// 50.45413315675924
// 42.92864323155684
// 36.25760102513104
// 29.66052971894962
setTimeout(function(){
	ani_obj.stop();
	console.log(jk.stringify(ani_obj.vals,{beautify:true}));
	// {
	// 	"from": 100,
	// 	"to": 0,
	// 	"f": function log_cur_val(obj) {
	// 		console.log(obj.vals.cur_val);
	// 	},
	// 	"duration": 300,
	// 	"n": "",
	// 	"start_time": 1553996074631,
	// 	"diff_time": 149,
	// 	"abs_percent": 0.49666666666666665,
	// 	"percent": 0.49666666666666665,
	// 	"anim_percent": 0.7033947028105039,
	// 	"cur_val": 29.66052971894962
	// }
	var ani_obj2 = jk.animate({from: ani_obj.vals.cur_val, to: 100, duration: 150, f:function(obj) {
		console.log(obj.vals.cur_val);
	}});
	// 37.0130064544886
	// 49.99087321040387
	// 60.93593269113734
	// 71.00503300421573
	// 80.4287618333185
	// 88.24776857633327
	// 94.21490393754453
	// 98.30599779211906
	// 99.86120112292397
	// 100
}, 150);

async_recursive - inspired by async.js

// TODO

async_parallel - inspired by async.js

// TODO

diff - inspired by git, svn, mercurial

// TODO

Installation

Browser - jsynk.js

<script type="text/javascript" src="jsynk.js"></script>

Node.js

npm install jsynk

Compatibility

Works in browser, Node.js. Tries to be crossbrowser Chrome, Firefox, Edge, IE9+, Safari and use vanilla js.

License

MIT