PageRenderTime 84ms CodeModel.GetById 64ms app.highlight 16ms RepoModel.GetById 2ms app.codeStats 0ms

/js/app.js

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