Showing preview only (498K chars total). Download the full file or copy to clipboard to get everything.
Repository: harvesthq/chosen
Branch: main
Commit: c914ecd5120c
Files: 37
Total size: 479.8 KB
Directory structure:
gitextract_85pi0xyb/
├── .github/
│ ├── ISSUE_TEMPLATE.md
│ └── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .travis.yml
├── Gruntfile.coffee
├── LICENSE.md
├── README.md
├── coffee/
│ ├── chosen.jquery.coffee
│ ├── chosen.proto.coffee
│ └── lib/
│ ├── abstract-chosen.coffee
│ └── select-parser.coffee
├── composer.json
├── contributing.md
├── package-travis.yml
├── package.json
├── public/
│ ├── docsupport/
│ │ ├── init.js
│ │ ├── init.proto.js
│ │ ├── prism.css
│ │ ├── prism.js
│ │ ├── prototype-1.7.0.0.js
│ │ └── style.css
│ ├── index.html
│ ├── index.proto.html
│ └── options.html
├── publish-package.sh
├── sass/
│ └── chosen.scss
├── spec/
│ ├── jquery/
│ │ ├── basic.spec.coffee
│ │ ├── bugfixes.spec.coffee
│ │ ├── events.spec.coffee
│ │ ├── max_shown_results.spec.coffee
│ │ └── searching.spec.coffee
│ └── proto/
│ ├── basic.spec.coffee
│ ├── bugfixes.spec.coffee
│ ├── events.spec.coffee
│ ├── max_shown_results.spec.coffee
│ └── searching.spec.coffee
└── tasks/
└── package.coffee
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
<!---
Please read our Contributing Guidelines before opening this issue: https://github.com/harvesthq/chosen/blob/master/contributing.md
Specifically, please note that the issue tracker is intended for bug reports and specific feature requests.
If you have a general support or usage question, please post somewhere like StackOverflow using the `jquery-chosen` tag: http://stackoverflow.com/questions/tagged/jquery-chosen — you'll be much more likely to get a quick answer there.
-->
Summarize your issue here.
### Steps to reproduce
Tell us how to reproduce this issue.
1. This is the first step
2. This is the second step
3. Further steps, etc.
Additionally, please link to a working demo that shows the issue so we can attempt to reproduce. You can use [this template](https://jsfiddle.net/j7k727cp/) as a base. Alternatively, confirm that the [Chosen demo page](http://harvesthq.github.io/chosen/) shows the issue.
### Expected behavior
Tell us what should happen.
### Actual behavior
Tell us what happens instead.
### Environment
- **Chosen Version**:
- **jQuery or Prototype Version**:
- **Browser and Version**:
- **OS and Version**:
### Additional information
Any other information you want to share that is relevant to the issue being reported. This might include the lines of code that you have identified as causing the bug, or potential solutions and workarounds.
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!---
Good pull requests — patches, improvements, new features — are a fantastic help. They should remain focused in scope and avoid containing unrelated commits.
Please review the Pull Requests section of our Contributing Guidelines before submitting your work: https://github.com/harvesthq/chosen/blob/master/contributing.md#pull-requests
-->
### Summary
Provide a general description of the code changes in your pull request.
Please double-check that:
- [ ] All changes were made in CoffeeScript files, **not** JavaScript files.
- [ ] You used [Grunt](https://github.com/harvesthq/chosen/blob/master/contributing.md#grunt) to build the JavaScript files and tested them locally.
- [ ] You've updated both the jQuery *and* Prototype versions.
- [ ] You haven't manually updated the version number in `package.json`.
- [ ] If necessary, you've updated [the documentation](https://github.com/harvesthq/chosen/blob/master/public/options.html).
See the [Pull Requests section of our Contributing Guidelines](https://github.com/harvesthq/chosen/blob/master/contributing.md#pull-requests) for more details.
### References
If your pull request is in reference to one or more open GitHub issues, please mention them here to keep the conversations linked together.
================================================
FILE: .gitignore
================================================
.DS_Store
node_modules
.project
public/*.js
public/*.css
public/*.json
public/LICENSE.md
chosen*.zip
.sass-cache
.ruby-version
.rbenv-gemsets
.grunt
_SpecRunner.html
spec/public
================================================
FILE: .travis.yml
================================================
sudo: false
language: node_js
node_js:
- 6
addons:
apt:
sources:
- git-core
packages:
- git
before_install: npm install -g grunt-cli
before_script: grunt build package-npm package-bower
after_success: ./publish-package.sh
env:
global:
secure: "SOYNh0YO4eLAM38FQxrg7iqytXgdjJHRkmj/1lFzGrGeuuXP6Owe/2TaMyTJXWb9nHAAtRRwQyhAUE07eKhxI6b3YNyozeRulMK4B0K8P3P1B2MslpROyvQYtZupno3dWc0tyvsQ3ucnZE25mtetH6KYcwiI+vHv6hT8HnzBnp0="
================================================
FILE: Gruntfile.coffee
================================================
module.exports = (grunt) ->
require('load-grunt-tasks')(grunt)
grunt.loadNpmTasks('grunt1.0-dom-munger') # the naming convention of the package does not allow auto-discovery.
grunt.initConfig
pkg: grunt.file.readJSON('package.json')
version_tag: 'v<%= pkg.version %>'
comments: """
/*!
Chosen, a Select Box Enhancer for jQuery and Prototype
by Patrick Filler for Harvest, http://getharvest.com
Version <%= pkg.version %>
Full source at https://github.com/harvesthq/chosen
Copyright (c) 2011-<%= grunt.template.today('yyyy') %> Harvest http://getharvest.com
MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
This file is generated by `grunt build`, do not edit it by hand.
*/
\n
"""
minified_comments: "/* Chosen <%= version_tag %> | (c) 2011-<%= grunt.template.today('yyyy') %> by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */\n"
concat:
options:
banner: '<%= comments %>'
jquery:
src: ['public/chosen.jquery.js']
dest: 'public/chosen.jquery.js'
proto:
src: ['public/chosen.proto.js']
dest: 'public/chosen.proto.js'
css:
src: ['public/chosen.css']
dest: 'public/chosen.css'
copy:
main:
src: 'LICENSE.md'
dest: 'public/'
php:
src: 'composer.json'
dest: 'public/'
coffee:
options:
join: true
jquery:
files:
'public/chosen.jquery.js': ['coffee/lib/select-parser.coffee', 'coffee/lib/abstract-chosen.coffee', 'coffee/chosen.jquery.coffee']
proto:
files:
'public/chosen.proto.js': ['coffee/lib/select-parser.coffee', 'coffee/lib/abstract-chosen.coffee', 'coffee/chosen.proto.coffee']
test:
files:
'spec/public/jquery_specs.js': 'spec/jquery/*.spec.coffee'
'spec/public/proto_specs.js': 'spec/proto/*.spec.coffee'
uglify:
options:
banner: '<%= minified_comments %>'
jquery:
options:
ie8: true
mangle:
reserved: ['jQuery']
files:
'public/chosen.jquery.min.js': ['public/chosen.jquery.js']
proto:
files:
'public/chosen.proto.min.js': ['public/chosen.proto.js']
sass:
options:
outputStyle: 'expanded'
chosen_css:
files:
'public/chosen.css': 'sass/chosen.scss'
postcss:
options:
processors: [
require('autoprefixer')(browsers: 'last 2 versions, IE 8')
]
main:
src: 'public/chosen.css'
cssmin:
options:
banner: '<%= minified_comments %>'
keepSpecialComments: 0
main:
src: 'public/chosen.css'
dest: 'public/chosen.min.css'
watch:
default:
files: ['coffee/**/*.coffee', 'sass/*.scss']
tasks: ['build', 'jasmine']
test:
files: ['spec/**/*.coffee']
tasks: ['jasmine']
jasmine:
jquery:
options:
vendor: [
'public/docsupport/jquery-3.2.1.min.js'
]
specs: 'spec/public/jquery_specs.js'
src: [ 'public/chosen.jquery.js' ]
jquery_old:
options:
vendor: [
'public/docsupport/jquery-1.12.4.min.js'
]
specs: 'spec/public/jquery_specs.js'
src: [ 'public/chosen.jquery.js' ]
proto:
options:
vendor: [
'public/docsupport/prototype-1.7.0.0.js'
'node_modules/simulant/dist/simulant.umd.js'
]
specs: 'spec/public/proto_specs.js'
src: [ 'public/chosen.proto.js' ]
grunt.loadTasks 'tasks'
grunt.registerTask 'default', ['build']
grunt.registerTask 'build', ['coffee:jquery', 'coffee:proto', 'sass', 'concat', 'uglify', 'postcss', 'cssmin', 'copy']
grunt.registerTask 'test', ['coffee', 'jasmine']
grunt.registerTask 'test:jquery', ['coffee:test', 'coffee:jquery', 'jasmine:jquery', 'jasmine:jquery_old']
grunt.registerTask 'test:proto', ['coffee:test', 'coffee:proto', 'jasmine:proto']
================================================
FILE: LICENSE.md
================================================
#### Chosen
- by Patrick Filler for [Harvest](http://getharvest.com)
- Copyright (c) 2011-2016 by Harvest
Available for use under the [MIT License](http://en.wikipedia.org/wiki/MIT_License)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: README.md
================================================
# Deprecated
#### This version of Chosen is not currently under active development while we decide on its future direction.
---
# Chosen
Chosen is a library for making long, unwieldy select boxes more user friendly.
- jQuery support: 1.7+
- Prototype support: 1.7+
For **documentation**, usage, and examples, see:
http://harvesthq.github.io/chosen/
For **downloads**, see:
https://github.com/harvesthq/chosen/releases/
### Package managers
Chosen is available through [Bower](https://bower.io/), [npm](https://www.npmjs.com), and [Composer](https://getcomposer.org/), _however, the package names are not the same_.
To install with Bower:
```
bower install chosen
```
To install with npm:
```
npm install chosen-js
```
To install with Composer:
```
composer require harvesthq/chosen
```
The compiled files for these packages are automatically generated and stored in a [2nd Chosen repository](https://github.com/harvesthq/chosen-package). No pull requests will be accepted to that repository.
### Contributing to this project
We welcome all to participate in making Chosen the best software it can be. The repository is maintained by only a few people, but has accepted contributions from over 50 authors after reviewing hundreds of pull requests related to thousands of issues. You can help reduce the maintainers' workload (and increase your chance of having an accepted contribution to Chosen) by following the
[guidelines for contributing](contributing.md).
* [Bug reports](contributing.md#bugs)
* [Feature requests](contributing.md#features)
* [Pull requests](contributing.md#pull-requests)
### Chosen Credits
- Concept and development by [Patrick Filler](http://patrickfiller.com) for [Harvest](http://getharvest.com/).
- Design and CSS by [Matthew Lettini](http://matthewlettini.com/)
- Repository maintained by [@pfiller](http://github.com/pfiller), [@kenearley](http://github.com/kenearley), [@stof](http://github.com/stof), [@koenpunt](http://github.com/koenpunt), and [@tjschuck](http://github.com/tjschuck).
- Chosen includes [contributions by many fine folks](https://github.com/harvesthq/chosen/contributors).
================================================
FILE: coffee/chosen.jquery.coffee
================================================
$ = jQuery
$.fn.extend({
chosen: (options) ->
# Do no harm and return as soon as possible for unsupported browsers, namely IE6 and IE7
# Continue on if running IE document type but in compatibility mode
return this unless AbstractChosen.browser_is_supported()
this.each (input_field) ->
$this = $ this
chosen = $this.data('chosen')
if options is 'destroy'
if chosen instanceof Chosen
chosen.destroy()
return
unless chosen instanceof Chosen
$this.data('chosen', new Chosen(this, options))
return
})
class Chosen extends AbstractChosen
setup: ->
@form_field_jq = $ @form_field
@current_selectedIndex = @form_field.selectedIndex
set_up_html: ->
container_classes = ["chosen-container"]
container_classes.push "chosen-container-" + (if @is_multiple then "multi" else "single")
container_classes.push @form_field.className if @inherit_select_classes && @form_field.className
container_classes.push "chosen-rtl" if @is_rtl
container_props =
'class': container_classes.join ' '
'title': @form_field.title
container_props.id = @form_field.id.replace(/[^\w]/g, '_') + "_chosen" if @form_field.id.length
@container = ($ "<div />", container_props)
# CSP without 'unsafe-inline' doesn't allow setting the style attribute directly
@container.width this.container_width()
if @is_multiple
@container.html this.get_multi_html()
else
@container.html this.get_single_html()
@form_field_jq.hide().after @container
@dropdown = @container.find('div.chosen-drop').first()
@search_field = @container.find('input').first()
@search_results = @container.find('ul.chosen-results').first()
this.search_field_scale()
@search_no_results = @container.find('li.no-results').first()
if @is_multiple
@search_choices = @container.find('ul.chosen-choices').first()
@search_container = @container.find('li.search-field').first()
else
@search_container = @container.find('div.chosen-search').first()
@selected_item = @container.find('.chosen-single').first()
this.results_build()
this.set_tab_index()
this.set_label_behavior()
on_ready: ->
@form_field_jq.trigger("chosen:ready", {chosen: this})
register_observers: ->
@container.on 'touchstart.chosen', (evt) => this.container_mousedown(evt); return
@container.on 'touchend.chosen', (evt) => this.container_mouseup(evt); return
@container.on 'mousedown.chosen', (evt) => this.container_mousedown(evt); return
@container.on 'mouseup.chosen', (evt) => this.container_mouseup(evt); return
@container.on 'mouseenter.chosen', (evt) => this.mouse_enter(evt); return
@container.on 'mouseleave.chosen', (evt) => this.mouse_leave(evt); return
@search_results.on 'mouseup.chosen', (evt) => this.search_results_mouseup(evt); return
@search_results.on 'mouseover.chosen', (evt) => this.search_results_mouseover(evt); return
@search_results.on 'mouseout.chosen', (evt) => this.search_results_mouseout(evt); return
@search_results.on 'mousewheel.chosen DOMMouseScroll.chosen', (evt) => this.search_results_mousewheel(evt); return
@search_results.on 'touchstart.chosen', (evt) => this.search_results_touchstart(evt); return
@search_results.on 'touchmove.chosen', (evt) => this.search_results_touchmove(evt); return
@search_results.on 'touchend.chosen', (evt) => this.search_results_touchend(evt); return
@form_field_jq.on "chosen:updated.chosen", (evt) => this.results_update_field(evt); return
@form_field_jq.on "chosen:activate.chosen", (evt) => this.activate_field(evt); return
@form_field_jq.on "chosen:open.chosen", (evt) => this.container_mousedown(evt); return
@form_field_jq.on "chosen:close.chosen", (evt) => this.close_field(evt); return
@search_field.on 'blur.chosen', (evt) => this.input_blur(evt); return
@search_field.on 'keyup.chosen', (evt) => this.keyup_checker(evt); return
@search_field.on 'keydown.chosen', (evt) => this.keydown_checker(evt); return
@search_field.on 'focus.chosen', (evt) => this.input_focus(evt); return
@search_field.on 'cut.chosen', (evt) => this.clipboard_event_checker(evt); return
@search_field.on 'paste.chosen', (evt) => this.clipboard_event_checker(evt); return
if @is_multiple
@search_choices.on 'click.chosen', (evt) => this.choices_click(evt); return
else
@container.on 'click.chosen', (evt) -> evt.preventDefault(); return # gobble click of anchor
destroy: ->
$(@container[0].ownerDocument).off 'click.chosen', @click_test_action
@form_field_label.off 'click.chosen' if @form_field_label.length > 0
if @search_field[0].tabIndex
@form_field_jq[0].tabIndex = @search_field[0].tabIndex
@container.remove()
@form_field_jq.removeData('chosen')
@form_field_jq.show()
search_field_disabled: ->
@is_disabled = @form_field.disabled || @form_field_jq.parents('fieldset').is(':disabled')
@container.toggleClass 'chosen-disabled', @is_disabled
@search_field[0].disabled = @is_disabled
unless @is_multiple
@selected_item.off 'focus.chosen', this.activate_field
if @is_disabled
this.close_field()
else unless @is_multiple
@selected_item.on 'focus.chosen', this.activate_field
container_mousedown: (evt) ->
return if @is_disabled
if evt and evt.type in ['mousedown', 'touchstart'] and not @results_showing
evt.preventDefault()
if not (evt? and ($ evt.target).hasClass "search-choice-close")
if not @active_field
@search_field.val "" if @is_multiple
$(@container[0].ownerDocument).on 'click.chosen', @click_test_action
this.results_show()
else if not @is_multiple and evt and (($(evt.target)[0] == @selected_item[0]) || $(evt.target).parents("a.chosen-single").length)
evt.preventDefault()
this.results_toggle()
this.activate_field()
container_mouseup: (evt) ->
this.results_reset(evt) if evt.target.nodeName is "ABBR" and not @is_disabled
search_results_mousewheel: (evt) ->
delta = evt.originalEvent.deltaY or -evt.originalEvent.wheelDelta or evt.originalEvent.detail if evt.originalEvent
if delta?
evt.preventDefault()
delta = delta * 40 if evt.type is 'DOMMouseScroll'
@search_results.scrollTop(delta + @search_results.scrollTop())
blur_test: (evt) ->
this.close_field() if not @active_field and @container.hasClass "chosen-container-active"
close_field: ->
$(@container[0].ownerDocument).off "click.chosen", @click_test_action
@active_field = false
this.results_hide()
@container.removeClass "chosen-container-active"
this.clear_backstroke()
this.show_search_field_default()
this.search_field_scale()
@search_field.blur()
activate_field: ->
return if @is_disabled
@container.addClass "chosen-container-active"
@active_field = true
@search_field.val(@search_field.val())
@search_field.focus()
test_active_click: (evt) ->
active_container = $(evt.target).closest('.chosen-container')
if active_container.length and @container[0] == active_container[0]
@active_field = true
else
this.close_field()
results_build: ->
@parsing = true
@selected_option_count = null
@results_data = SelectParser.select_to_array @form_field
if @is_multiple
@search_choices.find("li.search-choice").remove()
else
this.single_set_selected_text()
if @disable_search or @form_field.options.length <= @disable_search_threshold
@search_field[0].readOnly = true
@container.addClass "chosen-container-single-nosearch"
else
@search_field[0].readOnly = false
@container.removeClass "chosen-container-single-nosearch"
this.update_results_content this.results_option_build({first:true})
this.search_field_disabled()
this.show_search_field_default()
this.search_field_scale()
@parsing = false
result_do_highlight: (el) ->
if el.length
this.result_clear_highlight()
@result_highlight = el
@result_highlight.addClass "highlighted"
maxHeight = parseInt @search_results.css("maxHeight"), 10
visible_top = @search_results.scrollTop()
visible_bottom = maxHeight + visible_top
high_top = @result_highlight.position().top + @search_results.scrollTop()
high_bottom = high_top + @result_highlight.outerHeight()
if high_bottom >= visible_bottom
@search_results.scrollTop if (high_bottom - maxHeight) > 0 then (high_bottom - maxHeight) else 0
else if high_top < visible_top
@search_results.scrollTop high_top
result_clear_highlight: ->
@result_highlight.removeClass "highlighted" if @result_highlight
@result_highlight = null
results_show: ->
if @is_multiple and @max_selected_options <= this.choices_count()
@form_field_jq.trigger("chosen:maxselected", {chosen: this})
return false
@container.addClass "chosen-with-drop"
@results_showing = true
@search_field.focus()
@search_field.val this.get_search_field_value()
this.winnow_results()
@form_field_jq.trigger("chosen:showing_dropdown", {chosen: this})
update_results_content: (content) ->
@search_results.html content
results_hide: ->
if @results_showing
this.result_clear_highlight()
@container.removeClass "chosen-with-drop"
@form_field_jq.trigger("chosen:hiding_dropdown", {chosen: this})
@results_showing = false
set_tab_index: (el) ->
if @form_field.tabIndex
ti = @form_field.tabIndex
@form_field.tabIndex = -1
@search_field[0].tabIndex = ti
set_label_behavior: ->
@form_field_label = @form_field_jq.parents("label") # first check for a parent label
if not @form_field_label.length and @form_field.id.length
@form_field_label = $("label[for='#{@form_field.id}']") #next check for a for=#{id}
if @form_field_label.length > 0
@form_field_label.on 'click.chosen', this.label_click_handler
show_search_field_default: ->
if @is_multiple and this.choices_count() < 1 and not @active_field
@search_field.val(@default_text)
@search_field.addClass "default"
else
@search_field.val("")
@search_field.removeClass "default"
search_results_mouseup: (evt) ->
target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first()
if target.length
@result_highlight = target
this.result_select(evt)
@search_field.focus()
search_results_mouseover: (evt) ->
target = if $(evt.target).hasClass "active-result" then $(evt.target) else $(evt.target).parents(".active-result").first()
this.result_do_highlight( target ) if target
search_results_mouseout: (evt) ->
this.result_clear_highlight() if $(evt.target).hasClass("active-result") or $(evt.target).parents('.active-result').first()
choice_build: (item) ->
choice = $('<li />', { class: "search-choice" }).html("<span>#{this.choice_label(item)}</span>")
if item.disabled
choice.addClass 'search-choice-disabled'
else
close_link = $('<a />', { class: 'search-choice-close', 'data-option-array-index': item.array_index })
close_link.on 'click.chosen', (evt) => this.choice_destroy_link_click(evt)
choice.append close_link
@search_container.before choice
choice_destroy_link_click: (evt) ->
evt.preventDefault()
evt.stopPropagation()
this.choice_destroy $(evt.target) unless @is_disabled
choice_destroy: (link) ->
if this.result_deselect( link[0].getAttribute("data-option-array-index") )
if @active_field
@search_field.focus()
else
this.show_search_field_default()
this.results_hide() if @is_multiple and this.choices_count() > 0 and this.get_search_field_value().length < 1
link.parents('li').first().remove()
this.search_field_scale()
results_reset: ->
this.reset_single_select_options()
@form_field.options[0].selected = true
this.single_set_selected_text()
this.show_search_field_default()
this.results_reset_cleanup()
this.trigger_form_field_change()
this.results_hide() if @active_field
results_reset_cleanup: ->
@current_selectedIndex = @form_field.selectedIndex
@selected_item.find("abbr").remove()
result_select: (evt) ->
if @result_highlight
high = @result_highlight
this.result_clear_highlight()
if @is_multiple and @max_selected_options <= this.choices_count()
@form_field_jq.trigger("chosen:maxselected", {chosen: this})
return false
if @is_multiple
high.removeClass("active-result")
else
this.reset_single_select_options()
high.addClass("result-selected")
item = @results_data[ high[0].getAttribute("data-option-array-index") ]
item.selected = true
@form_field.options[item.options_index].selected = true
@selected_option_count = null
if @is_multiple
this.choice_build item
else
this.single_set_selected_text(this.choice_label(item))
if @is_multiple && (!@hide_results_on_select || (evt.metaKey or evt.ctrlKey))
if evt.metaKey or evt.ctrlKey
this.winnow_results(skip_highlight: true)
else
@search_field.val("")
this.winnow_results()
else
this.results_hide()
this.show_search_field_default()
this.trigger_form_field_change selected: @form_field.options[item.options_index].value if @is_multiple || @form_field.selectedIndex != @current_selectedIndex
@current_selectedIndex = @form_field.selectedIndex
evt.preventDefault()
this.search_field_scale()
single_set_selected_text: (text=@default_text) ->
if text is @default_text
@selected_item.addClass("chosen-default")
else
this.single_deselect_control_build()
@selected_item.removeClass("chosen-default")
@selected_item.find("span").html(text)
result_deselect: (pos) ->
result_data = @results_data[pos]
if not @form_field.options[result_data.options_index].disabled
result_data.selected = false
@form_field.options[result_data.options_index].selected = false
@selected_option_count = null
this.result_clear_highlight()
this.winnow_results() if @results_showing
this.trigger_form_field_change deselected: @form_field.options[result_data.options_index].value
this.search_field_scale()
return true
else
return false
single_deselect_control_build: ->
return unless @allow_single_deselect
@selected_item.find("span").first().after "<abbr class=\"search-choice-close\"></abbr>" unless @selected_item.find("abbr").length
@selected_item.addClass("chosen-single-with-deselect")
get_search_field_value: ->
@search_field.val()
get_search_text: ->
$.trim this.get_search_field_value()
escape_html: (text) ->
$('<div/>').text(text).html()
winnow_results_set_highlight: ->
selected_results = if not @is_multiple then @search_results.find(".result-selected.active-result") else []
do_high = if selected_results.length then selected_results.first() else @search_results.find(".active-result").first()
this.result_do_highlight do_high if do_high?
no_results: (terms) ->
no_results_html = this.get_no_results_html(terms)
@search_results.append no_results_html
@form_field_jq.trigger("chosen:no_results", {chosen:this})
no_results_clear: ->
@search_results.find(".no-results").remove()
keydown_arrow: ->
if @results_showing and @result_highlight
next_sib = @result_highlight.nextAll("li.active-result").first()
this.result_do_highlight next_sib if next_sib
else
this.results_show()
keyup_arrow: ->
if not @results_showing and not @is_multiple
this.results_show()
else if @result_highlight
prev_sibs = @result_highlight.prevAll("li.active-result")
if prev_sibs.length
this.result_do_highlight prev_sibs.first()
else
this.results_hide() if this.choices_count() > 0
this.result_clear_highlight()
keydown_backstroke: ->
if @pending_backstroke
this.choice_destroy @pending_backstroke.find("a").first()
this.clear_backstroke()
else
next_available_destroy = @search_container.siblings("li.search-choice").last()
if next_available_destroy.length and not next_available_destroy.hasClass("search-choice-disabled")
@pending_backstroke = next_available_destroy
if @single_backstroke_delete
@keydown_backstroke()
else
@pending_backstroke.addClass "search-choice-focus"
clear_backstroke: ->
@pending_backstroke.removeClass "search-choice-focus" if @pending_backstroke
@pending_backstroke = null
search_field_scale: ->
return unless @is_multiple
style_block =
position: 'absolute'
left: '-1000px'
top: '-1000px'
display: 'none'
whiteSpace: 'pre'
styles = ['fontSize', 'fontStyle', 'fontWeight', 'fontFamily', 'lineHeight', 'textTransform', 'letterSpacing']
for style in styles
style_block[style] = @search_field.css(style)
div = $('<div />').css(style_block)
div.text this.get_search_field_value()
$('body').append div
width = div.width() + 25
div.remove()
if @container.is(':visible')
width = Math.min(@container.outerWidth() - 10, width)
@search_field.width(width)
trigger_form_field_change: (extra) ->
@form_field_jq.trigger "input", extra
@form_field_jq.trigger "change", extra
================================================
FILE: coffee/chosen.proto.coffee
================================================
class @Chosen extends AbstractChosen
setup: ->
@current_selectedIndex = @form_field.selectedIndex
set_up_html: ->
container_classes = ["chosen-container"]
container_classes.push "chosen-container-" + (if @is_multiple then "multi" else "single")
container_classes.push @form_field.className if @inherit_select_classes && @form_field.className
container_classes.push "chosen-rtl" if @is_rtl
container_props =
'class': container_classes.join ' '
'title': @form_field.title
container_props.id = @form_field.id.replace(/[^\w]/g, '_') + "_chosen" if @form_field.id.length
@container = new Element('div', container_props)
# CSP without 'unsafe-inline' doesn't allow setting the style attribute directly
@container.setStyle(width: this.container_width())
if @is_multiple
@container.update this.get_multi_html()
else
@container.update this.get_single_html()
@form_field.hide().insert({ after: @container })
@dropdown = @container.down('div.chosen-drop')
@search_field = @container.down('input')
@search_results = @container.down('ul.chosen-results')
this.search_field_scale()
@search_no_results = @container.down('li.no-results')
if @is_multiple
@search_choices = @container.down('ul.chosen-choices')
@search_container = @container.down('li.search-field')
else
@search_container = @container.down('div.chosen-search')
@selected_item = @container.down('.chosen-single')
this.results_build()
this.set_tab_index()
this.set_label_behavior()
on_ready: ->
@form_field.fire("chosen:ready", {chosen: this})
register_observers: ->
@container.observe "touchstart", (evt) => this.container_mousedown(evt)
@container.observe "touchend", (evt) => this.container_mouseup(evt)
@container.observe "mousedown", (evt) => this.container_mousedown(evt)
@container.observe "mouseup", (evt) => this.container_mouseup(evt)
@container.observe "mouseenter", (evt) => this.mouse_enter(evt)
@container.observe "mouseleave", (evt) => this.mouse_leave(evt)
@search_results.observe "mouseup", (evt) => this.search_results_mouseup(evt)
@search_results.observe "mouseover", (evt) => this.search_results_mouseover(evt)
@search_results.observe "mouseout", (evt) => this.search_results_mouseout(evt)
@search_results.observe "mousewheel", (evt) => this.search_results_mousewheel(evt)
@search_results.observe "DOMMouseScroll", (evt) => this.search_results_mousewheel(evt)
@search_results.observe "touchstart", (evt) => this.search_results_touchstart(evt)
@search_results.observe "touchmove", (evt) => this.search_results_touchmove(evt)
@search_results.observe "touchend", (evt) => this.search_results_touchend(evt)
@form_field.observe "chosen:updated", (evt) => this.results_update_field(evt)
@form_field.observe "chosen:activate", (evt) => this.activate_field(evt)
@form_field.observe "chosen:open", (evt) => this.container_mousedown(evt)
@form_field.observe "chosen:close", (evt) => this.close_field(evt)
@search_field.observe "blur", (evt) => this.input_blur(evt)
@search_field.observe "keyup", (evt) => this.keyup_checker(evt)
@search_field.observe "keydown", (evt) => this.keydown_checker(evt)
@search_field.observe "focus", (evt) => this.input_focus(evt)
@search_field.observe "cut", (evt) => this.clipboard_event_checker(evt)
@search_field.observe "paste", (evt) => this.clipboard_event_checker(evt)
if @is_multiple
@search_choices.observe "click", (evt) => this.choices_click(evt)
else
@container.observe "click", (evt) => evt.preventDefault() # gobble click of anchor
destroy: ->
@container.ownerDocument.stopObserving "click", @click_test_action
for event in ['chosen:updated', 'chosen:activate', 'chosen:open', 'chosen:close']
@form_field.stopObserving(event)
@container.stopObserving()
@search_results.stopObserving()
@search_field.stopObserving()
@form_field_label.stopObserving() if @form_field_label?
if @is_multiple
@search_choices.stopObserving()
@container.select(".search-choice-close").each (choice) ->
choice.stopObserving()
else
@selected_item.stopObserving()
if @search_field.tabIndex
@form_field.tabIndex = @search_field.tabIndex
@container.remove()
@form_field.show()
search_field_disabled: ->
@is_disabled = @form_field.disabled || @form_field.up('fieldset')?.disabled || false
if @is_disabled
@container.addClassName 'chosen-disabled'
else
@container.removeClassName 'chosen-disabled'
@search_field.disabled = @is_disabled
unless @is_multiple
@selected_item.stopObserving 'focus', this.activate_field
if @is_disabled
this.close_field()
else unless @is_multiple
@selected_item.observe 'focus', this.activate_field
container_mousedown: (evt) ->
return if @is_disabled
if evt and evt.type in ['mousedown', 'touchstart'] and not @results_showing
evt.preventDefault()
if not (evt? and evt.target.hasClassName "search-choice-close")
if not @active_field
@search_field.clear() if @is_multiple
@container.ownerDocument.observe "click", @click_test_action
this.results_show()
else if not @is_multiple and evt and (evt.target is @selected_item || evt.target.up("a.chosen-single"))
this.results_toggle()
this.activate_field()
container_mouseup: (evt) ->
this.results_reset(evt) if evt.target.nodeName is "ABBR" and not @is_disabled
search_results_mousewheel: (evt) ->
delta = evt.deltaY or -evt.wheelDelta or evt.detail
if delta?
evt.preventDefault()
delta = delta * 40 if evt.type is 'DOMMouseScroll'
@search_results.scrollTop = delta + @search_results.scrollTop
blur_test: (evt) ->
this.close_field() if not @active_field and @container.hasClassName("chosen-container-active")
close_field: ->
@container.ownerDocument.stopObserving "click", @click_test_action
@active_field = false
this.results_hide()
@container.removeClassName "chosen-container-active"
this.clear_backstroke()
this.show_search_field_default()
this.search_field_scale()
@search_field.blur()
activate_field: ->
return if @is_disabled
@container.addClassName "chosen-container-active"
@active_field = true
@search_field.value = this.get_search_field_value()
@search_field.focus()
test_active_click: (evt) ->
if evt.target.up('.chosen-container') is @container
@active_field = true
else
this.close_field()
results_build: ->
@parsing = true
@selected_option_count = null
@results_data = SelectParser.select_to_array @form_field
if @is_multiple
@search_choices.select("li.search-choice").invoke("remove")
else
this.single_set_selected_text()
if @disable_search or @form_field.options.length <= @disable_search_threshold
@search_field.readOnly = true
@container.addClassName "chosen-container-single-nosearch"
else
@search_field.readOnly = false
@container.removeClassName "chosen-container-single-nosearch"
this.update_results_content this.results_option_build({first:true})
this.search_field_disabled()
this.show_search_field_default()
this.search_field_scale()
@parsing = false
result_do_highlight: (el) ->
this.result_clear_highlight()
@result_highlight = el
@result_highlight.addClassName "highlighted"
maxHeight = parseInt @search_results.getStyle('maxHeight'), 10
visible_top = @search_results.scrollTop
visible_bottom = maxHeight + visible_top
high_top = @result_highlight.positionedOffset().top
high_bottom = high_top + @result_highlight.getHeight()
if high_bottom >= visible_bottom
@search_results.scrollTop = if (high_bottom - maxHeight) > 0 then (high_bottom - maxHeight) else 0
else if high_top < visible_top
@search_results.scrollTop = high_top
result_clear_highlight: ->
@result_highlight.removeClassName('highlighted') if @result_highlight
@result_highlight = null
results_show: ->
if @is_multiple and @max_selected_options <= this.choices_count()
@form_field.fire("chosen:maxselected", {chosen: this})
return false
@container.addClassName "chosen-with-drop"
@results_showing = true
@search_field.focus()
@search_field.value = this.get_search_field_value()
this.winnow_results()
@form_field.fire("chosen:showing_dropdown", {chosen: this})
update_results_content: (content) ->
@search_results.update content
results_hide: ->
if @results_showing
this.result_clear_highlight()
@container.removeClassName "chosen-with-drop"
@form_field.fire("chosen:hiding_dropdown", {chosen: this})
@results_showing = false
set_tab_index: (el) ->
if @form_field.tabIndex
ti = @form_field.tabIndex
@form_field.tabIndex = -1
@search_field.tabIndex = ti
set_label_behavior: ->
@form_field_label = @form_field.up("label") # first check for a parent label
if not @form_field_label?
@form_field_label = $$("label[for='#{@form_field.id}']").first() #next check for a for=#{id}
if @form_field_label?
@form_field_label.observe "click", this.label_click_handler
show_search_field_default: ->
if @is_multiple and this.choices_count() < 1 and not @active_field
@search_field.value = @default_text
@search_field.addClassName "default"
else
@search_field.value = ""
@search_field.removeClassName "default"
search_results_mouseup: (evt) ->
target = if evt.target.hasClassName("active-result") then evt.target else evt.target.up(".active-result")
if target
@result_highlight = target
this.result_select(evt)
@search_field.focus()
search_results_mouseover: (evt) ->
target = if evt.target.hasClassName("active-result") then evt.target else evt.target.up(".active-result")
this.result_do_highlight( target ) if target
search_results_mouseout: (evt) ->
this.result_clear_highlight() if evt.target.hasClassName('active-result') or evt.target.up('.active-result')
choice_build: (item) ->
choice = new Element('li', { class: "search-choice" }).update("<span>#{this.choice_label(item)}</span>")
if item.disabled
choice.addClassName 'search-choice-disabled'
else
close_link = new Element('a', { href: '#', class: 'search-choice-close', rel: item.array_index })
close_link.observe "click", (evt) => this.choice_destroy_link_click(evt)
choice.insert close_link
@search_container.insert { before: choice }
choice_destroy_link_click: (evt) ->
evt.preventDefault()
evt.stopPropagation()
this.choice_destroy evt.target unless @is_disabled
choice_destroy: (link) ->
if this.result_deselect link.readAttribute("rel")
if @active_field
@search_field.focus()
else
this.show_search_field_default()
this.results_hide() if @is_multiple and this.choices_count() > 0 and this.get_search_field_value().length < 1
link.up('li').remove()
this.search_field_scale()
results_reset: ->
this.reset_single_select_options()
@form_field.options[0].selected = true
this.single_set_selected_text()
this.show_search_field_default()
this.results_reset_cleanup()
this.trigger_form_field_change()
this.results_hide() if @active_field
results_reset_cleanup: ->
@current_selectedIndex = @form_field.selectedIndex
deselect_trigger = @selected_item.down("abbr")
deselect_trigger.remove() if(deselect_trigger)
result_select: (evt) ->
if @result_highlight
high = @result_highlight
this.result_clear_highlight()
if @is_multiple and @max_selected_options <= this.choices_count()
@form_field.fire("chosen:maxselected", {chosen: this})
return false
if @is_multiple
high.removeClassName("active-result")
else
this.reset_single_select_options()
high.addClassName("result-selected")
item = @results_data[ high.getAttribute("data-option-array-index") ]
item.selected = true
@form_field.options[item.options_index].selected = true
@selected_option_count = null
if @is_multiple
this.choice_build item
else
this.single_set_selected_text(this.choice_label(item))
if @is_multiple && (!@hide_results_on_select || (evt.metaKey or evt.ctrlKey))
if evt.metaKey or evt.ctrlKey
this.winnow_results(skip_highlight: true)
else
@search_field.value = ""
this.winnow_results()
else
this.results_hide()
this.show_search_field_default()
this.trigger_form_field_change() if @is_multiple || @form_field.selectedIndex != @current_selectedIndex
@current_selectedIndex = @form_field.selectedIndex
evt.preventDefault()
this.search_field_scale()
single_set_selected_text: (text=@default_text) ->
if text is @default_text
@selected_item.addClassName("chosen-default")
else
this.single_deselect_control_build()
@selected_item.removeClassName("chosen-default")
@selected_item.down("span").update(text)
result_deselect: (pos) ->
result_data = @results_data[pos]
if not @form_field.options[result_data.options_index].disabled
result_data.selected = false
@form_field.options[result_data.options_index].selected = false
@selected_option_count = null
this.result_clear_highlight()
this.winnow_results() if @results_showing
this.trigger_form_field_change()
this.search_field_scale()
return true
else
return false
single_deselect_control_build: ->
return unless @allow_single_deselect
@selected_item.down("span").insert { after: "<abbr class=\"search-choice-close\"></abbr>" } unless @selected_item.down("abbr")
@selected_item.addClassName("chosen-single-with-deselect")
get_search_field_value: ->
@search_field.value
get_search_text: ->
this.get_search_field_value().strip()
escape_html: (text) ->
text.escapeHTML()
winnow_results_set_highlight: ->
if not @is_multiple
do_high = @search_results.down(".result-selected.active-result")
if not do_high?
do_high = @search_results.down(".active-result")
this.result_do_highlight do_high if do_high?
no_results: (terms) ->
@search_results.insert this.get_no_results_html(terms)
@form_field.fire("chosen:no_results", {chosen: this})
no_results_clear: ->
nr = null
nr.remove() while nr = @search_results.down(".no-results")
keydown_arrow: ->
if @results_showing and @result_highlight
next_sib = @result_highlight.next('.active-result')
this.result_do_highlight next_sib if next_sib
else
this.results_show()
keyup_arrow: ->
if not @results_showing and not @is_multiple
this.results_show()
else if @result_highlight
sibs = @result_highlight.previousSiblings()
actives = @search_results.select("li.active-result")
prevs = sibs.intersect(actives)
if prevs.length
this.result_do_highlight prevs.first()
else
this.results_hide() if this.choices_count() > 0
this.result_clear_highlight()
keydown_backstroke: ->
if @pending_backstroke
this.choice_destroy @pending_backstroke.down("a")
this.clear_backstroke()
else
next_available_destroy = @search_container.siblings().last()
if next_available_destroy and next_available_destroy.hasClassName("search-choice") and not next_available_destroy.hasClassName("search-choice-disabled")
@pending_backstroke = next_available_destroy
@pending_backstroke.addClassName("search-choice-focus") if @pending_backstroke
if @single_backstroke_delete
@keydown_backstroke()
else
@pending_backstroke.addClassName("search-choice-focus")
clear_backstroke: ->
@pending_backstroke.removeClassName("search-choice-focus") if @pending_backstroke
@pending_backstroke = null
search_field_scale: ->
return unless @is_multiple
style_block =
position: 'absolute'
left: '-1000px'
top: '-1000px'
display: 'none'
whiteSpace: 'pre'
styles = ['fontSize', 'fontStyle', 'fontWeight', 'fontFamily', 'lineHeight', 'textTransform', 'letterSpacing']
for style in styles
style_block[style] = @search_field.getStyle(style)
div = new Element('div').update(this.escape_html(this.get_search_field_value()))
# CSP without 'unsafe-inline' doesn't allow setting the style attribute directly
div.setStyle(style_block)
document.body.appendChild(div)
width = div.measure('width') + 25
div.remove()
if container_width = @container.getWidth()
width = Math.min(container_width - 10, width)
@search_field.setStyle(width: width + 'px')
trigger_form_field_change: ->
triggerHtmlEvent @form_field, 'input'
triggerHtmlEvent @form_field, 'change'
triggerHtmlEvent = (element, eventType) ->
if element.dispatchEvent # Modern way:
try
evt = new Event(eventType, bubbles: true, cancelable: true)
catch
evt = document.createEvent('HTMLEvents')
evt.initEvent(eventType, true, true);
element.dispatchEvent(evt)
else # Old IE:
element.fireEvent("on#{eventType}", document.createEventObject());
================================================
FILE: coffee/lib/abstract-chosen.coffee
================================================
class AbstractChosen
constructor: (@form_field, @options={}) ->
return unless AbstractChosen.browser_is_supported()
@is_multiple = @form_field.multiple
this.set_default_text()
this.set_default_values()
this.setup()
this.set_up_html()
this.register_observers()
# instantiation done, fire ready
this.on_ready()
set_default_values: ->
@click_test_action = (evt) => this.test_active_click(evt)
@activate_action = (evt) => this.activate_field(evt)
@active_field = false
@mouse_on_container = false
@results_showing = false
@result_highlighted = null
@is_rtl = @options.rtl || /\bchosen-rtl\b/.test(@form_field.className)
@allow_single_deselect = if @options.allow_single_deselect? and @form_field.options[0]? and @form_field.options[0].text is "" then @options.allow_single_deselect else false
@disable_search_threshold = @options.disable_search_threshold || 0
@disable_search = @options.disable_search || false
@enable_split_word_search = if @options.enable_split_word_search? then @options.enable_split_word_search else true
@group_search = if @options.group_search? then @options.group_search else true
@search_contains = @options.search_contains || false
@single_backstroke_delete = if @options.single_backstroke_delete? then @options.single_backstroke_delete else true
@max_selected_options = @options.max_selected_options || Infinity
@inherit_select_classes = @options.inherit_select_classes || false
@display_selected_options = if @options.display_selected_options? then @options.display_selected_options else true
@display_disabled_options = if @options.display_disabled_options? then @options.display_disabled_options else true
@include_group_label_in_selected = @options.include_group_label_in_selected || false
@max_shown_results = @options.max_shown_results || Number.POSITIVE_INFINITY
@case_sensitive_search = @options.case_sensitive_search || false
@hide_results_on_select = if @options.hide_results_on_select? then @options.hide_results_on_select else true
set_default_text: ->
if @form_field.getAttribute("data-placeholder")
@default_text = @form_field.getAttribute("data-placeholder")
else if @is_multiple
@default_text = @options.placeholder_text_multiple || @options.placeholder_text || AbstractChosen.default_multiple_text
else
@default_text = @options.placeholder_text_single || @options.placeholder_text || AbstractChosen.default_single_text
@default_text = this.escape_html(@default_text)
@results_none_found = @form_field.getAttribute("data-no_results_text") || @options.no_results_text || AbstractChosen.default_no_result_text
choice_label: (item) ->
if @include_group_label_in_selected and item.group_label?
"<b class='group-name'>#{this.escape_html(item.group_label)}</b>#{item.html}"
else
item.html
mouse_enter: -> @mouse_on_container = true
mouse_leave: -> @mouse_on_container = false
input_focus: (evt) ->
if @is_multiple
setTimeout (=> this.container_mousedown()), 50 unless @active_field
else
@activate_field() unless @active_field
input_blur: (evt) ->
if not @mouse_on_container
@active_field = false
setTimeout (=> this.blur_test()), 100
label_click_handler: (evt) =>
if @is_multiple
this.container_mousedown(evt)
else
this.activate_field()
results_option_build: (options) ->
content = ''
shown_results = 0
for data in @results_data
data_content = ''
if data.group
data_content = this.result_add_group data
else
data_content = this.result_add_option data
if data_content != ''
shown_results++
content += data_content
# this select logic pins on an awkward flag
# we can make it better
if options?.first
if data.selected and @is_multiple
this.choice_build data
else if data.selected and not @is_multiple
this.single_set_selected_text(this.choice_label(data))
if shown_results >= @max_shown_results
break
content
result_add_option: (option) ->
return '' unless option.search_match
return '' unless this.include_option_in_results(option)
classes = []
classes.push "active-result" if !option.disabled and !(option.selected and @is_multiple)
classes.push "disabled-result" if option.disabled and !(option.selected and @is_multiple)
classes.push "result-selected" if option.selected
classes.push "group-option" if option.group_array_index?
classes.push option.classes if option.classes != ""
option_el = document.createElement("li")
option_el.className = classes.join(" ")
option_el.style.cssText = option.style if option.style
option_el.setAttribute("data-option-array-index", option.array_index)
option_el.innerHTML = option.highlighted_html or option.html
option_el.title = option.title if option.title
this.outerHTML(option_el)
result_add_group: (group) ->
return '' unless group.search_match || group.group_match
return '' unless group.active_options > 0
classes = []
classes.push "group-result"
classes.push group.classes if group.classes
group_el = document.createElement("li")
group_el.className = classes.join(" ")
group_el.innerHTML = group.highlighted_html or this.escape_html(group.label)
group_el.title = group.title if group.title
this.outerHTML(group_el)
results_update_field: ->
this.set_default_text()
this.results_reset_cleanup() if not @is_multiple
this.result_clear_highlight()
this.results_build()
this.winnow_results() if @results_showing
reset_single_select_options: () ->
for result in @results_data
result.selected = false if result.selected
results_toggle: ->
if @results_showing
this.results_hide()
else
this.results_show()
results_search: (evt) ->
if @results_showing
this.winnow_results()
else
this.results_show()
winnow_results: (options) ->
this.no_results_clear()
results = 0
query = this.get_search_text()
escapedQuery = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
regex = this.get_search_regex(escapedQuery)
for option in @results_data
option.search_match = false
results_group = null
search_match = null
option.highlighted_html = ''
if this.include_option_in_results(option)
if option.group
option.group_match = false
option.active_options = 0
if option.group_array_index? and @results_data[option.group_array_index]
results_group = @results_data[option.group_array_index]
results += 1 if results_group.active_options is 0 and results_group.search_match
results_group.active_options += 1
text = if option.group then option.label else option.text
unless option.group and not @group_search
search_match = this.search_string_match(text, regex)
option.search_match = search_match?
results += 1 if option.search_match and not option.group
if option.search_match
if query.length
startpos = search_match.index
prefix = text.slice(0, startpos)
fix = text.slice(startpos, startpos + query.length)
suffix = text.slice(startpos + query.length)
option.highlighted_html = "#{this.escape_html(prefix)}<em>#{this.escape_html(fix)}</em>#{this.escape_html(suffix)}"
results_group.group_match = true if results_group?
else if option.group_array_index? and @results_data[option.group_array_index].search_match
option.search_match = true
this.result_clear_highlight()
if results < 1 and query.length
this.update_results_content ""
this.no_results query
else
this.update_results_content this.results_option_build()
this.winnow_results_set_highlight() unless options?.skip_highlight
get_search_regex: (escaped_search_string) ->
regex_string = if @search_contains then escaped_search_string else "(^|\\s|\\b)#{escaped_search_string}[^\\s]*"
regex_string = "^#{regex_string}" unless @enable_split_word_search or @search_contains
regex_flag = if @case_sensitive_search then "" else "i"
new RegExp(regex_string, regex_flag)
search_string_match: (search_string, regex) ->
match = regex.exec(search_string)
match.index += 1 if !@search_contains && match?[1] # make up for lack of lookbehind operator in regex
match
choices_count: ->
return @selected_option_count if @selected_option_count?
@selected_option_count = 0
for option in @form_field.options
@selected_option_count += 1 if option.selected
return @selected_option_count
choices_click: (evt) ->
evt.preventDefault()
this.activate_field()
this.results_show() unless @results_showing or @is_disabled
keydown_checker: (evt) ->
stroke = evt.which ? evt.keyCode
this.search_field_scale()
this.clear_backstroke() if stroke != 8 and @pending_backstroke
switch stroke
when 8 # backspace
@backstroke_length = this.get_search_field_value().length
break
when 9 # tab
this.result_select(evt) if @results_showing and not @is_multiple
@mouse_on_container = false
break
when 13 # enter
evt.preventDefault() if @results_showing
break
when 27 # escape
evt.preventDefault() if @results_showing
break
when 32 # space
evt.preventDefault() if @disable_search
break
when 38 # up arrow
evt.preventDefault()
this.keyup_arrow()
break
when 40 # down arrow
evt.preventDefault()
this.keydown_arrow()
break
keyup_checker: (evt) ->
stroke = evt.which ? evt.keyCode
this.search_field_scale()
switch stroke
when 8 # backspace
if @is_multiple and @backstroke_length < 1 and this.choices_count() > 0
this.keydown_backstroke()
else if not @pending_backstroke
this.result_clear_highlight()
this.results_search()
break
when 13 # enter
evt.preventDefault()
this.result_select(evt) if this.results_showing
break
when 27 # escape
this.results_hide() if @results_showing
break
when 9, 16, 17, 18, 38, 40, 91
# don't do anything on these keys
else
this.results_search()
break
clipboard_event_checker: (evt) ->
return if @is_disabled
setTimeout (=> this.results_search()), 50
container_width: ->
return if @options.width? then @options.width else "#{@form_field.offsetWidth}px"
include_option_in_results: (option) ->
return false if @is_multiple and (not @display_selected_options and option.selected)
return false if not @display_disabled_options and option.disabled
return false if option.empty
return true
search_results_touchstart: (evt) ->
@touch_started = true
this.search_results_mouseover(evt)
search_results_touchmove: (evt) ->
@touch_started = false
this.search_results_mouseout(evt)
search_results_touchend: (evt) ->
this.search_results_mouseup(evt) if @touch_started
outerHTML: (element) ->
return element.outerHTML if element.outerHTML
tmp = document.createElement("div")
tmp.appendChild(element)
tmp.innerHTML
get_single_html: ->
"""
<a class="chosen-single chosen-default">
<span>#{@default_text}</span>
<div><b></b></div>
</a>
<div class="chosen-drop">
<div class="chosen-search">
<input class="chosen-search-input" type="text" autocomplete="off" />
</div>
<ul class="chosen-results"></ul>
</div>
"""
get_multi_html: ->
"""
<ul class="chosen-choices">
<li class="search-field">
<input class="chosen-search-input" type="text" autocomplete="off" value="#{@default_text}" />
</li>
</ul>
<div class="chosen-drop">
<ul class="chosen-results"></ul>
</div>
"""
get_no_results_html: (terms) ->
"""
<li class="no-results">
#{@results_none_found} <span>#{this.escape_html(terms)}</span>
</li>
"""
# class methods and variables ============================================================
@browser_is_supported: ->
if "Microsoft Internet Explorer" is window.navigator.appName
return document.documentMode >= 8
if /iP(od|hone)/i.test(window.navigator.userAgent) or
/IEMobile/i.test(window.navigator.userAgent) or
/Windows Phone/i.test(window.navigator.userAgent) or
/BlackBerry/i.test(window.navigator.userAgent) or
/BB10/i.test(window.navigator.userAgent) or
/Android.*Mobile/i.test(window.navigator.userAgent)
return false
return true
@default_multiple_text: "Select Some Options"
@default_single_text: "Select an Option"
@default_no_result_text: "No results match"
================================================
FILE: coffee/lib/select-parser.coffee
================================================
class SelectParser
constructor: ->
@options_index = 0
@parsed = []
add_node: (child) ->
if child.nodeName.toUpperCase() is "OPTGROUP"
this.add_group child
else
this.add_option child
add_group: (group) ->
group_position = @parsed.length
@parsed.push
array_index: group_position
group: true
label: group.label
title: group.title if group.title
children: 0
disabled: group.disabled,
classes: group.className
this.add_option( option, group_position, group.disabled ) for option in group.childNodes
add_option: (option, group_position, group_disabled) ->
if option.nodeName.toUpperCase() is "OPTION"
if option.text != ""
if group_position?
@parsed[group_position].children += 1
@parsed.push
array_index: @parsed.length
options_index: @options_index
value: option.value
text: option.text
html: option.innerHTML
title: option.title if option.title
selected: option.selected
disabled: if group_disabled is true then group_disabled else option.disabled
group_array_index: group_position
group_label: if group_position? then @parsed[group_position].label else null
classes: option.className
style: option.style.cssText
else
@parsed.push
array_index: @parsed.length
options_index: @options_index
empty: true
@options_index += 1
SelectParser.select_to_array = (select) ->
parser = new SelectParser()
parser.add_node( child ) for child in select.childNodes
parser.parsed
================================================
FILE: composer.json
================================================
{
"name": "harvesthq/chosen",
"description": "Chosen is a JavaScript plugin that makes select boxes user-friendly. It is currently available in both jQuery and Prototype flavors.",
"authors": [
{
"name": "Patrick Filler",
"homepage": "https://github.com/pfiller"
},
{
"name": "Christophe Coevoet",
"homepage": "https://github.com/stof"
},
{
"name": "Ken Earley",
"homepage": "https://github.com/kenearley"
},
{
"name": "Koen Punt",
"homepage": "https://github.com/koenpunt"
}
],
"keywords": [
"select",
"multiselect",
"dropdown",
"form",
"input",
"ui"
],
"type": "library",
"license": "MIT",
"minimum-stability": "stable",
"homepage": "https://harvesthq.github.io/chosen/",
"require": {
}
}
================================================
FILE: contributing.md
================================================
# Contributing to this project
Please take a moment to review this document in order to make the contribution
process easy and effective for everyone involved.
Following these guidelines will help us get back to you more quickly, and will
show that you care about making Chosen better just like we do. In return, we'll
do our best to respond to your issue or pull request as soon as possible with
the same respect.
_**Please Note:** These guidelines are adapted from [@necolas](https://github.com/necolas)'s
[issue-guidelines](https://github.com/necolas/issue-guidelines) and serve as
an excellent starting point for contributing to any open source project._
## Using the issue tracker [](https://www.codetriage.com/harvesthq/chosen)
The [issue tracker](https://github.com/harvesthq/chosen/issues) is the
preferred channel for [bug reports](#bugs), [features requests](#features)
and [submitting pull requests](#pull-requests), but please respect the
following restrictions:
* Support issues or usage question that are not bugs should be posted on
[Stack Overflow, using the `chosen.js`](http://stackoverflow.com/questions/tagged/chosen.js) tag
(related tags: [`jquery-chosen`](http://stackoverflow.com/questions/tagged/jquery-chosen),
[`prototype-chosen`](http://stackoverflow.com/questions/tagged/prototype-chosen)).
* Please **do not** derail or troll issues. Keep the discussion on topic and
respect the opinions of others.
You can triage issues which may include reproducing bug reports or asking for vital information, such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to chosen on CodeTriage](https://www.codetriage.com/harvesthq/chosen).
<a name="bugs"></a>
## Bug reports
A bug is a _demonstrable problem_ that is caused by the code in the repository.
Good bug reports are extremely helpful — thank you!
Guidelines for bug reports:
1. **Use the [GitHub issue search](https://github.com/harvesthq/chosen/search?type=Issues)** — check if the issue has already been
reported.
2. **Check if the bug has already been fixed** — try to reproduce it using the
repository's latest `master` changes.
3. **Isolate the problem** — ideally create a [reduced test
case](https://css-tricks.com/reduced-test-cases/) and a live example
(perhaps a [fiddle](http://jsfiddle.net)).
A good bug report shouldn't leave others needing to contact you for more
information. Please try to be as detailed as possible in your report. What is
your environment? What steps will reproduce the issue? What browser(s) and OS
experience the problem? What outcome did you expect, and how did it differ from
what you actually saw? All these details will help people to fix any potential
bugs.
Example:
> Short and descriptive example bug report title
>
> A summary of the issue and the browser/OS environment in which it occurs. If
> suitable, include the steps required to reproduce the bug.
>
> 1. This is the first step
> 2. This is the second step
> 3. Further steps, etc.
>
> `<url>` - a link to the reduced test case
>
> Any other information you want to share that is relevant to the issue being
> reported. This might include the lines of code that you have identified as
> causing the bug, and potential solutions (and your opinions on their
> merits).
**Note:** In an effort to keep open issues to a manageable number, we will close any issues
that do not provide enough information for us to be able to work on a solution.
You will be encouraged to provide the necessary details, after which we will reopen the issue.
<a name="features"></a>
## Feature requests
Feature requests are welcome. But take a moment to find out whether your idea
fits with the scope and aims of the project. It's up to *you* to make a strong
case to convince the project's developers of the merits of this feature. Please
provide as much detail and context as possible.
Building something great means choosing features carefully especially because it
is much, much easier to add features than it is to take them away. Additions
to Chosen will be evaluated on a combination of scope (how well it fits into the
project), maintenance burden and general usefulness.
Creating something great often means saying no to seemingly good ideas. Don't
dispair if your feature request isn't accepted, take action! Fork the
repository, build your idea and share it with others. We released Chosen under
the MIT License for this purpose precisely. Open source works best when smart
and dedicated people riff off of each others' ideas to make even greater things.
<a name="pull-requests"></a>
## Pull requests
Good pull requests — patches, improvements, new features — are a fantastic help.
They should remain focused in scope and avoid containing unrelated commits.
**Please ask first** before embarking on any significant pull request (e.g.
implementing features, refactoring code, porting to a different language),
otherwise you risk spending a lot of time working on something that the
project's developers might not want to merge into the project. You can solicit
feedback and opinions in an open feature request thread or create a new one.
Please use the [git flow for pull requests](#git-flow) and follow Chosen's
[code conventions](#code-conventions) before submitting your work. Adhering to
these guidelines is the best way to get your work included in Chosen.
<a name="git-flow"></a>
#### Git Flow for pull requests
1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork,
and configure the remotes:
```bash
# Clone your fork of the repo into the current directory
git clone git@github.com:<YOUR_USERNAME>/chosen.git
# Navigate to the newly cloned directory
cd chosen
# Assign the original repo to a remote called "upstream"
git remote add upstream https://github.com/harvesthq/chosen
```
2. If you cloned a while ago, get the latest changes from upstream:
```bash
git checkout master
git pull upstream master
```
3. Create a new topic branch (off the main project development branch) to
contain your feature, change, or fix:
```bash
git checkout -b <topic-branch-name>
```
4. Commit your changes in logical chunks. Please adhere to these [git commit
message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
or your code is unlikely be merged into the main project. Use Git's
[interactive rebase](https://help.github.com/articles/interactive-rebase)
feature to tidy up your commits before making them public.
5. Locally merge (or rebase) the upstream development branch into your topic branch:
```bash
git pull [--rebase] upstream master
```
6. Push your topic branch up to your fork:
```bash
git push origin <topic-branch-name>
```
7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
with a clear title and description.
**IMPORTANT**: By submitting a patch, you agree to allow the project owner to
license your work under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
<a name="code-conventions"></a>
#### Chosen Code Conventions
1. Make all changes in CoffeeScript files, **not** JavaScript files.
2. Use [Grunt](#grunt) to build the JavaScript files.
3. For feature changes, update both jQuery *and* Prototype versions
4. Don't manually update the version number in `package.json`. This is done using a Grunt task on deployment.
<a name="grunt"></a>
#### Grunt tasks: Running Tests and building Chosen
To install all development dependencies, in the project's root directory, run
npm install
Once you're configured, `grunt` tasks are available:
grunt test # run the tests in spec/
grunt build # build Chosen from source
grunt watch # watch coffee/ for changes and build Chosen
If you're interested, you can find the task in [Gruntfile.coffee](https://github.com/harvesthq/chosen/blob/master/Gruntfile.coffee).
# Release a new version of Chosen
This documentation is for Chosen maintainers. You must have write permissions for this repository to cut a release.
1. Bump the version number in the source but _do not push it yet_. [Example commit](https://github.com/harvesthq/chosen/commit/be0a298f528ec59ce97889eaeeeb47a2dca9ca79).
2. Create a tag for that commit: `git tag -m "<tagname>" <tagname> <SHA>`
- `<tagname>` formatted as `vX.Y.Z`
- `<SHA>` is the SHA of the commit from step 1
3. Push the commit _and_ the tag: `git push origin --follow-tags`
4. Draft a new release [on the releases page](https://github.com/harvesthq/chosen/releases).
- Title formatted as "Version X.Y.Z"
- Tagged as `<tagname>` from step 2
- Body of the release should contain changes included in the release. Ideally, there will already be a draft release present with a running log from contributions merged since the last release.
5. Run `grunt prep-release`
6. Attach the generated `chosen_vX.Y.Z.zip` file (in the Chosen root directory) to the draft release from step 4.
7. Publish the release.
8. Run `grunt publish-release` to publish to the `gh-pages` branch.
9. Verify https://harvesthq.github.io/chosen/ is showing the new version.
_Note:_ the release repository [harvesthq/chosen-package](https://github.com/harvesthq/chosen-package) is automatically built by [Travis CI](https://travis-ci.org/harvesthq/chosen). No explicit action is necessary.
================================================
FILE: package-travis.yml
================================================
sudo: false
language: node_js
node_js:
- "node"
deploy:
provider: npm
email: chosenjs@getharvest.com
api_key:
# This key is for automatically publishing releases to NPM,
# but it is encrypted for publishing publicly like this using Travis.
# More information about how this token is generated and encrypted here:
# https://docs.travis-ci.com/user/deployment/npm#NPM-auth-token
#
# Be sure to use the _package_ repo when encrypting since that is what
# publishes to NPM:
# travis encrypt THE-API-KEY -r "harvesthq/chosen-package"
secure: "LymcaqX4oXPmaIxaTYeMziNsr+FBi4WVZCc5XqCEeZxC/spRousJDX+oEf/gnmWtN5+sOEtct/WKALXye9MiOVkrRG87YEGXGaG5EQVm4+NJbulHpp/TNhJ61Su+NA+52rpj6zgeq15ruIaMr8OQXGkqdq1IRSlShXuaUgKByNY="
on:
tags: true
repo: harvesthq/chosen-package
================================================
FILE: package.json
================================================
{
"author": "harvest",
"name": "chosen",
"version": "1.8.7",
"description": "Chosen is a JavaScript plugin that makes select boxes user-friendly. It is currently available in both jQuery and Prototype flavors.",
"keywords": [
"select",
"multiselect",
"dropdown",
"form",
"input",
"ui"
],
"repository": {
"type": "git",
"url": "https://github.com/harvesthq/chosen.git"
},
"engines": {
"node": ">=4"
},
"scripts": {
"test": "grunt test"
},
"dependencies": {},
"devDependencies": {
"autoprefixer": "^7.1.2",
"coffee-script": ">= 1.6",
"grunt": "~1.0",
"grunt-contrib-coffee": "~1.0",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-concat": "~1.0",
"grunt-contrib-cssmin": "~2.2",
"grunt-contrib-jasmine": "~1.1",
"grunt-contrib-uglify": "~3.0",
"grunt-contrib-watch": "~1.0",
"grunt-gh-pages": "~2.0",
"grunt-postcss": "^0.8.0",
"grunt-sass": "^2.0",
"grunt-zip": "~0.17.1",
"grunt1.0-dom-munger": "~3.4",
"load-grunt-tasks": "^3.5.2",
"simulant": "^0.2.2"
},
"contributors": [
{
"name": "Patrick Filler",
"url": "https://github.com/pfiller"
},
{
"name": "Christophe Coevoet",
"url": "https://github.com/stof"
},
{
"name": "Ken Earley",
"url": "https://github.com/kenearley"
},
{
"name": "Koen Punt",
"url": "https://github.com/koenpunt"
}
],
"license": "MIT",
"homepage": "https://harvesthq.github.io/chosen/",
"bugs": "https://github.com/harvesthq/chosen/issues",
"_extra": {
"title": "Chosen",
"license": {
"type": "MIT",
"url": "https://github.com/harvesthq/chosen/blob/master/LICENSE.md"
},
"links": {
"download": "https://github.com/harvesthq/chosen/releases",
"docs": "https://harvesthq.github.io/chosen/"
},
"main": [
"chosen.jquery.js",
"chosen.css"
],
"files": [
"chosen.jquery.js",
"chosen.jquery.min.js",
"chosen.proto.js",
"chosen.proto.min.js",
"chosen.css",
"chosen.min.css",
"chosen-sprite@2x.png",
"chosen-sprite.png"
]
}
}
================================================
FILE: public/docsupport/init.js
================================================
var config = {
'.chosen-select' : {},
'.chosen-select-deselect' : { allow_single_deselect: true },
'.chosen-select-no-single' : { disable_search_threshold: 10 },
'.chosen-select-no-results': { no_results_text: 'Oops, nothing found!' },
'.chosen-select-rtl' : { rtl: true },
'.chosen-select-width' : { width: '95%' }
}
for (var selector in config) {
$(selector).chosen(config[selector]);
}
================================================
FILE: public/docsupport/init.proto.js
================================================
document.observe('dom:loaded', function(evt) {
var config = {
'.chosen-select' : {},
'.chosen-select-deselect' : { allow_single_deselect: true },
'.chosen-select-no-single' : { disable_search_threshold: 10 },
'.chosen-select-no-results': { no_results_text: 'Oops, nothing found!' },
'.chosen-select-rtl' : { rtl: true },
'.chosen-select-width' : { width: '95%' }
}
for (var selector in config) {
$$(selector).each(function(element) {
new Chosen(element, config[selector]);
});
}
});
================================================
FILE: public/docsupport/prism.css
================================================
/**
* okaidia theme for JavaScript, CSS and HTML
* Loosely based on Monokai textmate theme by http://www.monokai.nl/
* @author ocodia
*/
code[class*="language-"],
pre[class*="language-"] {
color: #f8f8f2;
text-shadow: 0 1px rgba(0,0,0,0.3);
font-family: Consolas, Monaco, 'Andale Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
border-radius: 0.3em;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #272822;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #f8f8f2;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag {
color: #f92672;
}
.token.boolean,
.token.number{
color: #ae81ff;
}
.token.selector,
.token.attr-name,
.token.string {
color: #a6e22e;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #f8f8f2;
}
.token.atrule,
.token.attr-value
{
color: #e6db74;
}
.token.keyword{
color: #66d9ef;
}
.token.regex,
.token.important {
color: #fd971f;
}
.token.important {
font-weight: bold;
}
.token.entity {
cursor: help;
}
================================================
FILE: public/docsupport/prism.js
================================================
/**
* Prism: Lightweight, robust, elegant syntax highlighting
* MIT license http://www.opensource.org/licenses/mit-license.php/
* @author Lea Verou http://lea.verou.me
*/(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var r={};for(var i in e)e.hasOwnProperty(i)&&(r[i]=t.util.clone(e[i]));return r;case"Array":return e.slice()}return e}},languages:{extend:function(e,n){var r=t.util.clone(t.languages[e]);for(var i in n)r[i]=n[i];return r},insertBefore:function(e,n,r,i){i=i||t.languages;var s=i[e],o={};for(var u in s)if(s.hasOwnProperty(u)){if(u==n)for(var a in r)r.hasOwnProperty(a)&&(o[a]=r[a]);o[u]=s[u]}return i[e]=o},DFS:function(e,n){for(var r in e){n.call(e,r,e[r]);t.util.type(e)==="Object"&&t.languages.DFS(e[r],n)}}},highlightAll:function(e,n){var r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,s;s=r[i++];)t.highlightElement(s,e===!0,n)},highlightElement:function(r,i,s){var o,u,a=r;while(a&&!e.test(a.className))a=a.parentNode;if(a){o=(a.className.match(e)||[,""])[1];u=t.languages[o]}if(!u)return;r.className=r.className.replace(e,"").replace(/\s+/g," ")+" language-"+o;a=r.parentNode;/pre/i.test(a.nodeName)&&(a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+o);var f=r.textContent;if(!f)return;f=f.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ");var l={element:r,language:o,grammar:u,code:f};t.hooks.run("before-highlight",l);if(i&&self.Worker){var c=new Worker(t.filename);c.onmessage=function(e){l.highlightedCode=n.stringify(JSON.parse(e.data),o);t.hooks.run("before-insert",l);l.element.innerHTML=l.highlightedCode;s&&s.call(l.element);t.hooks.run("after-highlight",l)};c.postMessage(JSON.stringify({language:l.language,code:l.code}))}else{l.highlightedCode=t.highlight(l.code,l.grammar,l.language);t.hooks.run("before-insert",l);l.element.innerHTML=l.highlightedCode;s&&s.call(r);t.hooks.run("after-highlight",l)}},highlight:function(e,r,i){return n.stringify(t.tokenize(e,r),i)},tokenize:function(e,n,r){var i=t.Token,s=[e],o=n.rest;if(o){for(var u in o)n[u]=o[u];delete n.rest}e:for(var u in n){if(!n.hasOwnProperty(u)||!n[u])continue;var a=n[u],f=a.inside,l=!!a.lookbehind,c=0;a=a.pattern||a;for(var h=0;h<s.length;h++){var p=s[h];if(s.length>e.length)break e;if(p instanceof i)continue;a.lastIndex=0;var d=a.exec(p);if(d){l&&(c=d[1].length);var v=d.index-1+c,d=d[0].slice(c),m=d.length,g=v+m,y=p.slice(0,v+1),b=p.slice(g+1),w=[h,1];y&&w.push(y);var E=new i(u,f?t.tokenize(d,f):d);w.push(E);b&&w.push(b);Array.prototype.splice.apply(s,w)}}}return s},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e,r,i){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]")return e.map(function(t){return n.stringify(t,r,e)}).join("");var s={type:e.type,content:n.stringify(e.content,r,i),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:i};s.type=="comment"&&(s.attributes.spellcheck="true");t.hooks.run("wrap",s);var o="";for(var u in s.attributes)o+=u+'="'+(s.attributes[u]||"")+'"';return"<"+s.tag+' class="'+s.classes.join(" ")+'" '+o+">"+s.content+"</"+s.tag+">"};if(!self.document){self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,i=n.code;self.postMessage(JSON.stringify(t.tokenize(i,t.languages[r])));self.close()},!1);return}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}})();;
Prism.languages.markup={comment:/<!--[\w\W]*?-->/g,prolog:/<\?.+?\?>/,doctype:/<!DOCTYPE.+?>/,cdata:/<!\[CDATA\[[\w\W]*?]]>/i,tag:{pattern:/<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|\w+))?\s*)*\/?>/gi,inside:{tag:{pattern:/^<\/?[\w:-]+/i,inside:{punctuation:/^<\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,inside:{punctuation:/=|>|"/g}},punctuation:/\/?>/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&#?[\da-z]{1,8};/gi};Prism.hooks.add("wrap",function(e){e.type==="entity"&&(e.attributes.title=e.content.replace(/&/,"&"))});;
Prism.languages.css={comment:/\/\*[\w\W]*?\*\//g,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*{))/gi,inside:{punctuation:/[;:]/g}},url:/url\((["']?).*?\1\)/gi,selector:/[^\{\}\s][^\{\};]*(?=\s*\{)/g,property:/(\b|\B)[\w-]+(?=\s*:)/ig,string:/("|')(\\?.)*?\1/g,important:/\B!important\b/gi,ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\};:]/g};Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{style:{pattern:/(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/ig,inside:{tag:{pattern:/(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}});;
Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/ig,inside:{punctuation:/\(/}}, number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};;
Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|catch|finally|null|break|continue)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g});Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}});Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig,inside:{tag:{pattern:/(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});;
================================================
FILE: public/docsupport/prototype-1.7.0.0.js
================================================
/* Prototype JavaScript framework, version 1.7
* (c) 2005-2010 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://www.prototypejs.org/
*
*--------------------------------------------------------------------------*/
var Prototype = {
Version: '1.7',
Browser: (function(){
var ua = navigator.userAgent;
var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
return {
IE: !!window.attachEvent && !isOpera,
Opera: isOpera,
WebKit: ua.indexOf('AppleWebKit/') > -1,
Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
MobileSafari: /Apple.*Mobile/.test(ua)
}
})(),
BrowserFeatures: {
XPath: !!document.evaluate,
SelectorsAPI: !!document.querySelector,
ElementExtensions: (function() {
var constructor = window.Element || window.HTMLElement;
return !!(constructor && constructor.prototype);
})(),
SpecificElementExtensions: (function() {
if (typeof window.HTMLDivElement !== 'undefined')
return true;
var div = document.createElement('div'),
form = document.createElement('form'),
isSupported = false;
if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
isSupported = true;
}
div = form = null;
return isSupported;
})()
},
ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
emptyFunction: function() { },
K: function(x) { return x }
};
if (Prototype.Browser.MobileSafari)
Prototype.BrowserFeatures.SpecificElementExtensions = false;
var Abstract = { };
var Try = {
these: function() {
var returnValue;
for (var i = 0, length = arguments.length; i < length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
} catch (e) { }
}
return returnValue;
}
};
/* Based on Alex Arnell's inheritance implementation. */
var Class = (function() {
var IS_DONTENUM_BUGGY = (function(){
for (var p in { toString: 1 }) {
if (p === 'toString') return false;
}
return true;
})();
function subclass() {};
function create() {
var parent = null, properties = $A(arguments);
if (Object.isFunction(properties[0]))
parent = properties.shift();
function klass() {
this.initialize.apply(this, arguments);
}
Object.extend(klass, Class.Methods);
klass.superclass = parent;
klass.subclasses = [];
if (parent) {
subclass.prototype = parent.prototype;
klass.prototype = new subclass;
parent.subclasses.push(klass);
}
for (var i = 0, length = properties.length; i < length; i++)
klass.addMethods(properties[i]);
if (!klass.prototype.initialize)
klass.prototype.initialize = Prototype.emptyFunction;
klass.prototype.constructor = klass;
return klass;
}
function addMethods(source) {
var ancestor = this.superclass && this.superclass.prototype,
properties = Object.keys(source);
if (IS_DONTENUM_BUGGY) {
if (source.toString != Object.prototype.toString)
properties.push("toString");
if (source.valueOf != Object.prototype.valueOf)
properties.push("valueOf");
}
for (var i = 0, length = properties.length; i < length; i++) {
var property = properties[i], value = source[property];
if (ancestor && Object.isFunction(value) &&
value.argumentNames()[0] == "$super") {
var method = value;
value = (function(m) {
return function() { return ancestor[m].apply(this, arguments); };
})(property).wrap(method);
value.valueOf = method.valueOf.bind(method);
value.toString = method.toString.bind(method);
}
this.prototype[property] = value;
}
return this;
}
return {
create: create,
Methods: {
addMethods: addMethods
}
};
})();
(function() {
var _toString = Object.prototype.toString,
NULL_TYPE = 'Null',
UNDEFINED_TYPE = 'Undefined',
BOOLEAN_TYPE = 'Boolean',
NUMBER_TYPE = 'Number',
STRING_TYPE = 'String',
OBJECT_TYPE = 'Object',
FUNCTION_CLASS = '[object Function]',
BOOLEAN_CLASS = '[object Boolean]',
NUMBER_CLASS = '[object Number]',
STRING_CLASS = '[object String]',
ARRAY_CLASS = '[object Array]',
DATE_CLASS = '[object Date]',
NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
typeof JSON.stringify === 'function' &&
JSON.stringify(0) === '0' &&
typeof JSON.stringify(Prototype.K) === 'undefined';
function Type(o) {
switch(o) {
case null: return NULL_TYPE;
case (void 0): return UNDEFINED_TYPE;
}
var type = typeof o;
switch(type) {
case 'boolean': return BOOLEAN_TYPE;
case 'number': return NUMBER_TYPE;
case 'string': return STRING_TYPE;
}
return OBJECT_TYPE;
}
function extend(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
}
function inspect(object) {
try {
if (isUndefined(object)) return 'undefined';
if (object === null) return 'null';
return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
}
}
function toJSON(value) {
return Str('', { '': value }, []);
}
function Str(key, holder, stack) {
var value = holder[key],
type = typeof value;
if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
var _class = _toString.call(value);
switch (_class) {
case NUMBER_CLASS:
case BOOLEAN_CLASS:
case STRING_CLASS:
value = value.valueOf();
}
switch (value) {
case null: return 'null';
case true: return 'true';
case false: return 'false';
}
type = typeof value;
switch (type) {
case 'string':
return value.inspect(true);
case 'number':
return isFinite(value) ? String(value) : 'null';
case 'object':
for (var i = 0, length = stack.length; i < length; i++) {
if (stack[i] === value) { throw new TypeError(); }
}
stack.push(value);
var partial = [];
if (_class === ARRAY_CLASS) {
for (var i = 0, length = value.length; i < length; i++) {
var str = Str(i, value, stack);
partial.push(typeof str === 'undefined' ? 'null' : str);
}
partial = '[' + partial.join(',') + ']';
} else {
var keys = Object.keys(value);
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i], str = Str(key, value, stack);
if (typeof str !== "undefined") {
partial.push(key.inspect(true)+ ':' + str);
}
}
partial = '{' + partial.join(',') + '}';
}
stack.pop();
return partial;
}
}
function stringify(object) {
return JSON.stringify(object);
}
function toQueryString(object) {
return $H(object).toQueryString();
}
function toHTML(object) {
return object && object.toHTML ? object.toHTML() : String.interpret(object);
}
function keys(object) {
if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
var results = [];
for (var property in object) {
if (object.hasOwnProperty(property)) {
results.push(property);
}
}
return results;
}
function values(object) {
var results = [];
for (var property in object)
results.push(object[property]);
return results;
}
function clone(object) {
return extend({ }, object);
}
function isElement(object) {
return !!(object && object.nodeType == 1);
}
function isArray(object) {
return _toString.call(object) === ARRAY_CLASS;
}
var hasNativeIsArray = (typeof Array.isArray == 'function')
&& Array.isArray([]) && !Array.isArray({});
if (hasNativeIsArray) {
isArray = Array.isArray;
}
function isHash(object) {
return object instanceof Hash;
}
function isFunction(object) {
return _toString.call(object) === FUNCTION_CLASS;
}
function isString(object) {
return _toString.call(object) === STRING_CLASS;
}
function isNumber(object) {
return _toString.call(object) === NUMBER_CLASS;
}
function isDate(object) {
return _toString.call(object) === DATE_CLASS;
}
function isUndefined(object) {
return typeof object === "undefined";
}
extend(Object, {
extend: extend,
inspect: inspect,
toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
toQueryString: toQueryString,
toHTML: toHTML,
keys: Object.keys || keys,
values: values,
clone: clone,
isElement: isElement,
isArray: isArray,
isHash: isHash,
isFunction: isFunction,
isString: isString,
isNumber: isNumber,
isDate: isDate,
isUndefined: isUndefined
});
})();
Object.extend(Function.prototype, (function() {
var slice = Array.prototype.slice;
function update(array, args) {
var arrayLength = array.length, length = args.length;
while (length--) array[arrayLength + length] = args[length];
return array;
}
function merge(array, args) {
array = slice.call(array, 0);
return update(array, args);
}
function argumentNames() {
var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
.replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
.replace(/\s+/g, '').split(',');
return names.length == 1 && !names[0] ? [] : names;
}
function bind(context) {
if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
var __method = this, args = slice.call(arguments, 1);
return function() {
var a = merge(args, arguments);
return __method.apply(context, a);
}
}
function bindAsEventListener(context) {
var __method = this, args = slice.call(arguments, 1);
return function(event) {
var a = update([event || window.event], args);
return __method.apply(context, a);
}
}
function curry() {
if (!arguments.length) return this;
var __method = this, args = slice.call(arguments, 0);
return function() {
var a = merge(args, arguments);
return __method.apply(this, a);
}
}
function delay(timeout) {
var __method = this, args = slice.call(arguments, 1);
timeout = timeout * 1000;
return window.setTimeout(function() {
return __method.apply(__method, args);
}, timeout);
}
function defer() {
var args = update([0.01], arguments);
return this.delay.apply(this, args);
}
function wrap(wrapper) {
var __method = this;
return function() {
var a = update([__method.bind(this)], arguments);
return wrapper.apply(this, a);
}
}
function methodize() {
if (this._methodized) return this._methodized;
var __method = this;
return this._methodized = function() {
var a = update([this], arguments);
return __method.apply(null, a);
};
}
return {
argumentNames: argumentNames,
bind: bind,
bindAsEventListener: bindAsEventListener,
curry: curry,
delay: delay,
defer: defer,
wrap: wrap,
methodize: methodize
}
})());
(function(proto) {
function toISOString() {
return this.getUTCFullYear() + '-' +
(this.getUTCMonth() + 1).toPaddedString(2) + '-' +
this.getUTCDate().toPaddedString(2) + 'T' +
this.getUTCHours().toPaddedString(2) + ':' +
this.getUTCMinutes().toPaddedString(2) + ':' +
this.getUTCSeconds().toPaddedString(2) + 'Z';
}
function toJSON() {
return this.toISOString();
}
if (!proto.toISOString) proto.toISOString = toISOString;
if (!proto.toJSON) proto.toJSON = toJSON;
})(Date.prototype);
RegExp.prototype.match = RegExp.prototype.test;
RegExp.escape = function(str) {
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
var PeriodicalExecuter = Class.create({
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
this.currentlyExecuting = false;
this.registerCallback();
},
registerCallback: function() {
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
execute: function() {
this.callback(this);
},
stop: function() {
if (!this.timer) return;
clearInterval(this.timer);
this.timer = null;
},
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
this.execute();
this.currentlyExecuting = false;
} catch(e) {
this.currentlyExecuting = false;
throw e;
}
}
}
});
Object.extend(String, {
interpret: function(value) {
return value == null ? '' : String(value);
},
specialChar: {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'\\': '\\\\'
}
});
Object.extend(String.prototype, (function() {
var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
typeof JSON.parse === 'function' &&
JSON.parse('{"test": true}').test;
function prepareReplacement(replacement) {
if (Object.isFunction(replacement)) return replacement;
var template = new Template(replacement);
return function(match) { return template.evaluate(match) };
}
function gsub(pattern, replacement) {
var result = '', source = this, match;
replacement = prepareReplacement(replacement);
if (Object.isString(pattern))
pattern = RegExp.escape(pattern);
if (!(pattern.length || pattern.source)) {
replacement = replacement('');
return replacement + source.split('').join(replacement) + replacement;
}
while (source.length > 0) {
if (match = source.match(pattern)) {
result += source.slice(0, match.index);
result += String.interpret(replacement(match));
source = source.slice(match.index + match[0].length);
} else {
result += source, source = '';
}
}
return result;
}
function sub(pattern, replacement, count) {
replacement = prepareReplacement(replacement);
count = Object.isUndefined(count) ? 1 : count;
return this.gsub(pattern, function(match) {
if (--count < 0) return match[0];
return replacement(match);
});
}
function scan(pattern, iterator) {
this.gsub(pattern, iterator);
return String(this);
}
function truncate(length, truncation) {
length = length || 30;
truncation = Object.isUndefined(truncation) ? '...' : truncation;
return this.length > length ?
this.slice(0, length - truncation.length) + truncation : String(this);
}
function strip() {
return this.replace(/^\s+/, '').replace(/\s+$/, '');
}
function stripTags() {
return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
}
function stripScripts() {
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
}
function extractScripts() {
var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
matchOne = new RegExp(Prototype.ScriptFragment, 'im');
return (this.match(matchAll) || []).map(function(scriptTag) {
return (scriptTag.match(matchOne) || ['', ''])[1];
});
}
function evalScripts() {
return this.extractScripts().map(function(script) { return eval(script) });
}
function escapeHTML() {
return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
}
function unescapeHTML() {
return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&');
}
function toQueryParams(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
if (!match) return { };
return match[1].split(separator || '&').inject({ }, function(hash, pair) {
if ((pair = pair.split('='))[0]) {
var key = decodeURIComponent(pair.shift()),
value = pair.length > 1 ? pair.join('=') : pair[0];
if (value != undefined) value = decodeURIComponent(value);
if (key in hash) {
if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
hash[key].push(value);
}
else hash[key] = value;
}
return hash;
});
}
function toArray() {
return this.split('');
}
function succ() {
return this.slice(0, this.length - 1) +
String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
}
function times(count) {
return count < 1 ? '' : new Array(count + 1).join(this);
}
function camelize() {
return this.replace(/-+(.)?/g, function(match, chr) {
return chr ? chr.toUpperCase() : '';
});
}
function capitalize() {
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
}
function underscore() {
return this.replace(/::/g, '/')
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
.replace(/([a-z\d])([A-Z])/g, '$1_$2')
.replace(/-/g, '_')
.toLowerCase();
}
function dasherize() {
return this.replace(/_/g, '-');
}
function inspect(useDoubleQuotes) {
var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
if (character in String.specialChar) {
return String.specialChar[character];
}
return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
});
if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
return "'" + escapedString.replace(/'/g, '\\\'') + "'";
}
function unfilterJSON(filter) {
return this.replace(filter || Prototype.JSONFilter, '$1');
}
function isJSON() {
var str = this;
if (str.blank()) return false;
str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
return (/^[\],:{}\s]*$/).test(str);
}
function evalJSON(sanitize) {
var json = this.unfilterJSON(),
cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
if (cx.test(json)) {
json = json.replace(cx, function (a) {
return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
try {
if (!sanitize || json.isJSON()) return eval('(' + json + ')');
} catch (e) { }
throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
}
function parseJSON() {
var json = this.unfilterJSON();
return JSON.parse(json);
}
function include(pattern) {
return this.indexOf(pattern) > -1;
}
function startsWith(pattern) {
return this.lastIndexOf(pattern, 0) === 0;
}
function endsWith(pattern) {
var d = this.length - pattern.length;
return d >= 0 && this.indexOf(pattern, d) === d;
}
function empty() {
return this == '';
}
function blank() {
return /^\s*$/.test(this);
}
function interpolate(object, pattern) {
return new Template(this, pattern).evaluate(object);
}
return {
gsub: gsub,
sub: sub,
scan: scan,
truncate: truncate,
strip: String.prototype.trim || strip,
stripTags: stripTags,
stripScripts: stripScripts,
extractScripts: extractScripts,
evalScripts: evalScripts,
escapeHTML: escapeHTML,
unescapeHTML: unescapeHTML,
toQueryParams: toQueryParams,
parseQuery: toQueryParams,
toArray: toArray,
succ: succ,
times: times,
camelize: camelize,
capitalize: capitalize,
underscore: underscore,
dasherize: dasherize,
inspect: inspect,
unfilterJSON: unfilterJSON,
isJSON: isJSON,
evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
include: include,
startsWith: startsWith,
endsWith: endsWith,
empty: empty,
blank: blank,
interpolate: interpolate
};
})());
var Template = Class.create({
initialize: function(template, pattern) {
this.template = template.toString();
this.pattern = pattern || Template.Pattern;
},
evaluate: function(object) {
if (object && Object.isFunction(object.toTemplateReplacements))
object = object.toTemplateReplacements();
return this.template.gsub(this.pattern, function(match) {
if (object == null) return (match[1] + '');
var before = match[1] || '';
if (before == '\\') return match[2];
var ctx = object, expr = match[3],
pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
match = pattern.exec(expr);
if (match == null) return before;
while (match != null) {
var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
ctx = ctx[comp];
if (null == ctx || '' == match[3]) break;
expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
match = pattern.exec(expr);
}
return before + String.interpret(ctx);
});
}
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
var $break = { };
var Enumerable = (function() {
function each(iterator, context) {
var index = 0;
try {
this._each(function(value) {
iterator.call(context, value, index++);
});
} catch (e) {
if (e != $break) throw e;
}
return this;
}
function eachSlice(number, iterator, context) {
var index = -number, slices = [], array = this.toArray();
if (number < 1) return array;
while ((index += number) < array.length)
slices.push(array.slice(index, index+number));
return slices.collect(iterator, context);
}
function all(iterator, context) {
iterator = iterator || Prototype.K;
var result = true;
this.each(function(value, index) {
result = result && !!iterator.call(context, value, index);
if (!result) throw $break;
});
return result;
}
function any(iterator, context) {
iterator = iterator || Prototype.K;
var result = false;
this.each(function(value, index) {
if (result = !!iterator.call(context, value, index))
throw $break;
});
return result;
}
function collect(iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
this.each(function(value, index) {
results.push(iterator.call(context, value, index));
});
return results;
}
function detect(iterator, context) {
var result;
this.each(function(value, index) {
if (iterator.call(context, value, index)) {
result = value;
throw $break;
}
});
return result;
}
function findAll(iterator, context) {
var results = [];
this.each(function(value, index) {
if (iterator.call(context, value, index))
results.push(value);
});
return results;
}
function grep(filter, iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
if (Object.isString(filter))
filter = new RegExp(RegExp.escape(filter));
this.each(function(value, index) {
if (filter.match(value))
results.push(iterator.call(context, value, index));
});
return results;
}
function include(object) {
if (Object.isFunction(this.indexOf))
if (this.indexOf(object) != -1) return true;
var found = false;
this.each(function(value) {
if (value == object) {
found = true;
throw $break;
}
});
return found;
}
function inGroupsOf(number, fillWith) {
fillWith = Object.isUndefined(fillWith) ? null : fillWith;
return this.eachSlice(number, function(slice) {
while(slice.length < number) slice.push(fillWith);
return slice;
});
}
function inject(memo, iterator, context) {
this.each(function(value, index) {
memo = iterator.call(context, memo, value, index);
});
return memo;
}
function invoke(method) {
var args = $A(arguments).slice(1);
return this.map(function(value) {
return value[method].apply(value, args);
});
}
function max(iterator, context) {
iterator = iterator || Prototype.K;
var result;
this.each(function(value, index) {
value = iterator.call(context, value, index);
if (result == null || value >= result)
result = value;
});
return result;
}
function min(iterator, context) {
iterator = iterator || Prototype.K;
var result;
this.each(function(value, index) {
value = iterator.call(context, value, index);
if (result == null || value < result)
result = value;
});
return result;
}
function partition(iterator, context) {
iterator = iterator || Prototype.K;
var trues = [], falses = [];
this.each(function(value, index) {
(iterator.call(context, value, index) ?
trues : falses).push(value);
});
return [trues, falses];
}
function pluck(property) {
var results = [];
this.each(function(value) {
results.push(value[property]);
});
return results;
}
function reject(iterator, context) {
var results = [];
this.each(function(value, index) {
if (!iterator.call(context, value, index))
results.push(value);
});
return results;
}
function sortBy(iterator, context) {
return this.map(function(value, index) {
return {
value: value,
criteria: iterator.call(context, value, index)
};
}).sort(function(left, right) {
var a = left.criteria, b = right.criteria;
return a < b ? -1 : a > b ? 1 : 0;
}).pluck('value');
}
function toArray() {
return this.map();
}
function zip() {
var iterator = Prototype.K, args = $A(arguments);
if (Object.isFunction(args.last()))
iterator = args.pop();
var collections = [this].concat(args).map($A);
return this.map(function(value, index) {
return iterator(collections.pluck(index));
});
}
function size() {
return this.toArray().length;
}
function inspect() {
return '#<Enumerable:' + this.toArray().inspect() + '>';
}
return {
each: each,
eachSlice: eachSlice,
all: all,
every: all,
any: any,
some: any,
collect: collect,
map: collect,
detect: detect,
findAll: findAll,
select: findAll,
filter: findAll,
grep: grep,
include: include,
member: include,
inGroupsOf: inGroupsOf,
inject: inject,
invoke: invoke,
max: max,
min: min,
partition: partition,
pluck: pluck,
reject: reject,
sortBy: sortBy,
toArray: toArray,
entries: toArray,
zip: zip,
size: size,
inspect: inspect,
find: detect
};
})();
function $A(iterable) {
if (!iterable) return [];
if ('toArray' in Object(iterable)) return iterable.toArray();
var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
}
function $w(string) {
if (!Object.isString(string)) return [];
string = string.strip();
return string ? string.split(/\s+/) : [];
}
Array.from = $A;
(function() {
var arrayProto = Array.prototype,
slice = arrayProto.slice,
_each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
function each(iterator, context) {
for (var i = 0, length = this.length >>> 0; i < length; i++) {
if (i in this) iterator.call(context, this[i], i, this);
}
}
if (!_each) _each = each;
function clear() {
this.length = 0;
return this;
}
function first() {
return this[0];
}
function last() {
return this[this.length - 1];
}
function compact() {
return this.select(function(value) {
return value != null;
});
}
function flatten() {
return this.inject([], function(array, value) {
if (Object.isArray(value))
return array.concat(value.flatten());
array.push(value);
return array;
});
}
function without() {
var values = slice.call(arguments, 0);
return this.select(function(value) {
return !values.include(value);
});
}
function reverse(inline) {
return (inline === false ? this.toArray() : this)._reverse();
}
function uniq(sorted) {
return this.inject([], function(array, value, index) {
if (0 == index || (sorted ? array.last() != value : !array.include(value)))
array.push(value);
return array;
});
}
function intersect(array) {
return this.uniq().findAll(function(item) {
return array.detect(function(value) { return item === value });
});
}
function clone() {
return slice.call(this, 0);
}
function size() {
return this.length;
}
function inspect() {
return '[' + this.map(Object.inspect).join(', ') + ']';
}
function indexOf(item, i) {
i || (i = 0);
var length = this.length;
if (i < 0) i = length + i;
for (; i < length; i++)
if (this[i] === item) return i;
return -1;
}
function lastIndexOf(item, i) {
i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
var n = this.slice(0, i).reverse().indexOf(item);
return (n < 0) ? n : i - n - 1;
}
function concat() {
var array = slice.call(this, 0), item;
for (var i = 0, length = arguments.length; i < length; i++) {
item = arguments[i];
if (Object.isArray(item) && !('callee' in item)) {
for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
array.push(item[j]);
} else {
array.push(item);
}
}
return array;
}
Object.extend(arrayProto, Enumerable);
if (!arrayProto._reverse)
arrayProto._reverse = arrayProto.reverse;
Object.extend(arrayProto, {
_each: _each,
clear: clear,
first: first,
last: last,
compact: compact,
flatten: flatten,
without: without,
reverse: reverse,
uniq: uniq,
intersect: intersect,
clone: clone,
toArray: clone,
size: size,
inspect: inspect
});
var CONCAT_ARGUMENTS_BUGGY = (function() {
return [].concat(arguments)[0][0] !== 1;
})(1,2)
if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
})();
function $H(object) {
return new Hash(object);
};
var Hash = Class.create(Enumerable, (function() {
function initialize(object) {
this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
}
function _each(iterator) {
for (var key in this._object) {
var value = this._object[key], pair = [key, value];
pair.key = key;
pair.value = value;
iterator(pair);
}
}
function set(key, value) {
return this._object[key] = value;
}
function get(key) {
if (this._object[key] !== Object.prototype[key])
return this._object[key];
}
function unset(key) {
var value = this._object[key];
delete this._object[key];
return value;
}
function toObject() {
return Object.clone(this._object);
}
function keys() {
return this.pluck('key');
}
function values() {
return this.pluck('value');
}
function index(value) {
var match = this.detect(function(pair) {
return pair.value === value;
});
return match && match.key;
}
function merge(object) {
return this.clone().update(object);
}
function update(object) {
return new Hash(object).inject(this, function(result, pair) {
result.set(pair.key, pair.value);
return result;
});
}
function toQueryPair(key, value) {
if (Object.isUndefined(value)) return key;
return key + '=' + encodeURIComponent(String.interpret(value));
}
function toQueryString() {
return this.inject([], function(results, pair) {
var key = encodeURIComponent(pair.key), values = pair.value;
if (values && typeof values == 'object') {
if (Object.isArray(values)) {
var queryValues = [];
for (var i = 0, len = values.length, value; i < len; i++) {
value = values[i];
queryValues.push(toQueryPair(key, value));
}
return results.concat(queryValues);
}
} else results.push(toQueryPair(key, values));
return results;
}).join('&');
}
function inspect() {
return '#<Hash:{' + this.map(function(pair) {
return pair.map(Object.inspect).join(': ');
}).join(', ') + '}>';
}
function clone() {
return new Hash(this);
}
return {
initialize: initialize,
_each: _each,
set: set,
get: get,
unset: unset,
toObject: toObject,
toTemplateReplacements: toObject,
keys: keys,
values: values,
index: index,
merge: merge,
update: update,
toQueryString: toQueryString,
inspect: inspect,
toJSON: toObject,
clone: clone
};
})());
Hash.from = $H;
Object.extend(Number.prototype, (function() {
function toColorPart() {
return this.toPaddedString(2, 16);
}
function succ() {
return this + 1;
}
function times(iterator, context) {
$R(0, this, true).each(iterator, context);
return this;
}
function toPaddedString(length, radix) {
var string = this.toString(radix || 10);
return '0'.times(length - string.length) + string;
}
function abs() {
return Math.abs(this);
}
function round() {
return Math.round(this);
}
function ceil() {
return Math.ceil(this);
}
function floor() {
return Math.floor(this);
}
return {
toColorPart: toColorPart,
succ: succ,
times: times,
toPaddedString: toPaddedString,
abs: abs,
round: round,
ceil: ceil,
floor: floor
};
})());
function $R(start, end, exclusive) {
return new ObjectRange(start, end, exclusive);
}
var ObjectRange = Class.create(Enumerable, (function() {
function initialize(start, end, exclusive) {
this.start = start;
this.end = end;
this.exclusive = exclusive;
}
function _each(iterator) {
var value = this.start;
while (this.include(value)) {
iterator(value);
value = value.succ();
}
}
function include(value) {
if (value < this.start)
return false;
if (this.exclusive)
return value < this.end;
return value <= this.end;
}
return {
initialize: initialize,
_each: _each,
include: include
};
})());
var Ajax = {
getTransport: function() {
return Try.these(
function() {return new XMLHttpRequest()},
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')}
) || false;
},
activeRequestCount: 0
};
Ajax.Responders = {
responders: [],
_each: function(iterator) {
this.responders._each(iterator);
},
register: function(responder) {
if (!this.include(responder))
this.responders.push(responder);
},
unregister: function(responder) {
this.responders = this.responders.without(responder);
},
dispatch: function(callback, request, transport, json) {
this.each(function(responder) {
if (Object.isFunction(responder[callback])) {
try {
responder[callback].apply(responder, [request, transport, json]);
} catch (e) { }
}
});
}
};
Object.extend(Ajax.Responders, Enumerable);
Ajax.Responders.register({
onCreate: function() { Ajax.activeRequestCount++ },
onComplete: function() { Ajax.activeRequestCount-- }
});
Ajax.Base = Class.create({
initialize: function(options) {
this.options = {
method: 'post',
asynchronous: true,
contentType: 'application/x-www-form-urlencoded',
encoding: 'UTF-8',
parameters: '',
evalJSON: true,
evalJS: true
};
Object.extend(this.options, options || { });
this.options.method = this.options.method.toLowerCase();
if (Object.isHash(this.options.parameters))
this.options.parameters = this.options.parameters.toObject();
}
});
Ajax.Request = Class.create(Ajax.Base, {
_complete: false,
initialize: function($super, url, options) {
$super(options);
this.transport = Ajax.getTransport();
this.request(url);
},
request: function(url) {
this.url = url;
this.method = this.options.method;
var params = Object.isString(this.options.parameters) ?
this.options.parameters :
Object.toQueryString(this.options.parameters);
if (!['get', 'post'].include(this.method)) {
params += (params ? '&' : '') + "_method=" + this.method;
this.method = 'post';
}
if (params && this.method === 'get') {
this.url += (this.url.include('?') ? '&' : '?') + params;
}
this.parameters = params.toQueryParams();
try {
var response = new Ajax.Response(this);
if (this.options.onCreate) this.options.onCreate(response);
Ajax.Responders.dispatch('onCreate', this, response);
this.transport.open(this.method.toUpperCase(), this.url,
this.options.asynchronous);
if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
this.body = this.method == 'post' ? (this.options.postBody || params) : null;
this.transport.send(this.body);
/* Force Firefox to handle ready state 4 for synchronous requests */
if (!this.options.asynchronous && this.transport.overrideMimeType)
this.onStateChange();
}
catch (e) {
this.dispatchException(e);
}
},
onStateChange: function() {
var readyState = this.transport.readyState;
if (readyState > 1 && !((readyState == 4) && this._complete))
this.respondToReadyState(this.transport.readyState);
},
setRequestHeaders: function() {
var headers = {
'X-Requested-With': 'XMLHttpRequest',
'X-Prototype-Version': Prototype.Version,
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
};
if (this.method == 'post') {
headers['Content-type'] = this.options.contentType +
(this.options.encoding ? '; charset=' + this.options.encoding : '');
/* Force "Connection: close" for older Mozilla browsers to work
* around a bug where XMLHttpRequest sends an incorrect
* Content-length header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType &&
(navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
headers['Connection'] = 'close';
}
if (typeof this.options.requestHeaders == 'object') {
var extras = this.options.requestHeaders;
if (Object.isFunction(extras.push))
for (var i = 0, length = extras.length; i < length; i += 2)
headers[extras[i]] = extras[i+1];
else
$H(extras).each(function(pair) { headers[pair.key] = pair.value });
}
for (var name in headers)
this.transport.setRequestHeader(name, headers[name]);
},
success: function() {
var status = this.getStatus();
return !status || (status >= 200 && status < 300) || status == 304;
},
getStatus: function() {
try {
if (this.transport.status === 1223) return 204;
return this.transport.status || 0;
} catch (e) { return 0 }
},
respondToReadyState: function(readyState) {
var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
if (state == 'Complete') {
try {
this._complete = true;
(this.options['on' + response.status]
|| this.options['on' + (this.success() ? 'Success' : 'Failure')]
|| Prototype.emptyFunction)(response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
var contentType = response.getHeader('Content-type');
if (this.options.evalJS == 'force'
|| (this.options.evalJS && this.isSameOrigin() && contentType
&& contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
this.evalResponse();
}
try {
(this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
if (state == 'Complete') {
this.transport.onreadystatechange = Prototype.emptyFunction;
}
},
isSameOrigin: function() {
var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
protocol: location.protocol,
domain: document.domain,
port: location.port ? ':' + location.port : ''
}));
},
getHeader: function(name) {
try {
return this.transport.getResponseHeader(name) || null;
} catch (e) { return null; }
},
evalResponse: function() {
try {
return eval((this.transport.responseText || '').unfilterJSON());
} catch (e) {
this.dispatchException(e);
}
},
dispatchException: function(exception) {
(this.options.onException || Prototype.emptyFunction)(this, exception);
Ajax.Responders.dispatch('onException', this, exception);
}
});
Ajax.Request.Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
Ajax.Response = Class.create({
initialize: function(request){
this.request = request;
var transport = this.transport = request.transport,
readyState = this.readyState = transport.readyState;
if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
this.status = this.getStatus();
this.statusText = this.getStatusText();
this.responseText = String.interpret(transport.responseText);
this.headerJSON = this._getHeaderJSON();
}
if (readyState == 4) {
var xml = transport.responseXML;
this.responseXML = Object.isUndefined(xml) ? null : xml;
this.responseJSON = this._getResponseJSON();
}
},
status: 0,
statusText: '',
getStatus: Ajax.Request.prototype.getStatus,
getStatusText: function() {
try {
return this.transport.statusText || '';
} catch (e) { return '' }
},
getHeader: Ajax.Request.prototype.getHeader,
getAllHeaders: function() {
try {
return this.getAllResponseHeaders();
} catch (e) { return null }
},
getResponseHeader: function(name) {
return this.transport.getResponseHeader(name);
},
getAllResponseHeaders: function() {
return this.transport.getAllResponseHeaders();
},
_getHeaderJSON: function() {
var json = this.getHeader('X-JSON');
if (!json) return null;
json = decodeURIComponent(escape(json));
try {
return json.evalJSON(this.request.options.sanitizeJSON ||
!this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
},
_getResponseJSON: function() {
var options = this.request.options;
if (!options.evalJSON || (options.evalJSON != 'force' &&
!(this.getHeader('Content-type') || '').include('application/json')) ||
this.responseText.blank())
return null;
try {
return this.responseText.evalJSON(options.sanitizeJSON ||
!this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
}
});
Ajax.Updater = Class.create(Ajax.Request, {
initialize: function($super, container, url, options) {
this.container = {
success: (container.success || container),
failure: (container.failure || (container.success ? null : container))
};
options = Object.clone(options);
var onComplete = options.onComplete;
options.onComplete = (function(response, json) {
this.updateContent(response.responseText);
if (Object.isFunction(onComplete)) onComplete(response, json);
}).bind(this);
$super(url, options);
},
updateContent: function(responseText) {
var receiver = this.container[this.success() ? 'success' : 'failure'],
options = this.options;
if (!options.evalScripts) responseText = responseText.stripScripts();
if (receiver = $(receiver)) {
if (options.insertion) {
if (Object.isString(options.insertion)) {
var insertion = { }; insertion[options.insertion] = responseText;
receiver.insert(insertion);
}
else options.insertion(receiver, responseText);
}
else receiver.update(responseText);
}
}
});
Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
initialize: function($super, container, url, options) {
$super(options);
this.onComplete = this.options.onComplete;
this.frequency = (this.options.frequency || 2);
this.decay = (this.options.decay || 1);
this.updater = { };
this.container = container;
this.url = url;
this.start();
},
start: function() {
this.options.onComplete = this.updateComplete.bind(this);
this.onTimerEvent();
},
stop: function() {
this.updater.options.onComplete = undefined;
clearTimeout(this.timer);
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
},
updateComplete: function(response) {
if (this.options.decay) {
this.decay = (response.responseText == this.lastText ?
this.decay * this.options.decay : 1);
this.lastText = response.responseText;
}
this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
},
onTimerEvent: function() {
this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});
function $(element) {
if (arguments.length > 1) {
for (var i = 0, elements = [], length = arguments.length; i < length; i++)
elements.push($(arguments[i]));
return elements;
}
if (Object.isString(element))
element = document.getElementById(element);
return Element.extend(element);
}
if (Prototype.BrowserFeatures.XPath) {
document._getElementsByXPath = function(expression, parentElement) {
var results = [];
var query = document.evaluate(expression, $(parentElement) || document,
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0, length = query.snapshotLength; i < length; i++)
results.push(Element.extend(query.snapshotItem(i)));
return results;
};
}
/*--------------------------------------------------------------------------*/
if (!Node) var Node = { };
if (!Node.ELEMENT_NODE) {
Object.extend(Node, {
ELEMENT_NODE: 1,
ATTRIBUTE_NODE: 2,
TEXT_NODE: 3,
CDATA_SECTION_NODE: 4,
ENTITY_REFERENCE_NODE: 5,
ENTITY_NODE: 6,
PROCESSING_INSTRUCTION_NODE: 7,
COMMENT_NODE: 8,
DOCUMENT_NODE: 9,
DOCUMENT_TYPE_NODE: 10,
DOCUMENT_FRAGMENT_NODE: 11,
NOTATION_NODE: 12
});
}
(function(global) {
function shouldUseCache(tagName, attributes) {
if (tagName === 'select') return false;
if ('type' in attributes) return false;
return true;
}
var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
try {
var el = document.createElement('<input name="x">');
return el.tagName.toLowerCase() === 'input' && el.name === 'x';
}
catch(err) {
return false;
}
})();
var element = global.Element;
global.Element = function(tagName, attributes) {
attributes = attributes || { };
tagName = tagName.toLowerCase();
var cache = Element.cache;
if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
tagName = '<' + tagName + ' name="' + attributes.name + '">';
delete attributes.name;
return Element.writeAttribute(document.createElement(tagName), attributes);
}
if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
var node = shouldUseCache(tagName, attributes) ?
cache[tagName].cloneNode(false) : document.createElement(tagName);
return Element.writeAttribute(node, attributes);
};
Object.extend(global.Element, element || { });
if (element) global.Element.prototype = element.prototype;
})(this);
Element.idCounter = 1;
Element.cache = { };
Element._purgeElement = function(element) {
var uid = element._prototypeUID;
if (uid) {
Element.stopObserving(element);
element._prototypeUID = void 0;
delete Element.Storage[uid];
}
}
Element.Methods = {
visible: function(element) {
return $(element).style.display != 'none';
},
toggle: function(element) {
element = $(element);
Element[Element.visible(element) ? 'hide' : 'show'](element);
return element;
},
hide: function(element) {
element = $(element);
element.style.display = 'none';
return element;
},
show: function(element) {
element = $(element);
element.style.display = '';
return element;
},
remove: function(element) {
element = $(element);
element.parentNode.removeChild(element);
return element;
},
update: (function(){
var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
var el = document.createElement("select"),
isBuggy = true;
el.innerHTML = "<option value=\"test\">test</option>";
if (el.options && el.options[0]) {
isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
}
el = null;
return isBuggy;
})();
var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
try {
var el = document.createElement("table");
if (el && el.tBodies) {
el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
var isBuggy = typeof el.tBodies[0] == "undefined";
el = null;
return isBuggy;
}
} catch (e) {
return true;
}
})();
var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
try {
var el = document.createElement('div');
el.innerHTML = "<link>";
var isBuggy = (el.childNodes.length === 0);
el = null;
return isBuggy;
} catch(e) {
return true;
}
})();
var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
var s = document.createElement("script"),
isBuggy = false;
try {
s.appendChild(document.createTextNode(""));
isBuggy = !s.firstChild ||
s.firstChild && s.firstChild.nodeType !== 3;
} catch (e) {
isBuggy = true;
}
s = null;
return isBuggy;
})();
function update(element, content) {
element = $(element);
var purgeElement = Element._purgeElement;
var descendants = element.getElementsByTagName('*'),
i = descendants.length;
while (i--) purgeElement(descendants[i]);
if (content && content.toElement)
content = content.toElement();
if (Object.isElement(content))
return element.update().insert(content);
content = Object.toHTML(content);
var tagName = element.tagName.toUpperCase();
if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
element.text = content;
return element;
}
if (ANY_INNERHTML_BUGGY) {
if (tagName in Element._insertionTranslations.tags) {
while (element.firstChild) {
element.removeChild(element.firstChild);
}
Element._getContentFromAnonymousElement(tagName, content.stripScripts())
.each(function(node) {
element.appendChild(node)
});
} else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
while (element.firstChild) {
element.removeChild(element.firstChild);
}
var nodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts(), true);
nodes.each(function(node) { element.appendChild(node) });
}
else {
element.innerHTML = content.stripScripts();
}
}
else {
element.innerHTML = content.stripScripts();
}
content.evalScripts.bind(content).defer();
return element;
}
return update;
})(),
replace: function(element, content) {
element = $(element);
if (content && content.toElement) content = content.toElement();
else if (!Object.isElement(content)) {
content = Object.toHTML(content);
var range = element.ownerDocument.createRange();
range.selectNode(element);
content.evalScripts.bind(content).defer();
content = range.createContextualFragment(content.stripScripts());
}
element.parentNode.replaceChild(content, element);
return element;
},
insert: function(element, insertions) {
element = $(element);
if (Object.isString(insertions) || Object.isNumber(insertions) ||
Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
insertions = {bottom:insertions};
var content, insert, tagName, childNodes;
for (var position in insertions) {
content = insertions[position];
position = position.toLowerCase();
insert = Element._insertionTranslations[position];
if (content && content.toElement) content = content.toElement();
if (Object.isElement(content)) {
insert(element, content);
continue;
}
content = Object.toHTML(content);
tagName = ((position == 'before' || position == 'after')
? element.parentNode : element).tagName.toUpperCase();
childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
if (position == 'top' || position == 'after') childNodes.reverse();
childNodes.each(insert.curry(element));
content.evalScripts.bind(content).defer();
}
return element;
},
wrap: function(element, wrapper, attributes) {
element = $(element);
if (Object.isElement(wrapper))
$(wrapper).writeAttribute(attributes || { });
else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
else wrapper = new Element('div', wrapper);
if (element.parentNode)
element.parentNode.replaceChild(wrapper, element);
wrapper.appendChild(element);
return wrapper;
},
inspect: function(element) {
element = $(element);
var result = '<' + element.tagName.toLowerCase();
$H({'id': 'id', 'className': 'class'}).each(function(pair) {
var property = pair.first(),
attribute = pair.last(),
value = (element[property] || '').toString();
if (value) result += ' ' + attribute + '=' + value.inspect(true);
});
return result + '>';
},
recursivelyCollect: function(element, property, maximumLength) {
element = $(element);
maximumLength = maximumLength || -1;
var elements = [];
while (element = element[property]) {
if (element.nodeType == 1)
elements.push(Element.extend(element));
if (elements.length == maximumLength)
break;
}
return elements;
},
ancestors: function(element) {
return Element.recursivelyCollect(element, 'parentNode');
},
descendants: function(element) {
return Element.select(element, "*");
},
firstDescendant: function(element) {
element = $(element).firstChild;
while (element && element.nodeType != 1) element = element.nextSibling;
return $(element);
},
immediateDescendants: function(element) {
var results = [], child = $(element).firstChild;
while (child) {
if (child.nodeType === 1) {
results.push(Element.extend(child));
}
child = child.nextSibling;
}
return results;
},
previousSiblings: function(element, maximumLength) {
return Element.recursivelyCollect(element, 'previousSibling');
},
nextSiblings: function(element) {
return Element.recursivelyCollect(element, 'nextSibling');
},
siblings: function(element) {
element = $(element);
return Element.previousSiblings(element).reverse()
.concat(Element.nextSiblings(element));
},
match: function(element, selector) {
element = $(element);
if (Object.isString(selector))
return Prototype.Selector.match(element, selector);
return selector.match(element);
},
up: function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return $(element.parentNode);
var ancestors = Element.ancestors(element);
return Object.isNumber(expression) ? ancestors[expression] :
Prototype.Selector.find(ancestors, expression, index);
},
down: function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return Element.firstDescendant(element);
return Object.isNumber(expression) ? Element.descendants(element)[expression] :
Element.select(element, expression)[index || 0];
},
previous: function(element, expression, index) {
element = $(element);
if (Object.isNumber(expression)) index = expression, expression = false;
if (!Object.isNumber(index)) index = 0;
if (expression) {
return Prototype.Selector.find(element.previousSiblings(), expression, index);
} else {
return element.recursivelyCollect("previousSibling", index + 1)[index];
}
},
next: function(element, expression, index) {
element = $(element);
if (Object.isNumber(expression)) index = expression, expression = false;
if (!Object.isNumber(index)) index = 0;
if (expression) {
return Prototype.Selector.find(element.nextSiblings(), expression, index);
} else {
var maximumLength = Object.isNumber(index) ? index + 1 : 1;
return element.recursivelyCollect("nextSibling", index + 1)[index];
}
},
select: function(element) {
element = $(element);
var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
return Prototype.Selector.select(expressions, element);
},
adjacent: function(element) {
element = $(element);
var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
return Prototype.Selector.select(expressions, element.parentNode).without(element);
},
identify: function(element) {
element = $(element);
var id = Element.readAttribute(element, 'id');
if (id) return id;
do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));
Element.writeAttribute(element, 'id', id);
return id;
},
readAttribute: function(element, name) {
element = $(element);
if (Prototype.Browser.IE) {
var t = Element._attributeTranslations.read;
if (t.values[name]) return t.values[name](element, name);
if (t.names[name]) name = t.names[name];
if (name.include(':')) {
return (!element.attributes || !element.attributes[name]) ? null :
element.attributes[name].value;
}
}
return element.getAttribute(name);
},
writeAttribute: function(element, name, value) {
element = $(element);
var attributes = { }, t = Element._attributeTranslations.write;
if (typeof name == 'object') attributes = name;
else attributes[name] = Object.isUndefined(value) ? true : value;
for (var attr in attributes) {
name = t.names[attr] || attr;
value = attributes[attr];
if (t.values[attr]) name = t.values[attr](element, value);
if (value === false || value === null)
element.removeAttribute(name);
else if (value === true)
element.setAttribute(name, name);
else element.setAttribute(name, value);
}
return element;
},
getHeight: function(element) {
return Element.getDimensions(element).height;
},
getWidth: function(element) {
return Element.getDimensions(element).width;
},
classNames: function(element) {
return new Element.ClassNames(element);
},
hasClassName: function(element, className) {
if (!(element = $(element))) return;
var elementClassName = element.className;
return (elementClassName.length > 0 && (elementClassName == className ||
new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
},
addClassName: function(element, className) {
if (!(element = $(element))) return;
if (!Element.hasClassName(element, className))
element.className += (element.className ? ' ' : '') + className;
return element;
},
removeClassName: function(element, className) {
if (!(element = $(element))) return;
element.className = element.className.replace(
new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
return element;
},
toggleClassName: function(element, className) {
if (!(element = $(element))) return;
return Element[Element.hasClassName(element, className) ?
'removeClassName' : 'addClassName'](element, className);
},
cleanWhitespace: function(element) {
element = $(element);
var node = element.firstChild;
while (node) {
var nextNode = node.nextSibling;
if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
element.removeChild(node);
node = nextNode;
}
return element;
},
empty: function(element) {
return $(element).innerHTML.blank();
},
descendantOf: function(element, ancestor) {
element = $(element), ancestor = $(ancestor);
if (element.compareDocumentPosition)
return (element.compareDocumentPosition(ancestor) & 8) === 8;
if (ancestor.contains)
return ancestor.contains(element) && ancestor !== element;
while (element = element.parentNode)
if (element == ancestor) return true;
return false;
},
scrollTo: function(element) {
element = $(element);
var pos = Element.cumulativeOffset(element);
window.scrollTo(pos[0], pos[1]);
return element;
},
getStyle: function(element, style) {
element = $(element);
style = style == 'float' ? 'cssFloat' : style.camelize();
var value = element.style[style];
if (!value || value == 'auto') {
var css = document.defaultView.getComputedStyle(element, null);
value = css ? css[style] : null;
}
if (style == 'opacity') return value ? parseFloat(value) : 1.0;
return value == 'auto' ? null : value;
},
getOpacity: function(element) {
return $(element).getStyle('opacity');
},
setStyle: function(element, styles) {
element = $(element);
var elementStyle = element.style, match;
if (Object.isString(styles)) {
element.style.cssText += ';' + styles;
return styles.include('opacity') ?
element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
}
for (var property in styles)
if (property == 'opacity') element.setOpacity(styles[property]);
else
elementStyle[(property == 'float' || property == 'cssFloat') ?
(Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
property] = styles[property];
return element;
},
setOpacity: function(element, value) {
element = $(element);
element.style.opacity = (value == 1 || value === '') ? '' :
(value < 0.00001) ? 0 : value;
return element;
},
makePositioned: function(element) {
element = $(element);
var pos = Element.getStyle(element, 'position');
if (pos == 'static' || !pos) {
element._madePositioned = true;
element.style.position = 'relative';
if (Prototype.Browser.Opera) {
element.style.top = 0;
element.style.left = 0;
}
}
return element;
},
undoPositioned: function(element) {
element = $(element);
if (element._madePositioned) {
element._madePositioned = undefined;
element.style.position =
element.style.top =
element.style.left =
element.style.bottom =
element.style.right = '';
}
return element;
},
makeClipping: function(element) {
element = $(element);
if (element._overflow) return element;
element._overflow = Element.getStyle(element, 'overflow') || 'auto';
if (element._overflow !== 'hidden')
element.style.overflow = 'hidden';
return element;
},
undoClipping: function(element) {
element = $(element);
if (!element._overflow) return element;
element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
element._overflow = null;
return element;
},
clonePosition: function(element, source) {
var options = Object.extend({
setLeft: true,
setTop: true,
setWidth: true,
setHeight: true,
offsetTop: 0,
offsetLeft: 0
}, arguments[2] || { });
source = $(source);
var p = Element.viewportOffset(source), delta = [0, 0], parent = null;
element = $(element);
if (Element.getStyle(element, 'position') == 'absolute') {
parent = Element.getOffsetParent(element);
delta = Element.viewportOffset(parent);
}
if (parent == document.body) {
delta[0] -= document.body.offsetLeft;
delta[1] -= document.body.offsetTop;
}
if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
if (options.setWidth) element.style.width = source.offsetWidth + 'px';
if (options.setHeight) element.style.height = source.offsetHeight + 'px';
return element;
}
};
Object.extend(Element.Methods, {
getElementsBySelector: Element.Methods.select,
childElements: Element.Methods.immediateDescendants
});
Element._attributeTranslations = {
write: {
names: {
className: 'class',
htmlFor: 'for'
},
values: { }
}
};
if (Prototype.Browser.Opera) {
Element.Methods.getStyle = Element.Methods.getStyle.wrap(
function(proceed, element, style) {
switch (style) {
case 'height': case 'width':
if (!Element.visible(element)) return null;
var dim = parseInt(proceed(element, style), 10);
if (dim !== element['offset' + style.capitalize()])
return dim + 'px';
var properties;
if (style === 'height') {
properties = ['border-top-width', 'padding-top',
'padding-bottom', 'border-bottom-width'];
}
else {
properties = ['border-left-width', 'padding-left',
'padding-right', 'border-right-width'];
}
return properties.inject(dim, function(memo, property) {
var val = proceed(element, property);
return val === null ? memo : memo - parseInt(val, 10);
}) + 'px';
default: return proceed(element, style);
}
}
);
Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
function(proceed, element, attribute) {
if (attribute === 'title') return element.title;
return proceed(element, attribute);
}
);
}
else if (Prototype.Browser.IE) {
Element.Methods.getStyle = function(element, style) {
element = $(element);
style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
var value = element.style[style];
if (!value && element.currentStyle) value = element.currentStyle[style];
if (style == 'opacity') {
if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
if (value[1]) return parseFloat(value[1]) / 100;
return 1.0;
}
if (value == 'auto') {
if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
return element['offset' + style.capitalize()] + 'px';
return null;
}
return value;
};
Element.Methods.setOpacity = function(element, value) {
function stripAlpha(filter){
return filter.replace(/alpha\([^\)]*\)/gi,'');
}
element = $(element);
var currentStyle = element.currentStyle;
if ((currentStyle && !currentStyle.hasLayout) ||
(!currentStyle && element.style.zoom == 'normal'))
element.style.zoom = 1;
var filter = element.getStyle('filter'), style = element.style;
if (value == 1 || value === '') {
(filter = stripAlpha(filter)) ?
style.filter = filter : style.removeAttribute('filter');
return element;
} else if (value < 0.00001) value = 0;
style.filter = stripAlpha(filter) +
'alpha(opacity=' + (value * 100) + ')';
return element;
};
Element._attributeTranslations = (function(){
var classProp = 'className',
forProp = 'for',
el = document.createElement('div');
el.setAttribute(classProp, 'x');
if (el.className !== 'x') {
el.setAttribute('class', 'x');
if (el.className === 'x') {
classProp = 'class';
}
}
el = null;
el = document.createElement('label');
el.setAttribute(forProp, 'x');
if (el.htmlFor !== 'x') {
el.setAttribute('htmlFor', 'x');
if (el.htmlFor === 'x') {
forProp = 'htmlFor';
}
}
el = null;
return {
read: {
names: {
'class': classProp,
'className': classProp,
'for': forProp,
'htmlFor': forProp
},
values: {
_getAttr: function(element, attribute) {
return element.getAttribute(attribute);
},
_getAttr2: function(element, attribute) {
return element.getAttribute(attribute, 2);
},
_getAttrNode: function(element, attribute) {
var node = element.getAttributeNode(attribute);
return node ? node.value : "";
},
_getEv: (function(){
var el = document.createElement('div'), f;
el.onclick = Prototype.emptyFunction;
var value = el.getAttribute('onclick');
if (String(value).indexOf('{') > -1) {
f = function(element, attribute) {
attribute = element.getAttribute(attribute);
if (!attribute) return null;
attribute = attribute.toString();
attribute = attribute.split('{')[1];
attribute = attribute.split('}')[0];
return attribute.strip();
};
}
else if (value === '') {
f = function(element, attribute) {
attribute = element.getAttribute(attribute);
if (!attribute) return null;
return attribute.strip();
};
}
el = null;
return f;
})(),
_flag: function(element, attribute) {
return $(element).hasAttribute(attribute) ? attribute : null;
},
style: function(element) {
return element.style.cssText.toLowerCase();
},
title: function(element) {
return element.title;
}
}
}
}
})();
Element._attributeTranslations.write = {
names: Object.extend({
cellpadding: 'cellPadding',
cellspacing: 'cellSpacing'
}, Element._attributeTranslations.read.names),
values: {
checked: function(element, value) {
element.checked = !!value;
},
style: function(element, value) {
element.style.cssText = value ? value : '';
}
}
};
Element._attributeTranslations.has = {};
$w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
Element._attributeTranslations.has[attr.toLowerCase()] = attr;
});
(function(v) {
Object.extend(v, {
href: v._getAttr2,
src: v._getAttr2,
type: v._getAttr,
action: v._getAttrNode,
disabled: v._flag,
checked: v._flag,
readonly: v._flag,
multiple: v._flag,
onload: v._getEv,
onunload: v._getEv,
onclick: v._getEv,
ondblclick: v._getEv,
onmousedown: v._getEv,
onmouseup: v._getEv,
onmouseover: v._getEv,
onmousemove: v._getEv,
onmouseout: v._getEv,
onfocus: v._getEv,
onblur: v._getEv,
onkeypress: v._getEv,
onkeydown: v._getEv,
onkeyup: v._getEv,
onsubmit: v._getEv,
onreset: v._getEv,
onselect: v._getEv,
onchange: v._getEv
});
})(Element._attributeTranslations.read.values);
if (Prototype.BrowserFeatures.ElementExtensions) {
(function() {
function _descendants(element) {
var nodes = element.getElementsByTagName('*'), results = [];
for (var i = 0, node; node = nodes[i]; i++)
if (node.tagName !== "!") // Filter out comment nodes.
results.push(node);
return results;
}
Element.Methods.down = function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return element.firstDescendant();
return Object.isNumber(expression) ? _descendants(element)[expression] :
Element.select(element, expression)[index || 0];
}
})();
}
}
else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
Element.Methods.setOpacity = function(element, value) {
element = $(element);
element.style.opacity = (value == 1) ? 0.999999 :
(value === '') ? '' : (value < 0.00001) ? 0 : value;
return element;
};
}
else if (Prototype.Browser.WebKit) {
Element.Methods.setOpacity = function(element, value) {
element = $(element);
element.style.opacity = (value == 1 || value === '') ? '' :
(value < 0.00001) ? 0 : value;
if (value == 1)
if (element.tagName.toUpperCase() == 'IMG' && element.width) {
element.width++; element.width--;
} else try {
var n = document.createTextNode(' ');
element.appendChild(n);
element.removeChild(n);
} catch (e) { }
return element;
};
}
if ('outerHTML' in document.documentElement) {
Element.Methods.replace = function(element, content) {
element = $(element);
if (content && content.toElement) content = content.toElement();
if (Object.isElement(content)) {
element.parentNode.replaceChild(content, element);
return element;
}
content = Object.toHTML(content);
var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
if (Element._insertionTranslations.tags[tagName]) {
var nextSibling = element.next(),
fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
parent.removeChild(element);
if (nextSibling)
fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
else
fragments.each(function(node) { parent.appendChild(node) });
}
else element.outerHTML = content.stripScripts();
content.evalScripts.bind(content).defer();
return element;
};
}
Element._returnOffset = function(l, t) {
var result = [l, t];
result.left = l;
result.top = t;
return result;
};
Element._getContentFromAnonymousElement = function(tagName, html, force) {
var div = new Element('div'),
t = Element._insertionTranslations.tags[tagName];
var workaround = false;
if (t) workaround = true;
else if (force) {
workaround = true;
t = ['', '', 0];
}
if (workaround) {
div.innerHTML = ' ' + t[0] + html + t[1];
div.removeChild(div.firstChild);
for (var i = t[2]; i--; ) {
div = div.firstChild;
}
}
else {
div.innerHTML = html;
}
return $A(div.childNodes);
};
Element._insertionTranslations = {
before: function(element, node) {
element.parentNode.insertBefore(node, element);
},
top: function(element, node) {
element.insertBefore(node, element.firstChild);
},
bottom: function(element, node) {
element.appendChild(node);
},
after: function(element, node) {
element.parentNode.insertBefore(node, element.nextSibling);
},
tags: {
TABLE: ['<table>', '</table>', 1],
TBODY: ['<table><tbody>', '</tbody></table>', 2],
TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
SELECT: ['<select>', '</select>', 1]
}
};
(function() {
var tags = Element._insertionTranslations.tags;
Object.extend(tags, {
THEAD: tags.TBODY,
TFOOT: tags.TBODY,
TH: tags.TD
});
})();
Element.Methods.Simulated = {
hasAttribute: function(element, attribute) {
attribute = Element._attributeTranslations.has[attribute] || attribute;
var node = $(element).getAttributeNode(attribute);
return !!(node && node.specified);
}
};
Element.Methods.ByTag = { };
Object.extend(Element, Element.Methods);
(function(div) {
if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {
window.HTMLElement = { };
window.HTMLElement.prototype = div['__proto__'];
Prototype.BrowserFeatures.ElementExtensions = true;
}
div = null;
})(document.createElement('div'));
Element.extend = (function() {
function checkDeficiency(tagName) {
if (typeof window.Element != 'undefined') {
var proto = window.Element.prototype;
if (proto) {
var id = '_' + (Math.random()+'').slice(2),
el = document.createElement(tagName);
proto[id] = 'x';
var isBuggy = (el[id] !== 'x');
delete proto[id];
el = null;
return isBuggy;
}
}
return false;
}
function extendElementWith(element, methods) {
for (var property in methods) {
var value = methods[property];
if (Object.isFunction(value) && !(property in element))
element[property] = value.methodize();
}
}
var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');
if (Prototype.BrowserFeatures.SpecificElementExtensions) {
if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
return function(element) {
if (element && typeof element._extendedByPrototype == 'undefined') {
var t = element.tagName;
if (t && (/^(?:object|applet|embed)$/i.test(t))) {
extendElementWith(element, Element.Methods);
extendElementWith(element, Element.Methods.Simulated);
extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
}
}
return element;
}
}
return Prototype.K;
}
var Methods = { }, ByTag = Element.Methods.ByTag;
var extend = Object.extend(function(element) {
if (!element || typeof element._extendedByPrototype != 'undefined' ||
element.nodeType != 1 || element == window) return element;
var methods = Object.clone(Methods),
tagName = element.tagName.toUpperCase();
if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
extendElementWith(element, methods);
element._extendedByPrototype = Prototype.emptyFunction;
return element;
}, {
refresh: function() {
if (!Prototype.BrowserFeatures.ElementExtensions) {
Object.extend(Methods, Element.Methods);
Object.extend(Methods, Element.Methods.Simulated);
}
}
});
extend.refresh();
return extend;
})();
if (document.documentElement.hasAttribute) {
Element.hasAttribute = function(element, attribute) {
return element.hasAttribute(attribute);
};
}
else {
Element.hasAttribute = Element.Methods.Simulated.hasAttribute;
}
Element.addMethods = function(methods) {
var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
if (!methods) {
Object.extend(Form, Form.Methods);
Object.extend(Form.Element, Form.Element.Methods);
Object.extend(Element.Methods.ByTag, {
"FORM": Object.clone(Form.Methods),
"INPUT": Object.clone(Form.Element.Methods),
"SELECT": Object.clone(Form.Element.Methods),
"TEXTAREA": Object.clone(Form.Element.Methods),
"BUTTON": Object.clone(Form.Element.Methods)
});
}
if (arguments.length == 2) {
var tagName = methods;
methods = arguments[1];
}
if (!tagName) Object.extend(Element.Methods, methods || { });
else {
if (Object.isArray(tagName)) tagName.each(extend);
else extend(tagName);
}
function extend(tagName) {
tagName = tagName.toUpperCase();
if (!Element.Methods.ByTag[tagName])
Element.Methods.ByTag[tagName] = { };
Object.extend(Element.Methods.ByTag[tagName], methods);
}
function copy(methods, destination, onlyIfAbsent) {
onlyIfAbsent = onlyIfAbsent || false;
for (var property in methods) {
var value = methods[property];
if (!Object.isFunction(value)) continue;
if (!onlyIfAbsent || !(property in destination))
destination[property] = value.methodize();
}
}
function findDOMClass(tagName) {
var klass;
var trans = {
"OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
"FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
"DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
"H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
"INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
"TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
"TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
"TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
"FrameSet", "IFRAME": "IFrame"
};
if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
if (window[klass]) return window[klass];
klass = 'HTML' + tagName + 'Element';
if (window[klass]) return window[klass];
klass = 'HTML' + tagName.capitalize() + 'Element';
if (window[klass]) return window[klass];
var element = document.createElement(tagName),
proto = element['__proto__'] || element.constructor.prototype;
element = null;
return proto;
}
var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
Element.prototype;
if (F.ElementExtensions) {
copy(Element.Methods, elementPrototype);
copy(Element.Methods.Simulated, elementPrototype, true);
}
if (F.SpecificElementExtensions) {
for (var tag in Element.Methods.ByTag) {
var klass = findDOMClass(tag);
if (Object.isUndefined(klass)) continue;
copy(T[tag], klass.prototype);
}
}
Object.extend(Element, Element.Methods);
delete Element.ByTag;
if (Element.extend.refresh) Element.extend.refresh();
Element.cache = { };
};
document.viewport = {
getDimensions: function() {
return { width: this.getWidth(), height: this.getHeight() };
},
getScrollOffsets: function() {
return Element._returnOffset(
window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
}
};
(function(viewport) {
var B = Prototype.Browser, doc = document, element, property = {};
function getRootElement() {
if (B.WebKit && !doc.evaluate)
return document;
if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
return document.body;
return document.documentElement;
}
function define(D) {
if (!element) element = getRootElement();
property[D] = 'client' + D;
viewport['get' + D] = function() { return element[property[D]] };
return viewport['get' + D]();
}
viewport.getWidth = define.curry('Width');
viewport.getHeight = define.curry('Height');
})(document.viewport);
Element.Storage = {
UID: 1
};
Element.addMethods({
getStorage: function(element) {
if (!(element = $(element))) return;
var uid;
if (element === window) {
uid = 0;
} else {
if (typeof element._prototypeUID === "undefined")
element._prototypeUID = Element.Storage.UID++;
uid = element._prototypeUID;
}
if (!Element.Storage[uid])
Element.Storage[uid] = $H();
return Element.Storage[uid];
},
store: function(element, key, value) {
if (!(element = $(element))) return;
if (arguments.length === 2) {
Element.getStorage(element).update(key);
} else {
Element.getStorage(element).set(key, value);
}
return element;
},
retrieve: function(element, key, defaultValue) {
if (!(element = $(element))) return;
var hash = Element.getStorage(element), value = hash.get(key);
if (Object.isUndefined(value)) {
hash.set(key, defaultValue);
value = defaultValue;
}
return value;
},
clone: function(element, deep) {
if (!(element = $(element))) return;
var clone = element.cloneNode(deep);
clone._prototypeUID = void 0;
if (deep) {
var descendants = Element.select(clone, '*'),
i = descendants.length;
while (i--) {
descendants[i]._prototypeUID = void 0;
}
}
return Element.extend(clone);
},
purge: function(element) {
if (!(element = $(element))) return;
var purgeElement = Element._purgeElement;
purgeElement(element);
var descendants = element.getElementsByTagName('*'),
i = descendants.length;
while (i--) purgeElement(descendants[i]);
return null;
}
});
(function() {
function toDecimal(pctString) {
var match = pctString.match(/^(\d+)%?$/i);
if (!match) return null;
return (Number(match[1]) / 100);
}
function getPixelValue(value, property, context) {
var element = null;
if (Object.isElement(value)) {
element = value;
value = element.getStyle(property);
}
if (value === null) {
return null;
}
if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
return window.parseFloat(value);
}
var isPercentage = value.include('%'), isViewport = (context === document.viewport);
if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
var style = element.style.left, rStyle = element.runtimeStyle.left;
element.runtimeStyle.left = element.currentStyle.left;
element.style.left = value || 0;
value = element.style.pixelLeft;
element.style.left = style;
element.runtimeStyle.left = rStyle;
return value;
}
if (element && isPercentage) {
context = context || element.parentNode;
var decimal = toDecimal(value);
var whole = null;
var position = element.getStyle('position');
var isHorizontal = property.include('left') || property.include('right') ||
property.include('width');
var isVertical = property.include('top') || property.include('bottom') ||
property.include('height');
if (context === document.viewport) {
if (isHorizontal) {
whole = document.viewport.getWidth();
} else if (isVertical) {
whole = document.viewport.getHeight();
}
} else {
if (isHorizontal) {
whole = $(context).measure('width');
} else if (isVertical) {
whole = $(context).measure('height');
}
}
return (whole === null) ? 0 : whole * decimal;
}
return 0;
}
function toCSSPixels(number) {
if (Object.isString(number) && number.endsWith('px')) {
return number;
}
return number + 'px';
}
function isDisplayed(element) {
var originalElement = element;
while (element && element.parentNode) {
var display = element.getStyle('display');
if (display === 'none') {
return false;
}
element = $(element.parentNode);
}
return true;
}
var hasLayout = Prototype.K;
if ('currentStyle' in document.documentElement) {
hasLayout = function(element) {
if (!element.currentStyle.hasLayout) {
element.style.zoom = 1;
}
return element;
};
}
function cssNameFor(key) {
if (key.include('border')) key = key + '-width';
return key.camelize();
}
Element.Layout = Class.create(Hash, {
initialize: function($super, element, preCompute) {
$super();
this.element = $(element);
Element.Layout.PROPERTIES.each( function(property) {
this._set(property, null);
}, this);
if (preCompute) {
this._preComputing = true;
this._begin();
Element.Layout.PROPERTIES.each( this._compute, this );
this._end();
this._preComputing = false;
}
},
_set: function(property, value) {
return Hash.prototype.set.call(this, property, value);
},
set: function(property, value) {
throw "Properties of Element.Layout are read-only.";
},
get: function($super, property) {
var value = $super(property);
return value === null ? this._compute(property) : value;
},
_begin: function() {
if (this._prepared) return;
var element = this.element;
if (isDisplayed(element)) {
this._prepared = true;
return;
}
var originalStyles = {
position: element.style.position || '',
width: element.style.width || '',
visibility: element.style.visibility || '',
display: element.style.display || ''
};
element.store('prototype_original_styles', originalStyles);
var position = element.getStyle('position'),
width = element.getStyle('width');
if (width === "0px" || width === null) {
element.style.display = 'block';
width = element.getStyle('width');
}
var context = (position === 'fixed') ? document.viewport :
element.parentNode;
element.setStyle({
position: 'absolute',
visibility: 'hidden',
display: 'block'
});
var positionedWidth = element.getStyle('width');
var newWidth;
if (width && (positionedWidth === width)) {
newWidth = getPixelValue(element, 'width', context);
} else if (position === 'absolute' || position === 'fixed') {
newWidth = getPixelValue(element, 'width', context);
} else {
var parent = element.parentNode, pLayout = $(parent).getLayout();
newWidth = pLayout.get('width') -
this.get('margin-left') -
this.get('border-left') -
this.get('padding-left') -
this.get('padding-right') -
this.get('border-right') -
this.get('margin-right');
}
element.setStyle({ width: newWidth + 'px' });
this._prepared = true;
},
_end: function() {
var element = this.element;
var originalStyles = element.retrieve('prototype_original_styles');
element.store('prototype_original_styles', null);
element.setStyle(originalStyles);
this._prepared = false;
},
_compute: function(property) {
var COMPUTATIONS = Element.Layout.COMPUTATIONS;
if (!(property in COMPUTATIONS)) {
throw "Property not found.";
}
return this._set(property, COMPUTATIONS[property].call(this, this.element));
},
toObject: function() {
var args = $A(arguments);
var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
args.join(' ').split(' ');
var obj = {};
keys.each( function(key) {
if (!Element.Layout.PROPERTIES.include(key)) return;
var value = this.get(key);
if (value != null) obj[key] = value;
}, this);
return obj;
},
toHash: function() {
var obj = this.toObject.apply(this, arguments);
return new Hash(obj);
},
toCSS: function() {
var args = $A(arguments);
var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
args.join(' ').split(' ');
var css = {};
keys.each( function(key) {
if (!Element.Layout.PROPERTIES.include(key)) return;
if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;
var value = this.get(key);
if (value != null) css[cssNameFor(key)] = value + 'px';
}, this);
return css;
},
inspect: function() {
return "#<Element.Layout>";
}
});
Object.extend(Element.Layout, {
PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),
COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),
COMPUTATIONS: {
'height': function(element) {
if (!this._preComputing) this._begin();
var bHeight = this.get('border-box-height');
if (bHeight <= 0) {
if (!this._preComputing) this._end();
return 0;
}
var bTop = this.get('border-top'),
bBottom = this.get('border-bottom');
var pTop = this.get('padding-top'),
pBottom = this.get('padding-bottom');
if (!this._preComputing) this._end();
return bHeight - bTop - bBottom - pTop - pBottom;
},
'width': function(element) {
if (!this._preComputing) this._begin();
var bWidth = this.get('border-box-width');
if (bWidth <= 0) {
if (!this._preComputing) this._end();
return 0;
}
var bLeft = this.get('border-left'),
bRight = this.get('border-right');
var pLeft = this.get('padding-left'),
pRight = this.get('padding-right');
if (!this._preComputing) this._end();
return bWidth - bLeft - bRight - pLeft - pRight;
},
'padding-box-height': function(element) {
var height = this.get('height'),
pTop = this.get('padding-top'),
pBottom = this.get('padding-bottom');
return height + pTop + pBottom;
},
'padding-box-width': function(element) {
var width = this.get('width'),
pLeft = this.get('padding-left'),
pRight = this.get('padding-right');
return width + pLeft + pRight;
},
'border-box-height': function(element) {
if (!this._preComputing) this._begin();
var height = element.offsetHeight;
if (!this._preComputing) this._end();
return height;
},
'border-box-width': function(element) {
if (!this._preComputing) this._begin();
var width = element.offsetWidth;
if (!this._preComputing) this._end();
return width;
},
'margin-box-height': function(element) {
var bHeight = this.get('border-box-height'),
mTop = this.get('margin-top'),
mBottom = this.get('margin-bottom');
if (bHeight <= 0) return 0;
return bHeight + mTop + mBottom;
},
'margin-box-width': function(element) {
var bWidth = this.get('border-box-width'),
mLeft = this.get('margin-left'),
mRight = this.get('margin-right');
if (bWidth <= 0) return 0;
return bWidth + mLeft + mRight;
},
'top': function(element) {
var offset = element.positionedOffset();
return offset.top;
},
'bottom': function(element) {
var offset = element.positionedOffset(),
parent = element.getOffsetParent(),
pHeight = parent.measure('height');
var mHeight = this.get('border-box-height');
return pHeight - mHeight - offset.top;
},
'left': function(element) {
var offset = element.positionedOffset();
return offset.left;
},
'right': function(element) {
var offset = element.positionedOffset(),
parent = element.getOffsetParent(),
pWidth = parent.measure('width');
var mWidth = this.get('border-box-width');
return pWidth - mWidth - offset.left;
},
'padding-top': function(element) {
return getPixelValue(element, 'paddingTop');
},
'padding-bottom': function(element) {
return getPixelValue(element, 'paddingBottom');
},
'padding-left': function(element) {
return getPixelValue(element, 'paddingLeft');
},
'padding-right': function(element) {
return getPixelValue(element, 'paddingRight');
},
'border-top': function(element) {
return getPixelValue(element, 'borderTopWidth');
},
'border-bottom': function(element) {
return getPixelValue(element, 'borderBottomWidth');
},
'border-left': function(element) {
return getPixelValue(element, 'borderLeftWidth');
},
'border-right': function(element) {
return getPixelValue(element, 'borderRightWidth');
},
'margin-top': function(element) {
return getPixelValue(element, 'marginTop');
},
'margin-bottom': function(element) {
return getPixelValue(element, 'marginBottom');
},
'margin-left': function(element) {
return getPixelValue(element, 'marginLeft');
},
'margin-right': function(element) {
return getPixelValue(element, 'marginRight');
}
}
});
if ('getBoundingClientRect' in document.documentElement) {
Object.extend(Element.Layout.COMPUTATIONS, {
'right': function(element) {
var parent = hasLayout(element.getOffsetParent());
var rect = element.getBoundingClientRect(),
pRect = parent.getBoundingClientRect();
return (pRect.right - rect.right).round();
},
'bottom': function(element) {
var parent = hasLayout(element.getOffsetParent());
var rect = element.getBoundingClientRect(),
pRect = parent.getBoundingClientRect();
return (pRect.bottom - rect.bottom).round();
}
});
}
Element.Offset = Class.create({
initialize: function(left, top) {
this.left = left.round();
this.top = top.round();
this[0] = this.left;
this[1] = this.top;
},
relativeTo: function(offset) {
return new Element.Offset(
this.left - offset.left,
this.top - offset.top
);
},
inspect: function() {
return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this);
},
toString: function() {
return "[#{left}, #{top}]".interpolate(this);
},
toArray: function() {
return [this.left, this.top];
}
});
function getLayout(element, preCompute) {
return new Element.Layout(element, preCompute);
}
function measure(element, property) {
return $(element).getLayout().get(property);
}
function getDimensions(element) {
element = $(element);
var display = Element.getStyle(element, 'display');
if (display && display !== 'none') {
return { width: element.offsetWidth, height: element.offsetHeight };
}
var style = element.style;
var originalStyles = {
visibility: style.visibility,
position: style.position,
display: style.display
};
var newStyles = {
visibility: 'hidden',
display: 'block'
};
if (originalStyles.position !== 'fixed')
newStyles.position = 'absolute';
Element.setStyle(element, newStyles);
var dimensions = {
width: element.offsetWidth,
height: element.offsetHeight
};
Element.setStyle(element, originalStyles);
return dimensions;
}
function getOffsetParent(element) {
element = $(element);
if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
return $(document.body);
var isInline = (Element.getStyle(element, 'display') === 'inline');
if (!isInline && element.offsetParent) return $(element.offsetParent);
while ((element = element.parentNode) && element !== document.body) {
if (Element.getStyle(element, 'position') !== 'static') {
return isHtml(element) ? $(document.body) : $(element);
}
}
return $(document.body);
}
function cumulativeOffset(element) {
element = $(element);
var valueT = 0, valueL = 0;
if (element.parentNode) {
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
} while (element);
}
return new Element.Offset(valueL, valueT);
}
function positionedOffset(element) {
element = $(element);
var layout = element.getLayout();
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
if (element) {
if (isBody(element)) break;
var p = Element.getStyle(element, 'position');
if (p !== 'static') break;
}
} while (element);
valueL -= layout.get('margin-top');
valueT -= layout.get('margin-left');
return new Element.Offset(valueL, valueT);
}
function cumulativeScrollOffset(element) {
var valueT = 0, valueL = 0;
do {
valueT += element.scrollTop || 0;
valueL += element.scrollLeft || 0;
element = element.parentNode;
} while (element);
return new Element.Offset(valueL, valueT);
}
function viewportOffset(forElement) {
element = $(element);
var valueT = 0, valueL = 0, docBody = document.body;
var element = forElement;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
if (element.offsetParent == docBody &&
Element.getStyle(element, 'position') == 'absolute') break;
} while (element = element.offsetParent);
element = forElement;
do {
if (element != docBody) {
valueT -= element.scrollTop || 0;
valueL -= element.scrollLeft || 0;
}
} while (element = element.parentNode);
return new Element.Offset(valueL, valueT);
}
function absolutize(element) {
element = $(element);
if (Element.getStyle(element, 'position') === 'absolute') {
return element;
}
var offsetParent = getOffsetParent(element);
var eOffset = element.viewportOffset(),
pOffset = offsetParent.viewportOffset();
var offset = eOffset.relativeTo(pOffset);
var layout = element.getLayout();
element.store('prototype_absolutize_original_styles', {
left: element.getStyle('left'),
top: element.getStyle('top'),
width: element.getStyle('width'),
height: element.getStyle('height')
});
element.setStyle({
position: 'absolute',
top: offset.top + 'px',
left: offset.left + 'px',
width: layout.get('width') + 'px',
height: layout.get('height') + 'px'
});
return element;
}
function relativize(element) {
element = $(element);
if (Element.getStyle(element, 'position') === 'relative') {
return element;
}
var originalStyles =
element.retrieve('prototype_absolutize_original_styles');
if (originalStyles) element.setStyle(originalStyles);
return element;
}
if (Prototype.Browser.IE) {
getOffsetParent = getOffsetParent.wrap(
function(proceed, element) {
element = $(element);
if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
return $(document.body);
var position = element.getStyle('position');
if (position !== 'static') return proceed(element);
element.setStyle({ position: 'relative' });
var value = proceed(element);
element.setStyle({ position: position });
return value;
}
);
positionedOffset = positionedOffset.wrap(function(proceed, element) {
element = $(element);
if (!element.parentNode) return new Element.Offset(0, 0);
var position = element.getStyle('position');
if (position !== 'static') return proceed(element);
var offsetParent = element.getOffsetParent();
if (offsetParent && offsetParent.getStyle('position') === 'fixed')
hasLayout(offsetParent);
element.setStyle({ position: 'relative' });
var value = proceed(element);
element.setStyle({ position: position });
return value;
});
} else if (Prototype.Browser.Webkit) {
cumulativeOffset = function(element) {
element = $(element);
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
if (element.offsetParent == document.body)
if (Element.getStyle(element, 'position') == 'absolute') break;
element = element.offsetParent;
} while (element);
return new Element.Offset(valueL, valueT);
};
}
Element.addMethods({
getLayout: getLayout,
measure: measure,
getDimensions: getDimensions,
getOffsetParent: getOffsetParent,
cumulativeOffset: cumulativeOffset,
positionedOffset: positionedOffset,
cumulativeScrollOffset: cumulativeScrollOffset,
viewportOffset: viewportOffset,
absolutize: absolutize,
relativize: relativize
});
function isBody(element) {
return element.nodeName.toUpperCase() === 'BODY';
}
function isHtml(element) {
return element.nodeName.toUpperCase() === 'HTML';
}
function isDocument(element) {
return element.nodeType === Node.DOCUMENT_NODE;
}
function isDetached(element) {
return element !== document.body &&
!Element.descendantOf(element, document.body);
}
if ('getBoundingClientRect' in document.documentElement) {
Element.addMethods({
viewportOffset: function(element) {
element = $(element);
if (isDetached(element)) return new Element.Offset(0, 0);
var rect = element.getBoundingClientRect(),
docEl = document.documentElement;
return new Element.Offset(rect.left - docEl.clientLeft,
rect.top - docEl.clientTop);
}
});
}
})();
window.$$ = function() {
var expression = $A(arguments).join(', ');
return Prototype.Selector.select(expression, document);
};
Prototype.Selector = (function() {
function select() {
throw new Error('Method "Prototype.Selector.select" must be defined.');
}
function match() {
throw new Error('Method "Prototype.Selector.match" must be defined.');
}
function find(elements, expression, index) {
index = index || 0;
var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;
for (i = 0; i < length; i++) {
if (match(elements[i], expression) && index == matchIndex++) {
return Element.extend(elements[i]);
}
}
}
function extendElements(elements) {
for (var i = 0, length = elements.length; i < length; i++) {
Element.extend(elements[i]);
}
return elements;
}
var K = Prototype.K;
return {
select: select,
match: match,
find: find,
extendElements: (Element.extend === K) ? K : extendElements,
extendElement: Element.extend
};
})();
Prototype._original_property = window.Sizzle;
/*!
* Sizzle CSS Selector Engine - v1.0
* Copyright 2009, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
* More information: http://sizzlejs.com/
*/
(function(){
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
done = 0,
toString = Object.prototype.toString,
hasDuplicate = false,
baseHasDuplicate = true;
[0, 0].sort(function(){
baseHasDuplicate = false;
return 0;
});
var Sizzle = function(selector, context, results, seed) {
results = results || [];
var origContext = context = context || document;
if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
return [];
}
if ( !selector || typeof selector !== "string" ) {
return results;
}
var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context),
soFar = selector;
while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
soFar = m[3];
parts.push( m[1] );
if ( m[2] ) {
extra = m[3];
break;
}
}
if ( parts.length > 1 && origPOS.exec( selector ) ) {
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
set = posProcess( parts[0] + parts[1], context );
} else {
set = Expr.relative[ parts[0] ] ?
[ context ] :
Sizzle( parts.shift(), context );
while ( parts.length ) {
selector = parts.shift();
if ( Expr.relative[ selector ] )
selector += parts.shift();
set = posProcess( selector, set );
}
}
} else {
if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
var ret = Sizzle.find( parts.shift(), context, contextXML );
context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
}
if ( context ) {
var ret = seed ?
{ expr: parts.pop(), set: makeArray(seed) } :
Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
if ( parts.length > 0 ) {
checkSet = makeArray(set);
} else {
prune = false;
}
while ( parts.length ) {
var cur = parts.pop(), pop = cur;
if ( !Expr.relative[ cur ] ) {
cur = "";
} else {
pop = parts.pop();
}
if ( pop == null ) {
pop = context;
}
Expr.relative[ cur ]( checkSet, pop, contextXML );
}
} else {
checkSet = parts = [];
}
}
if ( !checkSet ) {
checkSet = set;
}
if ( !checkSet ) {
throw "Syntax error, unrecognized expression: " + (cur || selector);
}
if ( toString.call(checkSet) === "[object Array]" ) {
if ( !prune ) {
results.push.apply( results, checkSet );
} else if ( context && context.nodeType === 1 ) {
for ( var i = 0; checkSet[i] != null; i++ ) {
if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
results.push( set[i] );
}
}
} else {
for ( var i = 0; checkSet[i] != null; i++ ) {
if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
results.push( set[i] );
}
}
}
} else {
makeArray( checkSet, results );
}
if ( extra ) {
Sizzle( extra, origContext, results, seed );
Sizzle.uniqueSort( results );
}
return results;
};
Sizzle.uniqueSort = function(results){
if ( sortOrder ) {
hasDuplicate = baseHasDuplicate;
results.sort(sortOrder);
if ( hasDuplicate ) {
for ( var i = 1; i < results.length; i++ ) {
if ( results[i] === results[i-1] ) {
results.splice(i--, 1);
}
}
}
}
return results;
};
Sizzle.matches = function(expr, set){
return Sizzle(expr, null, null, set);
};
Sizzle.find = function(expr, context, isXML){
var set, match;
if ( !expr ) {
return [];
}
for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
var type = Expr.order[i], match;
if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
var left = match[1];
match.splice(1,1);
if ( left.substr( left.length - 1 ) !== "\\" ) {
match[1] = (match[1] || "").replace(/\\/g, "");
set = Expr.find[ type ]( match, context, isXML );
if ( set != null ) {
expr = expr.replace( Expr.match[ type ], "" );
break;
}
}
}
}
if ( !set ) {
set = context.getElementsByTagName("*");
}
return {set: set, expr: expr};
};
Sizzle.filter = function(expr, set, inplace, not){
var old = expr, result = [], curLoop = set, match, anyFound,
isXMLFilter = set && set[0] && isXML(set[0]);
while ( expr && set.length ) {
for ( var type in Expr.filter ) {
if ( (match = Expr.match[ type ].exec( expr )) != null ) {
var filter = Expr.filter[ type ], found, item;
anyFound = false;
if ( curLoop == result ) {
result = [];
}
if ( E
gitextract_85pi0xyb/
├── .github/
│ ├── ISSUE_TEMPLATE.md
│ └── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .travis.yml
├── Gruntfile.coffee
├── LICENSE.md
├── README.md
├── coffee/
│ ├── chosen.jquery.coffee
│ ├── chosen.proto.coffee
│ └── lib/
│ ├── abstract-chosen.coffee
│ └── select-parser.coffee
├── composer.json
├── contributing.md
├── package-travis.yml
├── package.json
├── public/
│ ├── docsupport/
│ │ ├── init.js
│ │ ├── init.proto.js
│ │ ├── prism.css
│ │ ├── prism.js
│ │ ├── prototype-1.7.0.0.js
│ │ └── style.css
│ ├── index.html
│ ├── index.proto.html
│ └── options.html
├── publish-package.sh
├── sass/
│ └── chosen.scss
├── spec/
│ ├── jquery/
│ │ ├── basic.spec.coffee
│ │ ├── bugfixes.spec.coffee
│ │ ├── events.spec.coffee
│ │ ├── max_shown_results.spec.coffee
│ │ └── searching.spec.coffee
│ └── proto/
│ ├── basic.spec.coffee
│ ├── bugfixes.spec.coffee
│ ├── events.spec.coffee
│ ├── max_shown_results.spec.coffee
│ └── searching.spec.coffee
└── tasks/
└── package.coffee
SYMBOL INDEX (202 symbols across 1 files)
FILE: public/docsupport/prototype-1.7.0.0.js
function subclass (line 94) | function subclass() {}
function create (line 95) | function create() {
function addMethods (line 124) | function addMethods(source) {
function Type (line 180) | function Type(o) {
function extend (line 194) | function extend(destination, source) {
function inspect (line 200) | function inspect(object) {
function toJSON (line 211) | function toJSON(value) {
function Str (line 215) | function Str(key, holder, stack) {
function stringify (line 273) | function stringify(object) {
function toQueryString (line 277) | function toQueryString(object) {
function toHTML (line 281) | function toHTML(object) {
function keys (line 285) | function keys(object) {
function values (line 296) | function values(object) {
function clone (line 303) | function clone(object) {
function isElement (line 307) | function isElement(object) {
function isArray (line 311) | function isArray(object) {
function isHash (line 322) | function isHash(object) {
function isFunction (line 326) | function isFunction(object) {
function isString (line 330) | function isString(object) {
function isNumber (line 334) | function isNumber(object) {
function isDate (line 338) | function isDate(object) {
function isUndefined (line 342) | function isUndefined(object) {
function update (line 368) | function update(array, args) {
function merge (line 374) | function merge(array, args) {
function argumentNames (line 379) | function argumentNames() {
function bind (line 386) | function bind(context) {
function bindAsEventListener (line 395) | function bindAsEventListener(context) {
function curry (line 403) | function curry() {
function delay (line 412) | function delay(timeout) {
function defer (line 420) | function defer() {
function wrap (line 425) | function wrap(wrapper) {
function methodize (line 433) | function methodize() {
function toISOString (line 459) | function toISOString() {
function toJSON (line 469) | function toJSON() {
function prepareReplacement (line 539) | function prepareReplacement(replacement) {
function gsub (line 545) | function gsub(pattern, replacement) {
function sub (line 569) | function sub(pattern, replacement, count) {
function scan (line 579) | function scan(pattern, iterator) {
function truncate (line 584) | function truncate(length, truncation) {
function strip (line 591) | function strip() {
function stripTags (line 595) | function stripTags() {
function stripScripts (line 599) | function stripScripts() {
function extractScripts (line 603) | function extractScripts() {
function evalScripts (line 611) | function evalScripts() {
function escapeHTML (line 615) | function escapeHTML() {
function unescapeHTML (line 619) | function unescapeHTML() {
function toQueryParams (line 624) | function toQueryParams(separator) {
function toArray (line 645) | function toArray() {
function succ (line 649) | function succ() {
function times (line 654) | function times(count) {
function camelize (line 658) | function camelize() {
function capitalize (line 664) | function capitalize() {
function underscore (line 668) | function underscore() {
function dasherize (line 676) | function dasherize() {
function inspect (line 680) | function inspect(useDoubleQuotes) {
function unfilterJSON (line 691) | function unfilterJSON(filter) {
function isJSON (line 695) | function isJSON() {
function evalJSON (line 704) | function evalJSON(sanitize) {
function parseJSON (line 718) | function parseJSON() {
function include (line 723) | function include(pattern) {
function startsWith (line 727) | function startsWith(pattern) {
function endsWith (line 731) | function endsWith(pattern) {
function empty (line 736) | function empty() {
function blank (line 740) | function blank() {
function interpolate (line 744) | function interpolate(object, pattern) {
function each (line 821) | function each(iterator, context) {
function eachSlice (line 833) | function eachSlice(number, iterator, context) {
function all (line 841) | function all(iterator, context) {
function any (line 851) | function any(iterator, context) {
function collect (line 861) | function collect(iterator, context) {
function detect (line 870) | function detect(iterator, context) {
function findAll (line 881) | function findAll(iterator, context) {
function grep (line 890) | function grep(filter, iterator, context) {
function include (line 904) | function include(object) {
function inGroupsOf (line 918) | function inGroupsOf(number, fillWith) {
function inject (line 926) | function inject(memo, iterator, context) {
function invoke (line 933) | function invoke(method) {
function max (line 940) | function max(iterator, context) {
function min (line 951) | function min(iterator, context) {
function partition (line 962) | function partition(iterator, context) {
function pluck (line 972) | function pluck(property) {
function reject (line 980) | function reject(iterator, context) {
function sortBy (line 989) | function sortBy(iterator, context) {
function toArray (line 1001) | function toArray() {
function zip (line 1005) | function zip() {
function size (line 1016) | function size() {
function inspect (line 1020) | function inspect() {
function $A (line 1066) | function $A(iterable) {
function $w (line 1075) | function $w(string) {
function each (line 1089) | function each(iterator, context) {
function clear (line 1096) | function clear() {
function first (line 1101) | function first() {
function last (line 1105) | function last() {
function compact (line 1109) | function compact() {
function flatten (line 1115) | function flatten() {
function without (line 1124) | function without() {
function reverse (line 1131) | function reverse(inline) {
function uniq (line 1135) | function uniq(sorted) {
function intersect (line 1143) | function intersect(array) {
function clone (line 1150) | function clone() {
function size (line 1154) | function size() {
function inspect (line 1158) | function inspect() {
function indexOf (line 1162) | function indexOf(item, i) {
function lastIndexOf (line 1171) | function lastIndexOf(item, i) {
function concat (line 1177) | function concat() {
function $H (line 1222) | function $H(object) {
function initialize (line 1227) | function initialize(object) {
function _each (line 1232) | function _each(iterator) {
function set (line 1241) | function set(key, value) {
function get (line 1245) | function get(key) {
function unset (line 1250) | function unset(key) {
function toObject (line 1256) | function toObject() {
function keys (line 1262) | function keys() {
function values (line 1266) | function values() {
function index (line 1270) | function index(value) {
function merge (line 1277) | function merge(object) {
function update (line 1281) | function update(object) {
function toQueryPair (line 1288) | function toQueryPair(key, value) {
function toQueryString (line 1293) | function toQueryString() {
function inspect (line 1311) | function inspect() {
function clone (line 1317) | function clone() {
function toColorPart (line 1343) | function toColorPart() {
function succ (line 1347) | function succ() {
function times (line 1351) | function times(iterator, context) {
function toPaddedString (line 1356) | function toPaddedString(length, radix) {
function abs (line 1361) | function abs() {
function round (line 1365) | function round() {
function ceil (line 1369) | function ceil() {
function floor (line 1373) | function floor() {
function $R (line 1389) | function $R(start, end, exclusive) {
function initialize (line 1394) | function initialize(start, end, exclusive) {
function _each (line 1400) | function _each(iterator) {
function include (line 1408) | function include(value) {
function $ (line 1818) | function $(element) {
function shouldUseCache (line 1864) | function shouldUseCache(tagName, attributes) {
function update (line 2004) | function update(element, content) {
function stripAlpha (line 2560) | function stripAlpha(filter){
function _descendants (line 2722) | function _descendants(element) {
function checkDeficiency (line 2886) | function checkDeficiency(tagName) {
function extendElementWith (line 2902) | function extendElementWith(element, methods) {
function extend (line 2993) | function extend(tagName) {
function copy (line 3000) | function copy(methods, destination, onlyIfAbsent) {
function findDOMClass (line 3010) | function findDOMClass(tagName) {
function getRootElement (line 3077) | function getRootElement() {
function define (line 3087) | function define(D) {
function toDecimal (line 3180) | function toDecimal(pctString) {
function getPixelValue (line 3186) | function getPixelValue(value, property, context) {
function toCSSPixels (line 3246) | function toCSSPixels(number) {
function isDisplayed (line 3253) | function isDisplayed(element) {
function cssNameFor (line 3275) | function cssNameFor(key) {
function getLayout (line 3651) | function getLayout(element, preCompute) {
function measure (line 3655) | function measure(element, property) {
function getDimensions (line 3659) | function getDimensions(element) {
function getOffsetParent (line 3694) | function getOffsetParent(element) {
function cumulativeOffset (line 3713) | function cumulativeOffset(element) {
function positionedOffset (line 3726) | function positionedOffset(element) {
function cumulativeScrollOffset (line 3749) | function cumulativeScrollOffset(element) {
function viewportOffset (line 3759) | function viewportOffset(forElement) {
function absolutize (line 3781) | function absolutize(element) {
function relativize (line 3813) | function relativize(element) {
function isBody (line 3890) | function isBody(element) {
function isHtml (line 3894) | function isHtml(element) {
function isDocument (line 3898) | function isDocument(element) {
function isDetached (line 3902) | function isDetached(element) {
function select (line 3928) | function select() {
function match (line 3932) | function match() {
function find (line 3936) | function find(elements, expression, index) {
function extendElements (line 3947) | function extendElements(elements) {
function dirNodeCheck (line 4831) | function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
function dirCheck (line 4867) | function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
function select (line 4947) | function select(selector, scope) {
function match (line 4951) | function match(element, selector) {
function input (line 5176) | function input(element, value) {
function inputSelector (line 5186) | function inputSelector(element, value) {
function valueSelector (line 5192) | function valueSelector(element, value) {
function select (line 5197) | function select(element, value) {
function selectOne (line 5215) | function selectOne(element) {
function selectMany (line 5220) | function selectMany(element) {
function optionValue (line 5231) | function optionValue(opt) {
function _isButtonForDOMEvents (line 5372) | function _isButtonForDOMEvents(event, code) {
function _isButtonForLegacyEvents (line 5377) | function _isButtonForLegacyEvents(event, code) {
function _isButtonForWebKit (line 5381) | function _isButtonForWebKit(event, code) {
function isLeftClick (line 5405) | function isLeftClick(event) { return _isButton(event, 0) }
function isMiddleClick (line 5407) | function isMiddleClick(event) { return _isButton(event, 1) }
function isRightClick (line 5409) | function isRightClick(event) { return _isButton(event, 2) }
function element (line 5411) | function element(event) {
function findElement (line 5430) | function findElement(event, expression) {
function pointer (line 5442) | function pointer(event) {
function pointerX (line 5446) | function pointerX(event) {
function pointerY (line 5455) | function pointerY(event) {
function stop (line 5465) | function stop(event) {
function _relatedTarget (line 5495) | function _relatedTarget(event) {
function _createResponder (line 5549) | function _createResponder(element, eventName, handler) {
function _destroyCache (line 5608) | function _destroyCache() {
function observe (line 5633) | function observe(element, eventName, handler) {
function stopObserving (line 5659) | function stopObserving(element, eventName, handler) {
function fire (line 5712) | function fire(element, eventName, memo, bubble) {
function on (line 5766) | function on(element, eventName, selector, callback) {
function fireContentLoadedEvent (line 5816) | function fireContentLoadedEvent() {
function checkReadyState (line 5823) | function checkReadyState() {
function pollDoScroll (line 5830) | function pollDoScroll() {
function iter (line 5960) | function iter(name) {
Condensed preview — 37 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (518K chars).
[
{
"path": ".github/ISSUE_TEMPLATE.md",
"chars": 1416,
"preview": "<!---\nPlease read our Contributing Guidelines before opening this issue: https://github.com/harvesthq/chosen/blob/master"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 1276,
"preview": "<!---\nGood pull requests — patches, improvements, new features — are a fantastic help. They should remain focused in sc"
},
{
"path": ".gitignore",
"chars": 178,
"preview": ".DS_Store\nnode_modules\n.project\npublic/*.js\npublic/*.css\npublic/*.json\npublic/LICENSE.md\nchosen*.zip\n.sass-cache\n.ruby-v"
},
{
"path": ".travis.yml",
"chars": 454,
"preview": "sudo: false\n\nlanguage: node_js\n\nnode_js:\n - 6\n\naddons:\n apt:\n sources:\n - git-core\n packages:\n - git\n\n"
},
{
"path": "Gruntfile.coffee",
"chars": 4102,
"preview": "module.exports = (grunt) ->\n require('load-grunt-tasks')(grunt)\n grunt.loadNpmTasks('grunt1.0-dom-munger') # the namin"
},
{
"path": "LICENSE.md",
"chars": 1215,
"preview": "#### Chosen\n- by Patrick Filler for [Harvest](http://getharvest.com)\n- Copyright (c) 2011-2016 by Harvest\n\nAvailable for"
},
{
"path": "README.md",
"chars": 2144,
"preview": "# Deprecated\n\n#### This version of Chosen is not currently under active development while we decide on its future direct"
},
{
"path": "coffee/chosen.jquery.coffee",
"chars": 17795,
"preview": "$ = jQuery\n\n$.fn.extend({\n chosen: (options) ->\n # Do no harm and return as soon as possible for unsupported browser"
},
{
"path": "coffee/chosen.proto.coffee",
"chars": 17659,
"preview": "class @Chosen extends AbstractChosen\n\n setup: ->\n @current_selectedIndex = @form_field.selectedIndex\n\n set_up_html:"
},
{
"path": "coffee/lib/abstract-chosen.coffee",
"chars": 13162,
"preview": "class AbstractChosen\n\n constructor: (@form_field, @options={}) ->\n return unless AbstractChosen.browser_is_supported"
},
{
"path": "coffee/lib/select-parser.coffee",
"chars": 1665,
"preview": "class SelectParser\n\n constructor: ->\n @options_index = 0\n @parsed = []\n\n add_node: (child) ->\n if child.nodeN"
},
{
"path": "composer.json",
"chars": 819,
"preview": "{\n \"name\": \"harvesthq/chosen\",\n \"description\": \"Chosen is a JavaScript plugin that makes select boxes user-friendly. I"
},
{
"path": "contributing.md",
"chars": 9651,
"preview": "# Contributing to this project\n\nPlease take a moment to review this document in order to make the contribution\nprocess e"
},
{
"path": "package-travis.yml",
"chars": 817,
"preview": "sudo: false\n\nlanguage: node_js\n\nnode_js:\n - \"node\"\n\ndeploy:\n provider: npm\n email: chosenjs@getharvest.com\n api_key:"
},
{
"path": "package.json",
"chars": 2190,
"preview": "{\n \"author\": \"harvest\",\n \"name\": \"chosen\",\n \"version\": \"1.8.7\",\n \"description\": \"Chosen is a JavaScript plugin that "
},
{
"path": "public/docsupport/init.js",
"chars": 424,
"preview": "var config = {\n '.chosen-select' : {},\n '.chosen-select-deselect' : { allow_single_deselect: true },\n '.ch"
},
{
"path": "public/docsupport/init.proto.js",
"chars": 553,
"preview": "document.observe('dom:loaded', function(evt) {\n var config = {\n '.chosen-select' : {},\n '.chosen-select"
},
{
"path": "public/docsupport/prism.css",
"chars": 1492,
"preview": "/**\n * okaidia theme for JavaScript, CSS and HTML\n * Loosely based on Monokai textmate theme by http://www.monokai.nl/\n "
},
{
"path": "public/docsupport/prism.js",
"chars": 6659,
"preview": "/**\n * Prism: Lightweight, robust, elegant syntax highlighting\n * MIT license http://www.opensource.org/licenses/mit-lic"
},
{
"path": "public/docsupport/prototype-1.7.0.0.js",
"chars": 163313,
"preview": "/* Prototype JavaScript framework, version 1.7\n * (c) 2005-2010 Sam Stephenson\n *\n * Prototype is freely distributabl"
},
{
"path": "public/docsupport/style.css",
"chars": 7191,
"preview": "/* Reset */\nhtml, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code"
},
{
"path": "public/index.html",
"chars": 85357,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Chosen: A jQuery Plugin by Harvest to Tame Unw"
},
{
"path": "public/index.proto.html",
"chars": 85703,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Chosen: A Prototype Plugin by Harvest to Tame "
},
{
"path": "public/options.html",
"chars": 14140,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Chosen: A jQuery Plugin by Harvest to Tame Unw"
},
{
"path": "publish-package.sh",
"chars": 1116,
"preview": "#!/bin/sh\n\nset -e\n\nCURRENT_BRANCH=`git name-rev --name-only HEAD`\n\nif [ $CURRENT_BRANCH != 'master' ] ; then\n echo \"Bui"
},
{
"path": "sass/chosen.scss",
"chars": 9648,
"preview": "$chosen-sprite: url('chosen-sprite.png') !default;\n$chosen-sprite-retina: url('chosen-sprite@2x.png') !default;\n\n/* @gro"
},
{
"path": "spec/jquery/basic.spec.coffee",
"chars": 3073,
"preview": "describe \"Basic setup\", ->\n it \"should add chosen to jQuery object\", ->\n expect(jQuery.fn.chosen).toBeDefined()\n\n i"
},
{
"path": "spec/jquery/bugfixes.spec.coffee",
"chars": 990,
"preview": "describe \"Bugfixes\", ->\n it \"https://github.com/harvesthq/chosen/issues/2996 - XSS Vulnerability with `include_group_la"
},
{
"path": "spec/jquery/events.spec.coffee",
"chars": 1136,
"preview": "describe \"Events\", ->\n it \"chosen should fire the right events\", ->\n tmpl = \"\n <select data-placeholder='Choose"
},
{
"path": "spec/jquery/max_shown_results.spec.coffee",
"chars": 2375,
"preview": "describe \"search\", ->\n it \"should display only matching items when entering a search term\", ->\n tmpl = \"\n <"
},
{
"path": "spec/jquery/searching.spec.coffee",
"chars": 13313,
"preview": "describe \"Searching\", ->\n it \"should not match the actual text of HTML entities\", ->\n tmpl = \"\n <select data-pl"
},
{
"path": "spec/proto/basic.spec.coffee",
"chars": 3340,
"preview": "describe \"Basic setup\", ->\n it \"should add expose a Chosen global\", ->\n expect(Chosen).toBeDefined()\n\n it \"should c"
},
{
"path": "spec/proto/bugfixes.spec.coffee",
"chars": 1094,
"preview": "describe \"Bugfixes\", ->\n it \"https://github.com/harvesthq/chosen/issues/2996 - XSS Vulnerability with `include_group_la"
},
{
"path": "spec/proto/events.spec.coffee",
"chars": 1074,
"preview": "describe \"Events\", ->\n it \"chosen should fire the right events\", ->\n tmpl = \"\n <select data-placeholder='Choose"
},
{
"path": "spec/proto/max_shown_results.spec.coffee",
"chars": 2464,
"preview": "describe 'search', ->\n it 'should display only matching items when entering a search term', ->\n tmpl = '''\n <se"
},
{
"path": "spec/proto/searching.spec.coffee",
"chars": 10460,
"preview": "describe \"Searching\", ->\n it \"should not match the actual text of HTML entities\", ->\n tmpl = \"\n <select data-pl"
},
{
"path": "tasks/package.coffee",
"chars": 1888,
"preview": "###\nThis file contains tasks only necessary for packaging and publishing Chosen\n###\nmodule.exports = (grunt) ->\n\n grunt"
}
]
About this extraction
This page contains the full source code of the harvesthq/chosen GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 37 files (479.8 KB), approximately 123.1k tokens, and a symbol index with 202 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.