PageRenderTime 105ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/resources/assets/js/app.js

https://bitbucket.org/atlassian/developer-toolbox
JavaScript | 407 lines | 362 code | 29 blank | 16 comment | 37 complexity | 73c332c24e26b87d03f119016892a5b3 MD5 | raw file
Possible License(s): Apache-2.0
  1. ;
  2. AJS.$('load', function($) {
  3. rest.slugify = function(str) {
  4. return str.toLowerCase().replace(/[^-a-zA-Z0-9,&\s]+/ig, '-').replace(/\s/gi, "-").replace(/^-/, '').replace(/-$/, '');
  5. };
  6. var Service = Backbone.Model.extend({});
  7. var Services = Backbone.Collection.extend({
  8. model: Service,
  9. findByKey: function(key) {
  10. return services.find(function(s) {
  11. return s.get('pluginCompleteKey') === key;
  12. });
  13. }
  14. });
  15. var Resource = Backbone.Model.extend({});
  16. var Resources = Backbone.Collection.extend({
  17. model: Resource
  18. });
  19. var services = [];
  20. rest.services = rest.services.sort(function(x, y) {
  21. return (x.pluginName < y.pluginName) ? - 1 : 1;
  22. });
  23. $.each(rest.services, function() {
  24. this.pluginCompleteKey = rest.slugify(this.pluginCompleteKey);
  25. services.push(new Service(this));
  26. });
  27. services = new Services(services);
  28. var ResourceBody = Backbone.View.extend({
  29. template: $('#rab-resource-body'),
  30. el: $('#rab'),
  31. initialize: function() {
  32. this.render();
  33. // Size and position sidebar and main content properly
  34. appViewController.sizeBoxes();
  35. },
  36. render: function() {
  37. $(window).scrollTop(0);
  38. console.log(1, this.model.toJSON());
  39. this.$el.html(this.template.tmpl(this.model.toJSON()));
  40. $(this.el).find('select[name=request]').each(function() {
  41. $(this).change();
  42. });
  43. prettyPrint();
  44. }
  45. });
  46. var CurrentService = Backbone.View.extend({
  47. el: $('.rab-curr-service'),
  48. template: $('#rab-header-tmpl'),
  49. initialize: function(model) {
  50. this.model = model;
  51. var self = this;
  52. this.render();
  53. new ServiceSelector(model);
  54. this.getResources(this.model.get('wadl'));
  55. },
  56. events: {
  57. 'click .rab-name': 'toggleDD',
  58. 'click .menu-item a': 'navigate'
  59. },
  60. render: function(model) {
  61. model = model || this.model;
  62. this.$('.rab-curr-head').html(this.template.tmpl(model.attributes));
  63. },
  64. name: function() {
  65. return this.model.get('pluginCompleteKey');
  66. },
  67. getResources: function(wadlUrl) {
  68. var self = this;
  69. processWADL(wadlUrl).done(function(d) {
  70. self.model.set(d);
  71. new ResourceBody({
  72. model: self.model
  73. });
  74. rest.resources = d;
  75. });
  76. },
  77. toggleDD: function(e) {
  78. if (this.$('.rab-services-dd').hasClass('rab-open')) {
  79. // Close the dd
  80. this.$('.rab-services-dd').removeClass('rab-open');
  81. this.$('.rab-dd-button').removeClass('rab-dd-button-open');
  82. } else {
  83. // Open the dd
  84. this.$('.rab-services-dd').css('left',
  85. function() {
  86. var point = e.clientX;
  87. var left = e.clientX - ($(this).width() / 2);
  88. return left > 0 ? left : 0;
  89. }).addClass('rab-open');
  90. this.$('.rab-dd-button').addClass('rab-dd-button-open');
  91. var self = this;
  92. $('body').bind('click', function() {
  93. if ($('.rab-services-dd').hasClass('rab-open')) {
  94. self.toggleDD(e);
  95. }
  96. $('body').unbind('click');
  97. return false
  98. });
  99. }
  100. return false;
  101. },
  102. navigate: function(e) {
  103. var target = $(e.currentTarget);
  104. // Disabled for Bamboo
  105. console.log('before routing',$('body'))
  106. if ($('body').id !== 'jira' && $('body').id !== 'com-atlassian-confluence') {
  107. console.log('routing')
  108. appRouter.navigate(target.attr('href'));
  109. }
  110. this.toggleDD(e);
  111. this.switchService(target.data('id'));
  112. return false;
  113. },
  114. switchService: function(key) {
  115. if (!key) {
  116. this.model = services.first();
  117. } else {
  118. this.model = services.findByKey(key);
  119. }
  120. this.render(this.model);
  121. this.getResources(this.model.get('wadl'));
  122. }
  123. });
  124. var ServicesDDItem = Backbone.View.extend({
  125. template: $('#rab-menu-item'),
  126. initialize: function() {
  127. this.render();
  128. },
  129. render: function() {
  130. $('.rab-services-dd').append(this.template.tmpl(this.model.toJSON()));
  131. }
  132. });
  133. var ServiceSelector = Backbone.View.extend({
  134. el: $('.rab-service-selector'),
  135. initialize: function(model) {
  136. services.each(function(service) {
  137. new ServicesDDItem({
  138. model: service
  139. });
  140. });
  141. }
  142. });
  143. var BrowserView = Backbone.View.extend({
  144. initialize: function(model) {
  145. rest.currService = new CurrentService(model);
  146. }
  147. });
  148. // Main view controller. Initialized only once.
  149. var AppViewController = Backbone.View.extend({
  150. el: $(window),
  151. events: {
  152. 'submit .rab-endpoint': 'performCall',
  153. 'click .rab-clear': 'clearOutput',
  154. 'change select[name=request]': 'changeRequest',
  155. 'change select[name=representation]': 'changeResponse',
  156. 'resize': 'sizeBoxes',
  157. 'click .rab-resources-sb a': 'scrollToResource',
  158. 'scroll': 'handleScroll',
  159. 'click .rab-add-custom-param': 'addCustomParam',
  160. 'click .rab-delete-custom-param': 'deleteCustomParam'
  161. },
  162. initialize:function() {
  163. // Stupid fucking hack to combat against fecru's weird
  164. // header positioning... lame.
  165. if ($('body > div.layoutCentredPane').length) {
  166. this.headerOffset = 0;
  167. } else {
  168. this.headerOffset = $('#header').height();
  169. }
  170. },
  171. addCustomParam: function(e) {
  172. var params = $(e.currentTarget).parent().parent();
  173. $('#rab-custom-param-tmpl').tmpl().insertBefore(params);
  174. return false;
  175. },
  176. deleteCustomParam: function(e) {
  177. $(e.currentTarget).parent().parent().remove();
  178. return false;
  179. },
  180. sizeBoxes: function() {
  181. var self = this;
  182. $('.rab-sidebar').height(function() {
  183. return self.$el.height() - 10;
  184. });
  185. this.origSidebarTop = $('.rab-sidebar').scrollTop();
  186. this.origSidebarOffsetTop = $('.rab-sidebar').offset().top;
  187. this.origSidebarWidth = $('.rab-sidebar').width();
  188. this.winHeight = this.$el.height();
  189. this.handleScroll();
  190. },
  191. handleScroll: function(w) {
  192. var currPosn, contentBottom, x = $('.rab-resources').position().left, top = this.$el.scrollTop(), elFromPoint = $(document.elementFromPoint(x, 5));
  193. // Highlight selected resource in sidebar as the main content
  194. // is scrolled.
  195. if (elFromPoint.hasClass('rab-resource')) {
  196. $('.rab-resource-sb a').removeClass('rab-resource-sb-active');
  197. $('#rab-nav-' + elFromPoint.data('id')).addClass('rab-resource-sb-active');
  198. }
  199. // Fix the sidebar as the main content container is scrolled allowing
  200. // for easy access to resources without it scrolling off the screen.
  201. currPosn = top + appViewController.winHeight;
  202. if (top > appViewController.origSidebarOffsetTop) {
  203. contentBottom = this.origSidebarOffsetTop + $('.rab-content').height();
  204. if (currPosn > contentBottom) {
  205. $('.rab-sidebar').css({
  206. top: contentBottom - currPosn
  207. });
  208. } else {
  209. $('.rab-sidebar').css({
  210. position: "fixed",
  211. top: 0,
  212. width: appViewController.origSidebarWidth
  213. });
  214. $('.rab-content').css({
  215. marginLeft: "20%"
  216. });
  217. }
  218. } else {
  219. $('.rab-sidebar').css({
  220. position: "static",
  221. width: "20%"
  222. });
  223. $('.rab-content').css({
  224. marginLeft: "0"
  225. });
  226. }
  227. },
  228. scrollToResource:function(e) {
  229. var self = $(e.currentTarget);
  230. $('.rab-resource-sb a').removeClass('rab-resource-sb-active');
  231. self.addClass('rab-resource-sb-active');
  232. $(window).scrollTop($(self.attr('href')).position().top + this.headerOffset);
  233. return false;
  234. },
  235. performCall: function(e) {
  236. var queryParams, jsonRpcParams, customParams, data, outputType,
  237. form = $(e.currentTarget),
  238. url = form.attr('action'),
  239. method = form.attr('method'),
  240. representation = form.find('select[name=representation]').val();
  241. $.each(form.find('.rab-param-style-template'), function() {
  242. var self = $(this), pat = new RegExp('\{' + self.attr('name') + '\:?(.*)\}', 'g');
  243. url = url.replace(pat, self.val());
  244. });
  245. queryParams = $.map(form.find('.rab-param-style-query'), function(e) {
  246. var self = $(e);
  247. if (self.val() !== '')
  248. return self.serialize();
  249. });
  250. jsonRpcParams = [].concat($.map(form.find('.rab-param-style-jsonRpc'), function(e) {
  251. return $(e).val();
  252. }));
  253. customParams = $.map(form.find('.rab-custom-params'), function(e) {
  254. var self = $(e), paramName = self.find('.rab-param-style-custom-name').val(), paramVal = self.find('.rab-param-style-custom-value').val();
  255. if (paramName && paramVal)
  256. return paramName + "=" + paramVal;
  257. });
  258. $.merge($.merge(queryParams, jsonRpcParams), customParams);
  259. if (queryParams.length > 0) {
  260. url += "?" + queryParams.join('&');
  261. }
  262. if (jsonRpcParams.length > 0) {
  263. data = JSON.stringify(jsonRpcParams);
  264. representation = 'application/json';
  265. } else if (method === "POST" || method === "PUT") {
  266. data = form.find('textarea').val();
  267. if (data.trim() === "") {
  268. data = "{}";
  269. }
  270. }
  271. if (representation === 'application/xml') {
  272. outputType = 'xml';
  273. } else if (representation === 'text/plain') {
  274. outputType = 'text';
  275. } else {
  276. outputType = 'json';
  277. }
  278. $.ajax({
  279. url: url,
  280. type: method,
  281. data: data,
  282. contentType: representation,
  283. dataType: outputType,
  284. beforeSend: function() {
  285. form.find('.rab-throbber').removeClass('hidden');
  286. form.find('.rab-exec').attr('disabled', 'disabled');
  287. },
  288. complete: function() {
  289. form.find('.rab-throbber').addClass('hidden');
  290. form.find('.rab-exec').removeAttr('disabled');
  291. }
  292. }).done(
  293. function(d, msg, o) {
  294. var contentType, rsp = {};
  295. rsp.headers = o.getAllResponseHeaders();
  296. contentType = o.getResponseHeader('Content-Type');
  297. if (/^application\/xml/.test(contentType)) {
  298. rsp.body = o.responseText;
  299. } else {
  300. try {
  301. rsp.body = JSON.stringify(d, null, 2);
  302. } catch(e) {
  303. try {
  304. rsp.body = d.documentElement.innerHTML;
  305. } catch(e) {
  306. rsp.body = d;
  307. }
  308. }
  309. }
  310. if (rsp.body == null) rsp.body = "";
  311. rsp.call = method + " " + url + " (" + o.status + ")";
  312. form.next().html($('#rab-output-tmpl').tmpl(rsp));
  313. prettyPrint();
  314. }).fail(function(o, msg, descr) {
  315. var rsp = {};
  316. rsp.headers = o.getAllResponseHeaders();
  317. try {
  318. rsp.body = JSON.stringify(JSON.parse(o.responseText), null, 2);
  319. } catch(e) {
  320. rsp.body = o.responseText;
  321. }
  322. if (rsp.body == null) rsp.body = "";
  323. rsp.call = method + " " + url + " (" + o.status + ")";
  324. form.next().html($('#rab-output-tmpl').tmpl(rsp));
  325. prettyPrint();
  326. });
  327. return false;
  328. },
  329. clearOutput:function(e) {
  330. $(e.currentTarget).parent().next().empty();
  331. return false;
  332. },
  333. changeRequest: function(e) {
  334. var $select = $(e.currentTarget)
  335. var $option = $select.find('option[value="' + $select.val() +'"]');
  336. $($select[0].form).find('textarea').val($option.attr('example'));
  337. },
  338. changeResponse: function(e) {
  339. var $select = $(e.currentTarget),
  340. $option = $select.find('option[value="' + $select.val() +'"]'),
  341. $form = $select.closest('form'),
  342. rsp = {body: $option.attr('example')};
  343. if (rsp.body) {
  344. $form.next().html($('#rab-sample-output-tmpl').tmpl(rsp));
  345. prettyPrint();
  346. }
  347. }
  348. });
  349. var appViewController = new AppViewController();
  350. var AppRouter = Backbone.Router.extend({
  351. routes: {
  352. '/': 'home',
  353. '/:key': 'service',
  354. '*page': 'catchAll'
  355. },
  356. home: function() {
  357. new BrowserView(services.first());
  358. },
  359. service: function(key) {
  360. var svc = services.findByKey(key);
  361. if (svc) {
  362. new BrowserView(svc);
  363. } else {
  364. appRouter.navigate('/');
  365. }
  366. },
  367. catchAll: function() {
  368. this.navigate('/', true);
  369. }
  370. });
  371. var appRouter = new AppRouter();
  372. // Workaround to Bamboo's shitty DOMContentLoad bug
  373. // if ($('body#jira').length > 0 || $('body#com-atlassian-confluence').length > 0) {
  374. // Backbone.history.start();
  375. // } else {
  376. new BrowserView(services.first());
  377. // }
  378. });