Last active
December 21, 2015 22:59
-
-
Save heygrady/fc6a34e236bcce2a2e09 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Ember from 'ember'; | |
import SearchableSelect from 'ember-searchable-select/components/searchable-select'; | |
import layout from './template'; | |
const menuSelector = '.Searchable-select__options-list-scroll-wrapper'; | |
export default SearchableSelect.extend({ | |
layout, | |
classNames: ['Searchable-select-infinite'], | |
teardown: Ember.on('willDestroyElement', function() { | |
// ensure that scroll event is removed on destroy | |
this.$(menuSelector).off(`scroll.${this.get('elementId')}`); | |
}), | |
_bindMenuScroll() { | |
if (this.get('autoloadMore')) { | |
const component = this; | |
component.$(menuSelector).on(`scroll.${component.elementId}`, function(event) { | |
Ember.run.debounce(component, '_debouncedMenuScroll', event.target, 50); | |
}); | |
} | |
}, | |
_unbindMenuScroll() { | |
const component = this; | |
component.$(menuSelector).off(`scroll.${component.elementId}`); | |
}, | |
_debouncedMenuScroll(target) { | |
const isLoading = this.get('isLoading'); | |
const isLoadingMore = this.get('isLoadingMore'); | |
const isShowingMenu = this.get('_isShowingMenu'); | |
if (isLoading || isLoadingMore || !isShowingMenu) { | |
return; | |
} | |
const menu = this.$(target); | |
const more = menu.find('.Searchable-select__more-label'); | |
const height = this.get('_menuHeight'); | |
if (!more.length || !menu.length || !height) { | |
return; | |
} | |
const scrollPosition = more.offset().top - menu.offset().top - height; | |
const hasMore = this.get('_hasMore'); | |
const shouldSearchMore = hasMore && scrollPosition < 0; | |
if (shouldSearchMore) { | |
this.send('searchMore'); | |
} | |
}, | |
// cache menu height, no need to measure it on every scroll | |
_menuHeight: Ember.computed('_filteredContent.length', '_isShowingMenu', function() { | |
if (!this.get('_isShowingMenu')) { | |
return 0; | |
} | |
const menu = this.$(menuSelector); | |
if (!menu.length) { | |
return 0; | |
} | |
return menu.height(); | |
}), | |
resultCountMessage: 'result', | |
loadingMoreMessage: 'Searching more results...', | |
moreMessage: 'More results available', | |
noMoreMessage: 'No more results', | |
autoloadMore: true, | |
isLoadingMore: false, | |
_isLoading: Ember.computed('isLoading', 'isLoadingMore', function() { | |
const isLoading = this.get('isLoading'); | |
const isLoadingMore = this.get('isLoadingMore'); | |
return isLoading && !isLoadingMore; | |
}), | |
showResultCount: true, | |
_isShowingResultCount: Ember.computed.and('showResultCount', 'meta.total', '_searchText'), | |
showSearchClear: true, | |
_isShowingSearchClear: Ember.computed.and('showSearchClear', '_searchText'), | |
meta: null, | |
_resultCount: Ember.computed('meta.total', function() { | |
return parseInt(this.get('meta.total'), 10); | |
}), | |
_currentPage: Ember.computed('meta.page', function() { | |
return parseInt(this.get('meta.page'), 10); | |
}), | |
_totalPages: Ember.computed('meta.pages', function() { | |
return parseInt(this.get('meta.pages'), 10); | |
}), | |
_hasMeta: Ember.computed.bool('meta'), | |
_hasMore: Ember.computed('_currentPage', '_totalPages', function() { | |
const currentPage = this.get('_currentPage') || 0; | |
const totalPages = this.get('_totalPages') || 0; | |
return currentPage < totalPages; | |
}), | |
_hasNoMore: Ember.computed.not('_hasMore'), | |
'on-search-more': Ember.K, | |
actions: { | |
// override for scrolling wrapper to top | |
updateSearch(text) { | |
this.set('_searchText', text); | |
this['on-search'].call(this, text); | |
Ember.run.scheduleOnce('afterRender', this, function() { | |
this.$(menuSelector).scrollTop(0); | |
}); | |
}, | |
clearSearch() { | |
this.set('_searchText', ''); | |
this.$('.Searchable-select__input').val('').focus().keyup(); | |
}, | |
searchMore() { | |
const searchText = this.get('_searchText'); | |
const nextPage = this.get('_currentPage') + 1; | |
Ember.run(this, 'on-search-more', searchText, nextPage); | |
}, | |
// override for binding scroll | |
showMenu() { | |
this.set('_isShowingMenu', true); | |
Ember.run.scheduleOnce('afterRender', this, function() { | |
this.$('.Searchable-select__input').focus(); | |
}); | |
Ember.run.next(this, function() { | |
this._bindOutsideClicks(); | |
this._bindMenuScroll(); | |
}); | |
}, | |
// override for unbinding scroll | |
hideMenu() { | |
this._unbindMenuScroll(); | |
this._unbindOutsideClicks(); | |
this.set('_isShowingMenu', false); | |
this.set('_searchText', ''); | |
this.$('.Searchable-select__label').focus(); | |
}, | |
clickResultCountLabel() { | |
this.$('.Searchable-select__input').focus(); | |
}, | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.Searchable-select-infinite { | |
.Searchable-select__options-list-scroll-wrapper { | |
max-height: 300px; | |
overflow: auto; | |
} | |
.Searchable-select__options-list { | |
overflow: visible; | |
max-height: auto; | |
} | |
.Searchable-select__options-list__has-more-item { | |
.Searchable-select__loader { | |
float:left; | |
margin-left: -20px; | |
} | |
} | |
.Searchable-select__more-label { | |
cursor: pointer; | |
} | |
.Searchable-select__clear-search { | |
border: none; | |
background: none; | |
color: #ccc; | |
position: absolute; | |
right: 20px; | |
top: 17px; | |
} | |
.Searchable-select__result-count-label { | |
color: #ccc; | |
position: absolute; | |
right: 20px; | |
top: 20px; | |
&.Searchable-select__result-count-label__with-search-clear { | |
right: 50px; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment