utils.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /**
  2. * Simple Javascript eXtension - 1.0
  3. * (c) 2011 - 2015 Steve L. Nyemba, steve@the-phi.com
  4. * License GPL version 3.0
  5. *
  6. * Implementation of miscellaneous utilities commonly used, These functions are reusable and simple:
  7. * jx.utils.vector extracts a vector from an array of objects (or a matrix)
  8. * jx.utils.keys extract keys from an associative array
  9. * jx.utils.unique returns unique objects in an array, including array of objects (provided an key function)
  10. *
  11. * jx.utils.patterns:
  12. * Implementation of design patterns defined by the GOF http://en.wikipedia.org/wiki/Software_design_pattern
  13. * jx.utils.patterns.visitor The visitor design pattern
  14. * jx.utils.patterns.iterator The iterator design pattern
  15. * jx.utils.patterns.observer The observer design pattern
  16. *
  17. * @TODO:
  18. * - Find a way to alias jx.utils
  19. */
  20. if(!jx){
  21. var jx = {} ;
  22. }
  23. jx.utils={} ;
  24. /**
  25. * Extract an array from an array of associative arrays (map),
  26. * This function can also perform a sort of join provided a set of keys (good for building a matrix)
  27. * @param key key or column of the associative array
  28. * @param array an array or associative arrays i.e [{}]
  29. */
  30. jx.utils.vector=function(key,rec){
  31. var vector = [] ;
  32. var value;
  33. for(var i=0; i < rec.length; i++){
  34. // value = rec[i][key] ;
  35. // if(key.constructor == String){
  36. // vector.push( value ) ;
  37. // }else
  38. if(key.constructor == Array){
  39. value = []
  40. for(ii in key){
  41. value.push(rec[i][key[ii]])
  42. }
  43. }else{
  44. value = rec[i][key] ;
  45. }
  46. vector.push( value ) ;
  47. }
  48. return vector ;
  49. }//-- end jx.utils.vector(key,rec)
  50. /**
  51. * Extract keys from an associative array
  52. * @param rec associative array
  53. */
  54. jx.utils.keys=function(rec){
  55. return Object.keys(rec) ;
  56. }//-- end jx.utils.keys
  57. jx.utils.values = function(rec){
  58. var r = []
  59. for(id in rec){
  60. var value = rec[id]
  61. r.push(value)
  62. }
  63. return r
  64. }
  65. /**
  66. * This function will returnt he unique elements of a list
  67. * @param list list of elements (duplicates are expected)
  68. */
  69. jx.utils.unique = function (list,getKey){
  70. var obj = {}
  71. for(var i=0; i < list.length; i++){
  72. if(list[i].constructor == Object && getKey != null){
  73. var key = getKey(list[i]) ;
  74. obj[key] = list[i] ;
  75. }else{
  76. obj[list[i]]= 1 ;
  77. }
  78. }
  79. if(getKey == null){
  80. return jx.utils.keys(obj);
  81. }else{
  82. //
  83. // This will return the unique list of objects, provided the user has given a key extraction function
  84. // The key extraction function is analogous to the equal operator in C++
  85. //
  86. return jx.utils.patterns.visitor(jx.utils.keys(obj),function(id){
  87. return obj[id] ;
  88. })
  89. }
  90. }
  91. jx.utils.join = function(x,y){
  92. if(x.length != y.length){
  93. return []
  94. }else{
  95. var rec = x ;
  96. for(var i in rec){
  97. //
  98. //@TODO: Consider the case we are adding to a matrix
  99. //
  100. rec[i] = [x[i],y[i]]
  101. }
  102. return rec ;
  103. }
  104. }
  105. jx.utils.size = function(id){
  106. if(id.match(/window|screen/i)){
  107. var width = window.innerWidth
  108. || document.documentElement.clientWidth
  109. || document.body.clientWidth;
  110. var height = window.innerHeight
  111. || document.body.clientHeight;
  112. }else if(jx.dom.exists(id)){
  113. var element = jx.dom.get.instance(id)
  114. var width = element.clientWdith
  115. var height = element.clientHeight
  116. }
  117. return {width:width,height:height}
  118. }
  119. /**
  120. * Implementation of a few standard design patterns. Their use is user/dependent
  121. * For more information on how/when to use a design pattern please use google/wikipedia ;-)
  122. */
  123. jx.utils.patterns = {}
  124. jx.utils.patterns.visitor = function(list,pointer){
  125. var rlist = [] ;
  126. for(var i=0; i < list.length; i++){
  127. value = pointer(list[i]) ;
  128. if(value != null){
  129. rlist.push(value) ;
  130. }
  131. }
  132. return (rlist.length > 0)?rlist:[];
  133. }
  134. /**
  135. * Implementation of an iterator design pattern: i.e we use a sequence of objects and call a given method on them
  136. * This is a basic iterator design pattern
  137. */
  138. jx.utils.patterns.iterator = function(list,pointer){
  139. for(var i=0; i < list.length; i++){
  140. list[i][pointer]();
  141. }
  142. }
  143. /**
  144. * This is an implementation of an observer design pattern, the obervers will just have to call notify on the subject
  145. * The observers' role is to render some stuff on the ui, having said this, this design pattern is suited for ui & asynchronous tasks
  146. * @param lobservers list of observers
  147. * @param init pointer to be called on each observer to trigger it
  148. */
  149. jx.utils.patterns.observer = function(lobservers,init){
  150. var p = {} ; //-- specification of the subject
  151. p.index = 0;
  152. p.nodes = lobservers ;
  153. p.pointer = init;
  154. p.notify = function(){
  155. //
  156. // This function is designed to be called by the observers
  157. //
  158. if( this.index < this.nodes.length){
  159. this.start() ;
  160. }
  161. }
  162. p.start = function(){
  163. var observer = this.nodes[this.index];
  164. try{
  165. ++this.index;
  166. if(this.pointer.constructor == String){
  167. observer[this.pointer](this) ;
  168. }else{
  169. this.pointer(observer);
  170. this.notify() ;
  171. }
  172. }catch(e){
  173. //
  174. // if an exception was thrown, chances are were unable to increment and call notify
  175. // In the spirit of "The show must go on", we will make the notify call here for the failed observer
  176. //
  177. ++this.index ;
  178. this.notify();
  179. }
  180. }
  181. //
  182. // let's fire the design pattern
  183. //
  184. p.start() ;
  185. }
  186. /**
  187. * Apply a function to an array (visitor-like design pattern)
  188. * @param fn casting function on the vector or array of data
  189. * @param list array of numeric data (hopefully)
  190. * @return array containing casted type
  191. */
  192. jx.utils.cast = jx.utils.patterns.visitor ;