From cdfb20cbc161b30ee58b34d0bb9d6e42b50cd387 Mon Sep 17 00:00:00 2001 From: Arek W Date: Wed, 28 Nov 2012 15:00:44 +1100 Subject: [PATCH 1/3] Replace tabs with spaces --- app/assets/javascripts/api_taster/app.js | 226 +++++++++++------------ 1 file changed, 113 insertions(+), 113 deletions(-) diff --git a/app/assets/javascripts/api_taster/app.js b/app/assets/javascripts/api_taster/app.js index 3632a08..75344b6 100644 --- a/app/assets/javascripts/api_taster/app.js +++ b/app/assets/javascripts/api_taster/app.js @@ -1,148 +1,148 @@ var ApiTaster = { - formAction: '', + formAction: '', - disableSubmitButton: function() { - $("#submit-api").attr("disabled", true); - }, + disableSubmitButton: function() { + $("#submit-api").attr("disabled", true); + }, - enableSubmitButton: function() { - $("#submit-api").attr("disabled", false); - }, + enableSubmitButton: function() { + $("#submit-api").attr("disabled", false); + }, - disableUrlParams: function() { - $("fieldset[ref=url-params] input").prop("disabled", true); - }, + disableUrlParams: function() { + $("fieldset[ref=url-params] input").prop("disabled", true); + }, - enableUrlParams: function() { - $("fieldset[ref=url-params] input").prop("disabled", false); - }, + enableUrlParams: function() { + $("fieldset[ref=url-params] input").prop("disabled", false); + }, - storeFormActionFor: function(form) { - ApiTaster.formAction = form.attr("action") - }, + storeFormActionFor: function(form) { + ApiTaster.formAction = form.attr("action") + }, - restoreFormActionFor: function(form) { - $(form).attr("action", ApiTaster.formAction); - }, + restoreFormActionFor: function(form) { + $(form).attr("action", ApiTaster.formAction); + }, - detectContentType: function(response) { - var contentType = response.getResponseHeader("Content-Type"); - var detectedContentType = null + detectContentType: function(response) { + var contentType = response.getResponseHeader("Content-Type"); + var detectedContentType = null - if (contentType.match(/application\/json/)) { - detectedContentType = 'json'; - } + if (contentType.match(/application\/json/)) { + detectedContentType = 'json'; + } - return detectedContentType; - } + return detectedContentType; + } }; $.fn.extend({ - replaceUrlParams: function(params) { - var form = this; + replaceUrlParams: function(params) { + var form = this; - ApiTaster.storeFormActionFor(form); + ApiTaster.storeFormActionFor(form); - var formAction = form.attr("action"); + var formAction = form.attr("action"); - $.each(params, function(i, param) { - var matches = param["name"].match(/\[api_taster_url_params\](.*)/) - if (matches) { - var paramKey = matches[1]; - var paramValue = param["value"]; - var regex = new RegExp(":" + paramKey); + $.each(params, function(i, param) { + var matches = param["name"].match(/\[api_taster_url_params\](.*)/) + if (matches) { + var paramKey = matches[1]; + var paramValue = param["value"]; + var regex = new RegExp(":" + paramKey); - formAction = formAction.replace(regex, paramValue); - } - }); + formAction = formAction.replace(regex, paramValue); + } + }); - form.attr("action", formAction); - }, + form.attr("action", formAction); + }, - enableNavTabsFor: function(contentElement) { - var container = this; + enableNavTabsFor: function(contentElement) { + var container = this; - $("ul.nav-tabs a", container).click(function(e) { - e.preventDefault(); + $("ul.nav-tabs a", container).click(function(e) { + e.preventDefault(); - $(this).parent().siblings().removeClass("active"); - $(this).parent().addClass("active"); + $(this).parent().siblings().removeClass("active"); + $(this).parent().addClass("active"); - $(contentElement, container).hide(); - $(contentElement + "[ref=" + $(this).attr("id") + "]", container).show(); - }); - }, + $(contentElement, container).hide(); + $(contentElement + "[ref=" + $(this).attr("id") + "]", container).show(); + }); + }, - showNavTab: function(name) { - $("ul.nav-tabs li", this).removeClass("active"); - $("ul.nav-tabs li a#response-" + name, this).parent().show().addClass("active"); + showNavTab: function(name) { + $("ul.nav-tabs li", this).removeClass("active"); + $("ul.nav-tabs li a#response-" + name, this).parent().show().addClass("active"); - $("pre", this).hide(); + $("pre", this).hide(); - return $("pre[ref=response-" + name + "]", this).show(); - }, + return $("pre[ref=response-" + name + "]", this).show(); + }, - displayOnlySelectedParamsFieldset: function() { - $("fieldset", this).hide(); - $("fieldset[ref=" + $("ul.nav-tabs li.active a").attr("id") + "]", this).show(); - } + displayOnlySelectedParamsFieldset: function() { + $("fieldset", this).hide(); + $("fieldset[ref=" + $("ul.nav-tabs li.active a").attr("id") + "]", this).show(); + } }); jQuery(function($) { - $("#list-api-div a").click(function(e) { - e.preventDefault(); - - $(this).parent().siblings().removeClass("active"); - $(this).parent().addClass("active"); - - $("#show-api-div .div-container").load(this.href, function() { - prettyPrint(); - - $("#show-api-div form").enableNavTabsFor("fieldset"); - $("#show-api-div form").displayOnlySelectedParamsFieldset(); - }); - }); - - $("#show-api-div").on("click", "#submit-api", function() { - $(this).parents("form").submit(function() { - ApiTaster.disableSubmitButton(); - - $(this).unbind("submit").ajaxSubmit({ - beforeSubmit: function(arr, $form, options) { - $form.replaceUrlParams(arr); - ApiTaster.disableUrlParams(); - return false; - } - }); - }); - - $("form").bind("ajax:complete", function(e, xhr, status) { - ApiTaster.enableSubmitButton(); - ApiTaster.enableUrlParams(); - ApiTaster.restoreFormActionFor(this); - - if ($("#show-api-response-div:visible").length == 0) { - $("#show-api-response-div").slideDown(100); - } - - switch (ApiTaster.detectContentType(xhr)) { - case "json": - $("#show-api-response-div").showNavTab("json").text( - JSON.stringify(JSON.parse(xhr.responseText), null, 2) - ); - break; - } - - $("#show-api-response-div pre[ref=response-raw]").text(xhr.responseText); - - prettyPrint(); - }); - - $("#show-api-response-div").enableNavTabsFor("pre"); - }); + $("#list-api-div a").click(function(e) { + e.preventDefault(); + + $(this).parent().siblings().removeClass("active"); + $(this).parent().addClass("active"); + + $("#show-api-div .div-container").load(this.href, function() { + prettyPrint(); + + $("#show-api-div form").enableNavTabsFor("fieldset"); + $("#show-api-div form").displayOnlySelectedParamsFieldset(); + }); + }); + + $("#show-api-div").on("click", "#submit-api", function() { + $(this).parents("form").submit(function() { + ApiTaster.disableSubmitButton(); + + $(this).unbind("submit").ajaxSubmit({ + beforeSubmit: function(arr, $form, options) { + $form.replaceUrlParams(arr); + ApiTaster.disableUrlParams(); + return false; + } + }); + }); + + $("form").bind("ajax:complete", function(e, xhr, status) { + ApiTaster.enableSubmitButton(); + ApiTaster.enableUrlParams(); + ApiTaster.restoreFormActionFor(this); + + if ($("#show-api-response-div:visible").length == 0) { + $("#show-api-response-div").slideDown(100); + } + + switch (ApiTaster.detectContentType(xhr)) { + case "json": + $("#show-api-response-div").showNavTab("json").text( + JSON.stringify(JSON.parse(xhr.responseText), null, 2) + ); + break; + } + + $("#show-api-response-div pre[ref=response-raw]").text(xhr.responseText); + + prettyPrint(); + }); + + $("#show-api-response-div").enableNavTabsFor("pre"); + }); }); From 67b95f7c28fb069ee659320973bc0d5d97c3f5aa Mon Sep 17 00:00:00 2001 From: Arek W Date: Wed, 28 Nov 2012 16:02:51 +1100 Subject: [PATCH 2/3] Add status tab with request info --- app/assets/javascripts/api_taster/app.js | 21 ++++++++++++++++++- .../stylesheets/api_taster/layout.css.scss | 17 +++++++++++++++ app/views/api_taster/routes/show.html.erb | 17 +++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/api_taster/app.js b/app/assets/javascripts/api_taster/app.js index 75344b6..15005f3 100644 --- a/app/assets/javascripts/api_taster/app.js +++ b/app/assets/javascripts/api_taster/app.js @@ -35,6 +35,12 @@ var ApiTaster = { } return detectedContentType; + }, + + fillInInfoTab: function($tab, xhr) { + $tab.find('.status td.value').text(xhr.status + " " + xhr.statusText); + $tab.find('.headers td.value').text(xhr.getAllResponseHeaders()); + $tab.find('.time td.value').text((ApiTaster.endTime - ApiTaster.startTime) + " ms"); } }; @@ -120,8 +126,16 @@ jQuery(function($) { }); }); + // These callbacks are a few ms more accurate than click/submit above/below + $("form").bind("ajax:beforeSend", function() { + ApiTaster.startTime = Date.now(); + }); + $("form").bind("ajax:success", function() { + ApiTaster.endTime = Date.now(); + }); + $("form").bind("ajax:complete", function(e, xhr, status) { - ApiTaster.enableSubmitButton(); + ApiTaster.enableSubmitButton(); ApiTaster.enableUrlParams(); ApiTaster.restoreFormActionFor(this); @@ -129,6 +143,11 @@ jQuery(function($) { $("#show-api-response-div").slideDown(100); } + ApiTaster.fillInInfoTab( + $("#show-api-response-div").showNavTab("info"), + xhr + ); + switch (ApiTaster.detectContentType(xhr)) { case "json": $("#show-api-response-div").showNavTab("json").text( diff --git a/app/assets/stylesheets/api_taster/layout.css.scss b/app/assets/stylesheets/api_taster/layout.css.scss index f7267b3..9d810bc 100644 --- a/app/assets/stylesheets/api_taster/layout.css.scss +++ b/app/assets/stylesheets/api_taster/layout.css.scss @@ -85,9 +85,26 @@ legend { } #show-api-response-div { + pre { + color: #fff; + } pre.nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; } + pre[ref=response-info] { + background: #000; + } + + table { + td { + padding: 0 1em 0 0; + vertical-align: top; + + &.name { + text-align: right; + } + } + } } diff --git a/app/views/api_taster/routes/show.html.erb b/app/views/api_taster/routes/show.html.erb index 5716469..2295d08 100644 --- a/app/views/api_taster/routes/show.html.erb +++ b/app/views/api_taster/routes/show.html.erb @@ -59,9 +59,26 @@ From 6eb0e9baf5b635529984823ab36f797491413229 Mon Sep 17 00:00:00 2001 From: Arek W Date: Thu, 29 Nov 2012 10:09:20 +1100 Subject: [PATCH 3/3] Clean up js code. Remove jquery.form --- .../javascripts/api_taster/02-jquery.form.js | 1076 ----------------- app/assets/javascripts/api_taster/app.js | 156 ++- 2 files changed, 72 insertions(+), 1160 deletions(-) delete mode 100644 app/assets/javascripts/api_taster/02-jquery.form.js diff --git a/app/assets/javascripts/api_taster/02-jquery.form.js b/app/assets/javascripts/api_taster/02-jquery.form.js deleted file mode 100644 index d4a1740..0000000 --- a/app/assets/javascripts/api_taster/02-jquery.form.js +++ /dev/null @@ -1,1076 +0,0 @@ -/*! - * jQuery Form Plugin - * version: 3.09 (16-APR-2012) - * @requires jQuery v1.3.2 or later - * - * Examples and documentation at: http://malsup.com/jquery/form/ - * Project repository: https://github.com/malsup/form - * Dual licensed under the MIT and GPL licenses: - * http://malsup.github.com/mit-license.txt - * http://malsup.github.com/gpl-license-v2.txt - */ -/*global ActiveXObject alert */ -;(function($) { -"use strict"; - -/* - Usage Note: - ----------- - Do not use both ajaxSubmit and ajaxForm on the same form. These - functions are mutually exclusive. Use ajaxSubmit if you want - to bind your own submit handler to the form. For example, - - $(document).ready(function() { - $('#myForm').on('submit', function(e) { - e.preventDefault(); // <-- important - $(this).ajaxSubmit({ - target: '#output' - }); - }); - }); - - Use ajaxForm when you want the plugin to manage all the event binding - for you. For example, - - $(document).ready(function() { - $('#myForm').ajaxForm({ - target: '#output' - }); - }); - - You can also use ajaxForm with delegation (requires jQuery v1.7+), so the - form does not have to exist when you invoke ajaxForm: - - $('#myForm').ajaxForm({ - delegation: true, - target: '#output' - }); - - When using ajaxForm, the ajaxSubmit function will be invoked for you - at the appropriate time. -*/ - -/** - * Feature detection - */ -var feature = {}; -feature.fileapi = $("").get(0).files !== undefined; -feature.formdata = window.FormData !== undefined; - -/** - * ajaxSubmit() provides a mechanism for immediately submitting - * an HTML form using AJAX. - */ -$.fn.ajaxSubmit = function(options) { - /*jshint scripturl:true */ - - // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) - if (!this.length) { - log('ajaxSubmit: skipping submit process - no element selected'); - return this; - } - - var method, action, url, $form = this; - - if (typeof options == 'function') { - options = { success: options }; - } - - method = this.attr('method'); - action = this.attr('action'); - url = (typeof action === 'string') ? $.trim(action) : ''; - url = url || window.location.href || ''; - if (url) { - // clean url (don't include hash vaue) - url = (url.match(/^([^#]+)/)||[])[1]; - } - - options = $.extend(true, { - url: url, - success: $.ajaxSettings.success, - type: method || 'GET', - iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' - }, options); - - // hook for manipulating the form data before it is extracted; - // convenient for use with rich editors like tinyMCE or FCKEditor - var veto = {}; - this.trigger('form-pre-serialize', [this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); - return this; - } - - // provide opportunity to alter form data before it is serialized - if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { - log('ajaxSubmit: submit aborted via beforeSerialize callback'); - return this; - } - - var traditional = options.traditional; - if ( traditional === undefined ) { - traditional = $.ajaxSettings.traditional; - } - - var elements = []; - var qx, a = this.formToArray(options.semantic, elements); - if (options.data) { - options.extraData = options.data; - qx = $.param(options.data, traditional); - } - - // give pre-submit callback an opportunity to abort the submit - if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { - log('ajaxSubmit: submit aborted via beforeSubmit callback'); - return this; - } - - // fire vetoable 'validate' event - this.trigger('form-submit-validate', [a, this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); - return this; - } - - var q = $.param(a, traditional); - if (qx) { - q = ( q ? (q + '&' + qx) : qx ); - } - if (options.type.toUpperCase() == 'GET') { - options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; - options.data = null; // data is null for 'get' - } - else { - options.data = q; // data is the query string for 'post' - } - - var callbacks = []; - if (options.resetForm) { - callbacks.push(function() { $form.resetForm(); }); - } - if (options.clearForm) { - callbacks.push(function() { $form.clearForm(options.includeHidden); }); - } - - // perform a load on the target only if dataType is not provided - if (!options.dataType && options.target) { - var oldSuccess = options.success || function(){}; - callbacks.push(function(data) { - var fn = options.replaceTarget ? 'replaceWith' : 'html'; - $(options.target)[fn](data).each(oldSuccess, arguments); - }); - } - else if (options.success) { - callbacks.push(options.success); - } - - options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg - var context = options.context || options; // jQuery 1.4+ supports scope context - for (var i=0, max=callbacks.length; i < max; i++) { - callbacks[i].apply(context, [data, status, xhr || $form, $form]); - } - }; - - // are there files to upload? - var fileInputs = $('input:file:enabled[value]', this); // [value] (issue #113) - var hasFileInputs = fileInputs.length > 0; - var mp = 'multipart/form-data'; - var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); - - var fileAPI = feature.fileapi && feature.formdata; - log("fileAPI :" + fileAPI); - var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI; - - // options.iframe allows user to force iframe mode - // 06-NOV-09: now defaulting to iframe mode if file input is detected - if (options.iframe !== false && (options.iframe || shouldUseFrame)) { - // hack to fix Safari hang (thanks to Tim Molendijk for this) - // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d - if (options.closeKeepAlive) { - $.get(options.closeKeepAlive, function() { - fileUploadIframe(a); - }); - } - else { - fileUploadIframe(a); - } - } - else if ((hasFileInputs || multipart) && fileAPI) { - fileUploadXhr(a); - } - else { - $.ajax(options); - } - - // clear element array - for (var k=0; k < elements.length; k++) - elements[k] = null; - - // fire 'notify' event - this.trigger('form-submit-notify', [this, options]); - return this; - - // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz) - function fileUploadXhr(a) { - var formdata = new FormData(); - - for (var i=0; i < a.length; i++) { - formdata.append(a[i].name, a[i].value); - } - - if (options.extraData) { - for (var p in options.extraData) - if (options.extraData.hasOwnProperty(p)) - formdata.append(p, options.extraData[p]); - } - - options.data = null; - - var s = $.extend(true, {}, $.ajaxSettings, options, { - contentType: false, - processData: false, - cache: false, - type: 'POST' - }); - - if (options.uploadProgress) { - // workaround because jqXHR does not expose upload property - s.xhr = function() { - var xhr = jQuery.ajaxSettings.xhr(); - if (xhr.upload) { - xhr.upload.onprogress = function(event) { - var percent = 0; - var position = event.loaded || event.position; /*event.position is deprecated*/ - var total = event.total; - if (event.lengthComputable) { - percent = Math.ceil(position / total * 100); - } - options.uploadProgress(event, position, total, percent); - }; - } - return xhr; - }; - } - - s.data = null; - var beforeSend = s.beforeSend; - s.beforeSend = function(xhr, o) { - o.data = formdata; - if(beforeSend) - beforeSend.call(o, xhr, options); - }; - $.ajax(s); - } - - // private function for handling file uploads (hat tip to YAHOO!) - function fileUploadIframe(a) { - var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle; - var useProp = !!$.fn.prop; - - if ($(':input[name=submit],:input[id=submit]', form).length) { - // if there is an input with a name or id of 'submit' then we won't be - // able to invoke the submit fn on the form (at least not x-browser) - alert('Error: Form elements must not have name or id of "submit".'); - return; - } - - if (a) { - // ensure that every serialized input is still enabled - for (i=0; i < elements.length; i++) { - el = $(elements[i]); - if ( useProp ) - el.prop('disabled', false); - else - el.removeAttr('disabled'); - } - } - - s = $.extend(true, {}, $.ajaxSettings, options); - s.context = s.context || s; - id = 'jqFormIO' + (new Date().getTime()); - if (s.iframeTarget) { - $io = $(s.iframeTarget); - n = $io.attr('name'); - if (!n) - $io.attr('name', id); - else - id = n; - } - else { - $io = $('