index.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. // TODO - Add initial page loading and handlers
  2. (function($,History){
  3. var State = History.getState(),
  4. Old = {},
  5. Key = null,
  6. flags = [],
  7. templates = [],
  8. flag = window.flag = function(name,value){
  9. if(exists(value)){
  10. flags[name] = value;
  11. }else{
  12. return exists(flags[name])?flags[name]:false;
  13. }
  14. },
  15. settings = {},
  16. exists = function(v){
  17. return typeof v != 'undefined';
  18. },
  19. get = window.get = function(s){
  20. return settings[s];
  21. },
  22. set = window.set = function(s,v){
  23. settings[s] = v;
  24. return v;
  25. },
  26. setKey = window.setKey = function(key){
  27. if(key !== null){
  28. console.log('Key change to '+key);
  29. Key = key;
  30. var d = new Date();
  31. d.setTime(d.getTime()+get('expire'));
  32. $.cookie('key',key,{
  33. expires: d
  34. });
  35. }else{
  36. console.log('Key deleted');
  37. Key = null;
  38. $.removeCookie('key');
  39. }
  40. },
  41. getKey = window.getKey = function(){
  42. return Key;
  43. },
  44. template = window.template = function(name,template){
  45. if(exists(template)){
  46. templates[name] = {
  47. template: template,
  48. date: get('expire')+new Date
  49. };
  50. $.localStorage('templates',templates);
  51. }else if(exists(templates[name])){
  52. console.log('Using cached template for: '+name);
  53. var template = templates[name].template;
  54. if(templates[name].date < +new Date){
  55. delete templates[name];
  56. $.localStorage('templates',templates);
  57. }
  58. return template;
  59. }else{
  60. console.log('No cached template stored for: '+name);
  61. return '';
  62. }
  63. },
  64. apiCall = window.apiCall = function(data,callback){
  65. console.log('apiCall('+data.type+'-'+data.id+')');
  66. $('#loading').show();
  67. data.get = 'api';
  68. data.timestamp = +new Date;
  69. if(exists(templates[data.type+'-'+data.id])){
  70. data.template = false;
  71. }
  72. $.get(location.href,data,function(d){
  73. if(exists(d['error'])){
  74. error(d);
  75. }else{
  76. if(location.href.substr(location.href.lastIndexOf('/')+1) != d.state.url){
  77. console.log('Forced redirection to '+d.state.url);
  78. History.replaceState(d.state.data,d.state.title,d.state.url);
  79. }
  80. }
  81. if(exists(callback)){
  82. callback(d);
  83. }
  84. },'json');
  85. },
  86. loadState = window.loadState = function(href,callback){
  87. console.log('loadState('+href+')');
  88. $('#loading').show();
  89. var data = {
  90. get:'state',
  91. timestamp: +new Date
  92. };
  93. $.get(href,data,function(d){
  94. if(exists(d['error'])){
  95. error(d);
  96. }else{
  97. History.pushState(d.state.data,d.state.title,href);
  98. getNewState();
  99. }
  100. if(exists(callback)){
  101. callback(d);
  102. }
  103. },'json');
  104. },
  105. apiState = window.apiState = function(href,callback){
  106. console.log('apiState('+href+')');
  107. $('#loading').show();
  108. var data = {
  109. get:'state',
  110. timestamp: +new Date
  111. };
  112. $.get(href,data,function(d){
  113. if(exists(d['error'])){
  114. error(d);
  115. }else{
  116. History.replaceState(d.state.data,d.state.title,href);
  117. getNewState();
  118. }
  119. if(exists(callback)){
  120. callback(d);
  121. }
  122. },'json');
  123. },
  124. error = function(e){
  125. e = '['+State.url+']'+e.error;
  126. console.error(e+"\n"+(exists(e.state)?JSON.stringify(e.state):''));
  127. alert(e);
  128. },
  129. getNewState = function(){
  130. State = History.getState();
  131. console.log("State change. "+JSON.stringify(State.data));
  132. if (!window.location.origin) {
  133. window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
  134. }
  135. },
  136. equal = function(o1,o2){
  137. for(var i in o1){
  138. if(!exists(o2[i])||o2[i]!=o1[i]){
  139. return false;
  140. }
  141. }
  142. for(i in o2){
  143. if(!exists(o1[i])||o2[i]!=o1[i]){
  144. return false;
  145. }
  146. }
  147. return true;
  148. },
  149. render = window.render = {
  150. topbar: function(t,c){
  151. $('#topbar').html(Handlebars.compile(t)(c));
  152. render.links('#topbar');
  153. },
  154. content: function(t,c){
  155. $('#content').html(
  156. Handlebars.compile(t)(c)
  157. );
  158. render.links('#content');
  159. $(window).resize();
  160. },
  161. links: function(selector){
  162. $(selector).find('a').each(function(){
  163. var href = this.href;
  164. if(href.indexOf('#')!=-1&&(href.indexOf(location.origin)!=-1||href.indexOf('#')==0)){
  165. href = href.substr(href.indexOf('#')+1);
  166. $(this).click(function(e){
  167. try{
  168. if(($(this).hasClass('topbar-home') || $(this).hasClass('topbar-back'))&&$(window).width()<767){
  169. $('#topbar').children('div.topbar-right,div.topbar-left').toggle();
  170. $('#topbar').resize();
  171. }else if($(this).hasClass('topbar-history')){
  172. History.back();
  173. }else{
  174. loadState(href);
  175. }
  176. }catch(error){
  177. console.error(error);
  178. }
  179. e.preventDefault();
  180. return false;
  181. });
  182. }
  183. });
  184. }
  185. };
  186. if(exists($.cookie('key'))){
  187. setKey($.cookie('key'));
  188. }else{
  189. setKey(null);
  190. }
  191. $(document).ready(function(){
  192. templates = $.localStorage('templates');
  193. if(templates === null){
  194. templates = [];
  195. }
  196. if(!exists($.support.touch)){
  197. $.support.touch = 'ontouchstart' in window || 'onmsgesturechange' in window;
  198. }
  199. $(window).on('statechange',function(){
  200. getNewState();
  201. if(!equal(State.data,Old)){
  202. document.title = State.title;
  203. switch(State.data.type){
  204. case 'page':case 'user':
  205. apiCall(State.data,function(d){
  206. if(exists(d.context)){
  207. if(!exists(d.context.key)&&Key!==null){
  208. console.log('Context detected logout');
  209. setKey(null);
  210. }
  211. if(exists(d.template)){
  212. template(State.data.type+'-'+State.data.id,d.template);
  213. }else{
  214. d.template = template(State.data.type+'-'+State.data.id);
  215. }
  216. render.topbar(d.topbar.template,d.topbar.context);
  217. render.content(d.template,d.context);
  218. $('#loading').hide();
  219. }else{
  220. console.error('No context given');
  221. History.back();
  222. }
  223. });
  224. break;
  225. case 'action':break;
  226. default:
  227. error({
  228. url: State.url,
  229. error: "Something went wrong!"
  230. });
  231. }
  232. Old = State.data;
  233. }else{
  234. console.log(State.data,Old);
  235. console.warn('Stopped double load of '+Old.type+'-'+Old.id);
  236. $('#loading').hide();
  237. }
  238. });
  239. if($.isEmptyObject(State.data)){
  240. History.replaceState({
  241. type: 'page',
  242. id: 'index'
  243. },'Bugs','page-index');
  244. console.log('Forcing default state.');
  245. }else{
  246. flag('load',true);
  247. }
  248. var data = {
  249. get: 'settings',
  250. timestamp: +new Date
  251. };
  252. $.get(location.href,data,function(d){
  253. settings = d;
  254. apiState(location.href,function(){
  255. if(flag('load')){
  256. State.data = {
  257. type: '',
  258. data: ''
  259. };
  260. }
  261. flag('load',false);
  262. });
  263. },'json');
  264. $('#content').niceScroll({
  265. cursorwidth: 10,
  266. nativeparentscrolling: false,
  267. preservenativescrolling: false
  268. });
  269. document.addEventListener('touchmove',function(e){
  270. e.preventDefault();
  271. });
  272. });
  273. $(window).resize(function(){
  274. if($(window).width()>767){
  275. $('#topbar div.topbar-right, #topbar div.topbar-left').css({
  276. 'display': ''
  277. });
  278. }
  279. $('#content').height($('body').height()-$('#topbar').height());
  280. $('#content').getNiceScroll().resize();
  281. }).resize();
  282. $('#topbar').resize(function(){
  283. $(window).resize();
  284. });
  285. shortcut.add('f12',function(){
  286. if(!flag('firebug-lite')){
  287. (function(F,i,r,e,b,u,g,L,I,T,E){
  288. if(F.getElementById(b))
  289. return;
  290. E=F[i+'NS']&&F.documentElement.namespaceURI;
  291. E=E?F[i+'NS'](E,'script'):F[i]('script');
  292. E[r]('id',b);
  293. E[r]('src',I+g+T);
  294. E[r](b,u);
  295. (F[e]('head')[0]||F[e]('body')[0]).appendChild(E);
  296. E=new Image;
  297. E[r]('src',I+L);
  298. })(document,'createElement','setAttribute','getElementsByTagName','FirebugLite','4','firebug-lite.js','releases/lite/latest/skin/xp/sprite.png','https://getfirebug.com/','#startOpened');
  299. flag('firebug-lite',true);
  300. }
  301. });
  302. $.fn.serializeObject = function(){
  303. var o = {},
  304. a = this.serializeArray();
  305. $.each(a,function(){
  306. if(o[this.name] !== undefined){
  307. if(!o[this.name].push){
  308. o[this.name] = [o[this.name]];
  309. }
  310. o[this.name].push(this.value || '');
  311. }else{
  312. o[this.name] = this.value || '';
  313. }
  314. });
  315. return o;
  316. };
  317. $.ajaxSetup({
  318. async: false
  319. });
  320. })(jQuery,History);