You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
5.5 KiB
JavaScript

/**
* Simple Javascript eXtension - 1.0
* (c) 2011 - 2015 Steve L. Nyemba, steve@the-phi.com
* License GPL version 3.0
*
* Implementation of miscellaneous utilities commonly used, These functions are reusable and simple:
* jx.utils.vector extracts a vector from an array of objects (or a matrix)
* jx.utils.keys extract keys from an associative array
* jx.utils.unique returns unique objects in an array, including array of objects (provided an key function)
*
* jx.utils.patterns:
* Implementation of design patterns defined by the GOF http://en.wikipedia.org/wiki/Software_design_pattern
* jx.utils.patterns.visitor The visitor design pattern
* jx.utils.patterns.iterator The iterator design pattern
* jx.utils.patterns.observer The observer design pattern
*/
if(!jx){
var jx = {} ;
}
jx.utils={} ;
/**
* Extract an array from an array of associative arrays (map),
* This function can also perform a sort of join provided a set of keys (good for building a matrix)
* @param key key or column of the associative array
* @param array an array or associative arrays i.e [{}]
*/
jx.utils.vector=function(key,rec){
var vector = [] ;
var value;
for(var i=0; i < rec.length; i++){
// value = rec[i][key] ;
// if(key.constructor == String){
// vector.push( value ) ;
// }else
if(key.constructor == Array){
value = []
for(ii in key){
value.push(rec[i][key[ii]])
}
}else{
value = rec[i][key] ;
}
vector.push( value ) ;
}
return vector ;
}//-- end jx.utils.vector(key,rec)
/**
* Extract keys from an associative array
* @param rec associative array
*/
jx.utils.keys=function(rec){
return Object.keys(rec) ;
}//-- end jx.utils.keys
jx.utils.values = function(rec){
var r = []
for(id in rec){
var value = rec[id]
r.push(value)
}
return r
}
/**
* This function will returnt he unique elements of a list
* @param list list of elements (duplicates are expected)
*/
jx.utils.unique = function (list,getKey){
var obj = {}
for(var i=0; i < list.length; i++){
if(list[i].constructor == Object && getKey != null){
var key = getKey(list[i]) ;
obj[key] = list[i] ;
}else{
obj[list[i]]= 1 ;
}
}
if(getKey == null){
return jx.utils.keys(obj);
}else{
//
// This will return the unique list of objects, provided the user has given a key extraction function
// The key extraction function is analogous to the equal operator in C++
//
return jx.utils.patterns.visitor(jx.utils.keys(obj),function(id){
return obj[id] ;
})
}
}
jx.utils.join = function(x,y){
if(x.length != y.length){
return []
}else{
var rec = x ;
for(var i in rec){
//
//@TODO: Consider the case we are adding to a matrix
//
rec[i] = [x[i],y[i]]
}
return rec ;
}
}
jx.utils.size = function(id){
if(id.match(/window|screen/i)){
var width = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var height = window.innerHeight
|| document.body.clientHeight;
}else if(jx.dom.exists(id)){
var element = jx.dom.get.instance(id)
var width = element.clientWdith
var height = element.clientHeight
}
return {width:width,height:height}
}
/**
* Implementation of a few standard design patterns. Their use is user/dependent
* For more information on how/when to use a design pattern please use google/wikipedia ;-)
*/
jx.utils.patterns = {}
jx.utils.patterns.visitor = function(list,pointer){
var rlist = [] ;
for(var i=0; i < list.length; i++){
value = pointer(list[i]) ;
if(value != null){
rlist.push(value) ;
}
}
return (rlist.length > 0)?rlist:[];
}
/**
* Implementation of an iterator design pattern: i.e we use a sequence of objects and call a given method on them
* This is a basic iterator design pattern
*/
jx.utils.patterns.iterator = function(list,pointer){
for(var i=0; i < list.length; i++){
list[i][pointer]();
}
}
/**
* This is an implementation of an observer design pattern, the obervers will just have to call notify on the subject
* The observers' role is to render some stuff on the ui, having said this, this design pattern is suited for ui & asynchronous tasks
* @param lobservers list of observers
* @param init pointer to be called on each observer to trigger it
*/
jx.utils.patterns.observer = function(lobservers,init){
var p = {} ; //-- specification of the subject
p.index = 0;
p.nodes = lobservers ;
p.pointer = init;
p.notify = function(){
//
// This function is designed to be called by the observers
//
if( this.index < this.nodes.length){
this.start() ;
}
}
p.start = function(){
var observer = this.nodes[this.index];
try{
++this.index;
if(this.pointer.constructor == String){
observer[this.pointer](this) ;
}else{
this.pointer(observer);
this.notify() ;
}
}catch(e){
//
// if an exception was thrown, chances are were unable to increment and call notify
// In the spirit of "The show must go on", we will make the notify call here for the failed observer
//
++this.index ;
this.notify();
}
}
//
// let's fire the design pattern
//
p.start() ;
}
/**
* Apply a function to an array (visitor-like design pattern)
* @param fn casting function on the vector or array of data
* @param list array of numeric data (hopefully)
* @return array containing casted type
*/
jx.utils.cast = jx.utils.patterns.visitor ;