Commit 96b74bab274c9e6fefca0a57f7365789684b780a

Authored by Karpikau Andrei
1 parent b7aedd88

remove dummy app, add images

Too many changes to show.

To preserve performance only 25 of 103 files are displayed.

1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<Settings><!--This file was automatically generated by Ruby plugin.
3   -You are allowed to:
4   -1. Reorder generators
5   -2. Remove generators
6   -3. Add installed generators
7   -To add new installed generators automatically delete this file and reload the project.
8   ---><GeneratorsGroup><Generator name="active_record:devise" /><Generator name="assets" /><Generator name="controller" /><Generator name="delayed_job" /><Generator name="delayed_job:active_record" /><Generator name="delayed_job:upgrade" /><Generator name="devise" /><Generator name="devise:controllers" /><Generator name="devise:install" /><Generator name="devise:views" /><Generator name="factory_girl:model" /><Generator name="generator" /><Generator name="helper" /><Generator name="integration_test" /><Generator name="jbuilder" /><Generator name="job" /><Generator name="js:assets" /><Generator name="mailer" /><Generator name="migration" /><Generator name="model" /><Generator name="mongoid:devise" /><Generator name="resource" /><Generator name="responders:install" /><Generator name="responders_controller" /><Generator name="rspec:controller" /><Generator name="rspec:feature" /><Generator name="rspec:helper" /><Generator name="rspec:install" /><Generator name="rspec:integration" /><Generator name="rspec:job" /><Generator name="rspec:mailer" /><Generator name="rspec:model" /><Generator name="rspec:observer" /><Generator name="rspec:request" /><Generator name="rspec:scaffold" /><Generator name="rspec:view" /><Generator name="sass:assets" /><Generator name="scaffold" /><Generator name="scaffold_controller" /><Generator name="scss:assets" /><Generator name="task" /><Generator name="test_unit:generator" /><Generator name="test_unit:job" /><Generator name="test_unit:plugin" /></GeneratorsGroup></Settings>
1   -kanjai
\ No newline at end of file
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<Settings><!--This file was automatically generated by Ruby plugin.
3   -You are allowed to:
4   -1. Remove rake task
5   -2. Add existing rake tasks
6   -To add existing rake tasks automatically delete this file and reload the project.
7   ---><RakeGroup description="" fullCmd="" taksId="rake"><RakeGroup description="" fullCmd="" taksId="app"><RakeTask description="List versions of all Rails frameworks and the environment" fullCmd="app:about" taksId="about" /><RakeGroup description="" fullCmd="" taksId="assets"><RakeTask description="Remove old compiled assets" fullCmd="app:assets:clean[keep]" taksId="clean[keep]" /><RakeTask description="Remove compiled assets" fullCmd="app:assets:clobber" taksId="clobber" /><RakeTask description="Load asset compile environment" fullCmd="app:assets:environment" taksId="environment" /><RakeTask description="Compile all the assets named in config.assets.precompile" fullCmd="app:assets:precompile" taksId="precompile" /><RakeTask description="" fullCmd="app:assets:clean" taksId="clean" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="cache_digests"><RakeTask description="Lookup first-level dependencies for TEMPLATE (like messages/show or comments/_comment.html)" fullCmd="app:cache_digests:dependencies" taksId="dependencies" /><RakeTask description="Lookup nested dependencies for TEMPLATE (like messages/show or comments/_comment.html)" fullCmd="app:cache_digests:nested_dependencies" taksId="nested_dependencies" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="db"><RakeTask description="Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config)" fullCmd="app:db:create" taksId="create" /><RakeTask description="Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config)" fullCmd="app:db:drop" taksId="drop" /><RakeGroup description="" fullCmd="" taksId="fixtures"><RakeTask description="Load fixtures into the current environment's database" fullCmd="app:db:fixtures:load" taksId="load" /><RakeTask description="" fullCmd="app:db:fixtures:identify" taksId="identify" /></RakeGroup><RakeTask description="Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)" fullCmd="app:db:migrate" taksId="migrate" /><RakeGroup description="" fullCmd="" taksId="migrate"><RakeTask description="Display status of migrations" fullCmd="app:db:migrate:status" taksId="status" /><RakeTask description="" fullCmd="app:db:migrate:down" taksId="down" /><RakeTask description="" fullCmd="app:db:migrate:redo" taksId="redo" /><RakeTask description="" fullCmd="app:db:migrate:reset" taksId="reset" /><RakeTask description="" fullCmd="app:db:migrate:up" taksId="up" /></RakeGroup><RakeTask description="Rolls the schema back to the previous version (specify steps w/ STEP=n)" fullCmd="app:db:rollback" taksId="rollback" /><RakeGroup description="" fullCmd="" taksId="schema"><RakeGroup description="" fullCmd="" taksId="cache"><RakeTask description="Clear a db/schema_cache.dump file" fullCmd="app:db:schema:cache:clear" taksId="clear" /><RakeTask description="Create a db/schema_cache.dump file" fullCmd="app:db:schema:cache:dump" taksId="dump" /></RakeGroup><RakeTask description="Create a db/schema.rb file that is portable against any DB supported by AR" fullCmd="app:db:schema:dump" taksId="dump" /><RakeTask description="Load a schema.rb file into the database" fullCmd="app:db:schema:load" taksId="load" /><RakeTask description="" fullCmd="app:db:schema:load_if_ruby" taksId="load_if_ruby" /></RakeGroup><RakeTask description="Load the seed data from db/seeds.rb" fullCmd="app:db:seed" taksId="seed" /><RakeTask description="Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the database first)" fullCmd="app:db:setup" taksId="setup" /><RakeGroup description="" fullCmd="" taksId="structure"><RakeTask description="Dump the database structure to db/structure.sql" fullCmd="app:db:structure:dump" taksId="dump" /><RakeTask description="Recreate the databases from the structure.sql file" fullCmd="app:db:structure:load" taksId="load" /><RakeTask description="" fullCmd="app:db:structure:load_if_sql" taksId="load_if_sql" /></RakeGroup><RakeTask description="Retrieves the current schema version number" fullCmd="app:db:version" taksId="version" /><RakeTask description="" fullCmd="app:db:_dump" taksId="_dump" /><RakeTask description="" fullCmd="app:db:abort_if_pending_migrations" taksId="abort_if_pending_migrations" /><RakeTask description="" fullCmd="app:db:charset" taksId="charset" /><RakeTask description="" fullCmd="app:db:collation" taksId="collation" /><RakeGroup description="" fullCmd="" taksId="create"><RakeTask description="" fullCmd="app:db:create:all" taksId="all" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="drop"><RakeTask description="" fullCmd="app:db:drop:all" taksId="all" /></RakeGroup><RakeTask description="" fullCmd="app:db:forward" taksId="forward" /><RakeTask description="" fullCmd="app:db:load_config" taksId="load_config" /><RakeTask description="" fullCmd="app:db:purge" taksId="purge" /><RakeGroup description="" fullCmd="" taksId="purge"><RakeTask description="" fullCmd="app:db:purge:all" taksId="all" /></RakeGroup><RakeTask description="" fullCmd="app:db:reset" taksId="reset" /><RakeGroup description="" fullCmd="" taksId="test"><RakeTask description="" fullCmd="app:db:test:clone" taksId="clone" /><RakeTask description="" fullCmd="app:db:test:clone_schema" taksId="clone_schema" /><RakeTask description="" fullCmd="app:db:test:clone_structure" taksId="clone_structure" /><RakeTask description="" fullCmd="app:db:test:deprecated" taksId="deprecated" /><RakeTask description="" fullCmd="app:db:test:load" taksId="load" /><RakeTask description="" fullCmd="app:db:test:load_schema" taksId="load_schema" /><RakeTask description="" fullCmd="app:db:test:load_structure" taksId="load_structure" /><RakeTask description="" fullCmd="app:db:test:prepare" taksId="prepare" /><RakeTask description="" fullCmd="app:db:test:purge" taksId="purge" /></RakeGroup></RakeGroup><RakeGroup description="" fullCmd="" taksId="doc"><RakeTask description="Generate docs for the app -- also available doc:rails, doc:guides (options: TEMPLATE=/rdoc-template.rb, TITLE=&quot;Custom Title&quot;)" fullCmd="app:doc:app" taksId="app" /><RakeTask description="" fullCmd="app:doc:clobber" taksId="clobber" /><RakeTask description="" fullCmd="app:doc:clobber_app" taksId="clobber_app" /><RakeTask description="" fullCmd="app:doc:clobber_rails" taksId="clobber_rails" /><RakeTask description="" fullCmd="app:doc:guides" taksId="guides" /><RakeTask description="" fullCmd="app:doc:rails" taksId="rails" /><RakeTask description="" fullCmd="app:doc:reapp" taksId="reapp" /><RakeTask description="" fullCmd="app:doc:rerails" taksId="rerails" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="This task test soap" fullCmd="app:install:user" taksId="user" /><RakeTask description="" fullCmd="app:install:zip_example" taksId="zip_example" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="jobs"><RakeTask description="Exit with error status if any jobs older than max_age seconds haven't been attempted yet" fullCmd="app:jobs:check[max_age]" taksId="check[max_age]" /><RakeTask description="Clear the delayed_job queue" fullCmd="app:jobs:clear" taksId="clear" /><RakeTask description="Start a delayed_job worker" fullCmd="app:jobs:work" taksId="work" /><RakeTask description="Start a delayed_job worker and exit when all available jobs are complete" fullCmd="app:jobs:workoff" taksId="workoff" /><RakeTask description="" fullCmd="app:jobs:check" taksId="check" /><RakeTask description="" fullCmd="app:jobs:environment_options" taksId="environment_options" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="kanjai"><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="Copy migrations from kanjai to application" fullCmd="app:kanjai:install:migrations" taksId="migrations" /></RakeGroup></RakeGroup><RakeGroup description="" fullCmd="" taksId="log"><RakeTask description="Truncates all *.log files in log/ to zero bytes (specify which logs with LOGS=test,development)" fullCmd="app:log:clear" taksId="clear" /></RakeGroup><RakeTask description="Prints out your Rack middleware stack" fullCmd="app:middleware" taksId="middleware" /><RakeTask description="Enumerate all annotations (use notes:optimize, :fixme, :todo for focus)" fullCmd="app:notes" taksId="notes" /><RakeGroup description="" fullCmd="" taksId="notes"><RakeTask description="Enumerate a custom annotation, specify with ANNOTATION=CUSTOM" fullCmd="app:notes:custom" taksId="custom" /><RakeTask description="" fullCmd="app:notes:fixme" taksId="fixme" /><RakeTask description="" fullCmd="app:notes:optimize" taksId="optimize" /><RakeTask description="" fullCmd="app:notes:todo" taksId="todo" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="rails"><RakeTask description="Applies the template supplied by LOCATION=(/path/to/template) or URL" fullCmd="app:rails:template" taksId="template" /><RakeTask description="Update configs and some other initially generated files (or use just update:configs or update:bin)" fullCmd="app:rails:update" taksId="update" /><RakeGroup description="" fullCmd="" taksId="templates"><RakeTask description="" fullCmd="app:rails:templates:copy" taksId="copy" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="update"><RakeTask description="" fullCmd="app:rails:update:bin" taksId="bin" /><RakeTask description="" fullCmd="app:rails:update:configs" taksId="configs" /></RakeGroup></RakeGroup><RakeTask description="Print out all defined routes in match order, with names" fullCmd="app:routes" taksId="routes" /><RakeTask description="Generate a cryptographically secure secret key (this is typically used to generate a secret for cookie sessions)" fullCmd="app:secret" taksId="secret" /><RakeTask description="Runs all tests in test folder" fullCmd="app:test" taksId="test" /><RakeGroup description="" fullCmd="" taksId="test"><RakeTask description="Run tests quickly by merging all types and not resetting db" fullCmd="app:test:all" taksId="all" /><RakeGroup description="" fullCmd="" taksId="all"><RakeTask description="Run tests quickly, but also reset db" fullCmd="app:test:all:db" taksId="db" /></RakeGroup><RakeTask description="Run tests quickly, but also reset db" fullCmd="app:test:db" taksId="db" /><RakeTask description="" fullCmd="app:test:controllers" taksId="controllers" /><RakeTask description="" fullCmd="app:test:deprecate_all" taksId="deprecate_all" /><RakeTask description="" fullCmd="app:test:functionals" taksId="functionals" /><RakeTask description="" fullCmd="app:test:generators" taksId="generators" /><RakeTask description="" fullCmd="app:test:helpers" taksId="helpers" /><RakeTask description="" fullCmd="app:test:integration" taksId="integration" /><RakeTask description="" fullCmd="app:test:jobs" taksId="jobs" /><RakeTask description="" fullCmd="app:test:mailers" taksId="mailers" /><RakeTask description="" fullCmd="app:test:models" taksId="models" /><RakeTask description="" fullCmd="app:test:prepare" taksId="prepare" /><RakeTask description="" fullCmd="app:test:run" taksId="run" /><RakeTask description="" fullCmd="app:test:single" taksId="single" /><RakeTask description="" fullCmd="app:test:units" taksId="units" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="time"><RakeGroup description="" fullCmd="" taksId="zones"><RakeTask description="Displays all time zones, also available: time:zones:us, time:zones:local -- filter with OFFSET parameter, e.g., OFFSET=-6" fullCmd="app:time:zones:all" taksId="all" /><RakeTask description="" fullCmd="app:time:zones:local" taksId="local" /><RakeTask description="" fullCmd="app:time:zones:us" taksId="us" /></RakeGroup></RakeGroup><RakeGroup description="" fullCmd="" taksId="tmp"><RakeTask description="Clear session, cache, and socket files from tmp/ (narrow w/ tmp:sessions:clear, tmp:cache:clear, tmp:sockets:clear)" fullCmd="app:tmp:clear" taksId="clear" /><RakeTask description="Creates tmp directories for sessions, cache, sockets, and pids" fullCmd="app:tmp:create" taksId="create" /><RakeGroup description="" fullCmd="" taksId="cache"><RakeTask description="" fullCmd="app:tmp:cache:clear" taksId="clear" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="pids"><RakeTask description="" fullCmd="app:tmp:pids:clear" taksId="clear" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="sessions"><RakeTask description="" fullCmd="app:tmp:sessions:clear" taksId="clear" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="sockets"><RakeTask description="" fullCmd="app:tmp:sockets:clear" taksId="clear" /></RakeGroup></RakeGroup><RakeTask description="" fullCmd="app:default" taksId="default" /><RakeTask description="" fullCmd="app:environment" taksId="environment" /><RakeGroup description="" fullCmd="" taksId="railties"><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="" fullCmd="app:railties:install:migrations" taksId="migrations" /></RakeGroup></RakeGroup></RakeGroup><RakeTask description="Build kanjai-0.0.25.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Remove RDoc HTML files" fullCmd="clobber_rdoc" taksId="clobber_rdoc" /><RakeGroup description="" fullCmd="" taksId="db"><RakeTask description="Create the database from config/database.yml for the current Rails.env (use db:create:all to create all databases in the config)" fullCmd="db:create" taksId="create" /><RakeTask description="Drops the database for the current Rails.env (use db:drop:all to drop all databases)" fullCmd="db:drop" taksId="drop" /><RakeGroup description="" fullCmd="" taksId="fixtures"><RakeTask description="Load fixtures into the current environment's database" fullCmd="db:fixtures:load" taksId="load" /></RakeGroup><RakeTask description="Migrate the database (options: VERSION=x, VERBOSE=false)" fullCmd="db:migrate" taksId="migrate" /><RakeGroup description="" fullCmd="" taksId="migrate"><RakeTask description="Display status of migrations" fullCmd="db:migrate:status" taksId="status" /><RakeTask description="" fullCmd="db:migrate:down" taksId="down" /><RakeTask description="" fullCmd="db:migrate:redo" taksId="redo" /><RakeTask description="" fullCmd="db:migrate:reset" taksId="reset" /><RakeTask description="" fullCmd="db:migrate:up" taksId="up" /></RakeGroup><RakeTask description="Rolls the schema back to the previous version (specify steps w/ STEP=n)" fullCmd="db:rollback" taksId="rollback" /><RakeGroup description="" fullCmd="" taksId="schema"><RakeTask description="Create a db/schema.rb file that can be portably used against any DB supported by AR" fullCmd="db:schema:dump" taksId="dump" /><RakeTask description="Load a schema.rb file into the database" fullCmd="db:schema:load" taksId="load" /></RakeGroup><RakeTask description="Load the seed data from db/seeds.rb" fullCmd="db:seed" taksId="seed" /><RakeTask description="Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the db first)" fullCmd="db:setup" taksId="setup" /><RakeGroup description="" fullCmd="" taksId="structure"><RakeTask description="Dump the database structure to an SQL file" fullCmd="db:structure:dump" taksId="dump" /></RakeGroup><RakeTask description="Retrieves the current schema version number" fullCmd="db:version" taksId="version" /><RakeGroup description="" fullCmd="" taksId="create"><RakeTask description="" fullCmd="db:create:all" taksId="all" /></RakeGroup><RakeGroup description="" fullCmd="" taksId="drop"><RakeTask description="" fullCmd="db:drop:all" taksId="all" /></RakeGroup><RakeTask description="" fullCmd="db:reset" taksId="reset" /></RakeGroup><RakeTask description="Build and install kanjai-0.0.25.gem into system gems" fullCmd="install" taksId="install" /><RakeTask description="Build RDoc HTML files" fullCmd="rdoc" taksId="rdoc" /><RakeTask description="Create tag v0.0.25 and build and push kanjai-0.0.25.gem to Rubygems" fullCmd="release" taksId="release" /><RakeTask description="Rebuild RDoc HTML files" fullCmd="rerdoc" taksId="rerdoc" /><RakeTask description="Report code statistics (KLOCs, etc) from the application or engine" fullCmd="stats" taksId="stats" /><RakeTask description="Run tests" fullCmd="test" taksId="test" /><RakeTask description="" fullCmd="clobber" taksId="clobber" /><RakeTask description="" fullCmd="default" taksId="default" /><RakeTask description="" fullCmd="doc" taksId="doc" /><RakeTask description="" fullCmd="doc/app" taksId="doc/app" /><RakeTask description="" fullCmd="doc/app/created.rid" taksId="doc/app/created.rid" /><RakeTask description="" fullCmd="environment" taksId="environment" /><RakeTask description="" fullCmd="html" taksId="html" /><RakeTask description="" fullCmd="html/created.rid" taksId="html/created.rid" /><RakeTask description="" fullCmd="load_app" taksId="load_app" /><RakeTask description="" fullCmd="rdoc/created.rid" taksId="rdoc/created.rid" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup><RakeTask description="" fullCmd="tmp" taksId="tmp" /><RakeTask description="" fullCmd="tmp/cache" taksId="tmp/cache" /><RakeTask description="" fullCmd="tmp/cache/assets" taksId="tmp/cache/assets" /><RakeTask description="" fullCmd="tmp/cache/assets/development" taksId="tmp/cache/assets/development" /><RakeTask description="" fullCmd="tmp/cache/assets/production" taksId="tmp/cache/assets/production" /><RakeTask description="" fullCmd="tmp/cache/assets/test" taksId="tmp/cache/assets/test" /><RakeTask description="" fullCmd="tmp/pids" taksId="tmp/pids" /><RakeTask description="" fullCmd="tmp/sessions" taksId="tmp/sessions" /><RakeTask description="" fullCmd="tmp/sockets" taksId="tmp/sockets" /></RakeGroup></Settings>
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<project version="4">
3   - <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
4   -</project>
\ No newline at end of file
1   -<component name="InspectionProjectProfileManager">
2   - <profile version="1.0" is_locked="false">
3   - <option name="myName" value="Project Default" />
4   - <inspection_tool class="Rubocop" enabled="false" level="WARNING" enabled_by_default="false" />
5   - </profile>
6   -</component>
\ No newline at end of file
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<module type="RUBY_MODULE" version="4">
3   - <component name="FacetManager">
4   - <facet type="RailsFacetType" name="Ruby on Rails">
5   - <configuration>
6   - <RAILS_FACET_CONFIG_ID NAME="RAILS_FACET_SUPPORT_REMOVED" VALUE="false" />
7   - <RAILS_FACET_CONFIG_ID NAME="RAILS_TESTS_SOURCES_PATCHED" VALUE="true" />
8   - <RAILS_FACET_CONFIG_ID NAME="RAILS_FACET_APPLICATION_ROOT" VALUE="$MODULE_DIR$" />
9   - </configuration>
10   - </facet>
11   - <facet type="gem" name="Ruby Gem">
12   - <configuration />
13   - </facet>
14   - </component>
15   - <component name="ModuleRunConfigurationManager">
16   - <shared>
17   - <configuration default="false" name="test: kanjai" type="RakeRunConfigurationType" factoryName="Rake">
18   - <module name="kanjai" />
19   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="" />
20   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="WORK DIR" VALUE="$MODULE_DIR$" />
21   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="SHOULD_USE_SDK" VALUE="false" />
22   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="ALTERN_SDK_NAME" VALUE="" />
23   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="myPassParentEnvs" VALUE="true" />
24   - <envs>
25   - <env name="RAILS_ENV" value="test" />
26   - </envs>
27   - <EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="false" />
28   - <EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
29   - <EXTENSION ID="RubyCoverageRunConfigurationExtension" track_test_folders="true" runner="rcov">
30   - <COVERAGE_PATTERN ENABLED="true">
31   - <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
32   - </COVERAGE_PATTERN>
33   - </EXTENSION>
34   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_NAME" VALUE="test" />
35   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_ARGS" VALUE="" />
36   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_ATTACHED_TEST_FRAMEWORKS" VALUE=":test_unit " />
37   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_TRACE" VALUE="false" />
38   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_DRYRUN" VALUE="false" />
39   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_PREREQS" VALUE="false" />
40   - <method v="2" />
41   - </configuration>
42   - <configuration default="false" name="spec: kanjai" type="RakeRunConfigurationType" factoryName="Rake">
43   - <module name="kanjai" />
44   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="" />
45   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="WORK DIR" VALUE="$MODULE_DIR$" />
46   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="SHOULD_USE_SDK" VALUE="false" />
47   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="ALTERN_SDK_NAME" VALUE="" />
48   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="myPassParentEnvs" VALUE="true" />
49   - <EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="false" />
50   - <EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
51   - <EXTENSION ID="RubyCoverageRunConfigurationExtension" track_test_folders="true" runner="rcov">
52   - <COVERAGE_PATTERN ENABLED="true">
53   - <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
54   - </COVERAGE_PATTERN>
55   - </EXTENSION>
56   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_NAME" VALUE="spec" />
57   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_ARGS" VALUE="" />
58   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_ATTACHED_TEST_FRAMEWORKS" VALUE=":rspec " />
59   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_TRACE" VALUE="false" />
60   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_DRYRUN" VALUE="false" />
61   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_PREREQS" VALUE="false" />
62   - <method v="2" />
63   - </configuration>
64   - <configuration default="false" name="Production: kanjai" type="RailsRunConfigurationType" factoryName="Rails">
65   - <predefined_log_file id="RUBY_RAILS_SERVER" enabled="true" />
66   - <module name="kanjai" />
67   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="" />
68   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="WORK DIR" VALUE="$MODULE_DIR$" />
69   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="SHOULD_USE_SDK" VALUE="false" />
70   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="ALTERN_SDK_NAME" VALUE="" />
71   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="myPassParentEnvs" VALUE="true" />
72   - <EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="false" />
73   - <EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
74   - <EXTENSION ID="RubyCoverageRunConfigurationExtension" track_test_folders="true" runner="rcov">
75   - <COVERAGE_PATTERN ENABLED="true">
76   - <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
77   - </COVERAGE_PATTERN>
78   - </EXTENSION>
79   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="SCRIPT_ARGS" VALUE="" />
80   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="PORT" VALUE="3000" />
81   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="IP" VALUE="0.0.0.0" />
82   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="DUMMY_APP" VALUE="test/dummy" />
83   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="RAILS_SERVER_TYPE" VALUE="Default" />
84   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="ENVIRONMENT_TYPE" VALUE="production" />
85   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="LAUNCH_JS" VALUE="false" />
86   - <method v="2" />
87   - </configuration>
88   - <configuration default="false" name="Development: kanjai" type="RailsRunConfigurationType" factoryName="Rails">
89   - <predefined_log_file id="RUBY_RAILS_SERVER" enabled="true" />
90   - <module name="kanjai" />
91   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="" />
92   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="WORK DIR" VALUE="$MODULE_DIR$" />
93   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="SHOULD_USE_SDK" VALUE="false" />
94   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="ALTERN_SDK_NAME" VALUE="" />
95   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="myPassParentEnvs" VALUE="true" />
96   - <EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="false" />
97   - <EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
98   - <EXTENSION ID="RubyCoverageRunConfigurationExtension" track_test_folders="true" runner="rcov">
99   - <COVERAGE_PATTERN ENABLED="true">
100   - <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
101   - </COVERAGE_PATTERN>
102   - </EXTENSION>
103   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="SCRIPT_ARGS" VALUE="" />
104   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="PORT" VALUE="3000" />
105   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="IP" VALUE="0.0.0.0" />
106   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="DUMMY_APP" VALUE="test/dummy" />
107   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="RAILS_SERVER_TYPE" VALUE="Default" />
108   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="ENVIRONMENT_TYPE" VALUE="development" />
109   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="LAUNCH_JS" VALUE="false" />
110   - <method v="2" />
111   - </configuration>
112   - </shared>
113   - </component>
114   - <component name="NewModuleRootManager">
115   - <content url="file://$MODULE_DIR$">
116   - <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
117   - </content>
118   - <orderEntry type="jdk" jdkName="rbenv: 2.1.3" jdkType="RUBY_SDK" />
119   - <orderEntry type="sourceFolder" forTests="false" />
120   - <orderEntry type="library" scope="PROVIDED" name="actionmailer (v4.2.6, rbenv: 2.1.3) [gem]" level="application" />
121   - <orderEntry type="library" scope="PROVIDED" name="actionpack (v4.2.6, rbenv: 2.1.3) [gem]" level="application" />
122   - <orderEntry type="library" scope="PROVIDED" name="actionview (v4.2.6, rbenv: 2.1.3) [gem]" level="application" />
123   - <orderEntry type="library" scope="PROVIDED" name="activejob (v4.2.6, rbenv: 2.1.3) [gem]" level="application" />
124   - <orderEntry type="library" scope="PROVIDED" name="activemodel (v4.2.6, rbenv: 2.1.3) [gem]" level="application" />
125   - <orderEntry type="library" scope="PROVIDED" name="activerecord (v4.2.6, rbenv: 2.1.3) [gem]" level="application" />
126   - <orderEntry type="library" scope="PROVIDED" name="activesupport (v4.2.6, rbenv: 2.1.3) [gem]" level="application" />
127   - <orderEntry type="library" scope="PROVIDED" name="acts_as_list (v0.9.5, rbenv: 2.1.3) [gem]" level="application" />
128   - <orderEntry type="library" scope="PROVIDED" name="acts_as_tree (v2.7.0, rbenv: 2.1.3) [gem]" level="application" />
129   - <orderEntry type="library" scope="PROVIDED" name="arel (v6.0.4, rbenv: 2.1.3) [gem]" level="application" />
130   - <orderEntry type="library" scope="PROVIDED" name="aws-sdk (v2.6.32, rbenv: 2.1.3) [gem]" level="application" />
131   - <orderEntry type="library" scope="PROVIDED" name="aws-sdk-core (v2.6.32, rbenv: 2.1.3) [gem]" level="application" />
132   - <orderEntry type="library" scope="PROVIDED" name="aws-sdk-resources (v2.6.32, rbenv: 2.1.3) [gem]" level="application" />
133   - <orderEntry type="library" scope="PROVIDED" name="aws-sigv4 (v1.0.2, rbenv: 2.1.3) [gem]" level="application" />
134   - <orderEntry type="library" scope="PROVIDED" name="backport_new_renderer (v1.0.0, rbenv: 2.1.3) [gem]" level="application" />
135   - <orderEntry type="library" scope="PROVIDED" name="bcrypt (v3.1.11, rbenv: 2.1.3) [gem]" level="application" />
136   - <orderEntry type="library" scope="PROVIDED" name="builder (v3.2.2, rbenv: 2.1.3) [gem]" level="application" />
137   - <orderEntry type="library" scope="PROVIDED" name="bundler (v1.9.0, rbenv: 2.1.3) [gem]" level="application" />
138   - <orderEntry type="library" scope="PROVIDED" name="concurrent-ruby (v1.0.5, rbenv: 2.1.3) [gem]" level="application" />
139   - <orderEntry type="library" scope="PROVIDED" name="daemons (v1.2.6, rbenv: 2.1.3) [gem]" level="application" />
140   - <orderEntry type="library" scope="PROVIDED" name="delayed_job (v4.1.4, rbenv: 2.1.3) [gem]" level="application" />
141   - <orderEntry type="library" scope="PROVIDED" name="delayed_job_active_record (v4.1.2, rbenv: 2.1.3) [gem]" level="application" />
142   - <orderEntry type="library" scope="PROVIDED" name="devise (v4.4.0, rbenv: 2.1.3) [gem]" level="application" />
143   - <orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.2.5, rbenv: 2.1.3) [gem]" level="application" />
144   - <orderEntry type="library" scope="PROVIDED" name="erubis (v2.7.0, rbenv: 2.1.3) [gem]" level="application" />
145   - <orderEntry type="library" scope="PROVIDED" name="execjs (v2.7.0, rbenv: 2.1.3) [gem]" level="application" />
146   - <orderEntry type="library" scope="PROVIDED" name="factory_girl (v4.7.0, rbenv: 2.1.3) [gem]" level="application" />
147   - <orderEntry type="library" scope="PROVIDED" name="factory_girl_rails (v4.8.0, rbenv: 2.1.3) [gem]" level="application" />
148   - <orderEntry type="library" scope="PROVIDED" name="ffi (v1.9.14, rbenv: 2.1.3) [gem]" level="application" />
149   - <orderEntry type="library" scope="PROVIDED" name="globalid (v0.4.1, rbenv: 2.1.3) [gem]" level="application" />
150   - <orderEntry type="library" scope="PROVIDED" name="i18n (v0.7.0, rbenv: 2.1.3) [gem]" level="application" />
151   - <orderEntry type="library" scope="PROVIDED" name="jbuilder (v2.7.0, rbenv: 2.1.3) [gem]" level="application" />
152   - <orderEntry type="library" scope="PROVIDED" name="jmespath (v1.3.1, rbenv: 2.1.3) [gem]" level="application" />
153   - <orderEntry type="library" scope="PROVIDED" name="jquery-rails (v3.1.2, rbenv: 2.1.3) [gem]" level="application" />
154   - <orderEntry type="library" scope="PROVIDED" name="json (v1.8.3, rbenv: 2.1.3) [gem]" level="application" />
155   - <orderEntry type="library" scope="PROVIDED" name="libv8 (v3.16.14.19, rbenv: 2.1.3) [gem]" level="application" />
156   - <orderEntry type="library" scope="PROVIDED" name="loofah (v2.0.3, rbenv: 2.1.3) [gem]" level="application" />
157   - <orderEntry type="library" scope="PROVIDED" name="mail (v2.7.0, rbenv: 2.1.3) [gem]" level="application" />
158   - <orderEntry type="library" scope="PROVIDED" name="mini_mime (v1.0.0, rbenv: 2.1.3) [gem]" level="application" />
159   - <orderEntry type="library" scope="PROVIDED" name="mini_portile (v0.5.3, rbenv: 2.1.3) [gem]" level="application" />
160   - <orderEntry type="library" scope="PROVIDED" name="minitest (v5.8.4, rbenv: 2.1.3) [gem]" level="application" />
161   - <orderEntry type="library" scope="PROVIDED" name="multi_json (v1.13.1, rbenv: 2.1.3) [gem]" level="application" />
162   - <orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.6.1, rbenv: 2.1.3) [gem]" level="application" />
163   - <orderEntry type="library" scope="PROVIDED" name="orm_adapter (v0.5.0, rbenv: 2.1.3) [gem]" level="application" />
164   - <orderEntry type="library" scope="PROVIDED" name="pg (v0.17.1, rbenv: 2.1.3) [gem]" level="application" />
165   - <orderEntry type="library" scope="PROVIDED" name="rack (v1.6.4, rbenv: 2.1.3) [gem]" level="application" />
166   - <orderEntry type="library" scope="PROVIDED" name="rack-test (v0.6.3, rbenv: 2.1.3) [gem]" level="application" />
167   - <orderEntry type="library" scope="PROVIDED" name="rails (v4.2.7.1, rbenv: 2.1.3) [gem]" level="application" />
168   - <orderEntry type="library" scope="PROVIDED" name="rails-deprecated_sanitizer (v1.0.3, rbenv: 2.1.3) [gem]" level="application" />
169   - <orderEntry type="library" scope="PROVIDED" name="rails-dom-testing (v1.0.7, rbenv: 2.1.3) [gem]" level="application" />
170   - <orderEntry type="library" scope="PROVIDED" name="rails-html-sanitizer (v1.0.3, rbenv: 2.1.3) [gem]" level="application" />
171   - <orderEntry type="library" scope="PROVIDED" name="rails_12factor (v0.0.3, rbenv: 2.1.3) [gem]" level="application" />
172   - <orderEntry type="library" scope="PROVIDED" name="rails_serve_static_assets (v0.0.5, rbenv: 2.1.3) [gem]" level="application" />
173   - <orderEntry type="library" scope="PROVIDED" name="rails_stdout_logging (v0.0.5, rbenv: 2.1.3) [gem]" level="application" />
174   - <orderEntry type="library" scope="PROVIDED" name="railties (v4.2.6, rbenv: 2.1.3) [gem]" level="application" />
175   - <orderEntry type="library" scope="PROVIDED" name="rake (v11.1.2, rbenv: 2.1.3) [gem]" level="application" />
176   - <orderEntry type="library" scope="PROVIDED" name="rb-fsevent (v0.10.2, rbenv: 2.1.3) [gem]" level="application" />
177   - <orderEntry type="library" scope="PROVIDED" name="rb-inotify (v0.9.10, rbenv: 2.1.3) [gem]" level="application" />
178   - <orderEntry type="library" scope="PROVIDED" name="rdoc (v4.3.0, rbenv: 2.1.3) [gem]" level="application" />
179   - <orderEntry type="library" scope="PROVIDED" name="ref (v2.0.0, rbenv: 2.1.3) [gem]" level="application" />
180   - <orderEntry type="library" scope="PROVIDED" name="responders (v2.4.0, rbenv: 2.1.3) [gem]" level="application" />
181   - <orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.4.4, rbenv: 2.1.3) [gem]" level="application" />
182   - <orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.4.0, rbenv: 2.1.3) [gem]" level="application" />
183   - <orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.4.1, rbenv: 2.1.3) [gem]" level="application" />
184   - <orderEntry type="library" scope="PROVIDED" name="rspec-rails (v3.4.2, rbenv: 2.1.3) [gem]" level="application" />
185   - <orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.4.1, rbenv: 2.1.3) [gem]" level="application" />
186   - <orderEntry type="library" scope="PROVIDED" name="sass (v3.5.5, rbenv: 2.1.3) [gem]" level="application" />
187   - <orderEntry type="library" scope="PROVIDED" name="sass-listen (v4.0.0, rbenv: 2.1.3) [gem]" level="application" />
188   - <orderEntry type="library" scope="PROVIDED" name="sass-rails (v5.0.7, rbenv: 2.1.3) [gem]" level="application" />
189   - <orderEntry type="library" scope="PROVIDED" name="sdoc (v0.4.2, rbenv: 2.1.3) [gem]" level="application" />
190   - <orderEntry type="library" scope="PROVIDED" name="sprockets (v3.7.1, rbenv: 2.1.3) [gem]" level="application" />
191   - <orderEntry type="library" scope="PROVIDED" name="sprockets-rails (v3.2.1, rbenv: 2.1.3) [gem]" level="application" />
192   - <orderEntry type="library" scope="PROVIDED" name="therubyracer (v0.12.2, rbenv: 2.1.3) [gem]" level="application" />
193   - <orderEntry type="library" scope="PROVIDED" name="thor (v0.19.1, rbenv: 2.1.3) [gem]" level="application" />
194   - <orderEntry type="library" scope="PROVIDED" name="thread_safe (v0.3.5, rbenv: 2.1.3) [gem]" level="application" />
195   - <orderEntry type="library" scope="PROVIDED" name="tilt (v2.0.8, rbenv: 2.1.3) [gem]" level="application" />
196   - <orderEntry type="library" scope="PROVIDED" name="tzinfo (v1.2.2, rbenv: 2.1.3) [gem]" level="application" />
197   - <orderEntry type="library" scope="PROVIDED" name="uglifier (v4.1.3, rbenv: 2.1.3) [gem]" level="application" />
198   - <orderEntry type="library" scope="PROVIDED" name="warden (v1.2.7, rbenv: 2.1.3) [gem]" level="application" />
199   - </component>
200   - <component name="RModuleSettingsStorage">
201   - <LOAD_PATH number="0" />
202   - <I18N_FOLDERS number="1" string0="$MODULE_DIR$/config/locales" />
203   - </component>
204   -</module>
\ No newline at end of file
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<project version="4">
3   - <component name="ProjectRootManager" version="2" project-jdk-name="rbenv: 1.8.7-p375" project-jdk-type="RUBY_SDK" />
4   -</project>
\ No newline at end of file
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<project version="4">
3   - <component name="ProjectModuleManager">
4   - <modules>
5   - <module fileurl="file://$PROJECT_DIR$/.idea/kanjai.iml" filepath="$PROJECT_DIR$/.idea/kanjai.iml" />
6   - </modules>
7   - </component>
8   -</project>
\ No newline at end of file
1   -<component name="ProjectRunConfigurationManager">
2   - <configuration default="false" name="Development: kanjai" type="RailsRunConfigurationType" factoryName="Rails">
3   - <predefined_log_file id="RUBY_RAILS_SERVER" enabled="true" />
4   - <module name="kanjai" />
5   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
6   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="WORK DIR" VALUE="$MODULE_DIR$" />
7   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="SHOULD_USE_SDK" VALUE="false" />
8   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="ALTERN_SDK_NAME" VALUE="" />
9   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="myPassParentEnvs" VALUE="true" />
10   - <envs />
11   - <EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="false" />
12   - <EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
13   - <EXTENSION ID="RubyCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" track_test_folders="true" runner="rcov">
14   - <COVERAGE_PATTERN ENABLED="true">
15   - <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
16   - </COVERAGE_PATTERN>
17   - </EXTENSION>
18   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="SCRIPT_ARGS" VALUE="" />
19   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="PORT" VALUE="3000" />
20   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="IP" VALUE="0.0.0.0" />
21   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="DUMMY_APP" VALUE="test/dummy" />
22   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="RAILS_SERVER_TYPE" VALUE="Default" />
23   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="ENVIRONMENT_TYPE" VALUE="development" />
24   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="LAUNCH_JS" VALUE="false" />
25   - <method />
26   - </configuration>
27   -</component>
\ No newline at end of file
1   -<component name="ProjectRunConfigurationManager">
2   - <configuration default="false" name="Production: kanjai" type="RailsRunConfigurationType" factoryName="Rails">
3   - <predefined_log_file id="RUBY_RAILS_SERVER" enabled="true" />
4   - <module name="kanjai" />
5   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
6   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="WORK DIR" VALUE="$MODULE_DIR$" />
7   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="SHOULD_USE_SDK" VALUE="false" />
8   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="ALTERN_SDK_NAME" VALUE="" />
9   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="myPassParentEnvs" VALUE="true" />
10   - <envs />
11   - <EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="false" />
12   - <EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
13   - <EXTENSION ID="RubyCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" track_test_folders="true" runner="rcov">
14   - <COVERAGE_PATTERN ENABLED="true">
15   - <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
16   - </COVERAGE_PATTERN>
17   - </EXTENSION>
18   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="SCRIPT_ARGS" VALUE="" />
19   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="PORT" VALUE="3000" />
20   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="IP" VALUE="0.0.0.0" />
21   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="DUMMY_APP" VALUE="test/dummy" />
22   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="RAILS_SERVER_TYPE" VALUE="Default" />
23   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="ENVIRONMENT_TYPE" VALUE="production" />
24   - <RAILS_SERVER_CONFIG_SETTINGS_ID NAME="LAUNCH_JS" VALUE="false" />
25   - <method />
26   - </configuration>
27   -</component>
\ No newline at end of file
1   -<component name="ProjectRunConfigurationManager">
2   - <configuration default="false" name="spec: kanjai" type="RakeRunConfigurationType" factoryName="Rake">
3   - <module name="kanjai" />
4   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
5   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="WORK DIR" VALUE="$MODULE_DIR$" />
6   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="SHOULD_USE_SDK" VALUE="false" />
7   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="ALTERN_SDK_NAME" VALUE="" />
8   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="myPassParentEnvs" VALUE="true" />
9   - <envs />
10   - <EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="false" />
11   - <EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
12   - <EXTENSION ID="RubyCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" track_test_folders="true" runner="rcov">
13   - <COVERAGE_PATTERN ENABLED="true">
14   - <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
15   - </COVERAGE_PATTERN>
16   - </EXTENSION>
17   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_NAME" VALUE="spec" />
18   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_ARGS" VALUE="" />
19   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_ATTACHED_TEST_FRAMEWORKS" VALUE=":rspec " />
20   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_TRACE" VALUE="false" />
21   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_DRYRUN" VALUE="false" />
22   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_PREREQS" VALUE="false" />
23   - <method />
24   - </configuration>
25   -</component>
\ No newline at end of file
1   -<component name="ProjectRunConfigurationManager">
2   - <configuration default="false" name="test: kanjai" type="RakeRunConfigurationType" factoryName="Rake">
3   - <module name="kanjai" />
4   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="-e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift)" />
5   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="WORK DIR" VALUE="$MODULE_DIR$" />
6   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="SHOULD_USE_SDK" VALUE="false" />
7   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="ALTERN_SDK_NAME" VALUE="" />
8   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="myPassParentEnvs" VALUE="true" />
9   - <envs>
10   - <env name="RAILS_ENV" value="test" />
11   - </envs>
12   - <EXTENSION ID="BundlerRunConfigurationExtension" bundleExecEnabled="false" />
13   - <EXTENSION ID="JRubyRunConfigurationExtension" NailgunExecEnabled="false" />
14   - <EXTENSION ID="RubyCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" track_test_folders="true" runner="rcov">
15   - <COVERAGE_PATTERN ENABLED="true">
16   - <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
17   - </COVERAGE_PATTERN>
18   - </EXTENSION>
19   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_NAME" VALUE="test" />
20   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_ARGS" VALUE="" />
21   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_ATTACHED_TEST_FRAMEWORKS" VALUE=":test_unit " />
22   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_TRACE" VALUE="false" />
23   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_DRYRUN" VALUE="false" />
24   - <RAKE_RUN_CONFIG_SETTINGS_ID NAME="RAKE_TASK_OPTION_PREREQS" VALUE="false" />
25   - <method />
26   - </configuration>
27   -</component>
\ No newline at end of file
1   -<component name="DependencyValidationManager">
2   - <state>
3   - <option name="SKIP_IMPORT_STATEMENTS" value="false" />
4   - </state>
5   -</component>
\ No newline at end of file
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<project version="4">
3   - <component name="VcsDirectoryMappings">
4   - <mapping directory="$PROJECT_DIR$" vcs="Git" />
5   - </component>
6   -</project>
\ No newline at end of file
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<project version="4">
3   - <component name="ChangeListManager">
4   - <list default="true" id="cbbcb0f9-d203-4967-aa4d-c08a939c7df0" name="Default" comment="">
5   - <change beforePath="$PROJECT_DIR$/.idea/kanjai.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/kanjai.iml" afterDir="false" />
6   - <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
7   - <change beforePath="$PROJECT_DIR$/Gemfile.lock" beforeDir="false" afterPath="$PROJECT_DIR$/Gemfile.lock" afterDir="false" />
8   - </list>
9   - <ignored path="kanjai.iws" />
10   - <ignored path=".idea/workspace.xml" />
11   - <ignored path=".idea/dataSources.local.xml" />
12   - <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
13   - <option name="SHOW_DIALOG" value="false" />
14   - <option name="HIGHLIGHT_CONFLICTS" value="true" />
15   - <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
16   - <option name="LAST_RESOLUTION" value="IGNORE" />
17   - </component>
18   - <component name="CreatePatchCommitExecutor">
19   - <option name="PATCH_PATH" value="" />
20   - </component>
21   - <component name="FUSProjectUsageTrigger">
22   - <session id="1963050572">
23   - <usages-collector id="statistics.lifecycle.project">
24   - <counts>
25   - <entry key="project.closed" value="1" />
26   - <entry key="project.open.time.8" value="1" />
27   - <entry key="project.open.time.9" value="1" />
28   - <entry key="project.opened" value="2" />
29   - </counts>
30   - </usages-collector>
31   - </session>
32   - </component>
33   - <component name="FavoritesManager">
34   - <favorites_list name="kanjai" />
35   - </component>
36   - <component name="FileEditorManager">
37   - <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
38   - <file pinned="false" current-in-tab="false">
39   - <entry file="file://$PROJECT_DIR$/config/initializers/aws.rb">
40   - <provider selected="true" editor-type-id="text-editor">
41   - <state relative-caret-position="75">
42   - <caret line="5" column="57" selection-start-line="5" selection-start-column="41" selection-end-line="5" selection-end-column="57" />
43   - </state>
44   - </provider>
45   - </entry>
46   - </file>
47   - <file pinned="false" current-in-tab="false">
48   - <entry file="file://$PROJECT_DIR$/lib/kanjai/template_generator.rb">
49   - <provider selected="true" editor-type-id="text-editor">
50   - <state relative-caret-position="3390">
51   - <caret line="226" column="42" selection-start-line="226" selection-start-column="23" selection-end-line="226" selection-end-column="42" />
52   - </state>
53   - </provider>
54   - </entry>
55   - </file>
56   - <file pinned="false" current-in-tab="false">
57   - <entry file="file://$PROJECT_DIR$/app/controllers/kanjai/pages_controller.rb">
58   - <provider selected="true" editor-type-id="text-editor">
59   - <state relative-caret-position="465">
60   - <caret line="31" selection-start-line="31" selection-end-line="31" />
61   - </state>
62   - </provider>
63   - </entry>
64   - </file>
65   - <file pinned="false" current-in-tab="true">
66   - <entry file="file://$PROJECT_DIR$/lib/kanjai/version.rb">
67   - <provider selected="true" editor-type-id="text-editor">
68   - <state relative-caret-position="45">
69   - <caret line="3" selection-start-line="3" selection-end-line="3" />
70   - </state>
71   - </provider>
72   - </entry>
73   - </file>
74   - <file pinned="false" current-in-tab="false">
75   - <entry file="file://$PROJECT_DIR$/Gemfile.lock">
76   - <provider selected="true" editor-type-id="text-editor">
77   - <state relative-caret-position="795">
78   - <caret line="53" column="13" selection-start-line="53" selection-start-column="13" selection-end-line="53" selection-end-column="13" />
79   - </state>
80   - </provider>
81   - </entry>
82   - </file>
83   - <file pinned="false" current-in-tab="false">
84   - <entry file="file://$PROJECT_DIR$/config/initializers/devise.rb">
85   - <provider selected="true" editor-type-id="text-editor">
86   - <state relative-caret-position="90">
87   - <caret line="6" column="46" selection-start-line="6" selection-start-column="22" selection-end-line="6" selection-end-column="46" />
88   - </state>
89   - </provider>
90   - </entry>
91   - </file>
92   - <file pinned="false" current-in-tab="false">
93   - <entry file="file://$PROJECT_DIR$/config/initializers/admin.rb">
94   - <provider selected="true" editor-type-id="text-editor">
95   - <state relative-caret-position="45">
96   - <caret line="3" column="46" selection-start-line="3" selection-start-column="46" selection-end-line="3" selection-end-column="46" />
97   - </state>
98   - </provider>
99   - </entry>
100   - </file>
101   - <file pinned="false" current-in-tab="false">
102   - <entry file="file://$PROJECT_DIR$/lib/kanjai.rb">
103   - <provider selected="true" editor-type-id="text-editor" />
104   - </entry>
105   - </file>
106   - <file pinned="false" current-in-tab="false">
107   - <entry file="file://$PROJECT_DIR$/lib/kanjai/engine.rb">
108   - <provider selected="true" editor-type-id="text-editor" />
109   - </entry>
110   - </file>
111   - <file pinned="false" current-in-tab="false">
112   - <entry file="file://$PROJECT_DIR$/db/migrate/20160707115443_add_show_public_only_to_kanjai_pages.rb">
113   - <provider selected="true" editor-type-id="text-editor">
114   - <state relative-caret-position="30">
115   - <caret line="2" column="73" selection-start-line="2" selection-start-column="4" selection-end-line="2" selection-end-column="73" />
116   - </state>
117   - </provider>
118   - </entry>
119   - </file>
120   - </leaf>
121   - </component>
122   - <component name="FindInProjectRecents">
123   - <findStrings>
124   - <find>check_p</find>
125   - <find>check_permission</find>
126   - <find>admin_email</find>
127   - <find>INCLUDE_JS_FILE</find>
128   - <find>files = $.makeArray(fileInput.prop('files'));</find>
129   - <find>If the files property is not available, the browser does</find>
130   - <find>If the files property is not available, the browser does not</find>
131   - <find>if (cookieValue.length &gt; 0) break</find>
132   - <find>Extracts flash array stored in cookie and clears</find>
133   - <find>UnobtrusiveFlash</find>
134   - <find>pa</find>
135   - <find>paper</find>
136   - <find>S3_BUCKET</find>
137   - <find>fil</find>
138   - <find>fileuploa</find>
139   - <find>fileupload</find>
140   - <find>help-block</find>
141   - <find>unzip_c</find>
142   - <find>page_template</find>
143   - <find>setTemplateContent</find>
144   - <find>form</find>
145   - <find>###FORM_ACTION###</find>
146   - <find>form_subject</find>
147   - <find>def get_marker_type</find>
148   - <find>sqlite3</find>
149   - <find>sqli</find>
150   - <find>show_public_only</find>
151   - <find>UserSession</find>
152   - <find>User</find>
153   - <find>KANJAI_DOMAIN</find>
154   - </findStrings>
155   - <dirStrings>
156   - <dir>$PROJECT_DIR$/app/controllers</dir>
157   - <dir>$PROJECT_DIR$/app/assets/javascripts</dir>
158   - <dir>$PROJECT_DIR$</dir>
159   - <dir>$PROJECT_DIR$/app</dir>
160   - </dirStrings>
161   - </component>
162   - <component name="Git.Settings">
163   - <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
164   - </component>
165   - <component name="IdeDocumentHistory">
166   - <option name="CHANGED_PATHS">
167   - <list>
168   - <option value="$PROJECT_DIR$/app/assets/stylesheets/kanjai/fileinput.css" />
169   - <option value="$PROJECT_DIR$/app/assets/stylesheets/kanjai/frontend.css.scss" />
170   - <option value="$PROJECT_DIR$/app/assets/javascripts/kanjai/frontend.js" />
171   - <option value="$PROJECT_DIR$/app/assets/javascripts/kanjai/admin/html_generator.js" />
172   - <option value="$PROJECT_DIR$/app/assets/javascripts/kanjai/frontend/html_editor.js" />
173   - <option value="$PROJECT_DIR$/db/migrate/20160804133136_add_image_link_to_kanjai_images.rb" />
174   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/pages/get_gallery.html.erb" />
175   - <option value="$PROJECT_DIR$/app/assets/stylesheets/kanjai/admin/admin.css.scss" />
176   - <option value="$PROJECT_DIR$/app/models/kanjai/image.rb" />
177   - <option value="$PROJECT_DIR$/app/models/kanjai/page.rb" />
178   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/pages/_gallery_exist_images.html.erb" />
179   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/pages/gallery.html.erb" />
180   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/pages/update_gallery.js.erb" />
181   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/pages/_preview.html.erb" />
182   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/pages/delete_gallery_image.js.erb" />
183   - <option value="$PROJECT_DIR$/app/assets/stylesheets/kanjai/general_admin.css.scss" />
184   - <option value="$PROJECT_DIR$/app/helpers/kanjai/admin/pages_helper.rb" />
185   - <option value="$PROJECT_DIR$/lib/kanjai/content_function.rb" />
186   - <option value="$PROJECT_DIR$/app/views/kanjai/pages/show.pdf.erb" />
187   - <option value="$PROJECT_DIR$/app/assets/javascripts/kanjai/admin/admin.js" />
188   - <option value="$PROJECT_DIR$/lib/zip.rb" />
189   - <option value="$PROJECT_DIR$/app/views/layouts/kanjai/admin.html.erb" />
190   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/admin_users/index.html.erb" />
191   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/admin_users/new.html.erb" />
192   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/admin_users/_form.html.erb" />
193   - <option value="$PROJECT_DIR$/app/controllers/kanjai/admin/admin_users_controller.rb" />
194   - <option value="$PROJECT_DIR$/config/locales/en.yml" />
195   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/admin_users/edit.html.erb" />
196   - <option value="$PROJECT_DIR$/app/controllers/kanjai/admin_controller.rb" />
197   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/pages/show_editor.html.erb" />
198   - <option value="$PROJECT_DIR$/db/migrate/20171214071607_add_form_data_to_page_content_marker.rb" />
199   - <option value="$PROJECT_DIR$/app/models/kanjai/page_content.rb" />
200   - <option value="$PROJECT_DIR$/config/routes.rb" />
201   - <option value="$PROJECT_DIR$/app/mailers/application_mailer.rb" />
202   - <option value="$PROJECT_DIR$/db/migrate/20171214092747_add_from_to_mai_to_page_content_marker.rb" />
203   - <option value="$PROJECT_DIR$/app/mailers/kanjai_mailer.rb" />
204   - <option value="$PROJECT_DIR$/app/views/kanjai_mailer/send_mail.html.erb" />
205   - <option value="$PROJECT_DIR$/db/migrate/20171214094525_add_answer_text_to_page_content_marker.rb" />
206   - <option value="$PROJECT_DIR$/app/controllers/kanjai/admin/pages_controller.rb" />
207   - <option value="$PROJECT_DIR$/app/controllers/kanjai/form_controller.rb" />
208   - <option value="$PROJECT_DIR$/kanjai.gemspec" />
209   - <option value="$PROJECT_DIR$/app/controllers/kanjai/site_controller.rb" />
210   - <option value="$PROJECT_DIR$/app/assets/javascripts/kanjai/admin/jquery.fileupload.js" />
211   - <option value="$PROJECT_DIR$/app/models/kanjai/page_template.rb" />
212   - <option value="$PROJECT_DIR$/app/views/kanjai/pages/show.html.erb" />
213   - <option value="$PROJECT_DIR$/lib/kanjai/template_generator.rb" />
214   - <option value="$PROJECT_DIR$/app/views/kanjai/admin/pages/content_types/_content.html.erb" />
215   - <option value="$PROJECT_DIR$/config/initializers/devise.rb" />
216   - <option value="$PROJECT_DIR$/app/controllers/kanjai/pages_controller.rb" />
217   - <option value="$PROJECT_DIR$/config/initializers/admin.rb" />
218   - <option value="$PROJECT_DIR$/lib/kanjai/version.rb" />
219   - </list>
220   - </option>
221   - </component>
222   - <component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
223   - <component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
224   - <component name="JsGulpfileManager">
225   - <detection-done>true</detection-done>
226   - <sorting>DEFINITION_ORDER</sorting>
227   - </component>
228   - <component name="ProjectFrameBounds" extendedState="6">
229   - <option name="y" value="23" />
230   - <option name="width" value="1280" />
231   - <option name="height" value="728" />
232   - </component>
233   - <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
234   - <component name="ProjectView">
235   - <navigator proportions="" version="1">
236   - <foldersAlwaysOnTop value="true" />
237   - </navigator>
238   - <panes>
239   - <pane id="ProjectPane">
240   - <subPane>
241   - <expand>
242   - <path>
243   - <item name="kanjai" type="b2602c69:ProjectViewProjectNode" />
244   - <item name="kanjai" type="462c0819:PsiDirectoryNode" />
245   - </path>
246   - <path>
247   - <item name="kanjai" type="b2602c69:ProjectViewProjectNode" />
248   - <item name="kanjai" type="462c0819:PsiDirectoryNode" />
249   - <item name="config" type="462c0819:PsiDirectoryNode" />
250   - </path>
251   - <path>
252   - <item name="kanjai" type="b2602c69:ProjectViewProjectNode" />
253   - <item name="kanjai" type="462c0819:PsiDirectoryNode" />
254   - <item name="config" type="462c0819:PsiDirectoryNode" />
255   - <item name="initializers" type="462c0819:PsiDirectoryNode" />
256   - </path>
257   - <path>
258   - <item name="kanjai" type="b2602c69:ProjectViewProjectNode" />
259   - <item name="kanjai" type="462c0819:PsiDirectoryNode" />
260   - <item name="lib" type="462c0819:PsiDirectoryNode" />
261   - </path>
262   - <path>
263   - <item name="kanjai" type="b2602c69:ProjectViewProjectNode" />
264   - <item name="kanjai" type="462c0819:PsiDirectoryNode" />
265   - <item name="lib" type="462c0819:PsiDirectoryNode" />
266   - <item name="kanjai" type="462c0819:PsiDirectoryNode" />
267   - </path>
268   - <path>
269   - <item name="kanjai" type="b2602c69:ProjectViewProjectNode" />
270   - <item name="kanjai" type="462c0819:PsiDirectoryNode" />
271   - <item name="lib" type="462c0819:PsiDirectoryNode" />
272   - <item name="tasks" type="462c0819:PsiDirectoryNode" />
273   - </path>
274   - </expand>
275   - <select />
276   - </subPane>
277   - </pane>
278   - <pane id="Scope" />
279   - <pane id="RailsProjectView" />
280   - </panes>
281   - </component>
282   - <component name="PropertiesComponent">
283   - <property name="HbShouldOpenHtmlAsHb" value="" />
284   - <property name="WebServerToolWindowFactoryState" value="false" />
285   - <property name="last_opened_file_path" value="$PROJECT_DIR$" />
286   - <property name="recentsLimit" value="5" />
287   - </component>
288   - <component name="RecentsManager">
289   - <key name="MoveFile.RECENT_KEYS">
290   - <recent name="$PROJECT_DIR$/app/assets/images/kanjai/fileinput" />
291   - <recent name="$PROJECT_DIR$/app/assets/stylesheets/kanjai" />
292   - <recent name="$PROJECT_DIR$/app/assets/javascripts/kanjai/lib" />
293   - </key>
294   - <key name="CopyFile.RECENT_KEYS">
295   - <recent name="$PROJECT_DIR$/app/mailers" />
296   - <recent name="$PROJECT_DIR$/app/views/kanjai/admin/admin_users" />
297   - <recent name="$PROJECT_DIR$/config/initializers" />
298   - <recent name="$PROJECT_DIR$/bin" />
299   - <recent name="$PROJECT_DIR$/app/assets/stylesheets/kanjai/general" />
300   - </key>
301   - </component>
302   - <component name="RunDashboard">
303   - <option name="ruleStates">
304   - <list>
305   - <RuleState>
306   - <option name="name" value="ConfigurationTypeDashboardGroupingRule" />
307   - </RuleState>
308   - <RuleState>
309   - <option name="name" value="StatusDashboardGroupingRule" />
310   - </RuleState>
311   - </list>
312   - </option>
313   - </component>
314   - <component name="RunManager" selected="Rails.Development: kanjai">
315   - <configuration default="true" type="js.build_tools.gulp" factoryName="Gulp.js">
316   - <node-interpreter>project</node-interpreter>
317   - <node-options />
318   - <gulpfile />
319   - <tasks />
320   - <arguments />
321   - <pass-parent-envs>true</pass-parent-envs>
322   - <method v="2" />
323   - </configuration>
324   - <list>
325   - <item itemvalue="Rake.test: kanjai" />
326   - <item itemvalue="Rake.spec: kanjai" />
327   - <item itemvalue="Rails.Production: kanjai" />
328   - <item itemvalue="Rails.Development: kanjai" />
329   - </list>
330   - </component>
331   - <component name="SpringUtil" SPRING_PRE_LOADER_OPTION="true" />
332   - <component name="SvnConfiguration">
333   - <configuration />
334   - </component>
335   - <component name="TaskManager">
336   - <task active="true" id="Default" summary="Default task">
337   - <changelist id="cbbcb0f9-d203-4967-aa4d-c08a939c7df0" name="Default" comment="" />
338   - <created>1461667396774</created>
339   - <option name="number" value="Default" />
340   - <option name="presentableId" value="Default" />
341   - <updated>1461667396774</updated>
342   - <workItem from="1494966983627" duration="731000" />
343   - <workItem from="1495090952619" duration="1573000" />
344   - <workItem from="1495108372095" duration="2000" />
345   - <workItem from="1498808617180" duration="1037000" />
346   - <workItem from="1498836423959" duration="4000" />
347   - <workItem from="1500931211896" duration="152000" />
348   - <workItem from="1500931637579" duration="304000" />
349   - <workItem from="1501482504677" duration="10000" />
350   - <workItem from="1513232887722" duration="10776000" />
351   - <workItem from="1513283335284" duration="121000" />
352   - <workItem from="1513543303254" duration="7193000" />
353   - <workItem from="1516654861781" duration="654000" />
354   - <workItem from="1519076359527" duration="5272000" />
355   - <workItem from="1519386347440" duration="1120000" />
356   - <workItem from="1519477125017" duration="2000" />
357   - <workItem from="1521110918867" duration="606000" />
358   - <workItem from="1521116413044" duration="527000" />
359   - <workItem from="1521124710073" duration="38000" />
360   - <workItem from="1522062575414" duration="786000" />
361   - <workItem from="1524563703669" duration="29000" />
362   - <workItem from="1524565240546" duration="602000" />
363   - <workItem from="1526849333726" duration="2848000" />
364   - <workItem from="1526898064400" duration="244000" />
365   - <workItem from="1526992788869" duration="3744000" />
366   - <workItem from="1527228957742" duration="663000" />
367   - <workItem from="1527239274712" duration="965000" />
368   - <workItem from="1527250151106" duration="1359000" />
369   - <workItem from="1528795289630" duration="58000" />
370   - <workItem from="1528797772730" duration="2306000" />
371   - <workItem from="1528983596909" duration="231000" />
372   - <workItem from="1528984727408" duration="942000" />
373   - <workItem from="1529067232509" duration="427000" />
374   - <workItem from="1529134009751" duration="477000" />
375   - <workItem from="1530563947793" duration="325000" />
376   - <workItem from="1532497382207" duration="775000" />
377   - <workItem from="1532528310773" duration="526000" />
378   - <workItem from="1532617523201" duration="881000" />
379   - <workItem from="1533023763618" duration="569000" />
380   - <workItem from="1533043884272" duration="812000" />
381   - <workItem from="1536316862776" duration="652000" />
382   - <workItem from="1536432181981" duration="68000" />
383   - </task>
384   - <servers />
385   - </component>
386   - <component name="TimeTrackingManager">
387   - <option name="totallyTimeSpent" value="50411000" />
388   - </component>
389   - <component name="ToolWindowManager">
390   - <frame x="0" y="23" width="1280" height="728" extended-state="6" />
391   - <layout>
392   - <window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.3861066" />
393   - <window_info id="Structure" order="1" side_tool="true" weight="0.25" />
394   - <window_info id="Favorites" order="2" side_tool="true" />
395   - <window_info anchor="bottom" id="Message" order="0" />
396   - <window_info anchor="bottom" id="Find" order="1" weight="0.32930514" />
397   - <window_info anchor="bottom" id="Run" order="2" />
398   - <window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
399   - <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
400   - <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
401   - <window_info anchor="bottom" id="TODO" order="6" />
402   - <window_info anchor="bottom" id="Changes" order="7" />
403   - <window_info anchor="bottom" id="Terminal" order="8" />
404   - <window_info anchor="bottom" id="Version Control" order="9" />
405   - <window_info anchor="bottom" id="Event Log" order="10" side_tool="true" weight="0.32930514" />
406   - <window_info anchor="bottom" id="Application Servers" order="11" />
407   - <window_info anchor="bottom" id="Messages" order="12" weight="0.32930514" />
408   - <window_info anchor="bottom" id="Docker" order="13" show_stripe_button="false" />
409   - <window_info anchor="bottom" id="Database Changes" order="14" show_stripe_button="false" />
410   - <window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
411   - <window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
412   - <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
413   - <window_info anchor="right" id="Database" order="3" />
414   - </layout>
415   - </component>
416   - <component name="TypeScriptGeneratedFilesManager">
417   - <option name="version" value="1" />
418   - </component>
419   - <component name="Vcs.Log.UiProperties">
420   - <option name="RECENTLY_FILTERED_USER_GROUPS">
421   - <collection />
422   - </option>
423   - <option name="RECENTLY_FILTERED_BRANCH_GROUPS">
424   - <collection />
425   - </option>
426   - </component>
427   - <component name="VcsContentAnnotationSettings">
428   - <option name="myLimit" value="2678400000" />
429   - </component>
430   - <component name="editorHistoryManager">
431   - <entry file="file://$PROJECT_DIR$/kanjai.gemspec">
432   - <provider selected="true" editor-type-id="text-editor">
433   - <state relative-caret-position="300">
434   - <caret line="20" column="41" selection-start-line="20" selection-start-column="41" selection-end-line="20" selection-end-column="41" />
435   - </state>
436   - </provider>
437   - </entry>
438   - <entry file="file://$PROJECT_DIR$/app/models/kanjai/page_content.rb">
439   - <provider selected="true" editor-type-id="text-editor">
440   - <state relative-caret-position="2115">
441   - <caret line="141" column="119" selection-start-line="141" selection-start-column="119" selection-end-line="141" selection-end-column="119" />
442   - </state>
443   - </provider>
444   - </entry>
445   - <entry file="file://$PROJECT_DIR$/app/views/kanjai/pages/show.html.erb">
446   - <provider selected="true" editor-type-id="text-editor">
447   - <state relative-caret-position="15">
448   - <caret line="1" column="27" selection-start-line="1" selection-start-column="27" selection-end-line="1" selection-end-column="27" />
449   - </state>
450   - </provider>
451   - </entry>
452   - <entry file="file://$PROJECT_DIR$/config/routes.rb">
453   - <provider selected="true" editor-type-id="text-editor">
454   - <state relative-caret-position="855">
455   - <caret line="57" column="32" selection-start-line="57" selection-start-column="17" selection-end-line="57" selection-end-column="32" />
456   - </state>
457   - </provider>
458   - </entry>
459   - <entry file="file://$PROJECT_DIR$/app/views/kanjai_mailer/send_mail.html.erb">
460   - <provider selected="true" editor-type-id="text-editor">
461   - <state relative-caret-position="45">
462   - <caret line="3" column="11" selection-start-line="3" selection-start-column="3" selection-end-line="3" selection-end-column="11" />
463   - </state>
464   - </provider>
465   - </entry>
466   - <entry file="file://$PROJECT_DIR$/app/mailers/kanjai_mailer.rb">
467   - <provider selected="true" editor-type-id="text-editor">
468   - <state relative-caret-position="60">
469   - <caret line="4" column="5" selection-start-line="4" selection-start-column="5" selection-end-line="4" selection-end-column="5" />
470   - </state>
471   - </provider>
472   - </entry>
473   - <entry file="file://$PROJECT_DIR$/app/controllers/kanjai/form_controller.rb">
474   - <provider selected="true" editor-type-id="text-editor">
475   - <state relative-caret-position="75">
476   - <caret line="5" column="44" selection-start-line="5" selection-start-column="32" selection-end-line="5" selection-end-column="44" />
477   - </state>
478   - </provider>
479   - </entry>
480   - <entry file="file://$PROJECT_DIR$/app/models/kanjai/page_content_marker.rb">
481   - <provider selected="true" editor-type-id="text-editor">
482   - <state relative-caret-position="255">
483   - <caret line="17" column="65" selection-start-line="17" selection-start-column="53" selection-end-line="17" selection-end-column="65" />
484   - </state>
485   - </provider>
486   - </entry>
487   - <entry file="file://$PROJECT_DIR$/app/views/kanjai/admin/pages/content_types/_content.html.erb">
488   - <provider selected="true" editor-type-id="text-editor">
489   - <state relative-caret-position="15">
490   - <caret line="1" column="121" selection-start-line="1" selection-start-column="121" selection-end-line="1" selection-end-column="121" />
491   - </state>
492   - </provider>
493   - </entry>
494   - <entry file="file://$PROJECT_DIR$/app/controllers/kanjai/admin/page_templates_controller.rb">
495   - <provider selected="true" editor-type-id="text-editor">
496   - <state relative-caret-position="1500">
497   - <caret line="100" column="21" selection-start-line="100" selection-start-column="6" selection-end-line="100" selection-end-column="21" />
498   - </state>
499   - </provider>
500   - </entry>
501   - <entry file="file://$PROJECT_DIR$/app/models/kanjai/page_template.rb">
502   - <provider selected="true" editor-type-id="text-editor">
503   - <state relative-caret-position="1815">
504   - <caret line="121" column="28" selection-start-line="121" selection-start-column="28" selection-end-line="121" selection-end-column="28" />
505   - </state>
506   - </provider>
507   - </entry>
508   - <entry file="file://$PROJECT_DIR$/app/assets/javascripts/kanjai/admin/admin.js">
509   - <provider selected="true" editor-type-id="text-editor">
510   - <state relative-caret-position="2295">
511   - <caret line="153" column="51" selection-start-line="153" selection-start-column="27" selection-end-line="153" selection-end-column="51" />
512   - </state>
513   - </provider>
514   - </entry>
515   - <entry file="file://$PROJECT_DIR$/.ruby-version">
516   - <provider selected="true" editor-type-id="text-editor">
517   - <state>
518   - <caret column="5" selection-end-column="5" />
519   - </state>
520   - </provider>
521   - </entry>
522   - <entry file="file://$PROJECT_DIR$/config/initializers/aws.rb">
523   - <provider selected="true" editor-type-id="text-editor">
524   - <state relative-caret-position="75">
525   - <caret line="5" column="57" selection-start-line="5" selection-start-column="41" selection-end-line="5" selection-end-column="57" />
526   - </state>
527   - </provider>
528   - </entry>
529   - <entry file="file://$PROJECT_DIR$/lib/kanjai/template_generator.rb">
530   - <provider selected="true" editor-type-id="text-editor">
531   - <state relative-caret-position="3390">
532   - <caret line="226" column="42" selection-start-line="226" selection-start-column="23" selection-end-line="226" selection-end-column="42" />
533   - </state>
534   - </provider>
535   - </entry>
536   - <entry file="file://$PROJECT_DIR$/app/controllers/kanjai/pages_controller.rb">
537   - <provider selected="true" editor-type-id="text-editor">
538   - <state relative-caret-position="465">
539   - <caret line="31" selection-start-line="31" selection-end-line="31" />
540   - </state>
541   - </provider>
542   - </entry>
543   - <entry file="file://$PROJECT_DIR$/Gemfile.lock">
544   - <provider selected="true" editor-type-id="text-editor">
545   - <state relative-caret-position="795">
546   - <caret line="53" column="13" selection-start-line="53" selection-start-column="13" selection-end-line="53" selection-end-column="13" />
547   - </state>
548   - </provider>
549   - </entry>
550   - <entry file="file://$PROJECT_DIR$/config/initializers/devise.rb">
551   - <provider selected="true" editor-type-id="text-editor">
552   - <state relative-caret-position="90">
553   - <caret line="6" column="46" selection-start-line="6" selection-start-column="22" selection-end-line="6" selection-end-column="46" />
554   - </state>
555   - </provider>
556   - </entry>
557   - <entry file="file://$PROJECT_DIR$/config/initializers/admin.rb">
558   - <provider selected="true" editor-type-id="text-editor">
559   - <state relative-caret-position="45">
560   - <caret line="3" column="46" selection-start-line="3" selection-start-column="46" selection-end-line="3" selection-end-column="46" />
561   - </state>
562   - </provider>
563   - </entry>
564   - <entry file="file://$PROJECT_DIR$/lib/kanjai.rb">
565   - <provider selected="true" editor-type-id="text-editor" />
566   - </entry>
567   - <entry file="file://$PROJECT_DIR$/lib/kanjai/engine.rb">
568   - <provider selected="true" editor-type-id="text-editor" />
569   - </entry>
570   - <entry file="file://$PROJECT_DIR$/db/migrate/20160707115443_add_show_public_only_to_kanjai_pages.rb">
571   - <provider selected="true" editor-type-id="text-editor">
572   - <state relative-caret-position="30">
573   - <caret line="2" column="73" selection-start-line="2" selection-start-column="4" selection-end-line="2" selection-end-column="73" />
574   - </state>
575   - </provider>
576   - </entry>
577   - <entry file="file://$PROJECT_DIR$/lib/kanjai/version.rb">
578   - <provider selected="true" editor-type-id="text-editor">
579   - <state relative-caret-position="45">
580   - <caret line="3" selection-start-line="3" selection-end-line="3" />
581   - </state>
582   - </provider>
583   - </entry>
584   - </component>
585   -</project>
\ No newline at end of file
... ... @@ -2,6 +2,7 @@ PATH
2 2 remote: .
3 3 specs:
4 4 kanjai (0.0.140)
  5 + acts-as-taggable-on (~> 6.5)
5 6 acts_as_list
6 7 acts_as_tree
7 8 aws-sdk
... ... @@ -55,8 +56,10 @@ GEM
55 56 i18n (>= 0.7, < 2)
56 57 minitest (~> 5.1)
57 58 tzinfo (~> 1.1)
58   - acts_as_list (0.9.19)
59   - activerecord (>= 3.0)
  59 + acts-as-taggable-on (6.5.0)
  60 + activerecord (>= 5.0, < 6.1)
  61 + acts_as_list (1.0.1)
  62 + activerecord (>= 4.2)
60 63 acts_as_tree (2.9.1)
61 64 activerecord (>= 3.0.0)
62 65 arel (9.0.0)
... ... @@ -1019,16 +1022,16 @@ GEM
1019 1022 rb-fsevent (0.10.3)
1020 1023 rb-inotify (0.10.1)
1021 1024 ffi (~> 1.0)
1022   - responders (2.4.1)
1023   - actionpack (>= 4.2.0, < 6.0)
1024   - railties (>= 4.2.0, < 6.0)
  1025 + responders (3.0.0)
  1026 + actionpack (>= 5.0)
  1027 + railties (>= 5.0)
1025 1028 sass (3.7.4)
1026 1029 sass-listen (~> 4.0.0)
1027 1030 sass-listen (4.0.0)
1028 1031 rb-fsevent (~> 0.9, >= 0.9.4)
1029 1032 rb-inotify (~> 0.9, >= 0.9.7)
1030   - sass-rails (5.0.7)
1031   - railties (>= 4.0.0, < 6)
  1033 + sass-rails (5.1.0)
  1034 + railties (>= 5.2.0)
1032 1035 sass (~> 3.1)
1033 1036 sprockets (>= 2.8, < 4.0)
1034 1037 sprockets-rails (>= 2.0, < 4.0)
... ... @@ -1060,4 +1063,4 @@ DEPENDENCIES
1060 1063 kanjai!
1061 1064
1062 1065 BUNDLED WITH
1063   - 2.0.1
  1066 + 2.1.4
... ...
... ... @@ -14,8 +14,8 @@ RDoc::Task.new(:rdoc) do |rdoc|
14 14 rdoc.rdoc_files.include('lib/**/*.rb')
15 15 end
16 16
17   -APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18   -load 'rails/tasks/engine.rake'
  17 +#APP_RAKEFILE = File.expand_path("../Rakefile", __FILE__)
  18 +#load 'rails/tasks/engine.rake'
19 19
20 20
21 21 load 'rails/tasks/statistics.rake'
... ...
... ... @@ -1389,40 +1389,31 @@ var add_fields = function(target, association, content){
1389 1389 jQuery(target).append(content.replace(regexp, new_id));
1390 1390 };
1391 1391
1392   -
1393   -
1394   -
1395   -var initAjaxFileUpload = function(selector){
1396   -
1397   -
1398   - function send_ajax_form($form){
1399   - $('#progress-window').find('.modal-body').append('<div>Upload form data, please wait...</div>');
1400   - var url = $form.attr('action');
1401   -
1402   - if($form.hasClass('simple_submit')){
  1392 +function send_ajax_form($form){
  1393 + $('#progress-window').find('.modal-body').append('<div>Upload form data, please wait...</div>');
  1394 + var url = $form.attr('action');
  1395 +
  1396 + if($form.hasClass('simple_submit')){
  1397 + $('#progress-window').modal('hide');
  1398 + $('#progress-window').remove();
  1399 + $form.removeClass('ajax-file-upload-form');
  1400 + //$form.unbind('submit', addFileForAjaxUpload);
  1401 + $form.unbind('submit');
  1402 + $form.submit();
  1403 +
  1404 + }else{
  1405 + $.post(url, $form.serialize(), function(){
1403 1406 $('#progress-window').modal('hide');
1404 1407 $('#progress-window').remove();
1405   - $form.removeClass('ajax-file-upload-form');
1406   - //$form.unbind('submit', addFileForAjaxUpload);
1407   - $form.unbind('submit', addFileForAjaxUpload);
1408   - $form.submit();
1409   -
1410   - }else{
1411   - $.post(url, $form.serialize(), function(){
1412   - $('#progress-window').modal('hide');
1413   - $('#progress-window').remove();
1414   - });
1415   - }
  1408 + $(window).trigger('images:update');
  1409 + });
1416 1410 }
  1411 +}
1417 1412
1418 1413
1419   -
1420   - var addFileForAjaxUpload = function(e){
1421   - var $form = $(this),
1422   - count_files = 0,
  1414 +var addFileForAjaxUpload = function(selector, $form){
  1415 + var count_files = 0,
1423 1416 count_upload = 0;
1424   - e.preventDefault();
1425   - e.stopPropagation();
1426 1417
1427 1418 selector.find(".ajax-file-upload-form input:file").each(function(){
1428 1419 var $this = $(this),
... ... @@ -1454,7 +1445,7 @@ var initAjaxFileUpload = function(selector){
1454 1445
1455 1446
1456 1447 $this.fileupload('send', {files: fileToSend})
1457   - .complete(function (result, textStatus, jqXHR) {
  1448 + .done(function (result, textStatus, jqXHR) {
1458 1449 count_upload = count_upload + 1;
1459 1450 if(count_upload == count_files){
1460 1451 send_ajax_form($form);
... ... @@ -1472,7 +1463,11 @@ var initAjaxFileUpload = function(selector){
1472 1463
1473 1464
1474 1465
1475   - }
  1466 +}
  1467 +
  1468 +
  1469 +var initAjaxFileUpload = function(selector){
  1470 +
1476 1471
1477 1472 var initFileInput = function(fileInputElem){
1478 1473 var form = $(fileInputElem.parents('form:first'));
... ... @@ -1499,7 +1494,6 @@ var initAjaxFileUpload = function(selector){
1499 1494 },
1500 1495 progressall: function (e, data) {
1501 1496 var progress = parseInt(data.loaded / data.total * 100, 10);
1502   -
1503 1497 $('.' + class_name).find('.progress-bar').css('width', progress + '%');
1504 1498 },
1505 1499 start: function (e) {
... ... @@ -1513,7 +1507,6 @@ var initAjaxFileUpload = function(selector){
1513 1507
1514 1508 $('.' + class_name).find('.progress-bar').addClass('progress-bar-success');
1515 1509
1516   -
1517 1510 // extract key and generate URL from response
1518 1511 var key = $(data.jqXHR.responseXML).find("Key").text();
1519 1512 var url = 'https://' + fileInputElem.data('host') + '/' + key;
... ... @@ -1542,7 +1535,12 @@ var initAjaxFileUpload = function(selector){
1542 1535
1543 1536
1544 1537
1545   - selector.find('.ajax-file-upload-form').submit(addFileForAjaxUpload);
  1538 + selector.find('.ajax-file-upload-form').submit(function(e){
  1539 + e.preventDefault();
  1540 + e.stopPropagation();
  1541 +
  1542 + addFileForAjaxUpload(selector, $(this))
  1543 + });
1546 1544
1547 1545 $(document).bind('drop dragover', function (e) {
1548 1546 e.preventDefault();
... ... @@ -1552,10 +1550,23 @@ var initAjaxFileUpload = function(selector){
1552 1550 };
1553 1551
1554 1552 var clearAjaxFileUpload = function(selector){
1555   - selector.find('.ajax-file-upload-form').unbind('submit', addFileForAjaxUpload);
  1553 + selector.find('.ajax-file-upload-form').unbind('submit');
1556 1554 };
1557 1555
1558 1556
  1557 +var tagnames = new Bloodhound({
  1558 + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title'),
  1559 + queryTokenizer: Bloodhound.tokenizers.whitespace,
  1560 + prefetch: {
  1561 + url: '/admin/tags',
  1562 + filter: function(list) {
  1563 + return $.map(list, function(title) {
  1564 + return { title: title }; });
  1565 + }
  1566 + }
  1567 +});
  1568 +tagnames.initialize();
  1569 +
1559 1570
1560 1571 jQuery(document).ready(function(){
1561 1572
... ... @@ -1724,46 +1735,78 @@ jQuery(document).ready(function(){
1724 1735 }else {
1725 1736 dropZone[0].ondrop = function (e) {
1726 1737 e.preventDefault();
1727   - var file = e.dataTransfer.files[0],
1728   - input_name = "gallery_image[" + file_index + "]",
1729   - $fileInput = $('<div><input name="' + input_name + '" type="file" class="fileupload-field"></div>');
  1738 + $.each(e.dataTransfer.files, function(){
  1739 + var file = this,
  1740 + input_name = "gallery_image[" + file_index + "]",
  1741 + $fileInput = $('<div><input name="' + input_name + 'file" type="file" class="fileupload-field"></div>');
1730 1742
1731   - file_index = file_index + 1;
  1743 + file_index = file_index + 1;
1732 1744
1733   - $fileInput.find('.fileupload-field').data('url', upload_url);
1734   - $fileInput.find('.fileupload-field').data('form-data', upload_form_data);
1735   - $fileInput.find('.fileupload-field').data('host', upload_host);
  1745 + $fileInput.find('.fileupload-field').data('url', upload_url);
  1746 + $fileInput.find('.fileupload-field').data('form-data', upload_form_data);
  1747 + $fileInput.find('.fileupload-field').data('host', upload_host);
1736 1748
1737 1749
1738   - $fileInput.find('.fileupload-field').data('files', [{input_name: input_name, file: file}]);
  1750 + $fileInput.find('.fileupload-field').data('files', [{input_name: input_name + 'file', file: file}]);
1739 1751
1740   - var reader = new FileReader();
1741   - reader.onload = function (evt) {
1742   - var options = {
1743   - showUpload:false,
1744   - dropZoneEnabled: false,
1745   - initialPreview: ["<img src='"+ evt.target.result +"' class='file-preview-image' alt='' title=''>"]
1746   - };
  1752 + var reader = new FileReader();
  1753 + reader.onload = function (evt) {
  1754 + var options = {
  1755 + showUpload:false,
  1756 + dropZoneEnabled: false,
  1757 + contentType: true,
  1758 + initialPreview: ["<img src='"+ evt.target.result +"' class='file-preview-image' alt='' title=''>"]
  1759 + };
1747 1760
1748   - $fileInput.find('.fileupload-field').fileinput(options);
  1761 + $fileInput.find('.fileupload-field').fileinput(options);
1749 1762
1750   - $fileInput.find('.fileupload-field').on('fileclear', function(event) {
1751   - $(this).closest('.file-input').remove();
1752   - });
  1763 + $fileInput.find('.fileupload-field').on('fileclear', function(event) {
  1764 + if($(this).closest('.new-image-wrapper').length > 0){
  1765 + $(this).closest('.new-image-wrapper').remove();
  1766 + }else{
  1767 + $(this).closest('.file-input').remove();
  1768 + }
  1769 + });
1753 1770
1754   - $fileInput.find('.fileupload-field').on('change', function(event) {
  1771 + $fileInput.find('.fileupload-field').on('change', function(event) {
1755 1772
1756   - });
  1773 + });
  1774 + if($('#gallery_form form').find('.add-new-field').length > 0){
  1775 + var template = $('#gallery_form form').find('.add-new-field').data('template');
  1776 + template = template.replace(/\{name\}/g, input_name);
  1777 + var $template = $(template);
  1778 + $template.find('.fileupload-preview').html($fileInput);
  1779 + $template.find('.file-type').val(file.type);
  1780 +
  1781 + $template.find('.remove').click(function(){
  1782 + $(this).closest('.new-image-wrapper').find('.fileinput-remove').trigger('click');
  1783 + return false;
  1784 + });
  1785 + $('#gallery_form form #new_images').append($template);
  1786 +
  1787 +
  1788 +
  1789 + $template.find("input[data-role=tagsinput]").tagsinput({
  1790 + typeaheadjs: {
  1791 + name: 'title',
  1792 + displayKey: 'title',
  1793 + valueKey: 'title',
  1794 + source: tagnames.ttAdapter()
  1795 + }
  1796 + });
  1797 + }else{
  1798 + $('#gallery_form form #new_images').append($fileInput);
  1799 + }
1757 1800
1758   - $('#gallery_form form #new_images').append($fileInput);
  1801 + $('#gallery_form form input:submit').removeClass('not-visible');
1759 1802
1760   - $('#gallery_form form input:submit').removeClass('not-visible');
  1803 + clearAjaxFileUpload($('#gallery_form'));
  1804 + initAjaxFileUpload($('#gallery_form'));
1761 1805
1762   - clearAjaxFileUpload($('#gallery_form'));
1763   - initAjaxFileUpload($('#gallery_form'));
  1806 + };
  1807 + reader.readAsDataURL(file);
  1808 + });
1764 1809
1765   - };
1766   - reader.readAsDataURL(file);
1767 1810
1768 1811
1769 1812
... ... @@ -1837,6 +1880,7 @@ jQuery(document).ready(function(){
1837 1880 });
1838 1881 });
1839 1882
  1883 +
1840 1884 $('.dropdown-toggle').dropdown();
1841 1885
1842 1886 });
... ...
  1 +/*
  2 + * bootstrap-filestyle
  3 + * doc: http://markusslima.github.io/bootstrap-filestyle/
  4 + * github: https://github.com/markusslima/bootstrap-filestyle
  5 + *
  6 + * Copyright (c) 2017 Markus Vinicius da Silva Lima
  7 + * Version 2.1.0
  8 + * Licensed under the MIT license.
  9 + */
  10 +(function($) {
  11 + "use strict";
  12 +
  13 + var nextId = 0;
  14 +
  15 + var Filestyle = function(element, options) {
  16 + this.options = options;
  17 + this.$elementFilestyle = [];
  18 + this.$element = $(element);
  19 + };
  20 +
  21 + Filestyle.prototype = {
  22 + clear : function() {
  23 + this.$element.val('');
  24 + this.$elementFilestyle.find(':text').val('');
  25 + this.$elementFilestyle.find('.badge').remove();
  26 + },
  27 +
  28 + destroy : function() {
  29 + this.$element.removeAttr('style').removeData('filestyle');
  30 + this.$elementFilestyle.remove();
  31 + },
  32 +
  33 + disabled : function(value) {
  34 + if (value === true || value === false) {
  35 + this.options.disabled = value;
  36 + this.$element.prop('disabled', this.options.disabled);
  37 + this.$elementFilestyle.find('label').prop('disabled', this.options.disabled);
  38 +
  39 + if (this.options.disabled)
  40 + this.$elementFilestyle.find('label').css('opacity', '0.65');
  41 + else
  42 + this.$elementFilestyle.find('label').css('opacity', '1');
  43 + } else {
  44 + return this.options.disabled;
  45 + }
  46 + },
  47 +
  48 + dragdrop : function(value) {
  49 + if (value === true || value === false) {
  50 + this.options.dragdrop = value;
  51 + } else {
  52 + return this.options.dragdrop;
  53 + }
  54 + },
  55 +
  56 + buttonBefore : function(value) {
  57 + if (value === true) {
  58 + if (!this.options.buttonBefore) {
  59 + this.options.buttonBefore = value;
  60 + if (this.options.input) {
  61 + this.$elementFilestyle.remove();
  62 + this.constructor();
  63 + this.pushNameFiles();
  64 + }
  65 + }
  66 + } else if (value === false) {
  67 + if (this.options.buttonBefore) {
  68 + this.options.buttonBefore = value;
  69 + if (this.options.input) {
  70 + this.$elementFilestyle.remove();
  71 + this.constructor();
  72 + this.pushNameFiles();
  73 + }
  74 + }
  75 + } else {
  76 + return this.options.buttonBefore;
  77 + }
  78 + },
  79 +
  80 + input : function(value) {
  81 + if (value === true) {
  82 + if (!this.options.input) {
  83 + this.options.input = value;
  84 +
  85 + if (this.options.buttonBefore) {
  86 + this.$elementFilestyle.append(this.htmlInput());
  87 + } else {
  88 + this.$elementFilestyle.prepend(this.htmlInput());
  89 + }
  90 +
  91 + this.pushNameFiles();
  92 + this.$elementFilestyle.find('.group-span-filestyle').addClass('input-group-btn');
  93 + }
  94 + } else if (value === false) {
  95 + if (this.options.input) {
  96 + this.options.input = value;
  97 + this.$elementFilestyle.find(':text').remove();
  98 + this.$elementFilestyle.find('.group-span-filestyle').removeClass('input-group-btn');
  99 + }
  100 + } else {
  101 + return this.options.input;
  102 + }
  103 + },
  104 +
  105 + size : function(value) {
  106 + if (value !== undefined) {
  107 + this.options.size = value;
  108 + var btn = this.$elementFilestyle.find('label'), input = this.$elementFilestyle.find('input');
  109 +
  110 + btn.removeClass('btn-lg btn-sm');
  111 + input.removeClass('form-control-lg form-control-sm');
  112 + if (this.options.size != 'nr') {
  113 + btn.addClass('btn-' + this.options.size);
  114 + input.addClass('form-control-' + this.options.size);
  115 + }
  116 + } else {
  117 + return this.options.size;
  118 + }
  119 + },
  120 +
  121 + placeholder : function(value) {
  122 + if (value !== undefined) {
  123 + this.options.placeholder = value;
  124 + this.$elementFilestyle.find('input').attr('placeholder', value);
  125 + } else {
  126 + return this.options.placeholder;
  127 + }
  128 + },
  129 +
  130 + text : function(value) {
  131 + if (value !== undefined) {
  132 + this.options.text = value;
  133 + this.$elementFilestyle.find('label .text').html(this.options.text);
  134 + } else {
  135 + return this.options.text;
  136 + }
  137 + },
  138 +
  139 + btnClass : function(value) {
  140 + if (value !== undefined) {
  141 + this.options.btnClass = value;
  142 + this.$elementFilestyle.find('label').attr({
  143 + 'class' : 'btn ' + this.options.btnClass + ' btn-' + this.options.size
  144 + });
  145 + } else {
  146 + return this.options.btnClass;
  147 + }
  148 + },
  149 +
  150 + badge : function(value) {
  151 + if (value === true) {
  152 + this.options.badge = value;
  153 + var files = this.pushNameFiles();
  154 + this.$elementFilestyle.find('label').append(' <span class="badge '+this.options.badgeName+'">' + files.length + '</span>');
  155 + } else if (value === false) {
  156 + this.options.badge = value;
  157 + this.$elementFilestyle.find('.badge').remove();
  158 + } else {
  159 + return this.options.badge;
  160 + }
  161 + },
  162 +
  163 + badgeName : function(value) {
  164 + if (value !== undefined) {
  165 + this.options.badgeName = value;
  166 + this.$elementFilestyle.find('.badge').attr({
  167 + 'class' : 'badge ' + this.options.badgeName
  168 + });
  169 + } else {
  170 + return this.options.badgeName;
  171 + }
  172 + },
  173 +
  174 + htmlIcon : function(value) {
  175 + if (value !== undefined) {
  176 + this.options.htmlIcon = value;
  177 + }
  178 +
  179 + return this.options.htmlIcon;
  180 + },
  181 +
  182 + htmlInput : function() {
  183 + if (this.options.input) {
  184 + return '<input type="text" class="form-control ' + (this.options.size == 'nr' ? '' : 'form-control-' + this.options.size) + '" placeholder="'+ this.options.placeholder +'" disabled> ';
  185 + } else {
  186 + return '';
  187 + }
  188 + },
  189 +
  190 + // puts the name of the input files
  191 + // return files
  192 + pushNameFiles : function() {
  193 + var content = '', files = [];
  194 + if (this.$element[0].files === undefined) {
  195 + files[0] = {
  196 + 'name' : this.$element[0] && this.$element[0].value
  197 + };
  198 + } else {
  199 + files = this.$element[0].files;
  200 + }
  201 +
  202 + for (var i = 0; i < files.length; i++) {
  203 + content += files[i].name.split("\\").pop() + ', ';
  204 + }
  205 +
  206 + if (content !== '') {
  207 + this.$elementFilestyle.find(':text').val(content.replace(/\, $/g, ''));
  208 + } else {
  209 + this.$elementFilestyle.find(':text').val('');
  210 + }
  211 +
  212 + return files;
  213 + },
  214 +
  215 + constructor : function() {
  216 + var _self = this,
  217 + html = '',
  218 + id = _self.$element.attr('id'),
  219 + files = [],
  220 + btn = '',
  221 + $label;
  222 +
  223 + if (id === '' || !id) {
  224 + id = 'filestyle-' + nextId;
  225 + _self.$element.attr({
  226 + 'id' : id
  227 + });
  228 + nextId++;
  229 + }
  230 +
  231 + btn = '<span class="group-span-filestyle ' + (_self.options.input ? 'input-group-btn' : '') + '">' +
  232 + '<label for="' + id + '" style="margin-bottom: 0;" class="btn ' + _self.options.btnClass + ' ' +
  233 + (_self.options.size == 'nr' ? '' : 'btn-' + _self.options.size) + '" ' +
  234 + (_self.options.disabled || _self.$element.attr('disabled') ? ' disabled="true"' : '') + '>' +
  235 + _self.htmlIcon() + '<span class="buttonText">' + _self.options.text + '</span>' +
  236 + '</label>' +
  237 + '</span>';
  238 +
  239 + html = _self.options.buttonBefore ? btn + _self.htmlInput() : _self.htmlInput() + btn;
  240 + _self.$elementFilestyle = $('<div class="bootstrap-filestyle input-group"><div name="filedrag"></div>' + html + '</div>');
  241 + _self.$elementFilestyle.find('.group-span-filestyle').attr('tabindex', "0").keypress(function(e) {
  242 + if (e.keyCode === 13 || e.charCode === 32) {
  243 + _self.$elementFilestyle.find('label').click();
  244 + return false;
  245 + }
  246 + });
  247 +
  248 + // hidding input file and add filestyle
  249 + _self.$element.css({
  250 + 'position' : 'absolute',
  251 + 'clip' : 'rect(0px 0px 0px 0px)' // using 0px for work in IE8
  252 + }).attr('tabindex', "-1").after(_self.$elementFilestyle);
  253 +
  254 + _self.$elementFilestyle.find(_self.options.buttonBefore ? 'label' : ':input').css({
  255 + 'border-top-left-radius': '.25rem',
  256 + 'border-bottom-left-radius': '.25rem'
  257 + });
  258 +
  259 + _self.$elementFilestyle.find('[name="filedrag"]').css({
  260 + position: 'absolute',
  261 + width: '100%',
  262 + height: _self.$elementFilestyle.height()+'px',
  263 + 'z-index': -1
  264 + });
  265 +
  266 + if (_self.options.disabled || _self.$element.attr('disabled')) {
  267 + _self.$element.attr('disabled', 'true');
  268 + if (_self.options.disabled)
  269 + _self.$elementFilestyle.find('label').css('opacity', '0.65');
  270 + else
  271 + _self.$elementFilestyle.find('label').css('opacity', '1');
  272 + }
  273 +
  274 + // Getting input file value
  275 + _self.$element.change(function () {
  276 + var files = _self.pushNameFiles();
  277 + if (_self.options.badge) {
  278 + if (_self.$elementFilestyle.find('.badge').length == 0) {
  279 + _self.$elementFilestyle.find('label').append(' <span class="badge '+_self.options.badgeName+'">' + files.length + '</span>');
  280 + } else if (files.length == 0) {
  281 + _self.$elementFilestyle.find('.badge').remove();
  282 + } else {
  283 + _self.$elementFilestyle.find('.badge').html(files.length);
  284 + }
  285 + } else {
  286 + _self.$elementFilestyle.find('.badge').remove();
  287 + }
  288 +
  289 + _self.options.onChange(files);
  290 + });
  291 +
  292 + // Check if browser is Firefox
  293 + if (window.navigator.userAgent.search(/firefox/i) > -1) {
  294 + // Simulating choose file for firefox
  295 + _self.$elementFilestyle.find('label').click(function() {
  296 + _self.$element.click();
  297 + return false;
  298 + });
  299 + }
  300 +
  301 + /** DRAG AND DROP EVENTS **/
  302 + $(document)
  303 + .on('dragover', function (e) {
  304 + e.preventDefault();
  305 + e.stopPropagation();
  306 + if (_self.options.dragdrop) {
  307 + $('[name="filedrag"]').css('z-index', '9');
  308 + }
  309 + })
  310 + .on('drop', function (e) {
  311 + e.preventDefault();
  312 + e.stopPropagation();
  313 + if (_self.options.dragdrop) {
  314 + $('[name="filedrag"]').css('z-index', '-1');
  315 + }
  316 + });
  317 +
  318 + _self.$elementFilestyle.find('[name="filedrag"]')
  319 + .on('dragover',
  320 + function (e) {
  321 + e.preventDefault();
  322 + e.stopPropagation();
  323 + }
  324 + )
  325 + .on('dragenter',
  326 + function (e) {
  327 + e.preventDefault();
  328 + e.stopPropagation();
  329 + }
  330 + )
  331 + .on('drop',
  332 + function (e) {
  333 + if (e.originalEvent.dataTransfer && !_self.options.disabled && _self.options.dragdrop) {
  334 + if (e.originalEvent.dataTransfer.files.length) {
  335 + e.preventDefault();
  336 + e.stopPropagation();
  337 + _self.$element[0].files = e.originalEvent.dataTransfer.files;
  338 + var files = _self.pushNameFiles();
  339 + if (_self.options.badge) {
  340 + if (_self.$elementFilestyle.find('.badge').length == 0) {
  341 + _self.$elementFilestyle.find('label').append(' <span class="badge '+_self.options.badgeName+'">' + files.length + '</span>');
  342 + } else if (files.length == 0) {
  343 + _self.$elementFilestyle.find('.badge').remove();
  344 + } else {
  345 + _self.$elementFilestyle.find('.badge').html(files.length);
  346 + }
  347 + } else {
  348 + _self.$elementFilestyle.find('.badge').remove();
  349 + }
  350 +
  351 + $('[name="filedrag"]').css('z-index', '-1');
  352 + }
  353 + }
  354 + }
  355 + );
  356 + }
  357 + };
  358 +
  359 + var old = $.fn.filestyle;
  360 +
  361 + $.fn.filestyle = function(option, value) {
  362 + var get = '', element = this.each(function() {
  363 + if ($(this).attr('type') === 'file') {
  364 + var $this = $(this), data = $this.data('filestyle'), options = $.extend({}, $.fn.filestyle.defaults, option, typeof option === 'object' && option);
  365 +
  366 + if (!data) {
  367 + $this.data('filestyle', ( data = new Filestyle(this, options)));
  368 + data.constructor();
  369 + }
  370 +
  371 + if ( typeof option === 'string') {
  372 + get = data[option](value);
  373 + }
  374 + }
  375 + });
  376 +
  377 + if ( typeof get !== undefined) {
  378 + return get;
  379 + } else {
  380 + return element;
  381 + }
  382 + };
  383 +
  384 + $.fn.filestyle.defaults = {
  385 + 'text' : 'Choose file',
  386 + 'htmlIcon' : '',
  387 + 'btnClass' : 'btn-secondary',
  388 + 'size' : 'nr',
  389 + 'input' : true,
  390 + 'badge' : false,
  391 + 'badgeName': 'badge-light',
  392 + 'buttonBefore' : false,
  393 + 'dragdrop' : true,
  394 + 'disabled' : false,
  395 + 'placeholder': '',
  396 + 'onChange': function () {}
  397 + };
  398 +
  399 + $.fn.filestyle.noConflict = function() {
  400 + $.fn.filestyle = old;
  401 + return this;
  402 + };
  403 +
  404 + $(function() {
  405 + $('.filestyle').each(function() {
  406 + var $this = $(this), options = {
  407 + 'input' : $this.attr('data-input') !== 'false',
  408 + 'htmlIcon' : $this.attr('data-icon'),
  409 + 'buttonBefore' : $this.attr('data-buttonBefore') === 'true',
  410 + 'disabled' : $this.attr('data-disabled') === 'true',
  411 + 'size' : $this.attr('data-size'),
  412 + 'text' : $this.attr('data-text'),
  413 + 'btnClass' : $this.attr('data-btnClass'),
  414 + 'badge' : $this.attr('data-badge') === 'true',
  415 + 'dragdrop' : $this.attr('data-dragdrop') !== 'false',
  416 + 'badgeName' : $this.attr('data-badgeName'),
  417 + 'placeholder': $this.attr('data-placeholder')
  418 + };
  419 +
  420 + $this.filestyle(options);
  421 + });
  422 + });
  423 +})(window.jQuery);
\ No newline at end of file
... ...
... ... @@ -455,6 +455,7 @@
455 455 options.headers['Content-Disposition'] = 'attachment; filename="' +
456 456 encodeURI(file.name) + '"';
457 457 }
  458 +
458 459 if (!multipart) {
459 460 options.contentType = file.type || 'application/octet-stream';
460 461 options.data = options.blob || file;
... ...
  1 +jQuery(document).ready(function(){
  2 + var loadImage = function($wrapper){
  3 + var url = $wrapper.data('url'),
  4 + $loader = $wrapper.find('.loader-demo'),
  5 + $images = $wrapper.find('.exist-image-list');
  6 +
  7 + $loader.removeClass('not-visible');
  8 + $images.addClass('not-visible');
  9 +
  10 + var mas = [];
  11 + $wrapper.find('.filter label.active').each(function(){
  12 + mas.push($(this).data('value'));
  13 + });
  14 +
  15 + jQuery.ajax({
  16 + type: 'POST',
  17 + url: url,
  18 + data: ({tags: mas}),
  19 + dataType: 'html',
  20 + success: function(data){
  21 + $images.html(data);
  22 + $loader.addClass('not-visible');
  23 + $images.removeClass('not-visible');
  24 + }
  25 + });
  26 + };
  27 +
  28 + if($('.image-list').length > 0){
  29 + var $wrapper = $('.image-list');
  30 + loadImage($wrapper);
  31 + $wrapper.find('.filter label').click(function(){
  32 + var $this = $(this);
  33 + if($this.hasClass('active')){
  34 + $this.removeClass('active');
  35 + }else{
  36 + $this.addClass('active');
  37 + }
  38 + if($this.data('value') == 'all' && $this.hasClass('active')){
  39 + $wrapper.find(".filter label.active").not($this).removeClass('active');
  40 + };
  41 + if($this.data('value') != 'all' && $this.hasClass('active')){
  42 + $wrapper.find(".filter label.active[data-value=all]").removeClass('active');
  43 + };
  44 + loadImage($wrapper);
  45 + });
  46 + }
  47 +
  48 + $(window).bind('images:update', function(){
  49 + if($('.image-list').length > 0){
  50 + loadImage($('.image-list'));
  51 + };
  52 + });
  53 +});
\ No newline at end of file
... ...
  1 +(function ($) {
  2 + "use strict";
  3 +
  4 + var defaultOptions = {
  5 + tagClass: function(item) {
  6 + return 'label label-info';
  7 + },
  8 + itemValue: function(item) {
  9 + return item ? item.toString() : item;
  10 + },
  11 + itemText: function(item) {
  12 + return this.itemValue(item);
  13 + },
  14 + itemTitle: function(item) {
  15 + return null;
  16 + },
  17 + freeInput: true,
  18 + addOnBlur: true,
  19 + maxTags: undefined,
  20 + maxChars: undefined,
  21 + confirmKeys: [13, 44],
  22 + delimiter: ',',
  23 + delimiterRegex: null,
  24 + cancelConfirmKeysOnEmpty: true,
  25 + onTagExists: function(item, $tag) {
  26 + $tag.hide().fadeIn();
  27 + },
  28 + trimValue: false,
  29 + allowDuplicates: false
  30 + };
  31 +
  32 + /**
  33 + * Constructor function
  34 + */
  35 + function TagsInput(element, options) {
  36 + this.itemsArray = [];
  37 +
  38 + this.$element = $(element);
  39 + this.$element.hide();
  40 +
  41 + this.isSelect = (element.tagName === 'SELECT');
  42 + this.multiple = (this.isSelect && element.hasAttribute('multiple'));
  43 + this.objectItems = options && options.itemValue;
  44 + this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : '';
  45 + this.inputSize = Math.max(1, this.placeholderText.length);
  46 +
  47 + this.$container = $('<div class="bootstrap-tagsinput"></div>');
  48 + this.$input = $('<input type="text" placeholder="' + this.placeholderText + '"/>').appendTo(this.$container);
  49 +
  50 + this.$element.before(this.$container);
  51 +
  52 + this.build(options);
  53 + }
  54 +
  55 + TagsInput.prototype = {
  56 + constructor: TagsInput,
  57 +
  58 + /**
  59 + * Adds the given item as a new tag. Pass true to dontPushVal to prevent
  60 + * updating the elements val()
  61 + */
  62 + add: function(item, dontPushVal, options) {
  63 + var self = this;
  64 +
  65 + if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags)
  66 + return;
  67 +
  68 + // Ignore falsey values, except false
  69 + if (item !== false && !item)
  70 + return;
  71 +
  72 + // Trim value
  73 + if (typeof item === "string" && self.options.trimValue) {
  74 + item = $.trim(item);
  75 + }
  76 +
  77 + // Throw an error when trying to add an object while the itemValue option was not set
  78 + if (typeof item === "object" && !self.objectItems)
  79 + throw("Can't add objects when itemValue option is not set");
  80 +
  81 + // Ignore strings only containg whitespace
  82 + if (item.toString().match(/^\s*$/))
  83 + return;
  84 +
  85 + // If SELECT but not multiple, remove current tag
  86 + if (self.isSelect && !self.multiple && self.itemsArray.length > 0)
  87 + self.remove(self.itemsArray[0]);
  88 +
  89 + if (typeof item === "string" && this.$element[0].tagName === 'INPUT') {
  90 + var delimiter = (self.options.delimiterRegex) ? self.options.delimiterRegex : self.options.delimiter;
  91 + var items = item.split(delimiter);
  92 + if (items.length > 1) {
  93 + for (var i = 0; i < items.length; i++) {
  94 + this.add(items[i], true);
  95 + }
  96 +
  97 + if (!dontPushVal)
  98 + self.pushVal();
  99 + return;
  100 + }
  101 + }
  102 +
  103 + var itemValue = self.options.itemValue(item),
  104 + itemText = self.options.itemText(item),
  105 + tagClass = self.options.tagClass(item),
  106 + itemTitle = self.options.itemTitle(item);
  107 +
  108 + // Ignore items allready added
  109 + var existing = $.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0];
  110 + if (existing && !self.options.allowDuplicates) {
  111 + // Invoke onTagExists
  112 + if (self.options.onTagExists) {
  113 + var $existingTag = $(".tag", self.$container).filter(function() { return $(this).data("item") === existing; });
  114 + self.options.onTagExists(item, $existingTag);
  115 + }
  116 + return;
  117 + }
  118 +
  119 + // if length greater than limit
  120 + if (self.items().toString().length + item.length + 1 > self.options.maxInputLength)
  121 + return;
  122 +
  123 + // raise beforeItemAdd arg
  124 + var beforeItemAddEvent = $.Event('beforeItemAdd', { item: item, cancel: false, options: options});
  125 + self.$element.trigger(beforeItemAddEvent);
  126 + if (beforeItemAddEvent.cancel)
  127 + return;
  128 +
  129 + // register item in internal array and map
  130 + self.itemsArray.push(item);
  131 +
  132 + // add a tag element
  133 +
  134 + var $tag = $('<span class="tag ' + htmlEncode(tagClass) + (itemTitle !== null ? ('" title="' + itemTitle) : '') + '">' + htmlEncode(itemText) + '<span data-role="remove"></span></span>');
  135 + $tag.data('item', item);
  136 + self.findInputWrapper().before($tag);
  137 + $tag.after(' ');
  138 +
  139 + // add <option /> if item represents a value not present in one of the <select />'s options
  140 + if (self.isSelect && !$('option[value="' + encodeURIComponent(itemValue) + '"]',self.$element)[0]) {
  141 + var $option = $('<option selected>' + htmlEncode(itemText) + '</option>');
  142 + $option.data('item', item);
  143 + $option.attr('value', itemValue);
  144 + self.$element.append($option);
  145 + }
  146 +
  147 + if (!dontPushVal)
  148 + self.pushVal();
  149 +
  150 + // Add class when reached maxTags
  151 + if (self.options.maxTags === self.itemsArray.length || self.items().toString().length === self.options.maxInputLength)
  152 + self.$container.addClass('bootstrap-tagsinput-max');
  153 +
  154 + self.$element.trigger($.Event('itemAdded', { item: item, options: options }));
  155 + },
  156 +
  157 + /**
  158 + * Removes the given item. Pass true to dontPushVal to prevent updating the
  159 + * elements val()
  160 + */
  161 + remove: function(item, dontPushVal, options) {
  162 + var self = this;
  163 +
  164 + if (self.objectItems) {
  165 + if (typeof item === "object")
  166 + item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == self.options.itemValue(item); } );
  167 + else
  168 + item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) == item; } );
  169 +
  170 + item = item[item.length-1];
  171 + }
  172 +
  173 + if (item) {
  174 + var beforeItemRemoveEvent = $.Event('beforeItemRemove', { item: item, cancel: false, options: options });
  175 + self.$element.trigger(beforeItemRemoveEvent);
  176 + if (beforeItemRemoveEvent.cancel)
  177 + return;
  178 +
  179 + $('.tag', self.$container).filter(function() { return $(this).data('item') === item; }).remove();
  180 + $('option', self.$element).filter(function() { return $(this).data('item') === item; }).remove();
  181 + if($.inArray(item, self.itemsArray) !== -1)
  182 + self.itemsArray.splice($.inArray(item, self.itemsArray), 1);
  183 + }
  184 +
  185 + if (!dontPushVal)
  186 + self.pushVal();
  187 +
  188 + // Remove class when reached maxTags
  189 + if (self.options.maxTags > self.itemsArray.length)
  190 + self.$container.removeClass('bootstrap-tagsinput-max');
  191 +
  192 + self.$element.trigger($.Event('itemRemoved', { item: item, options: options }));
  193 + },
  194 +
  195 + /**
  196 + * Removes all items
  197 + */
  198 + removeAll: function() {
  199 + var self = this;
  200 +
  201 + $('.tag', self.$container).remove();
  202 + $('option', self.$element).remove();
  203 +
  204 + while(self.itemsArray.length > 0)
  205 + self.itemsArray.pop();
  206 +
  207 + self.pushVal();
  208 + },
  209 +
  210 + /**
  211 + * Refreshes the tags so they match the text/value of their corresponding
  212 + * item.
  213 + */
  214 + refresh: function() {
  215 + var self = this;
  216 + $('.tag', self.$container).each(function() {
  217 + var $tag = $(this),
  218 + item = $tag.data('item'),
  219 + itemValue = self.options.itemValue(item),
  220 + itemText = self.options.itemText(item),
  221 + tagClass = self.options.tagClass(item);
  222 +
  223 + // Update tag's class and inner text
  224 + $tag.attr('class', null);
  225 + $tag.addClass('tag ' + htmlEncode(tagClass));
  226 + $tag.contents().filter(function() {
  227 + return this.nodeType == 3;
  228 + })[0].nodeValue = htmlEncode(itemText);
  229 +
  230 + if (self.isSelect) {
  231 + var option = $('option', self.$element).filter(function() { return $(this).data('item') === item; });
  232 + option.attr('value', itemValue);
  233 + }
  234 + });
  235 + },
  236 +
  237 + /**
  238 + * Returns the items added as tags
  239 + */
  240 + items: function() {
  241 + return this.itemsArray;
  242 + },
  243 +
  244 + /**
  245 + * Assembly value by retrieving the value of each item, and set it on the
  246 + * element.
  247 + */
  248 + pushVal: function() {
  249 + var self = this,
  250 + val = $.map(self.items(), function(item) {
  251 + return self.options.itemValue(item).toString();
  252 + });
  253 +
  254 + self.$element.val(val, true).trigger('change');
  255 + },
  256 +
  257 + /**
  258 + * Initializes the tags input behaviour on the element
  259 + */
  260 + build: function(options) {
  261 + var self = this;
  262 +
  263 + self.options = $.extend({}, defaultOptions, options);
  264 + // When itemValue is set, freeInput should always be false
  265 + if (self.objectItems)
  266 + self.options.freeInput = false;
  267 +
  268 + makeOptionItemFunction(self.options, 'itemValue');
  269 + makeOptionItemFunction(self.options, 'itemText');
  270 + makeOptionFunction(self.options, 'tagClass');
  271 +
  272 + // Typeahead Bootstrap version 2.3.2
  273 + if (self.options.typeahead) {
  274 + var typeahead = self.options.typeahead || {};
  275 +
  276 + makeOptionFunction(typeahead, 'source');
  277 +
  278 + self.$input.typeahead($.extend({}, typeahead, {
  279 + source: function (query, process) {
  280 + function processItems(items) {
  281 + var texts = [];
  282 +
  283 + for (var i = 0; i < items.length; i++) {
  284 + var text = self.options.itemText(items[i]);
  285 + map[text] = items[i];
  286 + texts.push(text);
  287 + }
  288 + process(texts);
  289 + }
  290 +
  291 + this.map = {};
  292 + var map = this.map,
  293 + data = typeahead.source(query);
  294 +
  295 + if ($.isFunction(data.success)) {
  296 + // support for Angular callbacks
  297 + data.success(processItems);
  298 + } else if ($.isFunction(data.then)) {
  299 + // support for Angular promises
  300 + data.then(processItems);
  301 + } else {
  302 + // support for functions and jquery promises
  303 + $.when(data)
  304 + .then(processItems);
  305 + }
  306 + },
  307 + updater: function (text) {
  308 + self.add(this.map[text]);
  309 + return this.map[text];
  310 + },
  311 + matcher: function (text) {
  312 + return (text.toLowerCase().indexOf(this.query.trim().toLowerCase()) !== -1);
  313 + },
  314 + sorter: function (texts) {
  315 + return texts.sort();
  316 + },
  317 + highlighter: function (text) {
  318 + var regex = new RegExp( '(' + this.query + ')', 'gi' );
  319 + return text.replace( regex, "<strong>$1</strong>" );
  320 + }
  321 + }));
  322 + }
  323 +
  324 + // typeahead.js
  325 + if (self.options.typeaheadjs) {
  326 + var typeaheadConfig = null;
  327 + var typeaheadDatasets = {};
  328 +
  329 + // Determine if main configurations were passed or simply a dataset
  330 + var typeaheadjs = self.options.typeaheadjs;
  331 + if ($.isArray(typeaheadjs)) {
  332 + typeaheadConfig = typeaheadjs[0];
  333 + typeaheadDatasets = typeaheadjs[1];
  334 + } else {
  335 + typeaheadDatasets = typeaheadjs;
  336 + }
  337 +
  338 + self.$input.typeahead(typeaheadConfig, typeaheadDatasets).on('typeahead:selected', $.proxy(function (obj, datum) {
  339 + if (typeaheadDatasets.valueKey)
  340 + self.add(datum[typeaheadDatasets.valueKey]);
  341 + else
  342 + self.add(datum);
  343 + self.$input.typeahead('val', '');
  344 + }, self));
  345 + }
  346 +
  347 + self.$container.on('click', $.proxy(function(event) {
  348 + if (! self.$element.attr('disabled')) {
  349 + self.$input.removeAttr('disabled');
  350 + }
  351 + self.$input.focus();
  352 + }, self));
  353 +
  354 + if (self.options.addOnBlur && self.options.freeInput) {
  355 + self.$input.on('focusout', $.proxy(function(event) {
  356 + // HACK: only process on focusout when no typeahead opened, to
  357 + // avoid adding the typeahead text as tag
  358 + if ($('.typeahead, .twitter-typeahead', self.$container).length === 0) {
  359 + self.add(self.$input.val());
  360 + self.$input.val('');
  361 + }
  362 + }, self));
  363 + }
  364 +
  365 +
  366 + self.$container.on('keydown', 'input', $.proxy(function(event) {
  367 + var $input = $(event.target),
  368 + $inputWrapper = self.findInputWrapper();
  369 +
  370 + if (self.$element.attr('disabled')) {
  371 + self.$input.attr('disabled', 'disabled');
  372 + return;
  373 + }
  374 +
  375 + switch (event.which) {
  376 + // BACKSPACE
  377 + case 8:
  378 + if (doGetCaretPosition($input[0]) === 0) {
  379 + var prev = $inputWrapper.prev();
  380 + if (prev.length) {
  381 + self.remove(prev.data('item'));
  382 + }
  383 + }
  384 + break;
  385 +
  386 + // DELETE
  387 + case 46:
  388 + if (doGetCaretPosition($input[0]) === 0) {
  389 + var next = $inputWrapper.next();
  390 + if (next.length) {
  391 + self.remove(next.data('item'));
  392 + }
  393 + }
  394 + break;
  395 +
  396 + // LEFT ARROW
  397 + case 37:
  398 + // Try to move the input before the previous tag
  399 + var $prevTag = $inputWrapper.prev();
  400 + if ($input.val().length === 0 && $prevTag[0]) {
  401 + $prevTag.before($inputWrapper);
  402 + $input.focus();
  403 + }
  404 + break;
  405 + // RIGHT ARROW
  406 + case 39:
  407 + // Try to move the input after the next tag
  408 + var $nextTag = $inputWrapper.next();
  409 + if ($input.val().length === 0 && $nextTag[0]) {
  410 + $nextTag.after($inputWrapper);
  411 + $input.focus();
  412 + }
  413 + break;
  414 + default:
  415 + // ignore
  416 + }
  417 +
  418 + // Reset internal input's size
  419 + var textLength = $input.val().length,
  420 + wordSpace = Math.ceil(textLength / 5),
  421 + size = textLength + wordSpace + 1;
  422 + $input.attr('size', Math.max(this.inputSize, $input.val().length));
  423 + }, self));
  424 +
  425 + self.$container.on('keypress', 'input', $.proxy(function(event) {
  426 + event.stopPropagation();
  427 + var $input = $(event.target);
  428 +
  429 + if (self.$element.attr('disabled')) {
  430 + self.$input.attr('disabled', 'disabled');
  431 + return;
  432 + }
  433 + var text = $input.val(),
  434 + maxLengthReached = self.options.maxChars && text.length >= self.options.maxChars;
  435 + if (self.options.freeInput && (keyCombinationInList(event, self.options.confirmKeys) || maxLengthReached)) {
  436 + // Only attempt to add a tag if there is data in the field
  437 + if (text.length !== 0) {
  438 + self.add(maxLengthReached ? text.substr(0, self.options.maxChars) : text);
  439 + $input.val('');
  440 + }
  441 +
  442 + // If the field is empty, let the event triggered fire as usual
  443 + if (self.options.cancelConfirmKeysOnEmpty === false) {
  444 + event.preventDefault();
  445 + }
  446 + }
  447 +
  448 + // Reset internal input's size
  449 + var textLength = $input.val().length,
  450 + wordSpace = Math.ceil(textLength / 5),
  451 + size = textLength + wordSpace + 1;
  452 + $input.attr('size', Math.max(this.inputSize, $input.val().length));
  453 + if(keyCombinationInList(event, [13]) ){
  454 + return false;
  455 + }else{
  456 + return true;
  457 + }
  458 +
  459 + }, self));
  460 +
  461 + // Remove icon clicked
  462 + self.$container.on('click', '[data-role=remove]', $.proxy(function(event) {
  463 + if (self.$element.attr('disabled')) {
  464 + return;
  465 + }
  466 + self.remove($(event.target).closest('.tag').data('item'));
  467 + }, self));
  468 +
  469 + // Only add existing value as tags when using strings as tags
  470 + if (self.options.itemValue === defaultOptions.itemValue) {
  471 + if (self.$element[0].tagName === 'INPUT') {
  472 + self.add(self.$element.val());
  473 + } else {
  474 + $('option', self.$element).each(function() {
  475 + self.add($(this).attr('value'), true);
  476 + });
  477 + }
  478 + }
  479 + },
  480 +
  481 + /**
  482 + * Removes all tagsinput behaviour and unregsiter all event handlers
  483 + */
  484 + destroy: function() {
  485 + var self = this;
  486 +
  487 + // Unbind events
  488 + self.$container.off('keypress', 'input');
  489 + self.$container.off('click', '[role=remove]');
  490 +
  491 + self.$container.remove();
  492 + self.$element.removeData('tagsinput');
  493 + self.$element.show();
  494 + },
  495 +
  496 + /**
  497 + * Sets focus on the tagsinput
  498 + */
  499 + focus: function() {
  500 + this.$input.focus();
  501 + },
  502 +
  503 + /**
  504 + * Returns the internal input element
  505 + */
  506 + input: function() {
  507 + return this.$input;
  508 + },
  509 +
  510 + /**
  511 + * Returns the element which is wrapped around the internal input. This
  512 + * is normally the $container, but typeahead.js moves the $input element.
  513 + */
  514 + findInputWrapper: function() {
  515 + var elt = this.$input[0],
  516 + container = this.$container[0];
  517 + while(elt && elt.parentNode !== container)
  518 + elt = elt.parentNode;
  519 +
  520 + return $(elt);
  521 + }
  522 + };
  523 +
  524 + /**
  525 + * Register JQuery plugin
  526 + */
  527 + $.fn.tagsinput = function(arg1, arg2, arg3) {
  528 + var results = [];
  529 +
  530 + this.each(function() {
  531 + var tagsinput = $(this).data('tagsinput');
  532 + // Initialize a new tags input
  533 + if (!tagsinput) {
  534 + tagsinput = new TagsInput(this, arg1);
  535 + $(this).data('tagsinput', tagsinput);
  536 + results.push(tagsinput);
  537 +
  538 + if (this.tagName === 'SELECT') {
  539 + $('option', $(this)).attr('selected', 'selected');
  540 + }
  541 +
  542 + // Init tags from $(this).val()
  543 + $(this).val($(this).val());
  544 + } else if (!arg1 && !arg2) {
  545 + // tagsinput already exists
  546 + // no function, trying to init
  547 + results.push(tagsinput);
  548 + } else if(tagsinput[arg1] !== undefined) {
  549 + // Invoke function on existing tags input
  550 + if(tagsinput[arg1].length === 3 && arg3 !== undefined){
  551 + var retVal = tagsinput[arg1](arg2, null, arg3);
  552 + }else{
  553 + var retVal = tagsinput[arg1](arg2);
  554 + }
  555 + if (retVal !== undefined)
  556 + results.push(retVal);
  557 + }
  558 + });
  559 +
  560 + if ( typeof arg1 == 'string') {
  561 + // Return the results from the invoked function calls
  562 + return results.length > 1 ? results : results[0];
  563 + } else {
  564 + return results;
  565 + }
  566 + };
  567 +
  568 + $.fn.tagsinput.Constructor = TagsInput;
  569 +
  570 + /**
  571 + * Most options support both a string or number as well as a function as
  572 + * option value. This function makes sure that the option with the given
  573 + * key in the given options is wrapped in a function
  574 + */
  575 + function makeOptionItemFunction(options, key) {
  576 + if (typeof options[key] !== 'function') {
  577 + var propertyName = options[key];
  578 + options[key] = function(item) { return item[propertyName]; };
  579 + }
  580 + }
  581 + function makeOptionFunction(options, key) {
  582 + if (typeof options[key] !== 'function') {
  583 + var value = options[key];
  584 + options[key] = function() { return value; };
  585 + }
  586 + }
  587 + /**
  588 + * HtmlEncodes the given value
  589 + */
  590 + var htmlEncodeContainer = $('<div />');
  591 + function htmlEncode(value) {
  592 + if (value) {
  593 + return htmlEncodeContainer.text(value).html();
  594 + } else {
  595 + return '';
  596 + }
  597 + }
  598 +
  599 + /**
  600 + * Returns the position of the caret in the given input field
  601 + * http://flightschool.acylt.com/devnotes/caret-position-woes/
  602 + */
  603 + function doGetCaretPosition(oField) {
  604 + var iCaretPos = 0;
  605 + if (document.selection) {
  606 + oField.focus ();
  607 + var oSel = document.selection.createRange();
  608 + oSel.moveStart ('character', -oField.value.length);
  609 + iCaretPos = oSel.text.length;
  610 + } else if (oField.selectionStart || oField.selectionStart == '0') {
  611 + iCaretPos = oField.selectionStart;
  612 + }
  613 + return (iCaretPos);
  614 + }
  615 +
  616 + /**
  617 + * Returns boolean indicates whether user has pressed an expected key combination.
  618 + * @param object keyPressEvent: JavaScript event object, refer
  619 + * http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
  620 + * @param object lookupList: expected key combinations, as in:
  621 + * [13, {which: 188, shiftKey: true}]
  622 + */
  623 + function keyCombinationInList(keyPressEvent, lookupList) {
  624 + var found = false;
  625 + $.each(lookupList, function (index, keyCombination) {
  626 + if (typeof (keyCombination) === 'number' && keyPressEvent.which === keyCombination) {
  627 + found = true;
  628 + return false;
  629 + }
  630 +
  631 + if (keyPressEvent.which === keyCombination.which) {
  632 + var alt = !keyCombination.hasOwnProperty('altKey') || keyPressEvent.altKey === keyCombination.altKey,
  633 + shift = !keyCombination.hasOwnProperty('shiftKey') || keyPressEvent.shiftKey === keyCombination.shiftKey,
  634 + ctrl = !keyCombination.hasOwnProperty('ctrlKey') || keyPressEvent.ctrlKey === keyCombination.ctrlKey;
  635 + if (alt && shift && ctrl) {
  636 + found = true;
  637 + return false;
  638 + }
  639 + }
  640 + });
  641 +
  642 + return found;
  643 + }
  644 +
  645 + /**
  646 + * Initialize tagsinput behaviour on inputs and selects which have
  647 + * data-role=tagsinput
  648 + */
  649 +
  650 + $(function() {
  651 + $("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput();
  652 + });
  653 +})(window.jQuery);
... ...
  1 +/*!
  2 + * typeahead.js 0.11.1
  3 + * https://github.com/twitter/typeahead.js
  4 + * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT
  5 + */
  6 +
  7 +(function(root, factory) {
  8 + if (typeof define === "function" && define.amd) {
  9 + define("bloodhound", [ "jquery" ], function(a0) {
  10 + return root["Bloodhound"] = factory(a0);
  11 + });
  12 + } else if (typeof exports === "object") {
  13 + module.exports = factory(require("jquery"));
  14 + } else {
  15 + root["Bloodhound"] = factory(jQuery);
  16 + }
  17 +})(this, function($) {
  18 + var _ = function() {
  19 + "use strict";
  20 + return {
  21 + isMsie: function() {
  22 + return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
  23 + },
  24 + isBlankString: function(str) {
  25 + return !str || /^\s*$/.test(str);
  26 + },
  27 + escapeRegExChars: function(str) {
  28 + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
  29 + },
  30 + isString: function(obj) {
  31 + return typeof obj === "string";
  32 + },
  33 + isNumber: function(obj) {
  34 + return typeof obj === "number";
  35 + },
  36 + isArray: $.isArray,
  37 + isFunction: $.isFunction,
  38 + isObject: $.isPlainObject,
  39 + isUndefined: function(obj) {
  40 + return typeof obj === "undefined";
  41 + },
  42 + isElement: function(obj) {
  43 + return !!(obj && obj.nodeType === 1);
  44 + },
  45 + isJQuery: function(obj) {
  46 + return obj instanceof $;
  47 + },
  48 + toStr: function toStr(s) {
  49 + return _.isUndefined(s) || s === null ? "" : s + "";
  50 + },
  51 + bind: $.proxy,
  52 + each: function(collection, cb) {
  53 + $.each(collection, reverseArgs);
  54 + function reverseArgs(index, value) {
  55 + return cb(value, index);
  56 + }
  57 + },
  58 + map: $.map,
  59 + filter: $.grep,
  60 + every: function(obj, test) {
  61 + var result = true;
  62 + if (!obj) {
  63 + return result;
  64 + }
  65 + $.each(obj, function(key, val) {
  66 + if (!(result = test.call(null, val, key, obj))) {
  67 + return false;
  68 + }
  69 + });
  70 + return !!result;
  71 + },
  72 + some: function(obj, test) {
  73 + var result = false;
  74 + if (!obj) {
  75 + return result;
  76 + }
  77 + $.each(obj, function(key, val) {
  78 + if (result = test.call(null, val, key, obj)) {
  79 + return false;
  80 + }
  81 + });
  82 + return !!result;
  83 + },
  84 + mixin: $.extend,
  85 + identity: function(x) {
  86 + return x;
  87 + },
  88 + clone: function(obj) {
  89 + return $.extend(true, {}, obj);
  90 + },
  91 + getIdGenerator: function() {
  92 + var counter = 0;
  93 + return function() {
  94 + return counter++;
  95 + };
  96 + },
  97 + templatify: function templatify(obj) {
  98 + return $.isFunction(obj) ? obj : template;
  99 + function template() {
  100 + return String(obj);
  101 + }
  102 + },
  103 + defer: function(fn) {
  104 + setTimeout(fn, 0);
  105 + },
  106 + debounce: function(func, wait, immediate) {
  107 + var timeout, result;
  108 + return function() {
  109 + var context = this, args = arguments, later, callNow;
  110 + later = function() {
  111 + timeout = null;
  112 + if (!immediate) {
  113 + result = func.apply(context, args);
  114 + }
  115 + };
  116 + callNow = immediate && !timeout;
  117 + clearTimeout(timeout);
  118 + timeout = setTimeout(later, wait);
  119 + if (callNow) {
  120 + result = func.apply(context, args);
  121 + }
  122 + return result;
  123 + };
  124 + },
  125 + throttle: function(func, wait) {
  126 + var context, args, timeout, result, previous, later;
  127 + previous = 0;
  128 + later = function() {
  129 + previous = new Date();
  130 + timeout = null;
  131 + result = func.apply(context, args);
  132 + };
  133 + return function() {
  134 + var now = new Date(), remaining = wait - (now - previous);
  135 + context = this;
  136 + args = arguments;
  137 + if (remaining <= 0) {
  138 + clearTimeout(timeout);
  139 + timeout = null;
  140 + previous = now;
  141 + result = func.apply(context, args);
  142 + } else if (!timeout) {
  143 + timeout = setTimeout(later, remaining);
  144 + }
  145 + return result;
  146 + };
  147 + },
  148 + stringify: function(val) {
  149 + return _.isString(val) ? val : JSON.stringify(val);
  150 + },
  151 + noop: function() {}
  152 + };
  153 + }();
  154 + var VERSION = "0.11.1";
  155 + var tokenizers = function() {
  156 + "use strict";
  157 + return {
  158 + nonword: nonword,
  159 + whitespace: whitespace,
  160 + obj: {
  161 + nonword: getObjTokenizer(nonword),
  162 + whitespace: getObjTokenizer(whitespace)
  163 + }
  164 + };
  165 + function whitespace(str) {
  166 + str = _.toStr(str);
  167 + return str ? str.split(/\s+/) : [];
  168 + }
  169 + function nonword(str) {
  170 + str = _.toStr(str);
  171 + return str ? str.split(/\W+/) : [];
  172 + }
  173 + function getObjTokenizer(tokenizer) {
  174 + return function setKey(keys) {
  175 + keys = _.isArray(keys) ? keys : [].slice.call(arguments, 0);
  176 + return function tokenize(o) {
  177 + var tokens = [];
  178 + _.each(keys, function(k) {
  179 + tokens = tokens.concat(tokenizer(_.toStr(o[k])));
  180 + });
  181 + return tokens;
  182 + };
  183 + };
  184 + }
  185 + }();
  186 + var LruCache = function() {
  187 + "use strict";
  188 + function LruCache(maxSize) {
  189 + this.maxSize = _.isNumber(maxSize) ? maxSize : 100;
  190 + this.reset();
  191 + if (this.maxSize <= 0) {
  192 + this.set = this.get = $.noop;
  193 + }
  194 + }
  195 + _.mixin(LruCache.prototype, {
  196 + set: function set(key, val) {
  197 + var tailItem = this.list.tail, node;
  198 + if (this.size >= this.maxSize) {
  199 + this.list.remove(tailItem);
  200 + delete this.hash[tailItem.key];
  201 + this.size--;
  202 + }
  203 + if (node = this.hash[key]) {
  204 + node.val = val;
  205 + this.list.moveToFront(node);
  206 + } else {
  207 + node = new Node(key, val);
  208 + this.list.add(node);
  209 + this.hash[key] = node;
  210 + this.size++;
  211 + }
  212 + },
  213 + get: function get(key) {
  214 + var node = this.hash[key];
  215 + if (node) {
  216 + this.list.moveToFront(node);
  217 + return node.val;
  218 + }
  219 + },
  220 + reset: function reset() {
  221 + this.size = 0;
  222 + this.hash = {};
  223 + this.list = new List();
  224 + }
  225 + });
  226 + function List() {
  227 + this.head = this.tail = null;
  228 + }
  229 + _.mixin(List.prototype, {
  230 + add: function add(node) {
  231 + if (this.head) {
  232 + node.next = this.head;
  233 + this.head.prev = node;
  234 + }
  235 + this.head = node;
  236 + this.tail = this.tail || node;
  237 + },
  238 + remove: function remove(node) {
  239 + node.prev ? node.prev.next = node.next : this.head = node.next;
  240 + node.next ? node.next.prev = node.prev : this.tail = node.prev;
  241 + },
  242 + moveToFront: function(node) {
  243 + this.remove(node);
  244 + this.add(node);
  245 + }
  246 + });
  247 + function Node(key, val) {
  248 + this.key = key;
  249 + this.val = val;
  250 + this.prev = this.next = null;
  251 + }
  252 + return LruCache;
  253 + }();
  254 + var PersistentStorage = function() {
  255 + "use strict";
  256 + var LOCAL_STORAGE;
  257 + try {
  258 + LOCAL_STORAGE = window.localStorage;
  259 + LOCAL_STORAGE.setItem("~~~", "!");
  260 + LOCAL_STORAGE.removeItem("~~~");
  261 + } catch (err) {
  262 + LOCAL_STORAGE = null;
  263 + }
  264 + function PersistentStorage(namespace, override) {
  265 + this.prefix = [ "__", namespace, "__" ].join("");
  266 + this.ttlKey = "__ttl__";
  267 + this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix));
  268 + this.ls = override || LOCAL_STORAGE;
  269 + !this.ls && this._noop();
  270 + }
  271 + _.mixin(PersistentStorage.prototype, {
  272 + _prefix: function(key) {
  273 + return this.prefix + key;
  274 + },
  275 + _ttlKey: function(key) {
  276 + return this._prefix(key) + this.ttlKey;
  277 + },
  278 + _noop: function() {
  279 + this.get = this.set = this.remove = this.clear = this.isExpired = _.noop;
  280 + },
  281 + _safeSet: function(key, val) {
  282 + try {
  283 + this.ls.setItem(key, val);
  284 + } catch (err) {
  285 + if (err.name === "QuotaExceededError") {
  286 + this.clear();
  287 + this._noop();
  288 + }
  289 + }
  290 + },
  291 + get: function(key) {
  292 + if (this.isExpired(key)) {
  293 + this.remove(key);
  294 + }
  295 + return decode(this.ls.getItem(this._prefix(key)));
  296 + },
  297 + set: function(key, val, ttl) {
  298 + if (_.isNumber(ttl)) {
  299 + this._safeSet(this._ttlKey(key), encode(now() + ttl));
  300 + } else {
  301 + this.ls.removeItem(this._ttlKey(key));
  302 + }
  303 + return this._safeSet(this._prefix(key), encode(val));
  304 + },
  305 + remove: function(key) {
  306 + this.ls.removeItem(this._ttlKey(key));
  307 + this.ls.removeItem(this._prefix(key));
  308 + return this;
  309 + },
  310 + clear: function() {
  311 + var i, keys = gatherMatchingKeys(this.keyMatcher);
  312 + for (i = keys.length; i--; ) {
  313 + this.remove(keys[i]);
  314 + }
  315 + return this;
  316 + },
  317 + isExpired: function(key) {
  318 + var ttl = decode(this.ls.getItem(this._ttlKey(key)));
  319 + return _.isNumber(ttl) && now() > ttl ? true : false;
  320 + }
  321 + });
  322 + return PersistentStorage;
  323 + function now() {
  324 + return new Date().getTime();
  325 + }
  326 + function encode(val) {
  327 + return JSON.stringify(_.isUndefined(val) ? null : val);
  328 + }
  329 + function decode(val) {
  330 + return $.parseJSON(val);
  331 + }
  332 + function gatherMatchingKeys(keyMatcher) {
  333 + var i, key, keys = [], len = LOCAL_STORAGE.length;
  334 + for (i = 0; i < len; i++) {
  335 + if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) {
  336 + keys.push(key.replace(keyMatcher, ""));
  337 + }
  338 + }
  339 + return keys;
  340 + }
  341 + }();
  342 + var Transport = function() {
  343 + "use strict";
  344 + var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10);
  345 + function Transport(o) {
  346 + o = o || {};
  347 + this.cancelled = false;
  348 + this.lastReq = null;
  349 + this._send = o.transport;
  350 + this._get = o.limiter ? o.limiter(this._get) : this._get;
  351 + this._cache = o.cache === false ? new LruCache(0) : sharedCache;
  352 + }
  353 + Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
  354 + maxPendingRequests = num;
  355 + };
  356 + Transport.resetCache = function resetCache() {
  357 + sharedCache.reset();
  358 + };
  359 + _.mixin(Transport.prototype, {
  360 + _fingerprint: function fingerprint(o) {
  361 + o = o || {};
  362 + return o.url + o.type + $.param(o.data || {});
  363 + },
  364 + _get: function(o, cb) {
  365 + var that = this, fingerprint, jqXhr;
  366 + fingerprint = this._fingerprint(o);
  367 + if (this.cancelled || fingerprint !== this.lastReq) {
  368 + return;
  369 + }
  370 + if (jqXhr = pendingRequests[fingerprint]) {
  371 + jqXhr.done(done).fail(fail);
  372 + } else if (pendingRequestsCount < maxPendingRequests) {
  373 + pendingRequestsCount++;
  374 + pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always);
  375 + } else {
  376 + this.onDeckRequestArgs = [].slice.call(arguments, 0);
  377 + }
  378 + function done(resp) {
  379 + cb(null, resp);
  380 + that._cache.set(fingerprint, resp);
  381 + }
  382 + function fail() {
  383 + cb(true);
  384 + }
  385 + function always() {
  386 + pendingRequestsCount--;
  387 + delete pendingRequests[fingerprint];
  388 + if (that.onDeckRequestArgs) {
  389 + that._get.apply(that, that.onDeckRequestArgs);
  390 + that.onDeckRequestArgs = null;
  391 + }
  392 + }
  393 + },
  394 + get: function(o, cb) {
  395 + var resp, fingerprint;
  396 + cb = cb || $.noop;
  397 + o = _.isString(o) ? {
  398 + url: o
  399 + } : o || {};
  400 + fingerprint = this._fingerprint(o);
  401 + this.cancelled = false;
  402 + this.lastReq = fingerprint;
  403 + if (resp = this._cache.get(fingerprint)) {
  404 + cb(null, resp);
  405 + } else {
  406 + this._get(o, cb);
  407 + }
  408 + },
  409 + cancel: function() {
  410 + this.cancelled = true;
  411 + }
  412 + });
  413 + return Transport;
  414 + }();
  415 + var SearchIndex = window.SearchIndex = function() {
  416 + "use strict";
  417 + var CHILDREN = "c", IDS = "i";
  418 + function SearchIndex(o) {
  419 + o = o || {};
  420 + if (!o.datumTokenizer || !o.queryTokenizer) {
  421 + $.error("datumTokenizer and queryTokenizer are both required");
  422 + }
  423 + this.identify = o.identify || _.stringify;
  424 + this.datumTokenizer = o.datumTokenizer;
  425 + this.queryTokenizer = o.queryTokenizer;
  426 + this.reset();
  427 + }
  428 + _.mixin(SearchIndex.prototype, {
  429 + bootstrap: function bootstrap(o) {
  430 + this.datums = o.datums;
  431 + this.trie = o.trie;
  432 + },
  433 + add: function(data) {
  434 + var that = this;
  435 + data = _.isArray(data) ? data : [ data ];
  436 + _.each(data, function(datum) {
  437 + var id, tokens;
  438 + that.datums[id = that.identify(datum)] = datum;
  439 + tokens = normalizeTokens(that.datumTokenizer(datum));
  440 + _.each(tokens, function(token) {
  441 + var node, chars, ch;
  442 + node = that.trie;
  443 + chars = token.split("");
  444 + while (ch = chars.shift()) {
  445 + node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode());
  446 + node[IDS].push(id);
  447 + }
  448 + });
  449 + });
  450 + },
  451 + get: function get(ids) {
  452 + var that = this;
  453 + return _.map(ids, function(id) {
  454 + return that.datums[id];
  455 + });
  456 + },
  457 + search: function search(query) {
  458 + var that = this, tokens, matches;
  459 + tokens = normalizeTokens(this.queryTokenizer(query));
  460 + _.each(tokens, function(token) {
  461 + var node, chars, ch, ids;
  462 + if (matches && matches.length === 0) {
  463 + return false;
  464 + }
  465 + node = that.trie;
  466 + chars = token.split("");
  467 + while (node && (ch = chars.shift())) {
  468 + node = node[CHILDREN][ch];
  469 + }
  470 + if (node && chars.length === 0) {
  471 + ids = node[IDS].slice(0);
  472 + matches = matches ? getIntersection(matches, ids) : ids;
  473 + } else {
  474 + matches = [];
  475 + return false;
  476 + }
  477 + });
  478 + return matches ? _.map(unique(matches), function(id) {
  479 + return that.datums[id];
  480 + }) : [];
  481 + },
  482 + all: function all() {
  483 + var values = [];
  484 + for (var key in this.datums) {
  485 + values.push(this.datums[key]);
  486 + }
  487 + return values;
  488 + },
  489 + reset: function reset() {
  490 + this.datums = {};
  491 + this.trie = newNode();
  492 + },
  493 + serialize: function serialize() {
  494 + return {
  495 + datums: this.datums,
  496 + trie: this.trie
  497 + };
  498 + }
  499 + });
  500 + return SearchIndex;
  501 + function normalizeTokens(tokens) {
  502 + tokens = _.filter(tokens, function(token) {
  503 + return !!token;
  504 + });
  505 + tokens = _.map(tokens, function(token) {
  506 + return token.toLowerCase();
  507 + });
  508 + return tokens;
  509 + }
  510 + function newNode() {
  511 + var node = {};
  512 + node[IDS] = [];
  513 + node[CHILDREN] = {};
  514 + return node;
  515 + }
  516 + function unique(array) {
  517 + var seen = {}, uniques = [];
  518 + for (var i = 0, len = array.length; i < len; i++) {
  519 + if (!seen[array[i]]) {
  520 + seen[array[i]] = true;
  521 + uniques.push(array[i]);
  522 + }
  523 + }
  524 + return uniques;
  525 + }
  526 + function getIntersection(arrayA, arrayB) {
  527 + var ai = 0, bi = 0, intersection = [];
  528 + arrayA = arrayA.sort();
  529 + arrayB = arrayB.sort();
  530 + var lenArrayA = arrayA.length, lenArrayB = arrayB.length;
  531 + while (ai < lenArrayA && bi < lenArrayB) {
  532 + if (arrayA[ai] < arrayB[bi]) {
  533 + ai++;
  534 + } else if (arrayA[ai] > arrayB[bi]) {
  535 + bi++;
  536 + } else {
  537 + intersection.push(arrayA[ai]);
  538 + ai++;
  539 + bi++;
  540 + }
  541 + }
  542 + return intersection;
  543 + }
  544 + }();
  545 + var Prefetch = function() {
  546 + "use strict";
  547 + var keys;
  548 + keys = {
  549 + data: "data",
  550 + protocol: "protocol",
  551 + thumbprint: "thumbprint"
  552 + };
  553 + function Prefetch(o) {
  554 + this.url = o.url;
  555 + this.ttl = o.ttl;
  556 + this.cache = o.cache;
  557 + this.prepare = o.prepare;
  558 + this.transform = o.transform;
  559 + this.transport = o.transport;
  560 + this.thumbprint = o.thumbprint;
  561 + this.storage = new PersistentStorage(o.cacheKey);
  562 + }
  563 + _.mixin(Prefetch.prototype, {
  564 + _settings: function settings() {
  565 + return {
  566 + url: this.url,
  567 + type: "GET",
  568 + dataType: "json"
  569 + };
  570 + },
  571 + store: function store(data) {
  572 + if (!this.cache) {
  573 + return;
  574 + }
  575 + this.storage.set(keys.data, data, this.ttl);
  576 + this.storage.set(keys.protocol, location.protocol, this.ttl);
  577 + this.storage.set(keys.thumbprint, this.thumbprint, this.ttl);
  578 + },
  579 + fromCache: function fromCache() {
  580 + var stored = {}, isExpired;
  581 + if (!this.cache) {
  582 + return null;
  583 + }
  584 + stored.data = this.storage.get(keys.data);
  585 + stored.protocol = this.storage.get(keys.protocol);
  586 + stored.thumbprint = this.storage.get(keys.thumbprint);
  587 + isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol;
  588 + return stored.data && !isExpired ? stored.data : null;
  589 + },
  590 + fromNetwork: function(cb) {
  591 + var that = this, settings;
  592 + if (!cb) {
  593 + return;
  594 + }
  595 + settings = this.prepare(this._settings());
  596 + this.transport(settings).fail(onError).done(onResponse);
  597 + function onError() {
  598 + cb(true);
  599 + }
  600 + function onResponse(resp) {
  601 + cb(null, that.transform(resp));
  602 + }
  603 + },
  604 + clear: function clear() {
  605 + this.storage.clear();
  606 + return this;
  607 + }
  608 + });
  609 + return Prefetch;
  610 + }();
  611 + var Remote = function() {
  612 + "use strict";
  613 + function Remote(o) {
  614 + this.url = o.url;
  615 + this.prepare = o.prepare;
  616 + this.transform = o.transform;
  617 + this.transport = new Transport({
  618 + cache: o.cache,
  619 + limiter: o.limiter,
  620 + transport: o.transport
  621 + });
  622 + }
  623 + _.mixin(Remote.prototype, {
  624 + _settings: function settings() {
  625 + return {
  626 + url: this.url,
  627 + type: "GET",
  628 + dataType: "json"
  629 + };
  630 + },
  631 + get: function get(query, cb) {
  632 + var that = this, settings;
  633 + if (!cb) {
  634 + return;
  635 + }
  636 + query = query || "";
  637 + settings = this.prepare(query, this._settings());
  638 + return this.transport.get(settings, onResponse);
  639 + function onResponse(err, resp) {
  640 + err ? cb([]) : cb(that.transform(resp));
  641 + }
  642 + },
  643 + cancelLastRequest: function cancelLastRequest() {
  644 + this.transport.cancel();
  645 + }
  646 + });
  647 + return Remote;
  648 + }();
  649 + var oParser = function() {
  650 + "use strict";
  651 + return function parse(o) {
  652 + var defaults, sorter;
  653 + defaults = {
  654 + initialize: true,
  655 + identify: _.stringify,
  656 + datumTokenizer: null,
  657 + queryTokenizer: null,
  658 + sufficient: 5,
  659 + sorter: null,
  660 + local: [],
  661 + prefetch: null,
  662 + remote: null
  663 + };
  664 + o = _.mixin(defaults, o || {});
  665 + !o.datumTokenizer && $.error("datumTokenizer is required");
  666 + !o.queryTokenizer && $.error("queryTokenizer is required");
  667 + sorter = o.sorter;
  668 + o.sorter = sorter ? function(x) {
  669 + return x.sort(sorter);
  670 + } : _.identity;
  671 + o.local = _.isFunction(o.local) ? o.local() : o.local;
  672 + o.prefetch = parsePrefetch(o.prefetch);
  673 + o.remote = parseRemote(o.remote);
  674 + return o;
  675 + };
  676 + function parsePrefetch(o) {
  677 + var defaults;
  678 + if (!o) {
  679 + return null;
  680 + }
  681 + defaults = {
  682 + url: null,
  683 + ttl: 24 * 60 * 60 * 1e3,
  684 + cache: true,
  685 + cacheKey: null,
  686 + thumbprint: "",
  687 + prepare: _.identity,
  688 + transform: _.identity,
  689 + transport: null
  690 + };
  691 + o = _.isString(o) ? {
  692 + url: o
  693 + } : o;
  694 + o = _.mixin(defaults, o);
  695 + !o.url && $.error("prefetch requires url to be set");
  696 + o.transform = o.filter || o.transform;
  697 + o.cacheKey = o.cacheKey || o.url;
  698 + o.thumbprint = VERSION + o.thumbprint;
  699 + o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
  700 + return o;
  701 + }
  702 + function parseRemote(o) {
  703 + var defaults;
  704 + if (!o) {
  705 + return;
  706 + }
  707 + defaults = {
  708 + url: null,
  709 + cache: true,
  710 + prepare: null,
  711 + replace: null,
  712 + wildcard: null,
  713 + limiter: null,
  714 + rateLimitBy: "debounce",
  715 + rateLimitWait: 300,
  716 + transform: _.identity,
  717 + transport: null
  718 + };
  719 + o = _.isString(o) ? {
  720 + url: o
  721 + } : o;
  722 + o = _.mixin(defaults, o);
  723 + !o.url && $.error("remote requires url to be set");
  724 + o.transform = o.filter || o.transform;
  725 + o.prepare = toRemotePrepare(o);
  726 + o.limiter = toLimiter(o);
  727 + o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
  728 + delete o.replace;
  729 + delete o.wildcard;
  730 + delete o.rateLimitBy;
  731 + delete o.rateLimitWait;
  732 + return o;
  733 + }
  734 + function toRemotePrepare(o) {
  735 + var prepare, replace, wildcard;
  736 + prepare = o.prepare;
  737 + replace = o.replace;
  738 + wildcard = o.wildcard;
  739 + if (prepare) {
  740 + return prepare;
  741 + }
  742 + if (replace) {
  743 + prepare = prepareByReplace;
  744 + } else if (o.wildcard) {
  745 + prepare = prepareByWildcard;
  746 + } else {
  747 + prepare = idenityPrepare;
  748 + }
  749 + return prepare;
  750 + function prepareByReplace(query, settings) {
  751 + settings.url = replace(settings.url, query);
  752 + return settings;
  753 + }
  754 + function prepareByWildcard(query, settings) {
  755 + settings.url = settings.url.replace(wildcard, encodeURIComponent(query));
  756 + return settings;
  757 + }
  758 + function idenityPrepare(query, settings) {
  759 + return settings;
  760 + }
  761 + }
  762 + function toLimiter(o) {
  763 + var limiter, method, wait;
  764 + limiter = o.limiter;
  765 + method = o.rateLimitBy;
  766 + wait = o.rateLimitWait;
  767 + if (!limiter) {
  768 + limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait);
  769 + }
  770 + return limiter;
  771 + function debounce(wait) {
  772 + return function debounce(fn) {
  773 + return _.debounce(fn, wait);
  774 + };
  775 + }
  776 + function throttle(wait) {
  777 + return function throttle(fn) {
  778 + return _.throttle(fn, wait);
  779 + };
  780 + }
  781 + }
  782 + function callbackToDeferred(fn) {
  783 + return function wrapper(o) {
  784 + var deferred = $.Deferred();
  785 + fn(o, onSuccess, onError);
  786 + return deferred;
  787 + function onSuccess(resp) {
  788 + _.defer(function() {
  789 + deferred.resolve(resp);
  790 + });
  791 + }
  792 + function onError(err) {
  793 + _.defer(function() {
  794 + deferred.reject(err);
  795 + });
  796 + }
  797 + };
  798 + }
  799 + }();
  800 + var Bloodhound = function() {
  801 + "use strict";
  802 + var old;
  803 + old = window && window.Bloodhound;
  804 + function Bloodhound(o) {
  805 + o = oParser(o);
  806 + this.sorter = o.sorter;
  807 + this.identify = o.identify;
  808 + this.sufficient = o.sufficient;
  809 + this.local = o.local;
  810 + this.remote = o.remote ? new Remote(o.remote) : null;
  811 + this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null;
  812 + this.index = new SearchIndex({
  813 + identify: this.identify,
  814 + datumTokenizer: o.datumTokenizer,
  815 + queryTokenizer: o.queryTokenizer
  816 + });
  817 + o.initialize !== false && this.initialize();
  818 + }
  819 + Bloodhound.noConflict = function noConflict() {
  820 + window && (window.Bloodhound = old);
  821 + return Bloodhound;
  822 + };
  823 + Bloodhound.tokenizers = tokenizers;
  824 + _.mixin(Bloodhound.prototype, {
  825 + __ttAdapter: function ttAdapter() {
  826 + var that = this;
  827 + return this.remote ? withAsync : withoutAsync;
  828 + function withAsync(query, sync, async) {
  829 + return that.search(query, sync, async);
  830 + }
  831 + function withoutAsync(query, sync) {
  832 + return that.search(query, sync);
  833 + }
  834 + },
  835 + _loadPrefetch: function loadPrefetch() {
  836 + var that = this, deferred, serialized;
  837 + deferred = $.Deferred();
  838 + if (!this.prefetch) {
  839 + deferred.resolve();
  840 + } else if (serialized = this.prefetch.fromCache()) {
  841 + this.index.bootstrap(serialized);
  842 + deferred.resolve();
  843 + } else {
  844 + this.prefetch.fromNetwork(done);
  845 + }
  846 + return deferred.promise();
  847 + function done(err, data) {
  848 + if (err) {
  849 + return deferred.reject();
  850 + }
  851 + that.add(data);
  852 + that.prefetch.store(that.index.serialize());
  853 + deferred.resolve();
  854 + }
  855 + },
  856 + _initialize: function initialize() {
  857 + var that = this, deferred;
  858 + this.clear();
  859 + (this.initPromise = this._loadPrefetch()).done(addLocalToIndex);
  860 + return this.initPromise;
  861 + function addLocalToIndex() {
  862 + that.add(that.local);
  863 + }
  864 + },
  865 + initialize: function initialize(force) {
  866 + return !this.initPromise || force ? this._initialize() : this.initPromise;
  867 + },
  868 + add: function add(data) {
  869 + this.index.add(data);
  870 + return this;
  871 + },
  872 + get: function get(ids) {
  873 + ids = _.isArray(ids) ? ids : [].slice.call(arguments);
  874 + return this.index.get(ids);
  875 + },
  876 + search: function search(query, sync, async) {
  877 + var that = this, local;
  878 + local = this.sorter(this.index.search(query));
  879 + sync(this.remote ? local.slice() : local);
  880 + if (this.remote && local.length < this.sufficient) {
  881 + this.remote.get(query, processRemote);
  882 + } else if (this.remote) {
  883 + this.remote.cancelLastRequest();
  884 + }
  885 + return this;
  886 + function processRemote(remote) {
  887 + var nonDuplicates = [];
  888 + _.each(remote, function(r) {
  889 + !_.some(local, function(l) {
  890 + return that.identify(r) === that.identify(l);
  891 + }) && nonDuplicates.push(r);
  892 + });
  893 + async && async(nonDuplicates);
  894 + }
  895 + },
  896 + all: function all() {
  897 + return this.index.all();
  898 + },
  899 + clear: function clear() {
  900 + this.index.reset();
  901 + return this;
  902 + },
  903 + clearPrefetchCache: function clearPrefetchCache() {
  904 + this.prefetch && this.prefetch.clear();
  905 + return this;
  906 + },
  907 + clearRemoteCache: function clearRemoteCache() {
  908 + Transport.resetCache();
  909 + return this;
  910 + },
  911 + ttAdapter: function ttAdapter() {
  912 + return this.__ttAdapter();
  913 + }
  914 + });
  915 + return Bloodhound;
  916 + }();
  917 + return Bloodhound;
  918 +});
  919 +
  920 +(function(root, factory) {
  921 + if (typeof define === "function" && define.amd) {
  922 + define("typeahead.js", [ "jquery" ], function(a0) {
  923 + return factory(a0);
  924 + });
  925 + } else if (typeof exports === "object") {
  926 + module.exports = factory(require("jquery"));
  927 + } else {
  928 + factory(jQuery);
  929 + }
  930 +})(this, function($) {
  931 + var _ = function() {
  932 + "use strict";
  933 + return {
  934 + isMsie: function() {
  935 + return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
  936 + },
  937 + isBlankString: function(str) {
  938 + return !str || /^\s*$/.test(str);
  939 + },
  940 + escapeRegExChars: function(str) {
  941 + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
  942 + },
  943 + isString: function(obj) {
  944 + return typeof obj === "string";
  945 + },
  946 + isNumber: function(obj) {
  947 + return typeof obj === "number";
  948 + },
  949 + isArray: $.isArray,
  950 + isFunction: $.isFunction,
  951 + isObject: $.isPlainObject,
  952 + isUndefined: function(obj) {
  953 + return typeof obj === "undefined";
  954 + },
  955 + isElement: function(obj) {
  956 + return !!(obj && obj.nodeType === 1);
  957 + },
  958 + isJQuery: function(obj) {
  959 + return obj instanceof $;
  960 + },
  961 + toStr: function toStr(s) {
  962 + return _.isUndefined(s) || s === null ? "" : s + "";
  963 + },
  964 + bind: $.proxy,
  965 + each: function(collection, cb) {
  966 + $.each(collection, reverseArgs);
  967 + function reverseArgs(index, value) {
  968 + return cb(value, index);
  969 + }
  970 + },
  971 + map: $.map,
  972 + filter: $.grep,
  973 + every: function(obj, test) {
  974 + var result = true;
  975 + if (!obj) {
  976 + return result;
  977 + }
  978 + $.each(obj, function(key, val) {
  979 + if (!(result = test.call(null, val, key, obj))) {
  980 + return false;
  981 + }
  982 + });
  983 + return !!result;
  984 + },
  985 + some: function(obj, test) {
  986 + var result = false;
  987 + if (!obj) {
  988 + return result;
  989 + }
  990 + $.each(obj, function(key, val) {
  991 + if (result = test.call(null, val, key, obj)) {
  992 + return false;
  993 + }
  994 + });
  995 + return !!result;
  996 + },
  997 + mixin: $.extend,
  998 + identity: function(x) {
  999 + return x;
  1000 + },
  1001 + clone: function(obj) {
  1002 + return $.extend(true, {}, obj);
  1003 + },
  1004 + getIdGenerator: function() {
  1005 + var counter = 0;
  1006 + return function() {
  1007 + return counter++;
  1008 + };
  1009 + },
  1010 + templatify: function templatify(obj) {
  1011 + return $.isFunction(obj) ? obj : template;
  1012 + function template() {
  1013 + return String(obj);
  1014 + }
  1015 + },
  1016 + defer: function(fn) {
  1017 + setTimeout(fn, 0);
  1018 + },
  1019 + debounce: function(func, wait, immediate) {
  1020 + var timeout, result;
  1021 + return function() {
  1022 + var context = this, args = arguments, later, callNow;
  1023 + later = function() {
  1024 + timeout = null;
  1025 + if (!immediate) {
  1026 + result = func.apply(context, args);
  1027 + }
  1028 + };
  1029 + callNow = immediate && !timeout;
  1030 + clearTimeout(timeout);
  1031 + timeout = setTimeout(later, wait);
  1032 + if (callNow) {
  1033 + result = func.apply(context, args);
  1034 + }
  1035 + return result;
  1036 + };
  1037 + },
  1038 + throttle: function(func, wait) {
  1039 + var context, args, timeout, result, previous, later;
  1040 + previous = 0;
  1041 + later = function() {
  1042 + previous = new Date();
  1043 + timeout = null;
  1044 + result = func.apply(context, args);
  1045 + };
  1046 + return function() {
  1047 + var now = new Date(), remaining = wait - (now - previous);
  1048 + context = this;
  1049 + args = arguments;
  1050 + if (remaining <= 0) {
  1051 + clearTimeout(timeout);
  1052 + timeout = null;
  1053 + previous = now;
  1054 + result = func.apply(context, args);
  1055 + } else if (!timeout) {
  1056 + timeout = setTimeout(later, remaining);
  1057 + }
  1058 + return result;
  1059 + };
  1060 + },
  1061 + stringify: function(val) {
  1062 + return _.isString(val) ? val : JSON.stringify(val);
  1063 + },
  1064 + noop: function() {}
  1065 + };
  1066 + }();
  1067 + var WWW = function() {
  1068 + "use strict";
  1069 + var defaultClassNames = {
  1070 + wrapper: "twitter-typeahead",
  1071 + input: "tt-input",
  1072 + hint: "tt-hint",
  1073 + menu: "tt-menu",
  1074 + dataset: "tt-dataset",
  1075 + suggestion: "tt-suggestion",
  1076 + selectable: "tt-selectable",
  1077 + empty: "tt-empty",
  1078 + open: "tt-open",
  1079 + cursor: "tt-cursor",
  1080 + highlight: "tt-highlight"
  1081 + };
  1082 + return build;
  1083 + function build(o) {
  1084 + var www, classes;
  1085 + classes = _.mixin({}, defaultClassNames, o);
  1086 + www = {
  1087 + css: buildCss(),
  1088 + classes: classes,
  1089 + html: buildHtml(classes),
  1090 + selectors: buildSelectors(classes)
  1091 + };
  1092 + return {
  1093 + css: www.css,
  1094 + html: www.html,
  1095 + classes: www.classes,
  1096 + selectors: www.selectors,
  1097 + mixin: function(o) {
  1098 + _.mixin(o, www);
  1099 + }
  1100 + };
  1101 + }
  1102 + function buildHtml(c) {
  1103 + return {
  1104 + wrapper: '<span class="' + c.wrapper + '"></span>',
  1105 + menu: '<div class="' + c.menu + '"></div>'
  1106 + };
  1107 + }
  1108 + function buildSelectors(classes) {
  1109 + var selectors = {};
  1110 + _.each(classes, function(v, k) {
  1111 + selectors[k] = "." + v;
  1112 + });
  1113 + return selectors;
  1114 + }
  1115 + function buildCss() {
  1116 + var css = {
  1117 + wrapper: {
  1118 + position: "relative",
  1119 + display: "inline-block"
  1120 + },
  1121 + hint: {
  1122 + position: "absolute",
  1123 + top: "0",
  1124 + left: "0",
  1125 + borderColor: "transparent",
  1126 + boxShadow: "none",
  1127 + opacity: "1"
  1128 + },
  1129 + input: {
  1130 + position: "relative",
  1131 + verticalAlign: "top",
  1132 + backgroundColor: "transparent"
  1133 + },
  1134 + inputWithNoHint: {
  1135 + position: "relative",
  1136 + verticalAlign: "top"
  1137 + },
  1138 + menu: {
  1139 + position: "absolute",
  1140 + top: "100%",
  1141 + left: "0",
  1142 + zIndex: "100",
  1143 + display: "none"
  1144 + },
  1145 + ltr: {
  1146 + left: "0",
  1147 + right: "auto"
  1148 + },
  1149 + rtl: {
  1150 + left: "auto",
  1151 + right: " 0"
  1152 + }
  1153 + };
  1154 + if (_.isMsie()) {
  1155 + _.mixin(css.input, {
  1156 + backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
  1157 + });
  1158 + }
  1159 + return css;
  1160 + }
  1161 + }();
  1162 + var EventBus = function() {
  1163 + "use strict";
  1164 + var namespace, deprecationMap;
  1165 + namespace = "typeahead:";
  1166 + deprecationMap = {
  1167 + render: "rendered",
  1168 + cursorchange: "cursorchanged",
  1169 + select: "selected",
  1170 + autocomplete: "autocompleted"
  1171 + };
  1172 + function EventBus(o) {
  1173 + if (!o || !o.el) {
  1174 + $.error("EventBus initialized without el");
  1175 + }
  1176 + this.$el = $(o.el);
  1177 + }
  1178 + _.mixin(EventBus.prototype, {
  1179 + _trigger: function(type, args) {
  1180 + var $e;
  1181 + $e = $.Event(namespace + type);
  1182 + (args = args || []).unshift($e);
  1183 + this.$el.trigger.apply(this.$el, args);
  1184 + return $e;
  1185 + },
  1186 + before: function(type) {
  1187 + var args, $e;
  1188 + args = [].slice.call(arguments, 1);
  1189 + $e = this._trigger("before" + type, args);
  1190 + return $e.isDefaultPrevented();
  1191 + },
  1192 + trigger: function(type) {
  1193 + var deprecatedType;
  1194 + this._trigger(type, [].slice.call(arguments, 1));
  1195 + if (deprecatedType = deprecationMap[type]) {
  1196 + this._trigger(deprecatedType, [].slice.call(arguments, 1));
  1197 + }
  1198 + }
  1199 + });
  1200 + return EventBus;
  1201 + }();
  1202 + var EventEmitter = function() {
  1203 + "use strict";
  1204 + var splitter = /\s+/, nextTick = getNextTick();
  1205 + return {
  1206 + onSync: onSync,
  1207 + onAsync: onAsync,
  1208 + off: off,
  1209 + trigger: trigger
  1210 + };
  1211 + function on(method, types, cb, context) {
  1212 + var type;
  1213 + if (!cb) {
  1214 + return this;
  1215 + }
  1216 + types = types.split(splitter);
  1217 + cb = context ? bindContext(cb, context) : cb;
  1218 + this._callbacks = this._callbacks || {};
  1219 + while (type = types.shift()) {
  1220 + this._callbacks[type] = this._callbacks[type] || {
  1221 + sync: [],
  1222 + async: []
  1223 + };
  1224 + this._callbacks[type][method].push(cb);
  1225 + }
  1226 + return this;
  1227 + }
  1228 + function onAsync(types, cb, context) {
  1229 + return on.call(this, "async", types, cb, context);
  1230 + }
  1231 + function onSync(types, cb, context) {
  1232 + return on.call(this, "sync", types, cb, context);
  1233 + }
  1234 + function off(types) {
  1235 + var type;
  1236 + if (!this._callbacks) {
  1237 + return this;
  1238 + }
  1239 + types = types.split(splitter);
  1240 + while (type = types.shift()) {
  1241 + delete this._callbacks[type];
  1242 + }
  1243 + return this;
  1244 + }
  1245 + function trigger(types) {
  1246 + var type, callbacks, args, syncFlush, asyncFlush;
  1247 + if (!this._callbacks) {
  1248 + return this;
  1249 + }
  1250 + types = types.split(splitter);
  1251 + args = [].slice.call(arguments, 1);
  1252 + while ((type = types.shift()) && (callbacks = this._callbacks[type])) {
  1253 + syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));
  1254 + asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));
  1255 + syncFlush() && nextTick(asyncFlush);
  1256 + }
  1257 + return this;
  1258 + }
  1259 + function getFlush(callbacks, context, args) {
  1260 + return flush;
  1261 + function flush() {
  1262 + var cancelled;
  1263 + for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
  1264 + cancelled = callbacks[i].apply(context, args) === false;
  1265 + }
  1266 + return !cancelled;
  1267 + }
  1268 + }
  1269 + function getNextTick() {
  1270 + var nextTickFn;
  1271 + if (window.setImmediate) {
  1272 + nextTickFn = function nextTickSetImmediate(fn) {
  1273 + setImmediate(function() {
  1274 + fn();
  1275 + });
  1276 + };
  1277 + } else {
  1278 + nextTickFn = function nextTickSetTimeout(fn) {
  1279 + setTimeout(function() {
  1280 + fn();
  1281 + }, 0);
  1282 + };
  1283 + }
  1284 + return nextTickFn;
  1285 + }
  1286 + function bindContext(fn, context) {
  1287 + return fn.bind ? fn.bind(context) : function() {
  1288 + fn.apply(context, [].slice.call(arguments, 0));
  1289 + };
  1290 + }
  1291 + }();
  1292 + var highlight = function(doc) {
  1293 + "use strict";
  1294 + var defaults = {
  1295 + node: null,
  1296 + pattern: null,
  1297 + tagName: "strong",
  1298 + className: null,
  1299 + wordsOnly: false,
  1300 + caseSensitive: false
  1301 + };
  1302 + return function hightlight(o) {
  1303 + var regex;
  1304 + o = _.mixin({}, defaults, o);
  1305 + if (!o.node || !o.pattern) {
  1306 + return;
  1307 + }
  1308 + o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];
  1309 + regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
  1310 + traverse(o.node, hightlightTextNode);
  1311 + function hightlightTextNode(textNode) {
  1312 + var match, patternNode, wrapperNode;
  1313 + if (match = regex.exec(textNode.data)) {
  1314 + wrapperNode = doc.createElement(o.tagName);
  1315 + o.className && (wrapperNode.className = o.className);
  1316 + patternNode = textNode.splitText(match.index);
  1317 + patternNode.splitText(match[0].length);
  1318 + wrapperNode.appendChild(patternNode.cloneNode(true));
  1319 + textNode.parentNode.replaceChild(wrapperNode, patternNode);
  1320 + }
  1321 + return !!match;
  1322 + }
  1323 + function traverse(el, hightlightTextNode) {
  1324 + var childNode, TEXT_NODE_TYPE = 3;
  1325 + for (var i = 0; i < el.childNodes.length; i++) {
  1326 + childNode = el.childNodes[i];
  1327 + if (childNode.nodeType === TEXT_NODE_TYPE) {
  1328 + i += hightlightTextNode(childNode) ? 1 : 0;
  1329 + } else {
  1330 + traverse(childNode, hightlightTextNode);
  1331 + }
  1332 + }
  1333 + }
  1334 + };
  1335 + function getRegex(patterns, caseSensitive, wordsOnly) {
  1336 + var escapedPatterns = [], regexStr;
  1337 + for (var i = 0, len = patterns.length; i < len; i++) {
  1338 + escapedPatterns.push(_.escapeRegExChars(patterns[i]));
  1339 + }
  1340 + regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
  1341 + return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i");
  1342 + }
  1343 + }(window.document);
  1344 + var Input = function() {
  1345 + "use strict";
  1346 + var specialKeyCodeMap;
  1347 + specialKeyCodeMap = {
  1348 + 9: "tab",
  1349 + 27: "esc",
  1350 + 37: "left",
  1351 + 39: "right",
  1352 + 13: "enter",
  1353 + 38: "up",
  1354 + 40: "down"
  1355 + };
  1356 + function Input(o, www) {
  1357 + o = o || {};
  1358 + if (!o.input) {
  1359 + $.error("input is missing");
  1360 + }
  1361 + www.mixin(this);
  1362 + this.$hint = $(o.hint);
  1363 + this.$input = $(o.input);
  1364 + this.query = this.$input.val();
  1365 + this.queryWhenFocused = this.hasFocus() ? this.query : null;
  1366 + this.$overflowHelper = buildOverflowHelper(this.$input);
  1367 + this._checkLanguageDirection();
  1368 + if (this.$hint.length === 0) {
  1369 + this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
  1370 + }
  1371 + }
  1372 + Input.normalizeQuery = function(str) {
  1373 + return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
  1374 + };
  1375 + _.mixin(Input.prototype, EventEmitter, {
  1376 + _onBlur: function onBlur() {
  1377 + this.resetInputValue();
  1378 + this.trigger("blurred");
  1379 + },
  1380 + _onFocus: function onFocus() {
  1381 + this.queryWhenFocused = this.query;
  1382 + this.trigger("focused");
  1383 + },
  1384 + _onKeydown: function onKeydown($e) {
  1385 + var keyName = specialKeyCodeMap[$e.which || $e.keyCode];
  1386 + this._managePreventDefault(keyName, $e);
  1387 + if (keyName && this._shouldTrigger(keyName, $e)) {
  1388 + this.trigger(keyName + "Keyed", $e);
  1389 + }
  1390 + },
  1391 + _onInput: function onInput() {
  1392 + this._setQuery(this.getInputValue());
  1393 + this.clearHintIfInvalid();
  1394 + this._checkLanguageDirection();
  1395 + },
  1396 + _managePreventDefault: function managePreventDefault(keyName, $e) {
  1397 + var preventDefault;
  1398 + switch (keyName) {
  1399 + case "up":
  1400 + case "down":
  1401 + preventDefault = !withModifier($e);
  1402 + break;
  1403 +
  1404 + default:
  1405 + preventDefault = false;
  1406 + }
  1407 + preventDefault && $e.preventDefault();
  1408 + },
  1409 + _shouldTrigger: function shouldTrigger(keyName, $e) {
  1410 + var trigger;
  1411 + switch (keyName) {
  1412 + case "tab":
  1413 + trigger = !withModifier($e);
  1414 + break;
  1415 +
  1416 + default:
  1417 + trigger = true;
  1418 + }
  1419 + return trigger;
  1420 + },
  1421 + _checkLanguageDirection: function checkLanguageDirection() {
  1422 + var dir = (this.$input.css("direction") || "ltr").toLowerCase();
  1423 + if (this.dir !== dir) {
  1424 + this.dir = dir;
  1425 + this.$hint.attr("dir", dir);
  1426 + this.trigger("langDirChanged", dir);
  1427 + }
  1428 + },
  1429 + _setQuery: function setQuery(val, silent) {
  1430 + var areEquivalent, hasDifferentWhitespace;
  1431 + areEquivalent = areQueriesEquivalent(val, this.query);
  1432 + hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false;
  1433 + this.query = val;
  1434 + if (!silent && !areEquivalent) {
  1435 + this.trigger("queryChanged", this.query);
  1436 + } else if (!silent && hasDifferentWhitespace) {
  1437 + this.trigger("whitespaceChanged", this.query);
  1438 + }
  1439 + },
  1440 + bind: function() {
  1441 + var that = this, onBlur, onFocus, onKeydown, onInput;
  1442 + onBlur = _.bind(this._onBlur, this);
  1443 + onFocus = _.bind(this._onFocus, this);
  1444 + onKeydown = _.bind(this._onKeydown, this);
  1445 + onInput = _.bind(this._onInput, this);
  1446 + this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
  1447 + if (!_.isMsie() || _.isMsie() > 9) {
  1448 + this.$input.on("input.tt", onInput);
  1449 + } else {
  1450 + this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
  1451 + if (specialKeyCodeMap[$e.which || $e.keyCode]) {
  1452 + return;
  1453 + }
  1454 + _.defer(_.bind(that._onInput, that, $e));
  1455 + });
  1456 + }
  1457 + return this;
  1458 + },
  1459 + focus: function focus() {
  1460 + this.$input.focus();
  1461 + },
  1462 + blur: function blur() {
  1463 + this.$input.blur();
  1464 + },
  1465 + getLangDir: function getLangDir() {
  1466 + return this.dir;
  1467 + },
  1468 + getQuery: function getQuery() {
  1469 + return this.query || "";
  1470 + },
  1471 + setQuery: function setQuery(val, silent) {
  1472 + this.setInputValue(val);
  1473 + this._setQuery(val, silent);
  1474 + },
  1475 + hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() {
  1476 + return this.query !== this.queryWhenFocused;
  1477 + },
  1478 + getInputValue: function getInputValue() {
  1479 + return this.$input.val();
  1480 + },
  1481 + setInputValue: function setInputValue(value) {
  1482 + this.$input.val(value);
  1483 + this.clearHintIfInvalid();
  1484 + this._checkLanguageDirection();
  1485 + },
  1486 + resetInputValue: function resetInputValue() {
  1487 + this.setInputValue(this.query);
  1488 + },
  1489 + getHint: function getHint() {
  1490 + return this.$hint.val();
  1491 + },
  1492 + setHint: function setHint(value) {
  1493 + this.$hint.val(value);
  1494 + },
  1495 + clearHint: function clearHint() {
  1496 + this.setHint("");
  1497 + },
  1498 + clearHintIfInvalid: function clearHintIfInvalid() {
  1499 + var val, hint, valIsPrefixOfHint, isValid;
  1500 + val = this.getInputValue();
  1501 + hint = this.getHint();
  1502 + valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;
  1503 + isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow();
  1504 + !isValid && this.clearHint();
  1505 + },
  1506 + hasFocus: function hasFocus() {
  1507 + return this.$input.is(":focus");
  1508 + },
  1509 + hasOverflow: function hasOverflow() {
  1510 + var constraint = this.$input.width() - 2;
  1511 + this.$overflowHelper.text(this.getInputValue());
  1512 + return this.$overflowHelper.width() >= constraint;
  1513 + },
  1514 + isCursorAtEnd: function() {
  1515 + var valueLength, selectionStart, range;
  1516 + valueLength = this.$input.val().length;
  1517 + selectionStart = this.$input[0].selectionStart;
  1518 + if (_.isNumber(selectionStart)) {
  1519 + return selectionStart === valueLength;
  1520 + } else if (document.selection) {
  1521 + range = document.selection.createRange();
  1522 + range.moveStart("character", -valueLength);
  1523 + return valueLength === range.text.length;
  1524 + }
  1525 + return true;
  1526 + },
  1527 + destroy: function destroy() {
  1528 + this.$hint.off(".tt");
  1529 + this.$input.off(".tt");
  1530 + this.$overflowHelper.remove();
  1531 + this.$hint = this.$input = this.$overflowHelper = $("<div>");
  1532 + }
  1533 + });
  1534 + return Input;
  1535 + function buildOverflowHelper($input) {
  1536 + return $('<pre aria-hidden="true"></pre>').css({
  1537 + position: "absolute",
  1538 + visibility: "hidden",
  1539 + whiteSpace: "pre",
  1540 + fontFamily: $input.css("font-family"),
  1541 + fontSize: $input.css("font-size"),
  1542 + fontStyle: $input.css("font-style"),
  1543 + fontVariant: $input.css("font-variant"),
  1544 + fontWeight: $input.css("font-weight"),
  1545 + wordSpacing: $input.css("word-spacing"),
  1546 + letterSpacing: $input.css("letter-spacing"),
  1547 + textIndent: $input.css("text-indent"),
  1548 + textRendering: $input.css("text-rendering"),
  1549 + textTransform: $input.css("text-transform")
  1550 + }).insertAfter($input);
  1551 + }
  1552 + function areQueriesEquivalent(a, b) {
  1553 + return Input.normalizeQuery(a) === Input.normalizeQuery(b);
  1554 + }
  1555 + function withModifier($e) {
  1556 + return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
  1557 + }
  1558 + }();
  1559 + var Dataset = function() {
  1560 + "use strict";
  1561 + var keys, nameGenerator;
  1562 + keys = {
  1563 + val: "tt-selectable-display",
  1564 + obj: "tt-selectable-object"
  1565 + };
  1566 + nameGenerator = _.getIdGenerator();
  1567 + function Dataset(o, www) {
  1568 + o = o || {};
  1569 + o.templates = o.templates || {};
  1570 + o.templates.notFound = o.templates.notFound || o.templates.empty;
  1571 + if (!o.source) {
  1572 + $.error("missing source");
  1573 + }
  1574 + if (!o.node) {
  1575 + $.error("missing node");
  1576 + }
  1577 + if (o.name && !isValidName(o.name)) {
  1578 + $.error("invalid dataset name: " + o.name);
  1579 + }
  1580 + www.mixin(this);
  1581 + this.highlight = !!o.highlight;
  1582 + this.name = o.name || nameGenerator();
  1583 + this.limit = o.limit || 5;
  1584 + this.displayFn = getDisplayFn(o.display || o.displayKey);
  1585 + this.templates = getTemplates(o.templates, this.displayFn);
  1586 + this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source;
  1587 + this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async;
  1588 + this._resetLastSuggestion();
  1589 + this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name);
  1590 + }
  1591 + Dataset.extractData = function extractData(el) {
  1592 + var $el = $(el);
  1593 + if ($el.data(keys.obj)) {
  1594 + return {
  1595 + val: $el.data(keys.val) || "",
  1596 + obj: $el.data(keys.obj) || null
  1597 + };
  1598 + }
  1599 + return null;
  1600 + };
  1601 + _.mixin(Dataset.prototype, EventEmitter, {
  1602 + _overwrite: function overwrite(query, suggestions) {
  1603 + suggestions = suggestions || [];
  1604 + if (suggestions.length) {
  1605 + this._renderSuggestions(query, suggestions);
  1606 + } else if (this.async && this.templates.pending) {
  1607 + this._renderPending(query);
  1608 + } else if (!this.async && this.templates.notFound) {
  1609 + this._renderNotFound(query);
  1610 + } else {
  1611 + this._empty();
  1612 + }
  1613 + this.trigger("rendered", this.name, suggestions, false);
  1614 + },
  1615 + _append: function append(query, suggestions) {
  1616 + suggestions = suggestions || [];
  1617 + if (suggestions.length && this.$lastSuggestion.length) {
  1618 + this._appendSuggestions(query, suggestions);
  1619 + } else if (suggestions.length) {
  1620 + this._renderSuggestions(query, suggestions);
  1621 + } else if (!this.$lastSuggestion.length && this.templates.notFound) {
  1622 + this._renderNotFound(query);
  1623 + }
  1624 + this.trigger("rendered", this.name, suggestions, true);
  1625 + },
  1626 + _renderSuggestions: function renderSuggestions(query, suggestions) {
  1627 + var $fragment;
  1628 + $fragment = this._getSuggestionsFragment(query, suggestions);
  1629 + this.$lastSuggestion = $fragment.children().last();
  1630 + this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions));
  1631 + },
  1632 + _appendSuggestions: function appendSuggestions(query, suggestions) {
  1633 + var $fragment, $lastSuggestion;
  1634 + $fragment = this._getSuggestionsFragment(query, suggestions);
  1635 + $lastSuggestion = $fragment.children().last();
  1636 + this.$lastSuggestion.after($fragment);
  1637 + this.$lastSuggestion = $lastSuggestion;
  1638 + },
  1639 + _renderPending: function renderPending(query) {
  1640 + var template = this.templates.pending;
  1641 + this._resetLastSuggestion();
  1642 + template && this.$el.html(template({
  1643 + query: query,
  1644 + dataset: this.name
  1645 + }));
  1646 + },
  1647 + _renderNotFound: function renderNotFound(query) {
  1648 + var template = this.templates.notFound;
  1649 + this._resetLastSuggestion();
  1650 + template && this.$el.html(template({
  1651 + query: query,
  1652 + dataset: this.name
  1653 + }));
  1654 + },
  1655 + _empty: function empty() {
  1656 + this.$el.empty();
  1657 + this._resetLastSuggestion();
  1658 + },
  1659 + _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) {
  1660 + var that = this, fragment;
  1661 + fragment = document.createDocumentFragment();
  1662 + _.each(suggestions, function getSuggestionNode(suggestion) {
  1663 + var $el, context;
  1664 + context = that._injectQuery(query, suggestion);
  1665 + $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable);
  1666 + fragment.appendChild($el[0]);
  1667 + });
  1668 + this.highlight && highlight({
  1669 + className: this.classes.highlight,
  1670 + node: fragment,
  1671 + pattern: query
  1672 + });
  1673 + return $(fragment);
  1674 + },
  1675 + _getFooter: function getFooter(query, suggestions) {
  1676 + return this.templates.footer ? this.templates.footer({
  1677 + query: query,
  1678 + suggestions: suggestions,
  1679 + dataset: this.name
  1680 + }) : null;
  1681 + },
  1682 + _getHeader: function getHeader(query, suggestions) {
  1683 + return this.templates.header ? this.templates.header({
  1684 + query: query,
  1685 + suggestions: suggestions,
  1686 + dataset: this.name
  1687 + }) : null;
  1688 + },
  1689 + _resetLastSuggestion: function resetLastSuggestion() {
  1690 + this.$lastSuggestion = $();
  1691 + },
  1692 + _injectQuery: function injectQuery(query, obj) {
  1693 + return _.isObject(obj) ? _.mixin({
  1694 + _query: query
  1695 + }, obj) : obj;
  1696 + },
  1697 + update: function update(query) {
  1698 + var that = this, canceled = false, syncCalled = false, rendered = 0;
  1699 + this.cancel();
  1700 + this.cancel = function cancel() {
  1701 + canceled = true;
  1702 + that.cancel = $.noop;
  1703 + that.async && that.trigger("asyncCanceled", query);
  1704 + };
  1705 + this.source(query, sync, async);
  1706 + !syncCalled && sync([]);
  1707 + function sync(suggestions) {
  1708 + if (syncCalled) {
  1709 + return;
  1710 + }
  1711 + syncCalled = true;
  1712 + suggestions = (suggestions || []).slice(0, that.limit);
  1713 + rendered = suggestions.length;
  1714 + that._overwrite(query, suggestions);
  1715 + if (rendered < that.limit && that.async) {
  1716 + that.trigger("asyncRequested", query);
  1717 + }
  1718 + }
  1719 + function async(suggestions) {
  1720 + suggestions = suggestions || [];
  1721 + if (!canceled && rendered < that.limit) {
  1722 + that.cancel = $.noop;
  1723 + rendered += suggestions.length;
  1724 + that._append(query, suggestions.slice(0, that.limit - rendered));
  1725 + that.async && that.trigger("asyncReceived", query);
  1726 + }
  1727 + }
  1728 + },
  1729 + cancel: $.noop,
  1730 + clear: function clear() {
  1731 + this._empty();
  1732 + this.cancel();
  1733 + this.trigger("cleared");
  1734 + },
  1735 + isEmpty: function isEmpty() {
  1736 + return this.$el.is(":empty");
  1737 + },
  1738 + destroy: function destroy() {
  1739 + this.$el = $("<div>");
  1740 + }
  1741 + });
  1742 + return Dataset;
  1743 + function getDisplayFn(display) {
  1744 + display = display || _.stringify;
  1745 + return _.isFunction(display) ? display : displayFn;
  1746 + function displayFn(obj) {
  1747 + return obj[display];
  1748 + }
  1749 + }
  1750 + function getTemplates(templates, displayFn) {
  1751 + return {
  1752 + notFound: templates.notFound && _.templatify(templates.notFound),
  1753 + pending: templates.pending && _.templatify(templates.pending),
  1754 + header: templates.header && _.templatify(templates.header),
  1755 + footer: templates.footer && _.templatify(templates.footer),
  1756 + suggestion: templates.suggestion || suggestionTemplate
  1757 + };
  1758 + function suggestionTemplate(context) {
  1759 + return $("<div>").text(displayFn(context));
  1760 + }
  1761 + }
  1762 + function isValidName(str) {
  1763 + return /^[_a-zA-Z0-9-]+$/.test(str);
  1764 + }
  1765 + }();
  1766 + var Menu = function() {
  1767 + "use strict";
  1768 + function Menu(o, www) {
  1769 + var that = this;
  1770 + o = o || {};
  1771 + if (!o.node) {
  1772 + $.error("node is required");
  1773 + }
  1774 + www.mixin(this);
  1775 + this.$node = $(o.node);
  1776 + this.query = null;
  1777 + this.datasets = _.map(o.datasets, initializeDataset);
  1778 + function initializeDataset(oDataset) {
  1779 + var node = that.$node.find(oDataset.node).first();
  1780 + oDataset.node = node.length ? node : $("<div>").appendTo(that.$node);
  1781 + return new Dataset(oDataset, www);
  1782 + }
  1783 + }
  1784 + _.mixin(Menu.prototype, EventEmitter, {
  1785 + _onSelectableClick: function onSelectableClick($e) {
  1786 + this.trigger("selectableClicked", $($e.currentTarget));
  1787 + },
  1788 + _onRendered: function onRendered(type, dataset, suggestions, async) {
  1789 + this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
  1790 + this.trigger("datasetRendered", dataset, suggestions, async);
  1791 + },
  1792 + _onCleared: function onCleared() {
  1793 + this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
  1794 + this.trigger("datasetCleared");
  1795 + },
  1796 + _propagate: function propagate() {
  1797 + this.trigger.apply(this, arguments);
  1798 + },
  1799 + _allDatasetsEmpty: function allDatasetsEmpty() {
  1800 + return _.every(this.datasets, isDatasetEmpty);
  1801 + function isDatasetEmpty(dataset) {
  1802 + return dataset.isEmpty();
  1803 + }
  1804 + },
  1805 + _getSelectables: function getSelectables() {
  1806 + return this.$node.find(this.selectors.selectable);
  1807 + },
  1808 + _removeCursor: function _removeCursor() {
  1809 + var $selectable = this.getActiveSelectable();
  1810 + $selectable && $selectable.removeClass(this.classes.cursor);
  1811 + },
  1812 + _ensureVisible: function ensureVisible($el) {
  1813 + var elTop, elBottom, nodeScrollTop, nodeHeight;
  1814 + elTop = $el.position().top;
  1815 + elBottom = elTop + $el.outerHeight(true);
  1816 + nodeScrollTop = this.$node.scrollTop();
  1817 + nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10);
  1818 + if (elTop < 0) {
  1819 + this.$node.scrollTop(nodeScrollTop + elTop);
  1820 + } else if (nodeHeight < elBottom) {
  1821 + this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
  1822 + }
  1823 + },
  1824 + bind: function() {
  1825 + var that = this, onSelectableClick;
  1826 + onSelectableClick = _.bind(this._onSelectableClick, this);
  1827 + this.$node.on("click.tt", this.selectors.selectable, onSelectableClick);
  1828 + _.each(this.datasets, function(dataset) {
  1829 + dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that);
  1830 + });
  1831 + return this;
  1832 + },
  1833 + isOpen: function isOpen() {
  1834 + return this.$node.hasClass(this.classes.open);
  1835 + },
  1836 + open: function open() {
  1837 + this.$node.addClass(this.classes.open);
  1838 + },
  1839 + close: function close() {
  1840 + this.$node.removeClass(this.classes.open);
  1841 + this._removeCursor();
  1842 + },
  1843 + setLanguageDirection: function setLanguageDirection(dir) {
  1844 + this.$node.attr("dir", dir);
  1845 + },
  1846 + selectableRelativeToCursor: function selectableRelativeToCursor(delta) {
  1847 + var $selectables, $oldCursor, oldIndex, newIndex;
  1848 + $oldCursor = this.getActiveSelectable();
  1849 + $selectables = this._getSelectables();
  1850 + oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1;
  1851 + newIndex = oldIndex + delta;
  1852 + newIndex = (newIndex + 1) % ($selectables.length + 1) - 1;
  1853 + newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex;
  1854 + return newIndex === -1 ? null : $selectables.eq(newIndex);
  1855 + },
  1856 + setCursor: function setCursor($selectable) {
  1857 + this._removeCursor();
  1858 + if ($selectable = $selectable && $selectable.first()) {
  1859 + $selectable.addClass(this.classes.cursor);
  1860 + this._ensureVisible($selectable);
  1861 + }
  1862 + },
  1863 + getSelectableData: function getSelectableData($el) {
  1864 + return $el && $el.length ? Dataset.extractData($el) : null;
  1865 + },
  1866 + getActiveSelectable: function getActiveSelectable() {
  1867 + var $selectable = this._getSelectables().filter(this.selectors.cursor).first();
  1868 + return $selectable.length ? $selectable : null;
  1869 + },
  1870 + getTopSelectable: function getTopSelectable() {
  1871 + var $selectable = this._getSelectables().first();
  1872 + return $selectable.length ? $selectable : null;
  1873 + },
  1874 + update: function update(query) {
  1875 + var isValidUpdate = query !== this.query;
  1876 + if (isValidUpdate) {
  1877 + this.query = query;
  1878 + _.each(this.datasets, updateDataset);
  1879 + }
  1880 + return isValidUpdate;
  1881 + function updateDataset(dataset) {
  1882 + dataset.update(query);
  1883 + }
  1884 + },
  1885 + empty: function empty() {
  1886 + _.each(this.datasets, clearDataset);
  1887 + this.query = null;
  1888 + this.$node.addClass(this.classes.empty);
  1889 + function clearDataset(dataset) {
  1890 + dataset.clear();
  1891 + }
  1892 + },
  1893 + destroy: function destroy() {
  1894 + this.$node.off(".tt");
  1895 + this.$node = $("<div>");
  1896 + _.each(this.datasets, destroyDataset);
  1897 + function destroyDataset(dataset) {
  1898 + dataset.destroy();
  1899 + }
  1900 + }
  1901 + });
  1902 + return Menu;
  1903 + }();
  1904 + var DefaultMenu = function() {
  1905 + "use strict";
  1906 + var s = Menu.prototype;
  1907 + function DefaultMenu() {
  1908 + Menu.apply(this, [].slice.call(arguments, 0));
  1909 + }
  1910 + _.mixin(DefaultMenu.prototype, Menu.prototype, {
  1911 + open: function open() {
  1912 + !this._allDatasetsEmpty() && this._show();
  1913 + return s.open.apply(this, [].slice.call(arguments, 0));
  1914 + },
  1915 + close: function close() {
  1916 + this._hide();
  1917 + return s.close.apply(this, [].slice.call(arguments, 0));
  1918 + },
  1919 + _onRendered: function onRendered() {
  1920 + if (this._allDatasetsEmpty()) {
  1921 + this._hide();
  1922 + } else {
  1923 + this.isOpen() && this._show();
  1924 + }
  1925 + return s._onRendered.apply(this, [].slice.call(arguments, 0));
  1926 + },
  1927 + _onCleared: function onCleared() {
  1928 + if (this._allDatasetsEmpty()) {
  1929 + this._hide();
  1930 + } else {
  1931 + this.isOpen() && this._show();
  1932 + }
  1933 + return s._onCleared.apply(this, [].slice.call(arguments, 0));
  1934 + },
  1935 + setLanguageDirection: function setLanguageDirection(dir) {
  1936 + this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl);
  1937 + return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0));
  1938 + },
  1939 + _hide: function hide() {
  1940 + this.$node.hide();
  1941 + },
  1942 + _show: function show() {
  1943 + this.$node.css("display", "block");
  1944 + }
  1945 + });
  1946 + return DefaultMenu;
  1947 + }();
  1948 + var Typeahead = function() {
  1949 + "use strict";
  1950 + function Typeahead(o, www) {
  1951 + var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged;
  1952 + o = o || {};
  1953 + if (!o.input) {
  1954 + $.error("missing input");
  1955 + }
  1956 + if (!o.menu) {
  1957 + $.error("missing menu");
  1958 + }
  1959 + if (!o.eventBus) {
  1960 + $.error("missing event bus");
  1961 + }
  1962 + www.mixin(this);
  1963 + this.eventBus = o.eventBus;
  1964 + this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
  1965 + this.input = o.input;
  1966 + this.menu = o.menu;
  1967 + this.enabled = true;
  1968 + this.active = false;
  1969 + this.input.hasFocus() && this.activate();
  1970 + this.dir = this.input.getLangDir();
  1971 + this._hacks();
  1972 + this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this);
  1973 + onFocused = c(this, "activate", "open", "_onFocused");
  1974 + onBlurred = c(this, "deactivate", "_onBlurred");
  1975 + onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed");
  1976 + onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed");
  1977 + onEscKeyed = c(this, "isActive", "_onEscKeyed");
  1978 + onUpKeyed = c(this, "isActive", "open", "_onUpKeyed");
  1979 + onDownKeyed = c(this, "isActive", "open", "_onDownKeyed");
  1980 + onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed");
  1981 + onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed");
  1982 + onQueryChanged = c(this, "_openIfActive", "_onQueryChanged");
  1983 + onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged");
  1984 + this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this);
  1985 + }
  1986 + _.mixin(Typeahead.prototype, {
  1987 + _hacks: function hacks() {
  1988 + var $input, $menu;
  1989 + $input = this.input.$input || $("<div>");
  1990 + $menu = this.menu.$node || $("<div>");
  1991 + $input.on("blur.tt", function($e) {
  1992 + var active, isActive, hasActive;
  1993 + active = document.activeElement;
  1994 + isActive = $menu.is(active);
  1995 + hasActive = $menu.has(active).length > 0;
  1996 + if (_.isMsie() && (isActive || hasActive)) {
  1997 + $e.preventDefault();
  1998 + $e.stopImmediatePropagation();
  1999 + _.defer(function() {
  2000 + $input.focus();
  2001 + });
  2002 + }
  2003 + });
  2004 + $menu.on("mousedown.tt", function($e) {
  2005 + $e.preventDefault();
  2006 + });
  2007 + },
  2008 + _onSelectableClicked: function onSelectableClicked(type, $el) {
  2009 + this.select($el);
  2010 + },
  2011 + _onDatasetCleared: function onDatasetCleared() {
  2012 + this._updateHint();
  2013 + },
  2014 + _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) {
  2015 + this._updateHint();
  2016 + this.eventBus.trigger("render", suggestions, async, dataset);
  2017 + },
  2018 + _onAsyncRequested: function onAsyncRequested(type, dataset, query) {
  2019 + this.eventBus.trigger("asyncrequest", query, dataset);
  2020 + },
  2021 + _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
  2022 + this.eventBus.trigger("asynccancel", query, dataset);
  2023 + },
  2024 + _onAsyncReceived: function onAsyncReceived(type, dataset, query) {
  2025 + this.eventBus.trigger("asyncreceive", query, dataset);
  2026 + },
  2027 + _onFocused: function onFocused() {
  2028 + this._minLengthMet() && this.menu.update(this.input.getQuery());
  2029 + },
  2030 + _onBlurred: function onBlurred() {
  2031 + if (this.input.hasQueryChangedSinceLastFocus()) {
  2032 + this.eventBus.trigger("change", this.input.getQuery());
  2033 + }
  2034 + },
  2035 + _onEnterKeyed: function onEnterKeyed(type, $e) {
  2036 + var $selectable;
  2037 + if ($selectable = this.menu.getActiveSelectable()) {
  2038 + this.select($selectable) && $e.preventDefault();
  2039 + }
  2040 + },
  2041 + _onTabKeyed: function onTabKeyed(type, $e) {
  2042 + var $selectable;
  2043 + if ($selectable = this.menu.getActiveSelectable()) {
  2044 + this.select($selectable) && $e.preventDefault();
  2045 + } else if ($selectable = this.menu.getTopSelectable()) {
  2046 + this.autocomplete($selectable) && $e.preventDefault();
  2047 + }
  2048 + },
  2049 + _onEscKeyed: function onEscKeyed() {
  2050 + this.close();
  2051 + },
  2052 + _onUpKeyed: function onUpKeyed() {
  2053 + this.moveCursor(-1);
  2054 + },
  2055 + _onDownKeyed: function onDownKeyed() {
  2056 + this.moveCursor(+1);
  2057 + },
  2058 + _onLeftKeyed: function onLeftKeyed() {
  2059 + if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
  2060 + this.autocomplete(this.menu.getTopSelectable());
  2061 + }
  2062 + },
  2063 + _onRightKeyed: function onRightKeyed() {
  2064 + if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
  2065 + this.autocomplete(this.menu.getTopSelectable());
  2066 + }
  2067 + },
  2068 + _onQueryChanged: function onQueryChanged(e, query) {
  2069 + this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
  2070 + },
  2071 + _onWhitespaceChanged: function onWhitespaceChanged() {
  2072 + this._updateHint();
  2073 + },
  2074 + _onLangDirChanged: function onLangDirChanged(e, dir) {
  2075 + if (this.dir !== dir) {
  2076 + this.dir = dir;
  2077 + this.menu.setLanguageDirection(dir);
  2078 + }
  2079 + },
  2080 + _openIfActive: function openIfActive() {
  2081 + this.isActive() && this.open();
  2082 + },
  2083 + _minLengthMet: function minLengthMet(query) {
  2084 + query = _.isString(query) ? query : this.input.getQuery() || "";
  2085 + return query.length >= this.minLength;
  2086 + },
  2087 + _updateHint: function updateHint() {
  2088 + var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
  2089 + $selectable = this.menu.getTopSelectable();
  2090 + data = this.menu.getSelectableData($selectable);
  2091 + val = this.input.getInputValue();
  2092 + if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
  2093 + query = Input.normalizeQuery(val);
  2094 + escapedQuery = _.escapeRegExChars(query);
  2095 + frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
  2096 + match = frontMatchRegEx.exec(data.val);
  2097 + match && this.input.setHint(val + match[1]);
  2098 + } else {
  2099 + this.input.clearHint();
  2100 + }
  2101 + },
  2102 + isEnabled: function isEnabled() {
  2103 + return this.enabled;
  2104 + },
  2105 + enable: function enable() {
  2106 + this.enabled = true;
  2107 + },
  2108 + disable: function disable() {
  2109 + this.enabled = false;
  2110 + },
  2111 + isActive: function isActive() {
  2112 + return this.active;
  2113 + },
  2114 + activate: function activate() {
  2115 + if (this.isActive()) {
  2116 + return true;
  2117 + } else if (!this.isEnabled() || this.eventBus.before("active")) {
  2118 + return false;
  2119 + } else {
  2120 + this.active = true;
  2121 + this.eventBus.trigger("active");
  2122 + return true;
  2123 + }
  2124 + },
  2125 + deactivate: function deactivate() {
  2126 + if (!this.isActive()) {
  2127 + return true;
  2128 + } else if (this.eventBus.before("idle")) {
  2129 + return false;
  2130 + } else {
  2131 + this.active = false;
  2132 + this.close();
  2133 + this.eventBus.trigger("idle");
  2134 + return true;
  2135 + }
  2136 + },
  2137 + isOpen: function isOpen() {
  2138 + return this.menu.isOpen();
  2139 + },
  2140 + open: function open() {
  2141 + if (!this.isOpen() && !this.eventBus.before("open")) {
  2142 + this.menu.open();
  2143 + this._updateHint();
  2144 + this.eventBus.trigger("open");
  2145 + }
  2146 + return this.isOpen();
  2147 + },
  2148 + close: function close() {
  2149 + if (this.isOpen() && !this.eventBus.before("close")) {
  2150 + this.menu.close();
  2151 + this.input.clearHint();
  2152 + this.input.resetInputValue();
  2153 + this.eventBus.trigger("close");
  2154 + }
  2155 + return !this.isOpen();
  2156 + },
  2157 + setVal: function setVal(val) {
  2158 + this.input.setQuery(_.toStr(val));
  2159 + },
  2160 + getVal: function getVal() {
  2161 + return this.input.getQuery();
  2162 + },
  2163 + select: function select($selectable) {
  2164 + var data = this.menu.getSelectableData($selectable);
  2165 + if (data && !this.eventBus.before("select", data.obj)) {
  2166 + this.input.setQuery(data.val, true);
  2167 + this.eventBus.trigger("select", data.obj);
  2168 + this.close();
  2169 + return true;
  2170 + }
  2171 + return false;
  2172 + },
  2173 + autocomplete: function autocomplete($selectable) {
  2174 + var query, data, isValid;
  2175 + query = this.input.getQuery();
  2176 + data = this.menu.getSelectableData($selectable);
  2177 + isValid = data && query !== data.val;
  2178 + if (isValid && !this.eventBus.before("autocomplete", data.obj)) {
  2179 + this.input.setQuery(data.val);
  2180 + this.eventBus.trigger("autocomplete", data.obj);
  2181 + return true;
  2182 + }
  2183 + return false;
  2184 + },
  2185 + moveCursor: function moveCursor(delta) {
  2186 + var query, $candidate, data, payload, cancelMove;
  2187 + query = this.input.getQuery();
  2188 + $candidate = this.menu.selectableRelativeToCursor(delta);
  2189 + data = this.menu.getSelectableData($candidate);
  2190 + payload = data ? data.obj : null;
  2191 + cancelMove = this._minLengthMet() && this.menu.update(query);
  2192 + if (!cancelMove && !this.eventBus.before("cursorchange", payload)) {
  2193 + this.menu.setCursor($candidate);
  2194 + if (data) {
  2195 + this.input.setInputValue(data.val);
  2196 + } else {
  2197 + this.input.resetInputValue();
  2198 + this._updateHint();
  2199 + }
  2200 + this.eventBus.trigger("cursorchange", payload);
  2201 + return true;
  2202 + }
  2203 + return false;
  2204 + },
  2205 + destroy: function destroy() {
  2206 + this.input.destroy();
  2207 + this.menu.destroy();
  2208 + }
  2209 + });
  2210 + return Typeahead;
  2211 + function c(ctx) {
  2212 + var methods = [].slice.call(arguments, 1);
  2213 + return function() {
  2214 + var args = [].slice.call(arguments);
  2215 + _.each(methods, function(method) {
  2216 + return ctx[method].apply(ctx, args);
  2217 + });
  2218 + };
  2219 + }
  2220 + }();
  2221 + (function() {
  2222 + "use strict";
  2223 + var old, keys, methods;
  2224 + old = $.fn.typeahead;
  2225 + keys = {
  2226 + www: "tt-www",
  2227 + attrs: "tt-attrs",
  2228 + typeahead: "tt-typeahead"
  2229 + };
  2230 + methods = {
  2231 + initialize: function initialize(o, datasets) {
  2232 + var www;
  2233 + datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
  2234 + o = o || {};
  2235 + www = WWW(o.classNames);
  2236 + return this.each(attach);
  2237 + function attach() {
  2238 + var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor;
  2239 + _.each(datasets, function(d) {
  2240 + d.highlight = !!o.highlight;
  2241 + });
  2242 + $input = $(this);
  2243 + $wrapper = $(www.html.wrapper);
  2244 + $hint = $elOrNull(o.hint);
  2245 + $menu = $elOrNull(o.menu);
  2246 + defaultHint = o.hint !== false && !$hint;
  2247 + defaultMenu = o.menu !== false && !$menu;
  2248 + defaultHint && ($hint = buildHintFromInput($input, www));
  2249 + defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
  2250 + $hint && $hint.val("");
  2251 + $input = prepInput($input, www);
  2252 + if (defaultHint || defaultMenu) {
  2253 + $wrapper.css(www.css.wrapper);
  2254 + $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
  2255 + $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
  2256 + }
  2257 + MenuConstructor = defaultMenu ? DefaultMenu : Menu;
  2258 + eventBus = new EventBus({
  2259 + el: $input
  2260 + });
  2261 + input = new Input({
  2262 + hint: $hint,
  2263 + input: $input
  2264 + }, www);
  2265 + menu = new MenuConstructor({
  2266 + node: $menu,
  2267 + datasets: datasets
  2268 + }, www);
  2269 + typeahead = new Typeahead({
  2270 + input: input,
  2271 + menu: menu,
  2272 + eventBus: eventBus,
  2273 + minLength: o.minLength
  2274 + }, www);
  2275 + $input.data(keys.www, www);
  2276 + $input.data(keys.typeahead, typeahead);
  2277 + }
  2278 + },
  2279 + isEnabled: function isEnabled() {
  2280 + var enabled;
  2281 + ttEach(this.first(), function(t) {
  2282 + enabled = t.isEnabled();
  2283 + });
  2284 + return enabled;
  2285 + },
  2286 + enable: function enable() {
  2287 + ttEach(this, function(t) {
  2288 + t.enable();
  2289 + });
  2290 + return this;
  2291 + },
  2292 + disable: function disable() {
  2293 + ttEach(this, function(t) {
  2294 + t.disable();
  2295 + });
  2296 + return this;
  2297 + },
  2298 + isActive: function isActive() {
  2299 + var active;
  2300 + ttEach(this.first(), function(t) {
  2301 + active = t.isActive();
  2302 + });
  2303 + return active;
  2304 + },
  2305 + activate: function activate() {
  2306 + ttEach(this, function(t) {
  2307 + t.activate();
  2308 + });
  2309 + return this;
  2310 + },
  2311 + deactivate: function deactivate() {
  2312 + ttEach(this, function(t) {
  2313 + t.deactivate();
  2314 + });
  2315 + return this;
  2316 + },
  2317 + isOpen: function isOpen() {
  2318 + var open;
  2319 + ttEach(this.first(), function(t) {
  2320 + open = t.isOpen();
  2321 + });
  2322 + return open;
  2323 + },
  2324 + open: function open() {
  2325 + ttEach(this, function(t) {
  2326 + t.open();
  2327 + });
  2328 + return this;
  2329 + },
  2330 + close: function close() {
  2331 + ttEach(this, function(t) {
  2332 + t.close();
  2333 + });
  2334 + return this;
  2335 + },
  2336 + select: function select(el) {
  2337 + var success = false, $el = $(el);
  2338 + ttEach(this.first(), function(t) {
  2339 + success = t.select($el);
  2340 + });
  2341 + return success;
  2342 + },
  2343 + autocomplete: function autocomplete(el) {
  2344 + var success = false, $el = $(el);
  2345 + ttEach(this.first(), function(t) {
  2346 + success = t.autocomplete($el);
  2347 + });
  2348 + return success;
  2349 + },
  2350 + moveCursor: function moveCursoe(delta) {
  2351 + var success = false;
  2352 + ttEach(this.first(), function(t) {
  2353 + success = t.moveCursor(delta);
  2354 + });
  2355 + return success;
  2356 + },
  2357 + val: function val(newVal) {
  2358 + var query;
  2359 + if (!arguments.length) {
  2360 + ttEach(this.first(), function(t) {
  2361 + query = t.getVal();
  2362 + });
  2363 + return query;
  2364 + } else {
  2365 + ttEach(this, function(t) {
  2366 + t.setVal(newVal);
  2367 + });
  2368 + return this;
  2369 + }
  2370 + },
  2371 + destroy: function destroy() {
  2372 + ttEach(this, function(typeahead, $input) {
  2373 + revert($input);
  2374 + typeahead.destroy();
  2375 + });
  2376 + return this;
  2377 + }
  2378 + };
  2379 + $.fn.typeahead = function(method) {
  2380 + if (methods[method]) {
  2381 + return methods[method].apply(this, [].slice.call(arguments, 1));
  2382 + } else {
  2383 + return methods.initialize.apply(this, arguments);
  2384 + }
  2385 + };
  2386 + $.fn.typeahead.noConflict = function noConflict() {
  2387 + $.fn.typeahead = old;
  2388 + return this;
  2389 + };
  2390 + function ttEach($els, fn) {
  2391 + $els.each(function() {
  2392 + var $input = $(this), typeahead;
  2393 + (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
  2394 + });
  2395 + }
  2396 + function buildHintFromInput($input, www) {
  2397 + return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({
  2398 + autocomplete: "off",
  2399 + spellcheck: "false",
  2400 + tabindex: -1
  2401 + });
  2402 + }
  2403 + function prepInput($input, www) {
  2404 + $input.data(keys.attrs, {
  2405 + dir: $input.attr("dir"),
  2406 + autocomplete: $input.attr("autocomplete"),
  2407 + spellcheck: $input.attr("spellcheck"),
  2408 + style: $input.attr("style")
  2409 + });
  2410 + $input.addClass(www.classes.input).attr({
  2411 + autocomplete: "off",
  2412 + spellcheck: false
  2413 + });
  2414 + try {
  2415 + !$input.attr("dir") && $input.attr("dir", "auto");
  2416 + } catch (e) {}
  2417 + return $input;
  2418 + }
  2419 + function getBackgroundStyles($el) {
  2420 + return {
  2421 + backgroundAttachment: $el.css("background-attachment"),
  2422 + backgroundClip: $el.css("background-clip"),
  2423 + backgroundColor: $el.css("background-color"),
  2424 + backgroundImage: $el.css("background-image"),
  2425 + backgroundOrigin: $el.css("background-origin"),
  2426 + backgroundPosition: $el.css("background-position"),
  2427 + backgroundRepeat: $el.css("background-repeat"),
  2428 + backgroundSize: $el.css("background-size")
  2429 + };
  2430 + }
  2431 + function revert($input) {
  2432 + var www, $wrapper;
  2433 + www = $input.data(keys.www);
  2434 + $wrapper = $input.parent().filter(www.selectors.wrapper);
  2435 + _.each($input.data(keys.attrs), function(val, key) {
  2436 + _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
  2437 + });
  2438 + $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
  2439 + if ($wrapper.length) {
  2440 + $input.detach().insertAfter($wrapper);
  2441 + $wrapper.remove();
  2442 + }
  2443 + }
  2444 + function $elOrNull(obj) {
  2445 + var isValid, $el;
  2446 + isValid = _.isJQuery(obj) || _.isElement(obj);
  2447 + $el = isValid ? $(obj).first() : [];
  2448 + return $el.length ? $el : null;
  2449 + }
  2450 + })();
  2451 +});
\ No newline at end of file
... ...
... ... @@ -2,6 +2,7 @@
2 2 //= require kanjai/jquery-ui
3 3 //= require kanjai/admin/popper.js/popper.js
4 4 //= require kanjai/admin/bootstrap/bootstrap
  5 +//= require kanjai/admin/tagsinput/typeahead
5 6 //= require kanjai/rails
6 7
7 8
... ... @@ -12,6 +13,8 @@
12 13 //= require kanjai/lib/epiceditor
13 14 //= require kanjai/lib/fileinput
14 15
  16 +//= require kanjai/admin/jquery.fileupload
  17 +
15 18 //= require kanjai/froala_editor/froala_editor.min
16 19 //= require kanjai/froala_editor/plugins/align.min
17 20 //= require kanjai/froala_editor/plugins/char_counter.min
... ... @@ -37,4 +40,6 @@
37 40 //= require kanjai/froala_editor/plugins/url.min
38 41 //= require kanjai/froala_editor/plugins/video.min
39 42
  43 +
  44 +
40 45 //= require_tree ./admin/.
... ...