123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- /**
- * 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
- *
- * @TODO:
- * - Find a way to alias jx.utils
- */
- 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 ;
|