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  
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>  
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>  
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>  
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>  
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>  
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>  
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>  
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>  
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>  
1 -<component name="DependencyValidationManager">  
2 - <state>  
3 - <option name="SKIP_IMPORT_STATEMENTS" value="false" />  
4 - </state>  
5 -</component>  
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>  
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>  
@@ -2,6 +2,7 @@ PATH @@ -2,6 +2,7 @@ PATH
2 remote: . 2 remote: .
3 specs: 3 specs:
4 kanjai (0.0.140) 4 kanjai (0.0.140)
  5 + acts-as-taggable-on (~> 6.5)
5 acts_as_list 6 acts_as_list
6 acts_as_tree 7 acts_as_tree
7 aws-sdk 8 aws-sdk
@@ -55,8 +56,10 @@ GEM @@ -55,8 +56,10 @@ GEM
55 i18n (>= 0.7, < 2) 56 i18n (>= 0.7, < 2)
56 minitest (~> 5.1) 57 minitest (~> 5.1)
57 tzinfo (~> 1.1) 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 acts_as_tree (2.9.1) 63 acts_as_tree (2.9.1)
61 activerecord (>= 3.0.0) 64 activerecord (>= 3.0.0)
62 arel (9.0.0) 65 arel (9.0.0)
@@ -1019,16 +1022,16 @@ GEM @@ -1019,16 +1022,16 @@ GEM
1019 rb-fsevent (0.10.3) 1022 rb-fsevent (0.10.3)
1020 rb-inotify (0.10.1) 1023 rb-inotify (0.10.1)
1021 ffi (~> 1.0) 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 sass (3.7.4) 1028 sass (3.7.4)
1026 sass-listen (~> 4.0.0) 1029 sass-listen (~> 4.0.0)
1027 sass-listen (4.0.0) 1030 sass-listen (4.0.0)
1028 rb-fsevent (~> 0.9, >= 0.9.4) 1031 rb-fsevent (~> 0.9, >= 0.9.4)
1029 rb-inotify (~> 0.9, >= 0.9.7) 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 sass (~> 3.1) 1035 sass (~> 3.1)
1033 sprockets (>= 2.8, < 4.0) 1036 sprockets (>= 2.8, < 4.0)
1034 sprockets-rails (>= 2.0, < 4.0) 1037 sprockets-rails (>= 2.0, < 4.0)
@@ -1060,4 +1063,4 @@ DEPENDENCIES @@ -1060,4 +1063,4 @@ DEPENDENCIES
1060 kanjai! 1063 kanjai!
1061 1064
1062 BUNDLED WITH 1065 BUNDLED WITH
1063 - 2.0.1 1066 + 2.1.4
@@ -14,8 +14,8 @@ RDoc::Task.new(:rdoc) do |rdoc| @@ -14,8 +14,8 @@ RDoc::Task.new(:rdoc) do |rdoc|
14 rdoc.rdoc_files.include('lib/**/*.rb') 14 rdoc.rdoc_files.include('lib/**/*.rb')
15 end 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 load 'rails/tasks/statistics.rake' 21 load 'rails/tasks/statistics.rake'
@@ -1389,40 +1389,31 @@ var add_fields = function(target, association, content){ @@ -1389,40 +1389,31 @@ var add_fields = function(target, association, content){
1389 jQuery(target).append(content.replace(regexp, new_id)); 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 $('#progress-window').modal('hide'); 1406 $('#progress-window').modal('hide');
1404 $('#progress-window').remove(); 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 count_upload = 0; 1416 count_upload = 0;
1424 - e.preventDefault();  
1425 - e.stopPropagation();  
1426 1417
1427 selector.find(".ajax-file-upload-form input:file").each(function(){ 1418 selector.find(".ajax-file-upload-form input:file").each(function(){
1428 var $this = $(this), 1419 var $this = $(this),
@@ -1454,7 +1445,7 @@ var initAjaxFileUpload = function(selector){ @@ -1454,7 +1445,7 @@ var initAjaxFileUpload = function(selector){
1454 1445
1455 1446
1456 $this.fileupload('send', {files: fileToSend}) 1447 $this.fileupload('send', {files: fileToSend})
1457 - .complete(function (result, textStatus, jqXHR) { 1448 + .done(function (result, textStatus, jqXHR) {
1458 count_upload = count_upload + 1; 1449 count_upload = count_upload + 1;
1459 if(count_upload == count_files){ 1450 if(count_upload == count_files){
1460 send_ajax_form($form); 1451 send_ajax_form($form);
@@ -1472,7 +1463,11 @@ var initAjaxFileUpload = function(selector){ @@ -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 var initFileInput = function(fileInputElem){ 1472 var initFileInput = function(fileInputElem){
1478 var form = $(fileInputElem.parents('form:first')); 1473 var form = $(fileInputElem.parents('form:first'));
@@ -1499,7 +1494,6 @@ var initAjaxFileUpload = function(selector){ @@ -1499,7 +1494,6 @@ var initAjaxFileUpload = function(selector){
1499 }, 1494 },
1500 progressall: function (e, data) { 1495 progressall: function (e, data) {
1501 var progress = parseInt(data.loaded / data.total * 100, 10); 1496 var progress = parseInt(data.loaded / data.total * 100, 10);
1502 -  
1503 $('.' + class_name).find('.progress-bar').css('width', progress + '%'); 1497 $('.' + class_name).find('.progress-bar').css('width', progress + '%');
1504 }, 1498 },
1505 start: function (e) { 1499 start: function (e) {
@@ -1513,7 +1507,6 @@ var initAjaxFileUpload = function(selector){ @@ -1513,7 +1507,6 @@ var initAjaxFileUpload = function(selector){
1513 1507
1514 $('.' + class_name).find('.progress-bar').addClass('progress-bar-success'); 1508 $('.' + class_name).find('.progress-bar').addClass('progress-bar-success');
1515 1509
1516 -  
1517 // extract key and generate URL from response 1510 // extract key and generate URL from response
1518 var key = $(data.jqXHR.responseXML).find("Key").text(); 1511 var key = $(data.jqXHR.responseXML).find("Key").text();
1519 var url = 'https://' + fileInputElem.data('host') + '/' + key; 1512 var url = 'https://' + fileInputElem.data('host') + '/' + key;
@@ -1542,7 +1535,12 @@ var initAjaxFileUpload = function(selector){ @@ -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 $(document).bind('drop dragover', function (e) { 1545 $(document).bind('drop dragover', function (e) {
1548 e.preventDefault(); 1546 e.preventDefault();
@@ -1552,10 +1550,23 @@ var initAjaxFileUpload = function(selector){ @@ -1552,10 +1550,23 @@ var initAjaxFileUpload = function(selector){
1552 }; 1550 };
1553 1551
1554 var clearAjaxFileUpload = function(selector){ 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 jQuery(document).ready(function(){ 1571 jQuery(document).ready(function(){
1561 1572
@@ -1724,46 +1735,78 @@ jQuery(document).ready(function(){ @@ -1724,46 +1735,78 @@ jQuery(document).ready(function(){
1724 }else { 1735 }else {
1725 dropZone[0].ondrop = function (e) { 1736 dropZone[0].ondrop = function (e) {
1726 e.preventDefault(); 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,6 +1880,7 @@ jQuery(document).ready(function(){
1837 }); 1880 });
1838 }); 1881 });
1839 1882
  1883 +
1840 $('.dropdown-toggle').dropdown(); 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);
@@ -455,6 +455,7 @@ @@ -455,6 +455,7 @@
455 options.headers['Content-Disposition'] = 'attachment; filename="' + 455 options.headers['Content-Disposition'] = 'attachment; filename="' +
456 encodeURI(file.name) + '"'; 456 encodeURI(file.name) + '"';
457 } 457 }
  458 +
458 if (!multipart) { 459 if (!multipart) {
459 options.contentType = file.type || 'application/octet-stream'; 460 options.contentType = file.type || 'application/octet-stream';
460 options.data = options.blob || file; 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 +});
  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 +});
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 //= require kanjai/jquery-ui 2 //= require kanjai/jquery-ui
3 //= require kanjai/admin/popper.js/popper.js 3 //= require kanjai/admin/popper.js/popper.js
4 //= require kanjai/admin/bootstrap/bootstrap 4 //= require kanjai/admin/bootstrap/bootstrap
  5 +//= require kanjai/admin/tagsinput/typeahead
5 //= require kanjai/rails 6 //= require kanjai/rails
6 7
7 8
@@ -12,6 +13,8 @@ @@ -12,6 +13,8 @@
12 //= require kanjai/lib/epiceditor 13 //= require kanjai/lib/epiceditor
13 //= require kanjai/lib/fileinput 14 //= require kanjai/lib/fileinput
14 15
  16 +//= require kanjai/admin/jquery.fileupload
  17 +
15 //= require kanjai/froala_editor/froala_editor.min 18 //= require kanjai/froala_editor/froala_editor.min
16 //= require kanjai/froala_editor/plugins/align.min 19 //= require kanjai/froala_editor/plugins/align.min
17 //= require kanjai/froala_editor/plugins/char_counter.min 20 //= require kanjai/froala_editor/plugins/char_counter.min
@@ -37,4 +40,6 @@ @@ -37,4 +40,6 @@
37 //= require kanjai/froala_editor/plugins/url.min 40 //= require kanjai/froala_editor/plugins/url.min
38 //= require kanjai/froala_editor/plugins/video.min 41 //= require kanjai/froala_editor/plugins/video.min
39 42
  43 +
  44 +
40 //= require_tree ./admin/. 45 //= require_tree ./admin/.