Skip to content

Commit

Permalink
Apply styling though js. Fixes #2.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jake Harding committed Feb 21, 2013
1 parent 38f9fe0 commit ae29dea
Show file tree
Hide file tree
Showing 4 changed files with 296 additions and 195 deletions.
63 changes: 50 additions & 13 deletions src/js/dropdown_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,30 @@
*/

var DropdownView = (function() {
var html = {
suggestionsList: '<div class="tt-suggestions"></div>'
},

css = {
suggestion: [
'white-space: nowrap;',
'cursor: pointer;'
].join(''),

suggestionChild: [
'white-space: normal;'
].join('')
};

// constructor
// -----------

function DropdownView(o) {
utils.bindAll(this);

this.isMouseOverDropdown;
this.isOpen = false;
this.isEmpty = true;
this.isMouseOverDropdown = false;

this.$menu = $(o.menu)
.on('mouseenter', this._handleMouseenter)
Expand Down Expand Up @@ -45,8 +61,8 @@ var DropdownView = (function() {
_moveCursor: function(increment) {
var $suggestions, $cur, nextIndex, $underCursor;

// don't bother moving the cursor if the menu is hidden
if (!this.$menu.hasClass('tt-is-open')) {
// don't bother moving the cursor if the menu is closed or empty
if (!this.isVisible()) {
return;
}

Expand Down Expand Up @@ -81,6 +97,10 @@ var DropdownView = (function() {
// public methods
// --------------

isVisible: function() {
return this.isOpen && !this.isEmpty;
},

hideUnlessMouseIsOverDropdown: function() {
// this helps detect the scenario a blur event has triggered
// this function. we don't want to hide the menu in that case
Expand All @@ -92,9 +112,11 @@ var DropdownView = (function() {
},

hide: function() {
if (this.$menu.hasClass('tt-is-open')) {
if (this.isOpen) {
this.isOpen = false;

this.$menu
.removeClass('tt-is-open')
.hide()
.find('.tt-suggestions > .tt-suggestion')
.removeClass('tt-is-under-cursor');

Expand All @@ -103,15 +125,20 @@ var DropdownView = (function() {
},

show: function() {
if (!this.$menu.hasClass('tt-is-open')) {
this.$menu.addClass('tt-is-open');
if (!this.isOpen) {
this.isOpen = true;

!this.isEmpty && this.$menu.show();

this.trigger('show');
}
},

isOpen: function() {
return this.$menu.hasClass('tt-is-open');
setLanguageDirection: function(dir) {
var ltrCss = { left: '0', right: 'auto' },
rtlCss = { left: 'auto', right:' 0' };

dir === 'ltr' ? this.$menu.css(ltrCss) : this.$menu.css(rtlCss);
},

moveCursorUp: function() {
Expand Down Expand Up @@ -147,8 +174,9 @@ var DropdownView = (function() {

// first time rendering suggestions for this dataset
if ($dataset.length === 0) {
$dataset = $('<li><ol class="tt-suggestions"></ol></li>')
$dataset = $('<div></div>')
.addClass(datasetClassName)
.append(html.suggestionsList)
.appendTo(this.$menu);
}

Expand All @@ -158,14 +186,20 @@ var DropdownView = (function() {
this.clearSuggestions(dataset.name);

if (suggestions.length > 0) {
this.$menu.removeClass('tt-is-empty');
this.isOpen && this.$menu.show();
this.isEmpty = false;

utils.each(suggestions, function(i, suggestion) {
elBuilder.innerHTML = dataset.template.render(suggestion);

el = elBuilder.firstChild;
el.setAttribute('style', css.suggestion);
el.setAttribute('data-value', suggestion.value);

for (var len = el.children.length; len--;) {
el.children[len].setAttribute('style', css.suggestionChild);
}

fragment.appendChild(el);
});
}
Expand All @@ -184,8 +218,11 @@ var DropdownView = (function() {

$suggestions.empty();

// add empty class if the dropdwn menu is empty
this._getSuggestions().length === 0 && this.$menu.addClass('tt-is-empty');

if (this._getSuggestions().length === 0) {
this.$menu.hide();
this.isEmpty = true;
}
}
});

Expand Down
100 changes: 76 additions & 24 deletions src/js/typeahead_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,64 @@
*/

var TypeaheadView = (function() {

var html = {
wrapper: '<span class="twitter-typeahead"></span>',
hint: '<input class="tt-hint" type="text" autocomplete="false" spellcheck="false" disabled>',
dropdown: '<ol class="tt-dropdown-menu tt-is-empty"></ol>'
};
wrapper: '<span class="twitter-typeahead"></span>',
hint: '<input class="tt-hint">',
dropdown: '<div class="tt-dropdown-menu"></div>'
},

css = {
wrapper: [
'position: relative;',
'display: inline-block;',
'*display: inline;',
'*zoom: 1;'
].join(''),

hint: [
'position: absolute;',
'top: 0;',
'left: 0;',
'border-color: transparent;',
'-webkit-box-shadow: none;',
'-moz-box-shadow: none;',
'box-shadow: none;'
].join(''),

query: [
'position: relative;',
'vertical-align: top;',
'background-color: transparent;',
// ie6-8 doesn't fire hover and click events for elements with
// transparent backgrounds, for a workaround, use 1x1 transparent gif
'background-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);',
// not sure why ie7 won't play nice
'*margin-top: -1px;'
].join(''),

dropdown: [
'position: absolute;',
'top: 100%;',
'left: 0;',
// TODO: should this be configurable?
'z-index: 100;',
'display: none;'
].join('')
};

// constructor
// -----------

function TypeaheadView(o) {
utils.bindAll(this);

this.$node = wrapInput(o.input);
this.$node = buildDomStructure(o.input);
this.datasets = o.datasets;
this.dir = null;

// precompile the templates
utils.each(this.datasets, function(key, dataset) {
var parentTemplate = '<li class="tt-suggestion">%body</li>';
var parentTemplate = '<div class="tt-suggestion">%body</div>';

if (dataset.template) {
dataset.template = dataset.engine
Expand Down Expand Up @@ -95,10 +134,12 @@ var TypeaheadView = (function() {
},

_setLanguageDirection: function() {
var dirClassName = 'tt-' + this.inputView.getLanguageDirection();
var dir = this.inputView.getLanguageDirection();

if (!this.$node.hasClass(dirClassName)) {
this.$node.removeClass('tt-ltr tt-rtl').addClass(dirClassName);
if (dir !== this.dir) {
this.dir = dir;
this.$node.css('direction', dir);
this.dropdownView.setLanguageDirection(dir);
}
},

Expand All @@ -110,7 +151,7 @@ var TypeaheadView = (function() {
beginsWithQuery,
match;

if (hint && this.dropdownView.isOpen()) {
if (hint && this.dropdownView.isVisible()) {
inputValue = this.inputView.getInputValue();
query = inputValue
.replace(/\s{2,}/g, ' ') // condense whitespace
Expand Down Expand Up @@ -212,26 +253,37 @@ var TypeaheadView = (function() {

return TypeaheadView;

function wrapInput(input) {
var $input = $(input),
$hint = $(html.hint).css({
'background-color': $input.css('background-color')
});

if ($input.length === 0) {
return null;
}
function buildDomStructure(input) {
var $wrapper = $(html.wrapper),
$dropdown = $(html.dropdown),
$input = $(input),
$hint = $(html.hint);

$wrapper = $wrapper.attr('style', css.wrapper);
$dropdown = $dropdown.attr('style', css.dropdown);

$hint
.attr({
style: css.hint,
type: 'text',
autocomplete: false,
spellcheck: false,
disabled: true
})
.css('background-color', $input.css('background-color'));

$input
.addClass('tt-query')
.attr({ style: css.query, autocomplete: false, spellcheck: false });

// ie7 does not like it when dir is set to auto,
// it does not like it one bit
try { !$input.attr('dir') && $input.attr('dir', 'auto'); } catch (e) {}

return $input
.attr({ autocomplete: false, spellcheck: false })
.addClass('tt-query')
.wrap(html.wrapper)
.wrap($wrapper)
.parent()
.prepend($hint)
.append(html.dropdown);
.append($dropdown);
}
})();
Loading

0 comments on commit ae29dea

Please sign in to comment.