github.com/qubitproducts/logspray@v0.2.14/server/swagger-ui/src/main/javascript/view/OperationView.js (about) 1 'use strict'; 2 3 SwaggerUi.Views.OperationView = Backbone.View.extend({ 4 invocationUrl: null, 5 6 events: { 7 'submit .sandbox' : 'submitOperation', 8 'click .submit' : 'submitOperation', 9 'click .response_hider' : 'hideResponse', 10 'click .toggleOperation' : 'toggleOperationContent', 11 'mouseenter .api-ic' : 'mouseEnter', 12 'dblclick .curl' : 'selectText', 13 'change [name=responseContentType]' : 'showSnippet' 14 }, 15 16 initialize: function(opts) { 17 opts = opts || {}; 18 this.router = opts.router; 19 this.auths = opts.auths; 20 this.parentId = this.model.parentId; 21 this.nickname = this.model.nickname; 22 this.model.encodedParentId = encodeURIComponent(this.parentId); 23 24 if (opts.swaggerOptions) { 25 this.model.defaultRendering = opts.swaggerOptions.defaultModelRendering; 26 27 if (opts.swaggerOptions.showRequestHeaders) { 28 this.model.showRequestHeaders = true; 29 } 30 } 31 return this; 32 }, 33 34 selectText: function(event) { 35 var doc = document, 36 text = event.target.firstChild, 37 range, 38 selection; 39 if (doc.body.createTextRange) { 40 range = document.body.createTextRange(); 41 range.moveToElementText(text); 42 range.select(); 43 } else if (window.getSelection) { 44 selection = window.getSelection(); 45 range = document.createRange(); 46 range.selectNodeContents(text); 47 selection.removeAllRanges(); 48 selection.addRange(range); 49 } 50 }, 51 52 mouseEnter: function(e) { 53 var elem = $(this.el).find('.content'); 54 var x = e.pageX; 55 var y = e.pageY; 56 var scX = $(window).scrollLeft(); 57 var scY = $(window).scrollTop(); 58 var scMaxX = scX + $(window).width(); 59 var scMaxY = scY + $(window).height(); 60 var wd = elem.width(); 61 var hgh = elem.height(); 62 63 if (x + wd > scMaxX) { 64 x = scMaxX - wd; 65 } 66 67 if (x < scX) { 68 x = scX; 69 } 70 71 if (y + hgh > scMaxY) { 72 y = scMaxY - hgh; 73 } 74 75 if (y < scY) { 76 y = scY; 77 } 78 79 var pos = {}; 80 pos.top = y; 81 pos.left = x; 82 elem.css(pos); 83 }, 84 85 // Note: copied from CoffeeScript compiled file 86 // TODO: refactor 87 render: function() { 88 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, produces, isXML, isJSON; 89 isMethodSubmissionSupported = jQuery.inArray(this.model.method, this.model.supportedSubmitMethods()) >= 0; 90 if (!isMethodSubmissionSupported) { 91 this.model.isReadOnly = true; 92 } 93 this.model.description = this.model.description || this.model.notes; 94 this.model.oauth = null; 95 modelAuths = this.model.authorizations || this.model.security; 96 if (modelAuths) { 97 if (Array.isArray(modelAuths)) { 98 for (l = 0, len = modelAuths.length; l < len; l++) { 99 auths = modelAuths[l]; 100 for (key in auths) { 101 for (a in this.auths) { 102 auth = this.auths[a]; 103 if (key === auth.name) { 104 if (auth.type === 'oauth2') { 105 this.model.oauth = {}; 106 this.model.oauth.scopes = []; 107 ref1 = auth.value.scopes; 108 for (k in ref1) { 109 v = ref1[k]; 110 scopeIndex = auths[key].indexOf(k); 111 if (scopeIndex >= 0) { 112 o = { 113 scope: k, 114 description: v 115 }; 116 this.model.oauth.scopes.push(o); 117 } 118 } 119 } 120 } 121 } 122 } 123 } 124 } else { 125 for (k in modelAuths) { 126 v = modelAuths[k]; 127 if (k === 'oauth2') { 128 if (this.model.oauth === null) { 129 this.model.oauth = {}; 130 } 131 if (this.model.oauth.scopes === void 0) { 132 this.model.oauth.scopes = []; 133 } 134 for (m = 0, len1 = v.length; m < len1; m++) { 135 o = v[m]; 136 this.model.oauth.scopes.push(o); 137 } 138 } 139 } 140 } 141 } 142 if (typeof this.model.responses !== 'undefined') { 143 this.model.responseMessages = []; 144 ref2 = this.model.responses; 145 for (code in ref2) { 146 value = ref2[code]; 147 schema = null; 148 schemaObj = this.model.responses[code].schema; 149 if (schemaObj && schemaObj.$ref) { 150 schema = schemaObj.$ref; 151 if (schema.indexOf('#/definitions/') !== -1) { 152 schema = schema.replace(/^.*#\/definitions\//, ''); 153 } 154 } 155 this.model.responseMessages.push({ 156 code: code, 157 message: value.description, 158 responseModel: schema, 159 headers: value.headers, 160 schema: schemaObj 161 }); 162 } 163 } 164 if (typeof this.model.responseMessages === 'undefined') { 165 this.model.responseMessages = []; 166 } 167 signatureModel = null; 168 produces = this.model.produces; 169 isXML = this.contains(produces, 'xml'); 170 isJSON = isXML ? this.contains(produces, 'json') : true; 171 172 if (this.model.successResponse) { 173 successResponse = this.model.successResponse; 174 for (key in successResponse) { 175 value = successResponse[key]; 176 this.model.successCode = key; 177 if (typeof value === 'object' && typeof value.createJSONSample === 'function') { 178 this.model.successDescription = value.description; 179 this.model.headers = this.parseResponseHeaders(value.headers); 180 signatureModel = { 181 sampleJSON: isJSON ? JSON.stringify(SwaggerUi.partials.signature.createJSONSample(value), void 0, 2) : false, 182 isParam: false, 183 sampleXML: isXML ? SwaggerUi.partials.signature.createXMLSample(value.name, value.definition, value.models) : false, 184 signature: SwaggerUi.partials.signature.getModelSignature(value.name, value.definition, value.models, value.modelPropertyMacro) 185 }; 186 } else { 187 signatureModel = { 188 signature: SwaggerUi.partials.signature.getPrimitiveSignature(value) 189 }; 190 } 191 } 192 } else if (this.model.responseClassSignature && this.model.responseClassSignature !== 'string') { 193 signatureModel = { 194 sampleJSON: this.model.responseSampleJSON, 195 isParam: false, 196 signature: this.model.responseClassSignature 197 }; 198 } 199 $(this.el).html(Handlebars.templates.operation(this.model)); 200 if (signatureModel) { 201 signatureModel.defaultRendering = this.model.defaultRendering; 202 responseSignatureView = new SwaggerUi.Views.SignatureView({ 203 model: signatureModel, 204 router: this.router, 205 tagName: 'div' 206 }); 207 $('.model-signature', $(this.el)).append(responseSignatureView.render().el); 208 } else { 209 this.model.responseClassSignature = 'string'; 210 $('.model-signature', $(this.el)).html(this.model.type); 211 } 212 contentTypeModel = { 213 isParam: false 214 }; 215 contentTypeModel.consumes = this.model.consumes; 216 contentTypeModel.produces = this.model.produces; 217 ref3 = this.model.parameters; 218 for (n = 0, len2 = ref3.length; n < len2; n++) { 219 param = ref3[n]; 220 type = param.type || param.dataType || ''; 221 if (typeof type === 'undefined') { 222 schema = param.schema; 223 if (schema && schema.$ref) { 224 ref = schema.$ref; 225 if (ref.indexOf('#/definitions/') === 0) { 226 type = ref.substring('#/definitions/'.length); 227 } else { 228 type = ref; 229 } 230 } 231 } 232 if (type && type.toLowerCase() === 'file') { 233 if (!contentTypeModel.consumes) { 234 contentTypeModel.consumes = 'multipart/form-data'; 235 } 236 } 237 param.type = type; 238 } 239 responseContentTypeView = new SwaggerUi.Views.ResponseContentTypeView({ 240 model: contentTypeModel, 241 router: this.router 242 }); 243 $('.response-content-type', $(this.el)).append(responseContentTypeView.render().el); 244 ref4 = this.model.parameters; 245 for (p = 0, len3 = ref4.length; p < len3; p++) { 246 param = ref4[p]; 247 this.addParameter(param, contentTypeModel.consumes); 248 } 249 ref5 = this.model.responseMessages; 250 for (q = 0, len4 = ref5.length; q < len4; q++) { 251 statusCode = ref5[q]; 252 statusCode.isXML = isXML; 253 statusCode.isJSON = isJSON; 254 if (!_.isUndefined(statusCode.headers)) { 255 statusCode.headers = this.parseHeadersType(statusCode.headers); 256 } 257 this.addStatusCode(statusCode); 258 } 259 260 if (Array.isArray(this.model.security)) { 261 var authsModel = SwaggerUi.utils.parseSecurityDefinitions(this.model.security, this.model.parent.securityDefinitions); 262 263 authsModel.isLogout = !_.isEmpty(this.model.clientAuthorizations.authz); 264 this.authView = new SwaggerUi.Views.AuthButtonView({ 265 data: authsModel, 266 router: this.router, 267 isOperation: true, 268 model: { 269 scopes: authsModel.scopes 270 } 271 }); 272 this.$('.authorize-wrapper').append(this.authView.render().el); 273 } 274 275 this.showSnippet(); 276 return this; 277 }, 278 279 parseHeadersType: function (headers) { 280 var map = { 281 'string': { 282 'date-time': 'dateTime', 283 'date' : 'date' 284 } 285 }; 286 287 _.forEach(headers, function (header) { 288 var value; 289 header = header || {}; 290 value = map[header.type] && map[header.type][header.format]; 291 if (!_.isUndefined(value)) { 292 header.type = value; 293 } 294 }); 295 296 return headers; 297 }, 298 299 contains: function (produces, type) { 300 return produces.filter(function (val) { 301 if (val.indexOf(type) > -1) { 302 return true; 303 } 304 }).length; 305 }, 306 307 parseResponseHeaders: function (data) { 308 var HEADERS_SEPARATOR = '; '; 309 var headers = _.clone(data); 310 311 _.forEach(headers, function (header) { 312 var other = []; 313 _.forEach(header, function (value, key) { 314 var properties = ['type', 'description']; 315 if (properties.indexOf(key.toLowerCase()) === -1) { 316 other.push(key + ': ' + value); 317 } 318 }); 319 320 other.join(HEADERS_SEPARATOR); 321 header.other = other; 322 }); 323 324 return headers; 325 }, 326 327 addParameter: function(param, consumes) { 328 // Render a parameter 329 param.consumes = consumes; 330 param.defaultRendering = this.model.defaultRendering; 331 332 // Copy this param JSON spec so that it will be available for JsonEditor 333 if(param.schema){ 334 $.extend(true, param.schema, this.model.definitions[param.type]); 335 param.schema.definitions = this.model.definitions; 336 // This is required for JsonEditor to display the root properly 337 if(!param.schema.type){ 338 param.schema.type = 'object'; 339 } 340 // This is the title that will be used by JsonEditor for the root 341 // Since we already display the parameter's name in the Parameter column 342 // We set this to space, we can't set it to null or space otherwise JsonEditor 343 // will replace it with the text "root" which won't look good on screen 344 if(!param.schema.title){ 345 param.schema.title = ' '; 346 } 347 } 348 349 var paramView = new SwaggerUi.Views.ParameterView({ 350 model: param, 351 tagName: 'tr', 352 readOnly: this.model.isReadOnly, 353 swaggerOptions: this.options.swaggerOptions 354 }); 355 $('.operation-params', $(this.el)).append(paramView.render().el); 356 }, 357 358 addStatusCode: function(statusCode) { 359 // Render status codes 360 statusCode.defaultRendering = this.model.defaultRendering; 361 var statusCodeView = new SwaggerUi.Views.StatusCodeView({ 362 model: statusCode, 363 tagName: 'tr', 364 router: this.router 365 }); 366 $('.operation-status', $(this.el)).append(statusCodeView.render().el); 367 }, 368 369 // Note: copied from CoffeeScript compiled file 370 // TODO: redactor 371 submitOperation: function(e) { 372 var error_free, form, isFileUpload, map, opts; 373 if (e !== null) { 374 e.preventDefault(); 375 } 376 form = $('.sandbox', $(this.el)); 377 error_free = true; 378 form.find('input.required').each(function() { 379 $(this).removeClass('error'); 380 if (jQuery.trim($(this).val()) === '') { 381 $(this).addClass('error'); 382 $(this).wiggle({ 383 callback: (function(_this) { 384 return function() { 385 $(_this).focus(); 386 }; 387 })(this) 388 }); 389 error_free = false; 390 } 391 }); 392 form.find('textarea.required:visible').each(function() { 393 $(this).removeClass('error'); 394 if (jQuery.trim($(this).val()) === '') { 395 $(this).addClass('error'); 396 $(this).wiggle({ 397 callback: (function(_this) { 398 return function() { 399 return $(_this).focus(); 400 }; 401 })(this) 402 }); 403 error_free = false; 404 } 405 }); 406 form.find('select.required').each(function() { 407 $(this).removeClass('error'); 408 if (this.selectedIndex === -1) { 409 $(this).addClass('error'); 410 $(this).wiggle({ 411 callback: (function(_this) { 412 return function() { 413 $(_this).focus(); 414 }; 415 })(this) 416 }); 417 error_free = false; 418 } 419 }); 420 if (error_free) { 421 map = this.getInputMap(form); 422 isFileUpload = this.isFileUpload(form); 423 opts = { 424 parent: this 425 }; 426 if (this.options.swaggerOptions) { 427 for(var key in this.options.swaggerOptions) { 428 opts[key] = this.options.swaggerOptions[key]; 429 } 430 } 431 432 var pi; 433 for(pi = 0; pi < this.model.parameters.length; pi++){ 434 var p = this.model.parameters[pi]; 435 if( p.jsonEditor && p.jsonEditor.isEnabled()){ 436 var json = p.jsonEditor.getValue(); 437 map[p.name] = JSON.stringify(json); 438 } 439 } 440 441 opts.responseContentType = $('div select[name=responseContentType]', $(this.el)).val(); 442 opts.requestContentType = $('div select[name=parameterContentType]', $(this.el)).val(); 443 $('.response_throbber', $(this.el)).show(); 444 if (isFileUpload) { 445 $('.request_url', $(this.el)).html('<pre></pre>'); 446 $('.request_url pre', $(this.el)).text(this.invocationUrl); 447 448 opts.useJQuery = true; 449 map.parameterContentType = 'multipart/form-data'; 450 this.map = map; 451 return this.model.execute(map, opts, this.showCompleteStatus, this.showErrorStatus, this); 452 } else { 453 this.map = map; 454 return this.model.execute(map, opts, this.showCompleteStatus, this.showErrorStatus, this); 455 } 456 } 457 }, 458 459 getInputMap: function (form) { 460 var map, ref1, l, len, o, ref2, m, len1, val, ref3, n, len2; 461 map = {}; 462 ref1 = form.find('input'); 463 for (l = 0, len = ref1.length; l < len; l++) { 464 o = ref1[l]; 465 if ((o.value !== null) && jQuery.trim(o.value).length > 0) { 466 map[o.name] = o.value; 467 } 468 if (o.type === 'file') { 469 map[o.name] = o.files[0]; 470 } 471 } 472 ref2 = form.find('textarea'); 473 for (m = 0, len1 = ref2.length; m < len1; m++) { 474 o = ref2[m]; 475 val = this.getTextAreaValue(o); 476 if ((val !== null) && jQuery.trim(val).length > 0) { 477 map[o.name] = val; 478 } 479 } 480 ref3 = form.find('select'); 481 for (n = 0, len2 = ref3.length; n < len2; n++) { 482 o = ref3[n]; 483 val = this.getSelectedValue(o); 484 if ((val !== null) && jQuery.trim(val).length > 0) { 485 map[o.name] = val; 486 } 487 } 488 return map; 489 }, 490 491 isFileUpload: function (form) { 492 var ref1, l, len, o; 493 var isFileUpload = false; 494 ref1 = form.find('input'); 495 for (l = 0, len = ref1.length; l < len; l++) { 496 o = ref1[l]; 497 if (o.type === 'file') { 498 isFileUpload = true; 499 } 500 } 501 return isFileUpload; 502 }, 503 504 success: function(response, parent) { 505 parent.showCompleteStatus(response); 506 }, 507 508 // wraps a jquery response as a shred response 509 wrap: function(data) { 510 var h, headerArray, headers, i, l, len, o; 511 headers = {}; 512 headerArray = data.getAllResponseHeaders().split('\r'); 513 for (l = 0, len = headerArray.length; l < len; l++) { 514 i = headerArray[l]; 515 h = i.match(/^([^:]*?):(.*)$/); 516 if (!h) { 517 h = []; 518 } 519 h.shift(); 520 if (h[0] !== void 0 && h[1] !== void 0) { 521 headers[h[0].trim()] = h[1].trim(); 522 } 523 } 524 o = {}; 525 o.content = {}; 526 o.content.data = data.responseText; 527 o.headers = headers; 528 o.request = {}; 529 o.request.url = this.invocationUrl; 530 o.status = data.status; 531 return o; 532 }, 533 534 getSelectedValue: function(select) { 535 if (!select.multiple) { 536 return select.value; 537 } else { 538 var options = []; 539 for (var l = 0, len = select.options.length; l < len; l++) { 540 var opt = select.options[l]; 541 if (opt.selected) { 542 options.push(opt.value); 543 } 544 } 545 if (options.length > 0) { 546 return options; 547 } else { 548 return null; 549 } 550 } 551 }, 552 553 // handler for hide response link 554 hideResponse: function(e) { 555 if (e) { e.preventDefault(); } 556 $('.response', $(this.el)).slideUp(); 557 $('.response_hider', $(this.el)).fadeOut(); 558 }, 559 560 // Show response from server 561 showResponse: function(response) { 562 var prettyJson = JSON.stringify(response, null, '\t').replace(/\n/g, '<br>'); 563 $('.response_body', $(this.el)).html(_.escape(prettyJson)); 564 }, 565 566 // Show error from server 567 showErrorStatus: function(data, parent) { 568 parent.showStatus(data); 569 }, 570 571 // show the status codes 572 showCompleteStatus: function(data, parent){ 573 parent.showStatus(data); 574 }, 575 576 // Adapted from http://stackoverflow.com/a/2893259/454004 577 // Note: directly ported from CoffeeScript 578 // TODO: Cleanup CoffeeScript artifacts 579 formatXml: function(xml) { 580 var contexp, fn, formatted, indent, l, lastType, len, lines, ln, pad, reg, transitions, wsexp; 581 reg = /(>)(<)(\/*)/g; 582 wsexp = /[ ]*(.*)[ ]+\n/g; 583 contexp = /(<.+>)(.+\n)/g; 584 xml = xml.replace(/\r\n/g, '\n').replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2'); 585 pad = 0; 586 formatted = ''; 587 lines = xml.split('\n'); 588 indent = 0; 589 lastType = 'other'; 590 transitions = { 591 'single->single': 0, 592 'single->closing': -1, 593 'single->opening': 0, 594 'single->other': 0, 595 'closing->single': 0, 596 'closing->closing': -1, 597 'closing->opening': 0, 598 'closing->other': 0, 599 'opening->single': 1, 600 'opening->closing': 0, 601 'opening->opening': 1, 602 'opening->other': 1, 603 'other->single': 0, 604 'other->closing': -1, 605 'other->opening': 0, 606 'other->other': 0 607 }; 608 fn = function(ln) { 609 var fromTo, j, key, padding, type, types, value; 610 types = { 611 single: Boolean(ln.match(/<.+\/>/)), 612 closing: Boolean(ln.match(/<\/.+>/)), 613 opening: Boolean(ln.match(/<[^!?].*>/)) 614 }; 615 type = ((function() { 616 var results; 617 results = []; 618 for (key in types) { 619 value = types[key]; 620 if (value) { 621 results.push(key); 622 } 623 } 624 return results; 625 })())[0]; 626 type = type === void 0 ? 'other' : type; 627 fromTo = lastType + '->' + type; 628 lastType = type; 629 padding = ''; 630 indent += transitions[fromTo]; 631 padding = ((function() { 632 var m, ref1, results; 633 results = []; 634 for (j = m = 0, ref1 = indent; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) { 635 results.push(' '); 636 } 637 return results; 638 })()).join(''); 639 if (fromTo === 'opening->closing') { 640 formatted = formatted.substr(0, formatted.length - 1) + ln + '\n'; 641 } else { 642 formatted += padding + ln + '\n'; 643 } 644 }; 645 for (l = 0, len = lines.length; l < len; l++) { 646 ln = lines[l]; 647 fn(ln); 648 } 649 return formatted; 650 }, 651 652 // puts the response data in UI 653 showStatus: function(response) { 654 var url, content; 655 if (response.content === undefined) { 656 content = response.data; 657 url = response.url; 658 } else { 659 content = response.content.data; 660 url = response.request.url; 661 } 662 var headers = response.headers; 663 if(typeof content === 'string') { 664 content = jQuery.trim(content); 665 } 666 667 // if server is nice, and sends content-type back, we can use it 668 var contentType = null; 669 if (headers) { 670 contentType = headers['Content-Type'] || headers['content-type']; 671 if (contentType) { 672 contentType = contentType.split(';')[0].trim(); 673 } 674 } 675 676 $('.response_body', $(this.el)).removeClass('json'); 677 $('.response_body', $(this.el)).removeClass('xml'); 678 679 var supportsAudioPlayback = function(contentType){ 680 var audioElement = document.createElement('audio'); 681 return !!(audioElement.canPlayType && audioElement.canPlayType(contentType).replace(/no/, '')); 682 }; 683 684 var pre; 685 var code; 686 if (!content) { 687 code = $('<code />').text('no content'); 688 pre = $('<pre class="json" />').append(code); 689 690 // JSON 691 } else if ( 692 contentType === 'application/octet-stream' || 693 headers['Content-Disposition'] && (/attachment/).test(headers['Content-Disposition']) || 694 headers['content-disposition'] && (/attachment/).test(headers['content-disposition']) || 695 headers['Content-Description'] && (/File Transfer/).test(headers['Content-Description']) || 696 headers['content-description'] && (/File Transfer/).test(headers['content-description'])) { 697 698 if ('Blob' in window) { 699 var type = contentType || 'text/html'; 700 var a = document.createElement('a'); 701 var href; 702 703 if({}.toString.apply(content) === '[object Blob]') { 704 href = window.URL.createObjectURL(content); 705 } 706 else { 707 var binaryData = []; 708 binaryData.push(content); 709 href = window.URL.createObjectURL(new Blob(binaryData, {type: type})); 710 } 711 var fileName = response.url.substr(response.url.lastIndexOf('/') + 1); 712 var download = [type, fileName, href].join(':'); 713 714 // Use filename from response header 715 var disposition = headers['content-disposition'] || headers['Content-Disposition']; 716 if(typeof disposition !== 'undefined') { 717 var responseFilename = /filename=([^;]*);?/.exec(disposition); 718 if(responseFilename !== null && responseFilename.length > 1) { 719 download = responseFilename[1]; 720 } 721 } 722 723 a.setAttribute('href', href); 724 a.setAttribute('download', download); 725 a.innerText = 'Download ' + fileName; 726 727 pre = $('<div/>').append(a); 728 } else { 729 pre = $('<pre class="json" />').append('Download headers detected but your browser does not support downloading binary via XHR (Blob).'); 730 } 731 } else if (contentType === 'application/json' || /\+json$/.test(contentType)) { 732 var json = null; 733 try { 734 json = JSON.stringify(JSON.parse(content), null, ' '); 735 } catch (_error) { 736 json = 'can\'t parse JSON. Raw result:\n\n' + content; 737 } 738 code = $('<code />').text(json); 739 pre = $('<pre class="json" />').append(code); 740 741 // XML 742 } else if (contentType === 'application/xml' || /\+xml$/.test(contentType)) { 743 code = $('<code />').text(this.formatXml(content)); 744 pre = $('<pre class="xml" />').append(code); 745 746 // HTML 747 } else if (contentType === 'text/html') { 748 code = $('<code />').html(_.escape(content)); 749 pre = $('<pre class="xml" />').append(code); 750 751 // Plain Text 752 } else if (/text\/plain/.test(contentType)) { 753 code = $('<code />').text(content); 754 pre = $('<pre class="plain" />').append(code); 755 756 // Image 757 } else if (/^image\//.test(contentType)) { 758 var urlCreator = window.URL || window.webkitURL; 759 var imageUrl = urlCreator.createObjectURL(content); 760 761 pre = $('<img>').attr( 'src', imageUrl); 762 // Audio 763 } else if (/^audio\//.test(contentType) && supportsAudioPlayback(contentType)) { 764 pre = $('<audio controls>').append($('<source>').attr('src', url).attr('type', contentType)); 765 } else if(headers.location || headers.Location) { 766 // Location header based redirect download 767 window.location = response.url; 768 769 // Anything else (CORS) 770 } else { 771 code = $('<code />').text(content); 772 pre = $('<pre class="json" />').append(code); 773 } 774 var response_body = pre; 775 $('.request_url', $(this.el)).html('<pre></pre>'); 776 $('.request_url pre', $(this.el)).text(url); 777 $('.response_code', $(this.el)).html('<pre>' + response.status + '</pre>'); 778 $('.response_body', $(this.el)).html(response_body); 779 $('.response_headers', $(this.el)).html('<pre>' + _.escape(JSON.stringify(response.headers, null, ' ')).replace(/\n/g, '<br>') + '</pre>'); 780 $('.response', $(this.el)).slideDown(); 781 $('.response_hider', $(this.el)).show(); 782 $('.response_throbber', $(this.el)).hide(); 783 784 785 // adds curl output 786 var curlCommand = this.model.asCurl(this.map, {responseContentType: contentType}); 787 curlCommand = curlCommand.replace('!', '!'); 788 $( 'div.curl', $(this.el)).html('<pre>' + _.escape(curlCommand) + '</pre>'); 789 790 // only highlight the response if response is less than threshold, default state is highlight response 791 var opts = this.options.swaggerOptions; 792 793 if (opts.showRequestHeaders) { 794 var form = $('.sandbox', $(this.el)), 795 map = this.getInputMap(form), 796 requestHeaders = this.model.getHeaderParams(map); 797 delete requestHeaders['Content-Type']; 798 $('.request_headers', $(this.el)).html('<pre>' + _.escape(JSON.stringify(requestHeaders, null, ' ')).replace(/\n/g, '<br>') + '</pre>'); 799 } 800 801 var response_body_el = $('.response_body', $(this.el))[0]; 802 // only highlight the response if response is less than threshold, default state is highlight response 803 if (opts.highlightSizeThreshold && typeof response.data !== 'undefined' && response.data.length > opts.highlightSizeThreshold) { 804 return response_body_el; 805 } else { 806 return hljs.highlightBlock(response_body_el); 807 } 808 }, 809 810 toggleOperationContent: function (event) { 811 var elem = $('#' + Docs.escapeResourceName(this.parentId + '_' + this.nickname + '_content')); 812 if (elem.is(':visible')){ 813 $.bbq.pushState('#/', 2); 814 event.preventDefault(); 815 Docs.collapseOperation(elem); 816 } else { 817 Docs.expandOperation(elem); 818 } 819 }, 820 821 getTextAreaValue: function(textArea) { 822 var param, parsed, result, i; 823 if (textArea.value === null || jQuery.trim(textArea.value).length === 0) { 824 return null; 825 } 826 param = this.getParamByName(textArea.name); 827 if (param && param.type && param.type.toLowerCase() === 'array') { 828 parsed = textArea.value.split('\n'); 829 result = []; 830 for (i = 0; i < parsed.length; i++) { 831 if (parsed[i] !== null && jQuery.trim(parsed[i]).length > 0) { 832 result.push(parsed[i]); 833 } 834 } 835 return result.length > 0 ? result : null; 836 } else { 837 return textArea.value; 838 } 839 }, 840 841 showSnippet: function () { 842 var contentTypeEl = this.$('[name=responseContentType]'); 843 var xmlSnippetEl = this.$('.operation-status .snippet_xml, .response-class .snippet_xml'); 844 var jsonSnippetEl = this.$('.operation-status .snippet_json, .response-class .snippet_json'); 845 var contentType; 846 847 if (!contentTypeEl.length) { return; } 848 contentType = contentTypeEl.val(); 849 850 if (contentType.indexOf('xml') > -1) { 851 xmlSnippetEl.show(); 852 jsonSnippetEl.hide(); 853 } else { 854 jsonSnippetEl.show(); 855 xmlSnippetEl.hide(); 856 } 857 }, 858 859 getParamByName: function(name) { 860 var i; 861 if (this.model.parameters) { 862 for(i = 0; i < this.model.parameters.length; i++) { 863 if (this.model.parameters[i].name === name) { 864 return this.model.parameters[i]; 865 } 866 } 867 } 868 return null; 869 } 870 871 });