AngularJS sample : $http and Promises

Now includes bootstrap styles and robust features. Full open source on https://github.com/ThomasBurleson/angularJS-TwitterSearch

by netsi1964

HTML

<script src="http://code.angularjs.org/angular-1.0.0rc4.min.js"></script>
<script src="http://code.angularjs.org/angular-resource-1.0.0rc4.min.js"></script>
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">
        <div ng-app="Twitter" ng-controller="SearchController">

            <!-- Header bar with query field -->
            <div id="header">
                <form ng:submit="doSearch(query)">
                    <img id="application" src="https://raw.github.com/ThomasBurleson/angularJS-TwitterSearch/master/webroot/assets/image/tweetbird.png" />
                    <span class="tweetCount" ng-show="tweets.length">{{tweets.length}}</span>

                    <h1>
                        Latest tweets about
                        <input class="input-xlarge focused" ng-model="query"/>
                        <img  id="img-spinner"
                                    ng-class="searching && 'active' "
                                    src="https://raw.github.com/ThomasBurleson/angularJS-TwitterSearch/master/webroot/assets/image/spinner2.gif" alt="Loading"/>

                        <div class="btns">
                            <a class="btn btn-success" ng-click="doSearch(query)" ng-hide="canRefresh()">
                                <i class="icon-search"></i> &nbsp;Search
                            </a>
                            <a class="btn btn-success" ng-click="doSearch(query)" ng-show="canRefresh()">
                                <i class="icon-refresh"></i> &nbsp;Refresh
                            </a>
                            <a class="btn btn-info filter" ng-click="showFilters()">
                                <i class="icon-tags"></i> &nbsp;Filters
                            </a>

                            <div class="hint" ng-show="canRefresh()">auto refresh {{countDown}} secs</div>
                        </div>
                    </h1>
                </form>
            </div>

        ...

CSS

/*@import url(http://fonts.googleapis.com/css?family=Chau+Philomene+One|PT+Mono);*/
@import url(http://fonts.googleapis.com/css?family=Chau+Philomene+One|PT+Sans+Narrow|Pontano+Sans);
@charset "UTF-8";

body {
    background-image: url(https://raw.github.com/ThomasBurleson/angularJS-TwitterSearch/master/webroot/assets/image/linen_gray.jpeg);
    background-repeat: repeat;

    padding: 0px;
}


[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak {
    display:none;
}
ng\:form {
    display:block;
}

#header {
    padding-top: 11px;
    padding-bottom:5px;
   /* overflow: hidden;*/
    height: 54px;
    width:100%;
    text-align: center;

    background: rgb(235,235,233); /* Old browsers */
    background: -moz-linear-gradient(top, rgba(235,235,233,1) 0%, rgba(176,176,176,1) 100%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(235,235,233,1)), color-stop(100%,rgba(176,176,176,1))); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top, rgba(235,235,233,1) 0%,rgba(176,176,176,1) 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top, rgba(235,235,233,1) 0%,rgba(176,176,176,1) 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(top, rgba(235,235,233,1) 0%,rgba(176,176,176,1) 100%); /* IE10+ */
    background: linear-gradient(top, rgba(235,235,233,1) 0%,rgba(176,176,176,1) 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ebebe9', endColorstr='#b0b0b0',GradientType=0 ); /* IE6-9 */

    border-bottom: solid #3a3a44 1px;
}

#header #application {
    float:right;
    padding-right:30px;
}

h1 {
    text-align: left;
    vertical-align: middle;
    background: url('https://raw.github.com/ThomasBurleson/angularJS-TwitterSearch/master/webroot/assets/image/read.png') -8px -7px no-repeat;
    padding-top: 3px;
    padding-bottom: 10px;
    margin-left: 40px;
    padding-left: 55px;
    width:80%;
}
h1 > input {
   ...

JavaScript

/**
 * Twitter `Recent Tweets` Angular JS application was originally presented
 * by Thierry Chatel. This version has
 *
 *   -  improved Controller
 *   -  use of angular.module in main app wrapper (TwitterSearch.js)
 *   -  improved skinning [with Twitter Bootstrap library],
 *   -  improved, complex filters and refresh timer,
 *   -  refresh count down, auto-reset, auto-search
 *   -  use of promise [see .then()],
 *   -  use of ng-hide/ng-show/,enter/return-key to search
 *   -  row selection,
 *   -  and more...
 *
 * Because `TwitterSearch.html` uses <div ng-controller="SearchController">
 * AngularJS will attempt to instantiate and scope a `SearchController` for
 * the specified <div /> and its descendants.
 *
 *  @author Thomas Burleson, Thierry Chatel
 *
 */
function SearchController($scope, $twitter, $log, $rootScope)
{
  var timerID;  // useful if we every wanted to kill the refresh timer

    // *****************************************************
    // Private methods used by controller features
    // *****************************************************

    function sameCase(value) {
      return $scope.filters.caseSensitive ? value : value.toUpperCase();
    }

    function updateTweets(items, merge) {
        merge = merge || false;
        this.tweets = merge ? items.concat( this.tweets ) : items;
    }

    function isEmpty(value) {
      return (typeof value == 'undefined') || value === '' || value === null || value !== value;
    }

  // *****************************************************
  // $scope variables and methods
  // *****************************************************

  $scope.tweets    =  [ ];
  $scope.selected  =  {};
  $scope.query     =  "angularjs";

  $scope.searching =  false;
  $scope.countDown =  180;

  $scope.filters   =  {
    visible         : false,
    caseSensitive   : false,
    any       : '',
    text      : '',
    from      : '',

    // Custom filters to match specific fields
    // e.g.
    //     ...