index.js 8.6 KB

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