2012-11-04

Bacon.js Tutorial Part I : Hacking With jQuery


This is the first part of a hopefully upcoming series of postings intended as a Bacon.js tutorial. I'll be building a fully functional, however simplified, AJAX registration form for an imaginary web site.
This material is based on my presentation/hands-on session at Reaktor Dev Day 2012 where I had to squeeze a Bacon.js intro and a coding session into less than an hour. I didn't have much time to discuss the problem and jumped into the solution a bit too fast. This time I'll first try to explain the problem I'm trying to solve with Bacon. So bear with me. Or have a look at the Full Solution first if you like.
Anyway, the registration form could look something like this:
ui-sketch
This seems ridiculously simple, right? Enter username, fullname, click and you're done. As in
      registerButton.click(function(event) {
        event.preventDefault()
        var data = { username: usernameField.val(), fullname: fullnameField.val()}
        $.ajax({
          type: "post",
          url: "/register",
          data: JSON.stringify(data)
        })
      })
At first it might seem so, but if you're planning on implementing a top-notch form, you'll want to consider including
  1. Username availability checking while the user is still typing the username
  2. Showing feedback on unavailable username
  3. Showing an AJAX indicator while this check is being performed
  4. Disabling the Register button until both username and fullname have been entered
  5. Disabling the Register button in case the username is unavailable
  6. Disabling the Register button while the check is being performed
  7. Disabling the Register button immediately when pressed to prevent double-submit
  8. Showing an AJAX indicator while registration is being processed
  9. Showing feedback after registration
Some requirements, huh? Still, all of these sound quite reasonable, at least to me. I'd even say that this is quite standard stuff nowadays. You might now model the UI like this:
dependencies
Now you see that, for instance, enabling/disabling the Register button depends on quite a many different things, some of them asynchronous. But hey, fuck the shit. Let's just hack it together now, right? Some jQuery and we're done in a while.
[hack hack hack] ... k, done.
      var usernameAvailable, checkingAvailability, clicked

      usernameField.keyup(function(event) {
        showUsernameAjaxIndicator(true)
        updateButtonState()
        $.ajax({ url : "/usernameavailable/" + usernameField.val()}).done(function(available) {
          usernameAvailable = available
          setVisibility(unavailabilityLabel, !available)
          showUsernameAjaxIndicator(false)
          updateButtonState()
        })
      })

      fullnameField.keyup(updateButtonState)

      registerButton.click(function(event) {
        event.preventDefault()
        clicked = true
        setVisibility(registerAjaxIndicator, true)
        updateButtonState()
        var data = { username: usernameField.val(), fullname: fullnameField.val()}
        $.ajax({
          type: "post",
          url: "/register",
          data: JSON.stringify(data)
        }).done(function() {
          setVisibility(registerAjaxIndicator, false)
          resultSpan.text("Thanks!")
        })
      })

      updateButtonState()

      function showUsernameAjaxIndicator(show) {
        checkingAvailability = show
        setVisibility(usernameAjaxIndicator, show)
      }

      function updateButtonState() {
        setEnabled(registerButton, usernameAvailable 
                                    && nonEmpty(usernameField.val()) 
                                    && nonEmpty(fullnameField.val())
                                    && !checkingAvailability
                                    && !clicked)
      }
Beautiful? Nope, could be even uglier though. Works? Seems to. Number of variables? 3.
Unfortunately, there's still a major bug in the code: the username availability responses may return in a different order than they were requested, in which case the code may end up showing an incorrect result. Easy to fix? Well, kinda.. Just add a counter and .. Oh, it's sending tons of requests even if you just move the cursor with the arrow keys in the username field. Hmm.. One more variable and.. Still too many requests... Throttling needed... It's starting to get a bit complicated now... Oh, setTimeout, clearTimeout... DONE.
Here's the code now:
      var usernameAvailable, checkingAvailability, clicked, previousUsername, timeout
      var counter = 0

      usernameField.keyup(function(event) {
        var username = usernameField.val()
        if (username != previousUsername) {
          if (timeout) {
            clearTimeout(timeout)
          }
          previousUsername = username
          timeout = setTimeout(function() {
            showUsernameAjaxIndicator(true)
            updateButtonState()
            var id = ++counter
            $.ajax({ url : "/usernameavailable/" + username}).done(function(available) {
              if (id == counter) {
                usernameAvailable = available
                setVisibility(unavailabilityLabel, !available)
                showUsernameAjaxIndicator(false)
                updateButtonState()
              }
            })
          }, 300)
        }
      })

      fullnameField.keyup(updateButtonState)

      registerButton.click(function(event) {
        event.preventDefault()
        clicked = true
        setVisibility(registerAjaxIndicator, true)
        updateButtonState()
        var data = { username: usernameField.val(), fullname: fullnameField.val()}
        $.ajax({
          type: "post",
          url: "/register",
          data: JSON.stringify(data)
        }).done(function() {
          setVisibility(registerAjaxIndicator, false)
          resultSpan.text("Thanks!")
        })
      })

      updateButtonState()

      function showUsernameAjaxIndicator(show) {
        checkingAvailability = show
        setVisibility(usernameAjaxIndicator, show)
      }

      function updateButtonState() {
        setEnabled(registerButton, usernameAvailable 
                                    && nonEmpty(usernameField.val()) 
                                    && nonEmpty(fullnameField.val())
                                    && !checkingAvailability
                                    && !clicked)
      }
Number of variables: 6 Max. level of nesting: 5
Are your eyes burning already?
Writing this kind of code is like changing diapers. Except kids grow up and change your diapers in the end. This kind of code just grows uglier and more disgusting and harder to maintain. It's like if your kids gradually started to... Well, let's not go there.
How to improve this code? With MVC frameworks. Nope. Object-oriented design? Maybe. You'll end up with more code and better structure, but iIt will still be hard to separate concerns cleanly...
No matter what, you'll need to store the UI state, like whether or not an AJAX request is pending, somewhere. And you need to trigger things like enabling/disabling the button somewhere, and usually in many places, as in the code above. This introduces dependencies in all the wrong places. Now many different parts of code need to know about updating the status of the button, while it should be the other way around.
With the well-known Observer pattern (say, jQuery custom events) you can do some decoupling, so that you'll have an Observer that observes many events and then updates the button state. But, this does not solve the problem of providing the updateButtonState function with all the relevant data. So you'll end up using one mechanism for triggering state update and another one for maintaining required mutable state. No good.
Wouldn't it be great if you had some abstraction for a signal that you can observe and compose, so that the "button enabled" state would be a composite signal constructed from all the required input signals?
Say yes.
Good. The Property class in Bacon.js is just that: a composable signal representing the state of something. The EventStream class is a composable signal representing distinct events. Define the following signals:
var username = ..
var fullname = ..
var buttonClick = ..
The rest is just composition.
But hey, I'll get to that in the next posting.

33 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. I built a promise-based version of your tutorial using when.js from cujoJS. I know it's not a full-blown version with respect to BaconJS but it is a start. Check it out at http://itjumpstart.net/demo3.html

    ReplyDelete
  3. Wonderful bloggers like yourself who would positively reply encouraged me to be more open and engaging in commenting.So know it's helpful.
    PHP Training in Chennai

    ReplyDelete
  4. What you have written in this post is exactly what I have experience when I first started my blog.I’m happy that I came across with your site this article is on point,thanks again and have a great day.Keep update more information.

    Hadoop Training in Chennai

    Dot Net Training in Chennai

    ReplyDelete
  5. Very Interesting information shared than other blogs
    Thanks for Sharing and Keep updating us

    ReplyDelete
  6. Thank you for taking the time and sharing this information with us. It was indeed very helpful and insightful while being straight forward and to the point.
    www.mcdonaldsgutscheine.net | www.startlr.com | www.saludlimpia.com

    ReplyDelete
  7. Thanks For Providing good Information.
    Can I know which courses will be helpful in Upgrading career apart from Java.
    Microsoft Dynamics CRM Online Training
    Oracle SCM Online Training
    Hadoop Admin Online Training
    Oracle Financials Training





    ReplyDelete
  8. Hello Well written Blog your way of narration is good and easy to understand. The tree structure which you showcased explains each and every element Well While I was doing my PMP Course in Kuwait. I found similar set of things very interesting and well I landed on your blog I am waiting for your next Update Thankyou..

    ReplyDelete
  9. Hello Juha Paananen, Thanks for your nice Information about Jquery. I just want to Share few words with you. I am Currently working on Microsoft Dynamics CRM . I want to Switch to Jquery is this useful for me to plan my career or not please let me Know Thanks in advance.

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. Really it was an awesome article...very interesting to read..You have provided an nice article....Thanks for sharing..
    Android Training in Chennai
    Ios Training in Chennai

    ReplyDelete
  12. Webtrackker is the first-rate SAP training in noida SAP is the sector's biggest business enterprise useful resource planning (ERP) software employer. Generally SAP stands for systems applications and merchandise in records processing
    Sap Training Institute in Noida
    Sas Training Institute in Noida
    PHP Training Institute in Noida
    Hadoop Training Institute in Noida
    Oracle Training Institute in Noida
    Linux Training Institute in Noida
    Dot net Training Institute in Noida
    Salesforce training institute in noida
    Java training institute in noida

    ReplyDelete
  13. Australia Best Tutor is one of the best Online Assignment Help providers at an affordable price. Here All Learners or Students are getting best quality assignment help with reference and styles formatting.

    Visit us for more Information

    Australia Best Tutor
    Sydney, NSW, Australia
    Call @ +61-730-407-305
    Live Chat @ https://www.australiabesttutor.com




    Our Services

    Online assignment help
    my assignment help Student
    Assignment help Student
    help with assignment Student
    Students instant assignment help

    ReplyDelete
  14. This comment has been removed by the author.

    ReplyDelete
  15. Thank you. Truly appreciate all your hardwork, especially your down-to-earth attitude. Also Visit this site for jQuery Certification

    ReplyDelete
  16. CIITN Noida provides Best java training in noida based on current industry standards that helps attendees to secure placements in their dream jobs at MNCs.The curriculum of our Java training institute in Noida is designed in a way to make sure that our students are not just able to understand the important concepts of the programming language but are also able to apply the knowledge in a practical way.
    Java is inescapable, stopping meters, open transportation passes, ATMs, charge cards and TVs wherever Java is utilized.
    What's more, that is the reason Well-prepared, profoundly gifted Java experts are high sought after.

    If you wanna best java training, java industrial training, java summer training, core java training in noida, then join CIITN Noida.

    ReplyDelete
  17. Nice looking sites and great work. Pretty nice information. it has a better understanding. thanks for spending time on it.

    Hadoop Training Institute in Noida

    Best Hadoop Training in Noida

    ReplyDelete
  18. CIIT Noida provides Best MCA Courses in Noida based on the current

    IT industry standards that help students to get high paying jobs in Top MNCs. CIIT provides Best MCA Training in Noida, Greater Noida, and Ghaziabad.

    CIIT is one of the trusted MCA training institutes in Noida providing practical knowledge and 100% job assistance with basic as well as advanced

    level MCA subjects. CIITN is the best MCA college in Noida, greater noida, ghaziabad, delhi, gurgaon regoin.

    At CIIT MCA classes in Noida is conducted by subject experts corporate professionals with 9+ years of experience in managing real-time and live

    projects. Sofracle Nano Specialized MCA classes Noida is the perfect blend of academic learning and practical sessions to provide maximum exposure to

    students that transform an average student into a corporate professional whom companies prefer to hire.

    Best MCA College in Noida

    ReplyDelete
  19. Such a informative post.thanks for sharing the post.Here iam also sharing a link
    B2B Mailing List. That will provide some good information

    ReplyDelete
  20. Such as very good information promoting content are provided and more skills are improved after refer that post.Thank you for sharing this article.For more details about Oracle Fusion SCM Training please Click Here

    ReplyDelete
  21. خدمات نقل وتخزين الاثاث
    تعرف شركة شراء اثاث مستعمل جدة
    ان الاثاث من اكثر الاشياء التي لها ثمن غالي ومكلف للغايةويحتاج الي عناية جيدة وشديدة لقيام بنقلة بطريقة غير مثالية وتعرضة للخدش او الكسر نحن في غني عنه فأن تلفيات الاثاث تؤدي الي التكاليف الباهظة نظرا لتكلفة الاثاث العالية كما انه يؤدي الي الحاجه الي تكلفة اضافية لشراء اثاث من جديد ،
    شركة شراء اثاث مستعمل بجدة
    ، ونظرا لان شركة نقل اثاث بجدة من الشركات التى تعلم جيدا حجم المشكلات والاضرار التى تحدث وهي ايضا من الشركات التى على دراية كاملة بكيفية الوصول الى افضل واحسن النتائج فى عملية النقل ،كل ماعليك ان تتعاون مع شركة شراء الاثاث المستعمل بجدة والاعتماد عليها بشكل كلي في عملية نقل الاثاث من اجل الحصول علي افضل النتائج المثالية في عمليات النقل
    من اهم الخدمات التي تقدمها شركة المستقبل في عملية النقل وتجعلك تضعها من
    ضمن اوائل الشركات هي :
    اعتماد شراء الاثاث المستعمل بجدة علي القيام بأعمال النقل علي عدة مراحل متميزة من اهما اثناء القيام بالنقل داخل المملكة او خارجها وهي مرحلة تصنيف الاثاث عن طريق المعاينة التي تتم من قبل الخبراء والفنين المتخصصين والتعرف علي اعداد القطع الموجودة من قطع خشبية او اجهزة كهربائية ا تحف او اثاث غرف وغيرهم.
    كما اننا نقوم بمرحلة فك الاثاث بعد ذلك وتعتمد شركتنا في هذة المرحلة علي اقوي الاساليب والطرق المستخدمة ويقوم بذلك العملية طاقم كبير من العمالة المتربة للقيام بأعمال الفك والتركيب.
    ارقام شراء الاثاث المستعمل بالرياضثم تأتي بعد ذلك مرحلة التغليف وهي من اهم المراحل التي تعمل علي الحفاظ علي اثاث منزلك وعلي كل قطعة به وتتم عملية التغليف بطريقة مميزة عن باقي الشركات.
    محلات شراء الاثاث المستعمل بالرياضويأتي بعد ذلك للمرحلة الاخيرة وهي نقل الاثاث وتركيبة ويتم اعتمادنا في عملية النقل علي اكبر الشاحنات المميزة التي تساعد علي الحفاظ علي كل قطع اثاثك اثناء عملية السير والنقل كما اننا لا نتطرق الي عمليات النقل التقليدية لخطورتها علي الاثاث وتعرضة للخدش والكسر .
    تخزين الاثاث بالرياض
    ارقام شراء الاثاث المستعمل بجدة
    تمتلك شركة المستقبل افضل واكبر المستودعات المميزة بجدة والتي تساعد علي تحقيق اعلي مستوي من الدقة والتميز فأذا كنت في حيرة من اتمام عملية النقل والتخزين فعليك الاستعانة بشركة نقل اثاث بجدة والاتصال بنا ارقام محلات شراء الاثاث المستعمل بجدة
    والتعاقد معنا للحصول علي كافة خدماتنا وعروضنا المقدمة بأفضل الاسعار المقدمة لعملائنا الكرام .

    ReplyDelete
  22. Its Good information about jquery . Thanks for sharing this information. Really appreciate to share this article. Again Thanks.
    mulesoft training

    ReplyDelete
  23. The information you provided in the article is useful and beneficial Bala Guntipalli Thanks for posting.

    ReplyDelete
  24. Really Thanks For Posting Such an Useful Content and Information.....Salesforce Training

    ReplyDelete
  25. Each department of CAD have specific programmes which, while completed could provide you with a recognisable qualification that could assist you get a job in anything design enterprise which you would really like.

    AutoCAD training in Noida

    AutoCAD training institute in Noida


    Best AutoCAD training institute in Noida

    ReplyDelete
  26. Thanks for sharing this blog. This very important and informative blog Learned a lot of new things from your post! Good creation and HATS OFF to the creativity of your mind.
    Very interesting and useful blog!
    best wireless bluetooth headphones
    best power bank for mobile
    dual sim smartphone
    keypad mobiles with wifi and whatsapp
    best smartphone accessories
    basic mobile phones dual sim low price
    Best Mouse under 300
    best wired Mouse under 500
    full hd computer monitor

    ReplyDelete