Pages

Visualizzazione post con etichetta JavaScript. Mostra tutti i post
Visualizzazione post con etichetta JavaScript. Mostra tutti i post

giovedì 7 marzo 2013

How to add a "Clear" button (or whatever you want) to jQuery UI's datepicker.

In a perfect world everybody would have an IQ at least equal than a sea sponge. Sadly, is not like this and we have to see a world where people still votes for Berlusconi and people that tries to insert dates haphazardly in our Web Application. Unfortunately we have no hope for the first problem, but for the second God gave us a powerful tool to face them: JQuery UI e it's datepicker.

This tool is useful against the dangerous criminals that enjoys putting "31/Feb/2040" as birth date, but has a little flaw: there's no "Clear" feature.

After seconds and seconds of meditation, i decided to take the screwdriver and put the hands on the jquery UI code to let it work as I wish. all it takes it's two simple steps and less that 100 chars of code:

the final result.
  • Add the functionality to the datepicker's handlers. In other words, exists a function called "_attachHandlers" that creates every command that will be called through the buttons placed inside the datepicker. All we gotta do is adding the indicated lines of code inside this function.

     _attachHandlers: function(inst) {
      var stepMonths = this._get(inst, "stepMonths"),
       id = "#" + inst.id.replace( /\\\\/g, "\\" );
      inst.dpDiv.find("[data-handler]").map(function () {
       var handler = {
        prev: function () {
         window["DP_jQuery_" + dpuuid].datepicker._adjustDate(id, -stepMonths, "M");
        },
        next: function () {
         window["DP_jQuery_" + dpuuid].datepicker._adjustDate(id, +stepMonths, "M");
        },
        hide: function () {
         window["DP_jQuery_" + dpuuid].datepicker._hideDatepicker();
        },
        today: function () {
         window["DP_jQuery_" + dpuuid].datepicker._gotoToday(id);
        },
        // ******** THIS IS THE FUNCTIONALITY ADDED **********
        clear: function () {
            window["DP_jQuery_" + dpuuid].datepicker._clearDate(id); 
        },
        // ********************************************************************    
        selectDay: function () {
         window["DP_jQuery_" + dpuuid].datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
         return false;
        },
        selectMonth: function () {
         window["DP_jQuery_" + dpuuid].datepicker._selectMonthYear(id, this, "M");
         return false;
        },
        selectYear: function () {
         window["DP_jQuery_" + dpuuid].datepicker._selectMonthYear(id, this, "Y");
         return false;
        }
       };
       $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
      });
     }
    
    
    

    The "clear" function is very simple: it just calls the _clearDate function from the datepicker to clear the value.

  • Add the button and link it to the brand new functionality: to do this we need to modify another function called "_generateHTML" to add to the button bar the html representing the button. Two attributes needs to be added to the button to let it link to the functionality just created above: the first is "data-handler" and it represents the name of the function to call ("clear" in our case) and "data-event" that represents the event of the HTML element that fires that functionality (in our case a boring but effective "click"). This is translated to the following code

      //********** old code
      buttonPanel = (showButtonPanel) ? "
    " + (isRTL ? controls : "") + (this._isInRange(inst, gotoDate) ? "" : "") //********** ADD THIS LINE + "" //****************** + (isRTL ? "" : controls) + "
    " : "";

    That's it. It doesn't take to much to achieve that. My example was limited to the "clear" function, but the same proceedings can be used to add new functionalities such as "copy value" functions or other stuff.

mercoledì 9 gennaio 2013

The Pinterest Url Sorcery: How Pinterest changes the url with just an AJAX call.

Before starting i need to tell you first: I do not have a Pinterest account and I'm not looking forward to create one in the future.

A reason why I'll never use Pinterest.

Despite that the Pinterest's homepage caught my attention:

There's a loads and loads of "pinned" (what a horrible verb) articles. When someone cliks on one of them, a popup comes out with the details of the article loaded by AJAX. The sorcery is the fact that in the same time the URL CHANGES AS WELL: that's really cool in a SEO prospective. In top of that, if you try to copy and paste the changed url in another tab of the browser you'll get a stand-alone page of the same article.

To achieve this we need to focus on two main topics:

  • Changing the Url without a HTML call
  • Manage in the same url the Full HTML document and a JSON object (or a partial HTML response)

Let's start with the first one:

 
 
 Link First Pin
 Link Second Pin
 

the magic is done through History API of HTML 5:

"history.pushState(event.target.href, tit, event.target.href)" is the key instruction that allows us to change the url and add it into the navigation history without an actual page refresh.

The event "popstate" instead is raised at the first loading of the page and everytime we go back to the browsing history (so "popping out" the previous history pushed before by the pushState function) and allows us to recreate the same page using the value stored in "e.state" by the first argument of "pushState".

About the second topic, all you need to do is to handle GET requests in the same url in two different ways depending if the value of the HTTP header "X-Requested-With" is set to "XMLHttpRequest"or not: in the first case, you'll need to return a JSON object (or a partial HTML code), else a normal XHTML document.

This can be easily done in WebForms by making a call to the function Server.Transfer to the "partial response" or in ASP.NET MVC returning a different type of ActionResult ("Content" and "Json" for instance instead of "View")

Summarizing that:

  • in your web application, handle with the same url a normal HTML document and a JSON/partial response if the header "X-Requested-With"is set to "XMLHttpRequest"
  • handle the click of the anchor calling history.pushState to modify the url and the navigation history without an actual page refresh.
  • handle the "popstate" event to load the same informations using the "e.state" passed by the first argument of the function pushState.

For more informations about History API click here or here.