CodePen

HTML

            
              <!-- note this first widget doesn't get setup in JS -->
<!-- everything is done declaratively via our data-widget attribute -->

<div class="widget standard fl bordered" data-widget="dateTime">
    <p class="widget-title">Declarative Widget</p>
    <div class="widget-body">
        <time data-time="date"></time>
        <time data-time="time"></time>
    </div>
</div>


<div class="plugin widget fancy fl bordered">
    <p class="widget-title">jQuery Plugin Widget</p>
    <div class="widget-body">
        <time data-time="date"></time>
        <time data-time="time"></time>
    </div>
</div>


<div id="object-widget" class="widget fancy large fl bordered">
    <p class="widget-title">Object Widget</p>
    <div class="widget-body">
        <a href="#" class="toggle-date">toggle date</a>
        <time data-time="date"></time>
        <time data-time="time"></time>
    </div>
</div>

            
          
!
via HTML Inspector

CSS

            
              body {
    font-family: sans-serif;
}

.fl {
    float: left;
}

.fr {
  float: right;
}

.bordered {
    border: 1px solid #333;
}

.large {
    font-size: 150%;
}

.widget {
    margin: 1em;
}
.widget-title {
    font-size: 1.2em;
    margin-bottom: 0.3em;
    padding: 0.8em;
    margin-top: 0;
}

.widget-body {
    padding: 1em;
}

.widget time {
    padding: 0.3em 0;
    display: block;
}


.widget.standard {
    box-shadow: 1px 1px 6px -2px #222;
}

.widget.standard .widget-title {
    color: white;
    text-shadow: 1px 1px 2px #000;
    border-bottom: 1px solid #333;
    background-color: red;
}


.widget.fancy {
	/* oooh fancy, rounded corners lol */
   border-radius: 0 0 0.4em 0.4em;
}


.fancy .widget-title {
  
  /* ahh fancy gradients */
  
	background: #7abcff; /* Old browsers */
	background: -moz-linear-gradient(top, #7abcff 0%, #60abf8 44%, #4096ee 100%); /* FF3.6+ */
	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#7abcff), color-stop(44%,#60abf8), color-stop(100%,#4096ee)); /* Chrome,Safari4+ */
	background: -webkit-linear-gradient(top, #7abcff 0%,#60abf8 44%,#4096ee 100%); /* Chrome10+,Safari5.1+ */
	background: -o-linear-gradient(top, #7abcff 0%,#60abf8 44%,#4096ee 100%); /* Opera 11.10+ */
	background: -ms-linear-gradient(top, #7abcff 0%,#60abf8 44%,#4096ee 100%); /* IE10+ */
	background: linear-gradient(to bottom, #7abcff 0%,#60abf8 44%,#4096ee 100%); /* W3C */
	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#7abcff', endColorstr='#4096ee',GradientType=0 ); /* IE6-9 */
}

.large .widget-body {
   padding-top: 0; 
}

.toggle-date {
   font-size: 0.5em;
}
            
          
!
? ?
? ?
Must be a valid URL.
+ add another resource
via CSS Lint

JS

            
              
// so first, we want to create a completely new scope 
// to work in, stops us polluting global namespace.
// we'll use a self-invoking function

// include semicolon to prevent issues if concatenating files

;(function($) {
  
    /////////////////////////////////////////////////////////////
    //// a contrived widget with a litle functionality
    /////////////////////////////////////////////////////////////

    // only constructors should begin with a capital letter!

    // plus constructors are awesome because all dependencies
    // get passed in, meaning we very easily unit test if need be :)

    function DateTimeWidget(elem) {
        this.$elem     = $(elem);
        this.$timeElem = this.$elem.find('[data-time="time"]');
        this.$dateElem = this.$elem.find('[data-time="date"]');

        this.timeTimer = null;
        this.dateTimer = null;

        this.hookupTime();
        this.hookupDate();
    };

    // use a prototype because that way every instance of a DateTimeWidget
    // can be extended at once, by anyone, to add new functionality
  
    DateTimeWidget.prototype = {
        
        constructor : DateTimeWidget,
        
        // note use of $.proxy below!

        // this ensures that the callback is always executed
        // in the context of the object you specify - in this
        // case the widget itself.
        // all functions/fields are available without the need
        // for another variable, 's', or whatever :)

        hookupDate : function() {
            this.updateDate();
            this.dateTimer = setInterval($.proxy(this.updateDate, this), 60000);
        },
        
        hookupTime : function() {
            this.updateTime();
            this.timeTimer = setInterval($.proxy(this.updateTime, this), 100);
        },

        updateTime : function() {
            this.$timeElem.text(new Date().toLocaleTimeString());
        },
        
        updateDate : function() {
            this.$dateElem.text(new Date().toDateString());
        },
        
        hideDate : function() {
            this.$dateElem.slideUp(100);
            clearInterval(this.dateTimer);
        },
        
        showDate : function() {
            this.$dateElem.slideDown(100);
            this.hookupDate();
        }
    };

    // also, latch onto something to expose to the wider world
    window.DateTimeWidget = DateTimeWidget;


    // while we're here, why not make it into 
    // a jQuery plugin?! why the hell not :)    
    // e.g. $(".my-widget").dateTimeWidget()
  
    $.fn.dateTimeWidget = function(option) {

        return this.each(function() {
          
            var $this = $(this),
                data  = $this.data("dateTimeWidget");
            
            // check if we'd already worked on this element
            // if not, new up a widget and store against the element
          
            if (!data) $this.data("dateTimeWidget", (data = new DateTimeWidget(this)));

            // if a string was passed a string
            // the intention is to call a method on the widget
            // e.g. $(".widget").dateTimeWidget("hideDate");
          
            if (typeof option === "string") data[option]();
        });
    };

    // we can go one step further again by hooking in a data API!
    // everything can then be set up purely declaratively from HTML
    // e.g. <div data-widget="dateTime"></div>
    // choose whatever naming convention you like
  
    $("[data-widget=dateTime]").each(function() {
        $(this).dateTimeWidget();
    });

  
}(jQuery)); 


// this is our initialisation script
// where everything on the page gets hooked up

;(function($) {
  
    
  var objectWidget  = new DateTimeWidget(document.getElementById("object-widget")),
      $pluginWidget = $(".plugin").dateTimeWidget();
        

    // we can then interact with the widget differently
    // depending whether working with jQuery plugin or directly with object object
  
    $pluginWidget.dateTimeWidget("hideDate");
  
    // so let's do something with our
    // object widget as well, just for proof :)
  
    // set up a click handler to toggle date
    // note $.proxy again to save writing out an anonymous function
  
    // NOTE: toggle() as used here has been removed from
    // jQuery 1.9+
  
  objectWidget.$elem.find(".toggle-date").toggle(
    $.proxy(objectWidget.hideDate, objectWidget),
    $.proxy(objectWidget.showDate, objectWidget)
  );

}(jQuery));

            
          
!
Must be a valid URL.
+ add another resource
via JS Hint
Loading ..................