diff --git a/django_jinja_knockout/static/djk/js/ajaxform.js b/django_jinja_knockout/static/djk/js/ajaxform.js
index eb632f1..75f0ca3 100644
--- a/django_jinja_knockout/static/djk/js/ajaxform.js
+++ b/django_jinja_knockout/static/djk/js/ajaxform.js
@@ -1,3 +1,4 @@
+import { default as axios } from './lib/axios.js';
import { create as laddaCreate } from './lib/ladda.js';
import { showAjaxError } from './errors.js';
@@ -71,14 +72,6 @@ function AjaxForms($selector) {
AjaxForms.submitSelector = 'button[type="submit"], input[type="submit"], input[type="image"]';
AjaxForms.formSubmitSelector = AjaxForms.formSelector + ', ' + AjaxForms.submitSelector;
- AjaxForms.has = function() {
- var result = (typeof $.fn.ajaxForm !== 'undefined');
- if (!result) {
- console.log('@note: jQuery AJAX form plugin is disabled.');
- }
- return result;
- };
-
AjaxForms.create = function($selector) {
this.$forms = $selector.findSelf(this.formSelector);
this.$cancelButtons = this.$forms.find('.btn-cancel-compose');
@@ -110,10 +103,6 @@ function AjaxForms($selector) {
};
AjaxForms.init = function() {
- if (!this.has()) {
- return;
- }
- this.$forms.ajaxForm();
this.$cancelButtons.on('click', AjaxForms.onCancelButtonClick);
// Do not use ajaxForm plugin submit event, otherwise form will be double-POSTed.
this.$submitButtons.on('click', AjaxForms.onSubmitButtonClick);
@@ -121,12 +110,8 @@ function AjaxForms($selector) {
};
AjaxForms.destroy = function() {
- if (!this.has()) {
- return;
- }
this.$submitButtons.off('click', AjaxForms.onSubmitButtonClick);
this.$cancelButtons.off('click', AjaxForms.onCancelButtonClick);
- this.$forms.ajaxFormUnbind();
};
}(AjaxForms.prototype);
@@ -184,11 +169,14 @@ function AjaxForm($form) {
};
AjaxForm.always = function() {
+ this.hasAlways = true;
enableInputs(this.$form);
if (this.$form.has(this.$btn).length === 0) {
enableInput(this.$btn);
}
- if (typeof this.options['uploadProgress'] !== 'undefined') {
+ // the order of calling is important - Ladda should be removed only after the inputs are enabled.
+ this.ladder.remove();
+ if (this.$progressBar !== null) {
this.$progressBar.remove();
}
this._callbacks.always();
@@ -207,36 +195,26 @@ function AjaxForm($form) {
AjaxForm.getOptions = function() {
var self = this;
- return {
- 'url': this.getUrl(),
- type: 'post',
- dataType: 'json',
- beforeSubmit: function() {
- self.beforeSubmit();
- },
- error: function(jqXHR, exception) {
- self.always();
- showAjaxError(jqXHR, exception);
- self._callbacks.error(jqXHR, exception);
- },
- success: function(response) {
- self.always();
- if (self._callbacks.success(response)) {
- /**
- * Set current AjaxForm bindContext for response viewmodel handler,
- * to read this.$form in the handler body.
- */
- vmRouter.respond(response, {context: self});
- }
+ var options = {
+ headers: {
+ // https://github.com/axios/axios/issues/1322#issuecomment-526580627
+ // 'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest',
+ 'Content-Type': 'multipart/form-data',
+ 'Accept': 'application/json, text/javascript',
},
- complete: function() {
- self.ladder.remove();
- }
};
+ if (this.$progressBar !== null) {
+ options.onUploadProgress = function (progressEvent) {
+ var percentComplete = (progressEvent.loaded / progressEvent.total) * 100;
+ self.$progressBar.find('.progress-bar').css('width', percentComplete + '%');
+ }
+ }
+ return options;
};
AjaxForm.setupProgressBar = function() {
var self = this;
+ this.$progressBar = null;
if (this.$form.find('input[type="file"]').length > 0) {
this.$progressBar = $.contents(
'
' +
@@ -246,13 +224,11 @@ function AjaxForm($form) {
'
'
);
this.$progressBar.insertAfter(this.$btn);
- this.options['uploadProgress'] = function(event, position, total, percentComplete) {
- self.$progressBar.find('.progress-bar').css('width', percentComplete + '%');
- };
}
};
AjaxForm.submit = function($btn, callbacks) {
+ var self = this;
this.$btn = $btn;
if (typeof AppConf('fileMaxSize') !== 'undefined' && !this.checkFiles(AppConf('fileMaxSize'))) {
return;
@@ -262,17 +238,42 @@ function AjaxForm($form) {
}
this._callbacks = $.extend({
always: function () {},
- error: function (jqXHR, exception) {},
+ error: function (request, exception) {},
success: function (response) { return true; },
},
callbacks
);
- this.options = this.getOptions();
this.setupProgressBar();
this.ladder = new Ladder(this.$btn);
- this.$form.ajaxSubmit(this.options);
- var jqXHR = this.$form.data('jqxhr');
- jqXHR.setRequestHeader('X_REQUESTED_WITH', 'XMLHttpRequest');
+ this.hasAlways = false;
+ var formData = new FormData(this.$form.get(0));
+ this.beforeSubmit();
+ axios.post(
+ this.getUrl(),
+ formData,
+ this.getOptions()
+ ).then(function (axiosResponse) {
+ self.always();
+ self.hasAlways = true;
+ if (self._callbacks.success(axiosResponse.data)) {
+ /**
+ * Set current AjaxForm bindContext for response viewmodel handler,
+ * to read this.$form in the handler body.
+ */
+ vmRouter.respond(axiosResponse.data, {context: self});
+ }
+ }).catch(function (axiosError) {
+ if (!self.hasAlways) {
+ self.always();
+ };
+ if (typeof axiosError.request !== 'undefined') {
+ showAjaxError(axiosError.request, axiosError.message);
+ self._callbacks.error(axiosError.request, axiosError.message);
+ } else {
+ // Most probably an vmRouter error:
+ console.log(axiosError);
+ }
+ });
return false;
};
diff --git a/django_jinja_knockout/static/djk/js/document.js b/django_jinja_knockout/static/djk/js/document.js
index 093704f..eca24a0 100644
--- a/django_jinja_knockout/static/djk/js/document.js
+++ b/django_jinja_knockout/static/djk/js/document.js
@@ -1,7 +1,6 @@
import moment from './lib/moment.js';
import { sprintf } from './lib/sprintf-esm.js';
import Cookies from './lib/js.cookie.js';
-import './lib/jquery.form.min.js'
/**
* Note: datetime.js is not the part of django-jinja-knockout.
diff --git a/django_jinja_knockout/static/djk/js/lib/jquery.form.min.js b/django_jinja_knockout/static/djk/js/lib/jquery.form.min.js
deleted file mode 100644
index 31ce43b..0000000
--- a/django_jinja_knockout/static/djk/js/lib/jquery.form.min.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/*!
- * jQuery Form Plugin
- * version: 4.3.0
- * Requires jQuery v1.7.2 or later
- * Project repository: https://github.com/jquery-form/form
-
- * Copyright 2017 Kevin Morris
- * Copyright 2006 M. Alsup
-
- * Dual licensed under the LGPL-2.1+ or MIT licenses
- * https://github.com/jquery-form/form#license
-
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- */
-!function(r){"function"==typeof define&&define.amd?define(["jquery"],r):"object"==typeof module&&module.exports?module.exports=function(e,t){return void 0===t&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),r(t),t}:r(jQuery)}(function(q){"use strict";var m=/\r?\n/g,S={};S.fileapi=void 0!==q('').get(0).files,S.formdata=void 0!==window.FormData;var _=!!q.fn.prop;function o(e){var t=e.data;e.isDefaultPrevented()||(e.preventDefault(),q(e.target).closest("form").ajaxSubmit(t))}function i(e){var t=e.target,r=q(t);if(!r.is("[type=submit],[type=image]")){var a=r.closest("[type=submit]");if(0===a.length)return;t=a[0]}var n,o=t.form;"image"===(o.clk=t).type&&(void 0!==e.offsetX?(o.clk_x=e.offsetX,o.clk_y=e.offsetY):"function"==typeof q.fn.offset?(n=r.offset(),o.clk_x=e.pageX-n.left,o.clk_y=e.pageY-n.top):(o.clk_x=e.pageX-t.offsetLeft,o.clk_y=e.pageY-t.offsetTop)),setTimeout(function(){o.clk=o.clk_x=o.clk_y=null},100)}function N(){var e;q.fn.ajaxSubmit.debug&&(e="[jquery.form] "+Array.prototype.join.call(arguments,""),window.console&&window.console.log?window.console.log(e):window.opera&&window.opera.postError&&window.opera.postError(e))}q.fn.attr2=function(){if(!_)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},q.fn.ajaxSubmit=function(M,e,t,r){if(!this.length)return N("ajaxSubmit: skipping submit process - no element selected"),this;var O,a,n,o,X=this;"function"==typeof M?M={success:M}:"string"==typeof M||!1===M&&0',s)).css({position:"absolute",top:"-1000px",left:"-1000px"}),m=d[0],p={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(e){var t="timeout"===e?"timeout":"aborted";N("aborting upload... "+t),this.aborted=1;try{m.contentWindow.document.execCommand&&m.contentWindow.document.execCommand("Stop")}catch(e){}d.attr("src",l.iframeSrc),p.error=t,l.error&&l.error.call(l.context,p,t,e),f&&q.event.trigger("ajaxError",[p,l,t]),l.complete&&l.complete.call(l.context,p,t)}},(f=l.global)&&0==q.active++&&q.event.trigger("ajaxStart"),f&&q.event.trigger("ajaxSend",[p,l]),l.beforeSend&&!1===l.beforeSend.call(l.context,p,l))return l.global&&q.active--,g.reject(),g;if(p.aborted)return g.reject(),g;(a=i.clk)&&(n=a.name)&&!a.disabled&&(l.extraData=l.extraData||{},l.extraData[n]=a.value,"image"===a.type&&(l.extraData[n+".x"]=i.clk_x,l.extraData[n+".y"]=i.clk_y));var x=1,y=2;function b(t){var r=null;try{t.contentWindow&&(r=t.contentWindow.document)}catch(e){N("cannot get iframe.contentWindow document: "+e)}if(r)return r;try{r=t.contentDocument?t.contentDocument:t.document}catch(e){N("cannot get iframe.contentDocument: "+e),r=t.document}return r}var c=q("meta[name=csrf-token]").attr("content"),T=q("meta[name=csrf-param]").attr("content");function j(){var e=X.attr2("target"),t=X.attr2("action"),r=X.attr("enctype")||X.attr("encoding")||"multipart/form-data";i.setAttribute("target",o),O&&!/post/i.test(O)||i.setAttribute("method","POST"),t!==l.url&&i.setAttribute("action",l.url),l.skipEncodingOverride||O&&!/post/i.test(O)||X.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),l.timeout&&(v=setTimeout(function(){h=!0,A(x)},l.timeout));var a=[];try{if(l.extraData)for(var n in l.extraData)l.extraData.hasOwnProperty(n)&&(q.isPlainObject(l.extraData[n])&&l.extraData[n].hasOwnProperty("name")&&l.extraData[n].hasOwnProperty("value")?a.push(q('',s).val(l.extraData[n].value).appendTo(i)[0]):a.push(q('',s).val(l.extraData[n]).appendTo(i)[0]));l.iframeTarget||d.appendTo(u),m.attachEvent?m.attachEvent("onload",A):m.addEventListener("load",A,!1),setTimeout(function e(){try{var t=b(m).readyState;N("state = "+t),t&&"uninitialized"===t.toLowerCase()&&setTimeout(e,50)}catch(e){N("Server abort: ",e," (",e.name,")"),A(y),v&&clearTimeout(v),v=void 0}},15);try{i.submit()}catch(e){document.createElement("form").submit.apply(i)}}finally{i.setAttribute("action",t),i.setAttribute("enctype",r),e?i.setAttribute("target",e):X.removeAttr("target"),q(a).remove()}}T&&c&&(l.extraData=l.extraData||{},l.extraData[T]=c),l.forceSync?j():setTimeout(j,10);var w,S,k,D=50;function A(e){if(!p.aborted&&!k){if((S=b(m))||(N("cannot access response document"),e=y),e===x&&p)return p.abort("timeout"),void g.reject(p,"timeout");if(e===y&&p)return p.abort("server abort"),void g.reject(p,"error","server abort");if(S&&S.location.href!==l.iframeSrc||h){m.detachEvent?m.detachEvent("onload",A):m.removeEventListener("load",A,!1);var t,r="success";try{if(h)throw"timeout";var a="xml"===l.dataType||S.XMLDocument||q.isXMLDoc(S);if(N("isXml="+a),!a&&window.opera&&(null===S.body||!S.body.innerHTML)&&--D)return N("requeing onLoad callback, DOM not available"),void setTimeout(A,250);var n=S.body?S.body:S.documentElement;p.responseText=n?n.innerHTML:null,p.responseXML=S.XMLDocument?S.XMLDocument:S,a&&(l.dataType="xml"),p.getResponseHeader=function(e){return{"content-type":l.dataType}[e.toLowerCase()]},n&&(p.status=Number(n.getAttribute("status"))||p.status,p.statusText=n.getAttribute("statusText")||p.statusText);var o,i,s,u=(l.dataType||"").toLowerCase(),c=/(json|script|text)/.test(u);c||l.textarea?(o=S.getElementsByTagName("textarea")[0])?(p.responseText=o.value,p.status=Number(o.getAttribute("status"))||p.status,p.statusText=o.getAttribute("statusText")||p.statusText):c&&(i=S.getElementsByTagName("pre")[0],s=S.getElementsByTagName("body")[0],i?p.responseText=i.textContent?i.textContent:i.innerText:s&&(p.responseText=s.textContent?s.textContent:s.innerText)):"xml"===u&&!p.responseXML&&p.responseText&&(p.responseXML=F(p.responseText));try{w=E(p,u,l)}catch(e){r="parsererror",p.error=t=e||r}}catch(e){N("error caught: ",e),r="error",p.error=t=e||r}p.aborted&&(N("upload aborted"),r=null),p.status&&(r=200<=p.status&&p.status<300||304===p.status?"success":"error"),"success"===r?(l.success&&l.success.call(l.context,w,"success",p),g.resolve(p.responseText,"success",p),f&&q.event.trigger("ajaxSuccess",[p,l])):r&&(void 0===t&&(t=p.statusText),l.error&&l.error.call(l.context,p,r,t),g.reject(p,"error",t),f&&q.event.trigger("ajaxError",[p,l,t])),f&&q.event.trigger("ajaxComplete",[p,l]),f&&!--q.active&&q.event.trigger("ajaxStop"),l.complete&&l.complete.call(l.context,p,r),k=!0,l.timeout&&clearTimeout(v),setTimeout(function(){l.iframeTarget?d.attr("src",l.iframeSrc):d.remove(),p.responseXML=null},100)}}}var F=q.parseXML||function(e,t){return window.ActiveXObject?((t=new ActiveXObject("Microsoft.XMLDOM")).async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!==t.documentElement.nodeName?t:null},L=q.parseJSON||function(e){return window.eval("("+e+")")},E=function(e,t,r){var a=e.getResponseHeader("content-type")||"",n=("xml"===t||!t)&&0<=a.indexOf("xml"),o=n?e.responseXML:e.responseText;return n&&"parsererror"===o.documentElement.nodeName&&q.error&&q.error("parsererror"),r&&r.dataFilter&&(o=r.dataFilter(o,t)),"string"==typeof o&&(("json"===t||!t)&&0<=a.indexOf("json")?o=L(o):("script"===t||!t)&&0<=a.indexOf("javascript")&&q.globalEval(o)),o};return g}},q.fn.ajaxForm=function(e,t,r,a){if(("string"==typeof e||!1===e&&0