as.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. ;(function(){
  2. function as(el, gun, cb, opt){
  3. el = $(el);
  4. if(gun === as.gui && as.el && as.el.is(el)){ return }
  5. opt = opt || {};
  6. opt.match = opt.match || '{{ ';
  7. opt.end = opt.end || ' }}';
  8. ;(function(){ // experimental
  9. function nest(t, s,e, r, i,tmp,u){
  10. if(r && !r.length){ return t||'' }
  11. if(!t){ return [] }
  12. e = e || s;
  13. i = t.indexOf(s, i||0);
  14. if(0 > i){ return [] }
  15. tmp = t.indexOf(e, i+1);
  16. if(!r){ return [t.slice(i+s.length, tmp)].concat(nest(t, s,e, r, tmp,tmp,u)) }
  17. return t.slice(0,i)+r[0]+nest(t.slice(tmp+e.length), s,e, r.slice(1), 0,tmp,u);
  18. }
  19. /* experimental */
  20. function template(tag, attr){
  21. var html = (tag = $(tag))[0].outerHTML, sub, tmp;
  22. if(html && (0 > html.indexOf(opt.match))){ return }
  23. if(!attr){
  24. $.each(tag[0].attributes, function(i,v){
  25. if(!v){ return }
  26. if(!nest(v.value, opt.match, opt.end).length){ return }
  27. template(tag, v.name)
  28. });
  29. if((sub = tag.children()).length){
  30. return sub.each(function(){ template(this) });
  31. }
  32. }
  33. var data = [], plate = attr? tag.attr(attr) : tag.html();
  34. tmp = nest(plate, opt.match, opt.end);
  35. if(!tmp.length){ return }
  36. $.each(tmp, function(pos, match){
  37. var expr = match.split(' ');
  38. var path = (expr[0]).split('.');
  39. if(expr = expr.slice(1).join(' ')){
  40. expr = new Function("_", "b", "return (_)" + expr);
  41. }
  42. var val = (expr && expr('')) || '';
  43. data.push(val);
  44. if(!attr){ tag.text(val) }
  45. var ref = gun, sup = [], tmp;
  46. if(tmp = tag.attr('name')){ sup.push(tmp) }
  47. tag.parents("[name]").each(function(){
  48. sup.push($(this).attr('name'));
  49. });
  50. $.each(path = sup.reverse().concat(path), function(i,v){
  51. ref = ref.get(v);
  52. });
  53. ref.on(function(v){
  54. v = data[pos] = expr? expr(v) : v;
  55. var tmp = nest(plate, opt.match, opt.end, data);
  56. if(attr){
  57. tag.attr(attr, tmp);
  58. } else {
  59. tag.text(tmp);
  60. }
  61. });
  62. });
  63. }
  64. template(el);
  65. }());
  66. as.gui = gun;
  67. as.el = el;
  68. if(el.data('as')){
  69. el.html(el.data('as').fresh);
  70. } else {
  71. el.data('as', {
  72. fresh: el.html()
  73. })
  74. }
  75. el.find("[name]").each(function(){
  76. if($(this).find("[name]").length){ return }
  77. var name = $(this),
  78. parents = name.parents("[name]"),
  79. path = [],
  80. ref = gun;
  81. path.push(name.attr('name'));
  82. parents.each(function(){
  83. path.push($(this).attr('name'));
  84. });
  85. path = path.reverse();
  86. path.forEach(function(key){
  87. if('#' === key){
  88. ref = ref.map()
  89. } else {
  90. ref = ref.get(key);
  91. }
  92. });
  93. var many = path.slice().reverse().indexOf('#'), model;
  94. many = (0 < ++many)? many : false;
  95. if(many){
  96. model = name.closest("[name='#']");
  97. model = model.data('model') || model.data('model', {$: model.clone(), on: model.parent(), has: {}}).hide().data('model');
  98. }
  99. ref.get(function(at){
  100. var data = at.put, key = at.get, gui = at.gun || at.$, ui = name, back;
  101. if(model){
  102. ui = model.has[(gui._).id];
  103. if(!ui){
  104. back = gui.back(many - 1);
  105. ui = model.has[(back._).id];
  106. if(!ui){
  107. if(!(back._).get){ return }
  108. ui = (model.has[(back._).id] = model.$.clone(true).prependTo(model.on));
  109. }
  110. ui = ui.find("[name='"+key+"']").first();
  111. model.has[(gui._).id] = ui;
  112. }
  113. }
  114. ui.data('gun', gui);
  115. if(ui.data('was') === data){ return }
  116. if(many && ui.is('.sort')){
  117. var up = ui.closest("[name='#']");
  118. var tmp = as.sort(data, up.parent().children().last());
  119. tmp? up.insertAfter(tmp) : up.prependTo(up.parent());
  120. }
  121. if(as.lock === gui){ return }
  122. if(!(data && data instanceof Object)){
  123. (ui[0] && u === ui[0].value)? ui.text(data) : ui.val(data);
  124. }
  125. ui.data('was', data);
  126. if(cb){
  127. cb(data, key, ui);
  128. }
  129. });
  130. });
  131. }
  132. as.wait = function(cb, wait, to){
  133. return function(a,b,c){
  134. var me = as.typing = this;
  135. clearTimeout(to);
  136. to = setTimeout(function(){
  137. cb.call(me, a,b,c);
  138. as.typing = me = false;
  139. }, wait || 200);
  140. }
  141. }
  142. as.sort = function sort(num, li){ return parseFloat(num) >= parseFloat($(li).find('.sort').text() || -Infinity)? li : sort(num, li.prev()) }
  143. $(document).on('keyup', 'input, textarea, [contenteditable]', as.wait(function(){
  144. var el = $(this);
  145. var data = (el[0] && u === el[0].value)? el.text() : el.val();
  146. var g = el.data('gun');
  147. if(!g){ return }
  148. as.lock = g;
  149. g.put(data);
  150. }, 99));
  151. //$(document).on('submit', 'form', function(e){ e.preventDefault() });
  152. var u;
  153. window.as = as;
  154. $.as = as;
  155. }());
  156. ;(function(){
  157. $(document).on('click', 'a, button', function(e){
  158. var tmp = $(this).attr('href') || '';
  159. if(0 === tmp.indexOf('http')){ return }
  160. e.preventDefault();
  161. r(tmp);
  162. });
  163. function r(href){
  164. if(!href){ return }
  165. if(href[0] == '#'){ href = href.slice(1) }
  166. var h = href.split('/')[0];
  167. $('.page').hide();
  168. $('#' + h).show();
  169. if(r.on === h){ return }
  170. location.hash = href;
  171. (r.page[h] || {on:function(){}}).on();
  172. r.on = h;
  173. return r;
  174. };
  175. r.page = function(h, cb){
  176. r.page[h] = r.page[h] || {on: cb};
  177. return r;
  178. }
  179. r.render = function(id, model, onto, data){
  180. var $data = $(
  181. $('#' + id).get(0) ||
  182. $('.model').find(model).clone(true).attr('id', id).appendTo(onto)
  183. );
  184. $.each(data, function(field, val){
  185. if($.isPlainObject(val)){ return }
  186. $data.find("[name='" + field + "']").val(val).text(val);
  187. });
  188. return $data;
  189. }
  190. window.onhashchange = function(){ r(location.hash.slice(1)) };
  191. $.as && ($.as.route = r);
  192. if(window.as){
  193. as.route = r;
  194. } else {
  195. $.route = r;
  196. }
  197. }());
  198. ;$(function(){
  199. $('.page').not(':first').hide();
  200. $.as.route(location.hash.slice(1));
  201. $(JOY.start = JOY.start || function(){ $.as(document, gun, null, JOY.opt) });
  202. if($('body').attr('peers')){ (console.warn || console.log)('Warning: Please upgrade <body peers=""> to https://github.com/eraeco/joydb#peers !') }
  203. });
  204. ;(function(){ // need to isolate into separate module!
  205. var joy = window.JOY = function(){};
  206. joy.auth = function(a,b,cb,o){
  207. if(!o){ o = cb ; cb = 0 }
  208. if(o === true){
  209. gun.user().create(a, b);
  210. return;
  211. }
  212. gun.user().auth(a,b, cb,o);
  213. }
  214. var opt = joy.opt = window.CONFIG || {}, peers;
  215. $('link[type=peer]').each(function(){ (peers || (peers = [])).push($(this).attr('href')) });
  216. !window.gun && (opt.peers = opt.peers || peers || (function(){
  217. (console.warn || console.log)('Warning: No peer provided, defaulting to DEMO peer. Do not run in production, or your data will be regularly wiped, reset, or deleted. For more info, check https://github.com/eraeco/joydb#peers !');
  218. return ['https://gunjs.herokuapp.com/gun'];
  219. }()));
  220. window.gun = window.gun || Gun(opt);
  221. gun.on('auth', function(ack){
  222. console.log("Your namespace is publicly available at", ack.soul);
  223. });
  224. }());