Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
15403 manish.sha 1
/*
2
 * typeahead.js
3
 * https://github.com/twitter/typeahead.js
4
 * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT
5
 */
6
 
7
var Dataset = (function() {
8
  'use strict';
9
 
10
  var datasetKey = 'ttDataset', valueKey = 'ttValue', datumKey = 'ttDatum';
11
 
12
  // constructor
13
  // -----------
14
 
15
  function Dataset(o) {
16
    o = o || {};
17
    o.templates = o.templates || {};
18
 
19
    if (!o.source) {
20
      $.error('missing source');
21
    }
22
 
23
    if (o.name && !isValidName(o.name)) {
24
      $.error('invalid dataset name: ' + o.name);
25
    }
26
 
27
    // tracks the last query the dataset was updated for
28
    this.query = null;
29
 
30
    this.highlight = !!o.highlight;
31
    this.name = o.name || _.getUniqueId();
32
 
33
    this.source = o.source;
34
    this.displayFn = getDisplayFn(o.display || o.displayKey);
35
 
36
    this.templates = getTemplates(o.templates, this.displayFn);
37
 
38
    this.$el = $(html.dataset.replace('%CLASS%', this.name));
39
  }
40
 
41
  // static methods
42
  // --------------
43
 
44
  Dataset.extractDatasetName = function extractDatasetName(el) {
45
    return $(el).data(datasetKey);
46
  };
47
 
48
  Dataset.extractValue = function extractDatum(el) {
49
    return $(el).data(valueKey);
50
  };
51
 
52
  Dataset.extractDatum = function extractDatum(el) {
53
    return $(el).data(datumKey);
54
  };
55
 
56
  // instance methods
57
  // ----------------
58
 
59
  _.mixin(Dataset.prototype, EventEmitter, {
60
 
61
    // ### private
62
 
63
    _render: function render(query, suggestions) {
64
      if (!this.$el) { return; }
65
 
66
      var that = this, hasSuggestions;
67
 
68
      this.$el.empty();
69
      hasSuggestions = suggestions && suggestions.length;
70
 
71
      if (!hasSuggestions && this.templates.empty) {
72
        this.$el
73
        .html(getEmptyHtml())
74
        .prepend(that.templates.header ? getHeaderHtml() : null)
75
        .append(that.templates.footer ? getFooterHtml() : null);
76
      }
77
 
78
      else if (hasSuggestions) {
79
        this.$el
80
        .html(getSuggestionsHtml())
81
        .prepend(that.templates.header ? getHeaderHtml() : null)
82
        .append(that.templates.footer ? getFooterHtml() : null);
83
      }
84
 
85
      this.trigger('rendered');
86
 
87
      function getEmptyHtml() {
88
        return that.templates.empty({ query: query, isEmpty: true });
89
      }
90
 
91
      function getSuggestionsHtml() {
92
        var $suggestions, nodes;
93
 
94
        $suggestions = $(html.suggestions).css(css.suggestions);
95
 
96
        // jQuery#append doesn't support arrays as the first argument
97
        // until version 1.8, see http://bugs.jquery.com/ticket/11231
98
        nodes = _.map(suggestions, getSuggestionNode);
99
        $suggestions.append.apply($suggestions, nodes);
100
 
101
        that.highlight && highlight({
102
          className: 'tt-highlight',
103
          node: $suggestions[0],
104
          pattern: query
105
        });
106
 
107
        return $suggestions;
108
 
109
        function getSuggestionNode(suggestion) {
110
          var $el;
111
 
112
          $el = $(html.suggestion)
113
          .append(that.templates.suggestion(suggestion))
114
          .data(datasetKey, that.name)
115
          .data(valueKey, that.displayFn(suggestion))
116
          .data(datumKey, suggestion);
117
 
118
          $el.children().each(function() { $(this).css(css.suggestionChild); });
119
 
120
          return $el;
121
        }
122
      }
123
 
124
      function getHeaderHtml() {
125
        return that.templates.header({
126
          query: query,
127
          isEmpty: !hasSuggestions
128
        });
129
      }
130
 
131
      function getFooterHtml() {
132
        return that.templates.footer({
133
          query: query,
134
          isEmpty: !hasSuggestions
135
        });
136
      }
137
    },
138
 
139
    // ### public
140
 
141
    getRoot: function getRoot() {
142
      return this.$el;
143
    },
144
 
145
    update: function update(query) {
146
      var that = this;
147
 
148
      this.query = query;
149
      this.canceled = false;
150
      this.source(query, render);
151
 
152
      function render(suggestions) {
153
        // if the update has been canceled or if the query has changed
154
        // do not render the suggestions as they've become outdated
155
        if (!that.canceled && query === that.query) {
156
          that._render(query, suggestions);
157
        }
158
      }
159
    },
160
 
161
    cancel: function cancel() {
162
      this.canceled = true;
163
    },
164
 
165
    clear: function clear() {
166
      this.cancel();
167
      this.$el.empty();
168
      this.trigger('rendered');
169
    },
170
 
171
    isEmpty: function isEmpty() {
172
      return this.$el.is(':empty');
173
    },
174
 
175
    destroy: function destroy() {
176
      this.$el = null;
177
    }
178
  });
179
 
180
  return Dataset;
181
 
182
  // helper functions
183
  // ----------------
184
 
185
  function getDisplayFn(display) {
186
    display = display || 'value';
187
 
188
    return _.isFunction(display) ? display : displayFn;
189
 
190
    function displayFn(obj) { return obj[display]; }
191
  }
192
 
193
  function getTemplates(templates, displayFn) {
194
    return {
195
      empty: templates.empty && _.templatify(templates.empty),
196
      header: templates.header && _.templatify(templates.header),
197
      footer: templates.footer && _.templatify(templates.footer),
198
      suggestion: templates.suggestion || suggestionTemplate
199
    };
200
 
201
    function suggestionTemplate(context) {
202
      return '<p>' + displayFn(context) + '</p>';
203
    }
204
  }
205
 
206
  function isValidName(str) {
207
    // dashes, underscores, letters, and numbers
208
    return (/^[_a-zA-Z0-9-]+$/).test(str);
209
  }
210
})();