Splitting jQuery code into reusable modules











up vote
1
down vote

favorite












I am in the middle of php app development with some addition of js. Since my JS knowledge is not particularly good, I rely on jQuery. However, I like to work with reusable code rather than spaghetti. So, there is a situation.



I have two kinds of form in the app - classic ones and ajax ones. Now I want to move my ajax form handlers to separated file, module and initiate it in main js file.



My current code:



main.js



import forms from './plugins/ajaxForms';

forms.init($('form.ajax'));


ajaxForms.js



function init(form) {
const obj = this;
form.on('submit', function (e) {
e.preventDefault();
const form = $(this);
const url = form.attr('action');
const data = form.serialize();
const method = form.find('input[name="method"]').val() ? form.find('input[name="method"]').val() : form.attr('method');

const call = $.ajax({
type: method,
url: url,
data: data,
dataType: "json",
beforeSend: function() {
obj.beforeSend(form);
}
});

call.done(function (response) {
Toastr["success"](response.message);
});

call.fail(function (response) {
Toastr["error"](response.responseJSON.message);
obj.renderErrors(form);
});

call.always(function () {
obj.after(form);
});
});
}

function beforeSend(container) {
if(container === null) {
return;
}
container.find('.form-loading-overlay').show();
}

function after(container) {
if(container === null) {
return;
}
container.find('.form-loading-overlay').hide();
}

export default {
init: init,
beforeSend: beforeSend,
after: after,
};


Expected solution:



I do not like the way I am using other functions from this module (such as after(container) - I needed to pass "this" to const obj in order to get it to work with i.e. beforeSend in const call.



In short, I believe there is better way to write this piece of code. I suppose that this particular example is overcomplicated and could be just left as a jquery code closed in submit event. However, I insist on making it modular as I want to learn on this example and refactor rest of my code myself.



Also, I need to be able to access methods like beforeSend(...) and after(...) without using init(...) method, as I am referecing to this methods in other modules while using ajax calls without forms - I still want to display loading overlay on given container during ajax action.










share|improve this question









New contributor




ficus is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • You can set the context : this at jQuery.ajax() for the same object to be set as this at beforeSend and .always(). Why can you not access beforeSend and after without init?
    – guest271314
    Nov 19 at 5:19






  • 1




    My bad. Ultimate goal is to move this code to its own module and make parts of it reusable (for i.e. displaying loading screen on given container). jQuery is just a way to accomplish that as I know it a bit. Didn't mean to override any jquery method.
    – ficus
    2 days ago






  • 1




    They are. Currect code works properly, however I belive it can be done better. It already got quite messy and it will get worse the moment I decide to add some stuff there. It looks more like random code closed in pseudo object rather than real object -> i.e. cannot use this.beforeSend(...) in ajax.beforeSend, need var "obj" as a workaround.
    – ficus
    2 days ago






  • 1




    this is the form within submit event, correct? Have you tried passing beforeSend and after to init(form, beforeSend, after) and using .bind()? Which should set this to the current form within beforeSend beforeSend:beforeSend.bind(this)
    – guest271314
    2 days ago






  • 1




    Yes, correct. I didn't try it tho. It doesn't really make sense for me to pass same object methods from outside to itself. It would generate something like "forms.init($('form.ajax'), forms.beforeSend($('form.ajax'), forms.after($('form.ajax')", wouldn't it? Otherwise I didnt get an idea of bind usage here :(
    – ficus
    yesterday















up vote
1
down vote

favorite












I am in the middle of php app development with some addition of js. Since my JS knowledge is not particularly good, I rely on jQuery. However, I like to work with reusable code rather than spaghetti. So, there is a situation.



I have two kinds of form in the app - classic ones and ajax ones. Now I want to move my ajax form handlers to separated file, module and initiate it in main js file.



My current code:



main.js



import forms from './plugins/ajaxForms';

forms.init($('form.ajax'));


ajaxForms.js



function init(form) {
const obj = this;
form.on('submit', function (e) {
e.preventDefault();
const form = $(this);
const url = form.attr('action');
const data = form.serialize();
const method = form.find('input[name="method"]').val() ? form.find('input[name="method"]').val() : form.attr('method');

const call = $.ajax({
type: method,
url: url,
data: data,
dataType: "json",
beforeSend: function() {
obj.beforeSend(form);
}
});

call.done(function (response) {
Toastr["success"](response.message);
});

call.fail(function (response) {
Toastr["error"](response.responseJSON.message);
obj.renderErrors(form);
});

call.always(function () {
obj.after(form);
});
});
}

function beforeSend(container) {
if(container === null) {
return;
}
container.find('.form-loading-overlay').show();
}

function after(container) {
if(container === null) {
return;
}
container.find('.form-loading-overlay').hide();
}

export default {
init: init,
beforeSend: beforeSend,
after: after,
};


Expected solution:



I do not like the way I am using other functions from this module (such as after(container) - I needed to pass "this" to const obj in order to get it to work with i.e. beforeSend in const call.



In short, I believe there is better way to write this piece of code. I suppose that this particular example is overcomplicated and could be just left as a jquery code closed in submit event. However, I insist on making it modular as I want to learn on this example and refactor rest of my code myself.



Also, I need to be able to access methods like beforeSend(...) and after(...) without using init(...) method, as I am referecing to this methods in other modules while using ajax calls without forms - I still want to display loading overlay on given container during ajax action.










share|improve this question









New contributor




ficus is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • You can set the context : this at jQuery.ajax() for the same object to be set as this at beforeSend and .always(). Why can you not access beforeSend and after without init?
    – guest271314
    Nov 19 at 5:19






  • 1




    My bad. Ultimate goal is to move this code to its own module and make parts of it reusable (for i.e. displaying loading screen on given container). jQuery is just a way to accomplish that as I know it a bit. Didn't mean to override any jquery method.
    – ficus
    2 days ago






  • 1




    They are. Currect code works properly, however I belive it can be done better. It already got quite messy and it will get worse the moment I decide to add some stuff there. It looks more like random code closed in pseudo object rather than real object -> i.e. cannot use this.beforeSend(...) in ajax.beforeSend, need var "obj" as a workaround.
    – ficus
    2 days ago






  • 1




    this is the form within submit event, correct? Have you tried passing beforeSend and after to init(form, beforeSend, after) and using .bind()? Which should set this to the current form within beforeSend beforeSend:beforeSend.bind(this)
    – guest271314
    2 days ago






  • 1




    Yes, correct. I didn't try it tho. It doesn't really make sense for me to pass same object methods from outside to itself. It would generate something like "forms.init($('form.ajax'), forms.beforeSend($('form.ajax'), forms.after($('form.ajax')", wouldn't it? Otherwise I didnt get an idea of bind usage here :(
    – ficus
    yesterday













up vote
1
down vote

favorite









up vote
1
down vote

favorite











I am in the middle of php app development with some addition of js. Since my JS knowledge is not particularly good, I rely on jQuery. However, I like to work with reusable code rather than spaghetti. So, there is a situation.



I have two kinds of form in the app - classic ones and ajax ones. Now I want to move my ajax form handlers to separated file, module and initiate it in main js file.



My current code:



main.js



import forms from './plugins/ajaxForms';

forms.init($('form.ajax'));


ajaxForms.js



function init(form) {
const obj = this;
form.on('submit', function (e) {
e.preventDefault();
const form = $(this);
const url = form.attr('action');
const data = form.serialize();
const method = form.find('input[name="method"]').val() ? form.find('input[name="method"]').val() : form.attr('method');

const call = $.ajax({
type: method,
url: url,
data: data,
dataType: "json",
beforeSend: function() {
obj.beforeSend(form);
}
});

call.done(function (response) {
Toastr["success"](response.message);
});

call.fail(function (response) {
Toastr["error"](response.responseJSON.message);
obj.renderErrors(form);
});

call.always(function () {
obj.after(form);
});
});
}

function beforeSend(container) {
if(container === null) {
return;
}
container.find('.form-loading-overlay').show();
}

function after(container) {
if(container === null) {
return;
}
container.find('.form-loading-overlay').hide();
}

export default {
init: init,
beforeSend: beforeSend,
after: after,
};


Expected solution:



I do not like the way I am using other functions from this module (such as after(container) - I needed to pass "this" to const obj in order to get it to work with i.e. beforeSend in const call.



In short, I believe there is better way to write this piece of code. I suppose that this particular example is overcomplicated and could be just left as a jquery code closed in submit event. However, I insist on making it modular as I want to learn on this example and refactor rest of my code myself.



Also, I need to be able to access methods like beforeSend(...) and after(...) without using init(...) method, as I am referecing to this methods in other modules while using ajax calls without forms - I still want to display loading overlay on given container during ajax action.










share|improve this question









New contributor




ficus is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











I am in the middle of php app development with some addition of js. Since my JS knowledge is not particularly good, I rely on jQuery. However, I like to work with reusable code rather than spaghetti. So, there is a situation.



I have two kinds of form in the app - classic ones and ajax ones. Now I want to move my ajax form handlers to separated file, module and initiate it in main js file.



My current code:



main.js



import forms from './plugins/ajaxForms';

forms.init($('form.ajax'));


ajaxForms.js



function init(form) {
const obj = this;
form.on('submit', function (e) {
e.preventDefault();
const form = $(this);
const url = form.attr('action');
const data = form.serialize();
const method = form.find('input[name="method"]').val() ? form.find('input[name="method"]').val() : form.attr('method');

const call = $.ajax({
type: method,
url: url,
data: data,
dataType: "json",
beforeSend: function() {
obj.beforeSend(form);
}
});

call.done(function (response) {
Toastr["success"](response.message);
});

call.fail(function (response) {
Toastr["error"](response.responseJSON.message);
obj.renderErrors(form);
});

call.always(function () {
obj.after(form);
});
});
}

function beforeSend(container) {
if(container === null) {
return;
}
container.find('.form-loading-overlay').show();
}

function after(container) {
if(container === null) {
return;
}
container.find('.form-loading-overlay').hide();
}

export default {
init: init,
beforeSend: beforeSend,
after: after,
};


Expected solution:



I do not like the way I am using other functions from this module (such as after(container) - I needed to pass "this" to const obj in order to get it to work with i.e. beforeSend in const call.



In short, I believe there is better way to write this piece of code. I suppose that this particular example is overcomplicated and could be just left as a jquery code closed in submit event. However, I insist on making it modular as I want to learn on this example and refactor rest of my code myself.



Also, I need to be able to access methods like beforeSend(...) and after(...) without using init(...) method, as I am referecing to this methods in other modules while using ajax calls without forms - I still want to display loading overlay on given container during ajax action.







javascript jquery modules






share|improve this question









New contributor




ficus is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




ficus is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited Nov 18 at 20:43









Stephen Rauch

3,75051530




3,75051530






New contributor




ficus is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked Nov 18 at 14:04









ficus

162




162




New contributor




ficus is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





ficus is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






ficus is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • You can set the context : this at jQuery.ajax() for the same object to be set as this at beforeSend and .always(). Why can you not access beforeSend and after without init?
    – guest271314
    Nov 19 at 5:19






  • 1




    My bad. Ultimate goal is to move this code to its own module and make parts of it reusable (for i.e. displaying loading screen on given container). jQuery is just a way to accomplish that as I know it a bit. Didn't mean to override any jquery method.
    – ficus
    2 days ago






  • 1




    They are. Currect code works properly, however I belive it can be done better. It already got quite messy and it will get worse the moment I decide to add some stuff there. It looks more like random code closed in pseudo object rather than real object -> i.e. cannot use this.beforeSend(...) in ajax.beforeSend, need var "obj" as a workaround.
    – ficus
    2 days ago






  • 1




    this is the form within submit event, correct? Have you tried passing beforeSend and after to init(form, beforeSend, after) and using .bind()? Which should set this to the current form within beforeSend beforeSend:beforeSend.bind(this)
    – guest271314
    2 days ago






  • 1




    Yes, correct. I didn't try it tho. It doesn't really make sense for me to pass same object methods from outside to itself. It would generate something like "forms.init($('form.ajax'), forms.beforeSend($('form.ajax'), forms.after($('form.ajax')", wouldn't it? Otherwise I didnt get an idea of bind usage here :(
    – ficus
    yesterday


















  • You can set the context : this at jQuery.ajax() for the same object to be set as this at beforeSend and .always(). Why can you not access beforeSend and after without init?
    – guest271314
    Nov 19 at 5:19






  • 1




    My bad. Ultimate goal is to move this code to its own module and make parts of it reusable (for i.e. displaying loading screen on given container). jQuery is just a way to accomplish that as I know it a bit. Didn't mean to override any jquery method.
    – ficus
    2 days ago






  • 1




    They are. Currect code works properly, however I belive it can be done better. It already got quite messy and it will get worse the moment I decide to add some stuff there. It looks more like random code closed in pseudo object rather than real object -> i.e. cannot use this.beforeSend(...) in ajax.beforeSend, need var "obj" as a workaround.
    – ficus
    2 days ago






  • 1




    this is the form within submit event, correct? Have you tried passing beforeSend and after to init(form, beforeSend, after) and using .bind()? Which should set this to the current form within beforeSend beforeSend:beforeSend.bind(this)
    – guest271314
    2 days ago






  • 1




    Yes, correct. I didn't try it tho. It doesn't really make sense for me to pass same object methods from outside to itself. It would generate something like "forms.init($('form.ajax'), forms.beforeSend($('form.ajax'), forms.after($('form.ajax')", wouldn't it? Otherwise I didnt get an idea of bind usage here :(
    – ficus
    yesterday
















You can set the context : this at jQuery.ajax() for the same object to be set as this at beforeSend and .always(). Why can you not access beforeSend and after without init?
– guest271314
Nov 19 at 5:19




You can set the context : this at jQuery.ajax() for the same object to be set as this at beforeSend and .always(). Why can you not access beforeSend and after without init?
– guest271314
Nov 19 at 5:19




1




1




My bad. Ultimate goal is to move this code to its own module and make parts of it reusable (for i.e. displaying loading screen on given container). jQuery is just a way to accomplish that as I know it a bit. Didn't mean to override any jquery method.
– ficus
2 days ago




My bad. Ultimate goal is to move this code to its own module and make parts of it reusable (for i.e. displaying loading screen on given container). jQuery is just a way to accomplish that as I know it a bit. Didn't mean to override any jquery method.
– ficus
2 days ago




1




1




They are. Currect code works properly, however I belive it can be done better. It already got quite messy and it will get worse the moment I decide to add some stuff there. It looks more like random code closed in pseudo object rather than real object -> i.e. cannot use this.beforeSend(...) in ajax.beforeSend, need var "obj" as a workaround.
– ficus
2 days ago




They are. Currect code works properly, however I belive it can be done better. It already got quite messy and it will get worse the moment I decide to add some stuff there. It looks more like random code closed in pseudo object rather than real object -> i.e. cannot use this.beforeSend(...) in ajax.beforeSend, need var "obj" as a workaround.
– ficus
2 days ago




1




1




this is the form within submit event, correct? Have you tried passing beforeSend and after to init(form, beforeSend, after) and using .bind()? Which should set this to the current form within beforeSend beforeSend:beforeSend.bind(this)
– guest271314
2 days ago




this is the form within submit event, correct? Have you tried passing beforeSend and after to init(form, beforeSend, after) and using .bind()? Which should set this to the current form within beforeSend beforeSend:beforeSend.bind(this)
– guest271314
2 days ago




1




1




Yes, correct. I didn't try it tho. It doesn't really make sense for me to pass same object methods from outside to itself. It would generate something like "forms.init($('form.ajax'), forms.beforeSend($('form.ajax'), forms.after($('form.ajax')", wouldn't it? Otherwise I didnt get an idea of bind usage here :(
– ficus
yesterday




Yes, correct. I didn't try it tho. It doesn't really make sense for me to pass same object methods from outside to itself. It would generate something like "forms.init($('form.ajax'), forms.beforeSend($('form.ajax'), forms.after($('form.ajax')", wouldn't it? Otherwise I didnt get an idea of bind usage here :(
– ficus
yesterday















active

oldest

votes











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});






ficus is a new contributor. Be nice, and check out our Code of Conduct.










 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207920%2fsplitting-jquery-code-into-reusable-modules%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes








ficus is a new contributor. Be nice, and check out our Code of Conduct.










 

draft saved


draft discarded


















ficus is a new contributor. Be nice, and check out our Code of Conduct.













ficus is a new contributor. Be nice, and check out our Code of Conduct.












ficus is a new contributor. Be nice, and check out our Code of Conduct.















 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207920%2fsplitting-jquery-code-into-reusable-modules%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Morgemoulin

Scott Moir

Souastre