UNPKG

alpaca

Version:

Alpaca provides the easiest and fastest way to generate interactive forms for the web and mobile devices. It runs simply as HTML5 or more elaborately using Bootstrap, jQuery Mobile or jQuery UI. Alpaca uses Handlebars to process JSON schema and provide

211 lines (157 loc) 5.15 kB
/* * typeahead.js * https://github.com/twitter/typeahead.js * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT */ var Dataset = (function() { 'use strict'; var datasetKey = 'ttDataset', valueKey = 'ttValue', datumKey = 'ttDatum'; // constructor // ----------- function Dataset(o) { o = o || {}; o.templates = o.templates || {}; if (!o.source) { $.error('missing source'); } if (o.name && !isValidName(o.name)) { $.error('invalid dataset name: ' + o.name); } // tracks the last query the dataset was updated for this.query = null; this.highlight = !!o.highlight; this.name = o.name || _.getUniqueId(); this.source = o.source; this.displayFn = getDisplayFn(o.display || o.displayKey); this.templates = getTemplates(o.templates, this.displayFn); this.$el = $(html.dataset.replace('%CLASS%', this.name)); } // static methods // -------------- Dataset.extractDatasetName = function extractDatasetName(el) { return $(el).data(datasetKey); }; Dataset.extractValue = function extractDatum(el) { return $(el).data(valueKey); }; Dataset.extractDatum = function extractDatum(el) { return $(el).data(datumKey); }; // instance methods // ---------------- _.mixin(Dataset.prototype, EventEmitter, { // ### private _render: function render(query, suggestions) { if (!this.$el) { return; } var that = this, hasSuggestions; this.$el.empty(); hasSuggestions = suggestions && suggestions.length; if (!hasSuggestions && this.templates.empty) { this.$el .html(getEmptyHtml()) .prepend(that.templates.header ? getHeaderHtml() : null) .append(that.templates.footer ? getFooterHtml() : null); } else if (hasSuggestions) { this.$el .html(getSuggestionsHtml()) .prepend(that.templates.header ? getHeaderHtml() : null) .append(that.templates.footer ? getFooterHtml() : null); } this.trigger('rendered'); function getEmptyHtml() { return that.templates.empty({ query: query, isEmpty: true }); } function getSuggestionsHtml() { var $suggestions, nodes; $suggestions = $(html.suggestions).css(css.suggestions); // jQuery#append doesn't support arrays as the first argument // until version 1.8, see http://bugs.jquery.com/ticket/11231 nodes = _.map(suggestions, getSuggestionNode); $suggestions.append.apply($suggestions, nodes); that.highlight && highlight({ className: 'tt-highlight', node: $suggestions[0], pattern: query }); return $suggestions; function getSuggestionNode(suggestion) { var $el; $el = $(html.suggestion) .append(that.templates.suggestion(suggestion)) .data(datasetKey, that.name) .data(valueKey, that.displayFn(suggestion)) .data(datumKey, suggestion); $el.children().each(function() { $(this).css(css.suggestionChild); }); return $el; } } function getHeaderHtml() { return that.templates.header({ query: query, isEmpty: !hasSuggestions }); } function getFooterHtml() { return that.templates.footer({ query: query, isEmpty: !hasSuggestions }); } }, // ### public getRoot: function getRoot() { return this.$el; }, update: function update(query) { var that = this; this.query = query; this.canceled = false; this.source(query, render); function render(suggestions) { // if the update has been canceled or if the query has changed // do not render the suggestions as they've become outdated if (!that.canceled && query === that.query) { that._render(query, suggestions); } } }, cancel: function cancel() { this.canceled = true; }, clear: function clear() { this.cancel(); this.$el.empty(); this.trigger('rendered'); }, isEmpty: function isEmpty() { return this.$el.is(':empty'); }, destroy: function destroy() { this.$el = null; } }); return Dataset; // helper functions // ---------------- function getDisplayFn(display) { display = display || 'value'; return _.isFunction(display) ? display : displayFn; function displayFn(obj) { return obj[display]; } } function getTemplates(templates, displayFn) { return { empty: templates.empty && _.templatify(templates.empty), header: templates.header && _.templatify(templates.header), footer: templates.footer && _.templatify(templates.footer), suggestion: templates.suggestion || suggestionTemplate }; function suggestionTemplate(context) { return '<p>' + displayFn(context) + '</p>'; } } function isValidName(str) { // dashes, underscores, letters, and numbers return (/^[_a-zA-Z0-9-]+$/).test(str); } })();