Merge pull request #482 from metamaps/develop
merge develop into master (version 2.8!)
3
.gitignore
vendored
|
@ -7,6 +7,7 @@
|
||||||
#assety stuff
|
#assety stuff
|
||||||
realtime/node_modules
|
realtime/node_modules
|
||||||
public/assets
|
public/assets
|
||||||
|
public/metamaps_mobile
|
||||||
vendor/
|
vendor/
|
||||||
|
|
||||||
#secrets and config
|
#secrets and config
|
||||||
|
@ -19,6 +20,8 @@ vendor/
|
||||||
log/*.log
|
log/*.log
|
||||||
tmp
|
tmp
|
||||||
|
|
||||||
|
coverage
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*/.DS_Store
|
*/.DS_Store
|
||||||
.DS_Store?
|
.DS_Store?
|
||||||
|
|
3
.simplecov
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
if ENV['COVERAGE'] == 'on'
|
||||||
|
SimpleCov.start 'rails'
|
||||||
|
end
|
9
.travis.yml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
sudo: false
|
||||||
|
language: ruby
|
||||||
|
rvm:
|
||||||
|
- 2.1.3
|
||||||
|
before_script:
|
||||||
|
- export RAILS_ENV=test
|
||||||
|
- cp .example-env .env
|
||||||
|
- bundle exec rake db:create
|
||||||
|
- bundle exec rake db:schema:load
|
11
Gemfile
|
@ -6,7 +6,9 @@ gem 'rails', '4.2.4'
|
||||||
gem 'devise'
|
gem 'devise'
|
||||||
gem 'redis'
|
gem 'redis'
|
||||||
gem 'pg'
|
gem 'pg'
|
||||||
gem 'cancancan'
|
gem 'pundit'
|
||||||
|
gem 'pundit_extra'
|
||||||
|
gem 'doorkeeper'
|
||||||
gem 'formula'
|
gem 'formula'
|
||||||
gem 'formtastic'
|
gem 'formtastic'
|
||||||
gem 'json'
|
gem 'json'
|
||||||
|
@ -15,6 +17,11 @@ gem 'best_in_place' #in-place editing
|
||||||
gem 'kaminari' # pagination
|
gem 'kaminari' # pagination
|
||||||
gem 'uservoice-ruby'
|
gem 'uservoice-ruby'
|
||||||
gem 'dotenv'
|
gem 'dotenv'
|
||||||
|
gem 'snorlax'
|
||||||
|
gem 'httparty'
|
||||||
|
gem 'active_model_serializers', '~> 0.8.1'
|
||||||
|
gem 'delayed_job', '~> 4.0.2'
|
||||||
|
gem 'delayed_job_active_record', '~> 4.0.1'
|
||||||
|
|
||||||
gem 'paperclip'
|
gem 'paperclip'
|
||||||
gem 'aws-sdk', '< 2.0'
|
gem 'aws-sdk', '< 2.0'
|
||||||
|
@ -42,6 +49,8 @@ group :test do
|
||||||
gem 'rspec-rails'
|
gem 'rspec-rails'
|
||||||
gem 'factory_girl_rails'
|
gem 'factory_girl_rails'
|
||||||
gem 'shoulda-matchers'
|
gem 'shoulda-matchers'
|
||||||
|
gem 'simplecov', require: false
|
||||||
|
gem 'json-schema'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :production do #this is used on heroku
|
group :production do #this is used on heroku
|
||||||
|
|
157
Gemfile.lock
|
@ -20,6 +20,8 @@ GEM
|
||||||
erubis (~> 2.7.0)
|
erubis (~> 2.7.0)
|
||||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||||
|
active_model_serializers (0.8.3)
|
||||||
|
activemodel (>= 3.0)
|
||||||
activejob (4.2.4)
|
activejob (4.2.4)
|
||||||
activesupport (= 4.2.4)
|
activesupport (= 4.2.4)
|
||||||
globalid (>= 0.3.0)
|
globalid (>= 0.3.0)
|
||||||
|
@ -36,14 +38,15 @@ GEM
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
thread_safe (~> 0.3, >= 0.3.4)
|
thread_safe (~> 0.3, >= 0.3.4)
|
||||||
tzinfo (~> 1.1)
|
tzinfo (~> 1.1)
|
||||||
|
addressable (2.3.8)
|
||||||
arel (6.0.3)
|
arel (6.0.3)
|
||||||
aws-sdk (1.66.0)
|
aws-sdk (1.66.0)
|
||||||
aws-sdk-v1 (= 1.66.0)
|
aws-sdk-v1 (= 1.66.0)
|
||||||
aws-sdk-v1 (1.66.0)
|
aws-sdk-v1 (1.66.0)
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
nokogiri (>= 1.4.4)
|
nokogiri (>= 1.4.4)
|
||||||
bcrypt (3.1.10)
|
bcrypt (3.1.11)
|
||||||
best_in_place (3.0.3)
|
best_in_place (3.1.0)
|
||||||
actionpack (>= 3.2)
|
actionpack (>= 3.2)
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
better_errors (2.1.1)
|
better_errors (2.1.1)
|
||||||
|
@ -53,24 +56,27 @@ GEM
|
||||||
binding_of_caller (0.7.2)
|
binding_of_caller (0.7.2)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
builder (3.2.2)
|
builder (3.2.2)
|
||||||
byebug (5.0.0)
|
byebug (8.2.2)
|
||||||
columnize (= 0.9.0)
|
|
||||||
cancancan (1.13.1)
|
|
||||||
climate_control (0.0.3)
|
climate_control (0.0.3)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
cocaine (0.5.7)
|
cocaine (0.5.8)
|
||||||
climate_control (>= 0.0.3, < 1.0)
|
climate_control (>= 0.0.3, < 1.0)
|
||||||
coderay (1.1.0)
|
coderay (1.1.1)
|
||||||
coffee-rails (4.1.0)
|
coffee-rails (4.1.1)
|
||||||
coffee-script (>= 2.2.0)
|
coffee-script (>= 2.2.0)
|
||||||
railties (>= 4.0.0, < 5.0)
|
railties (>= 4.0.0, < 5.1.x)
|
||||||
coffee-script (2.4.1)
|
coffee-script (2.4.1)
|
||||||
coffee-script-source
|
coffee-script-source
|
||||||
execjs
|
execjs
|
||||||
coffee-script-source (1.9.1.1)
|
coffee-script-source (1.10.0)
|
||||||
columnize (0.9.0)
|
concurrent-ruby (1.0.1)
|
||||||
debug_inspector (0.0.2)
|
debug_inspector (0.0.2)
|
||||||
devise (3.5.2)
|
delayed_job (4.0.6)
|
||||||
|
activesupport (>= 3.0, < 5.0)
|
||||||
|
delayed_job_active_record (4.0.3)
|
||||||
|
activerecord (>= 3.0, < 5.0)
|
||||||
|
delayed_job (>= 3.0, < 4.1)
|
||||||
|
devise (3.5.6)
|
||||||
bcrypt (~> 3.0)
|
bcrypt (~> 3.0)
|
||||||
orm_adapter (~> 0.1)
|
orm_adapter (~> 0.1)
|
||||||
railties (>= 3.2.6, < 5)
|
railties (>= 3.2.6, < 5)
|
||||||
|
@ -78,13 +84,16 @@ GEM
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
diff-lcs (1.2.5)
|
diff-lcs (1.2.5)
|
||||||
dotenv (2.0.2)
|
docile (1.1.5)
|
||||||
|
doorkeeper (3.1.0)
|
||||||
|
railties (>= 3.2)
|
||||||
|
dotenv (2.1.0)
|
||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
execjs (2.6.0)
|
execjs (2.6.0)
|
||||||
ezcrypto (0.7.2)
|
ezcrypto (0.7.2)
|
||||||
factory_girl (4.5.0)
|
factory_girl (4.5.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
factory_girl_rails (4.5.0)
|
factory_girl_rails (4.6.0)
|
||||||
factory_girl (~> 4.5.0)
|
factory_girl (~> 4.5.0)
|
||||||
railties (>= 3.0.0)
|
railties (>= 3.0.0)
|
||||||
formtastic (3.1.3)
|
formtastic (3.1.3)
|
||||||
|
@ -93,50 +102,61 @@ GEM
|
||||||
rails (> 3.0.0)
|
rails (> 3.0.0)
|
||||||
globalid (0.3.6)
|
globalid (0.3.6)
|
||||||
activesupport (>= 4.1.0)
|
activesupport (>= 4.1.0)
|
||||||
|
httparty (0.13.7)
|
||||||
|
json (~> 1.8)
|
||||||
|
multi_xml (>= 0.5.2)
|
||||||
i18n (0.7.0)
|
i18n (0.7.0)
|
||||||
jbuilder (2.3.2)
|
jbuilder (2.4.1)
|
||||||
activesupport (>= 3.0.0, < 5)
|
activesupport (>= 3.0.0, < 5.1)
|
||||||
multi_json (~> 1.2)
|
multi_json (~> 1.2)
|
||||||
jquery-rails (4.0.5)
|
jquery-rails (4.1.1)
|
||||||
rails-dom-testing (~> 1.0)
|
rails-dom-testing (>= 1, < 3)
|
||||||
railties (>= 4.2.0)
|
railties (>= 4.2.0)
|
||||||
thor (>= 0.14, < 2.0)
|
thor (>= 0.14, < 2.0)
|
||||||
jquery-ui-rails (5.0.5)
|
jquery-ui-rails (5.0.5)
|
||||||
railties (>= 3.2.16)
|
railties (>= 3.2.16)
|
||||||
json (1.8.3)
|
json (1.8.3)
|
||||||
|
json-schema (2.6.1)
|
||||||
|
addressable (~> 2.3.8)
|
||||||
kaminari (0.16.3)
|
kaminari (0.16.3)
|
||||||
actionpack (>= 3.0.0)
|
actionpack (>= 3.0.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
loofah (2.0.3)
|
loofah (2.0.3)
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.5.9)
|
||||||
mail (2.6.3)
|
mail (2.6.4)
|
||||||
mime-types (>= 1.16, < 3)
|
mime-types (>= 1.16, < 4)
|
||||||
method_source (0.8.2)
|
method_source (0.8.2)
|
||||||
mime-types (2.6.2)
|
mime-types (3.0)
|
||||||
|
mime-types-data (~> 3.2015)
|
||||||
|
mime-types-data (3.2016.0221)
|
||||||
mimemagic (0.3.0)
|
mimemagic (0.3.0)
|
||||||
mini_portile (0.6.2)
|
mini_portile2 (2.0.0)
|
||||||
minitest (5.8.2)
|
minitest (5.8.4)
|
||||||
multi_json (1.11.2)
|
multi_json (1.11.2)
|
||||||
nokogiri (1.6.6.2)
|
multi_xml (0.5.5)
|
||||||
mini_portile (~> 0.6.0)
|
nokogiri (1.6.7.2)
|
||||||
oauth (0.4.7)
|
mini_portile2 (~> 2.0.0.rc2)
|
||||||
|
oauth (0.5.1)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
paperclip (4.3.1)
|
paperclip (4.3.5)
|
||||||
activemodel (>= 3.2.0)
|
activemodel (>= 3.2.0)
|
||||||
activesupport (>= 3.2.0)
|
activesupport (>= 3.2.0)
|
||||||
cocaine (~> 0.5.5)
|
cocaine (~> 0.5.5)
|
||||||
mime-types
|
mime-types
|
||||||
mimemagic (= 0.3.0)
|
mimemagic (= 0.3.0)
|
||||||
pg (0.18.3)
|
pg (0.18.4)
|
||||||
pry (0.10.3)
|
pry (0.10.3)
|
||||||
coderay (~> 1.1.0)
|
coderay (~> 1.1.0)
|
||||||
method_source (~> 0.8.1)
|
method_source (~> 0.8.1)
|
||||||
slop (~> 3.4)
|
slop (~> 3.4)
|
||||||
pry-byebug (3.2.0)
|
pry-byebug (3.3.0)
|
||||||
byebug (~> 5.0)
|
byebug (~> 8.0)
|
||||||
pry (~> 0.10)
|
pry (~> 0.10)
|
||||||
pry-rails (0.3.4)
|
pry-rails (0.3.4)
|
||||||
pry (>= 0.9.10)
|
pry (>= 0.9.10)
|
||||||
|
pundit (1.1.0)
|
||||||
|
activesupport (>= 3.0.0)
|
||||||
|
pundit_extra (0.1.1)
|
||||||
quiet_assets (1.1.0)
|
quiet_assets (1.1.0)
|
||||||
railties (>= 3.1, < 5.0)
|
railties (>= 3.1, < 5.0)
|
||||||
rack (1.6.4)
|
rack (1.6.4)
|
||||||
|
@ -159,61 +179,69 @@ GEM
|
||||||
activesupport (>= 4.2.0.beta, < 5.0)
|
activesupport (>= 4.2.0.beta, < 5.0)
|
||||||
nokogiri (~> 1.6.0)
|
nokogiri (~> 1.6.0)
|
||||||
rails-deprecated_sanitizer (>= 1.0.1)
|
rails-deprecated_sanitizer (>= 1.0.1)
|
||||||
rails-html-sanitizer (1.0.2)
|
rails-html-sanitizer (1.0.3)
|
||||||
loofah (~> 2.0)
|
loofah (~> 2.0)
|
||||||
rails3-jquery-autocomplete (1.0.15)
|
rails3-jquery-autocomplete (1.0.15)
|
||||||
rails (>= 3.2)
|
rails (>= 3.2)
|
||||||
rails_12factor (0.0.3)
|
rails_12factor (0.0.3)
|
||||||
rails_serve_static_assets
|
rails_serve_static_assets
|
||||||
rails_stdout_logging
|
rails_stdout_logging
|
||||||
rails_serve_static_assets (0.0.4)
|
rails_serve_static_assets (0.0.5)
|
||||||
rails_stdout_logging (0.0.4)
|
rails_stdout_logging (0.0.4)
|
||||||
railties (4.2.4)
|
railties (4.2.4)
|
||||||
actionpack (= 4.2.4)
|
actionpack (= 4.2.4)
|
||||||
activesupport (= 4.2.4)
|
activesupport (= 4.2.4)
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (>= 0.18.1, < 2.0)
|
thor (>= 0.18.1, < 2.0)
|
||||||
rake (10.4.2)
|
rake (11.1.1)
|
||||||
redis (3.2.1)
|
redis (3.2.2)
|
||||||
responders (2.1.0)
|
responders (2.1.1)
|
||||||
railties (>= 4.2.0, < 5)
|
railties (>= 4.2.0, < 5.1)
|
||||||
rspec-core (3.3.2)
|
rspec-core (3.4.4)
|
||||||
rspec-support (~> 3.3.0)
|
rspec-support (~> 3.4.0)
|
||||||
rspec-expectations (3.3.1)
|
rspec-expectations (3.4.0)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.3.0)
|
rspec-support (~> 3.4.0)
|
||||||
rspec-mocks (3.3.2)
|
rspec-mocks (3.4.1)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.3.0)
|
rspec-support (~> 3.4.0)
|
||||||
rspec-rails (3.3.3)
|
rspec-rails (3.4.2)
|
||||||
actionpack (>= 3.0, < 4.3)
|
actionpack (>= 3.0, < 4.3)
|
||||||
activesupport (>= 3.0, < 4.3)
|
activesupport (>= 3.0, < 4.3)
|
||||||
railties (>= 3.0, < 4.3)
|
railties (>= 3.0, < 4.3)
|
||||||
rspec-core (~> 3.3.0)
|
rspec-core (~> 3.4.0)
|
||||||
rspec-expectations (~> 3.3.0)
|
rspec-expectations (~> 3.4.0)
|
||||||
rspec-mocks (~> 3.3.0)
|
rspec-mocks (~> 3.4.0)
|
||||||
rspec-support (~> 3.3.0)
|
rspec-support (~> 3.4.0)
|
||||||
rspec-support (3.3.0)
|
rspec-support (3.4.1)
|
||||||
sass (3.4.19)
|
sass (3.4.21)
|
||||||
sass-rails (5.0.4)
|
sass-rails (5.0.4)
|
||||||
railties (>= 4.0.0, < 5.0)
|
railties (>= 4.0.0, < 5.0)
|
||||||
sass (~> 3.1)
|
sass (~> 3.1)
|
||||||
sprockets (>= 2.8, < 4.0)
|
sprockets (>= 2.8, < 4.0)
|
||||||
sprockets-rails (>= 2.0, < 4.0)
|
sprockets-rails (>= 2.0, < 4.0)
|
||||||
tilt (>= 1.1, < 3)
|
tilt (>= 1.1, < 3)
|
||||||
shoulda-matchers (3.0.1)
|
shoulda-matchers (3.1.1)
|
||||||
activesupport (>= 4.0.0)
|
activesupport (>= 4.0.0)
|
||||||
|
simplecov (0.11.2)
|
||||||
|
docile (~> 1.1.0)
|
||||||
|
json (~> 1.8)
|
||||||
|
simplecov-html (~> 0.10.0)
|
||||||
|
simplecov-html (0.10.0)
|
||||||
slop (3.6.0)
|
slop (3.6.0)
|
||||||
sprockets (3.4.0)
|
snorlax (0.1.5)
|
||||||
|
rails (> 4.1)
|
||||||
|
sprockets (3.5.2)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
rack (> 1, < 3)
|
rack (> 1, < 3)
|
||||||
sprockets-rails (2.3.3)
|
sprockets-rails (3.0.4)
|
||||||
actionpack (>= 3.0)
|
actionpack (>= 4.0)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 4.0)
|
||||||
sprockets (>= 2.8, < 4.0)
|
sprockets (>= 3.0.0)
|
||||||
thor (0.19.1)
|
thor (0.19.1)
|
||||||
thread_safe (0.3.5)
|
thread_safe (0.3.5)
|
||||||
tilt (2.0.1)
|
tilt (2.0.2)
|
||||||
tunemygc (1.0.61)
|
tunemygc (1.0.65)
|
||||||
tzinfo (1.2.2)
|
tzinfo (1.2.2)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
uglifier (2.7.2)
|
uglifier (2.7.2)
|
||||||
|
@ -223,33 +251,40 @@ GEM
|
||||||
ezcrypto (>= 0.7.2)
|
ezcrypto (>= 0.7.2)
|
||||||
json (>= 1.7.5)
|
json (>= 1.7.5)
|
||||||
oauth (>= 0.4.7)
|
oauth (>= 0.4.7)
|
||||||
warden (1.2.3)
|
warden (1.2.6)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
active_model_serializers (~> 0.8.1)
|
||||||
aws-sdk (< 2.0)
|
aws-sdk (< 2.0)
|
||||||
best_in_place
|
best_in_place
|
||||||
better_errors
|
better_errors
|
||||||
binding_of_caller
|
binding_of_caller
|
||||||
cancancan
|
|
||||||
coffee-rails
|
coffee-rails
|
||||||
|
delayed_job (~> 4.0.2)
|
||||||
|
delayed_job_active_record (~> 4.0.1)
|
||||||
devise
|
devise
|
||||||
|
doorkeeper
|
||||||
dotenv
|
dotenv
|
||||||
factory_girl_rails
|
factory_girl_rails
|
||||||
formtastic
|
formtastic
|
||||||
formula
|
formula
|
||||||
|
httparty
|
||||||
jbuilder
|
jbuilder
|
||||||
jquery-rails
|
jquery-rails
|
||||||
jquery-ui-rails
|
jquery-ui-rails
|
||||||
json
|
json
|
||||||
|
json-schema
|
||||||
kaminari
|
kaminari
|
||||||
paperclip
|
paperclip
|
||||||
pg
|
pg
|
||||||
pry-byebug
|
pry-byebug
|
||||||
pry-rails
|
pry-rails
|
||||||
|
pundit
|
||||||
|
pundit_extra
|
||||||
quiet_assets
|
quiet_assets
|
||||||
rails (= 4.2.4)
|
rails (= 4.2.4)
|
||||||
rails3-jquery-autocomplete
|
rails3-jquery-autocomplete
|
||||||
|
@ -258,9 +293,11 @@ DEPENDENCIES
|
||||||
rspec-rails
|
rspec-rails
|
||||||
sass-rails
|
sass-rails
|
||||||
shoulda-matchers
|
shoulda-matchers
|
||||||
|
simplecov
|
||||||
|
snorlax
|
||||||
tunemygc
|
tunemygc
|
||||||
uglifier
|
uglifier
|
||||||
uservoice-ruby
|
uservoice-ruby
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.10.6
|
1.11.2
|
||||||
|
|
2
Procfile
|
@ -1 +1,3 @@
|
||||||
web: bundle exec rails server -p $PORT
|
web: bundle exec rails server -p $PORT
|
||||||
|
worker: bundle exec rake jobs:work
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@ Metamaps
|
||||||
=======
|
=======
|
||||||
|
|
||||||
[](https://gitter.im/metamaps/metamaps_gen002?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/metamaps/metamaps_gen002?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||

|
[](https://travis-ci.org/metamaps/metamaps_gen002)
|
||||||
|
|
||||||
Welcome to the Metamaps GitHub repo.
|
Welcome to the Metamaps GitHub repo.
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ Metamaps is a free and AGPL open source technology for changemakers, innovators,
|
||||||
|
|
||||||
You can find a version of this software running at [metamaps.cc][site-beta], where the technology is being tested in a private beta.
|
You can find a version of this software running at [metamaps.cc][site-beta], where the technology is being tested in a private beta.
|
||||||
|
|
||||||
Metamaps is created and maintained by a distributed, nomadic community comprised of technologists, artists and storytellers. You can get in touch with us at team@metamaps.cc or @metamapps on twitter.
|
Metamaps is created and maintained by a distributed, nomadic community comprised of technologists, artists and storytellers. You can get in touch with us at team@metamaps.cc or @metamapps on twitter.
|
||||||
|
|
||||||
To get connected with the community interested in Metamaps, join our [Google+ community][community].
|
To get connected with the community interested in Metamaps, join our [Google+ community][community].
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ We haven't figured out Vagrant for Windows yet, but we have a set of manual inst
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Cloning this repository directly is primarily for those wishing to contribute to our codebase. Check out our [contributing instructions][contributing] to get involved.
|
Cloning this repository directly is primarily for those wishing to contribute to our codebase. Check out our [contributing instructions][contributing] to get involved.
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
|
|
1
Vagrantfile
vendored
|
@ -16,7 +16,6 @@ sudo apt-get install nodejs -y
|
||||||
sudo apt-get install npm -y
|
sudo apt-get install npm -y
|
||||||
sudo apt-get install postgresql -y
|
sudo apt-get install postgresql -y
|
||||||
sudo apt-get install libpq-dev -y
|
sudo apt-get install libpq-dev -y
|
||||||
sudo apt-get install redis-server -y
|
|
||||||
|
|
||||||
# get imagemagick
|
# get imagemagick
|
||||||
sudo apt-get install imagemagick --fix-missing
|
sudo apt-get install imagemagick --fix-missing
|
||||||
|
|
BIN
app/assets/images/audio_sprite.png
Normal file
After Width: | Height: | Size: 854 B |
BIN
app/assets/images/camera_sprite.png
Normal file
After Width: | Height: | Size: 780 B |
BIN
app/assets/images/chat32.png
Normal file
After Width: | Height: | Size: 466 B |
BIN
app/assets/images/cursor_sprite.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
app/assets/images/default_profile.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
app/assets/images/ellipsis.gif
Normal file
After Width: | Height: | Size: 220 B |
BIN
app/assets/images/invitepeer16.png
Normal file
After Width: | Height: | Size: 223 B |
BIN
app/assets/images/junto.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
app/assets/images/junto_spinner_dark.gif
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
app/assets/images/sound_sprite.png
Normal file
After Width: | Height: | Size: 717 B |
BIN
app/assets/images/sounds/sounds.mp3
Normal file
BIN
app/assets/images/sounds/sounds.ogg
Normal file
BIN
app/assets/images/tray_tab.png
Normal file
After Width: | Height: | Size: 331 B |
BIN
app/assets/images/video_sprite.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
|
@ -1,28 +1,32 @@
|
||||||
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
||||||
// listed below.
|
// listed below.
|
||||||
//
|
//
|
||||||
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
||||||
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
||||||
//
|
//
|
||||||
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
||||||
// the compiled file.
|
// the compiled file.
|
||||||
//
|
//
|
||||||
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
||||||
// GO AFTER THE REQUIRES BELOW.
|
// GO AFTER THE REQUIRES BELOW.
|
||||||
//
|
//
|
||||||
//= require jquery
|
//= require jquery
|
||||||
//= require jquery-ui
|
//= require jquery-ui
|
||||||
//= require jquery_ujs
|
//= require jquery_ujs
|
||||||
//= require ./orderedLibraries/underscore
|
//= require ./orderedLibraries/underscore
|
||||||
//= require ./orderedLibraries/backbone
|
//= require ./orderedLibraries/backbone
|
||||||
//= require_directory ./lib
|
//= require_directory ./lib
|
||||||
//= require ./src/Metamaps.GlobalUI
|
//= require ./src/Metamaps.GlobalUI
|
||||||
//= require ./src/Metamaps.Router
|
//= require ./src/Metamaps.Router
|
||||||
//= require ./src/Metamaps.Backbone
|
//= require ./src/Metamaps.Backbone
|
||||||
//= require ./src/Metamaps.Views
|
//= require ./src/Metamaps.Views
|
||||||
//= require ./src/JIT
|
//= require ./src/views/chatView
|
||||||
//= require ./src/Metamaps
|
//= require ./src/views/videoView
|
||||||
//= require ./src/Metamaps.JIT
|
//= require ./src/views/room
|
||||||
//= require_directory ./shims
|
//= require ./src/JIT
|
||||||
//= require_directory ./require
|
//= require ./src/Metamaps
|
||||||
//= require_directory ./famous
|
//= require ./src/Metamaps.Import
|
||||||
|
//= require ./src/Metamaps.JIT
|
||||||
|
//= require_directory ./shims
|
||||||
|
//= require_directory ./require
|
||||||
|
//= require_directory ./famous
|
||||||
|
|
2756
app/assets/javascripts/lib/Autolinker.js
Normal file
39
app/assets/javascripts/lib/attachMediaStream.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
var attachMediaStream = function (stream, el, options) {
|
||||||
|
var URL = window.URL;
|
||||||
|
var opts = {
|
||||||
|
autoplay: true,
|
||||||
|
mirror: false,
|
||||||
|
muted: false
|
||||||
|
};
|
||||||
|
var element = el || document.createElement('video');
|
||||||
|
var item;
|
||||||
|
|
||||||
|
if (options) {
|
||||||
|
for (item in options) {
|
||||||
|
opts[item] = options[item];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.autoplay) element.autoplay = 'autoplay';
|
||||||
|
if (opts.muted) element.muted = true;
|
||||||
|
if (opts.mirror) {
|
||||||
|
['', 'moz', 'webkit', 'o', 'ms'].forEach(function (prefix) {
|
||||||
|
var styleName = prefix ? prefix + 'Transform' : 'transform';
|
||||||
|
element.style[styleName] = 'scaleX(-1)';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// this first one should work most everywhere now
|
||||||
|
// but we have a few fallbacks just in case.
|
||||||
|
if (URL && URL.createObjectURL) {
|
||||||
|
element.src = URL.createObjectURL(stream);
|
||||||
|
} else if (element.srcObject) {
|
||||||
|
element.srcObject = stream;
|
||||||
|
} else if (element.mozSrcObject) {
|
||||||
|
element.mozSrcObject = stream;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
};
|
|
@ -1,426 +1,426 @@
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
// CloudCarousel V1.0.5
|
// CloudCarousel V1.0.5
|
||||||
// (c) 2011 by R Cecco. <http://www.professorcloud.com>
|
// (c) 2011 by R Cecco. <http://www.professorcloud.com>
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Reflection code based on plugin by Christophe Beyls <http://www.digitalia.be>
|
// Reflection code based on plugin by Christophe Beyls <http://www.digitalia.be>
|
||||||
//
|
//
|
||||||
// Please retain this copyright header in all versions of the software
|
// Please retain this copyright header in all versions of the software
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
var matched, browser;
|
var matched, browser;
|
||||||
|
|
||||||
jQuery.uaMatch = function( ua ) {
|
jQuery.uaMatch = function( ua ) {
|
||||||
ua = ua.toLowerCase();
|
ua = ua.toLowerCase();
|
||||||
|
|
||||||
var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
|
var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
|
||||||
/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
|
/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
|
||||||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
|
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
|
||||||
/(msie) ([\w.]+)/.exec( ua ) ||
|
/(msie) ([\w.]+)/.exec( ua ) ||
|
||||||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
|
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
|
||||||
[];
|
[];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
browser: match[ 1 ] || "",
|
browser: match[ 1 ] || "",
|
||||||
version: match[ 2 ] || "0"
|
version: match[ 2 ] || "0"
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
matched = jQuery.uaMatch( navigator.userAgent );
|
matched = jQuery.uaMatch( navigator.userAgent );
|
||||||
browser = {};
|
browser = {};
|
||||||
|
|
||||||
if ( matched.browser ) {
|
if ( matched.browser ) {
|
||||||
browser[ matched.browser ] = true;
|
browser[ matched.browser ] = true;
|
||||||
browser.version = matched.version;
|
browser.version = matched.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chrome is Webkit, but Webkit is also Safari.
|
// Chrome is Webkit, but Webkit is also Safari.
|
||||||
if ( browser.chrome ) {
|
if ( browser.chrome ) {
|
||||||
browser.webkit = true;
|
browser.webkit = true;
|
||||||
} else if ( browser.webkit ) {
|
} else if ( browser.webkit ) {
|
||||||
browser.safari = true;
|
browser.safari = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery.browser = browser;
|
jQuery.browser = browser;
|
||||||
|
|
||||||
(function($) {
|
(function($) {
|
||||||
|
|
||||||
// START Reflection object.
|
// START Reflection object.
|
||||||
// Creates a reflection for underneath an image.
|
// Creates a reflection for underneath an image.
|
||||||
// IE uses an image with IE specific filter properties, other browsers use the Canvas tag.
|
// IE uses an image with IE specific filter properties, other browsers use the Canvas tag.
|
||||||
// The position and size of the reflection gets updated by updateAll() in Controller.
|
// The position and size of the reflection gets updated by updateAll() in Controller.
|
||||||
function Reflection(img, reflHeight, opacity) {
|
function Reflection(img, reflHeight, opacity) {
|
||||||
|
|
||||||
var reflection, cntx, imageWidth = img.width, imageHeight = img.width, gradient, parent;
|
var reflection, cntx, imageWidth = img.width, imageHeight = img.width, gradient, parent;
|
||||||
|
|
||||||
parent = $(img.parentNode);
|
parent = $(img.parentNode);
|
||||||
this.element = reflection = parent.append("<canvas class='reflection' style='position:absolute'/>").find(':last')[0];
|
this.element = reflection = parent.append("<canvas class='reflection' style='position:absolute'/>").find(':last')[0];
|
||||||
if ( !reflection.getContext && $.browser.msie) {
|
if ( !reflection.getContext && $.browser.msie) {
|
||||||
this.element = reflection = parent.append("<img class='reflection' style='position:absolute'/>").find(':last')[0];
|
this.element = reflection = parent.append("<img class='reflection' style='position:absolute'/>").find(':last')[0];
|
||||||
reflection.src = img.src;
|
reflection.src = img.src;
|
||||||
reflection.style.filter = "flipv progid:DXImageTransform.Microsoft.Alpha(opacity=" + (opacity * 100) + ", style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy=" + (reflHeight / imageHeight * 100) + ")";
|
reflection.style.filter = "flipv progid:DXImageTransform.Microsoft.Alpha(opacity=" + (opacity * 100) + ", style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy=" + (reflHeight / imageHeight * 100) + ")";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cntx = reflection.getContext("2d");
|
cntx = reflection.getContext("2d");
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
|
||||||
$(reflection).attr({width: imageWidth, height: reflHeight});
|
$(reflection).attr({width: imageWidth, height: reflHeight});
|
||||||
cntx.save();
|
cntx.save();
|
||||||
cntx.translate(0, imageHeight-1);
|
cntx.translate(0, imageHeight-1);
|
||||||
cntx.scale(1, -1);
|
cntx.scale(1, -1);
|
||||||
cntx.drawImage(img, 0, 0, imageWidth, imageHeight);
|
cntx.drawImage(img, 0, 0, imageWidth, imageHeight);
|
||||||
cntx.restore();
|
cntx.restore();
|
||||||
cntx.globalCompositeOperation = "destination-out";
|
cntx.globalCompositeOperation = "destination-out";
|
||||||
gradient = cntx.createLinearGradient(0, 0, 0, reflHeight);
|
gradient = cntx.createLinearGradient(0, 0, 0, reflHeight);
|
||||||
gradient.addColorStop(0, "rgba(255, 255, 255, " + (1 - opacity) + ")");
|
gradient.addColorStop(0, "rgba(255, 255, 255, " + (1 - opacity) + ")");
|
||||||
gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
|
gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
|
||||||
cntx.fillStyle = gradient;
|
cntx.fillStyle = gradient;
|
||||||
cntx.fillRect(0, 0, imageWidth, reflHeight);
|
cntx.fillRect(0, 0, imageWidth, reflHeight);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Store a copy of the alt and title attrs into the reflection
|
// Store a copy of the alt and title attrs into the reflection
|
||||||
$(reflection).attr({ 'alt': $(img).attr('alt'), title: $(img).attr('title')} );
|
$(reflection).attr({ 'alt': $(img).attr('alt'), title: $(img).attr('title')} );
|
||||||
|
|
||||||
} //END Reflection object
|
} //END Reflection object
|
||||||
|
|
||||||
// START Item object.
|
// START Item object.
|
||||||
// A wrapper object for items within the carousel.
|
// A wrapper object for items within the carousel.
|
||||||
var Item = function(imgIn, options)
|
var Item = function(imgIn, options)
|
||||||
{
|
{
|
||||||
this.orgWidth = imgIn.width;
|
this.orgWidth = imgIn.width;
|
||||||
this.orgHeight = imgIn.height;
|
this.orgHeight = imgIn.height;
|
||||||
this.image = imgIn;
|
this.image = imgIn;
|
||||||
this.reflection = null;
|
this.reflection = null;
|
||||||
this.alt = imgIn.alt;
|
this.alt = imgIn.alt;
|
||||||
this.title = imgIn.title;
|
this.title = imgIn.title;
|
||||||
this.imageOK = false;
|
this.imageOK = false;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
|
||||||
this.imageOK = true;
|
this.imageOK = true;
|
||||||
|
|
||||||
if (this.options.reflHeight > 0)
|
if (this.options.reflHeight > 0)
|
||||||
{
|
{
|
||||||
this.reflection = new Reflection(this.image, this.options.reflHeight, this.options.reflOpacity);
|
this.reflection = new Reflection(this.image, this.options.reflHeight, this.options.reflOpacity);
|
||||||
}
|
}
|
||||||
$(this.image).css('position','absolute'); // Bizarre. This seems to reset image width to 0 on webkit!
|
$(this.image).css('position','absolute'); // Bizarre. This seems to reset image width to 0 on webkit!
|
||||||
};// END Item object
|
};// END Item object
|
||||||
|
|
||||||
|
|
||||||
// Controller object.
|
// Controller object.
|
||||||
// This handles moving all the items, dealing with mouse clicks etc.
|
// This handles moving all the items, dealing with mouse clicks etc.
|
||||||
var Controller = function(container, images, options)
|
var Controller = function(container, images, options)
|
||||||
{
|
{
|
||||||
var items = [], funcSin = Math.sin, funcCos = Math.cos, ctx=this;
|
var items = [], funcSin = Math.sin, funcCos = Math.cos, ctx=this;
|
||||||
this.controlTimer = 0;
|
this.controlTimer = 0;
|
||||||
this.stopped = false;
|
this.stopped = false;
|
||||||
//this.imagesLoaded = 0;
|
//this.imagesLoaded = 0;
|
||||||
this.container = container;
|
this.container = container;
|
||||||
this.xRadius = options.xRadius;
|
this.xRadius = options.xRadius;
|
||||||
this.yRadius = options.yRadius;
|
this.yRadius = options.yRadius;
|
||||||
this.showFrontTextTimer = 0;
|
this.showFrontTextTimer = 0;
|
||||||
this.autoRotateTimer = 0;
|
this.autoRotateTimer = 0;
|
||||||
if (options.xRadius === 0)
|
if (options.xRadius === 0)
|
||||||
{
|
{
|
||||||
this.xRadius = ($(container).width()/2.3);
|
this.xRadius = ($(container).width()/2.3);
|
||||||
}
|
}
|
||||||
if (options.yRadius === 0)
|
if (options.yRadius === 0)
|
||||||
{
|
{
|
||||||
this.yRadius = ($(container).height()/6);
|
this.yRadius = ($(container).height()/6);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.xCentre = options.xPos;
|
this.xCentre = options.xPos;
|
||||||
this.yCentre = options.yPos;
|
this.yCentre = options.yPos;
|
||||||
this.frontIndex = 0; // Index of the item at the front
|
this.frontIndex = 0; // Index of the item at the front
|
||||||
|
|
||||||
// Start with the first item at the front.
|
// Start with the first item at the front.
|
||||||
this.rotation = this.destRotation = Math.PI/2;
|
this.rotation = this.destRotation = Math.PI/2;
|
||||||
this.timeDelay = 1000/options.FPS;
|
this.timeDelay = 1000/options.FPS;
|
||||||
|
|
||||||
// Turn on the infoBox
|
// Turn on the infoBox
|
||||||
if(options.altBox !== null)
|
if(options.altBox !== null)
|
||||||
{
|
{
|
||||||
$(options.altBox).css('display','block');
|
$(options.altBox).css('display','block');
|
||||||
$(options.titleBox).css('display','block');
|
$(options.titleBox).css('display','block');
|
||||||
}
|
}
|
||||||
// Turn on relative position for container to allow absolutely positioned elements
|
// Turn on relative position for container to allow absolutely positioned elements
|
||||||
// within it to work.
|
// within it to work.
|
||||||
$(container).css({ position:'relative', overflow:'hidden'} );
|
$(container).css({ position:'relative', overflow:'hidden'} );
|
||||||
|
|
||||||
$(options.buttonLeft).css('display','inline');
|
$(options.buttonLeft).css('display','inline');
|
||||||
$(options.buttonRight).css('display','inline');
|
$(options.buttonRight).css('display','inline');
|
||||||
|
|
||||||
// Setup the buttons.
|
// Setup the buttons.
|
||||||
$(options.buttonLeft).bind('mouseup',this,function(event){
|
$(options.buttonLeft).bind('mouseup',this,function(event){
|
||||||
event.data.rotate(-1);
|
event.data.rotate(-1);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
$(options.buttonRight).bind('mouseup',this,function(event){
|
$(options.buttonRight).bind('mouseup',this,function(event){
|
||||||
event.data.rotate(1);
|
event.data.rotate(1);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add code that makes tab and shift+tab scroll through metacodes
|
// Add code that makes tab and shift+tab scroll through metacodes
|
||||||
$('.new_topic').bind('keydown',this,function(event){
|
$('.new_topic').bind('keydown',this,function(event){
|
||||||
if (event.keyCode == 9 && event.shiftKey) {
|
if (event.keyCode == 9 && event.shiftKey) {
|
||||||
event.data.rotate(-1);
|
event.data.rotate(-1);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
} else if (event.keyCode == 9) {
|
} else if (event.keyCode == 9) {
|
||||||
event.data.rotate(1);
|
event.data.rotate(1);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel
|
// You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel
|
||||||
if (options.mouseWheel)
|
if (options.mouseWheel)
|
||||||
{
|
{
|
||||||
// START METAMAPS CODE
|
// START METAMAPS CODE
|
||||||
$('body').bind('mousewheel',this,function(event, delta) {
|
$('body').bind('mousewheel',this,function(event, delta) {
|
||||||
if (Metamaps.Create.newTopic.beingCreated && !Metamaps.Create.isSwitchingSet) {
|
if (Metamaps.Create.newTopic.beingCreated && !Metamaps.Create.isSwitchingSet) {
|
||||||
event.data.rotate(delta);
|
event.data.rotate(delta);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// END METAMAPS CODE
|
// END METAMAPS CODE
|
||||||
/* ORIGINAL CODE
|
/* ORIGINAL CODE
|
||||||
$(container).bind('mousewheel',this,function(event, delta) {
|
$(container).bind('mousewheel',this,function(event, delta) {
|
||||||
event.data.rotate(delta);
|
event.data.rotate(delta);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
$(container).bind('mouseover click',this,function(event){
|
$(container).bind('mouseover click',this,function(event){
|
||||||
|
|
||||||
clearInterval(event.data.autoRotateTimer); // Stop auto rotation if mouse over.
|
clearInterval(event.data.autoRotateTimer); // Stop auto rotation if mouse over.
|
||||||
var text = $(event.target).attr('alt');
|
var text = $(event.target).attr('alt');
|
||||||
// If we have moved over a carousel item, then show the alt and title text.
|
// If we have moved over a carousel item, then show the alt and title text.
|
||||||
|
|
||||||
if ( text !== undefined && text !== null )
|
if ( text !== undefined && text !== null )
|
||||||
{
|
{
|
||||||
|
|
||||||
clearTimeout(event.data.showFrontTextTimer);
|
clearTimeout(event.data.showFrontTextTimer);
|
||||||
$(options.altBox).html( ($(event.target).attr('alt') ));
|
$(options.altBox).html( ($(event.target).attr('alt') ));
|
||||||
//$(options.titleBox).html( ($(event.target).attr('title') ));
|
//$(options.titleBox).html( ($(event.target).attr('title') ));
|
||||||
if ( options.bringToFront && event.type == 'click' )
|
if ( options.bringToFront && event.type == 'click' )
|
||||||
{
|
{
|
||||||
$(options.titleBox).html( ($(event.target).attr('title') ));
|
$(options.titleBox).html( ($(event.target).attr('title') ));
|
||||||
// METAMAPS CODE
|
// METAMAPS CODE
|
||||||
Metamaps.Create.newTopic.metacode = $(event.target).attr('data-id');
|
Metamaps.Create.newTopic.metacode = $(event.target).attr('data-id');
|
||||||
// NOT METAMAPS CODE
|
// NOT METAMAPS CODE
|
||||||
var idx = $(event.target).data('itemIndex');
|
var idx = $(event.target).data('itemIndex');
|
||||||
var frontIndex = event.data.frontIndex;
|
var frontIndex = event.data.frontIndex;
|
||||||
//var diff = idx - frontIndex;
|
//var diff = idx - frontIndex;
|
||||||
var diff = (idx - frontIndex) % images.length;
|
var diff = (idx - frontIndex) % images.length;
|
||||||
if (Math.abs(diff) > images.length / 2) {
|
if (Math.abs(diff) > images.length / 2) {
|
||||||
diff += (diff > 0 ? -images.length : images.length);
|
diff += (diff > 0 ? -images.length : images.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
event.data.rotate(-diff);
|
event.data.rotate(-diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// If we have moved out of a carousel item (or the container itself),
|
// If we have moved out of a carousel item (or the container itself),
|
||||||
// restore the text of the front item in 1 second.
|
// restore the text of the front item in 1 second.
|
||||||
$(container).bind('mouseout',this,function(event){
|
$(container).bind('mouseout',this,function(event){
|
||||||
var context = event.data;
|
var context = event.data;
|
||||||
clearTimeout(context.showFrontTextTimer);
|
clearTimeout(context.showFrontTextTimer);
|
||||||
context.showFrontTextTimer = setTimeout( function(){context.showFrontText();},1000);
|
context.showFrontTextTimer = setTimeout( function(){context.showFrontText();},1000);
|
||||||
context.autoRotate(); // Start auto rotation.
|
context.autoRotate(); // Start auto rotation.
|
||||||
});
|
});
|
||||||
|
|
||||||
// Prevent items from being selected as mouse is moved and clicked in the container.
|
// Prevent items from being selected as mouse is moved and clicked in the container.
|
||||||
$(container).bind('mousedown',this,function(event){
|
$(container).bind('mousedown',this,function(event){
|
||||||
|
|
||||||
event.data.container.focus();
|
event.data.container.focus();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
container.onselectstart = function () { return false; }; // For IE.
|
container.onselectstart = function () { return false; }; // For IE.
|
||||||
|
|
||||||
this.innerWrapper = $(container).wrapInner('<div style="position:absolute;width:100%;height:100%;"/>').children()[0];
|
this.innerWrapper = $(container).wrapInner('<div style="position:absolute;width:100%;height:100%;"/>').children()[0];
|
||||||
|
|
||||||
// Shows the text from the front most item.
|
// Shows the text from the front most item.
|
||||||
this.showFrontText = function()
|
this.showFrontText = function()
|
||||||
{
|
{
|
||||||
if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet.
|
if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet.
|
||||||
// METAMAPS CODE
|
// METAMAPS CODE
|
||||||
Metamaps.Create.newTopic.metacode = $(items[this.frontIndex].image).attr('data-id');
|
Metamaps.Create.newTopic.metacode = $(items[this.frontIndex].image).attr('data-id');
|
||||||
//$('img.cloudcarousel').css({"background":"none", "width":"","height":""});
|
//$('img.cloudcarousel').css({"background":"none", "width":"","height":""});
|
||||||
//$(items[this.frontIndex].image).css({"width":"45px","height":"45px"});
|
//$(items[this.frontIndex].image).css({"width":"45px","height":"45px"});
|
||||||
// NOT METAMAPS CODE
|
// NOT METAMAPS CODE
|
||||||
$(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));
|
$(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));
|
||||||
$(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));
|
$(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));
|
||||||
};
|
};
|
||||||
|
|
||||||
this.go = function()
|
this.go = function()
|
||||||
{
|
{
|
||||||
if(this.controlTimer !== 0) { return; }
|
if(this.controlTimer !== 0) { return; }
|
||||||
var context = this;
|
var context = this;
|
||||||
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
|
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.stop = function()
|
this.stop = function()
|
||||||
{
|
{
|
||||||
clearTimeout(this.controlTimer);
|
clearTimeout(this.controlTimer);
|
||||||
this.controlTimer = 0;
|
this.controlTimer = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Starts the rotation of the carousel. Direction is the number (+-) of carousel items to rotate by.
|
// Starts the rotation of the carousel. Direction is the number (+-) of carousel items to rotate by.
|
||||||
this.rotate = function(direction)
|
this.rotate = function(direction)
|
||||||
{
|
{
|
||||||
this.frontIndex -= direction;
|
this.frontIndex -= direction;
|
||||||
if (this.frontIndex == -1) this.frontIndex = items.length - 1;
|
if (this.frontIndex == -1) this.frontIndex = items.length - 1;
|
||||||
this.frontIndex %= items.length;
|
this.frontIndex %= items.length;
|
||||||
this.destRotation += ( Math.PI / items.length ) * ( 2*direction );
|
this.destRotation += ( Math.PI / items.length ) * ( 2*direction );
|
||||||
this.showFrontText();
|
this.showFrontText();
|
||||||
this.go();
|
this.go();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.autoRotate = function()
|
this.autoRotate = function()
|
||||||
{
|
{
|
||||||
if ( options.autoRotate !== 'no' )
|
if ( options.autoRotate !== 'no' )
|
||||||
{
|
{
|
||||||
var dir = (options.autoRotate === 'right')? 1 : -1;
|
var dir = (options.autoRotate === 'right')? 1 : -1;
|
||||||
this.autoRotateTimer = setInterval( function(){ctx.rotate(dir); }, options.autoRotateDelay );
|
this.autoRotateTimer = setInterval( function(){ctx.rotate(dir); }, options.autoRotateDelay );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is the main loop function that moves everything.
|
// This is the main loop function that moves everything.
|
||||||
this.updateAll = function()
|
this.updateAll = function()
|
||||||
{
|
{
|
||||||
var minScale = options.minScale; // This is the smallest scale applied to the furthest item.
|
var minScale = options.minScale; // This is the smallest scale applied to the furthest item.
|
||||||
var smallRange = (1-minScale) * 0.5;
|
var smallRange = (1-minScale) * 0.5;
|
||||||
var w,h,x,y,scale,item,sinVal;
|
var w,h,x,y,scale,item,sinVal;
|
||||||
|
|
||||||
var change = (this.destRotation - this.rotation);
|
var change = (this.destRotation - this.rotation);
|
||||||
var absChange = Math.abs(change);
|
var absChange = Math.abs(change);
|
||||||
|
|
||||||
this.rotation += change * options.speed;
|
this.rotation += change * options.speed;
|
||||||
if ( absChange < 0.001 ) { this.rotation = this.destRotation; }
|
if ( absChange < 0.001 ) { this.rotation = this.destRotation; }
|
||||||
var itemsLen = items.length;
|
var itemsLen = items.length;
|
||||||
var spacing = (Math.PI / itemsLen) * 2;
|
var spacing = (Math.PI / itemsLen) * 2;
|
||||||
//var wrapStyle = null;
|
//var wrapStyle = null;
|
||||||
var radians = this.rotation;
|
var radians = this.rotation;
|
||||||
var isMSIE = $.browser.msie;
|
var isMSIE = $.browser.msie;
|
||||||
|
|
||||||
// Turn off display. This can reduce repaints/reflows when making style and position changes in the loop.
|
// Turn off display. This can reduce repaints/reflows when making style and position changes in the loop.
|
||||||
// See http://dev.opera.com/articles/view/efficient-javascript/?page=3
|
// See http://dev.opera.com/articles/view/efficient-javascript/?page=3
|
||||||
this.innerWrapper.style.display = 'none';
|
this.innerWrapper.style.display = 'none';
|
||||||
|
|
||||||
var style;
|
var style;
|
||||||
var px = 'px', reflHeight;
|
var px = 'px', reflHeight;
|
||||||
var context = this;
|
var context = this;
|
||||||
for (var i = 0; i<itemsLen ;i++)
|
for (var i = 0; i<itemsLen ;i++)
|
||||||
{
|
{
|
||||||
item = items[i];
|
item = items[i];
|
||||||
|
|
||||||
sinVal = funcSin(radians);
|
sinVal = funcSin(radians);
|
||||||
|
|
||||||
scale = ((sinVal+1) * smallRange) + minScale;
|
scale = ((sinVal+1) * smallRange) + minScale;
|
||||||
|
|
||||||
x = this.xCentre + (( (funcCos(radians) * this.xRadius) - (item.orgWidth*0.5)) * scale);
|
x = this.xCentre + (( (funcCos(radians) * this.xRadius) - (item.orgWidth*0.5)) * scale);
|
||||||
y = this.yCentre + (( (sinVal * this.yRadius) ) * scale);
|
y = this.yCentre + (( (sinVal * this.yRadius) ) * scale);
|
||||||
|
|
||||||
if (item.imageOK)
|
if (item.imageOK)
|
||||||
{
|
{
|
||||||
var img = item.image;
|
var img = item.image;
|
||||||
|
|
||||||
img.style.zIndex = "" + (scale * 100)>>0; // >>0 = Math.foor(). Firefox doesn't like fractional decimals in z-index.
|
img.style.zIndex = "" + (scale * 100)>>0; // >>0 = Math.foor(). Firefox doesn't like fractional decimals in z-index.
|
||||||
w = img.width = item.orgWidth * scale;
|
w = img.width = item.orgWidth * scale;
|
||||||
h = img.height = item.orgHeight * scale;
|
h = img.height = item.orgHeight * scale;
|
||||||
img.style.left = x + px ;
|
img.style.left = x + px ;
|
||||||
img.style.top = y + px;
|
img.style.top = y + px;
|
||||||
if (item.reflection !== null)
|
if (item.reflection !== null)
|
||||||
{
|
{
|
||||||
reflHeight = options.reflHeight * scale;
|
reflHeight = options.reflHeight * scale;
|
||||||
style = item.reflection.element.style;
|
style = item.reflection.element.style;
|
||||||
style.left = x + px;
|
style.left = x + px;
|
||||||
style.top = y + h + options.reflGap * scale + px;
|
style.top = y + h + options.reflGap * scale + px;
|
||||||
style.width = w + px;
|
style.width = w + px;
|
||||||
if (isMSIE)
|
if (isMSIE)
|
||||||
{
|
{
|
||||||
style.filter.finishy = (reflHeight / h * 100);
|
style.filter.finishy = (reflHeight / h * 100);
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
style.height = reflHeight + px;
|
style.height = reflHeight + px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
radians += spacing;
|
radians += spacing;
|
||||||
}
|
}
|
||||||
// Turn display back on.
|
// Turn display back on.
|
||||||
this.innerWrapper.style.display = 'block';
|
this.innerWrapper.style.display = 'block';
|
||||||
|
|
||||||
// If we have a preceptable change in rotation then loop again next frame.
|
// If we have a preceptable change in rotation then loop again next frame.
|
||||||
if ( absChange >= 0.001 )
|
if ( absChange >= 0.001 )
|
||||||
{
|
{
|
||||||
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
|
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
// Otherwise just stop completely.
|
// Otherwise just stop completely.
|
||||||
this.stop();
|
this.stop();
|
||||||
}
|
}
|
||||||
}; // END updateAll
|
}; // END updateAll
|
||||||
|
|
||||||
// Create an Item object for each image
|
// Create an Item object for each image
|
||||||
// func = function(){return;ctx.updateAll();} ;
|
// func = function(){return;ctx.updateAll();} ;
|
||||||
|
|
||||||
// Check if images have loaded. We need valid widths and heights for the reflections.
|
// Check if images have loaded. We need valid widths and heights for the reflections.
|
||||||
this.checkImagesLoaded = function()
|
this.checkImagesLoaded = function()
|
||||||
{
|
{
|
||||||
var i;
|
var i;
|
||||||
for(i=0;i<images.length;i++) {
|
for(i=0;i<images.length;i++) {
|
||||||
if ( (images[i].width === undefined) || ( (images[i].complete !== undefined) && (!images[i].complete) ))
|
if ( (images[i].width === undefined) || ( (images[i].complete !== undefined) && (!images[i].complete) ))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(i=0;i<images.length;i++) {
|
for(i=0;i<images.length;i++) {
|
||||||
items.push( new Item( images[i], options ) );
|
items.push( new Item( images[i], options ) );
|
||||||
$(images[i]).data('itemIndex',i);
|
$(images[i]).data('itemIndex',i);
|
||||||
}
|
}
|
||||||
// If all images have valid widths and heights, we can stop checking.
|
// If all images have valid widths and heights, we can stop checking.
|
||||||
clearInterval(this.tt);
|
clearInterval(this.tt);
|
||||||
this.showFrontText();
|
this.showFrontText();
|
||||||
this.autoRotate();
|
this.autoRotate();
|
||||||
this.updateAll();
|
this.updateAll();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.tt = setInterval( function(){ctx.checkImagesLoaded();},50);
|
this.tt = setInterval( function(){ctx.checkImagesLoaded();},50);
|
||||||
}; // END Controller object
|
}; // END Controller object
|
||||||
|
|
||||||
// The jQuery plugin part. Iterates through items specified in selector and inits a Controller class for each one.
|
// The jQuery plugin part. Iterates through items specified in selector and inits a Controller class for each one.
|
||||||
$.fn.CloudCarousel = function(options) {
|
$.fn.CloudCarousel = function(options) {
|
||||||
|
|
||||||
this.each( function() {
|
this.each( function() {
|
||||||
|
|
||||||
options = $.extend({}, {
|
options = $.extend({}, {
|
||||||
reflHeight:0,
|
reflHeight:0,
|
||||||
reflOpacity:0.5,
|
reflOpacity:0.5,
|
||||||
reflGap:0,
|
reflGap:0,
|
||||||
minScale:0.5,
|
minScale:0.5,
|
||||||
xPos:0,
|
xPos:0,
|
||||||
yPos:0,
|
yPos:0,
|
||||||
xRadius:0,
|
xRadius:0,
|
||||||
yRadius:0,
|
yRadius:0,
|
||||||
altBox:null,
|
altBox:null,
|
||||||
titleBox:null,
|
titleBox:null,
|
||||||
FPS: 30,
|
FPS: 30,
|
||||||
autoRotate: 'no',
|
autoRotate: 'no',
|
||||||
autoRotateDelay: 1500,
|
autoRotateDelay: 1500,
|
||||||
speed:0.2,
|
speed:0.2,
|
||||||
mouseWheel: false,
|
mouseWheel: false,
|
||||||
bringToFront: false
|
bringToFront: false
|
||||||
},options );
|
},options );
|
||||||
// Create a Controller for each carousel.
|
// Create a Controller for each carousel.
|
||||||
$(this).data('cloudcarousel', new Controller( this, $('.cloudcarousel',$(this)), options) );
|
$(this).data('cloudcarousel', new Controller( this, $('.cloudcarousel',$(this)), options) );
|
||||||
});
|
});
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
})(jQuery);
|
})(jQuery);
|
1353
app/assets/javascripts/lib/howler.js
Normal file
|
@ -1,180 +1,180 @@
|
||||||
/**
|
/**
|
||||||
* jquery.purr.js
|
* jquery.purr.js
|
||||||
* Copyright (c) 2008 Net Perspective (net-perspective.com)
|
* Copyright (c) 2008 Net Perspective (net-perspective.com)
|
||||||
* Licensed under the MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* Licensed under the MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*
|
*
|
||||||
* @author R.A. Ray
|
* @author R.A. Ray
|
||||||
* @projectDescription jQuery plugin for dynamically displaying unobtrusive messages in the browser. Mimics the behavior of the MacOS program "Growl."
|
* @projectDescription jQuery plugin for dynamically displaying unobtrusive messages in the browser. Mimics the behavior of the MacOS program "Growl."
|
||||||
* @version 0.1.0
|
* @version 0.1.0
|
||||||
*
|
*
|
||||||
* @requires jquery.js (tested with 1.2.6)
|
* @requires jquery.js (tested with 1.2.6)
|
||||||
*
|
*
|
||||||
* @param fadeInSpeed int - Duration of fade in animation in miliseconds
|
* @param fadeInSpeed int - Duration of fade in animation in miliseconds
|
||||||
* default: 500
|
* default: 500
|
||||||
* @param fadeOutSpeed int - Duration of fade out animationin miliseconds
|
* @param fadeOutSpeed int - Duration of fade out animationin miliseconds
|
||||||
default: 500
|
default: 500
|
||||||
* @param removeTimer int - Timeout, in miliseconds, before notice is removed once it is the top non-sticky notice in the list
|
* @param removeTimer int - Timeout, in miliseconds, before notice is removed once it is the top non-sticky notice in the list
|
||||||
default: 4000
|
default: 4000
|
||||||
* @param isSticky bool - Whether the notice should fade out on its own or wait to be manually closed
|
* @param isSticky bool - Whether the notice should fade out on its own or wait to be manually closed
|
||||||
default: false
|
default: false
|
||||||
* @param usingTransparentPNG bool - Whether or not the notice is using transparent .png images in its styling
|
* @param usingTransparentPNG bool - Whether or not the notice is using transparent .png images in its styling
|
||||||
default: false
|
default: false
|
||||||
*/
|
*/
|
||||||
|
|
||||||
( function( $ ) {
|
( function( $ ) {
|
||||||
|
|
||||||
$.purr = function ( notice, options )
|
$.purr = function ( notice, options )
|
||||||
{
|
{
|
||||||
// Convert notice to a jQuery object
|
// Convert notice to a jQuery object
|
||||||
notice = $( notice );
|
notice = $( notice );
|
||||||
|
|
||||||
// Add a class to denote the notice as not sticky
|
// Add a class to denote the notice as not sticky
|
||||||
if ( !options.isSticky )
|
if ( !options.isSticky )
|
||||||
{
|
{
|
||||||
notice.addClass( 'not-sticky' );
|
notice.addClass( 'not-sticky' );
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the container element from the page
|
// Get the container element from the page
|
||||||
var cont = document.getElementById( 'purr-container' );
|
var cont = document.getElementById( 'purr-container' );
|
||||||
|
|
||||||
// If the container doesn't yet exist, we need to create it
|
// If the container doesn't yet exist, we need to create it
|
||||||
if ( !cont )
|
if ( !cont )
|
||||||
{
|
{
|
||||||
cont = '<div id="purr-container"></div>';
|
cont = '<div id="purr-container"></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert cont to a jQuery object
|
// Convert cont to a jQuery object
|
||||||
cont = $( cont );
|
cont = $( cont );
|
||||||
|
|
||||||
// Add the container to the page
|
// Add the container to the page
|
||||||
$( 'body' ).append( cont );
|
$( 'body' ).append( cont );
|
||||||
|
|
||||||
notify();
|
notify();
|
||||||
|
|
||||||
function notify ()
|
function notify ()
|
||||||
{
|
{
|
||||||
// Set up the close button
|
// Set up the close button
|
||||||
var close = document.createElement( 'a' );
|
var close = document.createElement( 'a' );
|
||||||
$( close ).attr(
|
$( close ).attr(
|
||||||
{
|
{
|
||||||
className: 'close',
|
className: 'close',
|
||||||
href: '#close',
|
href: '#close',
|
||||||
innerHTML: 'Close'
|
innerHTML: 'Close'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.appendTo( notice )
|
.appendTo( notice )
|
||||||
.click( function ()
|
.click( function ()
|
||||||
{
|
{
|
||||||
removeNotice();
|
removeNotice();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add the notice to the page and keep it hidden initially
|
// Add the notice to the page and keep it hidden initially
|
||||||
notice.appendTo( cont )
|
notice.appendTo( cont )
|
||||||
.hide();
|
.hide();
|
||||||
|
|
||||||
if ( jQuery.browser.msie && options.usingTransparentPNG )
|
if ( jQuery.browser.msie && options.usingTransparentPNG )
|
||||||
{
|
{
|
||||||
// IE7 and earlier can't handle the combination of opacity and transparent pngs, so if we're using transparent pngs in our
|
// IE7 and earlier can't handle the combination of opacity and transparent pngs, so if we're using transparent pngs in our
|
||||||
// notice style, we'll just skip the fading in.
|
// notice style, we'll just skip the fading in.
|
||||||
notice.show();
|
notice.show();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Fade in the notice we just added
|
//Fade in the notice we just added
|
||||||
notice.fadeIn( options.fadeInSpeed );
|
notice.fadeIn( options.fadeInSpeed );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the removal interval for the added notice if that notice is not a sticky
|
// Set up the removal interval for the added notice if that notice is not a sticky
|
||||||
if ( !options.isSticky )
|
if ( !options.isSticky )
|
||||||
{
|
{
|
||||||
var topSpotInt = setInterval( function ()
|
var topSpotInt = setInterval( function ()
|
||||||
{
|
{
|
||||||
// Check to see if our notice is the first non-sticky notice in the list
|
// Check to see if our notice is the first non-sticky notice in the list
|
||||||
if ( notice.prevAll( '.not-sticky' ).length == 0 )
|
if ( notice.prevAll( '.not-sticky' ).length == 0 )
|
||||||
{
|
{
|
||||||
// Stop checking once the condition is met
|
// Stop checking once the condition is met
|
||||||
clearInterval( topSpotInt );
|
clearInterval( topSpotInt );
|
||||||
|
|
||||||
// Call the close action after the timeout set in options
|
// Call the close action after the timeout set in options
|
||||||
setTimeout( function ()
|
setTimeout( function ()
|
||||||
{
|
{
|
||||||
removeNotice();
|
removeNotice();
|
||||||
}, options.removeTimer
|
}, options.removeTimer
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, 200 );
|
}, 200 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeNotice ()
|
function removeNotice ()
|
||||||
{
|
{
|
||||||
// IE7 and earlier can't handle the combination of opacity and transparent pngs, so if we're using transparent pngs in our
|
// IE7 and earlier can't handle the combination of opacity and transparent pngs, so if we're using transparent pngs in our
|
||||||
// notice style, we'll just skip the fading out.
|
// notice style, we'll just skip the fading out.
|
||||||
if ( jQuery.browser.msie && options.usingTransparentPNG )
|
if ( jQuery.browser.msie && options.usingTransparentPNG )
|
||||||
{
|
{
|
||||||
notice.css( { opacity: 0 } )
|
notice.css( { opacity: 0 } )
|
||||||
.animate(
|
.animate(
|
||||||
{
|
{
|
||||||
height: '0px'
|
height: '0px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
duration: options.fadeOutSpeed,
|
duration: options.fadeOutSpeed,
|
||||||
complete: function ()
|
complete: function ()
|
||||||
{
|
{
|
||||||
notice.remove();
|
notice.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Fade the object out before reducing its height to produce the sliding effect
|
// Fade the object out before reducing its height to produce the sliding effect
|
||||||
notice.animate(
|
notice.animate(
|
||||||
{
|
{
|
||||||
opacity: '0'
|
opacity: '0'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
duration: options.fadeOutSpeed,
|
duration: options.fadeOutSpeed,
|
||||||
complete: function ()
|
complete: function ()
|
||||||
{
|
{
|
||||||
notice.animate(
|
notice.animate(
|
||||||
{
|
{
|
||||||
height: '0px'
|
height: '0px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
duration: options.fadeOutSpeed,
|
duration: options.fadeOutSpeed,
|
||||||
complete: function ()
|
complete: function ()
|
||||||
{
|
{
|
||||||
notice.remove();
|
notice.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.purr = function ( options )
|
$.fn.purr = function ( options )
|
||||||
{
|
{
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.fadeInSpeed = options.fadeInSpeed || 500;
|
options.fadeInSpeed = options.fadeInSpeed || 500;
|
||||||
options.fadeOutSpeed = options.fadeOutSpeed || 500;
|
options.fadeOutSpeed = options.fadeOutSpeed || 500;
|
||||||
options.removeTimer = options.removeTimer || 4000;
|
options.removeTimer = options.removeTimer || 4000;
|
||||||
options.isSticky = options.isSticky || false;
|
options.isSticky = options.isSticky || false;
|
||||||
options.usingTransparentPNG = options.usingTransparentPNG || false;
|
options.usingTransparentPNG = options.usingTransparentPNG || false;
|
||||||
|
|
||||||
this.each( function()
|
this.each( function()
|
||||||
{
|
{
|
||||||
new $.purr( this, options );
|
new $.purr( this, options );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
})( jQuery );
|
})( jQuery );
|
||||||
|
|
||||||
|
|
9808
app/assets/javascripts/lib/simplewebrtc.bundle.js
Normal file
23
app/assets/javascripts/lib/socketIoConnection.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
function SocketIoConnection(config) {
|
||||||
|
this.connection = io.connect(config.url, config.socketio);
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketIoConnection.prototype.on = function (ev, fn) {
|
||||||
|
this.connection.on(ev, fn);
|
||||||
|
};
|
||||||
|
|
||||||
|
SocketIoConnection.prototype.emit = function () {
|
||||||
|
this.connection.emit.apply(this.connection, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
SocketIoConnection.prototype.removeAllListeners = function () {
|
||||||
|
this.connection.removeAllListeners();
|
||||||
|
};
|
||||||
|
|
||||||
|
SocketIoConnection.prototype.getSessionid = function () {
|
||||||
|
return this.connection.socket.sessionid;
|
||||||
|
};
|
||||||
|
|
||||||
|
SocketIoConnection.prototype.disconnect = function () {
|
||||||
|
return this.connection.disconnect();
|
||||||
|
};
|
|
@ -1,227 +1,247 @@
|
||||||
Metamaps.Backbone = {};
|
Metamaps.Backbone = {};
|
||||||
Metamaps.Backbone.Map = Backbone.Model.extend({
|
Metamaps.Backbone.Map = Backbone.Model.extend({
|
||||||
urlRoot: '/maps',
|
urlRoot: '/maps',
|
||||||
blacklist: ['created_at', 'updated_at', 'created_at_clean', 'updated_at_clean', 'user_name', 'contributor_count', 'topic_count', 'synapse_count', 'topics', 'synapses', 'mappings', 'mappers'],
|
blacklist: ['created_at', 'updated_at', 'created_at_clean', 'updated_at_clean', 'user_name', 'contributor_count', 'topic_count', 'synapse_count', 'topics', 'synapses', 'mappings', 'mappers'],
|
||||||
toJSON: function (options) {
|
toJSON: function (options) {
|
||||||
return _.omit(this.attributes, this.blacklist);
|
return _.omit(this.attributes, this.blacklist);
|
||||||
},
|
},
|
||||||
save: function (key, val, options) {
|
save: function (key, val, options) {
|
||||||
|
|
||||||
var attrs;
|
var attrs;
|
||||||
|
|
||||||
// Handle both `"key", value` and `{key: value}` -style arguments.
|
// Handle both `"key", value` and `{key: value}` -style arguments.
|
||||||
if (key == null || typeof key === 'object') {
|
if (key == null || typeof key === 'object') {
|
||||||
attrs = key;
|
attrs = key;
|
||||||
options = val;
|
options = val;
|
||||||
} else {
|
} else {
|
||||||
(attrs = {})[key] = val;
|
(attrs = {})[key] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
var newOptions = options || {};
|
var newOptions = options || {};
|
||||||
var s = newOptions.success;
|
var s = newOptions.success;
|
||||||
|
|
||||||
newOptions.success = function (model, response, opt) {
|
newOptions.success = function (model, response, opt) {
|
||||||
if (s) s(model, response, opt);
|
if (s) s(model, response, opt);
|
||||||
model.trigger('saved');
|
model.trigger('saved');
|
||||||
};
|
};
|
||||||
return Backbone.Model.prototype.save.call(this, attrs, newOptions);
|
return Backbone.Model.prototype.save.call(this, attrs, newOptions);
|
||||||
},
|
},
|
||||||
initialize: function () {
|
initialize: function () {
|
||||||
this.on('changeByOther', this.updateView);
|
this.on('changeByOther', this.updateView);
|
||||||
this.on('saved', this.savedEvent);
|
this.on('saved', this.savedEvent);
|
||||||
},
|
},
|
||||||
savedEvent: function() {
|
savedEvent: function() {
|
||||||
Metamaps.Realtime.sendMapChange(this);
|
Metamaps.Realtime.sendMapChange(this);
|
||||||
},
|
},
|
||||||
authorizeToEdit: function (mapper) {
|
authorizeToEdit: function (mapper) {
|
||||||
if (mapper && (this.get('permission') === "commons" || this.get('user_id') === mapper.get('id'))) return true;
|
if (mapper && (this.get('permission') === "commons" || this.get('user_id') === mapper.get('id'))) return true;
|
||||||
else return false;
|
else return false;
|
||||||
},
|
},
|
||||||
authorizePermissionChange: function (mapper) {
|
authorizePermissionChange: function (mapper) {
|
||||||
if (mapper && this.get('user_id') === mapper.get('id')) return true;
|
if (mapper && this.get('user_id') === mapper.get('id')) return true;
|
||||||
else return false;
|
else return false;
|
||||||
},
|
},
|
||||||
getUser: function () {
|
getUser: function () {
|
||||||
return Metamaps.Mapper.get(this.get('user_id'));
|
return Metamaps.Mapper.get(this.get('user_id'));
|
||||||
},
|
},
|
||||||
fetchContained: function () {
|
fetchContained: function () {
|
||||||
var bb = Metamaps.Backbone;
|
var bb = Metamaps.Backbone;
|
||||||
var that = this;
|
var that = this;
|
||||||
var start = function (data) {
|
var start = function (data) {
|
||||||
that.set('mappers', new bb.MapperCollection(data.mappers));
|
that.set('mappers', new bb.MapperCollection(data.mappers));
|
||||||
that.set('topics', new bb.TopicCollection(data.topics));
|
that.set('topics', new bb.TopicCollection(data.topics));
|
||||||
that.set('synapses', new bb.SynapseCollection(data.synapses));
|
that.set('synapses', new bb.SynapseCollection(data.synapses));
|
||||||
that.set('mappings', new bb.MappingCollection(data.mappings));
|
that.set('mappings', new bb.MappingCollection(data.mappings));
|
||||||
};
|
};
|
||||||
|
|
||||||
var e = $.ajax({
|
var e = $.ajax({
|
||||||
url: "/maps/" + this.id + "/contains.json",
|
url: "/maps/" + this.id + "/contains.json",
|
||||||
success: start,
|
success: start,
|
||||||
error: errorFunc,
|
error: errorFunc,
|
||||||
async: false
|
async: false
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getTopics: function () {
|
getTopics: function () {
|
||||||
if (!this.get('topics')) {
|
if (!this.get('topics')) {
|
||||||
this.fetchContained();
|
this.fetchContained();
|
||||||
}
|
}
|
||||||
return this.get('topics');
|
return this.get('topics');
|
||||||
},
|
},
|
||||||
getSynapses: function () {
|
getSynapses: function () {
|
||||||
if (!this.get('synapses')) {
|
if (!this.get('synapses')) {
|
||||||
this.fetchContained();
|
this.fetchContained();
|
||||||
}
|
}
|
||||||
return this.get('synapses');
|
return this.get('synapses');
|
||||||
},
|
},
|
||||||
getMappings: function () {
|
getMappings: function () {
|
||||||
if (!this.get('mappings')) {
|
if (!this.get('mappings')) {
|
||||||
this.fetchContained();
|
this.fetchContained();
|
||||||
}
|
}
|
||||||
return this.get('mappings');
|
return this.get('mappings');
|
||||||
},
|
},
|
||||||
getMappers: function () {
|
getMappers: function () {
|
||||||
if (!this.get('mappers')) {
|
if (!this.get('mappers')) {
|
||||||
this.fetchContained();
|
this.fetchContained();
|
||||||
}
|
}
|
||||||
return this.get('mappers');
|
return this.get('mappers');
|
||||||
},
|
},
|
||||||
attrForCards: function () {
|
attrForCards: function () {
|
||||||
function capitalize(string) {
|
function capitalize(string) {
|
||||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var n = this.get('name');
|
var n = this.get('name');
|
||||||
var d = this.get('desc');
|
var d = this.get('desc');
|
||||||
|
|
||||||
var maxNameLength = 32;
|
var maxNameLength = 32;
|
||||||
var maxDescLength = 118;
|
var maxDescLength = 118;
|
||||||
var truncatedName = n ? (n.length > maxNameLength ? n.substring(0, maxNameLength) + "..." : n) : "";
|
var truncatedName = n ? (n.length > maxNameLength ? n.substring(0, maxNameLength) + "..." : n) : "";
|
||||||
var truncatedDesc = d ? (d.length > maxDescLength ? d.substring(0, maxDescLength) + "..." : d) : "";
|
var truncatedDesc = d ? (d.length > maxDescLength ? d.substring(0, maxDescLength) + "..." : d) : "";
|
||||||
|
|
||||||
var obj = {
|
var obj = {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
name: truncatedName,
|
name: truncatedName,
|
||||||
fullName: n,
|
fullName: n,
|
||||||
desc: truncatedDesc,
|
desc: truncatedDesc,
|
||||||
permission: this.get("permission") ? capitalize(this.get("permission")) : "Commons",
|
permission: this.get("permission") ? capitalize(this.get("permission")) : "Commons",
|
||||||
editPermission: this.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEdit' : 'cannotEdit',
|
editPermission: this.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEdit' : 'cannotEdit',
|
||||||
contributor_count_number: '<span class="cCountColor">' + this.get('contributor_count') + '</span>',
|
contributor_count_number: '<span class="cCountColor">' + this.get('contributor_count') + '</span>',
|
||||||
contributor_count_string: this.get('contributor_count') == 1 ? ' contributor' : ' contributors',
|
contributor_count_string: this.get('contributor_count') == 1 ? ' contributor' : ' contributors',
|
||||||
topic_count_number: '<span class="tCountColor">' + this.get('topic_count') + '</span>',
|
topic_count_number: '<span class="tCountColor">' + this.get('topic_count') + '</span>',
|
||||||
topic_count_string: this.get('topic_count') == 1 ? ' topic' : ' topics',
|
topic_count_string: this.get('topic_count') == 1 ? ' topic' : ' topics',
|
||||||
synapse_count_number: '<span class="sCountColor">' + this.get('synapse_count') + '</span>',
|
synapse_count_number: '<span class="sCountColor">' + this.get('synapse_count') + '</span>',
|
||||||
synapse_count_string: this.get('synapse_count') == 1 ? ' synapse' : ' synapses',
|
synapse_count_string: this.get('synapse_count') == 1 ? ' synapse' : ' synapses',
|
||||||
screenshot: '<img src="' + this.get('screenshot_url') + '" />'
|
screenshot: '<img src="' + this.get('screenshot_url') + '" />'
|
||||||
};
|
};
|
||||||
return obj;
|
return obj;
|
||||||
},
|
},
|
||||||
updateView: function() {
|
updateView: function() {
|
||||||
var map = Metamaps.Active.Map;
|
var map = Metamaps.Active.Map;
|
||||||
var isActiveMap = this.id === map.id;
|
var isActiveMap = this.id === map.id;
|
||||||
var authorized = map && map.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEditMap' : '';
|
var authorized = map && map.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEditMap' : '';
|
||||||
var commonsMap = map && map.get('permission') === 'commons' ? 'commonsMap' : '';
|
var commonsMap = map && map.get('permission') === 'commons' ? 'commonsMap' : '';
|
||||||
if (isActiveMap) {
|
if (isActiveMap) {
|
||||||
Metamaps.Map.InfoBox.updateNameDescPerm(this.get('name'), this.get('desc'), this.get('permission'));
|
Metamaps.Map.InfoBox.updateNameDescPerm(this.get('name'), this.get('desc'), this.get('permission'));
|
||||||
this.updateMapWrapper();
|
this.updateMapWrapper();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateMapWrapper: function() {
|
updateMapWrapper: function() {
|
||||||
var map = Metamaps.Active.Map;
|
var map = Metamaps.Active.Map;
|
||||||
var isActiveMap = this.id === map.id;
|
var isActiveMap = this.id === map.id;
|
||||||
var authorized = map && map.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEditMap' : '';
|
var authorized = map && map.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEditMap' : '';
|
||||||
var commonsMap = map && map.get('permission') === 'commons' ? 'commonsMap' : '';
|
var commonsMap = map && map.get('permission') === 'commons' ? 'commonsMap' : '';
|
||||||
if (isActiveMap) {
|
if (isActiveMap) {
|
||||||
$('.wrapper').removeClass('canEditMap commonsMap').addClass(authorized + ' ' + commonsMap);
|
$('.wrapper').removeClass('canEditMap commonsMap').addClass(authorized + ' ' + commonsMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Metamaps.Backbone.MapsCollection = Backbone.Collection.extend({
|
Metamaps.Backbone.MapsCollection = Backbone.Collection.extend({
|
||||||
model: Metamaps.Backbone.Map,
|
model: Metamaps.Backbone.Map,
|
||||||
initialize: function(models, options) {
|
initialize: function(models, options) {
|
||||||
this.id = options.id;
|
this.id = options.id;
|
||||||
this.sortBy = options.sortBy;
|
this.sortBy = options.sortBy;
|
||||||
|
|
||||||
if (options.mapperId) {
|
if (options.mapperId) {
|
||||||
this.mapperId = options.mapperId;
|
this.mapperId = options.mapperId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.page represents the NEXT page to fetch
|
// this.page represents the NEXT page to fetch
|
||||||
this.page = models.length > 0 ? (models.length < 20 ? "loadedAll" : 2) : 1;
|
this.page = models.length > 0 ? (models.length < 20 ? "loadedAll" : 2) : 1;
|
||||||
},
|
},
|
||||||
url: function() {
|
url: function() {
|
||||||
if (!this.mapperId) {
|
if (!this.mapperId) {
|
||||||
return '/explore/' + this.id + '.json';
|
return '/explore/' + this.id + '.json';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return '/explore/mapper/' + this.mapperId + '.json';
|
return '/explore/mapper/' + this.mapperId + '.json';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
comparator: function (a, b) {
|
comparator: function (a, b) {
|
||||||
a = a.get(this.sortBy);
|
a = a.get(this.sortBy);
|
||||||
b = b.get(this.sortBy);
|
b = b.get(this.sortBy);
|
||||||
var temp;
|
var temp;
|
||||||
if (this.sortBy === 'name') {
|
if (this.sortBy === 'name') {
|
||||||
a = a ? a.toLowerCase() : "";
|
a = a ? a.toLowerCase() : "";
|
||||||
b = b ? b.toLowerCase() : "";
|
b = b ? b.toLowerCase() : "";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// this is for updated_at and created_at
|
// this is for updated_at and created_at
|
||||||
temp = a;
|
temp = a;
|
||||||
a = b;
|
a = b;
|
||||||
b = temp;
|
b = temp;
|
||||||
a = (new Date(a)).getTime();
|
a = (new Date(a)).getTime();
|
||||||
b = (new Date(b)).getTime();
|
b = (new Date(b)).getTime();
|
||||||
}
|
}
|
||||||
return a > b ? 1 : a < b ? -1 : 0;
|
return a > b ? 1 : a < b ? -1 : 0;
|
||||||
},
|
},
|
||||||
getMaps: function (cb) {
|
getMaps: function (cb) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
Metamaps.Loading.show();
|
Metamaps.Loading.show();
|
||||||
|
|
||||||
if (this.page != "loadedAll") {
|
if (this.page != "loadedAll") {
|
||||||
var numBefore = this.length;
|
var numBefore = this.length;
|
||||||
this.fetch({
|
this.fetch({
|
||||||
remove: false,
|
remove: false,
|
||||||
silent: true,
|
silent: true,
|
||||||
data: { page: this.page },
|
data: { page: this.page },
|
||||||
success: function (collection, response, options) {
|
success: function (collection, response, options) {
|
||||||
// you can pass additional options to the event you trigger here as well
|
// you can pass additional options to the event you trigger here as well
|
||||||
if (collection.length - numBefore < 20) {
|
if (collection.length - numBefore < 20) {
|
||||||
self.page = "loadedAll";
|
self.page = "loadedAll";
|
||||||
}
|
}
|
||||||
else self.page += 1;
|
else self.page += 1;
|
||||||
self.trigger('successOnFetch', cb);
|
self.trigger('successOnFetch', cb);
|
||||||
},
|
},
|
||||||
error: function (collection, response, options) {
|
error: function (collection, response, options) {
|
||||||
// you can pass additional options to the event you trigger here as well
|
// you can pass additional options to the event you trigger here as well
|
||||||
self.trigger('errorOnFetch');
|
self.trigger('errorOnFetch');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.trigger('successOnFetch', cb);
|
self.trigger('successOnFetch', cb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Metamaps.Backbone.Mapper = Backbone.Model.extend({
|
Metamaps.Backbone.Message = Backbone.Model.extend({
|
||||||
urlRoot: '/users',
|
urlRoot: '/messages',
|
||||||
blacklist: ['created_at', 'updated_at'],
|
blacklist: ['created_at', 'updated_at'],
|
||||||
toJSON: function (options) {
|
toJSON: function (options) {
|
||||||
return _.omit(this.attributes, this.blacklist);
|
return _.omit(this.attributes, this.blacklist);
|
||||||
},
|
},
|
||||||
prepareLiForFilter: function () {
|
prepareLiForFilter: function () {
|
||||||
var li = '';
|
/*var li = '';
|
||||||
li += '<li data-id="' + this.id.toString() + '">';
|
li += '<li data-id="' + this.id.toString() + '">';
|
||||||
li += '<img src="' + this.get("image") + '" data-id="' + this.id.toString() + '"';
|
li += '<img src="' + this.get("image") + '" data-id="' + this.id.toString() + '"';
|
||||||
li += ' alt="' + this.get('name') + '" />';
|
li += ' alt="' + this.get('name') + '" />';
|
||||||
li += '<p>' + this.get('name') + '</p></li>';
|
li += '<p>' + this.get('name') + '</p></li>';
|
||||||
return li;
|
return li;*/
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Metamaps.Backbone.MapperCollection = Backbone.Collection.extend({
|
Metamaps.Backbone.MessageCollection = Backbone.Collection.extend({
|
||||||
model: Metamaps.Backbone.Mapper,
|
model: Metamaps.Backbone.Message,
|
||||||
url: '/users'
|
url: '/messages'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Metamaps.Backbone.Mapper = Backbone.Model.extend({
|
||||||
|
urlRoot: '/users',
|
||||||
|
blacklist: ['created_at', 'updated_at'],
|
||||||
|
toJSON: function (options) {
|
||||||
|
return _.omit(this.attributes, this.blacklist);
|
||||||
|
},
|
||||||
|
prepareLiForFilter: function () {
|
||||||
|
var li = '';
|
||||||
|
li += '<li data-id="' + this.id.toString() + '">';
|
||||||
|
li += '<img src="' + this.get("image") + '" data-id="' + this.id.toString() + '"';
|
||||||
|
li += ' alt="' + this.get('name') + '" />';
|
||||||
|
li += '<p>' + this.get('name') + '</p></li>';
|
||||||
|
return li;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Metamaps.Backbone.MapperCollection = Backbone.Collection.extend({
|
||||||
|
model: Metamaps.Backbone.Mapper,
|
||||||
|
url: '/users'
|
||||||
|
});
|
||||||
|
|
327
app/assets/javascripts/src/Metamaps.Import.js.erb
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
/*
|
||||||
|
* Example tab-separated input:
|
||||||
|
* Some fields will be ignored
|
||||||
|
*
|
||||||
|
* Topics
|
||||||
|
* Id Name Metacode X Y Description Link User Permission
|
||||||
|
* 8 topic8 Action -231 131 admin commons
|
||||||
|
* 5 topic Action -229 -131 admin commons
|
||||||
|
* 7 topic7.1 Action -470 -55 hey admin commons
|
||||||
|
* 2 topic2 Event -57 -63 admin commons
|
||||||
|
* 1 topic1 Catalyst -51 50 admin commons
|
||||||
|
* 6 topic6 Action -425 63 admin commons
|
||||||
|
*
|
||||||
|
* Synapses
|
||||||
|
* Topic1 Topic2 Category Description User Permission
|
||||||
|
* 6 2 from-to admin commons
|
||||||
|
* 6 1 from-to admin commons
|
||||||
|
* 6 5 from-to admin commons
|
||||||
|
* 2 7 from-to admin commons
|
||||||
|
* 8 6 from-to admin commons
|
||||||
|
* 8 1 from-to admin commons
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
Metamaps.Import = {
|
||||||
|
// note that user is not imported
|
||||||
|
topicWhitelist: [
|
||||||
|
'id', 'name', 'metacode', 'x', 'y', 'description', 'link', 'permission'
|
||||||
|
],
|
||||||
|
synapseWhitelist: [
|
||||||
|
'topic1', 'topic2', 'category', 'desc', 'description', 'permission'
|
||||||
|
],
|
||||||
|
cidMappings: {}, //to be filled by import_id => cid mappings
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
var self = Metamaps.Import;
|
||||||
|
|
||||||
|
$('body').bind('paste', function(e) {
|
||||||
|
if (e.target.tagName === "INPUT") return;
|
||||||
|
|
||||||
|
var text = e.originalEvent.clipboardData.getData('text/plain');
|
||||||
|
|
||||||
|
var results;
|
||||||
|
if (text[0] === '{') {
|
||||||
|
try {
|
||||||
|
results = JSON.parse(text);
|
||||||
|
} catch (e) {
|
||||||
|
results = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
results = self.parseTabbedString(text);
|
||||||
|
}
|
||||||
|
if (results === false) return;
|
||||||
|
|
||||||
|
var topics = results.topics;
|
||||||
|
var synapses = results.synapses;
|
||||||
|
|
||||||
|
if (topics.length > 0 || synapses.length > 0) {
|
||||||
|
if (confirm("Are you sure you want to create " + topics.length +
|
||||||
|
" new topics and " + synapses.length + " new synapses?")) {
|
||||||
|
self.importTopics(topics);
|
||||||
|
self.importSynapses(synapses);
|
||||||
|
}//if
|
||||||
|
}//if
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
abort: function(message) {
|
||||||
|
console.error(message);
|
||||||
|
},
|
||||||
|
|
||||||
|
simplify: function(string) {
|
||||||
|
return string
|
||||||
|
.replace(/(^\s*|\s*$)/g, '')
|
||||||
|
.toLowerCase();
|
||||||
|
},
|
||||||
|
|
||||||
|
parseTabbedString: function(text) {
|
||||||
|
var self = Metamaps.Import;
|
||||||
|
|
||||||
|
// determine line ending and split lines
|
||||||
|
var delim = "\n";
|
||||||
|
if (text.indexOf("\r\n") !== -1) {
|
||||||
|
delim = "\r\n";
|
||||||
|
} else if (text.indexOf("\r") !== -1) {
|
||||||
|
delim = "\r";
|
||||||
|
}//if
|
||||||
|
|
||||||
|
var STATES = {
|
||||||
|
ABORT: -1,
|
||||||
|
UNKNOWN: 0,
|
||||||
|
TOPICS_NEED_HEADERS: 1,
|
||||||
|
SYNAPSES_NEED_HEADERS: 2,
|
||||||
|
TOPICS: 3,
|
||||||
|
SYNAPSES: 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
// state & lines determine parser behaviour
|
||||||
|
var state = STATES.UNKNOWN;
|
||||||
|
var lines = text.split(delim);
|
||||||
|
var results = { topics: [], synapses: [] }
|
||||||
|
var topicHeaders = [];
|
||||||
|
var synapseHeaders = [];
|
||||||
|
|
||||||
|
lines.forEach(function(line_raw, index) {
|
||||||
|
var line = line_raw.split("\t");
|
||||||
|
var noblanks = line.filter(function(elt) {
|
||||||
|
return elt !== "";
|
||||||
|
});
|
||||||
|
switch(state) {
|
||||||
|
case STATES.UNKNOWN:
|
||||||
|
if (noblanks.length === 0) {
|
||||||
|
state = STATES.UNKNOWN;
|
||||||
|
break;
|
||||||
|
} else if (noblanks.length === 1 && self.simplify(line[0]) === 'topics') {
|
||||||
|
state = STATES.TOPICS_NEED_HEADERS;
|
||||||
|
break;
|
||||||
|
} else if (noblanks.length === 1 && self.simplify(line[0]) === 'synapses') {
|
||||||
|
state = STATES.SYNAPSES_NEED_HEADERS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = STATES.TOPICS_NEED_HEADERS;
|
||||||
|
// FALL THROUGH - if we're not sure what to do, pretend
|
||||||
|
// we're on the TOPICS_NEED_HEADERS state and parse some headers
|
||||||
|
|
||||||
|
case STATES.TOPICS_NEED_HEADERS:
|
||||||
|
if (noblanks.length < 2) {
|
||||||
|
self.abort("Not enough topic headers on line " + index);
|
||||||
|
state = STATES.ABORT;
|
||||||
|
}
|
||||||
|
topicHeaders = line.map(function(header, index) {
|
||||||
|
return header.toLowerCase().replace('description', 'desc');
|
||||||
|
});
|
||||||
|
state = STATES.TOPICS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATES.SYNAPSES_NEED_HEADERS:
|
||||||
|
if (noblanks.length < 2) {
|
||||||
|
self.abort("Not enough synapse headers on line " + index);
|
||||||
|
state = STATES.ABORT;
|
||||||
|
}
|
||||||
|
synapseHeaders = line.map(function(header, index) {
|
||||||
|
return header.toLowerCase().replace('description', 'desc');
|
||||||
|
});
|
||||||
|
state = STATES.SYNAPSES;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATES.TOPICS:
|
||||||
|
if (noblanks.length === 0) {
|
||||||
|
state = STATES.UNKNOWN;
|
||||||
|
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') {
|
||||||
|
state = STATES.TOPICS_NEED_HEADERS;
|
||||||
|
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') {
|
||||||
|
state = STATES.SYNAPSES_NEED_HEADERS;
|
||||||
|
} else {
|
||||||
|
var topic = {};
|
||||||
|
line.forEach(function(field, index) {
|
||||||
|
var header = topicHeaders[index];
|
||||||
|
if (self.topicWhitelist.indexOf(header) === -1) return;
|
||||||
|
topic[header] = field;
|
||||||
|
if (['id', 'x', 'y'].indexOf(header) !== -1) {
|
||||||
|
topic[header] = parseInt(topic[header]);
|
||||||
|
}//if
|
||||||
|
});
|
||||||
|
results.topics.push(topic);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATES.SYNAPSES:
|
||||||
|
if (noblanks.length === 0) {
|
||||||
|
state = STATES.UNKNOWN;
|
||||||
|
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'topics') {
|
||||||
|
state = STATES.TOPICS_NEED_HEADERS;
|
||||||
|
} else if (noblanks.length === 1 && line[0].toLowerCase() === 'synapses') {
|
||||||
|
state = STATES.SYNAPSES_NEED_HEADERS;
|
||||||
|
} else {
|
||||||
|
var synapse = {};
|
||||||
|
line.forEach(function(field, index) {
|
||||||
|
var header = synapseHeaders[index];
|
||||||
|
if (self.synapseWhitelist.indexOf(header) === -1) return;
|
||||||
|
synapse[header] = field;
|
||||||
|
if (['id', 'topic1', 'topic2'].indexOf(header) !== -1) {
|
||||||
|
synapse[header] = parseInt(synapse[header]);
|
||||||
|
}//if
|
||||||
|
});
|
||||||
|
results.synapses.push(synapse);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATES.ABORT:
|
||||||
|
;
|
||||||
|
default:
|
||||||
|
self.abort("Invalid state while parsing import data. Check code.");
|
||||||
|
state = STATES.ABORT;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (state === STATES.ABORT) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
importTopics: function(parsedTopics) {
|
||||||
|
var self = Metamaps.Import;
|
||||||
|
|
||||||
|
// up to 25 topics: scale 100
|
||||||
|
// up to 81 topics: scale 200
|
||||||
|
// up to 169 topics: scale 300
|
||||||
|
var scale = Math.floor((Math.sqrt(parsedTopics.length) - 1) / 4) * 100;
|
||||||
|
if (scale < 100) scale = 100;
|
||||||
|
var autoX = -scale;
|
||||||
|
var autoY = -scale;
|
||||||
|
|
||||||
|
parsedTopics.forEach(function(topic) {
|
||||||
|
var x, y;
|
||||||
|
if (topic.x && topic.y) {
|
||||||
|
x = topic.x;
|
||||||
|
y = topic.y;
|
||||||
|
} else {
|
||||||
|
x = autoX;
|
||||||
|
y = autoY;
|
||||||
|
autoX += 50;
|
||||||
|
if (autoX > scale) {
|
||||||
|
autoY += 50;
|
||||||
|
autoX = -scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.createTopicWithParameters(
|
||||||
|
topic.name, topic.metacode, topic.permission,
|
||||||
|
topic.desc, topic.link, x, y, topic.id
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
importSynapses: function(parsedSynapses) {
|
||||||
|
var self = Metamaps.Import;
|
||||||
|
|
||||||
|
parsedSynapses.forEach(function(synapse) {
|
||||||
|
//only createSynapseWithParameters once both topics are persisted
|
||||||
|
var topic1 = Metamaps.Topics.get(self.cidMappings[node1_id]);
|
||||||
|
var topic2 = Metamaps.Topics.get(self.cidMappings[node2_id]);
|
||||||
|
var synapse_created = false
|
||||||
|
topic1.once('sync', function() {
|
||||||
|
if (topic1.id && topic2.id && !synapse_created) {
|
||||||
|
synaprse_created = true
|
||||||
|
self.createSynapseWithParameters(
|
||||||
|
synapse.desc, synapse.category, synapse.permission,
|
||||||
|
topic1, topic2
|
||||||
|
);
|
||||||
|
}//if
|
||||||
|
});
|
||||||
|
topic2.once('sync', function() {
|
||||||
|
if (topic1.id && topic2.id && !synapse_created) {
|
||||||
|
synaprse_created = true
|
||||||
|
self.createSynapseWithParameters(
|
||||||
|
synapse.desc, synapse.category, synapse.permission,
|
||||||
|
topic1, topic2
|
||||||
|
);
|
||||||
|
}//if
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
createTopicWithParameters: function(name, metacode_name, permission, desc,
|
||||||
|
link, xloc, yloc, import_id) {
|
||||||
|
var self = Metamaps.Import;
|
||||||
|
$(document).trigger(Metamaps.Map.events.editedByActiveMapper);
|
||||||
|
var metacode = Metamaps.Metacodes.where({name: metacode_name})[0] || null;
|
||||||
|
if (metacode === null) return console.error("metacode not found");
|
||||||
|
|
||||||
|
var topic = new Metamaps.Backbone.Topic({
|
||||||
|
name: name,
|
||||||
|
metacode_id: metacode.id,
|
||||||
|
permission: permission || Metamaps.Active.Map.get('permission'),
|
||||||
|
desc: desc,
|
||||||
|
link: link,
|
||||||
|
});
|
||||||
|
Metamaps.Topics.add(topic);
|
||||||
|
self.cidMappings[import_id] = topic.cid;
|
||||||
|
|
||||||
|
var mapping = new Metamaps.Backbone.Mapping({
|
||||||
|
xloc: xloc,
|
||||||
|
yloc: yloc,
|
||||||
|
mappable_id: topic.cid,
|
||||||
|
mappable_type: "Topic",
|
||||||
|
});
|
||||||
|
Metamaps.Mappings.add(mapping);
|
||||||
|
|
||||||
|
// this function also includes the creation of the topic in the database
|
||||||
|
Metamaps.Topic.renderTopic(mapping, topic, true, true);
|
||||||
|
|
||||||
|
|
||||||
|
Metamaps.Famous.viz.hideInstructions();
|
||||||
|
},
|
||||||
|
|
||||||
|
createSynapseWithParameters: function(description, category, permission,
|
||||||
|
topic1, topic2) {
|
||||||
|
var self = Metamaps.Import;
|
||||||
|
var node1 = topic1.get('node');
|
||||||
|
var node2 = topic2.get('node');
|
||||||
|
|
||||||
|
if (!topic1.id || !topic2.id) {
|
||||||
|
console.error("missing topic id when creating synapse")
|
||||||
|
return;
|
||||||
|
}//if
|
||||||
|
|
||||||
|
var synapse = new Metamaps.Backbone.Synapse({
|
||||||
|
desc: description,
|
||||||
|
category: category,
|
||||||
|
permission: permission,
|
||||||
|
node1_id: topic1.id,
|
||||||
|
node2_id: topic2.id
|
||||||
|
});
|
||||||
|
Metamaps.Synapses.add(synapse);
|
||||||
|
|
||||||
|
var mapping = new Metamaps.Backbone.Mapping({
|
||||||
|
mappable_type: "Synapse",
|
||||||
|
mappable_id: synapse.cid,
|
||||||
|
});
|
||||||
|
Metamaps.Mappings.add(mapping);
|
||||||
|
|
||||||
|
Metamaps.Synapse.renderSynapse(mapping, synapse, node1, node2, true);
|
||||||
|
},
|
||||||
|
};
|
|
@ -1,262 +1,262 @@
|
||||||
(function () {
|
(function () {
|
||||||
|
|
||||||
Metamaps.currentPage = "";
|
Metamaps.currentPage = "";
|
||||||
|
|
||||||
var Router = Backbone.Router.extend({
|
var Router = Backbone.Router.extend({
|
||||||
routes: {
|
routes: {
|
||||||
"": "home", // #home
|
"": "home", // #home
|
||||||
"explore/:section": "explore", // #explore/active
|
"explore/:section": "explore", // #explore/active
|
||||||
"explore/:section/:id": "explore", // #explore/mapper/1234
|
"explore/:section/:id": "explore", // #explore/mapper/1234
|
||||||
"maps/:id": "maps" // #maps/7
|
"maps/:id": "maps" // #maps/7
|
||||||
},
|
},
|
||||||
home: function () {
|
home: function () {
|
||||||
clearTimeout(Metamaps.routerTimeoutId);
|
clearTimeout(Metamaps.routerTimeoutId);
|
||||||
|
|
||||||
if (Metamaps.Active.Mapper) document.title = 'Explore Active Maps | Metamaps';
|
if (Metamaps.Active.Mapper) document.title = 'Explore Active Maps | Metamaps';
|
||||||
else document.title = 'Home | Metamaps';
|
else document.title = 'Home | Metamaps';
|
||||||
|
|
||||||
Metamaps.currentSection = "";
|
Metamaps.currentSection = "";
|
||||||
Metamaps.currentPage = "";
|
Metamaps.currentPage = "";
|
||||||
$('.wrapper').removeClass('mapPage topicPage');
|
$('.wrapper').removeClass('mapPage topicPage');
|
||||||
|
|
||||||
var classes = Metamaps.Active.Mapper ? "homePage explorePage" : "homePage";
|
var classes = Metamaps.Active.Mapper ? "homePage explorePage" : "homePage";
|
||||||
$('.wrapper').addClass(classes);
|
$('.wrapper').addClass(classes);
|
||||||
|
|
||||||
var navigate = function() {
|
var navigate = function() {
|
||||||
Metamaps.routerTimeoutId = setTimeout(function() {
|
Metamaps.routerTimeoutId = setTimeout(function() {
|
||||||
Metamaps.Router.navigate("");
|
Metamaps.Router.navigate("");
|
||||||
}, 300);
|
}, 300);
|
||||||
};
|
};
|
||||||
// all this only for the logged in home page
|
// all this only for the logged in home page
|
||||||
if (Metamaps.Active.Mapper) {
|
if (Metamaps.Active.Mapper) {
|
||||||
|
|
||||||
Metamaps.Famous.yield.hide();
|
Metamaps.Famous.yield.hide();
|
||||||
|
|
||||||
Metamaps.Famous.explore.set('active');
|
Metamaps.Famous.explore.set('active');
|
||||||
Metamaps.Famous.maps.resetScroll(); // sets the scroll back to the top
|
Metamaps.Famous.maps.resetScroll(); // sets the scroll back to the top
|
||||||
Metamaps.Famous.explore.show();
|
Metamaps.Famous.explore.show();
|
||||||
|
|
||||||
Metamaps.Famous.maps.show();
|
Metamaps.Famous.maps.show();
|
||||||
|
|
||||||
Metamaps.GlobalUI.Search.open();
|
Metamaps.GlobalUI.Search.open();
|
||||||
Metamaps.GlobalUI.Search.lock();
|
Metamaps.GlobalUI.Search.lock();
|
||||||
|
|
||||||
Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps.Active );
|
Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps.Active );
|
||||||
if (Metamaps.Maps.Active.length === 0) {
|
if (Metamaps.Maps.Active.length === 0) {
|
||||||
Metamaps.Maps.Active.getMaps(navigate); // this will trigger an explore maps render
|
Metamaps.Maps.Active.getMaps(navigate); // this will trigger an explore maps render
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Metamaps.Views.exploreMaps.render(navigate);
|
Metamaps.Views.exploreMaps.render(navigate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// logged out home page
|
// logged out home page
|
||||||
else {
|
else {
|
||||||
|
|
||||||
Metamaps.Famous.yield.show();
|
Metamaps.Famous.yield.show();
|
||||||
|
|
||||||
Metamaps.Famous.explore.hide();
|
Metamaps.Famous.explore.hide();
|
||||||
|
|
||||||
Metamaps.GlobalUI.Search.unlock();
|
Metamaps.GlobalUI.Search.unlock();
|
||||||
Metamaps.GlobalUI.Search.close(0, true);
|
Metamaps.GlobalUI.Search.close(0, true);
|
||||||
|
|
||||||
Metamaps.Famous.maps.hide();
|
Metamaps.Famous.maps.hide();
|
||||||
Metamaps.routerTimeoutId = setTimeout(navigate, 500);
|
Metamaps.routerTimeoutId = setTimeout(navigate, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
Metamaps.Famous.viz.hide();
|
Metamaps.Famous.viz.hide();
|
||||||
Metamaps.Map.end();
|
Metamaps.Map.end();
|
||||||
Metamaps.Topic.end();
|
Metamaps.Topic.end();
|
||||||
Metamaps.Active.Map = null;
|
Metamaps.Active.Map = null;
|
||||||
Metamaps.Active.Topic = null;
|
Metamaps.Active.Topic = null;
|
||||||
},
|
},
|
||||||
explore: function (section, id) {
|
explore: function (section, id) {
|
||||||
clearTimeout(Metamaps.routerTimeoutId);
|
clearTimeout(Metamaps.routerTimeoutId);
|
||||||
|
|
||||||
// just capitalize the variable section
|
// just capitalize the variable section
|
||||||
// either 'featured', 'mapper', or 'active'
|
// either 'featured', 'mapper', or 'active'
|
||||||
var capitalize = section.charAt(0).toUpperCase() + section.slice(1);
|
var capitalize = section.charAt(0).toUpperCase() + section.slice(1);
|
||||||
|
|
||||||
if (section === "featured" || section === "active") {
|
if (section === "featured" || section === "active") {
|
||||||
document.title = 'Explore ' + capitalize + ' Maps | Metamaps';
|
document.title = 'Explore ' + capitalize + ' Maps | Metamaps';
|
||||||
}
|
}
|
||||||
else if (section === "mapper") {
|
else if (section === "mapper") {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/users/" + id + ".json",
|
url: "/users/" + id + ".json",
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
document.title = response.name + ' | Metamaps';
|
document.title = response.name + ' | Metamaps';
|
||||||
},
|
},
|
||||||
error: function () {
|
error: function () {
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (section === "mine") {
|
else if (section === "mine") {
|
||||||
document.title = 'Explore My Maps | Metamaps';
|
document.title = 'Explore My Maps | Metamaps';
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.wrapper').removeClass('homePage mapPage topicPage');
|
$('.wrapper').removeClass('homePage mapPage topicPage');
|
||||||
$('.wrapper').addClass('explorePage');
|
$('.wrapper').addClass('explorePage');
|
||||||
|
|
||||||
Metamaps.currentSection = "explore";
|
Metamaps.currentSection = "explore";
|
||||||
Metamaps.currentPage = section;
|
Metamaps.currentPage = section;
|
||||||
|
|
||||||
// this will mean it's a mapper page being loaded
|
// this will mean it's a mapper page being loaded
|
||||||
if (id) {
|
if (id) {
|
||||||
if (Metamaps.Maps.Mapper.mapperId !== id) {
|
if (Metamaps.Maps.Mapper.mapperId !== id) {
|
||||||
// empty the collection if we are trying to load the maps
|
// empty the collection if we are trying to load the maps
|
||||||
// collection of a different mapper than we had previously
|
// collection of a different mapper than we had previously
|
||||||
Metamaps.Maps.Mapper.reset();
|
Metamaps.Maps.Mapper.reset();
|
||||||
Metamaps.Maps.Mapper.page = 1;
|
Metamaps.Maps.Mapper.page = 1;
|
||||||
}
|
}
|
||||||
Metamaps.Maps.Mapper.mapperId = id;
|
Metamaps.Maps.Mapper.mapperId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] );
|
Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] );
|
||||||
|
|
||||||
var navigate = function(){
|
var navigate = function(){
|
||||||
var path = "/explore/" + Metamaps.currentPage;
|
var path = "/explore/" + Metamaps.currentPage;
|
||||||
|
|
||||||
// alter url if for mapper profile page
|
// alter url if for mapper profile page
|
||||||
if (Metamaps.currentPage == "mapper") {
|
if (Metamaps.currentPage == "mapper") {
|
||||||
path += "/" + Metamaps.Maps.Mapper.mapperId;
|
path += "/" + Metamaps.Maps.Mapper.mapperId;
|
||||||
}
|
}
|
||||||
|
|
||||||
Metamaps.Router.navigate(path);
|
Metamaps.Router.navigate(path);
|
||||||
};
|
};
|
||||||
var navigateTimeout = function() {
|
var navigateTimeout = function() {
|
||||||
Metamaps.routerTimeoutId = setTimeout(navigate, 300);
|
Metamaps.routerTimeoutId = setTimeout(navigate, 300);
|
||||||
};
|
};
|
||||||
if (Metamaps.Maps[capitalize].length === 0) {
|
if (Metamaps.Maps[capitalize].length === 0) {
|
||||||
Metamaps.Loading.show();
|
Metamaps.Loading.show();
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
Metamaps.Maps[capitalize].getMaps(navigate); // this will trigger an explore maps render
|
Metamaps.Maps[capitalize].getMaps(navigate); // this will trigger an explore maps render
|
||||||
}, 300); // wait 300 milliseconds till the other animations are done to do the fetch
|
}, 300); // wait 300 milliseconds till the other animations are done to do the fetch
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (id) {
|
if (id) {
|
||||||
Metamaps.Views.exploreMaps.fetchUserThenRender(navigateTimeout);
|
Metamaps.Views.exploreMaps.fetchUserThenRender(navigateTimeout);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Metamaps.Views.exploreMaps.render(navigateTimeout);
|
Metamaps.Views.exploreMaps.render(navigateTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Metamaps.GlobalUI.Search.open();
|
Metamaps.GlobalUI.Search.open();
|
||||||
Metamaps.GlobalUI.Search.lock();
|
Metamaps.GlobalUI.Search.lock();
|
||||||
|
|
||||||
Metamaps.Famous.yield.hide();
|
Metamaps.Famous.yield.hide();
|
||||||
|
|
||||||
Metamaps.Famous.maps.resetScroll(); // sets the scroll back to the top
|
Metamaps.Famous.maps.resetScroll(); // sets the scroll back to the top
|
||||||
Metamaps.Famous.maps.show();
|
Metamaps.Famous.maps.show();
|
||||||
Metamaps.Famous.explore.set(section, id);
|
Metamaps.Famous.explore.set(section, id);
|
||||||
Metamaps.Famous.explore.show();
|
Metamaps.Famous.explore.show();
|
||||||
|
|
||||||
Metamaps.Famous.viz.hide();
|
Metamaps.Famous.viz.hide();
|
||||||
Metamaps.Map.end();
|
Metamaps.Map.end();
|
||||||
Metamaps.Topic.end();
|
Metamaps.Topic.end();
|
||||||
Metamaps.Active.Map = null;
|
Metamaps.Active.Map = null;
|
||||||
Metamaps.Active.Topic = null;
|
Metamaps.Active.Topic = null;
|
||||||
},
|
},
|
||||||
maps: function (id) {
|
maps: function (id) {
|
||||||
clearTimeout(Metamaps.routerTimeoutId);
|
clearTimeout(Metamaps.routerTimeoutId);
|
||||||
|
|
||||||
document.title = 'Map ' + id + ' | Metamaps';
|
document.title = 'Map ' + id + ' | Metamaps';
|
||||||
|
|
||||||
Metamaps.currentSection = "map";
|
Metamaps.currentSection = "map";
|
||||||
Metamaps.currentPage = id;
|
Metamaps.currentPage = id;
|
||||||
|
|
||||||
$('.wrapper').removeClass('homePage explorePage topicPage');
|
$('.wrapper').removeClass('homePage explorePage topicPage');
|
||||||
$('.wrapper').addClass('mapPage');
|
$('.wrapper').addClass('mapPage');
|
||||||
// another class will be added to wrapper if you
|
// another class will be added to wrapper if you
|
||||||
// can edit this map '.canEditMap'
|
// can edit this map '.canEditMap'
|
||||||
|
|
||||||
Metamaps.Famous.yield.hide();
|
Metamaps.Famous.yield.hide();
|
||||||
Metamaps.Famous.maps.hide();
|
Metamaps.Famous.maps.hide();
|
||||||
Metamaps.Famous.explore.hide();
|
Metamaps.Famous.explore.hide();
|
||||||
|
|
||||||
// clear the visualization, if there was one, before showing its div again
|
// clear the visualization, if there was one, before showing its div again
|
||||||
if (Metamaps.Visualize.mGraph) {
|
if (Metamaps.Visualize.mGraph) {
|
||||||
Metamaps.Visualize.mGraph.graph.empty();
|
Metamaps.Visualize.mGraph.graph.empty();
|
||||||
Metamaps.Visualize.mGraph.plot();
|
Metamaps.Visualize.mGraph.plot();
|
||||||
Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas);
|
Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas);
|
||||||
}
|
}
|
||||||
Metamaps.Famous.viz.show();
|
Metamaps.Famous.viz.show();
|
||||||
Metamaps.Topic.end();
|
Metamaps.Topic.end();
|
||||||
Metamaps.Active.Topic = null;
|
Metamaps.Active.Topic = null;
|
||||||
|
|
||||||
Metamaps.GlobalUI.Search.unlock();
|
Metamaps.GlobalUI.Search.unlock();
|
||||||
Metamaps.GlobalUI.Search.close(0, true);
|
Metamaps.GlobalUI.Search.close(0, true);
|
||||||
|
|
||||||
Metamaps.Loading.show();
|
Metamaps.Loading.show();
|
||||||
Metamaps.Map.end();
|
Metamaps.Map.end();
|
||||||
Metamaps.Map.launch(id);
|
Metamaps.Map.launch(id);
|
||||||
},
|
},
|
||||||
topics: function (id) {
|
topics: function (id) {
|
||||||
clearTimeout(Metamaps.routerTimeoutId);
|
clearTimeout(Metamaps.routerTimeoutId);
|
||||||
|
|
||||||
document.title = 'Topic ' + id + ' | Metamaps';
|
document.title = 'Topic ' + id + ' | Metamaps';
|
||||||
|
|
||||||
Metamaps.currentSection = "topic";
|
Metamaps.currentSection = "topic";
|
||||||
Metamaps.currentPage = id;
|
Metamaps.currentPage = id;
|
||||||
|
|
||||||
$('.wrapper').removeClass('homePage explorePage mapPage');
|
$('.wrapper').removeClass('homePage explorePage mapPage');
|
||||||
$('.wrapper').addClass('topicPage');
|
$('.wrapper').addClass('topicPage');
|
||||||
|
|
||||||
Metamaps.Famous.yield.hide();
|
Metamaps.Famous.yield.hide();
|
||||||
Metamaps.Famous.maps.hide();
|
Metamaps.Famous.maps.hide();
|
||||||
Metamaps.Famous.explore.hide();
|
Metamaps.Famous.explore.hide();
|
||||||
|
|
||||||
// clear the visualization, if there was one, before showing its div again
|
// clear the visualization, if there was one, before showing its div again
|
||||||
if (Metamaps.Visualize.mGraph) {
|
if (Metamaps.Visualize.mGraph) {
|
||||||
Metamaps.Visualize.mGraph.graph.empty();
|
Metamaps.Visualize.mGraph.graph.empty();
|
||||||
Metamaps.Visualize.mGraph.plot();
|
Metamaps.Visualize.mGraph.plot();
|
||||||
Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas);
|
Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas);
|
||||||
}
|
}
|
||||||
Metamaps.Famous.viz.show();
|
Metamaps.Famous.viz.show();
|
||||||
Metamaps.Map.end();
|
Metamaps.Map.end();
|
||||||
Metamaps.Active.Map = null;
|
Metamaps.Active.Map = null;
|
||||||
|
|
||||||
Metamaps.GlobalUI.Search.unlock();
|
Metamaps.GlobalUI.Search.unlock();
|
||||||
Metamaps.GlobalUI.Search.close(0, true);
|
Metamaps.GlobalUI.Search.close(0, true);
|
||||||
|
|
||||||
Metamaps.Topic.end();
|
Metamaps.Topic.end();
|
||||||
Metamaps.Topic.launch(id);
|
Metamaps.Topic.launch(id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Metamaps.Router = new Router();
|
Metamaps.Router = new Router();
|
||||||
|
|
||||||
|
|
||||||
Metamaps.Router.intercept = function (evt) {
|
Metamaps.Router.intercept = function (evt) {
|
||||||
var segments;
|
var segments;
|
||||||
|
|
||||||
var href = {
|
var href = {
|
||||||
prop: $(this).prop("href"),
|
prop: $(this).prop("href"),
|
||||||
attr: $(this).attr("href")
|
attr: $(this).attr("href")
|
||||||
};
|
};
|
||||||
var root = location.protocol + "//" + location.host + Backbone.history.options.root;
|
var root = location.protocol + "//" + location.host + Backbone.history.options.root;
|
||||||
|
|
||||||
if (href.prop && href.prop === root) href.attr = "";
|
if (href.prop && href.prop === root) href.attr = "";
|
||||||
|
|
||||||
if (href.prop && href.prop.slice(0, root.length) === root) {
|
if (href.prop && href.prop.slice(0, root.length) === root) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
|
||||||
segments = href.attr.split('/');
|
segments = href.attr.split('/');
|
||||||
segments.splice(0,1); // pop off the element created by the first /
|
segments.splice(0,1); // pop off the element created by the first /
|
||||||
|
|
||||||
if (href.attr === "") Metamaps.Router.home();
|
if (href.attr === "") Metamaps.Router.home();
|
||||||
else {
|
else {
|
||||||
Metamaps.Router[segments[0]](segments[1], segments[2]);
|
Metamaps.Router[segments[0]](segments[1], segments[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Metamaps.Router.init = function () {
|
Metamaps.Router.init = function () {
|
||||||
Backbone.history.start({
|
Backbone.history.start({
|
||||||
silent: true,
|
silent: true,
|
||||||
pushState: true,
|
pushState: true,
|
||||||
root: '/'
|
root: '/'
|
||||||
});
|
});
|
||||||
$(document).on("click", "a:not([data-bypass])", Metamaps.Router.intercept);
|
$(document).on("click", "a:not([data-bypass])", Metamaps.Router.intercept);
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1,133 +1,133 @@
|
||||||
(function () {
|
(function () {
|
||||||
Metamaps.Views = {};
|
Metamaps.Views = {};
|
||||||
|
|
||||||
var initialized = false;
|
var initialized = false;
|
||||||
|
|
||||||
Metamaps.Views.init = function () {
|
Metamaps.Views.init = function () {
|
||||||
|
|
||||||
Metamaps.Views.MapperCard = Backbone.View.extend({
|
Metamaps.Views.MapperCard = Backbone.View.extend({
|
||||||
|
|
||||||
template: Hogan.compile( $('#mapperCardTemplate').html() ),
|
template: Hogan.compile( $('#mapperCardTemplate').html() ),
|
||||||
|
|
||||||
tagNamea: "div",
|
tagNamea: "div",
|
||||||
|
|
||||||
className: "mapper",
|
className: "mapper",
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
this.$el.html( this.template.render(this.model) );
|
this.$el.html( this.template.render(this.model) );
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Metamaps.Views.MapCard = Backbone.View.extend({
|
Metamaps.Views.MapCard = Backbone.View.extend({
|
||||||
|
|
||||||
template: Hogan.compile( $('#mapCardTemplate').html() ),
|
template: Hogan.compile( $('#mapCardTemplate').html() ),
|
||||||
|
|
||||||
tagName: "div",
|
tagName: "div",
|
||||||
|
|
||||||
className: "map",
|
className: "map",
|
||||||
|
|
||||||
id: function() {
|
id: function() {
|
||||||
return this.model.id;
|
return this.model.id;
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function () {
|
initialize: function () {
|
||||||
this.listenTo(this.model, "change", this.render);
|
this.listenTo(this.model, "change", this.render);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
this.$el.html( this.template.render(this.model.attrForCards()) );
|
this.$el.html( this.template.render(this.model.attrForCards()) );
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var mapsWrapper = Backbone.View.extend({
|
var mapsWrapper = Backbone.View.extend({
|
||||||
|
|
||||||
initialize: function (opts) {
|
initialize: function (opts) {
|
||||||
|
|
||||||
},
|
},
|
||||||
setCollection: function (collection) {
|
setCollection: function (collection) {
|
||||||
if (this.collection) this.stopListening(this.collection);
|
if (this.collection) this.stopListening(this.collection);
|
||||||
this.collection = collection;
|
this.collection = collection;
|
||||||
this.listenTo(this.collection, 'add', this.render);
|
this.listenTo(this.collection, 'add', this.render);
|
||||||
this.listenTo(this.collection, 'successOnFetch', this.handleSuccess);
|
this.listenTo(this.collection, 'successOnFetch', this.handleSuccess);
|
||||||
this.listenTo(this.collection, 'errorOnFetch', this.handleError);
|
this.listenTo(this.collection, 'errorOnFetch', this.handleError);
|
||||||
},
|
},
|
||||||
render: function (mapperObj, cb) {
|
render: function (mapperObj, cb) {
|
||||||
|
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
if (typeof mapperObj === "function") {
|
if (typeof mapperObj === "function") {
|
||||||
var cb = mapperObj;
|
var cb = mapperObj;
|
||||||
mapperObj = null;
|
mapperObj = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.el.innerHTML = "";
|
this.el.innerHTML = "";
|
||||||
|
|
||||||
// in case it is a page where we have to display the mapper card
|
// in case it is a page where we have to display the mapper card
|
||||||
if (mapperObj) {
|
if (mapperObj) {
|
||||||
var view = new Metamaps.Views.MapperCard({ model: mapperObj });
|
var view = new Metamaps.Views.MapperCard({ model: mapperObj });
|
||||||
|
|
||||||
that.el.appendChild( view.render().el );
|
that.el.appendChild( view.render().el );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.collection.each(function (map) {
|
this.collection.each(function (map) {
|
||||||
var view = new Metamaps.Views.MapCard({ model: map });
|
var view = new Metamaps.Views.MapCard({ model: map });
|
||||||
|
|
||||||
that.el.appendChild( view.render().el );
|
that.el.appendChild( view.render().el );
|
||||||
});
|
});
|
||||||
this.$el.append('<div class="clearfloat"></div>');
|
this.$el.append('<div class="clearfloat"></div>');
|
||||||
var m = Metamaps.Famous.maps.surf;
|
var m = Metamaps.Famous.maps.surf;
|
||||||
m.setContent(this.el);
|
m.setContent(this.el);
|
||||||
|
|
||||||
var updateHeight = function(){
|
var updateHeight = function(){
|
||||||
var height = $(that.el).height() + 32 + 56;
|
var height = $(that.el).height() + 32 + 56;
|
||||||
m.setSize([undefined, height]);
|
m.setSize([undefined, height]);
|
||||||
Metamaps.Famous.maps.lock = false;
|
Metamaps.Famous.maps.lock = false;
|
||||||
if (cb) cb();
|
if (cb) cb();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
m.deploy(m._currTarget);
|
m.deploy(m._currTarget);
|
||||||
initialized = true;
|
initialized = true;
|
||||||
setTimeout(updateHeight, 100);
|
setTimeout(updateHeight, 100);
|
||||||
} else {
|
} else {
|
||||||
setTimeout(updateHeight, 100);
|
setTimeout(updateHeight, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
Metamaps.Loading.hide();
|
Metamaps.Loading.hide();
|
||||||
},
|
},
|
||||||
handleSuccess: function (cb) {
|
handleSuccess: function (cb) {
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
if (this.collection && this.collection.id === "mapper") {
|
if (this.collection && this.collection.id === "mapper") {
|
||||||
this.fetchUserThenRender(cb);
|
this.fetchUserThenRender(cb);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.render(cb);
|
this.render(cb);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleError: function () {
|
handleError: function () {
|
||||||
console.log('error loading maps!'); //TODO
|
console.log('error loading maps!'); //TODO
|
||||||
},
|
},
|
||||||
fetchUserThenRender: function (cb) {
|
fetchUserThenRender: function (cb) {
|
||||||
var that = this;
|
var that = this;
|
||||||
// first load the mapper object and then call the render function
|
// first load the mapper object and then call the render function
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/users/" + this.collection.mapperId + "/details.json",
|
url: "/users/" + this.collection.mapperId + "/details.json",
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
that.render(response, cb);
|
that.render(response, cb);
|
||||||
},
|
},
|
||||||
error: function () {
|
error: function () {
|
||||||
that.render(cb);
|
that.render(cb);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Metamaps.Views.exploreMaps = new mapsWrapper();
|
Metamaps.Views.exploreMaps = new mapsWrapper();
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
339
app/assets/javascripts/src/views/chatView.js.erb
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
Metamaps.Views = Metamaps.Views || {};
|
||||||
|
|
||||||
|
Metamaps.Views.chatView = (function () {
|
||||||
|
var
|
||||||
|
chatView,
|
||||||
|
linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false, twitter: false });
|
||||||
|
|
||||||
|
var Private = {
|
||||||
|
messageHTML: "<div class='chat-message'>" +
|
||||||
|
"<div class='chat-message-user'><img src='{{ user_image }}' title='{{user_name }}'/></div>" +
|
||||||
|
"<div class='chat-message-text'>{{ message }}</div>" +
|
||||||
|
"<div class='chat-message-time'>{{ timestamp }}</div>" +
|
||||||
|
"<div class='clearfloat'></div>" +
|
||||||
|
"</div>",
|
||||||
|
participantHTML: "<div class='participant participant-{{ id }} {{ selfClass }}'>" +
|
||||||
|
"<div class='chat-participant-image'><img src='{{ image }}' style='border: 2px solid {{ color }};' /></div>" +
|
||||||
|
"<div class='chat-participant-name'>{{ username }} {{ selfName }}</div>" +
|
||||||
|
"<button type='button' class='button chat-participant-invite-call' onclick='Metamaps.Realtime.inviteACall({{ id}});'></button>" +
|
||||||
|
"<button type='button' class='button chat-participant-invite-join' onclick='Metamaps.Realtime.inviteToJoin({{ id}});'></button>" +
|
||||||
|
"<span class='chat-participant-participating'><div class='green-dot'></div></span>" +
|
||||||
|
"<div class='clearfloat'></div>" +
|
||||||
|
"</div>",
|
||||||
|
templates: function() {
|
||||||
|
_.templateSettings = {
|
||||||
|
interpolate: /\{\{(.+?)\}\}/g
|
||||||
|
};
|
||||||
|
this.messageTemplate = _.template(Private.messageHTML);
|
||||||
|
|
||||||
|
this.participantTemplate = _.template(Private.participantHTML);
|
||||||
|
},
|
||||||
|
createElements: function() {
|
||||||
|
this.$unread = $('<div class="chat-unread"></div>');
|
||||||
|
this.$button = $('<div class="chat-button"><div class="tooltips">Chat</div></div>');
|
||||||
|
this.$messageInput = $('<textarea placeholder="Send a message..." class="chat-input"></textarea>');
|
||||||
|
this.$juntoHeader = $('<div class="junto-header">PARTICIPANTS</div>');
|
||||||
|
this.$videoToggle = $('<div class="video-toggle"></div>');
|
||||||
|
this.$cursorToggle = $('<div class="cursor-toggle"></div>');
|
||||||
|
this.$participants = $('<div class="participants"></div>');
|
||||||
|
this.$conversationInProgress = $('<div class="conversation-live">LIVE <span class="call-action leave" onclick="Metamaps.Realtime.leaveCall();">LEAVE</span><span class="call-action join" onclick="Metamaps.Realtime.joinCall();">JOIN</span></div>');
|
||||||
|
this.$chatHeader = $('<div class="chat-header">CHAT</div>');
|
||||||
|
this.$soundToggle = $('<div class="sound-toggle active"></div>');
|
||||||
|
this.$messages = $('<div class="chat-messages"></div>');
|
||||||
|
this.$container = $('<div class="chat-box"></div>');
|
||||||
|
},
|
||||||
|
attachElements: function() {
|
||||||
|
this.$button.append(this.$unread);
|
||||||
|
|
||||||
|
this.$juntoHeader.append(this.$videoToggle);
|
||||||
|
this.$juntoHeader.append(this.$cursorToggle);
|
||||||
|
|
||||||
|
this.$chatHeader.append(this.$soundToggle);
|
||||||
|
|
||||||
|
this.$participants.append(this.$conversationInProgress);
|
||||||
|
|
||||||
|
this.$container.append(this.$juntoHeader);
|
||||||
|
this.$container.append(this.$participants);
|
||||||
|
this.$container.append(this.$chatHeader);
|
||||||
|
this.$container.append(this.$button);
|
||||||
|
this.$container.append(this.$messages);
|
||||||
|
this.$container.append(this.$messageInput);
|
||||||
|
},
|
||||||
|
addEventListeners: function() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.participants.on('add', function (participant) {
|
||||||
|
Private.addParticipant.call(self, participant);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.participants.on('remove', function (participant) {
|
||||||
|
Private.removeParticipant.call(self, participant);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$button.on('click', function () {
|
||||||
|
Handlers.buttonClick.call(self);
|
||||||
|
});
|
||||||
|
this.$videoToggle.on('click', function () {
|
||||||
|
Handlers.videoToggleClick.call(self);
|
||||||
|
});
|
||||||
|
this.$cursorToggle.on('click', function () {
|
||||||
|
Handlers.cursorToggleClick.call(self);
|
||||||
|
});
|
||||||
|
this.$soundToggle.on('click', function () {
|
||||||
|
Handlers.soundToggleClick.call(self);
|
||||||
|
});
|
||||||
|
this.$messageInput.on('keyup', function (event) {
|
||||||
|
Handlers.keyUp.call(self, event);
|
||||||
|
});
|
||||||
|
this.$messageInput.on('focus', function () {
|
||||||
|
Handlers.inputFocus.call(self);
|
||||||
|
});
|
||||||
|
this.$messageInput.on('blur', function () {
|
||||||
|
Handlers.inputBlur.call(self);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
initializeSounds: function() {
|
||||||
|
this.sound = new Howl({
|
||||||
|
urls: ["<%= asset_path 'sounds/sounds.mp3' %>", "<%= asset_path 'sounds/sounds.ogg' %>"],
|
||||||
|
sprite: {
|
||||||
|
laser: [3000, 700]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
incrementUnread: function() {
|
||||||
|
this.unreadMessages++;
|
||||||
|
this.$unread.html(this.unreadMessages);
|
||||||
|
this.$unread.show();
|
||||||
|
},
|
||||||
|
addMessage: function(message, isInitial) {
|
||||||
|
|
||||||
|
if (!this.isOpen && !isInitial) Private.incrementUnread.call(this);
|
||||||
|
|
||||||
|
function addZero(i) {
|
||||||
|
if (i < 10) {
|
||||||
|
i = "0" + i;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
var m = _.clone(message.attributes);
|
||||||
|
|
||||||
|
var today = new Date();
|
||||||
|
m.timestamp = new Date(m.created_at);
|
||||||
|
|
||||||
|
var date = (m.timestamp.getMonth() + 1) + '/' + m.timestamp.getDate();
|
||||||
|
date += " " + addZero(m.timestamp.getHours()) + ":" + addZero(m.timestamp.getMinutes());
|
||||||
|
m.timestamp = date;
|
||||||
|
m.image = m.user_image || 'http://www.hotpepper.ca/wp-content/uploads/2014/11/default_profile_1_200x200.png'; // TODO: remove
|
||||||
|
m.message = linker.link(m.message);
|
||||||
|
var $html = $(this.messageTemplate(m));
|
||||||
|
this.$messages.append($html);
|
||||||
|
if (!isInitial) this.scrollMessages(200);
|
||||||
|
|
||||||
|
if (!isInitial && this.alertSound) this.sound.play('laser');
|
||||||
|
},
|
||||||
|
initialMessages: function() {
|
||||||
|
var messages = this.messages.models;
|
||||||
|
for (var i = 0; i < messages.length; i++) {
|
||||||
|
Private.addMessage.call(this, messages[i], true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleInputMessage: function() {
|
||||||
|
var message = {
|
||||||
|
message: this.$messageInput.val(),
|
||||||
|
};
|
||||||
|
this.$messageInput.val('');
|
||||||
|
$(document).trigger(chatView.events.message + '-' + this.room, [message]);
|
||||||
|
},
|
||||||
|
addParticipant: function(participant) {
|
||||||
|
var p = _.clone(participant.attributes);
|
||||||
|
if (p.self) {
|
||||||
|
p.selfClass = 'is-self';
|
||||||
|
p.selfName = '(me)';
|
||||||
|
} else {
|
||||||
|
p.selfClass = '';
|
||||||
|
p.selfName = '';
|
||||||
|
}
|
||||||
|
var html = this.participantTemplate(p);
|
||||||
|
this.$participants.append(html);
|
||||||
|
},
|
||||||
|
removeParticipant: function(participant) {
|
||||||
|
this.$container.find('.participant-' + participant.get('id')).remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var Handlers = {
|
||||||
|
buttonClick: function() {
|
||||||
|
if (this.isOpen) this.close();
|
||||||
|
else if (!this.isOpen) this.open();
|
||||||
|
},
|
||||||
|
videoToggleClick: function() {
|
||||||
|
this.$videoToggle.toggleClass('active');
|
||||||
|
this.videosShowing = !this.videosShowing;
|
||||||
|
$(document).trigger(this.videosShowing ? chatView.events.videosOn : chatView.events.videosOff);
|
||||||
|
},
|
||||||
|
cursorToggleClick: function() {
|
||||||
|
this.$cursorToggle.toggleClass('active');
|
||||||
|
this.cursorsShowing = !this.cursorsShowing;
|
||||||
|
$(document).trigger(this.cursorsShowing ? chatView.events.cursorsOn : chatView.events.cursorsOff);
|
||||||
|
},
|
||||||
|
soundToggleClick: function() {
|
||||||
|
this.alertSound = !this.alertSound;
|
||||||
|
this.$soundToggle.toggleClass('active');
|
||||||
|
},
|
||||||
|
keyUp: function(event) {
|
||||||
|
switch(event.which) {
|
||||||
|
case 13: // enter
|
||||||
|
Private.handleInputMessage.call(this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inputFocus: function() {
|
||||||
|
$(document).trigger(chatView.events.inputFocus);
|
||||||
|
},
|
||||||
|
inputBlur: function() {
|
||||||
|
$(document).trigger(chatView.events.inputBlur);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
chatView = function(messages, mapper, room) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.room = room;
|
||||||
|
this.mapper = mapper;
|
||||||
|
this.messages = messages; // backbone collection
|
||||||
|
|
||||||
|
this.isOpen = false;
|
||||||
|
this.alertSound = false; // whether to play sounds on arrival of new messages or not
|
||||||
|
this.cursorsShowing = true;
|
||||||
|
this.videosShowing = true;
|
||||||
|
this.unreadMessages = 0;
|
||||||
|
this.participants = new Backbone.Collection();
|
||||||
|
|
||||||
|
Private.templates.call(this);
|
||||||
|
Private.createElements.call(this);
|
||||||
|
Private.attachElements.call(this);
|
||||||
|
Private.addEventListeners.call(this);
|
||||||
|
Private.initialMessages.call(this);
|
||||||
|
Private.initializeSounds.call(this);
|
||||||
|
this.$container.css({
|
||||||
|
right: '-300px'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
chatView.prototype.conversationInProgress = function (participating) {
|
||||||
|
this.$conversationInProgress.show();
|
||||||
|
this.$participants.addClass('is-live');
|
||||||
|
if (participating) this.$participants.addClass('is-participating');
|
||||||
|
this.$button.addClass('active');
|
||||||
|
|
||||||
|
// hide invite to call buttons
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.conversationEnded = function () {
|
||||||
|
this.$conversationInProgress.hide();
|
||||||
|
this.$participants.removeClass('is-live');
|
||||||
|
this.$participants.removeClass('is-participating');
|
||||||
|
this.$button.removeClass('active');
|
||||||
|
this.$participants.find('.participant').removeClass('active');
|
||||||
|
this.$participants.find('.participant').removeClass('pending');
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.leaveConversation = function () {
|
||||||
|
this.$participants.removeClass('is-participating');
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.mapperJoinedCall = function (id) {
|
||||||
|
this.$participants.find('.participant-' + id).addClass('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.mapperLeftCall = function (id) {
|
||||||
|
this.$participants.find('.participant-' + id).removeClass('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.invitationPending = function (id) {
|
||||||
|
this.$participants.find('.participant-' + id).addClass('pending');
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.invitationAnswered = function (id) {
|
||||||
|
this.$participants.find('.participant-' + id).removeClass('pending');
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.addParticipant = function (participant) {
|
||||||
|
this.participants.add(participant);
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.removeParticipant = function (username) {
|
||||||
|
var p = this.participants.find(function (p) { return p.get('username') === username; });
|
||||||
|
if (p) {
|
||||||
|
this.participants.remove(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.removeParticipants = function () {
|
||||||
|
this.participants.remove(this.participants.models);
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.open = function () {
|
||||||
|
this.$container.css({
|
||||||
|
right: '0'
|
||||||
|
});
|
||||||
|
this.$messageInput.focus();
|
||||||
|
this.isOpen = true;
|
||||||
|
this.unreadMessages = 0;
|
||||||
|
this.$unread.hide();
|
||||||
|
this.scrollMessages(0);
|
||||||
|
$(document).trigger(chatView.events.openTray);
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.addMessage = function(message, isInitial) {
|
||||||
|
this.messages.add(message);
|
||||||
|
Private.addMessage.call(this, message, isInitial);
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.scrollMessages = function(duration) {
|
||||||
|
duration = duration || 0;
|
||||||
|
|
||||||
|
this.$messages.animate({
|
||||||
|
scrollTop: this.$messages[0].scrollHeight
|
||||||
|
}, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.clearMessages = function () {
|
||||||
|
this.unreadMessages = 0;
|
||||||
|
this.$unread.hide();
|
||||||
|
this.$messages.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.close = function () {
|
||||||
|
this.$container.css({
|
||||||
|
right: '-300px'
|
||||||
|
});
|
||||||
|
this.$messageInput.blur();
|
||||||
|
this.isOpen = false;
|
||||||
|
$(document).trigger(chatView.events.closeTray);
|
||||||
|
}
|
||||||
|
|
||||||
|
chatView.prototype.remove = function () {
|
||||||
|
this.$button.off();
|
||||||
|
this.$container.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
chatView.events = {
|
||||||
|
message: 'ChatView:message',
|
||||||
|
openTray: 'ChatView:openTray',
|
||||||
|
closeTray: 'ChatView:closeTray',
|
||||||
|
inputFocus: 'ChatView:inputFocus',
|
||||||
|
inputBlur: 'ChatView:inputBlur',
|
||||||
|
cursorsOff: 'ChatView:cursorsOff',
|
||||||
|
cursorsOn: 'ChatView:cursorsOn',
|
||||||
|
videosOff: 'ChatView:videosOff',
|
||||||
|
videosOn: 'ChatView:videosOn'
|
||||||
|
};
|
||||||
|
|
||||||
|
return chatView;
|
||||||
|
|
||||||
|
})();
|
194
app/assets/javascripts/src/views/room.js
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
Metamaps.Views = Metamaps.Views || {};
|
||||||
|
|
||||||
|
Metamaps.Views.room = (function () {
|
||||||
|
|
||||||
|
var ChatView = Metamaps.Views.chatView;
|
||||||
|
var VideoView = Metamaps.Views.videoView;
|
||||||
|
|
||||||
|
var room = function(opts) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.isActiveRoom = false;
|
||||||
|
this.socket = opts.socket;
|
||||||
|
this.webrtc = opts.webrtc;
|
||||||
|
//this.roomRef = opts.firebase;
|
||||||
|
this.room = opts.room;
|
||||||
|
this.config = opts.config;
|
||||||
|
this.peopleCount = 0;
|
||||||
|
|
||||||
|
this.$myVideo = opts.$video;
|
||||||
|
this.myVideo = opts.myVideoView;
|
||||||
|
|
||||||
|
this.messages = new Backbone.Collection();
|
||||||
|
this.currentMapper = new Backbone.Model({ name: opts.username, image: opts.image });
|
||||||
|
this.chat = new ChatView(this.messages, this.currentMapper, this.room);
|
||||||
|
|
||||||
|
this.videos = {};
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
};
|
||||||
|
|
||||||
|
room.prototype.join = function(cb) {
|
||||||
|
this.isActiveRoom = true;
|
||||||
|
this.webrtc.joinRoom(this.room, cb);
|
||||||
|
this.chat.conversationInProgress(true); // true indicates participation
|
||||||
|
}
|
||||||
|
|
||||||
|
room.prototype.conversationInProgress = function() {
|
||||||
|
this.chat.conversationInProgress(false); // false indicates not participating
|
||||||
|
}
|
||||||
|
|
||||||
|
room.prototype.conversationEnding = function() {
|
||||||
|
this.chat.conversationEnded();
|
||||||
|
}
|
||||||
|
|
||||||
|
room.prototype.leaveVideoOnly = function() {
|
||||||
|
this.chat.leaveConversation(); // the conversation will carry on without you
|
||||||
|
for (var id in this.videos) {
|
||||||
|
this.removeVideo(id);
|
||||||
|
}
|
||||||
|
this.isActiveRoom = false;
|
||||||
|
this.webrtc.leaveRoom();
|
||||||
|
}
|
||||||
|
|
||||||
|
room.prototype.leave = function() {
|
||||||
|
for (var id in this.videos) {
|
||||||
|
this.removeVideo(id);
|
||||||
|
}
|
||||||
|
this.isActiveRoom = false;
|
||||||
|
this.webrtc.leaveRoom();
|
||||||
|
this.chat.conversationEnded();
|
||||||
|
this.chat.removeParticipants();
|
||||||
|
this.chat.clearMessages();
|
||||||
|
this.messages.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
room.prototype.setPeopleCount = function(count) {
|
||||||
|
this.peopleCount = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
room.prototype.init = function () {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
$(document).on(VideoView.events.audioControlClick, function (event, videoView) {
|
||||||
|
if (!videoView.audioStatus) self.webrtc.mute();
|
||||||
|
else if (videoView.audioStatus) self.webrtc.unmute();
|
||||||
|
});
|
||||||
|
$(document).on(VideoView.events.videoControlClick, function (event, videoView) {
|
||||||
|
if (!videoView.videoStatus) self.webrtc.pauseVideo();
|
||||||
|
else if (videoView.videoStatus) self.webrtc.resumeVideo();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.webrtc.webrtc.off('peerStreamAdded');
|
||||||
|
this.webrtc.webrtc.off('peerStreamRemoved');
|
||||||
|
this.webrtc.on('peerStreamAdded', function (peer) {
|
||||||
|
var mapper = Metamaps.Realtime.mappersOnMap[peer.nick];
|
||||||
|
peer.avatar = mapper.image;
|
||||||
|
peer.username = mapper.name;
|
||||||
|
if (self.isActiveRoom) {
|
||||||
|
self.addVideo(peer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.webrtc.on('peerStreamRemoved', function (peer) {
|
||||||
|
if (self.isActiveRoom) {
|
||||||
|
self.removeVideo(peer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.webrtc.on('mute', function (data) {
|
||||||
|
var v = self.videos[data.id];
|
||||||
|
if (!v) return;
|
||||||
|
|
||||||
|
if (data.name === 'audio') {
|
||||||
|
v.audioStatus = false;
|
||||||
|
}
|
||||||
|
else if (data.name === 'video') {
|
||||||
|
v.videoStatus = false;
|
||||||
|
v.$avatar.show();
|
||||||
|
}
|
||||||
|
if (!v.audioStatus && !v.videoStatus) v.$container.hide();
|
||||||
|
});
|
||||||
|
this.webrtc.on('unmute', function (data) {
|
||||||
|
var v = self.videos[data.id];
|
||||||
|
if (!v) return;
|
||||||
|
|
||||||
|
if (data.name === 'audio') {
|
||||||
|
v.audioStatus = true;
|
||||||
|
}
|
||||||
|
else if (data.name === 'video') {
|
||||||
|
v.videoStatus = true;
|
||||||
|
v.$avatar.hide();
|
||||||
|
}
|
||||||
|
v.$container.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
var sendChatMessage = function (event, data) {
|
||||||
|
self.sendChatMessage(data);
|
||||||
|
};
|
||||||
|
$(document).on(ChatView.events.message + '-' + this.room, sendChatMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
room.prototype.videoAdded = function (callback) {
|
||||||
|
this._videoAdded = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
room.prototype.addVideo = function (peer) {
|
||||||
|
var
|
||||||
|
id = this.webrtc.getDomId(peer),
|
||||||
|
video = attachMediaStream(peer.stream);
|
||||||
|
|
||||||
|
var
|
||||||
|
v = new VideoView(video, null, id, false, { DOUBLE_CLICK_TOLERANCE: 200, avatar: peer.avatar, username: peer.username });
|
||||||
|
|
||||||
|
this.videos[peer.id] = v;
|
||||||
|
if (this._videoAdded) this._videoAdded(v, peer.nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
room.prototype.removeVideo = function (peer) {
|
||||||
|
var id = typeof peer == 'string' ? peer : peer.id;
|
||||||
|
if (this.videos[id]) {
|
||||||
|
this.videos[id].remove();
|
||||||
|
delete this.videos[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
room.prototype.sendChatMessage = function (data) {
|
||||||
|
var self = this;
|
||||||
|
//this.roomRef.child('messages').push(data);
|
||||||
|
var m = new Metamaps.Backbone.Message({
|
||||||
|
message: data.message,
|
||||||
|
resource_id: Metamaps.Active.Map.id,
|
||||||
|
resource_type: "Map"
|
||||||
|
});
|
||||||
|
m.save(null, {
|
||||||
|
success: function (model, response) {
|
||||||
|
self.addMessages(new Metamaps.Backbone.MessageCollection(model));
|
||||||
|
$(document).trigger(room.events.newMessage, [model]);
|
||||||
|
},
|
||||||
|
error: function (model, response) {
|
||||||
|
console.log('error!', response);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// they should be instantiated as backbone models before they get
|
||||||
|
// passed to this function
|
||||||
|
room.prototype.addMessages = function (messages, isInitial) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
messages.models.forEach(function (message) {
|
||||||
|
self.chat.addMessage(message, isInitial);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
room.events = {
|
||||||
|
newMessage: "Room:newMessage"
|
||||||
|
};
|
||||||
|
|
||||||
|
return room;
|
||||||
|
})();
|
207
app/assets/javascripts/src/views/videoView.js
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
Metamaps.Views = Metamaps.Views || {};
|
||||||
|
|
||||||
|
Metamaps.Views.videoView = (function () {
|
||||||
|
|
||||||
|
var videoView;
|
||||||
|
|
||||||
|
var Private = {
|
||||||
|
addControls: function() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.$audioControl = $('<div class="video-audio"></div>');
|
||||||
|
this.$videoControl = $('<div class="video-video"></div>');
|
||||||
|
|
||||||
|
this.$audioControl.on('click', function () {
|
||||||
|
Handlers.audioControlClick.call(self);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$videoControl.on('click', function () {
|
||||||
|
Handlers.videoControlClick.call(self);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$container.append(this.$audioControl);
|
||||||
|
this.$container.append(this.$videoControl);
|
||||||
|
},
|
||||||
|
cancelClick: function() {
|
||||||
|
this.mouseIsDown = false;
|
||||||
|
|
||||||
|
if (this.hasMoved) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).trigger(videoView.events.dragEnd);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var Handlers = {
|
||||||
|
mousedown: function(event) {
|
||||||
|
this.mouseIsDown = true;
|
||||||
|
this.hasMoved = false;
|
||||||
|
this.mouseMoveStart = {
|
||||||
|
x: event.pageX,
|
||||||
|
y: event.pageY
|
||||||
|
};
|
||||||
|
this.posStart = {
|
||||||
|
x: parseInt(this.$container.css('left'), '10'),
|
||||||
|
y: parseInt(this.$container.css('top'), '10')
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).trigger(videoView.events.mousedown);
|
||||||
|
},
|
||||||
|
mouseup: function(event) {
|
||||||
|
$(document).trigger(videoView.events.mouseup, [this]);
|
||||||
|
|
||||||
|
var storedTime = this.lastClick;
|
||||||
|
var now = Date.now();
|
||||||
|
this.lastClick = now;
|
||||||
|
|
||||||
|
if (now - storedTime < this.config.DOUBLE_CLICK_TOLERANCE) {
|
||||||
|
$(document).trigger(videoView.events.doubleClick, [this]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mousemove: function(event) {
|
||||||
|
var
|
||||||
|
diffX,
|
||||||
|
diffY,
|
||||||
|
newX,
|
||||||
|
newY;
|
||||||
|
|
||||||
|
if (this.$parent && this.mouseIsDown) {
|
||||||
|
this.manuallyPositioned = true;
|
||||||
|
this.hasMoved = true;
|
||||||
|
diffX = event.pageX - this.mouseMoveStart.x;
|
||||||
|
diffY = this.mouseMoveStart.y - event.pageY;
|
||||||
|
newX = this.posStart.x + diffX;
|
||||||
|
newY = this.posStart.y - diffY;
|
||||||
|
this.$container.css({
|
||||||
|
top: newY,
|
||||||
|
left: newX
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
audioControlClick: function() {
|
||||||
|
if (this.audioStatus) {
|
||||||
|
this.audioOff();
|
||||||
|
} else {
|
||||||
|
this.audioOn();
|
||||||
|
}
|
||||||
|
$(document).trigger(videoView.events.audioControlClick, [this]);
|
||||||
|
},
|
||||||
|
videoControlClick: function() {
|
||||||
|
if (this.videoStatus) {
|
||||||
|
this.videoOff();
|
||||||
|
} else {
|
||||||
|
this.videoOn();
|
||||||
|
}
|
||||||
|
$(document).trigger(videoView.events.videoControlClick, [this]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var videoView = function(video, $parent, id, isMyself, config) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.$parent = $parent; // mapView
|
||||||
|
|
||||||
|
this.video = video;
|
||||||
|
this.id = id;
|
||||||
|
|
||||||
|
this.config = config;
|
||||||
|
|
||||||
|
this.mouseIsDown = false;
|
||||||
|
this.mouseDownOffset = { x: 0, y: 0 };
|
||||||
|
this.lastClick = null;
|
||||||
|
this.hasMoved = false;
|
||||||
|
|
||||||
|
this.audioStatus = true;
|
||||||
|
this.videoStatus = true;
|
||||||
|
|
||||||
|
this.$container = $('<div></div>');
|
||||||
|
this.$container.addClass('collaborator-video' + (isMyself ? ' my-video' : ''));
|
||||||
|
this.$container.attr('id', 'container_' + id);
|
||||||
|
|
||||||
|
|
||||||
|
var $vidContainer = $('<div></div>');
|
||||||
|
$vidContainer.addClass('video-cutoff');
|
||||||
|
$vidContainer.append(this.video);
|
||||||
|
|
||||||
|
this.avatar = config.avatar;
|
||||||
|
this.$avatar = $('<img draggable="false" class="collaborator-video-avatar" src="' + config.avatar + '" width="150" height="150" />');
|
||||||
|
$vidContainer.append(this.$avatar);
|
||||||
|
|
||||||
|
this.$container.append($vidContainer);
|
||||||
|
|
||||||
|
this.$container.on('mousedown', function (event) {
|
||||||
|
Handlers.mousedown.call(self, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isMyself) {
|
||||||
|
Private.addControls.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// suppress contextmenu
|
||||||
|
this.video.oncontextmenu = function () { return false; };
|
||||||
|
|
||||||
|
if (this.$parent) this.setParent(this.$parent);
|
||||||
|
};
|
||||||
|
|
||||||
|
videoView.prototype.setParent = function($parent) {
|
||||||
|
var self = this;
|
||||||
|
this.$parent = $parent;
|
||||||
|
this.$parent.off('.video' + this.id);
|
||||||
|
this.$parent.on('mouseup.video' + this.id, function (event) {
|
||||||
|
Handlers.mouseup.call(self, event);
|
||||||
|
Private.cancelClick.call(self);
|
||||||
|
});
|
||||||
|
this.$parent.on('mousemove.video' + this.id, function (event) {
|
||||||
|
Handlers.mousemove.call(self, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
videoView.prototype.setAvatar = function (src) {
|
||||||
|
this.$avatar.attr('src', src);
|
||||||
|
this.avatar = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
videoView.prototype.remove = function () {
|
||||||
|
this.$container.off();
|
||||||
|
if (this.$parent) this.$parent.off('.video' + this.id);
|
||||||
|
this.$container.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
videoView.prototype.videoOff = function () {
|
||||||
|
this.$videoControl.addClass('active');
|
||||||
|
this.$avatar.show();
|
||||||
|
this.videoStatus = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
videoView.prototype.videoOn = function () {
|
||||||
|
this.$videoControl.removeClass('active');
|
||||||
|
this.$avatar.hide();
|
||||||
|
this.videoStatus = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
videoView.prototype.audioOff = function () {
|
||||||
|
this.$audioControl.addClass('active');
|
||||||
|
this.audioStatus = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
videoView.prototype.audioOn = function () {
|
||||||
|
this.$audioControl.removeClass('active');
|
||||||
|
this.audioStatus = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
videoView.events = {
|
||||||
|
mousedown: "VideoView:mousedown",
|
||||||
|
mouseup: "VideoView:mouseup",
|
||||||
|
doubleClick: "VideoView:doubleClick",
|
||||||
|
dragEnd: "VideoView:dragEnd",
|
||||||
|
audioControlClick: "VideoView:audioControlClick",
|
||||||
|
videoControlClick: "VideoView:videoControlClick",
|
||||||
|
};
|
||||||
|
|
||||||
|
return videoView;
|
||||||
|
})();
|
|
@ -1,63 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
.allMetacodes {
|
|
||||||
float:left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.allMetacodes span {
|
|
||||||
margin:4px 8px;
|
|
||||||
color:#67AF9F;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editMetacodes {
|
|
||||||
z-index:12;
|
|
||||||
width:auto;
|
|
||||||
color: #67AF9F;
|
|
||||||
padding:10px;
|
|
||||||
float:left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editMetacodes ul {
|
|
||||||
display:block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editMetacodes ul li {
|
|
||||||
clear:both;
|
|
||||||
list-style-type:none;
|
|
||||||
display:block;
|
|
||||||
padding:3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editMetacodes ul img {
|
|
||||||
width:40px;
|
|
||||||
height:40px;
|
|
||||||
float:left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editMetacodes ul p {
|
|
||||||
float:left;
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
background: none;
|
|
||||||
padding: 10px 4px 2px 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editMetacodes #filters-one {
|
|
||||||
float:left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editMetacodes #filters-two {
|
|
||||||
float:left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editMetacodes #filters-three {
|
|
||||||
float:left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editMetacodes #filters-four {
|
|
||||||
float:left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editMetacodes li.toggledOff {
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
188
app/assets/stylesheets/admin.scss.erb
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
.allMetacodes {
|
||||||
|
float:left;
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin:4px 8px;
|
||||||
|
color:#67AF9F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.editMetacodes {
|
||||||
|
z-index:12;
|
||||||
|
width:auto;
|
||||||
|
color: #67AF9F;
|
||||||
|
padding:10px;
|
||||||
|
float:left;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul li {
|
||||||
|
clear:both;
|
||||||
|
list-style-type:none;
|
||||||
|
display:block;
|
||||||
|
padding:3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul img {
|
||||||
|
width:40px;
|
||||||
|
height:40px;
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul p {
|
||||||
|
float:left;
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
background: none;
|
||||||
|
padding: 10px 4px 2px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filters-one {
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filters-two {
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filters-three {
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filters-four {
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.toggledOff {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.blackBox {
|
||||||
|
width: 760px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px 0 60px 20px;
|
||||||
|
background: rgba(0, 0, 0, 0.4);
|
||||||
|
color: white;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.metacodeSetsDescription {
|
||||||
|
width: 314px;
|
||||||
|
}
|
||||||
|
td.metacodeSetDesc {
|
||||||
|
width: 314px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
.metacodeSetImage {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
tr {
|
||||||
|
display: table-row;
|
||||||
|
}
|
||||||
|
tr:nth-child(odd) {
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
td.iconURL {
|
||||||
|
max-width: 415px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
.field {
|
||||||
|
margin: 15px 0 5px;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
float: left;
|
||||||
|
width: 100px;
|
||||||
|
margin-right: 15px;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
input[type="text"] {
|
||||||
|
width: 336px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 15px;
|
||||||
|
direction: ltr;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 8px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-top: 1px solid #c0c0c0;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
-webkit-border-radius: 1px;
|
||||||
|
-moz-border-radius: 1px;
|
||||||
|
border-radius: 1px;
|
||||||
|
font: -webkit-small-control;
|
||||||
|
color: initial;
|
||||||
|
letter-spacing: normal;
|
||||||
|
word-spacing: normal;
|
||||||
|
text-transform: none;
|
||||||
|
text-indent: 0px;
|
||||||
|
text-shadow: none;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: start;
|
||||||
|
font-family: arial;
|
||||||
|
}
|
||||||
|
textarea:hover,
|
||||||
|
input[type="text"]:hover {
|
||||||
|
border: 1px solid #b9b9b9;
|
||||||
|
border-top: 1px solid #a0a0a0;
|
||||||
|
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
-moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-top: 1px solid #c0c0c0;
|
||||||
|
resize: none;
|
||||||
|
font: -webkit-small-control;
|
||||||
|
letter-spacing: normal;
|
||||||
|
word-spacing: normal;
|
||||||
|
text-transform: none;
|
||||||
|
text-indent: 0px;
|
||||||
|
text-shadow: none;
|
||||||
|
text-align: start;
|
||||||
|
font-family: arial;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 17px;
|
||||||
|
width: 318px;
|
||||||
|
}
|
||||||
|
.allMetacodes {
|
||||||
|
padding: 5px 0;
|
||||||
|
}
|
||||||
|
a.button {
|
||||||
|
margin-right: 20px;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
a.button,
|
||||||
|
input.add {
|
||||||
|
float: left;
|
||||||
|
margin-top: 5px;
|
||||||
|
height: 40px;
|
||||||
|
font-size: 17px;
|
||||||
|
width: auto;
|
||||||
|
padding: 0 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
a.button:hover,
|
||||||
|
input.add:hover {
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
131
app/assets/stylesheets/apps.css.erb
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
.centerContent {
|
||||||
|
position: relative;
|
||||||
|
margin: 92px auto 0 auto;
|
||||||
|
padding: 20px 0 60px 20px;
|
||||||
|
width: 760px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24);
|
||||||
|
background: #fff;
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
-moz-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #dcdcdc;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent .page-header {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid #DCDCDC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent .form-group {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent .inline-button {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent.showApp p {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent a {
|
||||||
|
color: #4fb5c0;
|
||||||
|
}
|
||||||
|
.centerContent a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent a.button {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent a.button:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent th {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent td {
|
||||||
|
padding-right: 20px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent .link-button {
|
||||||
|
line-height: 32px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent .button-margin {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent .button-margin-top {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent a.red-button, .centerContent button.red-button,
|
||||||
|
.centerContent input[type="submit"].red-button {
|
||||||
|
color: #c04f4f;
|
||||||
|
background: transparent;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
.centerContent .red-button:hover {
|
||||||
|
background: transparent;
|
||||||
|
color: #9A3E3E !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent input[type="text"] {
|
||||||
|
font-family: 'din-medium', helvetica, sans-serif;
|
||||||
|
width: 400px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 14px;
|
||||||
|
direction: ltr;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 8px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-top: 1px solid #c0c0c0;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
-webkit-border-radius: 1px;
|
||||||
|
-moz-border-radius: 1px;
|
||||||
|
border-radius: 2px;
|
||||||
|
color: #424242;
|
||||||
|
letter-spacing: normal;
|
||||||
|
word-spacing: normal;
|
||||||
|
text-transform: none;
|
||||||
|
text-indent: 0px;
|
||||||
|
text-shadow: none;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centerContent textarea {
|
||||||
|
color: #424242;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-top: 1px solid #c0c0c0;
|
||||||
|
resize: none;
|
||||||
|
letter-spacing: normal;
|
||||||
|
word-spacing: normal;
|
||||||
|
text-transform: none;
|
||||||
|
text-indent: 0px;
|
||||||
|
text-shadow: none;
|
||||||
|
text-align: start;
|
||||||
|
font-family: 'din-medium', helvetica, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 17px;
|
||||||
|
width: 400px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
|
@ -25,7 +25,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#famousOverlay {
|
#famousOverlay {
|
||||||
position:fixed;
|
position:absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
|
|
||||||
/* upperLeftUI */
|
/* upperLeftUI */
|
||||||
.upperLeftUI {
|
.upperLeftUI {
|
||||||
position: fixed;
|
position: absolute;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
left: 24px;
|
left: 24px;
|
||||||
z-index:3;
|
z-index:3;
|
||||||
|
@ -155,7 +155,7 @@
|
||||||
/* upperRightUI */
|
/* upperRightUI */
|
||||||
|
|
||||||
.upperRightUI {
|
.upperRightUI {
|
||||||
position: fixed;
|
position: absolute;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
right: 24px;
|
right: 24px;
|
||||||
z-index:4;
|
z-index:4;
|
||||||
|
@ -166,9 +166,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.upperRightBox {
|
.upperRightBox {
|
||||||
position: fixed;
|
position: absolute;
|
||||||
top:52px;
|
top:42px;
|
||||||
right:24px;
|
right:0;
|
||||||
background-color: #E0E0E0;
|
background-color: #E0E0E0;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
box-shadow: 0 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
|
box-shadow: 0 3px 3px rgba(0,0,0,0.23), 0 3px 3px rgba(0,0,0,0.16);
|
||||||
|
@ -187,17 +187,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.upperRightMapButtons {
|
.upperRightMapButtons {
|
||||||
position: relative;
|
|
||||||
top: -42px; /* puts it just offscreen */
|
top: -42px; /* puts it just offscreen */
|
||||||
}
|
}
|
||||||
.mapPage .upperRightMapButtons, .topicPage .upperRightMapButtons {
|
.mapPage .upperRightMapButtons, .topicPage .upperRightMapButtons {
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topicPage .sidebarCollaborate {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upperRightIcon {
|
.upperRightIcon {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
@ -205,20 +200,6 @@
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.sidebarCollaborateIcon {
|
|
||||||
background-position: 0 0;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.sidebarCollaborateIcon.blue {
|
|
||||||
background-position: -32px 0;
|
|
||||||
}
|
|
||||||
.sidebarCollaborateIcon.blue:hover {
|
|
||||||
background-position: -32px -32px;
|
|
||||||
}
|
|
||||||
/* only show the collaborate icon on commons */
|
|
||||||
.commonsMap .sidebarCollaborateIcon {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.sidebarFilterIcon {
|
.sidebarFilterIcon {
|
||||||
background-position: -64px 0;
|
background-position: -64px 0;
|
||||||
}
|
}
|
||||||
|
@ -384,7 +365,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.infoAndHelp {
|
.infoAndHelp {
|
||||||
position: fixed;
|
position: absolute;
|
||||||
bottom: 20px;
|
bottom: 20px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
|
@ -424,14 +405,14 @@
|
||||||
/* mapControls */
|
/* mapControls */
|
||||||
|
|
||||||
.mapControls {
|
.mapControls {
|
||||||
position: fixed;
|
position: absolute;
|
||||||
bottom: 24px;
|
bottom: 24px;
|
||||||
right:-32px; /* puts it just offscreen */
|
right:-32px; /* puts it just offscreen */
|
||||||
width:32px;
|
width:32px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
.mapPage .mapControls, .topicPage .mapControls {
|
.mapPage .mapControls, .topicPage .mapControls {
|
||||||
right: 24px;
|
right: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topicPage .zoomExtents {
|
.topicPage .zoomExtents {
|
||||||
|
@ -474,14 +455,13 @@
|
||||||
background-position: -32px 0;
|
background-position: -32px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zoomExtents:hover .tooltips, .zoomIn:hover .tooltips, .zoomOut:hover .tooltips, .takeScreenshot:hover .tooltips, .sidebarCollaborateIcon:hover .tooltipsUnder,
|
.zoomExtents:hover .tooltips, .zoomIn:hover .tooltips, .zoomOut:hover .tooltips, .takeScreenshot:hover .tooltips, .sidebarFilterIcon:hover .tooltipsUnder, .sidebarForkIcon:hover .tooltipsUnder, .addMap:hover .tooltipsUnder, .authenticated .sidebarAccountIcon:hover .tooltipsUnder,
|
||||||
.sidebarFilterIcon:hover .tooltipsUnder, .sidebarForkIcon:hover .tooltipsUnder, .addMap:hover .tooltipsUnder, .authenticated .sidebarAccountIcon:hover .tooltipsUnder,
|
.mapInfoIcon:hover .tooltipsAbove, .openCheatsheet:hover .tooltipsAbove, .chat-button:hover .tooltips {
|
||||||
.mapInfoIcon:hover .tooltipsAbove, .openCheatsheet:hover .tooltipsAbove {
|
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hide {
|
.hide {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltips {
|
.tooltips {
|
||||||
|
@ -532,10 +512,6 @@
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebarCollaborateIcon .tooltipsUnder {
|
|
||||||
margin-left: -3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebarFilterIcon .tooltipsUnder {
|
.sidebarFilterIcon .tooltipsUnder {
|
||||||
margin-left: -4px;
|
margin-left: -4px;
|
||||||
}
|
}
|
||||||
|
@ -560,16 +536,20 @@
|
||||||
left: -11px;
|
left: -11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-button .tooltips {
|
||||||
|
top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.openCheatsheet .tooltipsAbove {
|
.openCheatsheet .tooltipsAbove {
|
||||||
left: -4px;
|
left: -4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebarAccountIcon .tooltipsUnder {
|
.sidebarAccountIcon .tooltipsUnder {
|
||||||
margin-left: -8px;
|
margin-left: -12px;
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zoomExtents div::after, .zoomIn div::after, .zoomOut div::after, .takeScreenshot div:after {
|
.zoomExtents div::after, .zoomIn div::after, .zoomOut div::after, .takeScreenshot div:after, .chat-button div.tooltips::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 57%;
|
top: 57%;
|
||||||
|
@ -582,21 +562,20 @@
|
||||||
border-bottom: 5px solid transparent;
|
border-bottom: 5px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebarCollaborateIcon div:after, .sidebarFilterIcon div:after, .sidebarAccountIcon .tooltipsUnder:after {
|
.sidebarFilterIcon div:after, .sidebarForkIcon div:after, .addMap div:after, .sidebarAccountIcon .tooltipsUnder:after {
|
||||||
left: 38%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebarCollaborateIcon div:after, .sidebarFilterIcon div:after, .sidebarForkIcon div:after, .addMap div:after, .sidebarAccountIcon .tooltipsUnder:after {
|
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 129%;
|
right: 40%;
|
||||||
margin-top: -30px;
|
margin-top: -7px;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
border-bottom: 4px solid #000000;
|
border-bottom: 4px solid #000000;
|
||||||
border-left: 5px solid transparent;
|
border-left: 5px solid transparent;
|
||||||
border-right: 5px solid transparent;
|
border-right: 5px solid transparent;
|
||||||
}
|
}
|
||||||
|
.sidebarFilterIcon div:after {
|
||||||
|
right: 37% !important;
|
||||||
|
}
|
||||||
|
|
||||||
.mapInfoIcon div:after, .openCheatsheet div:after {
|
.mapInfoIcon div:after, .openCheatsheet div:after {
|
||||||
content: '';
|
content: '';
|
||||||
|
@ -735,7 +714,7 @@
|
||||||
color: #F5F5F5;
|
color: #F5F5F5;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
z-index: 1 !important; /* important necessary for firefox */
|
z-index: 4 !important; /* important necessary for firefox */
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height:14px;
|
line-height:14px;
|
||||||
}
|
}
|
||||||
|
@ -764,3 +743,11 @@ box-shadow: 0px 1px 1.5px rgba(0,0,0,0.12), 0 1px 1px rgba(0,0,0,0.24);
|
||||||
body a#barometer_tab:hover {
|
body a#barometer_tab:hover {
|
||||||
background-position: 0 -110px;
|
background-position: 0 -110px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hideVideos .collaborator-video {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hideCursors .collabCompass {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
|
@ -1,474 +1,474 @@
|
||||||
/*! jQuery UI - v1.9.2 - 2012-11-23
|
/*! jQuery UI - v1.9.2 - 2012-11-23
|
||||||
* http://jqueryui.com
|
* http://jqueryui.com
|
||||||
* Includes: jquery.ui.core.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css
|
* Includes: jquery.ui.core.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css
|
||||||
* Copyright 2012 jQuery Foundation and other contributors; Licensed MIT */
|
* Copyright 2012 jQuery Foundation and other contributors; Licensed MIT */
|
||||||
|
|
||||||
/* Layout helpers
|
/* Layout helpers
|
||||||
----------------------------------*/
|
----------------------------------*/
|
||||||
.ui-helper-hidden { display: none; }
|
.ui-helper-hidden { display: none; }
|
||||||
.ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
|
.ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
|
||||||
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
|
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
|
||||||
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
|
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
|
||||||
.ui-helper-clearfix:after { clear: both; }
|
.ui-helper-clearfix:after { clear: both; }
|
||||||
.ui-helper-clearfix { zoom: 1; }
|
.ui-helper-clearfix { zoom: 1; }
|
||||||
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
|
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
|
||||||
|
|
||||||
|
|
||||||
/* Interaction Cues
|
/* Interaction Cues
|
||||||
----------------------------------*/
|
----------------------------------*/
|
||||||
.ui-state-disabled { cursor: default !important; }
|
.ui-state-disabled { cursor: default !important; }
|
||||||
|
|
||||||
|
|
||||||
/* Icons
|
/* Icons
|
||||||
----------------------------------*/
|
----------------------------------*/
|
||||||
|
|
||||||
/* states and images */
|
/* states and images */
|
||||||
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
|
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
|
||||||
|
|
||||||
|
|
||||||
/* Misc visuals
|
/* Misc visuals
|
||||||
----------------------------------*/
|
----------------------------------*/
|
||||||
|
|
||||||
/* Overlays */
|
/* Overlays */
|
||||||
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
||||||
|
|
||||||
.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; }
|
.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; }
|
||||||
.ui-accordion .ui-accordion-icons { padding-left: 2.2em; }
|
.ui-accordion .ui-accordion-icons { padding-left: 2.2em; }
|
||||||
.ui-accordion .ui-accordion-noicons { padding-left: .7em; }
|
.ui-accordion .ui-accordion-noicons { padding-left: .7em; }
|
||||||
.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; }
|
.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; }
|
||||||
.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
||||||
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; }
|
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; }
|
||||||
|
|
||||||
.ui-autocomplete {
|
.ui-autocomplete {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* workarounds */
|
/* workarounds */
|
||||||
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
|
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
|
||||||
|
|
||||||
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
|
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
|
||||||
.ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { text-decoration: none; }
|
.ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { text-decoration: none; }
|
||||||
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
|
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
|
||||||
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
|
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
|
||||||
.ui-button-icons-only { width: 3.4em; }
|
.ui-button-icons-only { width: 3.4em; }
|
||||||
button.ui-button-icons-only { width: 3.7em; }
|
button.ui-button-icons-only { width: 3.7em; }
|
||||||
|
|
||||||
/*button text element */
|
/*button text element */
|
||||||
.ui-button .ui-button-text { display: block; line-height: 1.4; }
|
.ui-button .ui-button-text { display: block; line-height: 1.4; }
|
||||||
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
|
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
|
||||||
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
|
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
|
||||||
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
|
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
|
||||||
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
|
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
|
||||||
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
|
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
|
||||||
/* no icon support for input elements, provide padding by default */
|
/* no icon support for input elements, provide padding by default */
|
||||||
input.ui-button { padding: .4em 1em; }
|
input.ui-button { padding: .4em 1em; }
|
||||||
|
|
||||||
/*button icon element(s) */
|
/*button icon element(s) */
|
||||||
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
|
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
|
||||||
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
|
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
|
||||||
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
|
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
|
||||||
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
||||||
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
||||||
|
|
||||||
/*button sets*/
|
/*button sets*/
|
||||||
.ui-buttonset { margin-right: 7px; }
|
.ui-buttonset { margin-right: 7px; }
|
||||||
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
|
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
|
||||||
|
|
||||||
/* workarounds */
|
/* workarounds */
|
||||||
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
||||||
|
|
||||||
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
||||||
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
||||||
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
||||||
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
||||||
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
||||||
.ui-datepicker .ui-datepicker-next { right:2px; }
|
.ui-datepicker .ui-datepicker-next { right:2px; }
|
||||||
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
||||||
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
||||||
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
||||||
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
||||||
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
|
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
|
||||||
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
||||||
.ui-datepicker select.ui-datepicker-month,
|
.ui-datepicker select.ui-datepicker-month,
|
||||||
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
||||||
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
||||||
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
||||||
.ui-datepicker td { border: 0; padding: 1px; }
|
.ui-datepicker td { border: 0; padding: 1px; }
|
||||||
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
||||||
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
||||||
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
||||||
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
||||||
|
|
||||||
/* with multiple calendars */
|
/* with multiple calendars */
|
||||||
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
||||||
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
||||||
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
||||||
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
||||||
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
||||||
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
||||||
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
||||||
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
||||||
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
||||||
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
|
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
|
||||||
|
|
||||||
/* RTL support */
|
/* RTL support */
|
||||||
.ui-datepicker-rtl { direction: rtl; }
|
.ui-datepicker-rtl { direction: rtl; }
|
||||||
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
||||||
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
||||||
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
||||||
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
||||||
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
||||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
||||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
||||||
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
||||||
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||||
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||||
|
|
||||||
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
||||||
.ui-datepicker-cover {
|
.ui-datepicker-cover {
|
||||||
position: absolute; /*must have*/
|
position: absolute; /*must have*/
|
||||||
z-index: -1; /*must have*/
|
z-index: -1; /*must have*/
|
||||||
filter: mask(); /*must have*/
|
filter: mask(); /*must have*/
|
||||||
top: -4px; /*must have*/
|
top: -4px; /*must have*/
|
||||||
left: -4px; /*must have*/
|
left: -4px; /*must have*/
|
||||||
width: 200px; /*must have*/
|
width: 200px; /*must have*/
|
||||||
height: 200px; /*must have*/
|
height: 200px; /*must have*/
|
||||||
}
|
}
|
||||||
.ui-dialog { position: absolute; top: 0; left: 0; padding: .2em; width: 300px; overflow: hidden; }
|
.ui-dialog { position: absolute; top: 0; left: 0; padding: .2em; width: 300px; overflow: hidden; }
|
||||||
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
|
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
|
||||||
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
|
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
|
||||||
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
|
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
|
||||||
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
||||||
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
|
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
|
||||||
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
||||||
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
||||||
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
|
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
|
||||||
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
|
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
|
||||||
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
||||||
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
||||||
|
|
||||||
.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }
|
.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }
|
||||||
.ui-menu .ui-menu { margin-top: -3px; position: absolute; }
|
.ui-menu .ui-menu { margin-top: -3px; position: absolute; }
|
||||||
.ui-menu .ui-menu-topic { margin: 0; padding: 0; zoom: 1; width: 100%; }
|
.ui-menu .ui-menu-topic { margin: 0; padding: 0; zoom: 1; width: 100%; }
|
||||||
.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
|
.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
|
||||||
.ui-menu .ui-menu-topic a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
|
.ui-menu .ui-menu-topic a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
|
||||||
.ui-menu .ui-menu-topic a.ui-state-focus,
|
.ui-menu .ui-menu-topic a.ui-state-focus,
|
||||||
.ui-menu .ui-menu-topic a.ui-state-active { font-weight: normal; margin: -1px; }
|
.ui-menu .ui-menu-topic a.ui-state-active { font-weight: normal; margin: -1px; }
|
||||||
|
|
||||||
.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
|
.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
|
||||||
.ui-menu .ui-state-disabled a { cursor: default; }
|
.ui-menu .ui-state-disabled a { cursor: default; }
|
||||||
|
|
||||||
/* icon support */
|
/* icon support */
|
||||||
.ui-menu-icons { position: relative; }
|
.ui-menu-icons { position: relative; }
|
||||||
.ui-menu-icons .ui-menu-topic a { position: relative; padding-left: 2em; }
|
.ui-menu-icons .ui-menu-topic a { position: relative; padding-left: 2em; }
|
||||||
|
|
||||||
/* left-aligned */
|
/* left-aligned */
|
||||||
.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
|
.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
|
||||||
|
|
||||||
/* right-aligned */
|
/* right-aligned */
|
||||||
.ui-menu .ui-menu-icon { position: static; float: right; }
|
.ui-menu .ui-menu-icon { position: static; float: right; }
|
||||||
|
|
||||||
.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
|
.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
|
||||||
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
|
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
|
||||||
.ui-resizable { position: relative;}
|
.ui-resizable { position: relative;}
|
||||||
.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
|
.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
|
||||||
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
||||||
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
|
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
|
||||||
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
|
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
|
||||||
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
|
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
|
||||||
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
|
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
|
||||||
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
||||||
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
||||||
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
||||||
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
|
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
|
||||||
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
|
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
|
||||||
|
|
||||||
.ui-slider { position: relative; text-align: left; }
|
.ui-slider { position: relative; text-align: left; }
|
||||||
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
|
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
|
||||||
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
|
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
|
||||||
|
|
||||||
.ui-slider-horizontal { height: .8em; }
|
.ui-slider-horizontal { height: .8em; }
|
||||||
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
|
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
|
||||||
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
|
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
|
||||||
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
|
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
|
||||||
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
|
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
|
||||||
|
|
||||||
.ui-slider-vertical { width: .8em; height: 100px; }
|
.ui-slider-vertical { width: .8em; height: 100px; }
|
||||||
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
||||||
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
||||||
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
||||||
.ui-slider-vertical .ui-slider-range-max { top: 0; }
|
.ui-slider-vertical .ui-slider-range-max { top: 0; }
|
||||||
.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
|
.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
|
||||||
.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
|
.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
|
||||||
.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
|
.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
|
||||||
.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
|
.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
|
||||||
.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
|
.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
|
||||||
.ui-spinner-up { top: 0; }
|
.ui-spinner-up { top: 0; }
|
||||||
.ui-spinner-down { bottom: 0; }
|
.ui-spinner-down { bottom: 0; }
|
||||||
|
|
||||||
/* TR overrides */
|
/* TR overrides */
|
||||||
.ui-spinner .ui-icon-triangle-1-s {
|
.ui-spinner .ui-icon-triangle-1-s {
|
||||||
/* need to fix icons sprite */
|
/* need to fix icons sprite */
|
||||||
background-position:-65px -16px;
|
background-position:-65px -16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
||||||
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
|
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
|
||||||
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0; padding: 0; white-space: nowrap; }
|
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0; padding: 0; white-space: nowrap; }
|
||||||
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
|
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
|
||||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; }
|
.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; }
|
||||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
|
.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
|
||||||
.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
||||||
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
|
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
|
||||||
|
|
||||||
.ui-tooltip {
|
.ui-tooltip {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
-webkit-box-shadow: 0 0 5px #aaa;
|
-webkit-box-shadow: 0 0 5px #aaa;
|
||||||
box-shadow: 0 0 5px #aaa;
|
box-shadow: 0 0 5px #aaa;
|
||||||
}
|
}
|
||||||
/* Fades and background-images don't work well together in IE6, drop the image */
|
/* Fades and background-images don't work well together in IE6, drop the image */
|
||||||
* html .ui-tooltip {
|
* html .ui-tooltip {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
}
|
}
|
||||||
body .ui-tooltip { border-width: 2px; }
|
body .ui-tooltip { border-width: 2px; }
|
||||||
|
|
||||||
/* Component containers
|
/* Component containers
|
||||||
----------------------------------*/
|
----------------------------------*/
|
||||||
.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
|
.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
|
||||||
.ui-widget .ui-widget { font-size: 1em; }
|
.ui-widget .ui-widget { font-size: 1em; }
|
||||||
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
|
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
|
||||||
.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(<%= asset_data_uri('ui-bg_flat_75_ffffff_40x100.png') %>)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
|
.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(<%= asset_data_uri('ui-bg_flat_75_ffffff_40x100.png') %>)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
|
||||||
.ui-widget-content a { color: #222222/*{fcContent}*/; }
|
.ui-widget-content a { color: #222222/*{fcContent}*/; }
|
||||||
.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(<%= asset_data_uri('images/ui-bg_highlight-soft_75_cccccc_1x100.png') %>)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
|
.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(<%= asset_data_uri('images/ui-bg_highlight-soft_75_cccccc_1x100.png') %>)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
|
||||||
.ui-widget-header a { color: #222222/*{fcHeader}*/; }
|
.ui-widget-header a { color: #222222/*{fcHeader}*/; }
|
||||||
|
|
||||||
/* Interaction states
|
/* Interaction states
|
||||||
----------------------------------*/
|
----------------------------------*/
|
||||||
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(<%= asset_data_uri('images/ui-bg_glass_75_e6e6e6_1x400.png') %>)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }
|
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(<%= asset_data_uri('images/ui-bg_glass_75_e6e6e6_1x400.png') %>)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }
|
||||||
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
|
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
|
||||||
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 0px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(<%= asset_data_uri('images/ui-bg_glass_75_dadada_1x400.png') %>)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }
|
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 0px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(<%= asset_data_uri('images/ui-bg_glass_75_dadada_1x400.png') %>)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }
|
||||||
.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #212121/*{fcHover}*/; text-decoration: none; }
|
.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #212121/*{fcHover}*/; text-decoration: none; }
|
||||||
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(<%= asset_data_uri('images/ui-bg_glass_65_ffffff_1x400.png') %>)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }
|
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(<%= asset_data_uri('images/ui-bg_glass_65_ffffff_1x400.png') %>)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }
|
||||||
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
|
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
|
||||||
|
|
||||||
/* Interaction Cues
|
/* Interaction Cues
|
||||||
----------------------------------*/
|
----------------------------------*/
|
||||||
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(<%= asset_data_uri('images/ui-bg_glass_55_fbf9ee_1x400.png') %>)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
|
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(<%= asset_data_uri('images/ui-bg_glass_55_fbf9ee_1x400.png') %>)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
|
||||||
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
|
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
|
||||||
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(<%= asset_data_uri('images/ui-bg_glass_95_fef1ec_1x400.png') %>)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
|
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(<%= asset_data_uri('images/ui-bg_glass_95_fef1ec_1x400.png') %>)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
|
||||||
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
|
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
|
||||||
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
|
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
|
||||||
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
|
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
|
||||||
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
||||||
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
||||||
.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */
|
.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */
|
||||||
|
|
||||||
/* Icons
|
/* Icons
|
||||||
----------------------------------*/
|
----------------------------------*/
|
||||||
|
|
||||||
/* states and images */
|
/* states and images */
|
||||||
.ui-icon { width: 16px; height: 16px; background-image: url(<%= asset_data_uri('images/ui-icons_222222_256x240.png') %>)/*{iconsContent}*/; }
|
.ui-icon { width: 16px; height: 16px; background-image: url(<%= asset_data_uri('images/ui-icons_222222_256x240.png') %>)/*{iconsContent}*/; }
|
||||||
.ui-widget-content .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_222222_256x240.png') %>)/*{iconsContent}*/; }
|
.ui-widget-content .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_222222_256x240.png') %>)/*{iconsContent}*/; }
|
||||||
.ui-widget-header .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_222222_256x240.png') %>)/*{iconsHeader}*/; }
|
.ui-widget-header .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_222222_256x240.png') %>)/*{iconsHeader}*/; }
|
||||||
.ui-state-default .ui-icon { background-image: url(<%= asset_data_uri('images/ui-icons_888888_256x240.png') %>)/*{iconsDefault}*/; }
|
.ui-state-default .ui-icon { background-image: url(<%= asset_data_uri('images/ui-icons_888888_256x240.png') %>)/*{iconsDefault}*/; }
|
||||||
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_454545_256x240.png') %>)/*{iconsHover}*/; }
|
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_454545_256x240.png') %>)/*{iconsHover}*/; }
|
||||||
.ui-state-active .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_454545_256x240.png') %>)/*{iconsActive}*/; }
|
.ui-state-active .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_454545_256x240.png') %>)/*{iconsActive}*/; }
|
||||||
.ui-state-highlight .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_2e83ff_256x240.png') %>)/*{iconsHighlight}*/; }
|
.ui-state-highlight .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_2e83ff_256x240.png') %>)/*{iconsHighlight}*/; }
|
||||||
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_cd0a0a_256x240.png') %>)/*{iconsError}*/; }
|
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(<%= asset_data_uri('images/ui-icons_cd0a0a_256x240.png') %>)/*{iconsError}*/; }
|
||||||
|
|
||||||
/* positioning */
|
/* positioning */
|
||||||
.ui-icon-carat-1-n { background-position: 0 0; }
|
.ui-icon-carat-1-n { background-position: 0 0; }
|
||||||
.ui-icon-carat-1-ne { background-position: -16px 0; }
|
.ui-icon-carat-1-ne { background-position: -16px 0; }
|
||||||
.ui-icon-carat-1-e { background-position: -32px 0; }
|
.ui-icon-carat-1-e { background-position: -32px 0; }
|
||||||
.ui-icon-carat-1-se { background-position: -48px 0; }
|
.ui-icon-carat-1-se { background-position: -48px 0; }
|
||||||
.ui-icon-carat-1-s { background-position: -64px 0; }
|
.ui-icon-carat-1-s { background-position: -64px 0; }
|
||||||
.ui-icon-carat-1-sw { background-position: -80px 0; }
|
.ui-icon-carat-1-sw { background-position: -80px 0; }
|
||||||
.ui-icon-carat-1-w { background-position: -96px 0; }
|
.ui-icon-carat-1-w { background-position: -96px 0; }
|
||||||
.ui-icon-carat-1-nw { background-position: -112px 0; }
|
.ui-icon-carat-1-nw { background-position: -112px 0; }
|
||||||
.ui-icon-carat-2-n-s { background-position: -128px 0; }
|
.ui-icon-carat-2-n-s { background-position: -128px 0; }
|
||||||
.ui-icon-carat-2-e-w { background-position: -144px 0; }
|
.ui-icon-carat-2-e-w { background-position: -144px 0; }
|
||||||
.ui-icon-triangle-1-n { background-position: 0 -16px; }
|
.ui-icon-triangle-1-n { background-position: 0 -16px; }
|
||||||
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
|
||||||
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
.ui-icon-triangle-1-e { background-position: -32px -16px; }
|
||||||
.ui-icon-triangle-1-se { background-position: -48px -16px; }
|
.ui-icon-triangle-1-se { background-position: -48px -16px; }
|
||||||
.ui-icon-triangle-1-s { background-position: -64px -16px; }
|
.ui-icon-triangle-1-s { background-position: -64px -16px; }
|
||||||
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
|
||||||
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
.ui-icon-triangle-1-w { background-position: -96px -16px; }
|
||||||
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
|
||||||
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
|
||||||
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
|
||||||
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
.ui-icon-arrow-1-n { background-position: 0 -32px; }
|
||||||
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
|
||||||
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
.ui-icon-arrow-1-e { background-position: -32px -32px; }
|
||||||
.ui-icon-arrow-1-se { background-position: -48px -32px; }
|
.ui-icon-arrow-1-se { background-position: -48px -32px; }
|
||||||
.ui-icon-arrow-1-s { background-position: -64px -32px; }
|
.ui-icon-arrow-1-s { background-position: -64px -32px; }
|
||||||
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
|
||||||
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
.ui-icon-arrow-1-w { background-position: -96px -32px; }
|
||||||
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
|
||||||
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
|
||||||
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
|
||||||
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
|
||||||
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
|
||||||
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
|
||||||
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
|
||||||
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
|
||||||
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
|
||||||
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
|
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
|
||||||
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
|
||||||
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
|
||||||
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
|
||||||
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
|
||||||
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
|
||||||
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
|
||||||
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
|
||||||
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
|
||||||
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
|
||||||
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
|
||||||
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
|
||||||
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
|
||||||
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
|
||||||
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
|
||||||
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
|
||||||
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
|
||||||
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
|
||||||
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
|
||||||
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
|
||||||
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
|
||||||
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
|
||||||
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
|
||||||
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
|
||||||
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
|
||||||
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
|
||||||
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
|
||||||
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
|
||||||
.ui-icon-arrow-4 { background-position: 0 -80px; }
|
.ui-icon-arrow-4 { background-position: 0 -80px; }
|
||||||
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
|
||||||
.ui-icon-extlink { background-position: -32px -80px; }
|
.ui-icon-extlink { background-position: -32px -80px; }
|
||||||
.ui-icon-newwin { background-position: -48px -80px; }
|
.ui-icon-newwin { background-position: -48px -80px; }
|
||||||
.ui-icon-refresh { background-position: -64px -80px; }
|
.ui-icon-refresh { background-position: -64px -80px; }
|
||||||
.ui-icon-shuffle { background-position: -80px -80px; }
|
.ui-icon-shuffle { background-position: -80px -80px; }
|
||||||
.ui-icon-transfer-e-w { background-position: -96px -80px; }
|
.ui-icon-transfer-e-w { background-position: -96px -80px; }
|
||||||
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
|
||||||
.ui-icon-folder-collapsed { background-position: 0 -96px; }
|
.ui-icon-folder-collapsed { background-position: 0 -96px; }
|
||||||
.ui-icon-folder-open { background-position: -16px -96px; }
|
.ui-icon-folder-open { background-position: -16px -96px; }
|
||||||
.ui-icon-document { background-position: -32px -96px; }
|
.ui-icon-document { background-position: -32px -96px; }
|
||||||
.ui-icon-document-b { background-position: -48px -96px; }
|
.ui-icon-document-b { background-position: -48px -96px; }
|
||||||
.ui-icon-note { background-position: -64px -96px; }
|
.ui-icon-note { background-position: -64px -96px; }
|
||||||
.ui-icon-mail-closed { background-position: -80px -96px; }
|
.ui-icon-mail-closed { background-position: -80px -96px; }
|
||||||
.ui-icon-mail-open { background-position: -96px -96px; }
|
.ui-icon-mail-open { background-position: -96px -96px; }
|
||||||
.ui-icon-suitcase { background-position: -112px -96px; }
|
.ui-icon-suitcase { background-position: -112px -96px; }
|
||||||
.ui-icon-comment { background-position: -128px -96px; }
|
.ui-icon-comment { background-position: -128px -96px; }
|
||||||
.ui-icon-person { background-position: -144px -96px; }
|
.ui-icon-person { background-position: -144px -96px; }
|
||||||
.ui-icon-print { background-position: -160px -96px; }
|
.ui-icon-print { background-position: -160px -96px; }
|
||||||
.ui-icon-trash { background-position: -176px -96px; }
|
.ui-icon-trash { background-position: -176px -96px; }
|
||||||
.ui-icon-locked { background-position: -192px -96px; }
|
.ui-icon-locked { background-position: -192px -96px; }
|
||||||
.ui-icon-unlocked { background-position: -208px -96px; }
|
.ui-icon-unlocked { background-position: -208px -96px; }
|
||||||
.ui-icon-bookmark { background-position: -224px -96px; }
|
.ui-icon-bookmark { background-position: -224px -96px; }
|
||||||
.ui-icon-tag { background-position: -240px -96px; }
|
.ui-icon-tag { background-position: -240px -96px; }
|
||||||
.ui-icon-home { background-position: 0 -112px; }
|
.ui-icon-home { background-position: 0 -112px; }
|
||||||
.ui-icon-flag { background-position: -16px -112px; }
|
.ui-icon-flag { background-position: -16px -112px; }
|
||||||
.ui-icon-calendar { background-position: -32px -112px; }
|
.ui-icon-calendar { background-position: -32px -112px; }
|
||||||
.ui-icon-cart { background-position: -48px -112px; }
|
.ui-icon-cart { background-position: -48px -112px; }
|
||||||
.ui-icon-pencil { background-position: -64px -112px; }
|
.ui-icon-pencil { background-position: -64px -112px; }
|
||||||
.ui-icon-clock { background-position: -80px -112px; }
|
.ui-icon-clock { background-position: -80px -112px; }
|
||||||
.ui-icon-disk { background-position: -96px -112px; }
|
.ui-icon-disk { background-position: -96px -112px; }
|
||||||
.ui-icon-calculator { background-position: -112px -112px; }
|
.ui-icon-calculator { background-position: -112px -112px; }
|
||||||
.ui-icon-zoomin { background-position: -128px -112px; }
|
.ui-icon-zoomin { background-position: -128px -112px; }
|
||||||
.ui-icon-zoomout { background-position: -144px -112px; }
|
.ui-icon-zoomout { background-position: -144px -112px; }
|
||||||
.ui-icon-search { background-position: -160px -112px; }
|
.ui-icon-search { background-position: -160px -112px; }
|
||||||
.ui-icon-wrench { background-position: -176px -112px; }
|
.ui-icon-wrench { background-position: -176px -112px; }
|
||||||
.ui-icon-gear { background-position: -192px -112px; }
|
.ui-icon-gear { background-position: -192px -112px; }
|
||||||
.ui-icon-heart { background-position: -208px -112px; }
|
.ui-icon-heart { background-position: -208px -112px; }
|
||||||
.ui-icon-star { background-position: -224px -112px; }
|
.ui-icon-star { background-position: -224px -112px; }
|
||||||
.ui-icon-link { background-position: -240px -112px; }
|
.ui-icon-link { background-position: -240px -112px; }
|
||||||
.ui-icon-cancel { background-position: 0 -128px; }
|
.ui-icon-cancel { background-position: 0 -128px; }
|
||||||
.ui-icon-plus { background-position: -16px -128px; }
|
.ui-icon-plus { background-position: -16px -128px; }
|
||||||
.ui-icon-plusthick { background-position: -32px -128px; }
|
.ui-icon-plusthick { background-position: -32px -128px; }
|
||||||
.ui-icon-minus { background-position: -48px -128px; }
|
.ui-icon-minus { background-position: -48px -128px; }
|
||||||
.ui-icon-minusthick { background-position: -64px -128px; }
|
.ui-icon-minusthick { background-position: -64px -128px; }
|
||||||
.ui-icon-close { background-position: -80px -128px; }
|
.ui-icon-close { background-position: -80px -128px; }
|
||||||
.ui-icon-closethick { background-position: -96px -128px; }
|
.ui-icon-closethick { background-position: -96px -128px; }
|
||||||
.ui-icon-key { background-position: -112px -128px; }
|
.ui-icon-key { background-position: -112px -128px; }
|
||||||
.ui-icon-lightbulb { background-position: -128px -128px; }
|
.ui-icon-lightbulb { background-position: -128px -128px; }
|
||||||
.ui-icon-scissors { background-position: -144px -128px; }
|
.ui-icon-scissors { background-position: -144px -128px; }
|
||||||
.ui-icon-clipboard { background-position: -160px -128px; }
|
.ui-icon-clipboard { background-position: -160px -128px; }
|
||||||
.ui-icon-copy { background-position: -176px -128px; }
|
.ui-icon-copy { background-position: -176px -128px; }
|
||||||
.ui-icon-contact { background-position: -192px -128px; }
|
.ui-icon-contact { background-position: -192px -128px; }
|
||||||
.ui-icon-image { background-position: -208px -128px; }
|
.ui-icon-image { background-position: -208px -128px; }
|
||||||
.ui-icon-video { background-position: -224px -128px; }
|
.ui-icon-video { background-position: -224px -128px; }
|
||||||
.ui-icon-script { background-position: -240px -128px; }
|
.ui-icon-script { background-position: -240px -128px; }
|
||||||
.ui-icon-alert { background-position: 0 -144px; }
|
.ui-icon-alert { background-position: 0 -144px; }
|
||||||
.ui-icon-info { background-position: -16px -144px; }
|
.ui-icon-info { background-position: -16px -144px; }
|
||||||
.ui-icon-notice { background-position: -32px -144px; }
|
.ui-icon-notice { background-position: -32px -144px; }
|
||||||
.ui-icon-help { background-position: -48px -144px; }
|
.ui-icon-help { background-position: -48px -144px; }
|
||||||
.ui-icon-check { background-position: -64px -144px; }
|
.ui-icon-check { background-position: -64px -144px; }
|
||||||
.ui-icon-bullet { background-position: -80px -144px; }
|
.ui-icon-bullet { background-position: -80px -144px; }
|
||||||
.ui-icon-radio-on { background-position: -96px -144px; }
|
.ui-icon-radio-on { background-position: -96px -144px; }
|
||||||
.ui-icon-radio-off { background-position: -112px -144px; }
|
.ui-icon-radio-off { background-position: -112px -144px; }
|
||||||
.ui-icon-pin-w { background-position: -128px -144px; }
|
.ui-icon-pin-w { background-position: -128px -144px; }
|
||||||
.ui-icon-pin-s { background-position: -144px -144px; }
|
.ui-icon-pin-s { background-position: -144px -144px; }
|
||||||
.ui-icon-play { background-position: 0 -160px; }
|
.ui-icon-play { background-position: 0 -160px; }
|
||||||
.ui-icon-pause { background-position: -16px -160px; }
|
.ui-icon-pause { background-position: -16px -160px; }
|
||||||
.ui-icon-seek-next { background-position: -32px -160px; }
|
.ui-icon-seek-next { background-position: -32px -160px; }
|
||||||
.ui-icon-seek-prev { background-position: -48px -160px; }
|
.ui-icon-seek-prev { background-position: -48px -160px; }
|
||||||
.ui-icon-seek-end { background-position: -64px -160px; }
|
.ui-icon-seek-end { background-position: -64px -160px; }
|
||||||
.ui-icon-seek-start { background-position: -80px -160px; }
|
.ui-icon-seek-start { background-position: -80px -160px; }
|
||||||
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
|
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
|
||||||
.ui-icon-seek-first { background-position: -80px -160px; }
|
.ui-icon-seek-first { background-position: -80px -160px; }
|
||||||
.ui-icon-stop { background-position: -96px -160px; }
|
.ui-icon-stop { background-position: -96px -160px; }
|
||||||
.ui-icon-eject { background-position: -112px -160px; }
|
.ui-icon-eject { background-position: -112px -160px; }
|
||||||
.ui-icon-volume-off { background-position: -128px -160px; }
|
.ui-icon-volume-off { background-position: -128px -160px; }
|
||||||
.ui-icon-volume-on { background-position: -144px -160px; }
|
.ui-icon-volume-on { background-position: -144px -160px; }
|
||||||
.ui-icon-power { background-position: 0 -176px; }
|
.ui-icon-power { background-position: 0 -176px; }
|
||||||
.ui-icon-signal-diag { background-position: -16px -176px; }
|
.ui-icon-signal-diag { background-position: -16px -176px; }
|
||||||
.ui-icon-signal { background-position: -32px -176px; }
|
.ui-icon-signal { background-position: -32px -176px; }
|
||||||
.ui-icon-battery-0 { background-position: -48px -176px; }
|
.ui-icon-battery-0 { background-position: -48px -176px; }
|
||||||
.ui-icon-battery-1 { background-position: -64px -176px; }
|
.ui-icon-battery-1 { background-position: -64px -176px; }
|
||||||
.ui-icon-battery-2 { background-position: -80px -176px; }
|
.ui-icon-battery-2 { background-position: -80px -176px; }
|
||||||
.ui-icon-battery-3 { background-position: -96px -176px; }
|
.ui-icon-battery-3 { background-position: -96px -176px; }
|
||||||
.ui-icon-circle-plus { background-position: 0 -192px; }
|
.ui-icon-circle-plus { background-position: 0 -192px; }
|
||||||
.ui-icon-circle-minus { background-position: -16px -192px; }
|
.ui-icon-circle-minus { background-position: -16px -192px; }
|
||||||
.ui-icon-circle-close { background-position: -32px -192px; }
|
.ui-icon-circle-close { background-position: -32px -192px; }
|
||||||
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
|
||||||
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
|
||||||
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
|
||||||
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
|
||||||
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
|
||||||
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
|
||||||
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
|
||||||
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
|
||||||
.ui-icon-circle-zoomin { background-position: -176px -192px; }
|
.ui-icon-circle-zoomin { background-position: -176px -192px; }
|
||||||
.ui-icon-circle-zoomout { background-position: -192px -192px; }
|
.ui-icon-circle-zoomout { background-position: -192px -192px; }
|
||||||
.ui-icon-circle-check { background-position: -208px -192px; }
|
.ui-icon-circle-check { background-position: -208px -192px; }
|
||||||
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
|
||||||
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
|
||||||
.ui-icon-circlesmall-close { background-position: -32px -208px; }
|
.ui-icon-circlesmall-close { background-position: -32px -208px; }
|
||||||
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
|
||||||
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
|
||||||
.ui-icon-squaresmall-close { background-position: -80px -208px; }
|
.ui-icon-squaresmall-close { background-position: -80px -208px; }
|
||||||
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
|
||||||
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
|
||||||
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
|
||||||
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
|
||||||
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
||||||
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
|
||||||
|
|
||||||
|
|
||||||
/* Misc visuals
|
/* Misc visuals
|
||||||
----------------------------------*/
|
----------------------------------*/
|
||||||
|
|
||||||
/* Corner radius */
|
/* Corner radius */
|
||||||
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -khtml-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }
|
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -khtml-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }
|
||||||
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -khtml-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
|
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -khtml-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
|
||||||
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
|
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
|
||||||
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
|
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
|
||||||
|
|
||||||
/* Overlays */
|
/* Overlays */
|
||||||
.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(<%= asset_data_uri('images/ui-bg_flat_0_aaaaaa_40x100.png') %>)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
|
.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(<%= asset_data_uri('images/ui-bg_flat_0_aaaaaa_40x100.png') %>)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
|
||||||
.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/<%= asset_data_uri('ui-bg_flat_0_aaaaaa_40x100.png') %>)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; }
|
.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/<%= asset_data_uri('ui-bg_flat_0_aaaaaa_40x100.png') %>)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; }
|
||||||
|
|
|
@ -1,473 +1,473 @@
|
||||||
/* basic scrollbar styling */
|
/* basic scrollbar styling */
|
||||||
/* vertical scrollbar */
|
/* vertical scrollbar */
|
||||||
.mCSB_container{
|
.mCSB_container{
|
||||||
width:auto;
|
width:auto;
|
||||||
margin-right:30px;
|
margin-right:30px;
|
||||||
overflow:hidden;
|
overflow:hidden;
|
||||||
}
|
}
|
||||||
.mCSB_container.mCS_no_scrollbar{
|
.mCSB_container.mCS_no_scrollbar{
|
||||||
margin-right:0;
|
margin-right:0;
|
||||||
}
|
}
|
||||||
.mCS_disabled>.mCustomScrollBox>.mCSB_container.mCS_no_scrollbar,
|
.mCS_disabled>.mCustomScrollBox>.mCSB_container.mCS_no_scrollbar,
|
||||||
.mCS_destroyed>.mCustomScrollBox>.mCSB_container.mCS_no_scrollbar{
|
.mCS_destroyed>.mCustomScrollBox>.mCSB_container.mCS_no_scrollbar{
|
||||||
margin-right:30px;
|
margin-right:30px;
|
||||||
}
|
}
|
||||||
.mCustomScrollBox>.mCSB_scrollTools{
|
.mCustomScrollBox>.mCSB_scrollTools{
|
||||||
width:16px;
|
width:16px;
|
||||||
height:100%;
|
height:100%;
|
||||||
top:0;
|
top:0;
|
||||||
right:0;
|
right:0;
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_draggerContainer{
|
.mCSB_scrollTools .mCSB_draggerContainer{
|
||||||
position:absolute;
|
position:absolute;
|
||||||
top:0;
|
top:0;
|
||||||
left:0;
|
left:0;
|
||||||
bottom:0;
|
bottom:0;
|
||||||
right:0;
|
right:0;
|
||||||
height:auto;
|
height:auto;
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools a+.mCSB_draggerContainer{
|
.mCSB_scrollTools a+.mCSB_draggerContainer{
|
||||||
margin:20px 0;
|
margin:20px 0;
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_draggerRail{
|
.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:2px;
|
width:2px;
|
||||||
height:100%;
|
height:100%;
|
||||||
margin:0 auto;
|
margin:0 auto;
|
||||||
-webkit-border-radius:10px;
|
-webkit-border-radius:10px;
|
||||||
-moz-border-radius:10px;
|
-moz-border-radius:10px;
|
||||||
border-radius:10px;
|
border-radius:10px;
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_dragger{
|
.mCSB_scrollTools .mCSB_dragger{
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
width:100%;
|
width:100%;
|
||||||
height:30px;
|
height:30px;
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:4px;
|
width:4px;
|
||||||
height:100%;
|
height:100%;
|
||||||
margin:0 auto;
|
margin:0 auto;
|
||||||
-webkit-border-radius:10px;
|
-webkit-border-radius:10px;
|
||||||
-moz-border-radius:10px;
|
-moz-border-radius:10px;
|
||||||
border-radius:10px;
|
border-radius:10px;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_buttonUp,
|
.mCSB_scrollTools .mCSB_buttonUp,
|
||||||
.mCSB_scrollTools .mCSB_buttonDown{
|
.mCSB_scrollTools .mCSB_buttonDown{
|
||||||
display:block;
|
display:block;
|
||||||
position:relative;
|
position:relative;
|
||||||
height:20px;
|
height:20px;
|
||||||
overflow:hidden;
|
overflow:hidden;
|
||||||
margin:0 auto;
|
margin:0 auto;
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_buttonDown{
|
.mCSB_scrollTools .mCSB_buttonDown{
|
||||||
top:100%;
|
top:100%;
|
||||||
margin-top:-40px;
|
margin-top:-40px;
|
||||||
}
|
}
|
||||||
/* horizontal scrollbar */
|
/* horizontal scrollbar */
|
||||||
.mCSB_horizontal>.mCSB_container{
|
.mCSB_horizontal>.mCSB_container{
|
||||||
height:auto;
|
height:auto;
|
||||||
margin-right:0;
|
margin-right:0;
|
||||||
margin-bottom:30px;
|
margin-bottom:30px;
|
||||||
overflow:hidden;
|
overflow:hidden;
|
||||||
}
|
}
|
||||||
.mCSB_horizontal>.mCSB_container.mCS_no_scrollbar{
|
.mCSB_horizontal>.mCSB_container.mCS_no_scrollbar{
|
||||||
margin-bottom:0;
|
margin-bottom:0;
|
||||||
}
|
}
|
||||||
.mCS_disabled>.mCSB_horizontal>.mCSB_container.mCS_no_scrollbar,
|
.mCS_disabled>.mCSB_horizontal>.mCSB_container.mCS_no_scrollbar,
|
||||||
.mCS_destroyed>.mCSB_horizontal>.mCSB_container.mCS_no_scrollbar{
|
.mCS_destroyed>.mCSB_horizontal>.mCSB_container.mCS_no_scrollbar{
|
||||||
margin-right:0;
|
margin-right:0;
|
||||||
margin-bottom:30px;
|
margin-bottom:30px;
|
||||||
}
|
}
|
||||||
.mCSB_horizontal.mCustomScrollBox>.mCSB_scrollTools{
|
.mCSB_horizontal.mCustomScrollBox>.mCSB_scrollTools{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:16px;
|
height:16px;
|
||||||
top:auto;
|
top:auto;
|
||||||
right:auto;
|
right:auto;
|
||||||
bottom:0;
|
bottom:0;
|
||||||
left:0;
|
left:0;
|
||||||
overflow:hidden;
|
overflow:hidden;
|
||||||
}
|
}
|
||||||
.mCSB_horizontal>.mCSB_scrollTools a+.mCSB_draggerContainer{
|
.mCSB_horizontal>.mCSB_scrollTools a+.mCSB_draggerContainer{
|
||||||
margin:0 20px;
|
margin:0 20px;
|
||||||
}
|
}
|
||||||
.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:2px;
|
height:2px;
|
||||||
margin:7px 0;
|
margin:7px 0;
|
||||||
-webkit-border-radius:10px;
|
-webkit-border-radius:10px;
|
||||||
-moz-border-radius:10px;
|
-moz-border-radius:10px;
|
||||||
border-radius:10px;
|
border-radius:10px;
|
||||||
}
|
}
|
||||||
.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger{
|
.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger{
|
||||||
width:30px;
|
width:30px;
|
||||||
height:100%;
|
height:100%;
|
||||||
}
|
}
|
||||||
.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:4px;
|
height:4px;
|
||||||
margin:6px auto;
|
margin:6px auto;
|
||||||
-webkit-border-radius:10px;
|
-webkit-border-radius:10px;
|
||||||
-moz-border-radius:10px;
|
-moz-border-radius:10px;
|
||||||
border-radius:10px;
|
border-radius:10px;
|
||||||
}
|
}
|
||||||
.mCSB_horizontal>.mCSB_scrollTools .mCSB_buttonLeft,
|
.mCSB_horizontal>.mCSB_scrollTools .mCSB_buttonLeft,
|
||||||
.mCSB_horizontal>.mCSB_scrollTools .mCSB_buttonRight{
|
.mCSB_horizontal>.mCSB_scrollTools .mCSB_buttonRight{
|
||||||
display:block;
|
display:block;
|
||||||
position:relative;
|
position:relative;
|
||||||
width:20px;
|
width:20px;
|
||||||
height:100%;
|
height:100%;
|
||||||
overflow:hidden;
|
overflow:hidden;
|
||||||
margin:0 auto;
|
margin:0 auto;
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
float:left;
|
float:left;
|
||||||
}
|
}
|
||||||
.mCSB_horizontal>.mCSB_scrollTools .mCSB_buttonRight{
|
.mCSB_horizontal>.mCSB_scrollTools .mCSB_buttonRight{
|
||||||
margin-left:-40px;
|
margin-left:-40px;
|
||||||
float:right;
|
float:right;
|
||||||
}
|
}
|
||||||
.mCustomScrollBox{
|
.mCustomScrollBox{
|
||||||
-ms-touch-action:none; /*MSPointer events - direct all pointer events to js*/
|
-ms-touch-action:none; /*MSPointer events - direct all pointer events to js*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* default scrollbar colors and backgrounds (default theme) */
|
/* default scrollbar colors and backgrounds (default theme) */
|
||||||
.mCustomScrollBox>.mCSB_scrollTools{
|
.mCustomScrollBox>.mCSB_scrollTools{
|
||||||
opacity:0.75;
|
opacity:0.75;
|
||||||
filter:"alpha(opacity=75)"; -ms-filter:"alpha(opacity=75)"; /* old ie */
|
filter:"alpha(opacity=75)"; -ms-filter:"alpha(opacity=75)"; /* old ie */
|
||||||
}
|
}
|
||||||
.mCustomScrollBox:hover>.mCSB_scrollTools{
|
.mCustomScrollBox:hover>.mCSB_scrollTools{
|
||||||
opacity:1;
|
opacity:1;
|
||||||
filter:"alpha(opacity=100)"; -ms-filter:"alpha(opacity=100)"; /* old ie */
|
filter:"alpha(opacity=100)"; -ms-filter:"alpha(opacity=100)"; /* old ie */
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_draggerRail{
|
.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
background:#000; /* rgba fallback */
|
background:#000; /* rgba fallback */
|
||||||
background:rgba(0,0,0,0.4);
|
background:rgba(0,0,0,0.4);
|
||||||
filter:"alpha(opacity=40)"; -ms-filter:"alpha(opacity=40)"; /* old ie */
|
filter:"alpha(opacity=40)"; -ms-filter:"alpha(opacity=40)"; /* old ie */
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
background:#fff; /* rgba fallback */
|
background:#fff; /* rgba fallback */
|
||||||
background:rgba(255,255,255,0.75);
|
background:rgba(255,255,255,0.75);
|
||||||
filter:"alpha(opacity=75)"; -ms-filter:"alpha(opacity=75)"; /* old ie */
|
filter:"alpha(opacity=75)"; -ms-filter:"alpha(opacity=75)"; /* old ie */
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
||||||
background:rgba(255,255,255,0.85);
|
background:rgba(255,255,255,0.85);
|
||||||
filter:"alpha(opacity=85)"; -ms-filter:"alpha(opacity=85)"; /* old ie */
|
filter:"alpha(opacity=85)"; -ms-filter:"alpha(opacity=85)"; /* old ie */
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
||||||
.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
||||||
background:rgba(255,255,255,0.9);
|
background:rgba(255,255,255,0.9);
|
||||||
filter:"alpha(opacity=90)"; -ms-filter:"alpha(opacity=90)"; /* old ie */
|
filter:"alpha(opacity=90)"; -ms-filter:"alpha(opacity=90)"; /* old ie */
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_buttonUp,
|
.mCSB_scrollTools .mCSB_buttonUp,
|
||||||
.mCSB_scrollTools .mCSB_buttonDown,
|
.mCSB_scrollTools .mCSB_buttonDown,
|
||||||
.mCSB_scrollTools .mCSB_buttonLeft,
|
.mCSB_scrollTools .mCSB_buttonLeft,
|
||||||
.mCSB_scrollTools .mCSB_buttonRight{
|
.mCSB_scrollTools .mCSB_buttonRight{
|
||||||
background-repeat:no-repeat;
|
background-repeat:no-repeat;
|
||||||
opacity:0.4;
|
opacity:0.4;
|
||||||
filter:"alpha(opacity=40)"; -ms-filter:"alpha(opacity=40)"; /* old ie */
|
filter:"alpha(opacity=40)"; -ms-filter:"alpha(opacity=40)"; /* old ie */
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_buttonUp{
|
.mCSB_scrollTools .mCSB_buttonUp{
|
||||||
background-position:0 0;
|
background-position:0 0;
|
||||||
/*
|
/*
|
||||||
sprites locations are 0 0/-16px 0/-32px 0/-48px 0 (light) and -80px 0/-96px 0/-112px 0/-128px 0 (dark)
|
sprites locations are 0 0/-16px 0/-32px 0/-48px 0 (light) and -80px 0/-96px 0/-112px 0/-128px 0 (dark)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_buttonDown{
|
.mCSB_scrollTools .mCSB_buttonDown{
|
||||||
background-position:0 -20px;
|
background-position:0 -20px;
|
||||||
/*
|
/*
|
||||||
sprites locations are 0 -20px/-16px -20px/-32px -20px/-48px -20px (light) and -80px -20px/-96px -20px/-112px -20px/-128px -20px (dark)
|
sprites locations are 0 -20px/-16px -20px/-32px -20px/-48px -20px (light) and -80px -20px/-96px -20px/-112px -20px/-128px -20px (dark)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_buttonLeft{
|
.mCSB_scrollTools .mCSB_buttonLeft{
|
||||||
background-position:0 -40px;
|
background-position:0 -40px;
|
||||||
/*
|
/*
|
||||||
sprites locations are 0 -40px/-20px -40px/-40px -40px/-60px -40px (light) and -80px -40px/-100px -40px/-120px -40px/-140px -40px (dark)
|
sprites locations are 0 -40px/-20px -40px/-40px -40px/-60px -40px (light) and -80px -40px/-100px -40px/-120px -40px/-140px -40px (dark)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_buttonRight{
|
.mCSB_scrollTools .mCSB_buttonRight{
|
||||||
background-position:0 -56px;
|
background-position:0 -56px;
|
||||||
/*
|
/*
|
||||||
sprites locations are 0 -56px/-20px -56px/-40px -56px/-60px -56px (light) and -80px -56px/-100px -56px/-120px -56px/-140px -56px (dark)
|
sprites locations are 0 -56px/-20px -56px/-40px -56px/-60px -56px (light) and -80px -56px/-100px -56px/-120px -56px/-140px -56px (dark)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_buttonUp:hover,
|
.mCSB_scrollTools .mCSB_buttonUp:hover,
|
||||||
.mCSB_scrollTools .mCSB_buttonDown:hover,
|
.mCSB_scrollTools .mCSB_buttonDown:hover,
|
||||||
.mCSB_scrollTools .mCSB_buttonLeft:hover,
|
.mCSB_scrollTools .mCSB_buttonLeft:hover,
|
||||||
.mCSB_scrollTools .mCSB_buttonRight:hover{
|
.mCSB_scrollTools .mCSB_buttonRight:hover{
|
||||||
opacity:0.75;
|
opacity:0.75;
|
||||||
filter:"alpha(opacity=75)"; -ms-filter:"alpha(opacity=75)"; /* old ie */
|
filter:"alpha(opacity=75)"; -ms-filter:"alpha(opacity=75)"; /* old ie */
|
||||||
}
|
}
|
||||||
.mCSB_scrollTools .mCSB_buttonUp:active,
|
.mCSB_scrollTools .mCSB_buttonUp:active,
|
||||||
.mCSB_scrollTools .mCSB_buttonDown:active,
|
.mCSB_scrollTools .mCSB_buttonDown:active,
|
||||||
.mCSB_scrollTools .mCSB_buttonLeft:active,
|
.mCSB_scrollTools .mCSB_buttonLeft:active,
|
||||||
.mCSB_scrollTools .mCSB_buttonRight:active{
|
.mCSB_scrollTools .mCSB_buttonRight:active{
|
||||||
opacity:0.9;
|
opacity:0.9;
|
||||||
filter:"alpha(opacity=90)"; -ms-filter:"alpha(opacity=90)"; /* old ie */
|
filter:"alpha(opacity=90)"; -ms-filter:"alpha(opacity=90)"; /* old ie */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*scrollbar themes*/
|
/*scrollbar themes*/
|
||||||
/*dark (dark colored scrollbar)*/
|
/*dark (dark colored scrollbar)*/
|
||||||
.mCS-dark>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-dark>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
background:#000; /* rgba fallback */
|
background:#000; /* rgba fallback */
|
||||||
background:rgba(0,0,0,0.15);
|
background:rgba(0,0,0,0.15);
|
||||||
}
|
}
|
||||||
.mCS-dark>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-dark>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
background:#000; /* rgba fallback */
|
background:#000; /* rgba fallback */
|
||||||
background:rgba(0,0,0,0.75);
|
background:rgba(0,0,0,0.75);
|
||||||
}
|
}
|
||||||
.mCS-dark>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
.mCS-dark>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
||||||
background:rgba(0,0,0,0.85);
|
background:rgba(0,0,0,0.85);
|
||||||
}
|
}
|
||||||
.mCS-dark>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
.mCS-dark>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
||||||
.mCS-dark>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
.mCS-dark>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
||||||
background:rgba(0,0,0,0.9);
|
background:rgba(0,0,0,0.9);
|
||||||
}
|
}
|
||||||
.mCS-dark>.mCSB_scrollTools .mCSB_buttonUp{
|
.mCS-dark>.mCSB_scrollTools .mCSB_buttonUp{
|
||||||
background-position:-80px 0;
|
background-position:-80px 0;
|
||||||
}
|
}
|
||||||
.mCS-dark>.mCSB_scrollTools .mCSB_buttonDown{
|
.mCS-dark>.mCSB_scrollTools .mCSB_buttonDown{
|
||||||
background-position:-80px -20px;
|
background-position:-80px -20px;
|
||||||
}
|
}
|
||||||
.mCS-dark>.mCSB_scrollTools .mCSB_buttonLeft{
|
.mCS-dark>.mCSB_scrollTools .mCSB_buttonLeft{
|
||||||
background-position:-80px -40px;
|
background-position:-80px -40px;
|
||||||
}
|
}
|
||||||
.mCS-dark>.mCSB_scrollTools .mCSB_buttonRight{
|
.mCS-dark>.mCSB_scrollTools .mCSB_buttonRight{
|
||||||
background-position:-80px -56px;
|
background-position:-80px -56px;
|
||||||
}
|
}
|
||||||
/*light-2*/
|
/*light-2*/
|
||||||
.mCS-light-2>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-light-2>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:4px;
|
width:4px;
|
||||||
background:#fff; /* rgba fallback */
|
background:#fff; /* rgba fallback */
|
||||||
background:rgba(255,255,255,0.1);
|
background:rgba(255,255,255,0.1);
|
||||||
-webkit-border-radius:1px;
|
-webkit-border-radius:1px;
|
||||||
-moz-border-radius:1px;
|
-moz-border-radius:1px;
|
||||||
border-radius:1px;
|
border-radius:1px;
|
||||||
}
|
}
|
||||||
.mCS-light-2>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-light-2>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:4px;
|
width:4px;
|
||||||
background:#fff; /* rgba fallback */
|
background:#fff; /* rgba fallback */
|
||||||
background:rgba(255,255,255,0.75);
|
background:rgba(255,255,255,0.75);
|
||||||
-webkit-border-radius:1px;
|
-webkit-border-radius:1px;
|
||||||
-moz-border-radius:1px;
|
-moz-border-radius:1px;
|
||||||
border-radius:1px;
|
border-radius:1px;
|
||||||
}
|
}
|
||||||
.mCS-light-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-light-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:4px;
|
height:4px;
|
||||||
margin:6px 0;
|
margin:6px 0;
|
||||||
}
|
}
|
||||||
.mCS-light-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-light-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:4px;
|
height:4px;
|
||||||
margin:6px auto;
|
margin:6px auto;
|
||||||
}
|
}
|
||||||
.mCS-light-2>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
.mCS-light-2>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
||||||
background:rgba(255,255,255,0.85);
|
background:rgba(255,255,255,0.85);
|
||||||
}
|
}
|
||||||
.mCS-light-2>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
.mCS-light-2>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
||||||
.mCS-light-2>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
.mCS-light-2>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
||||||
background:rgba(255,255,255,0.9);
|
background:rgba(255,255,255,0.9);
|
||||||
}
|
}
|
||||||
.mCS-light-2>.mCSB_scrollTools .mCSB_buttonUp{
|
.mCS-light-2>.mCSB_scrollTools .mCSB_buttonUp{
|
||||||
background-position:-32px 0;
|
background-position:-32px 0;
|
||||||
}
|
}
|
||||||
.mCS-light-2>.mCSB_scrollTools .mCSB_buttonDown{
|
.mCS-light-2>.mCSB_scrollTools .mCSB_buttonDown{
|
||||||
background-position:-32px -20px;
|
background-position:-32px -20px;
|
||||||
}
|
}
|
||||||
.mCS-light-2>.mCSB_scrollTools .mCSB_buttonLeft{
|
.mCS-light-2>.mCSB_scrollTools .mCSB_buttonLeft{
|
||||||
background-position:-40px -40px;
|
background-position:-40px -40px;
|
||||||
}
|
}
|
||||||
.mCS-light-2>.mCSB_scrollTools .mCSB_buttonRight{
|
.mCS-light-2>.mCSB_scrollTools .mCSB_buttonRight{
|
||||||
background-position:-40px -56px;
|
background-position:-40px -56px;
|
||||||
}
|
}
|
||||||
/*dark-2*/
|
/*dark-2*/
|
||||||
.mCS-dark-2>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-dark-2>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:4px;
|
width:4px;
|
||||||
background:#000; /* rgba fallback */
|
background:#000; /* rgba fallback */
|
||||||
background:rgba(0,0,0,0.1);
|
background:rgba(0,0,0,0.1);
|
||||||
-webkit-border-radius:1px;
|
-webkit-border-radius:1px;
|
||||||
-moz-border-radius:1px;
|
-moz-border-radius:1px;
|
||||||
border-radius:1px;
|
border-radius:1px;
|
||||||
}
|
}
|
||||||
.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:4px;
|
width:4px;
|
||||||
background:#000; /* rgba fallback */
|
background:#000; /* rgba fallback */
|
||||||
background:rgba(0,0,0,0.75);
|
background:rgba(0,0,0,0.75);
|
||||||
-webkit-border-radius:1px;
|
-webkit-border-radius:1px;
|
||||||
-moz-border-radius:1px;
|
-moz-border-radius:1px;
|
||||||
border-radius:1px;
|
border-radius:1px;
|
||||||
}
|
}
|
||||||
.mCS-dark-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-dark-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:4px;
|
height:4px;
|
||||||
margin:6px 0;
|
margin:6px 0;
|
||||||
}
|
}
|
||||||
.mCS-dark-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-dark-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:4px;
|
height:4px;
|
||||||
margin:6px auto;
|
margin:6px auto;
|
||||||
}
|
}
|
||||||
.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
||||||
background:rgba(0,0,0,0.85);
|
background:rgba(0,0,0,0.85);
|
||||||
}
|
}
|
||||||
.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
||||||
.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
||||||
background:rgba(0,0,0,0.9);
|
background:rgba(0,0,0,0.9);
|
||||||
}
|
}
|
||||||
.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonUp{
|
.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonUp{
|
||||||
background-position:-112px 0;
|
background-position:-112px 0;
|
||||||
}
|
}
|
||||||
.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonDown{
|
.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonDown{
|
||||||
background-position:-112px -20px;
|
background-position:-112px -20px;
|
||||||
}
|
}
|
||||||
.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonLeft{
|
.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonLeft{
|
||||||
background-position:-120px -40px;
|
background-position:-120px -40px;
|
||||||
}
|
}
|
||||||
.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonRight{
|
.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonRight{
|
||||||
background-position:-120px -56px;
|
background-position:-120px -56px;
|
||||||
}
|
}
|
||||||
/*light-thick*/
|
/*light-thick*/
|
||||||
.mCS-light-thick>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-light-thick>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:4px;
|
width:4px;
|
||||||
background:#fff; /* rgba fallback */
|
background:#fff; /* rgba fallback */
|
||||||
background:rgba(255,255,255,0.1);
|
background:rgba(255,255,255,0.1);
|
||||||
-webkit-border-radius:2px;
|
-webkit-border-radius:2px;
|
||||||
-moz-border-radius:2px;
|
-moz-border-radius:2px;
|
||||||
border-radius:2px;
|
border-radius:2px;
|
||||||
}
|
}
|
||||||
.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:6px;
|
width:6px;
|
||||||
background:#fff; /* rgba fallback */
|
background:#fff; /* rgba fallback */
|
||||||
background:rgba(255,255,255,0.75);
|
background:rgba(255,255,255,0.75);
|
||||||
-webkit-border-radius:2px;
|
-webkit-border-radius:2px;
|
||||||
-moz-border-radius:2px;
|
-moz-border-radius:2px;
|
||||||
border-radius:2px;
|
border-radius:2px;
|
||||||
}
|
}
|
||||||
.mCS-light-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-light-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:4px;
|
height:4px;
|
||||||
margin:6px 0;
|
margin:6px 0;
|
||||||
}
|
}
|
||||||
.mCS-light-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-light-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:6px;
|
height:6px;
|
||||||
margin:5px auto;
|
margin:5px auto;
|
||||||
}
|
}
|
||||||
.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
||||||
background:rgba(255,255,255,0.85);
|
background:rgba(255,255,255,0.85);
|
||||||
}
|
}
|
||||||
.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
||||||
.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
||||||
background:rgba(255,255,255,0.9);
|
background:rgba(255,255,255,0.9);
|
||||||
}
|
}
|
||||||
.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonUp{
|
.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonUp{
|
||||||
background-position:-16px 0;
|
background-position:-16px 0;
|
||||||
}
|
}
|
||||||
.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonDown{
|
.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonDown{
|
||||||
background-position:-16px -20px;
|
background-position:-16px -20px;
|
||||||
}
|
}
|
||||||
.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonLeft{
|
.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonLeft{
|
||||||
background-position:-20px -40px;
|
background-position:-20px -40px;
|
||||||
}
|
}
|
||||||
.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonRight{
|
.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonRight{
|
||||||
background-position:-20px -56px;
|
background-position:-20px -56px;
|
||||||
}
|
}
|
||||||
/*dark-thick*/
|
/*dark-thick*/
|
||||||
.mCS-dark-thick>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-dark-thick>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:4px;
|
width:4px;
|
||||||
background:#000; /* rgba fallback */
|
background:#000; /* rgba fallback */
|
||||||
background:rgba(0,0,0,0.1);
|
background:rgba(0,0,0,0.1);
|
||||||
-webkit-border-radius:2px;
|
-webkit-border-radius:2px;
|
||||||
-moz-border-radius:2px;
|
-moz-border-radius:2px;
|
||||||
border-radius:2px;
|
border-radius:2px;
|
||||||
}
|
}
|
||||||
.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:6px;
|
width:6px;
|
||||||
background:#000; /* rgba fallback */
|
background:#000; /* rgba fallback */
|
||||||
background:rgba(0,0,0,0.75);
|
background:rgba(0,0,0,0.75);
|
||||||
-webkit-border-radius:2px;
|
-webkit-border-radius:2px;
|
||||||
-moz-border-radius:2px;
|
-moz-border-radius:2px;
|
||||||
border-radius:2px;
|
border-radius:2px;
|
||||||
}
|
}
|
||||||
.mCS-dark-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-dark-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:4px;
|
height:4px;
|
||||||
margin:6px 0;
|
margin:6px 0;
|
||||||
}
|
}
|
||||||
.mCS-dark-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-dark-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:6px;
|
height:6px;
|
||||||
margin:5px auto;
|
margin:5px auto;
|
||||||
}
|
}
|
||||||
.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
||||||
background:rgba(0,0,0,0.85);
|
background:rgba(0,0,0,0.85);
|
||||||
}
|
}
|
||||||
.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
||||||
.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
||||||
background:rgba(0,0,0,0.9);
|
background:rgba(0,0,0,0.9);
|
||||||
}
|
}
|
||||||
.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonUp{
|
.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonUp{
|
||||||
background-position:-96px 0;
|
background-position:-96px 0;
|
||||||
}
|
}
|
||||||
.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonDown{
|
.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonDown{
|
||||||
background-position:-96px -20px;
|
background-position:-96px -20px;
|
||||||
}
|
}
|
||||||
.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonLeft{
|
.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonLeft{
|
||||||
background-position:-100px -40px;
|
background-position:-100px -40px;
|
||||||
}
|
}
|
||||||
.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonRight{
|
.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonRight{
|
||||||
background-position:-100px -56px;
|
background-position:-100px -56px;
|
||||||
}
|
}
|
||||||
/*light-thin*/
|
/*light-thin*/
|
||||||
.mCS-light-thin>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-light-thin>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
background:#fff; /* rgba fallback */
|
background:#fff; /* rgba fallback */
|
||||||
background:rgba(255,255,255,0.1);
|
background:rgba(255,255,255,0.1);
|
||||||
}
|
}
|
||||||
.mCS-light-thin>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-light-thin>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:2px;
|
width:2px;
|
||||||
}
|
}
|
||||||
.mCS-light-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-light-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:100%;
|
width:100%;
|
||||||
}
|
}
|
||||||
.mCS-light-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-light-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:2px;
|
height:2px;
|
||||||
margin:7px auto;
|
margin:7px auto;
|
||||||
}
|
}
|
||||||
/*dark-thin*/
|
/*dark-thin*/
|
||||||
.mCS-dark-thin>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-dark-thin>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
background:#000; /* rgba fallback */
|
background:#000; /* rgba fallback */
|
||||||
background:rgba(0,0,0,0.15);
|
background:rgba(0,0,0,0.15);
|
||||||
}
|
}
|
||||||
.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:2px;
|
width:2px;
|
||||||
background:#000; /* rgba fallback */
|
background:#000; /* rgba fallback */
|
||||||
background:rgba(0,0,0,0.75);
|
background:rgba(0,0,0,0.75);
|
||||||
}
|
}
|
||||||
.mCS-dark-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
.mCS-dark-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{
|
||||||
width:100%;
|
width:100%;
|
||||||
}
|
}
|
||||||
.mCS-dark-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
.mCS-dark-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{
|
||||||
width:100%;
|
width:100%;
|
||||||
height:2px;
|
height:2px;
|
||||||
margin:7px auto;
|
margin:7px auto;
|
||||||
}
|
}
|
||||||
.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{
|
||||||
background:rgba(0,0,0,0.85);
|
background:rgba(0,0,0,0.85);
|
||||||
}
|
}
|
||||||
.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
|
||||||
.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{
|
||||||
background:rgba(0,0,0,0.9);
|
background:rgba(0,0,0,0.9);
|
||||||
}
|
}
|
||||||
.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonUp{
|
.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonUp{
|
||||||
background-position:-80px 0;
|
background-position:-80px 0;
|
||||||
}
|
}
|
||||||
.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonDown{
|
.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonDown{
|
||||||
background-position:-80px -20px;
|
background-position:-80px -20px;
|
||||||
}
|
}
|
||||||
.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonLeft{
|
.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonLeft{
|
||||||
background-position:-80px -40px;
|
background-position:-80px -40px;
|
||||||
}
|
}
|
||||||
.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonRight{
|
.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonRight{
|
||||||
background-position:-80px -56px;
|
background-position:-80px -56px;
|
||||||
}
|
}
|
||||||
|
|
348
app/assets/stylesheets/junto.css.erb
Normal file
|
@ -0,0 +1,348 @@
|
||||||
|
.collaborator-video {
|
||||||
|
z-index: 1;
|
||||||
|
position: absolute;
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
cursor: default;
|
||||||
|
color: #FFF;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-receive {
|
||||||
|
position: absolute;
|
||||||
|
width: 160px;
|
||||||
|
padding: 20px 20px 20px 170px;
|
||||||
|
background: #424242;
|
||||||
|
height: 110px;
|
||||||
|
border-top-left-radius: 75px;
|
||||||
|
border-bottom-left-radius: 75px;
|
||||||
|
border-top-right-radius: 2px;
|
||||||
|
border-bottom-right-radius: 2px;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-receive .video-statement {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-receive .btn-group .btn-yes {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-receive .btn-group .btn-no {
|
||||||
|
background-color: #c04f4f;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-receive .btn-group .btn-no:hover {
|
||||||
|
background-color: #A54242;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-cutoff {
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 75px;
|
||||||
|
z-index: 0;
|
||||||
|
position: relative;
|
||||||
|
-webkit-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
|
||||||
|
-moz-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
|
||||||
|
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
.collaborator-video .video-cutoff video {
|
||||||
|
height: 150px;
|
||||||
|
margin-left: -25px;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-cutoff .collaborator-video-avatar {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-o-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-audio {
|
||||||
|
position: absolute;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
top: 85%;
|
||||||
|
right: 0px;
|
||||||
|
cursor: pointer;
|
||||||
|
background: url(<%= asset_path 'audio_sprite.png' %>) no-repeat;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-audio:hover {
|
||||||
|
background-position-x: -24px;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-audio.active {
|
||||||
|
background-position-y: -24px;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-video {
|
||||||
|
position: absolute;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
top: 85%;
|
||||||
|
left: 0px;
|
||||||
|
cursor: pointer;
|
||||||
|
background: url(<%= asset_path 'camera_sprite.png' %>) no-repeat;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-video:hover {
|
||||||
|
background-position-x: -24px;
|
||||||
|
}
|
||||||
|
.collaborator-video .video-video.active {
|
||||||
|
background-position-y: -24px;
|
||||||
|
}
|
||||||
|
.collaborator-video.my-video {
|
||||||
|
left: 30px;
|
||||||
|
top: 72px;
|
||||||
|
}
|
||||||
|
.chat-box {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
z-index: 1;
|
||||||
|
width: 300px;
|
||||||
|
float: right;
|
||||||
|
height: 100%;
|
||||||
|
background: #424242;
|
||||||
|
box-shadow: 0px 0px 16px 8px rgba(0, 0, 0, 0.23), -2px 10px 10px rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
.chat-box .chat-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: -36px;
|
||||||
|
width: 36px;
|
||||||
|
height: 49px;
|
||||||
|
background: url(<%= asset_path 'junto.png' %>) no-repeat 2px 9px, url(<%= asset_path 'tray_tab.png' %>) no-repeat;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.chat-box .chat-button.active {
|
||||||
|
background: url(<%= asset_path 'junto_spinner_dark.gif' %>) no-repeat 2px 8px, url(<%= asset_path 'tray_tab.png' %>) no-repeat !important;
|
||||||
|
}
|
||||||
|
.chat-box .chat-button .chat-unread {
|
||||||
|
display: none;
|
||||||
|
background: #DAB539;
|
||||||
|
position: absolute;
|
||||||
|
top: -3px;
|
||||||
|
left: -11px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 11px;
|
||||||
|
border: 2px solid #424242;
|
||||||
|
color: #424242;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
.chat-box .junto-header {
|
||||||
|
width: 100%;
|
||||||
|
padding: 16px 8px 16px 16px;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: left;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: #000000;
|
||||||
|
color: #f5f5f5;
|
||||||
|
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
.chat-box .junto-header .cursor-toggle {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-top: -8px;
|
||||||
|
float: right;
|
||||||
|
background: url(<%= asset_path 'cursor_sprite.png' %>) no-repeat;
|
||||||
|
}
|
||||||
|
.chat-box .junto-header .cursor-toggle:hover {
|
||||||
|
background-position-x: -32px;
|
||||||
|
}
|
||||||
|
.chat-box .junto-header .cursor-toggle.active {
|
||||||
|
background-position-y: -32px;
|
||||||
|
}
|
||||||
|
.chat-box .junto-header .video-toggle {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin-right: 32px;
|
||||||
|
margin-top: -8px;
|
||||||
|
float: right;
|
||||||
|
background: url(<%= asset_path 'video_sprite.png' %>) no-repeat;
|
||||||
|
}
|
||||||
|
.chat-box .junto-header .video-toggle:hover {
|
||||||
|
background-position-x: -32px;
|
||||||
|
}
|
||||||
|
.chat-box .junto-header .video-toggle.active {
|
||||||
|
background-position-y: -32px;
|
||||||
|
}
|
||||||
|
.chat-box .participants {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 150px;
|
||||||
|
padding: 16px 0px 16px 0px;
|
||||||
|
text-align: left;
|
||||||
|
color: #f5f5f5;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.chat-box .participants .conversation-live {
|
||||||
|
display: none;
|
||||||
|
padding: 5px 10px 5px 10px;
|
||||||
|
background: #c04f4f;
|
||||||
|
margin: 5px 10px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.chat-box .participants .conversation-live .call-action {
|
||||||
|
float: right;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #EBFF00;
|
||||||
|
}
|
||||||
|
.chat-box .participants .conversation-live .leave {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.chat-box .participants.is-participating .conversation-live .leave {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.chat-box .participants.is-participating .conversation-live .join {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.chat-box .participants .participant {
|
||||||
|
width: 89%;
|
||||||
|
padding: 8px 8px 2px 8px;
|
||||||
|
color: #f5f5f5;
|
||||||
|
font-family: arial, sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 14px;
|
||||||
|
}
|
||||||
|
.chat-box .participants .participant .chat-participant-image {
|
||||||
|
width: 15%;
|
||||||
|
float: left;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #BBB;
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
.chat-box .participants .participant .chat-participant-image img {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 18px;
|
||||||
|
}
|
||||||
|
.chat-box .participants .participant .chat-participant-name {
|
||||||
|
width: 53%;
|
||||||
|
float: left;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 12px;
|
||||||
|
padding: 2px 8px 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.chat-box .participants .participant.is-self .chat-participant-invite-call,
|
||||||
|
.chat-box .participants .participant.is-self .chat-participant-invite-join {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.chat-box .participants.is-live .participant .chat-participant-invite-call {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.chat-box .participants .participant .chat-participant-invite-join {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.chat-box .participants.is-live.is-participating .participant:not(.active) .chat-participant-invite-join {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.chat-box .participants .participant .chat-participant-invite-call,
|
||||||
|
.chat-box .participants .participant .chat-participant-invite-join
|
||||||
|
{
|
||||||
|
float: right;
|
||||||
|
background: #4FC059 url(<%= asset_path 'invitepeer16.png' %>) no-repeat center center;
|
||||||
|
}
|
||||||
|
.chat-box .participants .participant.pending .chat-participant-invite-call,
|
||||||
|
.chat-box .participants .participant.pending .chat-participant-invite-join {
|
||||||
|
background: #dab539 url(<%= asset_path 'ellipsis.gif' %>) no-repeat center center;
|
||||||
|
}
|
||||||
|
.chat-box .participants .participant .chat-participant-participating {
|
||||||
|
float: right;
|
||||||
|
display: none;
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
.chat-box .participants .participant .chat-participant-participating .green-dot {
|
||||||
|
background: #4fc059;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
.chat-box .participants .participant.active .chat-participant-participating {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.chat-box .chat-header {
|
||||||
|
width: 100%;
|
||||||
|
padding: 16px 8px 16px 16px;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: left;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: #000000;
|
||||||
|
color: #f5f5f5;
|
||||||
|
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
.chat-box .chat-header .sound-toggle {
|
||||||
|
display: none;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
margin-right: 32px;
|
||||||
|
margin-top: -2px;
|
||||||
|
float: right;
|
||||||
|
background: url(<%= asset_path 'sound_sprite.png' %>) no-repeat;
|
||||||
|
}
|
||||||
|
.chat-box .chat-header .sound-toggle:hover {
|
||||||
|
background-position-x: -24px;
|
||||||
|
}
|
||||||
|
.chat-box .chat-header .sound-toggle.active {
|
||||||
|
background-position-y: -24px;
|
||||||
|
}
|
||||||
|
.chat-box .chat-input {
|
||||||
|
min-height: 80px;
|
||||||
|
width: 94%;
|
||||||
|
padding: 8px 3% 8px 3%;
|
||||||
|
font-size: 13px;
|
||||||
|
outline: none;
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
.chat-box .chat-messages {
|
||||||
|
width: 100%;
|
||||||
|
padding: 16px 0px 0px 0px;
|
||||||
|
overflow-y: auto;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
.chat-box .chat-messages .chat-message {
|
||||||
|
width: 89%;
|
||||||
|
padding: 8px 8px 2px 8px;
|
||||||
|
color: #f5f5f5;
|
||||||
|
font-family: arial, sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 14px;
|
||||||
|
}
|
||||||
|
.chat-box .chat-messages .chat-message a:link {
|
||||||
|
color: #4fb5c0;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.chat-box .chat-messages .chat-message a:visited {
|
||||||
|
color: #aea9fd;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.chat-box .chat-messages .chat-message a:hover {
|
||||||
|
color: #dab539;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.chat-box .chat-messages .chat-message .chat-message-user {
|
||||||
|
width: 15%;
|
||||||
|
float: left;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #BBB;
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
.chat-box .chat-messages .chat-message .chat-message-user img {
|
||||||
|
border: 2px solid #424242;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 18px;
|
||||||
|
}
|
||||||
|
.chat-box .chat-messages .chat-message .chat-message-text {
|
||||||
|
width: 73%;
|
||||||
|
float: left;
|
||||||
|
margin-top: 12px;
|
||||||
|
padding: 2px 8px 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.chat-box .chat-messages .chat-message .chat-message-time {
|
||||||
|
float: right;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #757575;
|
||||||
|
}
|
3
app/controllers/api/mappings_controller.rb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
class Api::MappingsController < API::RestfulController
|
||||||
|
|
||||||
|
end
|
3
app/controllers/api/maps_controller.rb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
class Api::MapsController < API::RestfulController
|
||||||
|
|
||||||
|
end
|
53
app/controllers/api/restful_controller.rb
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
class API::RestfulController < ActionController::Base
|
||||||
|
include Pundit
|
||||||
|
include PunditExtra
|
||||||
|
|
||||||
|
snorlax_used_rest!
|
||||||
|
|
||||||
|
load_and_authorize_resource only: [:show, :update, :destroy]
|
||||||
|
|
||||||
|
def create
|
||||||
|
instantiate_resource
|
||||||
|
resource.user = current_user
|
||||||
|
authorize resource
|
||||||
|
create_action
|
||||||
|
respond_with_resource
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def resource_serializer
|
||||||
|
"new_#{resource_name}_serializer".camelize.constantize
|
||||||
|
end
|
||||||
|
|
||||||
|
def accessible_records
|
||||||
|
if current_user
|
||||||
|
visible_records
|
||||||
|
else
|
||||||
|
public_records
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_user
|
||||||
|
super || token_user || doorkeeper_user || nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def token_user
|
||||||
|
token = params[:access_token]
|
||||||
|
access_token = Token.find_by_token(token)
|
||||||
|
if access_token
|
||||||
|
@token_user ||= access_token.user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def doorkeeper_user
|
||||||
|
return unless doorkeeper_token.present?
|
||||||
|
doorkeeper_render_error unless valid_doorkeeper_token?
|
||||||
|
@doorkeeper_user ||= User.find(doorkeeper_token.resource_owner_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def permitted_params
|
||||||
|
@permitted_params ||= PermittedParams.new(params)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
3
app/controllers/api/synapses_controller.rb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
class Api::SynapsesController < API::RestfulController
|
||||||
|
|
||||||
|
end
|
19
app/controllers/api/tokens_controller.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
class Api::TokensController < API::RestfulController
|
||||||
|
|
||||||
|
def my_tokens
|
||||||
|
raise Pundit::NotAuthorizedError.new unless current_user
|
||||||
|
instantiate_collection page_collection: false, timeframe_collection: false
|
||||||
|
respond_with_collection
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def resource_serializer
|
||||||
|
"#{resource_name}_serializer".camelize.constantize
|
||||||
|
end
|
||||||
|
|
||||||
|
def visible_records
|
||||||
|
current_user.tokens
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
3
app/controllers/api/topics_controller.rb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
class Api::TopicsController < API::RestfulController
|
||||||
|
|
||||||
|
end
|
|
@ -1,23 +1,25 @@
|
||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
|
include ApplicationHelper
|
||||||
|
include Pundit
|
||||||
|
include PunditExtra
|
||||||
|
rescue_from Pundit::NotAuthorizedError, with: :handle_unauthorized
|
||||||
protect_from_forgery
|
protect_from_forgery
|
||||||
|
|
||||||
before_filter :get_invite_link
|
after_action :allow_embedding
|
||||||
|
|
||||||
|
def default_serializer_options
|
||||||
|
{ root: false }
|
||||||
|
end
|
||||||
|
|
||||||
# this is for global login
|
# this is for global login
|
||||||
include ContentHelper
|
include ContentHelper
|
||||||
|
|
||||||
helper_method :user
|
helper_method :user
|
||||||
helper_method :authenticated?
|
helper_method :authenticated?
|
||||||
helper_method :admin?
|
helper_method :admin?
|
||||||
|
|
||||||
def after_sign_in_path_for(resource)
|
def after_sign_in_path_for(resource)
|
||||||
unsafe_uri = request.env["REQUEST_URI"]
|
sign_in_url = url_for(:action => 'new', :controller => 'sessions', :only_path => false, :protocol => 'https')
|
||||||
if unsafe_uri.starts_with?('http') && !unsafe_uri.starts_with?('https')
|
|
||||||
protocol = 'http'
|
|
||||||
else
|
|
||||||
protocol = 'https'
|
|
||||||
end
|
|
||||||
sign_in_url = url_for(:action => 'new', :controller => 'sessions', :only_path => false, :protocol => protocol)
|
|
||||||
|
|
||||||
if request.referer == sign_in_url
|
if request.referer == sign_in_url
|
||||||
super
|
super
|
||||||
|
@ -27,7 +29,11 @@ class ApplicationController < ActionController::Base
|
||||||
stored_location_for(resource) || request.referer || root_path
|
stored_location_for(resource) || request.referer || root_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def handle_unauthorized
|
||||||
|
head :forbidden # TODO make this better
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def require_no_user
|
def require_no_user
|
||||||
|
@ -36,37 +42,37 @@ private
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_user
|
def require_user
|
||||||
unless authenticated?
|
unless authenticated?
|
||||||
redirect_to new_user_session_path, notice: "You must be logged in."
|
redirect_to new_user_session_path, notice: "You must be logged in."
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_admin
|
def require_admin
|
||||||
unless authenticated? && admin?
|
unless authenticated? && admin?
|
||||||
redirect_to root_url, notice: "You need to be an admin for that."
|
redirect_to root_url, notice: "You need to be an admin for that."
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def user
|
def user
|
||||||
current_user
|
current_user
|
||||||
end
|
end
|
||||||
|
|
||||||
def authenticated?
|
def authenticated?
|
||||||
current_user
|
current_user
|
||||||
end
|
end
|
||||||
|
|
||||||
def admin?
|
def admin?
|
||||||
authenticated? && current_user.admin
|
authenticated? && current_user.admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_invite_link
|
def allow_embedding
|
||||||
unsafe_uri = request.env["REQUEST_URI"] || 'https://metamaps.cc'
|
#allow all
|
||||||
valid_url = /^https?:\/\/([\w\.-]+)(:\d{1,5})?\/?$/
|
response.headers.except! 'X-Frame-Options'
|
||||||
safe_uri = (unsafe_uri.match(valid_url)) ? unsafe_uri : '//metamaps.cc/'
|
# or allow a whitelist
|
||||||
@invite_link = "#{safe_uri}join" + (current_user ? "?code=#{current_user.code}" : "")
|
# response.headers['X-Frame-Options'] = 'ALLOW-FROM http://blog.metamaps.cc'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,20 +3,20 @@ class MainController < ApplicationController
|
||||||
include MapsHelper
|
include MapsHelper
|
||||||
include UsersHelper
|
include UsersHelper
|
||||||
include SynapsesHelper
|
include SynapsesHelper
|
||||||
|
|
||||||
|
after_action :verify_policy_scoped
|
||||||
|
|
||||||
respond_to :html, :json
|
respond_to :html, :json
|
||||||
|
|
||||||
# home page
|
# home page
|
||||||
def home
|
def home
|
||||||
@current = current_user
|
@maps = policy_scope(Map).order("updated_at DESC").page(1).per(20)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html {
|
format.html {
|
||||||
if authenticated?
|
if not authenticated?
|
||||||
@maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(1).per(20)
|
render 'main/home'
|
||||||
respond_with(@maps, @current)
|
|
||||||
else
|
else
|
||||||
respond_with(@current)
|
render 'maps/activemaps'
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -59,69 +59,35 @@ class MainController < ApplicationController
|
||||||
filterByMetacode = m
|
filterByMetacode = m
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
search = '%' + term.downcase + '%'
|
||||||
|
builder = policy_scope(Topic)
|
||||||
|
|
||||||
if filterByMetacode
|
if filterByMetacode
|
||||||
if term == ""
|
if term == ""
|
||||||
@topics = []
|
builder = builder.none
|
||||||
else
|
else
|
||||||
search = term.downcase + '%'
|
builder = builder.where('LOWER("name") like ? OR
|
||||||
|
LOWER("desc") like ? OR
|
||||||
if user
|
LOWER("link") like ?', search, search, search)
|
||||||
@topics = Set.new(Topic.where('LOWER("name") like ?', search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"'))
|
builder = builder.where(metacode_id: filterByMetacode.id)
|
||||||
@topics2 = Set.new(Topic.where('LOWER("name") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"'))
|
|
||||||
@topics3 = Set.new(Topic.where('LOWER("desc") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"'))
|
|
||||||
@topics4 = Set.new(Topic.where('LOWER("link") like ?', '%' + search).where('metacode_id = ? AND user_id = ?', filterByMetacode.id, user).order('"name"'))
|
|
||||||
else
|
|
||||||
@topics = Set.new(Topic.where('LOWER("name") like ?', search).where('metacode_id = ?', filterByMetacode.id).order('"name"'))
|
|
||||||
@topics2 = Set.new(Topic.where('LOWER("name") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"'))
|
|
||||||
@topics3 = Set.new(Topic.where('LOWER("desc") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"'))
|
|
||||||
@topics4 = Set.new(Topic.where('LOWER("link") like ?', '%' + search).where('metacode_id = ?', filterByMetacode.id).order('"name"'))
|
|
||||||
end
|
|
||||||
|
|
||||||
#get unique elements only through the magic of Sets
|
|
||||||
@topics = (@topics + @topics2 + @topics3 + @topics4).to_a
|
|
||||||
end
|
end
|
||||||
elsif desc
|
elsif desc
|
||||||
search = '%' + term.downcase + '%'
|
builder = builder.where('LOWER("desc") like ?', search)
|
||||||
if !user
|
|
||||||
@topics = Topic.where('LOWER("desc") like ?', search).order('"name"')
|
|
||||||
elsif user
|
|
||||||
@topics = Topic.where('LOWER("desc") like ?', search).where('user_id = ?', user).order('"name"')
|
|
||||||
end
|
|
||||||
elsif link
|
elsif link
|
||||||
search = '%' + term.downcase + '%'
|
builder = builder.where('LOWER("link") like ?', search)
|
||||||
if !user
|
|
||||||
@topics = Topic.where('LOWER("link") like ?', search).order('"name"')
|
|
||||||
elsif user
|
|
||||||
@topics = Topic.where('LOWER("link") like ?', search).where('user_id = ?', user).order('"name"')
|
|
||||||
end
|
|
||||||
else #regular case, just search the name
|
else #regular case, just search the name
|
||||||
search = term.downcase + '%'
|
builder = builder.where('LOWER("name") like ? OR
|
||||||
if !user
|
LOWER("desc") like ? OR
|
||||||
@topics = Topic.where('LOWER("name") like ?', search).order('"name"')
|
LOWER("link") like ?', search, search, search)
|
||||||
@topics2 = Topic.where('LOWER("name") like ?', '%' + search).order('"name"')
|
|
||||||
@topics3 = Topic.where('LOWER("desc") like ?', '%' + search).order('"name"')
|
|
||||||
@topics4 = Topic.where('LOWER("link") like ?', '%' + search).order('"name"')
|
|
||||||
@topics = @topics + (@topics2 - @topics)
|
|
||||||
@topics = @topics + (@topics3 - @topics)
|
|
||||||
@topics = @topics + (@topics4 - @topics)
|
|
||||||
elsif user
|
|
||||||
@topics = Topic.where('LOWER("name") like ?', search).where('user_id = ?', user).order('"name"')
|
|
||||||
@topics2 = Topic.where('LOWER("name") like ?', '%' + search).where('user_id = ?', user).order('"name"')
|
|
||||||
@topics3 = Topic.where('LOWER("desc") like ?', '%' + search).where('user_id = ?', user).order('"name"')
|
|
||||||
@topics4 = Topic.where('LOWER("link") like ?', '%' + search).where('user_id = ?', user).order('"name"')
|
|
||||||
@topics = @topics + (@topics2 - @topics)
|
|
||||||
@topics = @topics + (@topics3 - @topics)
|
|
||||||
@topics = @topics + (@topics4 - @topics)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
builder = builder.where(user: user) if user
|
||||||
|
@topics = builder.order(:name)
|
||||||
else
|
else
|
||||||
@topics = []
|
@topics = []
|
||||||
end
|
end
|
||||||
|
|
||||||
#read this next line as 'delete a topic if its private and you're either 1. logged out or 2. logged in but not the topic creator
|
|
||||||
@topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) }
|
|
||||||
|
|
||||||
render json: autocomplete_array_json(@topics)
|
render json: autocomplete_array_json(@topics)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -141,21 +107,21 @@ class MainController < ApplicationController
|
||||||
term = term[5..-1]
|
term = term[5..-1]
|
||||||
desc = true
|
desc = true
|
||||||
end
|
end
|
||||||
|
|
||||||
search = '%' + term.downcase + '%'
|
search = '%' + term.downcase + '%'
|
||||||
query = desc ? 'LOWER("desc") like ?' : 'LOWER("name") like ?'
|
builder = policy_scope(Map)
|
||||||
if !user
|
|
||||||
# !connor why is the limit 5 done here and not above? also, why not limit after sorting alphabetically?
|
if desc
|
||||||
@maps = Map.where(query, search).limit(5).order('"name"')
|
builder = builder.where('LOWER("desc") like ?', search)
|
||||||
elsif user
|
else
|
||||||
@maps = Map.where(query, search).where('user_id = ?', user).order('"name"')
|
builder = builder.where('LOWER("name") like ?', search)
|
||||||
end
|
end
|
||||||
|
builder = builder.where(user: user) if user
|
||||||
|
@maps = builder.order(:name)
|
||||||
else
|
else
|
||||||
@maps = []
|
@maps = []
|
||||||
end
|
end
|
||||||
|
|
||||||
#read this next line as 'delete a map if its private and you're either 1. logged out or 2. logged in but not the map creator
|
|
||||||
@maps.to_a.delete_if {|m| m.permission == "private" && (!authenticated? || (authenticated? && current_user.id != m.user_id)) }
|
|
||||||
|
|
||||||
render json: autocomplete_map_array_json(@maps)
|
render json: autocomplete_map_array_json(@maps)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -166,7 +132,10 @@ class MainController < ApplicationController
|
||||||
|
|
||||||
#remove "mapper:" if appended at beginning
|
#remove "mapper:" if appended at beginning
|
||||||
term = term[7..-1] if term.downcase[0..6] == "mapper:"
|
term = term[7..-1] if term.downcase[0..6] == "mapper:"
|
||||||
@mappers = User.where('LOWER("name") like ?', term.downcase + '%').order('"name"')
|
search = term.downcase + '%'
|
||||||
|
builder = policy_scope(User) # TODO do I need to policy scope? I guess yes to verify_policy_scoped
|
||||||
|
builder = builder.where('LOWER("name") like ?', search)
|
||||||
|
@mappers = builder.order(:name)
|
||||||
else
|
else
|
||||||
@mappers = []
|
@mappers = []
|
||||||
end
|
end
|
||||||
|
@ -181,7 +150,7 @@ class MainController < ApplicationController
|
||||||
topic2id = params[:topic2id]
|
topic2id = params[:topic2id]
|
||||||
|
|
||||||
if term && !term.empty?
|
if term && !term.empty?
|
||||||
@synapses = Synapse.where('LOWER("desc") like ?', '%' + term.downcase + '%').order('"desc"')
|
@synapses = policy_scope(Synapse).where('LOWER("desc") like ?', '%' + term.downcase + '%').order('"desc"')
|
||||||
|
|
||||||
# remove any duplicate synapse types that just differ by
|
# remove any duplicate synapse types that just differ by
|
||||||
# leading or trailing whitespaces
|
# leading or trailing whitespaces
|
||||||
|
@ -195,23 +164,18 @@ class MainController < ApplicationController
|
||||||
boolean = true
|
boolean = true
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
#limit to 5 results
|
|
||||||
@synapses = @synapses.slice(0,5)
|
|
||||||
elsif topic1id && !topic1id.empty?
|
elsif topic1id && !topic1id.empty?
|
||||||
@one = Synapse.where('node1_id = ? AND node2_id = ?', topic1id, topic2id)
|
@one = policy_scope(Synapse).where('node1_id = ? AND node2_id = ?', topic1id, topic2id)
|
||||||
@two = Synapse.where('node2_id = ? AND node1_id = ?', topic1id, topic2id)
|
@two = policy_scope(Synapse).where('node2_id = ? AND node1_id = ?', topic1id, topic2id)
|
||||||
@synapses = @one + @two
|
@synapses = @one + @two
|
||||||
@synapses.sort! {|s1,s2| s1.desc <=> s2.desc }.to_a
|
@synapses.sort! {|s1,s2| s1.desc <=> s2.desc }.to_a
|
||||||
|
|
||||||
#permissions
|
|
||||||
@synapses.delete_if {|s| s.permission == "private" && !authenticated? }
|
|
||||||
@synapses.delete_if {|s| s.permission == "private" && authenticated? && current_user.id != s.user_id }
|
|
||||||
else
|
else
|
||||||
@synapses = []
|
@synapses = []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#limit to 5 results
|
||||||
|
@synapses = @synapses.slice(0,5)
|
||||||
|
|
||||||
render json: autocomplete_synapse_array_json(@synapses)
|
render json: autocomplete_synapse_array_json(@synapses)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
class MappingsController < ApplicationController
|
class MappingsController < ApplicationController
|
||||||
|
|
||||||
before_filter :require_user, only: [:create, :update, :destroy]
|
before_action :require_user, only: [:create, :update, :destroy]
|
||||||
|
after_action :verify_authorized, except: :index
|
||||||
|
after_action :verify_policy_scoped, only: :index
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
# GET /mappings/1.json
|
# GET /mappings/1.json
|
||||||
def show
|
def show
|
||||||
@mapping = Mapping.find(params[:id])
|
@mapping = Mapping.find(params[:id])
|
||||||
|
authorize @mapping
|
||||||
|
|
||||||
render json: @mapping
|
render json: @mapping
|
||||||
end
|
end
|
||||||
|
@ -14,11 +17,12 @@ class MappingsController < ApplicationController
|
||||||
# POST /mappings.json
|
# POST /mappings.json
|
||||||
def create
|
def create
|
||||||
@mapping = Mapping.new(mapping_params)
|
@mapping = Mapping.new(mapping_params)
|
||||||
|
authorize @mapping
|
||||||
@mapping.map.touch(:updated_at)
|
@mapping.user = current_user
|
||||||
|
|
||||||
if @mapping.save
|
if @mapping.save
|
||||||
render json: @mapping, status: :created
|
render json: @mapping, status: :created
|
||||||
|
Events::NewMapping.publish!(@mapping, current_user)
|
||||||
else
|
else
|
||||||
render json: @mapping.errors, status: :unprocessable_entity
|
render json: @mapping.errors, status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
@ -27,8 +31,7 @@ class MappingsController < ApplicationController
|
||||||
# PUT /mappings/1.json
|
# PUT /mappings/1.json
|
||||||
def update
|
def update
|
||||||
@mapping = Mapping.find(params[:id])
|
@mapping = Mapping.find(params[:id])
|
||||||
|
authorize @mapping
|
||||||
@mapping.map.touch(:updated_at)
|
|
||||||
|
|
||||||
if @mapping.update_attributes(mapping_params)
|
if @mapping.update_attributes(mapping_params)
|
||||||
head :no_content
|
head :no_content
|
||||||
|
@ -40,18 +43,16 @@ class MappingsController < ApplicationController
|
||||||
# DELETE /mappings/1.json
|
# DELETE /mappings/1.json
|
||||||
def destroy
|
def destroy
|
||||||
@mapping = Mapping.find(params[:id])
|
@mapping = Mapping.find(params[:id])
|
||||||
@map = @mapping.map
|
authorize @mapping
|
||||||
|
|
||||||
@mapping.destroy
|
@mapping.destroy
|
||||||
|
|
||||||
@map.touch(:updated_at)
|
|
||||||
|
|
||||||
head :no_content
|
head :no_content
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
# Never trust parameters from the scary internet, only allow the white list through.
|
# Never trust parameters from the scary internet, only allow the white list through.
|
||||||
def mapping_params
|
def mapping_params
|
||||||
params.require(:mapping).permit(:id, :xloc, :yloc, :mappable_id, :mappable_type, :map_id, :user_id)
|
params.require(:mapping).permit(:id, :xloc, :yloc, :mappable_id, :mappable_type, :map_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,106 +1,119 @@
|
||||||
class MapsController < ApplicationController
|
class MapsController < ApplicationController
|
||||||
|
|
||||||
before_filter :require_user, only: [:create, :update, :screenshot, :destroy]
|
before_action :require_user, only: [:create, :update, :screenshot, :destroy]
|
||||||
|
after_action :verify_authorized, except: [:activemaps, :featuredmaps, :mymaps, :usermaps]
|
||||||
|
after_action :verify_policy_scoped, only: [:activemaps, :featuredmaps, :mymaps, :usermaps]
|
||||||
|
|
||||||
respond_to :html, :json
|
respond_to :html, :json, :csv
|
||||||
|
|
||||||
autocomplete :map, :name, :full => true, :extra_data => [:user_id]
|
autocomplete :map, :name, :full => true, :extra_data => [:user_id]
|
||||||
|
|
||||||
# GET /explore/active
|
# GET /explore/active
|
||||||
# GET /explore/featured
|
def activemaps
|
||||||
# GET /explore/mapper/:id
|
page = params[:page].present? ? params[:page] : 1
|
||||||
def index
|
@maps = policy_scope(Map).order("updated_at DESC")
|
||||||
|
.page(page).per(20)
|
||||||
if request.path == "/explore"
|
|
||||||
redirect_to activemaps_url and return
|
|
||||||
end
|
|
||||||
|
|
||||||
@current = current_user
|
|
||||||
@user = nil
|
|
||||||
@maps = []
|
|
||||||
@mapperId = nil
|
|
||||||
|
|
||||||
if !params[:page]
|
|
||||||
page = 1
|
|
||||||
else
|
|
||||||
page = params[:page]
|
|
||||||
end
|
|
||||||
|
|
||||||
if request.path.index("/explore/active") != nil
|
|
||||||
@maps = Map.where("maps.permission != ?", "private").order("updated_at DESC").page(page).per(20)
|
|
||||||
@request = "active"
|
|
||||||
|
|
||||||
elsif request.path.index("/explore/featured") != nil
|
|
||||||
@maps = Map.where("maps.featured = ? AND maps.permission != ?", true, "private").order("updated_at DESC").page(page).per(20)
|
|
||||||
@request = "featured"
|
|
||||||
|
|
||||||
elsif request.path.index('/explore/mine') != nil # looking for maps by me
|
|
||||||
if !authenticated?
|
|
||||||
redirect_to activemaps_url and return
|
|
||||||
end
|
|
||||||
# don't need to exclude private maps because they all belong to you
|
|
||||||
@maps = Map.where("maps.user_id = ?", @current.id).order("updated_at DESC").page(page).per(20)
|
|
||||||
@request = "you"
|
|
||||||
|
|
||||||
elsif request.path.index('/explore/mapper/') != nil # looking for maps by a mapper
|
|
||||||
@user = User.find(params[:id])
|
|
||||||
@maps = Map.where("maps.user_id = ? AND maps.permission != ?", @user.id, "private").order("updated_at DESC").page(page).per(20)
|
|
||||||
@request = "mapper"
|
|
||||||
end
|
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html {
|
format.html {
|
||||||
if @request == "active" && authenticated?
|
# root url => main/home. main/home renders maps/activemaps view.
|
||||||
redirect_to root_url and return
|
redirect_to root_url and return if authenticated?
|
||||||
end
|
respond_with(@maps, @user)
|
||||||
respond_with(@maps, @request, @user)
|
|
||||||
}
|
}
|
||||||
format.json { render json: @maps }
|
format.json { render json: @maps }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# GET /explore/featured
|
||||||
|
def featuredmaps
|
||||||
|
page = params[:page].present? ? params[:page] : 1
|
||||||
|
@maps = policy_scope(
|
||||||
|
Map.where("maps.featured = ? AND maps.permission != ?",
|
||||||
|
true, "private")
|
||||||
|
).order("updated_at DESC").page(page).per(20)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { respond_with(@maps, @user) }
|
||||||
|
format.json { render json: @maps }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /explore/mine
|
||||||
|
def mymaps
|
||||||
|
return redirect_to activemaps_url if !authenticated?
|
||||||
|
|
||||||
|
page = params[:page].present? ? params[:page] : 1
|
||||||
|
@maps = policy_scope(
|
||||||
|
Map.where("maps.user_id = ?", current_user.id)
|
||||||
|
).order("updated_at DESC").page(page).per(20)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { respond_with(@maps, @user) }
|
||||||
|
format.json { render json: @maps }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /explore/mapper/:id
|
||||||
|
def usermaps
|
||||||
|
page = params[:page].present? ? params[:page] : 1
|
||||||
|
@user = User.find(params[:id])
|
||||||
|
@maps = policy_scope(Map.where(user: @user))
|
||||||
|
.order("updated_at DESC").page(page).per(20)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { respond_with(@maps, @user) }
|
||||||
|
format.json { render json: @maps }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# GET maps/:id
|
# GET maps/:id
|
||||||
def show
|
def show
|
||||||
|
@map = Map.find(params[:id])
|
||||||
@current = current_user
|
authorize @map
|
||||||
@map = Map.find(params[:id]).authorize_to_show(@current)
|
|
||||||
|
|
||||||
if not @map
|
|
||||||
redirect_to root_url, notice: "Access denied. That map is private." and return
|
|
||||||
end
|
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html {
|
format.html {
|
||||||
@allmappers = @map.contributors
|
@allmappers = @map.contributors
|
||||||
@alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) }
|
@alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) }
|
||||||
@allsynapses = @map.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
|
@allsynapses = @map.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && current_user.id != s.user_id)) }
|
||||||
@allmappings = @map.mappings.to_a.delete_if {|m|
|
@allmappings = @map.mappings.to_a.delete_if {|m|
|
||||||
object = m.mappable
|
object = m.mappable
|
||||||
!object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id)))
|
!object || (object.permission == "private" && (!authenticated? || (authenticated? && current_user.id != object.user_id)))
|
||||||
}
|
}
|
||||||
|
@allmessages = @map.messages.sort_by(&:created_at)
|
||||||
|
|
||||||
respond_with(@allmappers, @allmappings, @allsynapses, @alltopics, @map)
|
respond_with(@allmappers, @allmappings, @allsynapses, @alltopics, @allmessages, @map)
|
||||||
}
|
}
|
||||||
format.json { render json: @map }
|
format.json { render json: @map }
|
||||||
|
format.csv { redirect_to action: :export, format: :csv }
|
||||||
|
format.xls { redirect_to action: :export, format: :xls }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# GET maps/:id/export
|
||||||
|
def export
|
||||||
|
map = Map.find(params[:id])
|
||||||
|
authorize map
|
||||||
|
exporter = MapExportService.new(current_user, map)
|
||||||
|
respond_to do |format|
|
||||||
|
format.json { render json: exporter.json }
|
||||||
|
format.csv { send_data exporter.csv }
|
||||||
|
format.xls { @spreadsheet = exporter.xls }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# GET maps/:id/contains
|
# GET maps/:id/contains
|
||||||
def contains
|
def contains
|
||||||
|
@map = Map.find(params[:id])
|
||||||
@current = current_user
|
authorize @map
|
||||||
@map = Map.find(params[:id]).authorize_to_show(@current)
|
|
||||||
|
|
||||||
if not @map
|
|
||||||
redirect_to root_url, notice: "Access denied. That map is private." and return
|
|
||||||
end
|
|
||||||
|
|
||||||
@allmappers = @map.contributors
|
@allmappers = @map.contributors
|
||||||
@alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) }
|
@alltopics = @map.topics.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && current_user.id != t.user_id)) }
|
||||||
@allsynapses = @map.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
|
@allsynapses = @map.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && current_user.id != s.user_id)) }
|
||||||
@allmappings = @map.mappings.to_a.delete_if {|m|
|
@allmappings = @map.mappings.to_a.delete_if {|m|
|
||||||
object = m.mappable
|
object = m.mappable
|
||||||
!object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id)))
|
!object || (object.permission == "private" && (!authenticated? || (authenticated? && current_user.id != object.user_id)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@json = Hash.new()
|
@json = Hash.new()
|
||||||
|
@ -109,6 +122,7 @@ class MapsController < ApplicationController
|
||||||
@json['synapses'] = @allsynapses
|
@json['synapses'] = @allsynapses
|
||||||
@json['mappings'] = @allmappings
|
@json['mappings'] = @allmappings
|
||||||
@json['mappers'] = @allmappers
|
@json['mappers'] = @allmappers
|
||||||
|
@json['messages'] = @map.messages.sort_by(&:created_at)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json { render json: @json }
|
format.json { render json: @json }
|
||||||
|
@ -117,60 +131,66 @@ class MapsController < ApplicationController
|
||||||
|
|
||||||
# POST maps
|
# POST maps
|
||||||
def create
|
def create
|
||||||
|
|
||||||
@user = current_user
|
@user = current_user
|
||||||
@map = Map.new()
|
@map = Map.new()
|
||||||
@map.name = params[:name]
|
@map.name = params[:name]
|
||||||
@map.desc = params[:desc]
|
@map.desc = params[:desc]
|
||||||
@map.permission = params[:permission]
|
@map.permission = params[:permission]
|
||||||
@map.user = @user
|
@map.user = @user
|
||||||
@map.arranged = false
|
@map.arranged = false
|
||||||
@map.save
|
|
||||||
|
|
||||||
if params[:topicsToMap]
|
if params[:topicsToMap]
|
||||||
@all = params[:topicsToMap]
|
@all = params[:topicsToMap]
|
||||||
@all = @all.split(',')
|
@all = @all.split(',')
|
||||||
@all.each do |topic|
|
@all.each do |topic|
|
||||||
topic = topic.split('/')
|
topic = topic.split('/')
|
||||||
@mapping = Mapping.new()
|
mapping = Mapping.new()
|
||||||
@mapping.user = @user
|
mapping.user = @user
|
||||||
@mapping.map = @map
|
mapping.mappable = Topic.find(topic[0])
|
||||||
@mapping.mappable = Topic.find(topic[0])
|
mapping.xloc = topic[1]
|
||||||
@mapping.xloc = topic[1]
|
mapping.yloc = topic[2]
|
||||||
@mapping.yloc = topic[2]
|
@map.topicmappings << mapping
|
||||||
@mapping.save
|
authorize mapping, :create
|
||||||
|
mapping.save
|
||||||
end
|
end
|
||||||
|
|
||||||
if params[:synapsesToMap]
|
if params[:synapsesToMap]
|
||||||
@synAll = params[:synapsesToMap]
|
@synAll = params[:synapsesToMap]
|
||||||
@synAll = @synAll.split(',')
|
@synAll = @synAll.split(',')
|
||||||
@synAll.each do |synapse_id|
|
@synAll.each do |synapse_id|
|
||||||
@mapping = Mapping.new()
|
mapping = Mapping.new()
|
||||||
@mapping.user = @user
|
mapping.user = @user
|
||||||
@mapping.map = @map
|
mapping.map = @map
|
||||||
@mapping.mappable = Synapse.find(synapse_id)
|
mapping.mappable = Synapse.find(synapse_id)
|
||||||
@mapping.save
|
@map.synapsemappings << mapping
|
||||||
|
authorize mapping, :create
|
||||||
|
mapping.save
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@map.arranged = true
|
@map.arranged = true
|
||||||
@map.save
|
|
||||||
end
|
end
|
||||||
|
|
||||||
respond_to do |format|
|
authorize @map
|
||||||
|
|
||||||
|
if @map.save
|
||||||
|
respond_to do |format|
|
||||||
format.json { render :json => @map }
|
format.json { render :json => @map }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
respond_to do |format|
|
||||||
|
format.json { render :json => "invalid params" }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# PUT maps/:id
|
# PUT maps/:id
|
||||||
def update
|
def update
|
||||||
@current = current_user
|
@map = Map.find(params[:id])
|
||||||
@map = Map.find(params[:id]).authorize_to_edit(@current)
|
authorize @map
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if !@map
|
if @map.update_attributes(map_params)
|
||||||
format.json { render json: "unauthorized" }
|
|
||||||
elsif @map.update_attributes(map_params)
|
|
||||||
format.json { head :no_content }
|
format.json { head :no_content }
|
||||||
else
|
else
|
||||||
format.json { render json: @map.errors, status: :unprocessable_entity }
|
format.json { render json: @map.errors, status: :unprocessable_entity }
|
||||||
|
@ -180,51 +200,42 @@ class MapsController < ApplicationController
|
||||||
|
|
||||||
# POST maps/:id/upload_screenshot
|
# POST maps/:id/upload_screenshot
|
||||||
def screenshot
|
def screenshot
|
||||||
@current = current_user
|
@map = Map.find(params[:id])
|
||||||
@map = Map.find(params[:id]).authorize_to_edit(@current)
|
authorize @map
|
||||||
|
|
||||||
if @map
|
png = Base64.decode64(params[:encoded_image]['data:image/png;base64,'.length .. -1])
|
||||||
png = Base64.decode64(params[:encoded_image]['data:image/png;base64,'.length .. -1])
|
StringIO.open(png) do |data|
|
||||||
StringIO.open(png) do |data|
|
data.class.class_eval { attr_accessor :original_filename, :content_type }
|
||||||
data.class.class_eval { attr_accessor :original_filename, :content_type }
|
data.original_filename = "map-" + @map.id.to_s + "-screenshot.png"
|
||||||
data.original_filename = "map-" + @map.id.to_s + "-screenshot.png"
|
data.content_type = "image/png"
|
||||||
data.content_type = "image/png"
|
@map.screenshot = data
|
||||||
@map.screenshot = data
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if @map.save
|
if @map.save
|
||||||
render :json => {:message => "Successfully uploaded the map screenshot."}
|
render :json => {:message => "Successfully uploaded the map screenshot."}
|
||||||
else
|
else
|
||||||
render :json => {:message => "Failed to upload image."}
|
render :json => {:message => "Failed to upload image."}
|
||||||
end
|
end
|
||||||
else
|
|
||||||
render :json => {:message => "Unauthorized to set map screenshot."}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# DELETE maps/:id
|
# DELETE maps/:id
|
||||||
def destroy
|
def destroy
|
||||||
@current = current_user
|
@map = Map.find(params[:id])
|
||||||
|
authorize @map
|
||||||
|
|
||||||
@map = Map.find(params[:id]).authorize_to_delete(@current)
|
@map.delete
|
||||||
|
|
||||||
@map.delete if @map
|
respond_to do |format|
|
||||||
|
format.json do
|
||||||
respond_to do |format|
|
head :no_content
|
||||||
format.json {
|
|
||||||
if @map
|
|
||||||
render json: "success"
|
|
||||||
else
|
|
||||||
render json: "unauthorized"
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Never trust parameters from the scary internet, only allow the white list through.
|
# Never trust parameters from the scary internet, only allow the white list through.
|
||||||
def map_params
|
def map_params
|
||||||
params.require(:map).permit(:id, :name, :arranged, :desc, :permission, :user_id)
|
params.require(:map).permit(:id, :name, :arranged, :desc, :permission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
67
app/controllers/messages_controller.rb
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
class MessagesController < ApplicationController
|
||||||
|
|
||||||
|
before_action :require_user, except: [:show]
|
||||||
|
after_action :verify_authorized
|
||||||
|
|
||||||
|
# GET /messages/1.json
|
||||||
|
def show
|
||||||
|
@message = Message.find(params[:id])
|
||||||
|
authorize @message
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.json { render json: @message }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /messages
|
||||||
|
# POST /messages.json
|
||||||
|
def create
|
||||||
|
@message = Message.new(message_params)
|
||||||
|
@message.user = current_user
|
||||||
|
authorize @message
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @message.save
|
||||||
|
format.json { render json: @message, status: :created, location: messages_url }
|
||||||
|
else
|
||||||
|
format.json { render json: @message.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PUT /messages/1
|
||||||
|
# PUT /messages/1.json
|
||||||
|
def update
|
||||||
|
@message = Message.find(params[:id])
|
||||||
|
authorize @message
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @message.update_attributes(message_params)
|
||||||
|
format.json { head :no_content }
|
||||||
|
else
|
||||||
|
format.json { render json: @message.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /messages/1
|
||||||
|
# DELETE /messages/1.json
|
||||||
|
def destroy
|
||||||
|
@message = Message.find(params[:id])
|
||||||
|
authorize @message
|
||||||
|
|
||||||
|
@message.destroy
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Never trust parameters from the scary internet, only allow the white list through.
|
||||||
|
def message_params
|
||||||
|
#params.require(:message).permit(:id, :resource_id, :message)
|
||||||
|
params.permit(:id, :resource_id, :resource_type, :message)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,6 @@
|
||||||
class MetacodeSetsController < ApplicationController
|
class MetacodeSetsController < ApplicationController
|
||||||
|
|
||||||
before_filter :require_admin
|
before_action :require_admin
|
||||||
|
|
||||||
# GET /metacode_sets
|
# GET /metacode_sets
|
||||||
# GET /metacode_sets.json
|
# GET /metacode_sets.json
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
class MetacodesController < ApplicationController
|
class MetacodesController < ApplicationController
|
||||||
before_filter :require_admin, except: [:index]
|
before_action :require_admin, except: [:index, :show]
|
||||||
|
|
||||||
# GET /metacodes
|
# GET /metacodes
|
||||||
# GET /metacodes.json
|
# GET /metacodes.json
|
||||||
def index
|
def index
|
||||||
@metacodes = Metacode.order("name").all
|
@metacodes = Metacode.order("name").all
|
||||||
@metacodes.map do |metacode|
|
|
||||||
metacode.icon = ActionController::Base.helpers.asset_path(metacode.icon)
|
|
||||||
end
|
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html {
|
format.html {
|
||||||
|
@ -15,23 +12,23 @@ class MetacodesController < ApplicationController
|
||||||
redirect_to root_url, notice: "You need to be an admin for that."
|
redirect_to root_url, notice: "You need to be an admin for that."
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
render action: "index"
|
render :index
|
||||||
}
|
}
|
||||||
format.json { render json: @metacodes }
|
format.json { render json: @metacodes }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
### SHOW IS CURRENTLY DISABLED
|
|
||||||
# GET /metacodes/1
|
|
||||||
# GET /metacodes/1.json
|
# GET /metacodes/1.json
|
||||||
# def show
|
# GET /metacodes/Action.json
|
||||||
# @metacode = Metacode.find(params[:id])
|
# GET /metacodes/action.json
|
||||||
#
|
def show
|
||||||
# respond_to do |format|
|
@metacode = Metacode.where('DOWNCASE(name) = ?', downcase(params[:name])).first if params[:name]
|
||||||
# format.html # show.html.erb
|
@metacode = Metacode.find(params[:id]) unless @metacode
|
||||||
# format.json { render json: @metacode }
|
|
||||||
# end
|
respond_to do |format|
|
||||||
# end
|
format.json { render json: @metacode }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# GET /metacodes/new
|
# GET /metacodes/new
|
||||||
# GET /metacodes/new.json
|
# GET /metacodes/new.json
|
||||||
|
@ -59,7 +56,7 @@ class MetacodesController < ApplicationController
|
||||||
format.html { redirect_to metacodes_url, notice: 'Metacode was successfully created.' }
|
format.html { redirect_to metacodes_url, notice: 'Metacode was successfully created.' }
|
||||||
format.json { render json: @metacode, status: :created, location: metacodes_url }
|
format.json { render json: @metacode, status: :created, location: metacodes_url }
|
||||||
else
|
else
|
||||||
format.html { render action: "new" }
|
format.html { render :new }
|
||||||
format.json { render json: @metacode.errors, status: :unprocessable_entity }
|
format.json { render json: @metacode.errors, status: :unprocessable_entity }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -71,34 +68,20 @@ class MetacodesController < ApplicationController
|
||||||
@metacode = Metacode.find(params[:id])
|
@metacode = Metacode.find(params[:id])
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @metacode.update_attributes(metacode_params)
|
if @metacode.update(metacode_params)
|
||||||
format.html { redirect_to metacodes_url, notice: 'Metacode was successfully updated.' }
|
format.html { redirect_to metacodes_url, notice: 'Metacode was successfully updated.' }
|
||||||
format.json { head :no_content }
|
format.json { head :no_content }
|
||||||
else
|
else
|
||||||
format.html { render action: "edit" }
|
format.html { render :edit }
|
||||||
format.json { render json: @metacode.errors, status: :unprocessable_entity }
|
format.json { render json: @metacode.errors, status: :unprocessable_entity }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
### DESTROY IS CURRENTLY DISABLED
|
|
||||||
# DELETE /metacodes/1
|
|
||||||
# DELETE /metacodes/1.json
|
|
||||||
# def destroy
|
|
||||||
# @metacode = Metacode.find(params[:id])
|
|
||||||
# @metacode.destroy
|
|
||||||
#
|
|
||||||
# respond_to do |format|
|
|
||||||
# format.html { redirect_to metacodes_url }
|
|
||||||
# format.json { head :no_content }
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Never trust parameters from the scary internet, only allow the white list through.
|
# Never trust parameters from the scary internet, only allow the white list through.
|
||||||
def metacode_params
|
def metacode_params
|
||||||
params.require(:metacode).permit(:id, :name, :icon, :color)
|
params.require(:metacode).permit(:id, :name, :aws_icon, :manual_icon, :color)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
class SynapsesController < ApplicationController
|
class SynapsesController < ApplicationController
|
||||||
include TopicsHelper
|
include TopicsHelper
|
||||||
|
|
||||||
before_filter :require_user, only: [:create, :update, :destroy]
|
before_action :require_user, only: [:create, :update, :destroy]
|
||||||
|
after_action :verify_authorized, except: :index
|
||||||
|
after_action :verify_policy_scoped, only: :index
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
# GET /synapses/1.json
|
# GET /synapses/1.json
|
||||||
def show
|
def show
|
||||||
@synapse = Synapse.find(params[:id])
|
@synapse = Synapse.find(params[:id])
|
||||||
|
authorize @synapse
|
||||||
|
|
||||||
#.authorize_to_show(@current)
|
|
||||||
|
|
||||||
#if not @synapse
|
|
||||||
# redirect_to root_url and return
|
|
||||||
#end
|
|
||||||
|
|
||||||
render json: @synapse
|
render json: @synapse
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -22,7 +19,8 @@ class SynapsesController < ApplicationController
|
||||||
# POST /synapses.json
|
# POST /synapses.json
|
||||||
def create
|
def create
|
||||||
@synapse = Synapse.new(synapse_params)
|
@synapse = Synapse.new(synapse_params)
|
||||||
@synapse.update_attribute :desc, "" if @synapse.desc.nil?
|
@synapse.desc = "" if @synapse.desc.nil?
|
||||||
|
authorize @synapse
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @synapse.save
|
if @synapse.save
|
||||||
|
@ -37,7 +35,8 @@ class SynapsesController < ApplicationController
|
||||||
# PUT /synapses/1.json
|
# PUT /synapses/1.json
|
||||||
def update
|
def update
|
||||||
@synapse = Synapse.find(params[:id])
|
@synapse = Synapse.find(params[:id])
|
||||||
@synapse.update_attribute :desc, "" if @synapse.desc.nil?
|
@synapse.desc = "" if @synapse.desc.nil?
|
||||||
|
authorize @synapse
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @synapse.update_attributes(synapse_params)
|
if @synapse.update_attributes(synapse_params)
|
||||||
|
@ -50,8 +49,9 @@ class SynapsesController < ApplicationController
|
||||||
|
|
||||||
# DELETE synapses/:id
|
# DELETE synapses/:id
|
||||||
def destroy
|
def destroy
|
||||||
@synapse = Synapse.find(params[:id]).authorize_to_delete(current_user)
|
@synapse = Synapse.find(params[:id])
|
||||||
@synapse.delete if @synapse
|
authorize @synapse
|
||||||
|
@synapse.delete
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json { head :no_content }
|
format.json { head :no_content }
|
||||||
|
|
|
@ -1,215 +1,164 @@
|
||||||
class TopicsController < ApplicationController
|
class TopicsController < ApplicationController
|
||||||
include TopicsHelper
|
include TopicsHelper
|
||||||
|
|
||||||
before_filter :require_user, only: [:create, :update, :destroy]
|
before_action :require_user, only: [:create, :update, :destroy]
|
||||||
|
after_action :verify_authorized, except: :autocomplete_topic
|
||||||
respond_to :html, :js, :json
|
|
||||||
|
respond_to :html, :js, :json
|
||||||
# GET /topics/autocomplete_topic
|
|
||||||
def autocomplete_topic
|
# GET /topics/autocomplete_topic
|
||||||
@current = current_user
|
def autocomplete_topic
|
||||||
term = params[:term]
|
term = params[:term]
|
||||||
if term && !term.empty?
|
if term && !term.empty?
|
||||||
@topics = Topic.where('LOWER("name") like ?', term.downcase + '%').order('"name"')
|
@topics = policy_scope(Topic.where('LOWER("name") like ?', term.downcase + '%')).order('"name"')
|
||||||
|
else
|
||||||
#read this next line as 'delete a topic if its private and you're either
|
@topics = []
|
||||||
#1. logged out or 2. logged in but not the topic creator
|
end
|
||||||
@topics.to_a.delete_if {|t| t.permission == "private" &&
|
render json: autocomplete_array_json(@topics)
|
||||||
(!authenticated? || (authenticated? && @current.id != t.user_id)) }
|
end
|
||||||
else
|
|
||||||
@topics = []
|
# GET topics/:id
|
||||||
end
|
def show
|
||||||
render json: autocomplete_array_json(@topics)
|
@topic = Topic.find(params[:id])
|
||||||
end
|
authorize @topic
|
||||||
|
|
||||||
# GET topics/:id
|
respond_to do |format|
|
||||||
def show
|
format.html {
|
||||||
@current = current_user
|
@alltopics = [@topic].concat(policy_scope(Topic.relatives1(@topic.id)).to_a).concat(policy_scope(Topic.relatives2(@topic.id)).to_a)
|
||||||
@topic = Topic.find(params[:id]).authorize_to_show(@current)
|
@allsynapses = policy_scope(Synapse.for_topic(@topic.id)).to_a
|
||||||
|
puts @alltopics.length
|
||||||
if not @topic
|
puts @allsynapses.length
|
||||||
redirect_to root_url, notice: "Access denied. That topic is private." and return
|
@allcreators = @alltopics.map(&:user).uniq
|
||||||
end
|
@allcreators += @allsynapses.map(&:user).uniq
|
||||||
|
|
||||||
respond_to do |format|
|
respond_with(@allsynapses, @alltopics, @allcreators, @topic)
|
||||||
format.html {
|
}
|
||||||
@alltopics = ([@topic] + @topic.relatives).delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } # should limit to topics visible to user
|
format.json { render json: @topic }
|
||||||
@allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
|
end
|
||||||
|
end
|
||||||
@allcreators = []
|
|
||||||
@alltopics.each do |t|
|
# GET topics/:id/network
|
||||||
if @allcreators.index(t.user) == nil
|
def network
|
||||||
@allcreators.push(t.user)
|
@topic = Topic.find(params[:id])
|
||||||
end
|
authorize @topic
|
||||||
end
|
|
||||||
@allsynapses.each do |s|
|
@alltopics = [@topic].concat(policy_scope(Topic.relatives1(@topic.id)).to_a).concat(policy_scope(Topic.relatives2(@topic.id)).to_a)
|
||||||
if @allcreators.index(s.user) == nil
|
@allsynapses = policy_scope(Synapse.for_topic(@topic.id))
|
||||||
@allcreators.push(s.user)
|
|
||||||
end
|
@allcreators = @alltopics.map(&:user).uniq
|
||||||
end
|
@allcreators += @allsynapses.map(&:user).uniq
|
||||||
|
|
||||||
respond_with(@allsynapses, @alltopics, @allcreators, @topic)
|
@json = Hash.new()
|
||||||
}
|
@json['topic'] = @topic
|
||||||
format.json { render json: @topic }
|
@json['creators'] = @allcreators
|
||||||
end
|
@json['relatives'] = @alltopics
|
||||||
end
|
@json['synapses'] = @allsynapses
|
||||||
|
|
||||||
# GET topics/:id/network
|
respond_to do |format|
|
||||||
def network
|
format.json { render json: @json }
|
||||||
@current = current_user
|
end
|
||||||
@topic = Topic.find(params[:id]).authorize_to_show(@current)
|
end
|
||||||
|
|
||||||
if not @topic
|
# GET topics/:id/relative_numbers
|
||||||
redirect_to root_url, notice: "Access denied. That topic is private." and return
|
def relative_numbers
|
||||||
end
|
@topic = Topic.find(params[:id])
|
||||||
|
authorize @topic
|
||||||
@alltopics = @topic.relatives.to_a.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) }
|
|
||||||
@allsynapses = @topic.synapses.to_a.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
|
topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : []
|
||||||
@allcreators = []
|
|
||||||
@allcreators.push(@topic.user)
|
@alltopics = policy_scope(Topic.relatives1(@topic.id)).to_a.concat(policy_scope(Topic.relatives2(@topic.id)).to_a).uniq
|
||||||
@alltopics.each do |t|
|
@alltopics.delete_if do |topic|
|
||||||
if @allcreators.index(t.user) == nil
|
topicsAlreadyHas.index(topic.id) != nil
|
||||||
@allcreators.push(t.user)
|
end
|
||||||
end
|
|
||||||
end
|
@json = Hash.new(0)
|
||||||
@allsynapses.each do |s|
|
@alltopics.each do |t|
|
||||||
if @allcreators.index(s.user) == nil
|
@json[t.metacode.id] += 1
|
||||||
@allcreators.push(s.user)
|
end
|
||||||
end
|
|
||||||
end
|
respond_to do |format|
|
||||||
|
format.json { render json: @json }
|
||||||
@json = Hash.new()
|
end
|
||||||
@json['topic'] = @topic
|
end
|
||||||
@json['creators'] = @allcreators
|
|
||||||
@json['relatives'] = @alltopics
|
# GET topics/:id/relatives
|
||||||
@json['synapses'] = @allsynapses
|
def relatives
|
||||||
|
@topic = Topic.find(params[:id])
|
||||||
respond_to do |format|
|
authorize @topic
|
||||||
format.json { render json: @json }
|
|
||||||
end
|
topicsAlreadyHas = params[:network] ? params[:network].split(',').map(&:to_i) : []
|
||||||
end
|
|
||||||
|
alltopics = policy_scope(Topic.relatives1(@topic.id)).to_a.concat(policy_scope(Topic.relatives2(@topic.id)).to_a).uniq
|
||||||
# GET topics/:id/relative_numbers
|
alltopics.delete_if do |topic|
|
||||||
def relative_numbers
|
topicsAlreadyHas.index(topic.id.to_s) != nil
|
||||||
@current = current_user
|
end
|
||||||
@topic = Topic.find(params[:id]).authorize_to_show(@current)
|
|
||||||
|
#find synapses between topics in alltopics array
|
||||||
if not @topic
|
allsynapses = policy_scope(Synapse.for_topic(@topic.id)).to_a
|
||||||
redirect_to root_url, notice: "Access denied. That topic is private." and return
|
synapse_ids = (allsynapses.map(&:node1_id) + allsynapses.map(&:node2_id)).uniq
|
||||||
end
|
allsynapses.delete_if do |synapse|
|
||||||
|
synapse_ids.index(synapse.id) != nil
|
||||||
@topicsAlreadyHas = params[:network] ? params[:network].split(',') : []
|
end
|
||||||
|
|
||||||
@alltopics = @topic.relatives.to_a.delete_if {|t|
|
creatorsAlreadyHas = params[:creators] ? params[:creators].split(',').map(&:to_i) : []
|
||||||
@topicsAlreadyHas.index(t.id.to_s) != nil ||
|
allcreators = (alltopics.map(&:user) + allsynapses.map(&:user)).uniq.delete_if do |user|
|
||||||
(t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)))
|
creatorsAlreadyHas.index(user.id) != nil
|
||||||
}
|
end
|
||||||
|
|
||||||
@alltopics.uniq!
|
@json = Hash.new()
|
||||||
|
@json['topics'] = alltopics
|
||||||
@json = Hash.new()
|
@json['synapses'] = allsynapses
|
||||||
@alltopics.each do |t|
|
@json['creators'] = allcreators
|
||||||
if @json[t.metacode.id]
|
|
||||||
@json[t.metacode.id] += 1
|
respond_to do |format|
|
||||||
else
|
format.json { render json: @json }
|
||||||
@json[t.metacode.id] = 1
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
# POST /topics
|
||||||
respond_to do |format|
|
# POST /topics.json
|
||||||
format.json { render json: @json }
|
def create
|
||||||
end
|
@topic = Topic.new(topic_params)
|
||||||
end
|
authorize @topic
|
||||||
|
|
||||||
# GET topics/:id/relatives
|
respond_to do |format|
|
||||||
def relatives
|
if @topic.save
|
||||||
@current = current_user
|
format.json { render json: @topic, status: :created }
|
||||||
@topic = Topic.find(params[:id]).authorize_to_show(@current)
|
else
|
||||||
|
format.json { render json: @topic.errors, status: :unprocessable_entity }
|
||||||
if not @topic
|
end
|
||||||
redirect_to root_url, notice: "Access denied. That topic is private." and return
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@topicsAlreadyHas = params[:network] ? params[:network].split(',') : []
|
# PUT /topics/1
|
||||||
|
# PUT /topics/1.json
|
||||||
@alltopics = @topic.relatives.to_a.delete_if {|t|
|
def update
|
||||||
@topicsAlreadyHas.index(t.id.to_s) != nil ||
|
@topic = Topic.find(params[:id])
|
||||||
(params[:metacode] && t.metacode_id.to_s != params[:metacode]) ||
|
authorize @topic
|
||||||
(t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)))
|
|
||||||
}
|
respond_to do |format|
|
||||||
|
if @topic.update_attributes(topic_params)
|
||||||
@alltopics.uniq!
|
format.json { head :no_content }
|
||||||
|
else
|
||||||
@allsynapses = @topic.synapses.to_a.delete_if {|s|
|
format.json { render json: @topic.errors, status: :unprocessable_entity }
|
||||||
(s.topic1 == @topic && @alltopics.index(s.topic2) == nil) ||
|
end
|
||||||
(s.topic2 == @topic && @alltopics.index(s.topic1) == nil)
|
end
|
||||||
}
|
end
|
||||||
|
|
||||||
@creatorsAlreadyHas = params[:creators] ? params[:creators].split(',') : []
|
# DELETE topics/:id
|
||||||
@allcreators = []
|
def destroy
|
||||||
@alltopics.each do |t|
|
@topic = Topic.find(params[:id])
|
||||||
if @allcreators.index(t.user) == nil && @creatorsAlreadyHas.index(t.user_id.to_s) == nil
|
authorize @topic
|
||||||
@allcreators.push(t.user)
|
|
||||||
end
|
@topic.delete
|
||||||
end
|
respond_to do |format|
|
||||||
@allsynapses.each do |s|
|
format.json { head :no_content }
|
||||||
if @allcreators.index(s.user) == nil && @creatorsAlreadyHas.index(s.user_id.to_s) == nil
|
end
|
||||||
@allcreators.push(s.user)
|
end
|
||||||
end
|
|
||||||
end
|
private
|
||||||
|
|
||||||
@json = Hash.new()
|
def topic_params
|
||||||
@json['topics'] = @alltopics
|
params.require(:topic).permit(:id, :name, :desc, :link, :permission, :user_id, :metacode_id)
|
||||||
@json['synapses'] = @allsynapses
|
end
|
||||||
@json['creators'] = @allcreators
|
end
|
||||||
|
|
||||||
respond_to do |format|
|
|
||||||
format.json { render json: @json }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# POST /topics
|
|
||||||
# POST /topics.json
|
|
||||||
def create
|
|
||||||
@topic = Topic.new(topic_params)
|
|
||||||
|
|
||||||
respond_to do |format|
|
|
||||||
if @topic.save
|
|
||||||
format.json { render json: @topic, status: :created }
|
|
||||||
else
|
|
||||||
format.json { render json: @topic.errors, status: :unprocessable_entity }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# PUT /topics/1
|
|
||||||
# PUT /topics/1.json
|
|
||||||
def update
|
|
||||||
@topic = Topic.find(params[:id])
|
|
||||||
|
|
||||||
respond_to do |format|
|
|
||||||
if @topic.update_attributes(topic_params)
|
|
||||||
format.json { head :no_content }
|
|
||||||
else
|
|
||||||
format.json { render json: @topic.errors, status: :unprocessable_entity }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# DELETE topics/:id
|
|
||||||
def destroy
|
|
||||||
@current = current_user
|
|
||||||
@topic = Topic.find(params[:id]).authorize_to_delete(@current)
|
|
||||||
@topic.delete if @topic
|
|
||||||
|
|
||||||
respond_to do |format|
|
|
||||||
format.json { head :no_content }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def topic_params
|
|
||||||
params.require(:topic).permit(:id, :name, :desc, :link, :permission, :user_id, :metacode_id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class Users::RegistrationsController < Devise::RegistrationsController
|
class Users::RegistrationsController < Devise::RegistrationsController
|
||||||
before_filter :configure_sign_up_params, only: [:create]
|
before_action :configure_sign_up_params, only: [:create]
|
||||||
before_filter :configure_account_update_params, only: [:update]
|
before_action :configure_account_update_params, only: [:update]
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def after_sign_up_path_for(resource)
|
def after_sign_up_path_for(resource)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class UsersController < ApplicationController
|
class UsersController < ApplicationController
|
||||||
before_filter :require_user, only: [:edit, :update, :updatemetacodes]
|
before_action :require_user, only: [:edit, :update, :updatemetacodes]
|
||||||
|
|
||||||
respond_to :html, :json
|
respond_to :html, :json
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
module ApplicationHelper
|
module ApplicationHelper
|
||||||
def get_metacodeset
|
def get_metacodeset
|
||||||
@m = user.settings.metacodes
|
@m = current_user.settings.metacodes
|
||||||
set = @m[0].include?("metacodeset") ? MetacodeSet.find(@m[0].sub("metacodeset-","").to_i) : false
|
set = @m[0].include?("metacodeset") ? MetacodeSet.find(@m[0].sub("metacodeset-","").to_i) : false
|
||||||
return set
|
return set
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_metacodes
|
def user_metacodes
|
||||||
@m = user.settings.metacodes
|
@m = current_user.settings.metacodes
|
||||||
set = get_metacodeset
|
set = get_metacodeset
|
||||||
if set
|
if set
|
||||||
@metacodes = set.metacodes.to_a
|
@metacodes = set.metacodes.to_a
|
||||||
|
@ -15,4 +15,8 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
@metacodes.sort! {|m1,m2| m2.name.downcase <=> m1.name.downcase }.rotate!(-1)
|
@metacodes.sort! {|m1,m2| m2.name.downcase <=> m1.name.downcase }.rotate!(-1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def determine_invite_link
|
||||||
|
"#{request.base_url}/join" + (current_user ? "?code=#{current_user.code}" : "")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ module TopicsHelper
|
||||||
topic['id'] = t.id
|
topic['id'] = t.id
|
||||||
topic['label'] = t.name
|
topic['label'] = t.name
|
||||||
topic['value'] = t.name
|
topic['value'] = t.name
|
||||||
topic['description'] = t.desc.truncate(70) # make this return matched results
|
topic['description'] = t.desc ? t.desc.truncate(70) : '' # make this return matched results
|
||||||
topic['type'] = t.metacode.name
|
topic['type'] = t.metacode.name
|
||||||
topic['typeImageURL'] = t.metacode.icon
|
topic['typeImageURL'] = t.metacode.icon
|
||||||
topic['permission'] = t.permission
|
topic['permission'] = t.permission
|
||||||
|
|
10
app/models/concerns/routing.rb
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
module Routing
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
include Rails.application.routes.url_helpers
|
||||||
|
|
||||||
|
included do
|
||||||
|
def default_url_options
|
||||||
|
ActionMailer::Base.default_url_options
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
31
app/models/event.rb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
class Event < ActiveRecord::Base
|
||||||
|
KINDS = %w[topic_added_to_map synapse_added_to_map]
|
||||||
|
|
||||||
|
#has_many :notifications, dependent: :destroy
|
||||||
|
belongs_to :eventable, polymorphic: true
|
||||||
|
belongs_to :map
|
||||||
|
belongs_to :user
|
||||||
|
|
||||||
|
scope :chronologically, -> { order('created_at asc') }
|
||||||
|
|
||||||
|
after_create :notify_webhooks!, if: :map
|
||||||
|
|
||||||
|
validates_inclusion_of :kind, :in => KINDS
|
||||||
|
validates_presence_of :eventable
|
||||||
|
|
||||||
|
#def notify!(user)
|
||||||
|
# notifications.create!(user: user)
|
||||||
|
#end
|
||||||
|
|
||||||
|
def belongs_to?(this_user)
|
||||||
|
self.user_id == this_user.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def notify_webhooks!
|
||||||
|
#group = self.discussion.group
|
||||||
|
self.map.webhooks.each { |webhook| WebhookService.publish! webhook: webhook, event: self }
|
||||||
|
#group.webhooks.each { |webhook| WebhookService.publish! webhook: webhook, event: self }
|
||||||
|
end
|
||||||
|
handle_asynchronously :notify_webhooks!
|
||||||
|
|
||||||
|
end
|
18
app/models/events/new_mapping.rb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
class Events::NewMapping < Event
|
||||||
|
#after_create :notify_users!
|
||||||
|
|
||||||
|
def self.publish!(mapping, user)
|
||||||
|
create!(kind: mapping.mappable_type == "Topic" ? "topic_added_to_map" : "synapse_added_to_map",
|
||||||
|
eventable: mapping,
|
||||||
|
map: mapping.map,
|
||||||
|
user: user)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
#def notify_users!
|
||||||
|
# unless comment_vote.user == comment_vote.comment_user
|
||||||
|
# notify!(comment_vote.comment_user)
|
||||||
|
# end
|
||||||
|
#end
|
||||||
|
end
|
|
@ -6,6 +6,10 @@ class Map < ActiveRecord::Base
|
||||||
has_many :synapsemappings, -> { Mapping.synapsemapping }, class_name: :Mapping, dependent: :destroy
|
has_many :synapsemappings, -> { Mapping.synapsemapping }, class_name: :Mapping, dependent: :destroy
|
||||||
has_many :topics, through: :topicmappings, source: :mappable, source_type: "Topic"
|
has_many :topics, through: :topicmappings, source: :mappable, source_type: "Topic"
|
||||||
has_many :synapses, through: :synapsemappings, source: :mappable, source_type: "Synapse"
|
has_many :synapses, through: :synapsemappings, source: :mappable, source_type: "Synapse"
|
||||||
|
has_many :messages, as: :resource, dependent: :destroy
|
||||||
|
|
||||||
|
has_many :webhooks, as: :hookable
|
||||||
|
has_many :events, -> { includes :user }, as: :eventable, dependent: :destroy
|
||||||
|
|
||||||
# This method associates the attribute ":image" with a file attachment
|
# This method associates the attribute ":image" with a file attachment
|
||||||
has_attached_file :screenshot, :styles => {
|
has_attached_file :screenshot, :styles => {
|
||||||
|
@ -13,15 +17,16 @@ class Map < ActiveRecord::Base
|
||||||
#:full => ['940x630#', :png]
|
#:full => ['940x630#', :png]
|
||||||
},
|
},
|
||||||
:default_url => 'https://s3.amazonaws.com/metamaps-assets/site/missing-map.png'
|
:default_url => 'https://s3.amazonaws.com/metamaps-assets/site/missing-map.png'
|
||||||
|
|
||||||
validates :name, presence: true
|
validates :name, presence: true
|
||||||
validates :arranged, inclusion: { in: [true, false] }
|
validates :arranged, inclusion: { in: [true, false] }
|
||||||
validates :permission, presence: true
|
validates :permission, presence: true
|
||||||
validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) }
|
validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) }
|
||||||
|
|
||||||
# Validate the attached image is image/jpg, image/png, etc
|
# Validate the attached image is image/jpg, image/png, etc
|
||||||
validates_attachment_content_type :screenshot, :content_type => /\Aimage\/.*\Z/
|
validates_attachment_content_type :screenshot, :content_type => /\Aimage\/.*\Z/
|
||||||
|
|
||||||
def mappings
|
def mappings
|
||||||
topicmappings + synapsemappings
|
topicmappings + synapsemappings
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -32,85 +37,56 @@ class Map < ActiveRecord::Base
|
||||||
#return an array of the contributors to the map
|
#return an array of the contributors to the map
|
||||||
def contributors
|
def contributors
|
||||||
contributors = []
|
contributors = []
|
||||||
|
|
||||||
self.mappings.each do |m|
|
self.mappings.each do |m|
|
||||||
contributors.push(m.user) if !contributors.include?(m.user)
|
contributors.push(m.user) if !contributors.include?(m.user)
|
||||||
end
|
end
|
||||||
|
|
||||||
return contributors
|
return contributors
|
||||||
end
|
end
|
||||||
|
|
||||||
def topic_count
|
def topic_count
|
||||||
self.topics.length
|
topics.length
|
||||||
end
|
end
|
||||||
|
|
||||||
def synapse_count
|
def synapse_count
|
||||||
self.synapses.length
|
synapses.length
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_name
|
def user_name
|
||||||
self.user.name
|
user.name
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_image
|
def user_image
|
||||||
self.user.image.url
|
user.image.url
|
||||||
end
|
end
|
||||||
|
|
||||||
def contributor_count
|
def contributor_count
|
||||||
self.contributors.length
|
contributors.length
|
||||||
end
|
end
|
||||||
|
|
||||||
def screenshot_url
|
def screenshot_url
|
||||||
self.screenshot.url(:thumb)
|
screenshot.url(:thumb)
|
||||||
end
|
end
|
||||||
|
|
||||||
def created_at_str
|
def created_at_str
|
||||||
self.created_at.strftime("%m/%d/%Y")
|
created_at.strftime("%m/%d/%Y")
|
||||||
end
|
end
|
||||||
|
|
||||||
def updated_at_str
|
def updated_at_str
|
||||||
self.updated_at.strftime("%m/%d/%Y")
|
updated_at.strftime("%m/%d/%Y")
|
||||||
end
|
end
|
||||||
|
|
||||||
def as_json(options={})
|
def as_json(options={})
|
||||||
json = super(:methods =>[:user_name, :user_image, :topic_count, :synapse_count, :contributor_count, :screenshot_url], :except => [:screenshot_content_type, :screenshot_file_size, :screenshot_file_name, :screenshot_updated_at])
|
json = super(:methods =>[:user_name, :user_image, :topic_count, :synapse_count, :contributor_count, :screenshot_url], :except => [:screenshot_content_type, :screenshot_file_size, :screenshot_file_name, :screenshot_updated_at])
|
||||||
json[:created_at_clean] = self.created_at_str
|
json[:created_at_clean] = created_at_str
|
||||||
json[:updated_at_clean] = self.updated_at_str
|
json[:updated_at_clean] = updated_at_str
|
||||||
json
|
json
|
||||||
end
|
end
|
||||||
|
|
||||||
##### PERMISSIONS ######
|
|
||||||
|
|
||||||
def authorize_to_delete(user)
|
|
||||||
if (self.user != user)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
# returns false if user not allowed to 'show' Topic, Synapse, or Map
|
|
||||||
def authorize_to_show(user)
|
|
||||||
if (self.permission == "private" && self.user != user)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
# returns false if user not allowed to 'edit' Topic, Synapse, or Map
|
|
||||||
def authorize_to_edit(user)
|
|
||||||
if !user
|
|
||||||
return false
|
|
||||||
elsif (self.permission == "private" && self.user != user)
|
|
||||||
return false
|
|
||||||
elsif (self.permission == "public" && self.user != user)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
def decode_base64(imgBase64)
|
def decode_base64(imgBase64)
|
||||||
decoded_data = Base64.decode64(imgBase64)
|
decoded_data = Base64.decode64(imgBase64)
|
||||||
|
|
||||||
data = StringIO.new(decoded_data)
|
data = StringIO.new(decoded_data)
|
||||||
data.class_eval do
|
data.class_eval do
|
||||||
attr_accessor :content_type, :original_filename
|
attr_accessor :content_type, :original_filename
|
||||||
|
|
|
@ -4,10 +4,15 @@ class Mapping < ActiveRecord::Base
|
||||||
scope :synapsemapping, -> { where(mappable_type: :Synapse) }
|
scope :synapsemapping, -> { where(mappable_type: :Synapse) }
|
||||||
|
|
||||||
belongs_to :mappable, polymorphic: true
|
belongs_to :mappable, polymorphic: true
|
||||||
|
belongs_to :map, :class_name => "Map", :foreign_key => "map_id", touch: true
|
||||||
belongs_to :map, :class_name => "Map", :foreign_key => "map_id"
|
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
|
||||||
|
validates :xloc, presence: true,
|
||||||
|
unless: Proc.new { |m| m.mappable_type == 'Synapse' }
|
||||||
|
validates :yloc, presence: true,
|
||||||
|
unless: Proc.new { |m| m.mappable_type == 'Synapse' }
|
||||||
|
validates :map, presence: true
|
||||||
|
validates :mappable, presence: true
|
||||||
|
|
||||||
def user_name
|
def user_name
|
||||||
self.user.name
|
self.user.name
|
||||||
|
@ -20,5 +25,5 @@ class Mapping < ActiveRecord::Base
|
||||||
def as_json(options={})
|
def as_json(options={})
|
||||||
super(:methods =>[:user_name, :user_image])
|
super(:methods =>[:user_name, :user_image])
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
19
app/models/message.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
class Message < ActiveRecord::Base
|
||||||
|
|
||||||
|
belongs_to :user
|
||||||
|
belongs_to :resource, polymorphic: true
|
||||||
|
|
||||||
|
def user_name
|
||||||
|
self.user.name
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_image
|
||||||
|
self.user.image.url
|
||||||
|
end
|
||||||
|
|
||||||
|
def as_json(options={})
|
||||||
|
json = super(:methods =>[:user_name, :user_image])
|
||||||
|
json
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,16 +1,63 @@
|
||||||
class Metacode < ActiveRecord::Base
|
class Metacode < ActiveRecord::Base
|
||||||
|
|
||||||
has_many :in_metacode_sets
|
has_many :in_metacode_sets
|
||||||
has_many :metacode_sets, :through => :in_metacode_sets
|
has_many :metacode_sets, :through => :in_metacode_sets
|
||||||
has_many :topics
|
has_many :topics
|
||||||
|
|
||||||
|
# This method associates the attribute ":aws_icon" with a file attachment
|
||||||
|
has_attached_file :aws_icon, :styles => {
|
||||||
|
:ninetysix => ['96x96#', :png],
|
||||||
|
},
|
||||||
|
:default_url => 'https://s3.amazonaws.com/metamaps-assets/metacodes/generics/96px/gen_wildcard.png'
|
||||||
|
|
||||||
|
# Validate the attached icon is image/jpg, image/png, etc
|
||||||
|
validates_attachment_content_type :aws_icon, :content_type => /\Aimage\/.*\Z/
|
||||||
|
|
||||||
|
validate :aws_xor_manual_icon
|
||||||
|
validate :manual_icon_https
|
||||||
|
before_create do
|
||||||
|
self.manual_icon = nil if self.manual_icon == ""
|
||||||
|
end
|
||||||
|
|
||||||
|
def icon(*args)
|
||||||
|
if manual_icon.present?
|
||||||
|
manual_icon
|
||||||
|
else
|
||||||
|
aws_icon(*args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def as_json(options={})
|
||||||
|
default = super(options)
|
||||||
|
default[:icon] = icon
|
||||||
|
default.except('aws_icon_file_name', 'aws_icon_content_type', 'aws_icon_file_size', 'aws_icon_updated_at', 'manual_icon')
|
||||||
|
end
|
||||||
|
|
||||||
def hasSelected(user)
|
def hasSelected(user)
|
||||||
return true if user.settings.metacodes.include? self.id.to_s
|
return true if user.settings.metacodes.include? self.id.to_s
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
def inMetacodeSet(metacode_set)
|
def inMetacodeSet(metacode_set)
|
||||||
return true if self.metacode_sets.include? metacode_set
|
return true if self.metacode_sets.include? metacode_set
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def aws_xor_manual_icon
|
||||||
|
if aws_icon.blank? && manual_icon.blank?
|
||||||
|
errors.add(:base, "Either aws_icon or manual_icon is required")
|
||||||
|
end
|
||||||
|
if aws_icon.present? && manual_icon.present?
|
||||||
|
errors.add(:base, "Specify aws_icon or manual_icon, not both")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def manual_icon_https
|
||||||
|
if manual_icon.present?
|
||||||
|
unless manual_icon.starts_with? 'https'
|
||||||
|
errors.add(:base, "Manual icon must begin with https")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
33
app/models/permitted_params.rb
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
class PermittedParams < Struct.new(:params)
|
||||||
|
|
||||||
|
%w[map synapse topic mapping token].each do |kind|
|
||||||
|
define_method(kind) do
|
||||||
|
permitted_attributes = self.send("#{kind}_attributes")
|
||||||
|
params.require(kind).permit(*permitted_attributes)
|
||||||
|
end
|
||||||
|
alias_method :"api_#{kind}", kind.to_sym
|
||||||
|
end
|
||||||
|
|
||||||
|
alias :read_attribute_for_serialization :send
|
||||||
|
|
||||||
|
def token_attributes
|
||||||
|
[:description]
|
||||||
|
end
|
||||||
|
|
||||||
|
def map_attributes
|
||||||
|
[:name, :desc, :permission, :arranged]
|
||||||
|
end
|
||||||
|
|
||||||
|
def synapse_attributes
|
||||||
|
[:desc, :category, :weight, :permission, :node1_id, :node2_id]
|
||||||
|
end
|
||||||
|
|
||||||
|
def topic_attributes
|
||||||
|
[:name, :desc, :link, :permission, :metacode_id]
|
||||||
|
end
|
||||||
|
|
||||||
|
def mapping_attributes
|
||||||
|
[:xloc, :yloc, :map_id, :mappable_type, :mappable_id]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,5 +1,4 @@
|
||||||
class Synapse < ActiveRecord::Base
|
class Synapse < ActiveRecord::Base
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
|
||||||
belongs_to :topic1, :class_name => "Topic", :foreign_key => "node1_id"
|
belongs_to :topic1, :class_name => "Topic", :foreign_key => "node1_id"
|
||||||
|
@ -11,44 +10,32 @@ class Synapse < ActiveRecord::Base
|
||||||
validates :desc, length: { minimum: 0, allow_nil: false }
|
validates :desc, length: { minimum: 0, allow_nil: false }
|
||||||
|
|
||||||
validates :permission, presence: true
|
validates :permission, presence: true
|
||||||
|
validates :node1_id, presence: true
|
||||||
|
validates :node2_id, presence: true
|
||||||
validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) }
|
validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) }
|
||||||
|
|
||||||
|
validates :category, inclusion: { in: ['from-to', 'both'], allow_nil: true }
|
||||||
|
|
||||||
|
scope :for_topic, ->(topic_id = nil) {
|
||||||
|
where("node1_id = ? OR node2_id = ?", topic_id, topic_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
# :nocov:
|
||||||
def user_name
|
def user_name
|
||||||
self.user.name
|
user.name
|
||||||
end
|
end
|
||||||
|
# :nocov:
|
||||||
|
|
||||||
|
# :nocov:
|
||||||
def user_image
|
def user_image
|
||||||
self.user.image.url
|
user.image.url
|
||||||
end
|
end
|
||||||
|
# :nocov:
|
||||||
|
|
||||||
|
# :nocov:
|
||||||
def as_json(options={})
|
def as_json(options={})
|
||||||
super(:methods =>[:user_name, :user_image])
|
super(:methods =>[:user_name, :user_image])
|
||||||
end
|
end
|
||||||
|
# :nocov:
|
||||||
|
|
||||||
##### PERMISSIONS ######
|
|
||||||
|
|
||||||
# returns false if user not allowed to 'show' Topic, Synapse, or Map
|
|
||||||
def authorize_to_show(user)
|
|
||||||
if (self.permission == "private" && self.user != user)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
# returns false if user not allowed to 'edit' Topic, Synapse, or Map
|
|
||||||
def authorize_to_edit(user)
|
|
||||||
if (self.permission == "private" && self.user != user)
|
|
||||||
return false
|
|
||||||
elsif (self.permission == "public" && self.user != user)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
def authorize_to_delete(user)
|
|
||||||
if (self.user == user || user.admin)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
22
app/models/token.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
class Token < ActiveRecord::Base
|
||||||
|
belongs_to :user
|
||||||
|
|
||||||
|
before_create :assign_token
|
||||||
|
|
||||||
|
CHARS = 32
|
||||||
|
|
||||||
|
private
|
||||||
|
def assign_token
|
||||||
|
self.token = generate_token
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_token
|
||||||
|
loop do
|
||||||
|
candidate = SecureRandom.base64(CHARS).gsub(/\W/, '')
|
||||||
|
if candidate.size >= CHARS
|
||||||
|
return candidate[0...CHARS]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,117 +1,123 @@
|
||||||
class Topic < ActiveRecord::Base
|
class Topic < ActiveRecord::Base
|
||||||
include TopicsHelper
|
include TopicsHelper
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
|
||||||
has_many :synapses1, :class_name => 'Synapse', :foreign_key => 'node1_id', dependent: :destroy
|
has_many :synapses1, :class_name => 'Synapse', :foreign_key => 'node1_id', dependent: :destroy
|
||||||
has_many :synapses2, :class_name => 'Synapse', :foreign_key => 'node2_id', dependent: :destroy
|
has_many :synapses2, :class_name => 'Synapse', :foreign_key => 'node2_id', dependent: :destroy
|
||||||
has_many :topics1, :through => :synapses2, :source => :topic1
|
has_many :topics1, :through => :synapses2, source: :topic1
|
||||||
has_many :topics2, :through => :synapses1, :source => :topic2
|
has_many :topics2, :through => :synapses1, source: :topic2
|
||||||
|
|
||||||
has_many :mappings, as: :mappable, dependent: :destroy
|
has_many :mappings, as: :mappable, dependent: :destroy
|
||||||
has_many :maps, :through => :mappings
|
has_many :maps, :through => :mappings
|
||||||
|
|
||||||
validates :permission, presence: true
|
validates :permission, presence: true
|
||||||
validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) }
|
validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) }
|
||||||
|
|
||||||
# This method associates the attribute ":image" with a file attachment
|
# This method associates the attribute ":image" with a file attachment
|
||||||
has_attached_file :image
|
has_attached_file :image
|
||||||
|
|
||||||
#, styles: {
|
#, styles: {
|
||||||
# thumb: '100x100>',
|
# thumb: '100x100>',
|
||||||
# square: '200x200#',
|
# square: '200x200#',
|
||||||
# medium: '300x300>'
|
# medium: '300x300>'
|
||||||
#}
|
#}
|
||||||
|
|
||||||
# Validate the attached image is image/jpg, image/png, etc
|
# Validate the attached image is image/jpg, image/png, etc
|
||||||
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
|
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
|
||||||
|
|
||||||
# This method associates the attribute ":image" with a file attachment
|
# This method associates the attribute ":image" with a file attachment
|
||||||
has_attached_file :audio
|
has_attached_file :audio
|
||||||
# Validate the attached audio is audio/wav, audio/mp3, etc
|
# Validate the attached audio is audio/wav, audio/mp3, etc
|
||||||
validates_attachment_content_type :audio, :content_type => /\Aaudio\/.*\Z/
|
validates_attachment_content_type :audio, :content_type => /\Aaudio\/.*\Z/
|
||||||
|
|
||||||
def synapses
|
def synapses
|
||||||
synapses1 + synapses2
|
synapses1 + synapses2
|
||||||
end
|
end
|
||||||
|
|
||||||
def relatives
|
def relatives
|
||||||
topics1 + topics2
|
topics1 + topics2
|
||||||
end
|
end
|
||||||
|
|
||||||
belongs_to :metacode
|
belongs_to :metacode
|
||||||
|
|
||||||
def user_name
|
scope :relatives1, ->(topic_id = nil) {
|
||||||
user.name
|
includes(:topics1)
|
||||||
end
|
.where('synapses.node1_id = ?', topic_id)
|
||||||
|
.references(:synapses)
|
||||||
def user_image
|
}
|
||||||
user.image.url
|
|
||||||
end
|
scope :relatives2, ->(topic_id = nil) {
|
||||||
|
includes(:topics2)
|
||||||
def map_count
|
.where('synapses.node2_id = ?', topic_id)
|
||||||
maps.count
|
.references(:synapses)
|
||||||
end
|
}
|
||||||
|
|
||||||
def synapse_count
|
def user_name
|
||||||
synapses.count
|
user.name
|
||||||
end
|
end
|
||||||
|
|
||||||
def inmaps
|
def user_image
|
||||||
maps.map(&:name)
|
user.image.url
|
||||||
end
|
end
|
||||||
|
|
||||||
def inmapsLinks
|
def map_count
|
||||||
maps.map(&:id)
|
maps.count
|
||||||
end
|
end
|
||||||
|
|
||||||
def as_json(options={})
|
def synapse_count
|
||||||
super(:methods =>[:user_name, :user_image, :map_count, :synapse_count, :inmaps, :inmapsLinks])
|
synapses.count
|
||||||
end
|
end
|
||||||
|
|
||||||
def topic_autocomplete_method
|
def inmaps
|
||||||
"Get: #{self.name}"
|
maps.map(&:name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def mk_permission
|
def inmapsLinks
|
||||||
Perm.short(permission)
|
maps.map(&:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
# has no viewable synapses helper function
|
def as_json(options={})
|
||||||
def has_viewable_synapses(current)
|
super(:methods =>[:user_name, :user_image, :map_count, :synapse_count, :inmaps, :inmapsLinks])
|
||||||
result = false
|
end
|
||||||
synapses.each do |synapse|
|
|
||||||
if synapse.authorize_to_show(current)
|
# TODO move to a decorator?
|
||||||
result = true
|
def synapses_csv(output_format = 'array')
|
||||||
end
|
output = []
|
||||||
end
|
synapses.each do |synapse|
|
||||||
result
|
if synapse.category == 'from-to'
|
||||||
end
|
if synapse.node1_id == id
|
||||||
|
output << synapse.node1_id.to_s + '->' + synapse.node2_id.to_s
|
||||||
##### PERMISSIONS ######
|
elsif synapse.node2_id == id
|
||||||
|
output << synapse.node2_id.to_s + '<-' + synapse.node1_id.to_s
|
||||||
# returns false if user not allowed to 'show' Topic, Synapse, or Map
|
else
|
||||||
def authorize_to_show(user)
|
fail 'invalid synapse on topic in synapse_csv'
|
||||||
if (self.permission == "private" && self.user != user)
|
end
|
||||||
return false
|
elsif synapse.category == 'both'
|
||||||
end
|
if synapse.node1_id == id
|
||||||
return self
|
output << synapse.node1_id.to_s + '<->' + synapse.node2_id.to_s
|
||||||
end
|
elsif synapse.node2_id == id
|
||||||
|
output << synapse.node2_id.to_s + '<->' + synapse.node1_id.to_s
|
||||||
# returns false if user not allowed to 'edit' Topic, Synapse, or Map
|
else
|
||||||
def authorize_to_edit(user)
|
fail 'invalid synapse on topic in synapse_csv'
|
||||||
if (self.permission == "private" && self.user != user)
|
end
|
||||||
return false
|
end
|
||||||
elsif (self.permission == "public" && self.user != user)
|
end
|
||||||
return false
|
if output_format == 'array'
|
||||||
end
|
return output
|
||||||
return self
|
elsif output_format == 'text'
|
||||||
end
|
return output.join('; ')
|
||||||
|
else
|
||||||
def authorize_to_delete(user)
|
fail 'invalid argument to synapses_csv'
|
||||||
if (self.user == user || user.admin)
|
end
|
||||||
return self
|
output
|
||||||
end
|
end
|
||||||
return false
|
|
||||||
end
|
def topic_autocomplete_method
|
||||||
end
|
"Get: #{self.name}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def mk_permission
|
||||||
|
Perm.short(permission)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -6,13 +6,14 @@ class User < ActiveRecord::Base
|
||||||
has_many :synapses
|
has_many :synapses
|
||||||
has_many :maps
|
has_many :maps
|
||||||
has_many :mappings
|
has_many :mappings
|
||||||
|
has_many :tokens
|
||||||
|
|
||||||
after_create :generate_code
|
after_create :generate_code
|
||||||
|
|
||||||
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :registerable
|
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :registerable
|
||||||
|
|
||||||
serialize :settings, UserPreference
|
serialize :settings, UserPreference
|
||||||
|
|
||||||
validates :password, :presence => true,
|
validates :password, :presence => true,
|
||||||
:length => { :within => 8..40 },
|
:length => { :within => 8..40 },
|
||||||
:on => :create
|
:on => :create
|
||||||
|
@ -27,7 +28,7 @@ class User < ActiveRecord::Base
|
||||||
validates_uniqueness_of :email # done by devise
|
validates_uniqueness_of :email # done by devise
|
||||||
|
|
||||||
validates :joinedwithcode, :presence => true, :inclusion => { :in => $codes, :message => "%{value} is not valid" }, :on => :create
|
validates :joinedwithcode, :presence => true, :inclusion => { :in => $codes, :message => "%{value} is not valid" }, :on => :create
|
||||||
|
|
||||||
# This method associates the attribute ":image" with a file attachment
|
# This method associates the attribute ":image" with a file attachment
|
||||||
has_attached_file :image, :styles => {
|
has_attached_file :image, :styles => {
|
||||||
:thirtytwo => ['32x32#', :png],
|
:thirtytwo => ['32x32#', :png],
|
||||||
|
@ -36,7 +37,7 @@ class User < ActiveRecord::Base
|
||||||
:onetwentyeight => ['128x128#', :png]
|
:onetwentyeight => ['128x128#', :png]
|
||||||
},
|
},
|
||||||
:default_url => 'https://s3.amazonaws.com/metamaps-assets/site/user.png'
|
:default_url => 'https://s3.amazonaws.com/metamaps-assets/site/user.png'
|
||||||
|
|
||||||
# Validate the attached image is image/jpg, image/png, etc
|
# Validate the attached image is image/jpg, image/png, etc
|
||||||
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
|
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ class User < ActiveRecord::Base
|
||||||
json['rtype'] = "mapper"
|
json['rtype'] = "mapper"
|
||||||
json
|
json
|
||||||
end
|
end
|
||||||
|
|
||||||
#generate a random 8 letter/digit code that they can use to invite people
|
#generate a random 8 letter/digit code that they can use to invite people
|
||||||
def generate_code
|
def generate_code
|
||||||
self.code ||= rand(36**8).to_s(36)
|
self.code ||= rand(36**8).to_s(36)
|
||||||
|
@ -76,7 +77,7 @@ class User < ActiveRecord::Base
|
||||||
update(generation: User.find_by_code(joinedwithcode).generation + 1)
|
update(generation: User.find_by_code(joinedwithcode).generation + 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def settings
|
def settings
|
||||||
# make sure we always return a UserPreference instance
|
# make sure we always return a UserPreference instance
|
||||||
if read_attribute(:settings).nil?
|
if read_attribute(:settings).nil?
|
||||||
|
@ -84,7 +85,7 @@ class User < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
read_attribute :settings
|
read_attribute :settings
|
||||||
end
|
end
|
||||||
|
|
||||||
def settings=(val)
|
def settings=(val)
|
||||||
write_attribute :settings, val
|
write_attribute :settings, val
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
class UserPreference
|
class UserPreference
|
||||||
attr_accessor :metacodes
|
attr_accessor :metacodes
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
array = []
|
array = []
|
||||||
Metacode.all.each do |m|
|
Metacode.all.each do |m|
|
||||||
array.push(m.id.to_s)
|
array.push(m.id.to_s)
|
||||||
end
|
end
|
||||||
@metacodes = array
|
@metacodes = array
|
||||||
end
|
end
|
||||||
end
|
end
|
13
app/models/webhook.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
class Webhook < ActiveRecord::Base
|
||||||
|
belongs_to :hookable, polymorphic: true
|
||||||
|
|
||||||
|
validates :uri, presence: true
|
||||||
|
validates :hookable, presence: true
|
||||||
|
validates_inclusion_of :kind, in: %w[slack]
|
||||||
|
validates :event_types, length: { minimum: 1 }
|
||||||
|
|
||||||
|
def headers
|
||||||
|
{}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
72
app/models/webhooks/slack/base.rb
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
Webhooks::Slack::Base = Struct.new(:event) do
|
||||||
|
include Routing
|
||||||
|
|
||||||
|
def username
|
||||||
|
"Metamaps Bot"
|
||||||
|
end
|
||||||
|
|
||||||
|
def icon_url
|
||||||
|
"https://pbs.twimg.com/profile_images/539300245029392385/dJ1bwnw7.jpeg"
|
||||||
|
end
|
||||||
|
|
||||||
|
def text
|
||||||
|
"something"
|
||||||
|
end
|
||||||
|
|
||||||
|
def attachments
|
||||||
|
[{
|
||||||
|
title: attachment_title,
|
||||||
|
text: attachment_text,
|
||||||
|
fields: attachment_fields,
|
||||||
|
fallback: attachment_fallback
|
||||||
|
}]
|
||||||
|
end
|
||||||
|
|
||||||
|
alias :read_attribute_for_serialization :send
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
#def motion_vote_field
|
||||||
|
# {
|
||||||
|
# title: "Vote on this proposal",
|
||||||
|
# value: "#{proposal_link(eventable, "yes")} · " +
|
||||||
|
# "#{proposal_link(eventable, "abstain")} · " +
|
||||||
|
# "#{proposal_link(eventable, "no")} · " +
|
||||||
|
# "#{proposal_link(eventable, "block")}"
|
||||||
|
# }
|
||||||
|
#end
|
||||||
|
|
||||||
|
def view_map_on_metamaps(text = nil)
|
||||||
|
"<#{map_url(eventable.map)}|#{text || eventable.map.name}>"
|
||||||
|
end
|
||||||
|
|
||||||
|
#def view_discussion_on_loomio(params = {})
|
||||||
|
# { value: discussion_link(I18n.t(:"webhooks.slack.view_it_on_loomio"), params) }
|
||||||
|
#end
|
||||||
|
|
||||||
|
#def proposal_link(proposal, position = nil)
|
||||||
|
# discussion_link position || proposal.name, { proposal: proposal.key, position: position }
|
||||||
|
#end
|
||||||
|
|
||||||
|
#def discussion_link(text = nil, params = {})
|
||||||
|
# "<#{discussion_url(eventable.map, params)}|#{text || eventable.discussion.title}>"
|
||||||
|
#end
|
||||||
|
|
||||||
|
def eventable
|
||||||
|
@eventable ||= event.eventable
|
||||||
|
end
|
||||||
|
|
||||||
|
def author
|
||||||
|
@author ||= eventable.author
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
#webhooks:
|
||||||
|
# slack:
|
||||||
|
# motion_closed: "*%{name}* has closed"
|
||||||
|
# motion_closing_soon: "*%{name}* has a proposal closing in 24 hours"
|
||||||
|
# motion_outcome_created: "*%{author}* published an outcome in *%{name}*"
|
||||||
|
# motion_outcome_updated: "*%{author}* updated the outcome for *%{name}*"
|
||||||
|
# new_motion: "*%{author}* started a new proposal in *%{name}*"
|
||||||
|
# view_it_on_loomio: "View it on Loomio"
|
26
app/models/webhooks/slack/synapse_added_to_map.rb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
class Webhooks::Slack::SynapseAddedToMap < Webhooks::Slack::Base
|
||||||
|
|
||||||
|
def text
|
||||||
|
"\"*#{eventable.mappable.topic1.name}* #{eventable.mappable.desc || '->'} *#{eventable.mappable.topic2.name}*\" was added as a connection to the map *#{view_map_on_metamaps()}*"
|
||||||
|
end
|
||||||
|
|
||||||
|
def attachment_fallback
|
||||||
|
"" #{}"*#{eventable.name}*\n#{eventable.description}\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def attachment_title
|
||||||
|
"" #proposal_link(eventable)
|
||||||
|
end
|
||||||
|
|
||||||
|
def attachment_text
|
||||||
|
"" # "#{eventable.description}\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def attachment_fields
|
||||||
|
[{
|
||||||
|
title: "nothing",
|
||||||
|
value: "nothing"
|
||||||
|
}] #[motion_vote_field]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
27
app/models/webhooks/slack/topic_added_to_map.rb
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
class Webhooks::Slack::TopicAddedToMap < Webhooks::Slack::Base
|
||||||
|
|
||||||
|
def text
|
||||||
|
"New #{eventable.mappable.metacode.name} topic *#{eventable.mappable.name}* was added to the map *#{view_map_on_metamaps()}*"
|
||||||
|
end
|
||||||
|
# todo: it would be sweet if it sends it with the metacode as the icon_url
|
||||||
|
|
||||||
|
def attachment_fallback
|
||||||
|
"" #{}"*#{eventable.name}*\n#{eventable.description}\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def attachment_title
|
||||||
|
"" #proposal_link(eventable)
|
||||||
|
end
|
||||||
|
|
||||||
|
def attachment_text
|
||||||
|
"" # "#{eventable.description}\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def attachment_fields
|
||||||
|
[{
|
||||||
|
title: "nothing",
|
||||||
|
value: "nothing"
|
||||||
|
}] #[motion_vote_field]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
61
app/policies/application_policy.rb
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
class ApplicationPolicy
|
||||||
|
attr_reader :user, :record
|
||||||
|
|
||||||
|
def initialize(user, record)
|
||||||
|
@user = user
|
||||||
|
@record = record
|
||||||
|
end
|
||||||
|
|
||||||
|
def index?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
scope.where(:id => record.id).exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def new?
|
||||||
|
create?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit?
|
||||||
|
update?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO update this function to enable some flag in the interface
|
||||||
|
# so that admins usually can't do super admin stuff unless they
|
||||||
|
# explicitly say they want to (E.g. seeing/editing/deleting private
|
||||||
|
# maps - they should be able to, but not by accident)
|
||||||
|
def admin_override
|
||||||
|
user && user.admin
|
||||||
|
end
|
||||||
|
|
||||||
|
def scope
|
||||||
|
Pundit.policy_scope!(user, record.class)
|
||||||
|
end
|
||||||
|
|
||||||
|
class Scope
|
||||||
|
attr_reader :user, :scope
|
||||||
|
|
||||||
|
def initialize(user, scope)
|
||||||
|
@user = user
|
||||||
|
@scope = scope
|
||||||
|
end
|
||||||
|
|
||||||
|
def resolve
|
||||||
|
scope
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
26
app/policies/main_policy.rb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
class MainPolicy < ApplicationPolicy
|
||||||
|
def initialize(user, record)
|
||||||
|
@user = user
|
||||||
|
@record = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def home?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def searchtopics?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def searchmaps?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def searchmappers?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def searchsynapses?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
57
app/policies/map_policy.rb
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
class MapPolicy < ApplicationPolicy
|
||||||
|
class Scope < Scope
|
||||||
|
def resolve
|
||||||
|
visible = ['public', 'commons']
|
||||||
|
permission = 'maps.permission IN (?)'
|
||||||
|
if user
|
||||||
|
scope.where(permission + ' OR maps.user_id = ?', visible, user.id)
|
||||||
|
else
|
||||||
|
scope.where(permission, visible)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def activemaps?
|
||||||
|
user.blank? # redirect to root url if authenticated for some reason
|
||||||
|
end
|
||||||
|
|
||||||
|
def featuredmaps?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def mymaps?
|
||||||
|
user.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def usermaps?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
record.permission == 'commons' || record.permission == 'public' || record.user == user
|
||||||
|
end
|
||||||
|
|
||||||
|
def export?
|
||||||
|
show?
|
||||||
|
end
|
||||||
|
|
||||||
|
def contains?
|
||||||
|
show?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
user.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
user.present? && (record.permission == 'commons' || record.user == user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def screenshot?
|
||||||
|
update?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
record.user == user || admin_override
|
||||||
|
end
|
||||||
|
end
|
43
app/policies/mapping_policy.rb
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
class MappingPolicy < ApplicationPolicy
|
||||||
|
class Scope < Scope
|
||||||
|
def resolve
|
||||||
|
# TODO base this on the map policy
|
||||||
|
# it would be nice if we could also base this on the mappable, but that
|
||||||
|
# gets really complicated. Devin thinks it's OK to SHOW a mapping for
|
||||||
|
# a private topic, since you can't see the private topic anyways
|
||||||
|
visible = ['public', 'commons']
|
||||||
|
permission = 'maps.permission IN (?)'
|
||||||
|
if user
|
||||||
|
scope.joins(:maps).where(permission + ' OR maps.user_id = ?', visible, user.id)
|
||||||
|
else
|
||||||
|
scope.where(permission, visible)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
map_policy.show? && mappable_policy.show?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
record.map.present? && map_policy.update?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
record.mappable_type == 'Topic' && map_policy.update?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
map_policy.update? || admin_override
|
||||||
|
end
|
||||||
|
|
||||||
|
# Helpers
|
||||||
|
|
||||||
|
def map_policy
|
||||||
|
@map_policy ||= Pundit.policy(user, record.map)
|
||||||
|
end
|
||||||
|
|
||||||
|
def mappable_policy
|
||||||
|
@mappable_policy ||= Pundit.policy(user, record.mappable)
|
||||||
|
end
|
||||||
|
end
|
36
app/policies/message_policy.rb
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
class MessagePolicy < ApplicationPolicy
|
||||||
|
class Scope < Scope
|
||||||
|
def resolve
|
||||||
|
visible = ['public', 'commons']
|
||||||
|
permission = 'maps.permission IN (?)'
|
||||||
|
if user
|
||||||
|
scope.joins(:maps).where(permission + ' OR maps.user_id = ?', visible, user.id)
|
||||||
|
else
|
||||||
|
scope.where(permission, visible)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
resource_policy.show?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
record.resource.present? && resource_policy.update?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
record.user == user
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
record.user == user || admin_override
|
||||||
|
end
|
||||||
|
|
||||||
|
# Helpers
|
||||||
|
|
||||||
|
def resource_policy
|
||||||
|
@resource_policy ||= Pundit.policy(user, record.resource)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
30
app/policies/synapse_policy.rb
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
class SynapsePolicy < ApplicationPolicy
|
||||||
|
class Scope < Scope
|
||||||
|
def resolve
|
||||||
|
visible = ['public', 'commons']
|
||||||
|
permission = 'synapses.permission IN (?)'
|
||||||
|
if user
|
||||||
|
scope.where(permission + ' OR synapses.user_id = ?', visible, user.id)
|
||||||
|
else
|
||||||
|
scope.where(permission, visible)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
user.present?
|
||||||
|
# todo add validation against whether you can see both topics
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
record.permission == 'commons' || record.permission == 'public' || record.user == user
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
user.present? && (record.permission == 'commons' || record.user == user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
record.user == user || admin_override
|
||||||
|
end
|
||||||
|
end
|
24
app/policies/token_policy.rb
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
class TokenPolicy < ApplicationPolicy
|
||||||
|
class Scope < Scope
|
||||||
|
def resolve
|
||||||
|
if user
|
||||||
|
scope.where('tokens.user_id = ?', user.id)
|
||||||
|
else
|
||||||
|
where(:id => nil).where("id IS NOT ?", nil) # to just return none
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
user.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def my_tokens?
|
||||||
|
user.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
user.present? && record.user == user
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
45
app/policies/topic_policy.rb
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
class TopicPolicy < ApplicationPolicy
|
||||||
|
class Scope < Scope
|
||||||
|
def resolve
|
||||||
|
visible = ['public', 'commons']
|
||||||
|
permission = 'topics.permission IN (?)'
|
||||||
|
if user
|
||||||
|
scope.where(permission + ' OR topics.user_id = ?', visible, user.id)
|
||||||
|
else
|
||||||
|
scope.where(permission, visible)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
user.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
record.permission == 'commons' || record.permission == 'public' || record.user == user
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
user.present? && (record.permission == 'commons' || record.user == user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
record.user == user || admin_override
|
||||||
|
end
|
||||||
|
|
||||||
|
def autocomplete_topic?
|
||||||
|
user.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def network?
|
||||||
|
show?
|
||||||
|
end
|
||||||
|
|
||||||
|
def relative_numbers?
|
||||||
|
show?
|
||||||
|
end
|
||||||
|
|
||||||
|
def relatives?
|
||||||
|
show?
|
||||||
|
end
|
||||||
|
end
|
15
app/serializers/event_serializer.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
class EventSerializer < ActiveModel::Serializer
|
||||||
|
embed :ids, include: true
|
||||||
|
attributes :id, :sequence_id, :kind, :map_id, :created_at
|
||||||
|
|
||||||
|
has_one :actor, serializer: NewUserSerializer, root: 'users'
|
||||||
|
has_one :map, serializer: NewMapSerializer
|
||||||
|
|
||||||
|
def actor
|
||||||
|
object.user || object.eventable.try(:user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def map
|
||||||
|
object.eventable.try(:map) || object.eventable.map
|
||||||
|
end
|
||||||
|
end
|
16
app/serializers/new_map_serializer.rb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
class NewMapSerializer < ActiveModel::Serializer
|
||||||
|
embed :ids, include: true
|
||||||
|
attributes :id,
|
||||||
|
:name,
|
||||||
|
:desc,
|
||||||
|
:permission,
|
||||||
|
:screenshot,
|
||||||
|
:created_at,
|
||||||
|
:updated_at
|
||||||
|
|
||||||
|
has_many :topics, serializer: NewTopicSerializer
|
||||||
|
has_many :synapses, serializer: NewSynapseSerializer
|
||||||
|
has_many :mappings, serializer: NewMappingSerializer
|
||||||
|
has_many :contributors, root: :users, serializer: NewUserSerializer
|
||||||
|
|
||||||
|
end
|
19
app/serializers/new_mapping_serializer.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
class NewMappingSerializer < ActiveModel::Serializer
|
||||||
|
embed :ids, include: true
|
||||||
|
attributes :id,
|
||||||
|
:xloc,
|
||||||
|
:yloc,
|
||||||
|
:created_at,
|
||||||
|
:updated_at,
|
||||||
|
:mappable_id,
|
||||||
|
:mappable_type
|
||||||
|
|
||||||
|
has_one :user, serializer: NewUserSerializer
|
||||||
|
has_one :map, serializer: NewMapSerializer
|
||||||
|
|
||||||
|
def filter(keys)
|
||||||
|
keys.delete(:xloc) unless object.mappable_type == "Topic"
|
||||||
|
keys.delete(:yloc) unless object.mappable_type == "Topic"
|
||||||
|
keys
|
||||||
|
end
|
||||||
|
end
|
7
app/serializers/new_metacode_serializer.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
class NewMetacodeSerializer < ActiveModel::Serializer
|
||||||
|
attributes :id,
|
||||||
|
:name,
|
||||||
|
:manual_icon,
|
||||||
|
:color,
|
||||||
|
:aws_icon
|
||||||
|
end
|