| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- class app.views.Search extends app.View
- SEARCH_PARAM = app.config.search_param
- @el: '._search'
- @activeClass: '_search-active'
- @elements:
- input: '._search-input'
- resetLink: '._search-clear'
- @events:
- input: 'onInput'
- click: 'onClick'
- submit: 'onSubmit'
- @shortcuts:
- typing: 'focus'
- altG: 'google'
- altS: 'stackoverflow'
- altD: 'duckduckgo'
- @routes:
- after: 'afterRoute'
- init: ->
- @addSubview @scope = new app.views.SearchScope @el
- @searcher = new app.Searcher
- @searcher
- .on 'results', @onResults
- .on 'end', @onEnd
- @scope
- .on 'change', @onScopeChange
- app.on 'ready', @onReady
- $.on window, 'hashchange', @searchUrl
- $.on window, 'focus', @onWindowFocus
- return
- focus: =>
- return if document.activeElement is @input
- return if app.settings.get('noAutofocus')
- @input.focus()
- return
- autoFocus: =>
- return if app.isMobile() or $.isAndroid() or $.isIOS()
- return if document.activeElement?.tagName is 'INPUT'
- return if app.settings.get('noAutofocus')
- @input.focus()
- return
- onWindowFocus: (event) =>
- @autoFocus() if event.target is window
- getScopeDoc: ->
- @scope.getScope() if @scope.isActive()
- reset: (force) ->
- @scope.reset() if force or not @input.value
- @el.reset()
- @onInput()
- @autoFocus()
- return
- onReady: =>
- @value = ''
- @delay @onInput
- return
- onInput: =>
- return if not @value? or # ignore events pre-"ready"
- @value is @input.value
- @value = @input.value
- if @value.length
- @search()
- else
- @clear()
- return
- search: (url = false) ->
- @addClass @constructor.activeClass
- @trigger 'searching'
- @hasResults = null
- @flags = urlSearch: url, initialResults: true
- @searcher.find @scope.getScope().entries.all(), 'text', @value
- return
- searchUrl: =>
- if location.pathname is '/'
- @scope.searchUrl()
- else if not app.router.isIndex()
- return
- return unless value = @extractHashValue()
- @input.value = @value = value
- @input.setSelectionRange(value.length, value.length)
- @search true
- true
- clear: ->
- @removeClass @constructor.activeClass
- @trigger 'clear'
- return
- externalSearch: (url) ->
- if value = @value
- value = "#{@scope.name()} #{value}" if @scope.name()
- $.popup "#{url}#{encodeURIComponent value}"
- @reset()
- return
- google: =>
- @externalSearch "https://www.google.com/search?q="
- return
- stackoverflow: =>
- @externalSearch "https://stackoverflow.com/search?q="
- return
- duckduckgo: =>
- @externalSearch "https://duckduckgo.com/?t=devdocs&q="
- return
- onResults: (results) =>
- @hasResults = true if results.length
- @trigger 'results', results, @flags
- @flags.initialResults = false
- return
- onEnd: =>
- @trigger 'noresults' unless @hasResults
- return
- onClick: (event) =>
- if event.target is @resetLink
- $.stopEvent(event)
- @reset()
- return
- onSubmit: (event) ->
- $.stopEvent(event)
- return
- onScopeChange: =>
- @value = ''
- @onInput()
- return
- afterRoute: (name, context) =>
- return if app.shortcuts.eventInProgress?.name is 'escape'
- @reset(true) if not context.init and app.router.isIndex()
- @delay @searchUrl if context.hash
- $.requestAnimationFrame @autoFocus
- return
- extractHashValue: ->
- if (value = @getHashValue())?
- app.router.replaceHash()
- value
- HASH_RGX = new RegExp "^##{SEARCH_PARAM}=(.*)"
- getHashValue: ->
- try HASH_RGX.exec($.urlDecode location.hash)?[1] catch
|