'use strict'; SwaggerUi.Views.OperationView = Backbone.View.extend({ invocationUrl: null, events: { 'submit .sandbox' : 'submitOperation', 'click .submit' : 'submitOperation', 'click .response_hider' : 'hideResponse', 'click .toggleOperation' : 'toggleOperationContent', 'mouseenter .api-ic' : 'mouseEnter', 'mouseout .api-ic' : 'mouseExit', }, initialize: function(opts) { opts = opts || {}; this.router = opts.router; this.auths = opts.auths; this.parentId = this.model.parentId; this.nickname = this.model.nickname; this.model.encodedParentId = encodeURIComponent(this.parentId); return this; }, mouseEnter: function(e) { var elem = $(this.el).find('.content'); var x = e.pageX; var y = e.pageY; var scX = $(window).scrollLeft(); var scY = $(window).scrollTop(); var scMaxX = scX + $(window).width(); var scMaxY = scY + $(window).height(); var wd = elem.width(); var hgh = elem.height(); if (x + wd > scMaxX) { x = scMaxX - wd; } if (x < scX) { x = scX; } if (y + hgh > scMaxY) { y = scMaxY - hgh; } if (y < scY) { y = scY; } var pos = {}; pos.top = y; pos.left = x; elem.css(pos); $(e.currentTarget.parentNode).find('#api_information_panel').show(); }, mouseExit: function(e) { $(e.currentTarget.parentNode).find('#api_information_panel').hide(); }, // Note: copied from CoffeeScript compiled file // TODO: redactor render: function() { var a, auth, auths, code, contentTypeModel, isMethodSubmissionSupported, k, key, l, len, len1, len2, len3, len4, m, modelAuths, n, o, p, param, q, ref, ref1, ref2, ref3, ref4, ref5, responseContentTypeView, responseSignatureView, schema, schemaObj, scopeIndex, signatureModel, statusCode, successResponse, type, v, value; isMethodSubmissionSupported = jQuery.inArray(this.model.method, this.model.supportedSubmitMethods()) >= 0; if (!isMethodSubmissionSupported) { this.model.isReadOnly = true; } this.model.description = this.model.description || this.model.notes; this.model.oauth = null; modelAuths = this.model.authorizations || this.model.security; if (modelAuths) { if (Array.isArray(modelAuths)) { for (l = 0, len = modelAuths.length; l < len; l++) { auths = modelAuths[l]; for (key in auths) { auth = auths[key]; for (a in this.auths) { auth = this.auths[a]; if (auth.type === 'oauth2') { this.model.oauth = {}; this.model.oauth.scopes = []; ref1 = auth.value.scopes; for (k in ref1) { v = ref1[k]; scopeIndex = auths[key].indexOf(k); if (scopeIndex >= 0) { o = { scope: k, description: v }; this.model.oauth.scopes.push(o); } } } } } } } else { for (k in modelAuths) { v = modelAuths[k]; if (k === 'oauth2') { if (this.model.oauth === null) { this.model.oauth = {}; } if (this.model.oauth.scopes === void 0) { this.model.oauth.scopes = []; } for (m = 0, len1 = v.length; m < len1; m++) { o = v[m]; this.model.oauth.scopes.push(o); } } } } } if (typeof this.model.responses !== 'undefined') { this.model.responseMessages = []; ref2 = this.model.responses; for (code in ref2) { value = ref2[code]; schema = null; schemaObj = this.model.responses[code].schema; if (schemaObj && schemaObj.$ref) { schema = schemaObj.$ref; if (schema.indexOf('#/definitions/') === 0) { schema = schema.substring('#/definitions/'.length); } } this.model.responseMessages.push({ code: code, message: value.description, responseModel: schema }); } } if (typeof this.model.responseMessages === 'undefined') { this.model.responseMessages = []; } signatureModel = null; if (this.model.successResponse) { successResponse = this.model.successResponse; for (key in successResponse) { value = successResponse[key]; this.model.successCode = key; if (typeof value === 'object' && typeof value.createJSONSample === 'function') { signatureModel = { sampleJSON: JSON.stringify(value.createJSONSample(), void 0, 2), isParam: false, signature: value.getMockSignature() }; } } } else if (this.model.responseClassSignature && this.model.responseClassSignature !== 'string') { signatureModel = { sampleJSON: this.model.responseSampleJSON, isParam: false, signature: this.model.responseClassSignature }; } $(this.el).html(Handlebars.templates.operation(this.model)); if (signatureModel) { responseSignatureView = new SwaggerUi.Views.SignatureView({ model: signatureModel, router: this.router, tagName: 'div' }); $('.model-signature', $(this.el)).append(responseSignatureView.render().el); } else { this.model.responseClassSignature = 'string'; $('.model-signature', $(this.el)).html(this.model.type); } contentTypeModel = { isParam: false }; contentTypeModel.consumes = this.model.consumes; contentTypeModel.produces = this.model.produces; ref3 = this.model.parameters; for (n = 0, len2 = ref3.length; n < len2; n++) { param = ref3[n]; type = param.type || param.dataType || ''; if (typeof type === 'undefined') { schema = param.schema; if (schema && schema.$ref) { ref = schema.$ref; if (ref.indexOf('#/definitions/') === 0) { type = ref.substring('#/definitions/'.length); } else { type = ref; } } } if (type && type.toLowerCase() === 'file') { if (!contentTypeModel.consumes) { contentTypeModel.consumes = 'multipart/form-data'; } } param.type = type; } responseContentTypeView = new SwaggerUi.Views.ResponseContentTypeView({ model: contentTypeModel, router: this.router }); $('.response-content-type', $(this.el)).append(responseContentTypeView.render().el); ref4 = this.model.parameters; for (p = 0, len3 = ref4.length; p < len3; p++) { param = ref4[p]; this.addParameter(param, contentTypeModel.consumes); } ref5 = this.model.responseMessages; for (q = 0, len4 = ref5.length; q < len4; q++) { statusCode = ref5[q]; this.addStatusCode(statusCode); } return this; }, addParameter: function(param, consumes) { // Render a parameter param.consumes = consumes; var paramView = new SwaggerUi.Views.ParameterView({ model: param, tagName: 'tr', readOnly: this.model.isReadOnly }); $('.operation-params', $(this.el)).append(paramView.render().el); }, addStatusCode: function(statusCode) { // Render status codes var statusCodeView = new SwaggerUi.Views.StatusCodeView({ model: statusCode, tagName: 'tr', router: this.router }); $('.operation-status', $(this.el)).append(statusCodeView.render().el); }, // Note: copied from CoffeeScript compiled file // TODO: redactor submitOperation: function(e) { var error_free, form, isFileUpload, l, len, len1, len2, m, map, n, o, opts, ref1, ref2, ref3, val; if (e !== null) { e.preventDefault(); } form = $('.sandbox', $(this.el)); error_free = true; form.find('input.required').each(function() { $(this).removeClass('error'); if (jQuery.trim($(this).val()) === '') { $(this).addClass('error'); $(this).wiggle({ callback: (function(_this) { return function() { $(_this).focus(); }; })(this) }); error_free = false; } }); form.find('textarea.required').each(function() { $(this).removeClass('error'); if (jQuery.trim($(this).val()) === '') { $(this).addClass('error'); $(this).wiggle({ callback: (function(_this) { return function() { return $(_this).focus(); }; })(this) }); error_free = false; } }); if (error_free) { map = {}; opts = { parent: this }; isFileUpload = false; ref1 = form.find('input'); for (l = 0, len = ref1.length; l < len; l++) { o = ref1[l]; if ((o.value !== null) && jQuery.trim(o.value).length > 0) { map[o.name] = o.value; } if (o.type === 'file') { map[o.name] = o.files[0]; isFileUpload = true; } } ref2 = form.find('textarea'); for (m = 0, len1 = ref2.length; m < len1; m++) { o = ref2[m]; if ((o.value !== null) && jQuery.trim(o.value).length > 0) { map[o.name] = o.value; } } ref3 = form.find('select'); for (n = 0, len2 = ref3.length; n < len2; n++) { o = ref3[n]; val = this.getSelectedValue(o); if ((val !== null) && jQuery.trim(val).length > 0) { map[o.name] = val; } } opts.responseContentType = $('div select[name=responseContentType]', $(this.el)).val(); opts.requestContentType = $('div select[name=parameterContentType]', $(this.el)).val(); $('.response_throbber', $(this.el)).show(); if (isFileUpload) { return this.handleFileUpload(map, form); } else { return this.model['do'](map, opts, this.showCompleteStatus, this.showErrorStatus, this); } } }, success: function(response, parent) { parent.showCompleteStatus(response); }, // Note: This is compiled code // TODO: Refactor handleFileUpload: function(map, form) { var bodyParam, el, headerParams, l, len, len1, len2, len3, m, n, o, obj, p, param, params, ref1, ref2, ref3, ref4; ref1 = form.serializeArray(); for (l = 0, len = ref1.length; l < len; l++) { o = ref1[l]; if ((o.value !== null) && jQuery.trim(o.value).length > 0) { map[o.name] = o.value; } } bodyParam = new FormData(); params = 0; ref2 = this.model.parameters; for (m = 0, len1 = ref2.length; m < len1; m++) { param = ref2[m]; if (param.paramType === 'form' || param['in'] === 'formData') { if (param.type.toLowerCase() !== 'file' && map[param.name] !== void 0) { bodyParam.append(param.name, map[param.name]); } } } headerParams = {}; ref3 = this.model.parameters; for (n = 0, len2 = ref3.length; n < len2; n++) { param = ref3[n]; if (param.paramType === 'header') { headerParams[param.name] = map[param.name]; } } ref4 = form.find('input[type~="file"]'); for (p = 0, len3 = ref4.length; p < len3; p++) { el = ref4[p]; if (typeof el.files[0] !== 'undefined') { bodyParam.append($(el).attr('name'), el.files[0]); params += 1; } } this.invocationUrl = this.model.supportHeaderParams() ? (headerParams = this.model.getHeaderParams(map), delete headerParams['Content-Type'], this.model.urlify(map, false)) : this.model.urlify(map, true); $('.request_url', $(this.el)).html('
');
    $('.request_url pre', $(this.el)).text(this.invocationUrl);
    obj = {
      type: this.model.method,
      url: this.invocationUrl,
      headers: headerParams,
      data: bodyParam,
      dataType: 'json',
      contentType: false,
      processData: false,
      error: (function(_this) {
        return function(data) {
          return _this.showErrorStatus(_this.wrap(data), _this);
        };
      })(this),
      success: (function(_this) {
        return function(data) {
          return _this.showResponse(data, _this);
        };
      })(this),
      complete: (function(_this) {
        return function(data) {
          return _this.showCompleteStatus(_this.wrap(data), _this);
        };
      })(this)
    };
    if (window.authorizations) {
      window.authorizations.apply(obj);
    }
    jQuery.ajax(obj);
    return false;
    // end of file-upload nastiness
  },
  // wraps a jquery response as a shred response

  wrap: function(data) {
   var h, headerArray, headers, i, l, len, o;
    headers = {};
    headerArray = data.getAllResponseHeaders().split('\r');
    for (l = 0, len = headerArray.length; l < len; l++) {
      i = headerArray[l];
      h = i.match(/^([^:]*?):(.*)$/);
      if (!h) {
        h = [];
      }
      h.shift();
      if (h[0] !== void 0 && h[1] !== void 0) {
        headers[h[0].trim()] = h[1].trim();
      }
    }
    o = {};
    o.content = {};
    o.content.data = data.responseText;
    o.headers = headers;
    o.request = {};
    o.request.url = this.invocationUrl;
    o.status = data.status;
    return o;
  },

  getSelectedValue: function(select) {
    if (!select.multiple) {
      return select.value;
    } else {
      var options = [];
      for (var l = 0, len = select.options.length; l < len; l++) {
        var opt = select.options[l];
        if (opt.selected) {
          options.push(opt.value);
        }
      }
      if (options.length > 0) {
        return options;
      } else {
        return null;
      }
    }
  },

  // handler for hide response link
  hideResponse: function(e) {
    if (e) { e.preventDefault(); }
    $('.response', $(this.el)).slideUp();
    $('.response_hider', $(this.el)).fadeOut();
  },

  // Show response from server
  showResponse: function(response) {
    var prettyJson = JSON.stringify(response, null, '\t').replace(/\n/g, '
'); $('.response_body', $(this.el)).html(_.escape(prettyJson)); }, // Show error from server showErrorStatus: function(data, parent) { parent.showStatus(data); }, // show the status codes showCompleteStatus: function(data, parent){ parent.showStatus(data); }, // Adapted from http://stackoverflow.com/a/2893259/454004 // Note: directly ported from CoffeeScript // TODO: Cleanup CoffeeScript artifacts formatXml: function(xml) { var contexp, fn, formatted, indent, l, lastType, len, lines, ln, pad, reg, transitions, wsexp; reg = /(>)(<)(\/*)/g; wsexp = /[ ]*(.*)[ ]+\n/g; contexp = /(<.+>)(.+\n)/g; xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2'); pad = 0; formatted = ''; lines = xml.split('\n'); indent = 0; lastType = 'other'; transitions = { 'single->single': 0, 'single->closing': -1, 'single->opening': 0, 'single->other': 0, 'closing->single': 0, 'closing->closing': -1, 'closing->opening': 0, 'closing->other': 0, 'opening->single': 1, 'opening->closing': 0, 'opening->opening': 1, 'opening->other': 1, 'other->single': 0, 'other->closing': -1, 'other->opening': 0, 'other->other': 0 }; fn = function(ln) { var fromTo, j, key, padding, type, types, value; types = { single: Boolean(ln.match(/<.+\/>/)), closing: Boolean(ln.match(/<\/.+>/)), opening: Boolean(ln.match(/<[^!?].*>/)) }; type = ((function() { var results; results = []; for (key in types) { value = types[key]; if (value) { results.push(key); } } return results; })())[0]; type = type === void 0 ? 'other' : type; fromTo = lastType + '->' + type; lastType = type; padding = ''; indent += transitions[fromTo]; padding = ((function() { var m, ref1, results; results = []; for (j = m = 0, ref1 = indent; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) { results.push(' '); } return results; })()).join(''); if (fromTo === 'opening->closing') { formatted = formatted.substr(0, formatted.length - 1) + ln + '\n'; } else { formatted += padding + ln + '\n'; } }; for (l = 0, len = lines.length; l < len; l++) { ln = lines[l]; fn(ln); } return formatted; }, // puts the response data in UI showStatus: function(response) { var url, content; if (response.content === undefined) { content = response.data; url = response.url; } else { content = response.content.data; url = response.request.url; } var headers = response.headers; // if server is nice, and sends content-type back, we can use it var contentType = null; if (headers) { contentType = headers['Content-Type'] || headers['content-type']; if (contentType) { contentType = contentType.split(';')[0].trim(); } } $('.response_body', $(this.el)).removeClass('json'); $('.response_body', $(this.el)).removeClass('xml'); var supportsAudioPlayback = function(contentType){ var audioElement = document.createElement('audio'); return !!(audioElement.canPlayType && audioElement.canPlayType(contentType).replace(/no/, '')); }; var pre; var code; if (!content) { code = $('').text('no content'); pre = $('
').append(code);

    // JSON
    } else if (contentType === 'application/json' || /\+json$/.test(contentType)) {
      var json = null;
      try {
        json = JSON.stringify(JSON.parse(content), null, '  ');
      } catch (_error) {
        json = 'can\'t parse JSON.  Raw result:\n\n' + content;
      }
      code = $('').text(json);
      pre = $('
').append(code);

    // XML
    } else if (contentType === 'application/xml' || /\+xml$/.test(contentType)) {
      code = $('').text(this.formatXml(content));
      pre = $('
').append(code);

    // HTML
    } else if (contentType === 'text/html') {
      code = $('').html(_.escape(content));
      pre = $('
').append(code);

    // Image
    } else if (/^image\//.test(contentType)) {
      pre = $('').attr('src', url);

    // Audio
    } else if (/^audio\//.test(contentType) && supportsAudioPlayback(contentType)) {
      pre = $('