Search code examples
javascriptjqueryjsonjquery-uiuicomponents

How to make login box into a reusable UI component?


Using jQuery, how would I go about making a reusable UI component from this login box, so that it could be used twice on one page?

jQuery:

(function ($) {
  $.fn.loginBox = function () {

    this.html('<div class="loginContainer"><div class="formContainer"><form action="api.yoursite.com/login" class="loginForm" name="loginForm" method="post"><fieldset class="loginFields"><legend>User Login</legend><h1>User Login</h1><input autofocus class="loginID" type="email" name="email" placeholder="Apple ID" required /><input class="loginPassword" type="password" name="password" placeholder="Password" required /><button class="loginSubmit" name="submit" type="submit">Login to your account</button></fieldset></form></div></div>');

    $(".loginForm").submit(function () {

      var username = $(this).find(".loginID").val();
      var password = $(this).find(".loginPassword").val();

      $.ajax({
        type: "POST",
        url: "api.yoursite.com/login",
        data: { username: username, password: password },
        success: function (data) {
          console.log("succeeded");
        },
        error: function (data) {
          console.log("failed");
        }
      });

      return false;
    });

    return this; // make this plug-in chainable
  };

}(jQuery));

var loginOne = $("#loginOne").loginBox();
var loginTwo = $("#loginTwo").loginBox();

Am I best suited taking cues from a framework like Ink.js and loading separate scripts for each component, or is there a simpler approach?

HTML:

<body>
    <div id="loginOne"></div>

    <br />

    <div id="loginTwo"></div>

</body>

Update: I've tied two separate form instances to a single script - will it manage separate state and common behavior for each of them, or is this approach problematic?


Solution

  • I guess your code would work, however, I have some suggestions:

    • I would have added a hidden login template to the DOM that you can clone() and re-use. Keeping the HTML inline in the javascript will start becoming troublesome when you want some more complex functionality and/or layout.

    • You can't simply do var username = $(".loginID").val();. This will always get you the first element with class loginID. You need to make use of the this pointer when dealing with multiple instances.

    • Pass the data as an object literal. Change data: "username=" + username + "&password=" + password to data: { username: username, password: password }.

    Just my two cents.

    var Loginbox = (function($){
    
        function loginbox(){
    
            this.$element = $('.logintemplate').clone()
                                               .removeClass('logintemplate');
            this.bindEvents();
        }
    
        loginbox.prototype = {
            bindEvents: function(){
    
                var that = this;
    
                this.$element.find('.send').on('click', function(){
    
                    $.ajax({
                        url: '/echo/json',
                        type: 'POST',
                        data: { 
                            username: that.$element.find('.username').val(), 
                            password: that.$element.find('.password').val() 
                        }
    
                    }).done(function(data){
                         console.log('done');
                    }).fail(function(){
                        console.log('fail');
                    });
    
                });
            }
        };
    
        return loginbox;
    
    })(jQuery);
    
    for(var i = 0; i < 4; i++){
        var box = new Loginbox();
        $('body').append(box.$element.show());
    }
    

    http://jsfiddle.net/wJK4p/