HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Handling a text field and submit button with Ajax

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
handlingfieldajaxwithtextsubmitbuttonand

Problem

There's this Ajax-heavy, jQuery-based site which I'm about to work on. There hasn't been much structure in the JavaScript code so far (lots of functions at global scope, hard-coded in the HTML onclick="something(args);". How can I improve upon that and introduce some structure?

Here's what I've tried. This part is supposed to handle a single element which consists of a text field (span) which is replaced by an input on focus and runs an AJAX update call when a submit button is clicked or enter is pressed.

$(function() {
    var box = $('.foobar-info'),
        input = box.find('input'),
        label = box.find('span#name'),
        button = box.find('button');

    label.click(start_edit);
    button.click(submit);
    input.keypress2(KEYS.enter, submit);

    function start_edit() {
        box.addClass('is-edit');
    }
    function submit() {
        MyAjaxModule.edit_foobar(save_success,
            {'id': GLOBAL_FOO_ID, 'value': input.val()});
    }
    function save_success(data) {
        label.text(input.val());
        box.removeClass('is-edit');
    }
});


Showing and hiding of parts is driven by the CSS:

.foobar-info .state-display {display: inline;}
.foobar-info .state-edit {display: none;}
.foobar-info.is-edit .state-display {display: none;}
.foobar-info.is-edit .state-edit {display: inline;}


So far this achieves:

  • keeps the behaviour away from the markup



  • keeps relevant behaviour together in one block



On the other hand, I don't think it's testable or particularly easy to re-use with different configurations.

I've attempted to rewrite this to use objects and this. lookups instead of the big closure, but didn't end up in a code that would please me. For example, this part

label.click(start_edit);


would look like

this.label.click(this.start_edit.bind(this));


which looks really verbose plus it's super-easy to forget the unwieldy .bind(this) part.

This article served some inspiration, but felt rather ha

Solution

There are two schools of thought

  • Programmatic



  • Declarative



Your example here is programmatic, where JavaScript is binding events after the DOM load. The problem I have with programmatic is, using your words, although it "keeps the behavior away from the markup" it moves the markup into the behavior. The interface that is needed to reuse the same JavaScript is now tied to what is defined on the page. Using declarative, your example being onclick="something(args);", I can more easily follow a Model View Presenter (MVP) pattern where the view simply forwards all events to the Presenter to perform the business logic.

Here the events can be organized into a class object to remove them from the global namespace. Scope can be controlled by passing in the model as a parameter.

presenter.js

function Presenter(parameter) {

  // private variables
  var myVar;

  // public method
  this.submit = function() {
  };

  // private method
  function doSomething() {
  }
}


page.html

...

  var presenter = new Presenter(...);

...
Click me

Code Snippets

function Presenter(parameter) {

  // private variables
  var myVar;

  // public method
  this.submit = function() {
  };

  // private method
  function doSomething() {
  }
}
...
<script type="text/javascript" src=".../presenter.js"></script>
<script type="text/javascript">
  var presenter = new Presenter(...);
</script>
...
<button onclick="presenter.onButtonClick();">Click me</button>

Context

StackExchange Code Review Q#28030, answer score: 2

Revisions (0)

No revisions yet.