Compare commits
1 commit
develop
...
feature/la
Author | SHA1 | Date | |
---|---|---|---|
|
97aca38d53 |
|
@ -1 +0,0 @@
|
||||||
app/assets/javascripts/metamaps.secret.bundle.js
|
|
10
.babelrc
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [
|
|
||||||
"react",
|
|
||||||
"es2015"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"lodash",
|
|
||||||
"transform-class-properties"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,2 +1 @@
|
||||||
https://github.com/heroku/heroku-buildpack-nodejs.git
|
|
||||||
https://github.com/heroku/heroku-buildpack-ruby.git
|
https://github.com/heroku/heroku-buildpack-ruby.git
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
---
|
|
||||||
engines:
|
|
||||||
brakeman:
|
|
||||||
enabled: true
|
|
||||||
bundler-audit:
|
|
||||||
enabled: true
|
|
||||||
duplication:
|
|
||||||
enabled: true
|
|
||||||
config:
|
|
||||||
languages:
|
|
||||||
count_threshold: 3 # rule of three
|
|
||||||
ruby:
|
|
||||||
mass_threshold: 36 # default: 18
|
|
||||||
javascript:
|
|
||||||
mass_threshold: 80 # default: 40
|
|
||||||
eslint:
|
|
||||||
enabled: true
|
|
||||||
channel: "eslint-3"
|
|
||||||
fixme:
|
|
||||||
enabled: true
|
|
||||||
rubocop:
|
|
||||||
enabled: true
|
|
||||||
exclude_fingerprints:
|
|
||||||
- 74f18007b920e8d81148d2f6a2756534
|
|
||||||
ratings:
|
|
||||||
paths:
|
|
||||||
- 'Gemfile.lock'
|
|
||||||
- '**.erb'
|
|
||||||
- '**.rb'
|
|
||||||
- '**.js'
|
|
||||||
- '**.jsx'
|
|
||||||
exclude_paths:
|
|
||||||
- app/assets/images/
|
|
||||||
- app/assets/javascripts/lib/
|
|
||||||
- frontend/src/patched/
|
|
||||||
- db/
|
|
||||||
- script/
|
|
||||||
- spec/
|
|
|
@ -1,3 +0,0 @@
|
||||||
**/*{.,-}min.js
|
|
||||||
frontend/src/patched/*
|
|
||||||
app/assets/javascripts/lib/*
|
|
26
.eslintrc.js
|
@ -1,26 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
"sourceType": "module",
|
|
||||||
"parser": "babel-eslint",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"jsx": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extends": "standard",
|
|
||||||
"installedESLint": true,
|
|
||||||
"env": {
|
|
||||||
"es6": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"plugins": [
|
|
||||||
"promise",
|
|
||||||
"standard",
|
|
||||||
"react"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"react/jsx-uses-react": [2],
|
|
||||||
"react/jsx-uses-vars": [2],
|
|
||||||
"space-before-function-paren": [2, "never"],
|
|
||||||
"yoda": [2, "never", { "exceptRange": true }]
|
|
||||||
}
|
|
||||||
}
|
|
56
.example-env
|
@ -1,56 +0,0 @@
|
||||||
# Node JS env
|
|
||||||
export NODE_REALTIME_PORT='5000' # should match REALTIME_SERVER, below
|
|
||||||
|
|
||||||
# Rails env
|
|
||||||
export DB_USERNAME='postgres'
|
|
||||||
export DB_PASSWORD='3112'
|
|
||||||
export DB_HOST='localhost'
|
|
||||||
export DB_PORT='5432'
|
|
||||||
export DB_NAME='metamaps'
|
|
||||||
|
|
||||||
export REALTIME_SERVER='http://localhost:5000'
|
|
||||||
export MAILER_DEFAULT_URL='localhost:3000'
|
|
||||||
export DEVISE_MAILER_SENDER='team@metamaps.cc'
|
|
||||||
|
|
||||||
export DEVISE_SECRET_KEY='f71c467e526f23d614b3b08866cad4788c502bed869c282f06e73ee6c94675b62fe1f6d52fa7ba8196b33031f0d2f3b67e27ea07693c52ecebccb01700cad614'
|
|
||||||
export SECRET_KEY_BASE='267c8a84f63963282f45bc3010eaddf027abfab58fc759d6e239c8005f85ee99d6d01b1ab6394cdee9ca7f8c9213a0cf91d3d8d3350f096123e2caccbcc0924f'
|
|
||||||
|
|
||||||
# # you can safely leave these blank, unless you're deploying an instance, in
|
|
||||||
# # which case you'll need to set them up
|
|
||||||
#
|
|
||||||
# export S3_REGION
|
|
||||||
# export S3_BUCKET_NAME
|
|
||||||
# export AWS_ACCESS_KEY_ID
|
|
||||||
# export AWS_SECRET_ACCESS_KEY
|
|
||||||
#
|
|
||||||
# export SMTP_DOMAIN
|
|
||||||
# export SMTP_PASSWORD
|
|
||||||
# export SMTP_PORT
|
|
||||||
# export SMTP_SERVER
|
|
||||||
# export SMTP_USERNAME
|
|
||||||
|
|
||||||
# # send exception notifications to a slack incoming webhook
|
|
||||||
# export SLACK_EN_WEBHOOK_URL
|
|
||||||
|
|
||||||
# ruby garbage collection stuff
|
|
||||||
|
|
||||||
export RUBY_GC_TUNE=0 #set to 1 to enable GC test
|
|
||||||
export RUBY_GC_TOKEN=4f4380fc9a2857d1f008005a3eb86928
|
|
||||||
export RUBY_GC_HEAP_INIT_SLOTS=186426
|
|
||||||
export RUBY_GC_HEAP_FREE_SLOTS=559278
|
|
||||||
export RUBY_GC_HEAP_GROWTH_FACTOR=1.03
|
|
||||||
export RUBY_GC_HEAP_GROWTH_MAX_SLOTS=74570
|
|
||||||
export RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=1.4
|
|
||||||
export RUBY_GC_MALLOC_LIMIT=32883406
|
|
||||||
export RUBY_GC_MALLOC_LIMIT_MAX=69055153
|
|
||||||
export RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR=1.68
|
|
||||||
export RUBY_GC_OLDMALLOC_LIMIT=32509481
|
|
||||||
export RUBY_GC_OLDMALLOC_LIMIT_MAX=68269910
|
|
||||||
export RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR=1.4
|
|
||||||
|
|
||||||
## find the ENV currently in use in the app using :
|
|
||||||
## grep -rIso -P "(?<=ENV)(\.fetch\(|\[).[A-Z_]+.(\)|\])"
|
|
||||||
|
|
||||||
# for a uniq ordered list of env vars:
|
|
||||||
## grep -rIsoh -P "(?<=ENV)(\.fetch\(|\[).[A-Z_]+.(\)|\])" | grep -oP "[A-Z_]+" | sort -u > temp
|
|
||||||
|
|
26
.gitignore
vendored
|
@ -4,32 +4,20 @@
|
||||||
# or operating system, you probably want to add a global ignore instead:
|
# or operating system, you probably want to add a global ignore instead:
|
||||||
# git config --global core.excludesfile ~/.gitignore_global
|
# git config --global core.excludesfile ~/.gitignore_global
|
||||||
|
|
||||||
#assety stuff
|
realtime/node_modules
|
||||||
public/assets
|
config/database.yml
|
||||||
public/metamaps_mobile
|
#public/assets
|
||||||
public/api/index.html
|
|
||||||
vendor/
|
|
||||||
node_modules
|
|
||||||
npm-debug.log
|
|
||||||
app/assets/javascripts/webpacked
|
|
||||||
|
|
||||||
#secrets and config
|
|
||||||
.env
|
|
||||||
*.swp
|
|
||||||
|
|
||||||
# Ignore bundler config
|
# Ignore bundler config
|
||||||
.bundle
|
.bundle
|
||||||
|
|
||||||
|
# Ignore the default SQLite database.
|
||||||
|
db/*.sqlite3
|
||||||
|
|
||||||
# Ignore all logfiles and tempfiles.
|
# Ignore all logfiles and tempfiles.
|
||||||
log/*.log
|
log/*.log
|
||||||
tmp
|
tmp
|
||||||
.tmp
|
|
||||||
|
|
||||||
coverage
|
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*/.DS_Store
|
|
||||||
.DS_Store?
|
|
||||||
.vagrant
|
.vagrant
|
||||||
gentle/
|
|
||||||
startserver.sh
|
|
||||||
|
|
1
.nvmrc
|
@ -1 +0,0 @@
|
||||||
6.2.2
|
|
2
.rspec
|
@ -1,2 +0,0 @@
|
||||||
--color
|
|
||||||
--require spec_helper
|
|
29
.rubocop.yml
|
@ -1,29 +0,0 @@
|
||||||
AllCops:
|
|
||||||
TargetRubyVersion: 2.3
|
|
||||||
Exclude:
|
|
||||||
- 'db/**/*'
|
|
||||||
- 'tmp/**/*'
|
|
||||||
- 'bin/**/*'
|
|
||||||
- 'vendor/**/*'
|
|
||||||
- 'app/assets/javascripts/node_modules/**/*'
|
|
||||||
- 'Vagrantfile'
|
|
||||||
|
|
||||||
Rails:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
Metrics/LineLength:
|
|
||||||
Max: 120
|
|
||||||
|
|
||||||
Metrics/AbcSize:
|
|
||||||
Max: 16
|
|
||||||
|
|
||||||
Style/Documentation:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
Style/EmptyMethod:
|
|
||||||
EnforcedStyle: expanded
|
|
||||||
|
|
||||||
# I like this cop, but occasionally code is more readable without a guard clause,
|
|
||||||
# and I don't want to write rubocop:disable comments every time that happens
|
|
||||||
Style/GuardClause:
|
|
||||||
Enabled: false
|
|
|
@ -1 +0,0 @@
|
||||||
metamaps
|
|
|
@ -1 +0,0 @@
|
||||||
2.3.0
|
|
|
@ -1,7 +0,0 @@
|
||||||
if ENV['COVERAGE'] == 'on'
|
|
||||||
SimpleCov.start 'rails' do
|
|
||||||
add_group 'Policies', 'app/policies'
|
|
||||||
add_group 'Services', 'app/services'
|
|
||||||
add_group 'Serializers', 'app/serializers'
|
|
||||||
end
|
|
||||||
end
|
|
25
.travis.yml
|
@ -1,25 +0,0 @@
|
||||||
sudo: false
|
|
||||||
language: ruby
|
|
||||||
cache:
|
|
||||||
bundler: true
|
|
||||||
directories:
|
|
||||||
- app/assets/javascripts/node_modules
|
|
||||||
rvm:
|
|
||||||
- 2.3.0
|
|
||||||
before_script:
|
|
||||||
- echo "Rspec setup"
|
|
||||||
- export RAILS_ENV=test
|
|
||||||
- cp .example-env .env
|
|
||||||
- bundle exec rake db:create
|
|
||||||
- bundle exec rake db:schema:load
|
|
||||||
- echo "node setup"
|
|
||||||
- . $HOME/.nvm/nvm.sh
|
|
||||||
- nvm install stable
|
|
||||||
- nvm use stable
|
|
||||||
- npm install --no-optional
|
|
||||||
script:
|
|
||||||
- bundle exec rspec && bundle exec brakeman -q -z && npm test
|
|
||||||
addons:
|
|
||||||
code_climate:
|
|
||||||
repo_token: 479d3bf56798fbc7fff3fc8151a5ed09e8ac368fd5af332c437b9e07dbebb44e
|
|
||||||
postgresql: "9.4"
|
|
93
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
# Contributing to Metamaps
|
||||||
|
|
||||||
|
Active involvement from the community is essential to help make Metamaps as beneficial for communities as it can be. You can help by reporting bugs, fixing bugs, adding features, contributing new modules and by providing feedback.
|
||||||
|
|
||||||
|
|
||||||
|
## Reporting bugs and other issues
|
||||||
|
|
||||||
|
If you think you've encountered a bug, do the following:
|
||||||
|
|
||||||
|
1. Make sure you are working with the latest version of the Metamaps `master` branch.
|
||||||
|
2. Browse through the [issues][metamaps-issues] to check if
|
||||||
|
anyone else has already reported. If someone has, feel free to add more
|
||||||
|
information to that issue to help us solve it.
|
||||||
|
3. If no one has yet submitted the issue you are encountering, add it in! Please be sure
|
||||||
|
to include as much information as possible, include errors, warnings,
|
||||||
|
screenshots, links to a video showing the problem or code that can reproduce
|
||||||
|
the issue.
|
||||||
|
|
||||||
|
|
||||||
|
## Contributing code
|
||||||
|
|
||||||
|
Metamaps is made possible by open source
|
||||||
|
contributors like you. We're very interested in getting help from the greater
|
||||||
|
community, but before you start it's important that you become acquainted with
|
||||||
|
our workflow. Following these guidelines below will make collaboration much
|
||||||
|
smoother and increase the chances that we will accept your pull request without
|
||||||
|
hiccups.
|
||||||
|
|
||||||
|
|
||||||
|
### Development Process
|
||||||
|
|
||||||
|
Our development process is very similar to the approach
|
||||||
|
described in the well-known article [A Successful Git Branching Model by Vincent
|
||||||
|
Driessen][git-branching-model]. Here's an overview:
|
||||||
|
|
||||||
|
* Our `master` branch is the branch upon which
|
||||||
|
Metamaps developers should be basing their work on. The `master` branch is not guaranteed to be stable.
|
||||||
|
* All commits intended for `master` should take place on your own personal
|
||||||
|
fork, and be submitted via pull request when ready.
|
||||||
|
* Only maintainers can accept pull requests from forks into the core Metamaps.cc
|
||||||
|
repository.
|
||||||
|
* Please squash your commits into a single commit before making a pull request.
|
||||||
|
|
||||||
|
### Getting started
|
||||||
|
|
||||||
|
1. Make sure you have a [GitHub account](https://github.com/signup/free)
|
||||||
|
2. [Fork metamaps][fork-metamaps]
|
||||||
|
3. Keep your fork up to date. Metamaps is a fast moving project, and things are
|
||||||
|
changing all the time. It's important that any changes you make are based on
|
||||||
|
the most recent version of metamaps, since it's possible that something may
|
||||||
|
have changed that breaks your pull request or invalidates its need.
|
||||||
|
4. Make sure you have a [Contributor License Agreement](http://caa.metamaps.cc) on file.
|
||||||
|
5. Read on ...
|
||||||
|
|
||||||
|
|
||||||
|
### Contributor License Agreement
|
||||||
|
|
||||||
|
Before we can accept any contributions to Metamaps, we first require that all
|
||||||
|
individuals or companies agree to our Contributor License Agreement (CLA). The e-mail
|
||||||
|
address used in the pull request will be used to check if a CLA has already been
|
||||||
|
filed, so be sure to list all email addresses that you might use to submit your
|
||||||
|
pull requests when filling it out. Our CLA can be found [here](http://caa.metamaps.cc).
|
||||||
|
|
||||||
|
### Testing and Linting
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
|
||||||
|
### Branch grouping tokens
|
||||||
|
|
||||||
|
All pull requests submitted to Metamaps.cc should occur on a new branch. For these
|
||||||
|
branches, we at metamaps use a short token indicating the nature of the branch in
|
||||||
|
question followed by a solidus (`/`) and a kebab-cased string describing the
|
||||||
|
branch. We are using the following tokens:
|
||||||
|
**NOTE: Not sure the above is right, but also not sure what to change it to **
|
||||||
|
|
||||||
|
bug // bug fixes
|
||||||
|
wip // work in progress
|
||||||
|
feat // feature
|
||||||
|
|
||||||
|
Bug fixes follow a [slightly different format](#bug-fixes).
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
If you'd like to contribute a fix for a bug you've encountered, first read up on
|
||||||
|
[how to report a bug](#reporting-bugs-and-other-issues) and report it so we are
|
||||||
|
aware of the issue. By filing the issue first, we may be able to provide you
|
||||||
|
with some insight that guides you in the right direction.
|
||||||
|
|
||||||
|
[metamaps-issues]: https://github.com/metamaps/metamaps_gen002/issues
|
||||||
|
[git-branching-model]: http://nvie.com/posts/a-successful-git-branching-model/
|
||||||
|
[fork-metamaps]: https://github.com/metamaps/metamaps_gen002/fork
|
||||||
|
[cla]: http://metamaps.cc/cla
|
96
Gemfile
|
@ -1,57 +1,59 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
ruby '2.3.0'
|
ruby '2.1.3'
|
||||||
|
|
||||||
gem 'rails', '~> 5.0.0'
|
gem 'rails', '3.2.17'
|
||||||
|
|
||||||
|
# Bundle edge Rails instead:
|
||||||
|
# gem 'rails', :git => 'git://github.com/rails/rails.git'
|
||||||
|
|
||||||
gem 'active_model_serializers'
|
|
||||||
gem 'aws-sdk', '~> 2.7.0'
|
|
||||||
gem 'best_in_place'
|
|
||||||
gem 'delayed_job'
|
|
||||||
gem 'delayed_job_active_record'
|
|
||||||
gem 'devise'
|
gem 'devise'
|
||||||
gem 'doorkeeper'
|
gem 'redis'
|
||||||
gem 'dotenv-rails'
|
|
||||||
gem 'exception_notification'
|
|
||||||
gem 'httparty'
|
|
||||||
gem 'json'
|
|
||||||
gem 'kaminari'
|
|
||||||
gem 'mailboxer'
|
|
||||||
gem 'paperclip'
|
|
||||||
gem 'pg'
|
gem 'pg'
|
||||||
gem 'puma'
|
gem 'cancan'
|
||||||
gem 'pundit'
|
gem 'formula'
|
||||||
gem 'pundit_extra'
|
gem 'formtastic'
|
||||||
gem 'rack-attack'
|
gem 'json'
|
||||||
gem 'rack-cors'
|
gem 'rails3-jquery-autocomplete'
|
||||||
gem 'redis', '~> 3.3.3'
|
gem 'best_in_place' #in-place editing
|
||||||
gem 'slack-notifier'
|
gem 'kaminari' # pagination
|
||||||
gem 'snorlax'
|
gem 'uservoice-ruby'
|
||||||
gem 'sucker_punch'
|
|
||||||
|
|
||||||
# asset stuff
|
gem 'paperclip'
|
||||||
gem 'jquery-rails'
|
gem 'aws-sdk'
|
||||||
gem 'jquery-ui-rails'
|
|
||||||
gem 'sass-rails'
|
|
||||||
gem 'uglifier'
|
|
||||||
|
|
||||||
group :test do
|
#gem 'therubyracer' #optional
|
||||||
gem 'brakeman', require: false
|
#gem 'rb-readline'
|
||||||
gem 'factory_bot_rails'
|
|
||||||
gem 'json-schema'
|
# Gems used only for assets and not required
|
||||||
gem 'rspec-rails'
|
# in production environments by default.
|
||||||
gem 'shoulda-matchers'
|
group :assets do
|
||||||
gem 'simplecov', require: false
|
gem 'sass-rails'
|
||||||
|
gem 'coffee-rails', '~> 3.2.1'
|
||||||
|
|
||||||
|
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
|
||||||
|
# gem 'therubyracer'
|
||||||
|
|
||||||
|
gem 'uglifier', '>= 1.0.3'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development, :test do
|
group :production do #this is used on heroku
|
||||||
gem 'better_errors'
|
#gem 'rmagick'
|
||||||
gem 'binding_of_caller'
|
|
||||||
gem 'faker'
|
|
||||||
gem 'pry-byebug'
|
|
||||||
gem 'pry-rails'
|
|
||||||
gem 'rubocop', '~> 0.48.1' # match code climate https://github.com/tootsuite/mastodon/issues/1758
|
|
||||||
gem 'timecop'
|
|
||||||
gem 'tunemygc'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
gem 'jquery-rails', '2.1.2'
|
||||||
|
|
||||||
|
# To use ActiveModel has_secure_password
|
||||||
|
# gem 'bcrypt-ruby', '~> 3.0.0'
|
||||||
|
|
||||||
|
# To use Jbuilder templates for JSON
|
||||||
|
gem 'jbuilder', '0.8.2'
|
||||||
|
|
||||||
|
# Use unicorn as the web server
|
||||||
|
# gem 'unicorn'
|
||||||
|
|
||||||
|
# Deploy with Capistrano
|
||||||
|
# gem 'capistrano'
|
||||||
|
|
||||||
|
# To use debugger
|
||||||
|
# gem 'ruby-debug19', :require => 'ruby-debug'
|
||||||
|
|
||||||
|
|
487
Gemfile.lock
|
@ -1,350 +1,181 @@
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (5.0.5)
|
actionmailer (3.2.17)
|
||||||
actionpack (= 5.0.5)
|
actionpack (= 3.2.17)
|
||||||
nio4r (>= 1.2, < 3.0)
|
mail (~> 2.5.4)
|
||||||
websocket-driver (~> 0.6.1)
|
actionpack (3.2.17)
|
||||||
actionmailer (5.0.5)
|
activemodel (= 3.2.17)
|
||||||
actionpack (= 5.0.5)
|
activesupport (= 3.2.17)
|
||||||
actionview (= 5.0.5)
|
builder (~> 3.0.0)
|
||||||
activejob (= 5.0.5)
|
|
||||||
mail (~> 2.5, >= 2.5.4)
|
|
||||||
rails-dom-testing (~> 2.0)
|
|
||||||
actionpack (5.0.5)
|
|
||||||
actionview (= 5.0.5)
|
|
||||||
activesupport (= 5.0.5)
|
|
||||||
rack (~> 2.0)
|
|
||||||
rack-test (~> 0.6.3)
|
|
||||||
rails-dom-testing (~> 2.0)
|
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
|
||||||
actionview (5.0.5)
|
|
||||||
activesupport (= 5.0.5)
|
|
||||||
builder (~> 3.1)
|
|
||||||
erubis (~> 2.7.0)
|
erubis (~> 2.7.0)
|
||||||
rails-dom-testing (~> 2.0)
|
journey (~> 1.0.4)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
rack (~> 1.4.5)
|
||||||
active_model_serializers (0.10.6)
|
rack-cache (~> 1.2)
|
||||||
actionpack (>= 4.1, < 6)
|
rack-test (~> 0.6.1)
|
||||||
activemodel (>= 4.1, < 6)
|
sprockets (~> 2.2.1)
|
||||||
case_transform (>= 0.2)
|
activemodel (3.2.17)
|
||||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
|
activesupport (= 3.2.17)
|
||||||
activejob (5.0.5)
|
builder (~> 3.0.0)
|
||||||
activesupport (= 5.0.5)
|
activerecord (3.2.17)
|
||||||
globalid (>= 0.3.6)
|
activemodel (= 3.2.17)
|
||||||
activemodel (5.0.5)
|
activesupport (= 3.2.17)
|
||||||
activesupport (= 5.0.5)
|
arel (~> 3.0.2)
|
||||||
activerecord (5.0.5)
|
tzinfo (~> 0.3.29)
|
||||||
activemodel (= 5.0.5)
|
activeresource (3.2.17)
|
||||||
activesupport (= 5.0.5)
|
activemodel (= 3.2.17)
|
||||||
arel (~> 7.0)
|
activesupport (= 3.2.17)
|
||||||
activesupport (5.0.5)
|
activesupport (3.2.17)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
i18n (~> 0.6, >= 0.6.4)
|
||||||
i18n (~> 0.7)
|
multi_json (~> 1.0)
|
||||||
minitest (~> 5.1)
|
arel (3.0.3)
|
||||||
tzinfo (~> 1.1)
|
aws-sdk (1.54.0)
|
||||||
addressable (2.5.2)
|
aws-sdk-v1 (= 1.54.0)
|
||||||
public_suffix (>= 2.0.2, < 4.0)
|
aws-sdk-v1 (1.54.0)
|
||||||
arel (7.1.4)
|
json (~> 1.4)
|
||||||
ast (2.3.0)
|
nokogiri (>= 1.4.4)
|
||||||
aws-sdk (2.7.0)
|
bcrypt (3.1.7)
|
||||||
aws-sdk-resources (= 2.7.0)
|
bcrypt (3.1.7-x86-mingw32)
|
||||||
aws-sdk-core (2.7.0)
|
best_in_place (2.1.0)
|
||||||
aws-sigv4 (~> 1.0)
|
jquery-rails
|
||||||
jmespath (~> 1.0)
|
rails (~> 3.1)
|
||||||
aws-sdk-resources (2.7.0)
|
builder (3.0.4)
|
||||||
aws-sdk-core (= 2.7.0)
|
cancan (1.6.10)
|
||||||
aws-sigv4 (1.0.2)
|
climate_control (0.0.3)
|
||||||
bcrypt (3.1.11)
|
activesupport (>= 3.0)
|
||||||
best_in_place (3.1.1)
|
cocaine (0.5.4)
|
||||||
actionpack (>= 3.2)
|
|
||||||
railties (>= 3.2)
|
|
||||||
better_errors (2.3.0)
|
|
||||||
coderay (>= 1.0.0)
|
|
||||||
erubi (>= 1.0.0)
|
|
||||||
rack (>= 0.9.0)
|
|
||||||
binding_of_caller (0.7.2)
|
|
||||||
debug_inspector (>= 0.0.1)
|
|
||||||
brakeman (3.7.2)
|
|
||||||
builder (3.2.3)
|
|
||||||
byebug (9.1.0)
|
|
||||||
carrierwave (1.1.0)
|
|
||||||
activemodel (>= 4.0.0)
|
|
||||||
activesupport (>= 4.0.0)
|
|
||||||
mime-types (>= 1.16)
|
|
||||||
case_transform (0.2)
|
|
||||||
activesupport
|
|
||||||
climate_control (0.2.0)
|
|
||||||
cocaine (0.5.8)
|
|
||||||
climate_control (>= 0.0.3, < 1.0)
|
climate_control (>= 0.0.3, < 1.0)
|
||||||
coderay (1.1.2)
|
coffee-rails (3.2.2)
|
||||||
concurrent-ruby (1.0.5)
|
coffee-script (>= 2.2.0)
|
||||||
debug_inspector (0.0.3)
|
railties (~> 3.2.0)
|
||||||
delayed_job (4.1.3)
|
coffee-script (2.3.0)
|
||||||
activesupport (>= 3.0, < 5.2)
|
coffee-script-source
|
||||||
delayed_job_active_record (4.1.2)
|
execjs
|
||||||
activerecord (>= 3.0, < 5.2)
|
coffee-script-source (1.8.0)
|
||||||
delayed_job (>= 3.0, < 5)
|
devise (3.4.0)
|
||||||
devise (4.3.0)
|
|
||||||
bcrypt (~> 3.0)
|
bcrypt (~> 3.0)
|
||||||
orm_adapter (~> 0.1)
|
orm_adapter (~> 0.1)
|
||||||
railties (>= 4.1.0, < 5.2)
|
railties (>= 3.2.6, < 5)
|
||||||
responders
|
responders
|
||||||
warden (~> 1.2.3)
|
|
||||||
diff-lcs (1.3)
|
|
||||||
docile (1.1.5)
|
|
||||||
doorkeeper (4.2.6)
|
|
||||||
railties (>= 4.2)
|
|
||||||
dotenv (2.2.1)
|
|
||||||
dotenv-rails (2.2.1)
|
|
||||||
dotenv (= 2.2.1)
|
|
||||||
railties (>= 3.2, < 5.2)
|
|
||||||
erubi (1.6.1)
|
|
||||||
erubis (2.7.0)
|
|
||||||
exception_notification (4.2.2)
|
|
||||||
actionmailer (>= 4.0, < 6)
|
|
||||||
activesupport (>= 4.0, < 6)
|
|
||||||
execjs (2.7.0)
|
|
||||||
factory_bot (4.8.2)
|
|
||||||
activesupport (>= 3.0.0)
|
|
||||||
factory_bot_rails (4.8.2)
|
|
||||||
factory_bot (~> 4.8.2)
|
|
||||||
railties (>= 3.0.0)
|
|
||||||
faker (1.8.4)
|
|
||||||
i18n (~> 0.5)
|
|
||||||
ffi (1.9.18)
|
|
||||||
globalid (0.4.0)
|
|
||||||
activesupport (>= 4.2.0)
|
|
||||||
httparty (0.15.6)
|
|
||||||
multi_xml (>= 0.5.2)
|
|
||||||
i18n (0.9.3)
|
|
||||||
concurrent-ruby (~> 1.0)
|
|
||||||
jmespath (1.3.1)
|
|
||||||
jquery-rails (4.3.1)
|
|
||||||
rails-dom-testing (>= 1, < 3)
|
|
||||||
railties (>= 4.2.0)
|
|
||||||
thor (>= 0.14, < 2.0)
|
|
||||||
jquery-ui-rails (6.0.1)
|
|
||||||
railties (>= 3.2.16)
|
|
||||||
json (2.1.0)
|
|
||||||
json-schema (2.8.0)
|
|
||||||
addressable (>= 2.4)
|
|
||||||
jsonapi-renderer (0.1.3)
|
|
||||||
kaminari (1.0.1)
|
|
||||||
activesupport (>= 4.1.0)
|
|
||||||
kaminari-actionview (= 1.0.1)
|
|
||||||
kaminari-activerecord (= 1.0.1)
|
|
||||||
kaminari-core (= 1.0.1)
|
|
||||||
kaminari-actionview (1.0.1)
|
|
||||||
actionview
|
|
||||||
kaminari-core (= 1.0.1)
|
|
||||||
kaminari-activerecord (1.0.1)
|
|
||||||
activerecord
|
|
||||||
kaminari-core (= 1.0.1)
|
|
||||||
kaminari-core (1.0.1)
|
|
||||||
loofah (2.0.3)
|
|
||||||
nokogiri (>= 1.5.9)
|
|
||||||
mail (2.6.6)
|
|
||||||
mime-types (>= 1.16, < 4)
|
|
||||||
mailboxer (0.15.1)
|
|
||||||
carrierwave (>= 0.5.8)
|
|
||||||
rails (>= 5.0.0)
|
|
||||||
method_source (0.8.2)
|
|
||||||
mime-types (3.1)
|
|
||||||
mime-types-data (~> 3.2015)
|
|
||||||
mime-types-data (3.2016.0521)
|
|
||||||
mimemagic (0.3.2)
|
|
||||||
mini_portile2 (2.3.0)
|
|
||||||
minitest (5.11.1)
|
|
||||||
multi_xml (0.6.0)
|
|
||||||
nio4r (2.1.0)
|
|
||||||
nokogiri (1.8.1)
|
|
||||||
mini_portile2 (~> 2.3.0)
|
|
||||||
orm_adapter (0.5.0)
|
|
||||||
paperclip (5.2.0)
|
|
||||||
activemodel (>= 4.2.0)
|
|
||||||
activesupport (>= 4.2.0)
|
|
||||||
cocaine (~> 0.5.5)
|
|
||||||
mime-types
|
|
||||||
mimemagic (~> 0.3.0)
|
|
||||||
parser (2.4.0.2)
|
|
||||||
ast (~> 2.3)
|
|
||||||
pg (0.21.0)
|
|
||||||
powerpack (0.1.1)
|
|
||||||
pry (0.10.4)
|
|
||||||
coderay (~> 1.1.0)
|
|
||||||
method_source (~> 0.8.1)
|
|
||||||
slop (~> 3.4)
|
|
||||||
pry-byebug (3.5.0)
|
|
||||||
byebug (~> 9.1)
|
|
||||||
pry (~> 0.10)
|
|
||||||
pry-rails (0.3.6)
|
|
||||||
pry (>= 0.10.4)
|
|
||||||
public_suffix (3.0.0)
|
|
||||||
puma (3.10.0)
|
|
||||||
pundit (1.1.0)
|
|
||||||
activesupport (>= 3.0.0)
|
|
||||||
pundit_extra (0.3.0)
|
|
||||||
rack (2.0.3)
|
|
||||||
rack-attack (5.0.1)
|
|
||||||
rack
|
|
||||||
rack-cors (1.0.1)
|
|
||||||
rack-test (0.6.3)
|
|
||||||
rack (>= 1.0)
|
|
||||||
rails (5.0.5)
|
|
||||||
actioncable (= 5.0.5)
|
|
||||||
actionmailer (= 5.0.5)
|
|
||||||
actionpack (= 5.0.5)
|
|
||||||
actionview (= 5.0.5)
|
|
||||||
activejob (= 5.0.5)
|
|
||||||
activemodel (= 5.0.5)
|
|
||||||
activerecord (= 5.0.5)
|
|
||||||
activesupport (= 5.0.5)
|
|
||||||
bundler (>= 1.3.0)
|
|
||||||
railties (= 5.0.5)
|
|
||||||
sprockets-rails (>= 2.0.0)
|
|
||||||
rails-dom-testing (2.0.3)
|
|
||||||
activesupport (>= 4.2.0)
|
|
||||||
nokogiri (>= 1.6)
|
|
||||||
rails-html-sanitizer (1.0.3)
|
|
||||||
loofah (~> 2.0)
|
|
||||||
railties (5.0.5)
|
|
||||||
actionpack (= 5.0.5)
|
|
||||||
activesupport (= 5.0.5)
|
|
||||||
method_source
|
|
||||||
rake (>= 0.8.7)
|
|
||||||
thor (>= 0.18.1, < 2.0)
|
|
||||||
rainbow (2.2.2)
|
|
||||||
rake
|
|
||||||
rake (12.3.0)
|
|
||||||
rb-fsevent (0.10.2)
|
|
||||||
rb-inotify (0.9.10)
|
|
||||||
ffi (>= 0.5.0, < 2)
|
|
||||||
redis (3.3.3)
|
|
||||||
responders (2.4.0)
|
|
||||||
actionpack (>= 4.2.0, < 5.3)
|
|
||||||
railties (>= 4.2.0, < 5.3)
|
|
||||||
rspec-core (3.6.0)
|
|
||||||
rspec-support (~> 3.6.0)
|
|
||||||
rspec-expectations (3.6.0)
|
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
|
||||||
rspec-support (~> 3.6.0)
|
|
||||||
rspec-mocks (3.6.0)
|
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
|
||||||
rspec-support (~> 3.6.0)
|
|
||||||
rspec-rails (3.6.1)
|
|
||||||
actionpack (>= 3.0)
|
|
||||||
activesupport (>= 3.0)
|
|
||||||
railties (>= 3.0)
|
|
||||||
rspec-core (~> 3.6.0)
|
|
||||||
rspec-expectations (~> 3.6.0)
|
|
||||||
rspec-mocks (~> 3.6.0)
|
|
||||||
rspec-support (~> 3.6.0)
|
|
||||||
rspec-support (3.6.0)
|
|
||||||
rubocop (0.48.1)
|
|
||||||
parser (>= 2.3.3.1, < 3.0)
|
|
||||||
powerpack (~> 0.1)
|
|
||||||
rainbow (>= 1.99.1, < 3.0)
|
|
||||||
ruby-progressbar (~> 1.7)
|
|
||||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
|
||||||
ruby-progressbar (1.9.0)
|
|
||||||
sass (3.5.1)
|
|
||||||
sass-listen (~> 4.0.0)
|
|
||||||
sass-listen (4.0.0)
|
|
||||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
|
||||||
rb-inotify (~> 0.9, >= 0.9.7)
|
|
||||||
sass-rails (5.0.6)
|
|
||||||
railties (>= 4.0.0, < 6)
|
|
||||||
sass (~> 3.1)
|
|
||||||
sprockets (>= 2.8, < 4.0)
|
|
||||||
sprockets-rails (>= 2.0, < 4.0)
|
|
||||||
tilt (>= 1.1, < 3)
|
|
||||||
shoulda-matchers (3.1.2)
|
|
||||||
activesupport (>= 4.0.0)
|
|
||||||
simplecov (0.15.0)
|
|
||||||
docile (~> 1.1.0)
|
|
||||||
json (>= 1.8, < 3)
|
|
||||||
simplecov-html (~> 0.10.0)
|
|
||||||
simplecov-html (0.10.2)
|
|
||||||
slack-notifier (2.3.1)
|
|
||||||
slop (3.6.0)
|
|
||||||
snorlax (0.1.6)
|
|
||||||
rails (> 4.1)
|
|
||||||
sprockets (3.7.1)
|
|
||||||
concurrent-ruby (~> 1.0)
|
|
||||||
rack (> 1, < 3)
|
|
||||||
sprockets-rails (3.2.1)
|
|
||||||
actionpack (>= 4.0)
|
|
||||||
activesupport (>= 4.0)
|
|
||||||
sprockets (>= 3.0.0)
|
|
||||||
sucker_punch (2.0.3)
|
|
||||||
concurrent-ruby (~> 1.0.0)
|
|
||||||
thor (0.20.0)
|
|
||||||
thread_safe (0.3.6)
|
|
||||||
tilt (2.0.8)
|
|
||||||
timecop (0.9.1)
|
|
||||||
tunemygc (1.0.69)
|
|
||||||
tzinfo (1.2.4)
|
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
uglifier (3.2.0)
|
warden (~> 1.2.3)
|
||||||
execjs (>= 0.3.0, < 3)
|
erubis (2.7.0)
|
||||||
unicode-display_width (1.3.0)
|
execjs (2.2.1)
|
||||||
warden (1.2.7)
|
ezcrypto (0.7.2)
|
||||||
|
formtastic (3.0.0)
|
||||||
|
actionpack (>= 3.2.13)
|
||||||
|
formula (1.0.1)
|
||||||
|
rails (> 3.0.0)
|
||||||
|
hike (1.2.3)
|
||||||
|
i18n (0.6.11)
|
||||||
|
jbuilder (0.8.2)
|
||||||
|
activesupport (>= 3.0.0)
|
||||||
|
journey (1.0.4)
|
||||||
|
jquery-rails (2.1.2)
|
||||||
|
railties (>= 3.1.0, < 5.0)
|
||||||
|
thor (~> 0.14)
|
||||||
|
json (1.8.1)
|
||||||
|
kaminari (0.16.1)
|
||||||
|
actionpack (>= 3.0.0)
|
||||||
|
activesupport (>= 3.0.0)
|
||||||
|
mail (2.5.4)
|
||||||
|
mime-types (~> 1.16)
|
||||||
|
treetop (~> 1.4.8)
|
||||||
|
mime-types (1.25.1)
|
||||||
|
mini_portile (0.6.0)
|
||||||
|
multi_json (1.10.1)
|
||||||
|
nokogiri (1.6.3.1)
|
||||||
|
mini_portile (= 0.6.0)
|
||||||
|
nokogiri (1.6.3.1-x86-mingw32)
|
||||||
|
mini_portile (= 0.6.0)
|
||||||
|
oauth (0.4.7)
|
||||||
|
orm_adapter (0.5.0)
|
||||||
|
paperclip (4.2.0)
|
||||||
|
activemodel (>= 3.0.0)
|
||||||
|
activesupport (>= 3.0.0)
|
||||||
|
cocaine (~> 0.5.3)
|
||||||
|
mime-types
|
||||||
|
pg (0.17.1)
|
||||||
|
pg (0.17.1-x86-mingw32)
|
||||||
|
polyglot (0.3.5)
|
||||||
|
rack (1.4.5)
|
||||||
|
rack-cache (1.2)
|
||||||
|
rack (>= 0.4)
|
||||||
|
rack-ssl (1.3.4)
|
||||||
|
rack
|
||||||
|
rack-test (0.6.2)
|
||||||
|
rack (>= 1.0)
|
||||||
|
rails (3.2.17)
|
||||||
|
actionmailer (= 3.2.17)
|
||||||
|
actionpack (= 3.2.17)
|
||||||
|
activerecord (= 3.2.17)
|
||||||
|
activeresource (= 3.2.17)
|
||||||
|
activesupport (= 3.2.17)
|
||||||
|
bundler (~> 1.0)
|
||||||
|
railties (= 3.2.17)
|
||||||
|
rails3-jquery-autocomplete (1.0.14)
|
||||||
|
rails (>= 3.0)
|
||||||
|
railties (3.2.17)
|
||||||
|
actionpack (= 3.2.17)
|
||||||
|
activesupport (= 3.2.17)
|
||||||
|
rack-ssl (~> 1.3.2)
|
||||||
|
rake (>= 0.8.7)
|
||||||
|
rdoc (~> 3.4)
|
||||||
|
thor (>= 0.14.6, < 2.0)
|
||||||
|
rake (10.3.2)
|
||||||
|
rdoc (3.12.2)
|
||||||
|
json (~> 1.4)
|
||||||
|
redis (3.1.0)
|
||||||
|
responders (1.1.1)
|
||||||
|
railties (>= 3.2, < 4.2)
|
||||||
|
sass (3.4.5)
|
||||||
|
sass-rails (3.2.6)
|
||||||
|
railties (~> 3.2.0)
|
||||||
|
sass (>= 3.1.10)
|
||||||
|
tilt (~> 1.3)
|
||||||
|
sprockets (2.2.2)
|
||||||
|
hike (~> 1.2)
|
||||||
|
multi_json (~> 1.0)
|
||||||
|
rack (~> 1.0)
|
||||||
|
tilt (~> 1.1, != 1.3.0)
|
||||||
|
thor (0.19.1)
|
||||||
|
thread_safe (0.3.4)
|
||||||
|
tilt (1.4.1)
|
||||||
|
treetop (1.4.15)
|
||||||
|
polyglot
|
||||||
|
polyglot (>= 0.3.1)
|
||||||
|
tzinfo (0.3.41)
|
||||||
|
uglifier (2.5.3)
|
||||||
|
execjs (>= 0.3.0)
|
||||||
|
json (>= 1.8.0)
|
||||||
|
uservoice-ruby (0.0.11)
|
||||||
|
ezcrypto (>= 0.7.2)
|
||||||
|
json (>= 1.7.5)
|
||||||
|
oauth (>= 0.4.7)
|
||||||
|
warden (1.2.3)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
websocket-driver (0.6.5)
|
|
||||||
websocket-extensions (>= 0.1.0)
|
|
||||||
websocket-extensions (0.1.2)
|
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
x86-mingw32
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
active_model_serializers
|
aws-sdk
|
||||||
aws-sdk (~> 2.7.0)
|
|
||||||
best_in_place
|
best_in_place
|
||||||
better_errors
|
cancan
|
||||||
binding_of_caller
|
coffee-rails (~> 3.2.1)
|
||||||
brakeman
|
|
||||||
delayed_job
|
|
||||||
delayed_job_active_record
|
|
||||||
devise
|
devise
|
||||||
doorkeeper
|
formtastic
|
||||||
dotenv-rails
|
formula
|
||||||
exception_notification
|
jbuilder (= 0.8.2)
|
||||||
factory_bot_rails
|
jquery-rails (= 2.1.2)
|
||||||
faker
|
|
||||||
httparty
|
|
||||||
jquery-rails
|
|
||||||
jquery-ui-rails
|
|
||||||
json
|
json
|
||||||
json-schema
|
|
||||||
kaminari
|
kaminari
|
||||||
mailboxer
|
|
||||||
paperclip
|
paperclip
|
||||||
pg
|
pg
|
||||||
pry-byebug
|
rails (= 3.2.17)
|
||||||
pry-rails
|
rails3-jquery-autocomplete
|
||||||
puma
|
redis
|
||||||
pundit
|
|
||||||
pundit_extra
|
|
||||||
rack-attack
|
|
||||||
rack-cors
|
|
||||||
rails (~> 5.0.0)
|
|
||||||
redis (~> 3.3.3)
|
|
||||||
rspec-rails
|
|
||||||
rubocop (~> 0.48.1)
|
|
||||||
sass-rails
|
sass-rails
|
||||||
shoulda-matchers
|
uglifier (>= 1.0.3)
|
||||||
simplecov
|
uservoice-ruby
|
||||||
slack-notifier
|
|
||||||
snorlax
|
|
||||||
sucker_punch
|
|
||||||
timecop
|
|
||||||
tunemygc
|
|
||||||
uglifier
|
|
||||||
|
|
||||||
RUBY VERSION
|
|
||||||
ruby 2.3.0p0
|
|
||||||
|
|
||||||
BUNDLED WITH
|
|
||||||
1.16.1
|
|
||||||
|
|
42
MacInstallation.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
If you are doing an upgrade and or recent pull for changes you will need to change your default ruby package from 2.1.1 to ruby 2.1.2
|
||||||
|
|
||||||
|
install homebrew
|
||||||
|
|
||||||
|
\curl -sSL https://get.rvm.io | bash -s stable --rails
|
||||||
|
|
||||||
|
rvm install 2.1.3 --with-gcc=clang
|
||||||
|
|
||||||
|
rvm use 2.1.3
|
||||||
|
|
||||||
|
gem install lunchy
|
||||||
|
|
||||||
|
(http://www.moncefbelyamani.com/how-to-install-postgresql-on-a-mac-with-homebrew-and-lunchy/)
|
||||||
|
|
||||||
|
|
||||||
|
brew install postgresql
|
||||||
|
ln -sfv /usr/local/opt/postgresql/*.plist ~/Library/LaunchAgents
|
||||||
|
createuser metamaps -P -s -d
|
||||||
|
|
||||||
|
set a password
|
||||||
|
|
||||||
|
lunchy start postgres
|
||||||
|
|
||||||
|
|
||||||
|
cd into the metamaps directory
|
||||||
|
|
||||||
|
bundle install
|
||||||
|
|
||||||
|
|
||||||
|
copy the database.yml.default file and rename it database.yml
|
||||||
|
make sure the username and password match the POSTGRES username and password you set
|
||||||
|
|
||||||
|
|
||||||
|
http://nodejs.org/ hit install, download, open, install
|
||||||
|
|
||||||
|
|
||||||
|
rake db:create
|
||||||
|
rake db:schema:load
|
||||||
|
rake db:fixtures:load
|
||||||
|
rails s
|
||||||
|
|
||||||
|
( to start the server)
|
4
Procfile
|
@ -1,3 +1 @@
|
||||||
web: bundle exec puma -p $PORT
|
web: bundle exec rails server -p $PORT
|
||||||
worker: bundle exec rake jobs:work
|
|
||||||
|
|
||||||
|
|
97
README.md
|
@ -1,62 +1,77 @@
|
||||||
Metamaps
|
Metamaps
|
||||||
=======
|
=======
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/metamaps/metamaps.svg?branch=develop)](https://travis-ci.org/metamaps/metamaps)
|
[![Join the chat at https://gitter.im/metamaps/metamaps_gen002](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/metamaps/metamaps_gen002?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
[![Code Climate](https://codeclimate.com/github/metamaps/metamaps/badges/gpa.svg)](https://codeclimate.com/github/metamaps/metamaps)
|
|
||||||
|
|
||||||
## What is Metamaps?
|
Welcome to the Metamaps GitHub repo.
|
||||||
|
|
||||||
Metamaps is a free and open-source technology for changemakers, innovators, educators and students. It enables individuals and communities to build and visualize their shared knowledge and unlock their collective intelligence.
|
## About
|
||||||
|
|
||||||
You can find a version of this software running at [metamaps.cc][site-beta], where the technology is being tested in an open beta.
|
Metamaps is a free and AGPL open source technology for changemakers, innovators, educators and students. It enables individuals and communities to build and visualize their shared knowledge and unlock their collective intelligence. You can find out about more about the project at the [blog][site-blog].
|
||||||
|
|
||||||
Metamaps is developed and maintained by a distributed, nomadic community comprised of technologists, artists and storytellers. You can get in touch by using whichever of these channels you prefer:
|
You can find a version of this software running at [metamaps.cc][site-beta], where the technology is being tested in a private beta.
|
||||||
|
|
||||||
## How do I learn more?
|
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.
|
||||||
|
|
||||||
- Contact: [team@metamaps.cc](mailto:team@metamaps.cc) or [@metamapps](https://twitter.com/metamapps) on Twitter
|
|
||||||
- User Documentation: [docs.metamaps.cc](https://docs.metamaps.cc)
|
|
||||||
- User Community: [hylo.com/c/metamaps](https://www.hylo.com/c/metamaps)
|
|
||||||
- To see what we're developing, or to weigh in on what you'd like to see developed, see our [Metamaps Feedback and Features](https://trello.com/b/uFOA6a2x/metamaps-feedback-feature-ideas-requests) board on trello
|
|
||||||
- To follow along with, or contribute,to our design process, see our [Metamaps Design](https://trello.com/b/8HlCikOX/metamaps-design) board on trello
|
|
||||||
- To follow along with, or contribute to, our development process, see our [Github Issues and Pull Requests](https://github.com/metamaps/metamaps/issues)
|
|
||||||
- Request an invite to the open beta [here](https://metamaps.cc/request)
|
|
||||||
|
|
||||||
<!-- markdown hack to split two lists -->
|
To get connected with the community interested in Metamaps, join our [Google+ community][community].
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
If you are on Mac or Ubuntu you can use the following instructions to quickly get a local copy of metamaps up and running using a Vagrant virtualbox. Don't be intimidated, it's easy!
|
||||||
|
```
|
||||||
|
git clone git@github.com:metamaps/metamaps_gen002.git
|
||||||
|
```
|
||||||
|
Now ensure you have VirtualBox and Vagrant installed on your computer
|
||||||
|
```
|
||||||
|
cd metamaps_gen002
|
||||||
|
./configure.sh
|
||||||
|
```
|
||||||
|
This will do all the setup steps to make Metamaps work with a bit of behind the scenes ninja magick.
|
||||||
|
|
||||||
|
To start servers which will run metamaps you can then run:
|
||||||
|
```
|
||||||
|
./bin/start
|
||||||
|
```
|
||||||
|
To stop them:
|
||||||
|
```
|
||||||
|
./bin/stop
|
||||||
|
```
|
||||||
|
With your webservers running, open a web browser and go to `http://localhost:3000`
|
||||||
|
|
||||||
|
You can sign in with the default account
|
||||||
|
email: `user@user.com`
|
||||||
|
password: `toolsplusconsciousness`
|
||||||
|
OR create a new account at `/join`, and use access code `qwertyui`
|
||||||
|
|
||||||
|
Start mapping and programming!
|
||||||
|
|
||||||
|
While we are still figuring out vagrant for Windows, there is an older set of instructions below
|
||||||
|
- [For Windows][windows-installation]
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Cloning this repository directly is primarily for those wishing to contribute to our codebase. Check out our [contributing instructions][contributing] to get involved.
|
||||||
|
|
||||||
|
## Community
|
||||||
|
|
||||||
- To send us a personal message get in touch with us via email, Twitter, or Hylo
|
|
||||||
- If you would like to report a bug, please check the [issues][contributing-issues] section in our [contributing instructions][contributing].
|
- If you would like to report a bug, please check the [issues][contributing-issues] section in our [contributing instructions][contributing].
|
||||||
- If you would like to get set up as a developer, that's great! Read on for help getting your development environment set up.
|
- To participate in discussions and a public forum about Metamaps, join the [Google+ community][community]
|
||||||
|
- For contributors, read more instructions in [CONTRIBUTING.md][contributing].
|
||||||
## Installation for local use or development of Metamaps
|
|
||||||
|
|
||||||
First off is getting the code downloaded to your computer. You can download a zip file from github, but if you've got `git` you can just run `git clone https://github.com/metamaps/metamaps` in your terminal.
|
|
||||||
|
|
||||||
There are instructions for setup on various platforms, with particular support for Mac and Ubuntu, which can be found here:
|
|
||||||
- [Mac Install Walkthrough][mac-installation]
|
|
||||||
- [Ubuntu Install Walkthrough][ubuntu-installation]
|
|
||||||
|
|
||||||
If you prefer to isolate your install in a virtual machine, you may find it simpler to setup using Vagrant:
|
|
||||||
- [Vagrant installation][vagrant-installation]
|
|
||||||
|
|
||||||
We don't promise support for Windows, but at one point we had it running and we've kept those docs available for reference
|
|
||||||
- [Outdated Windows Walkthrough][windows-installation]
|
|
||||||
|
|
||||||
## Licensing information
|
## Licensing information
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
||||||
|
|
||||||
The license can be read [here][license].
|
The license can be read [here][license].
|
||||||
|
|
||||||
Copyright (c) 2017 Connor Turland
|
Copyright (c) 2015 Connor Turland
|
||||||
|
|
||||||
|
|
||||||
|
[site-blog]: http://blog.metamaps.cc
|
||||||
[site-beta]: http://metamaps.cc
|
[site-beta]: http://metamaps.cc
|
||||||
[license]: https://github.com/metamaps/metamaps/blob/develop/LICENSE
|
[community]: https://plus.google.com/u/0/communities/115060009262157699234
|
||||||
[contributing]: https://github.com/metamaps/metamaps/blob/develop/doc/CONTRIBUTING.md
|
[license]: https://github.com/metamaps/metamaps_gen002/blob/master/LICENSE
|
||||||
[contributing-issues]: https://github.com/metamaps/metamaps/blob/develop/doc/CONTRIBUTING.md#reporting-bugs-and-other-issues
|
[contributing]: https://github.com/metamaps/metamaps_gen002/blob/master/CONTRIBUTING.md
|
||||||
[mac-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/MacInstallation.md
|
[contributing-issues]: https://github.com/metamaps/metamaps_gen002/blob/master/CONTRIBUTING.md#reporting-bugs-and-other-issues
|
||||||
[ubuntu-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/UbuntuInstallation.md
|
[windows-installation]: https://github.com/metamaps/metamaps_gen002/blob/master/WindowsInstallation.md
|
||||||
[vagrant-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/VagrantInstallation.md
|
|
||||||
[windows-installation]: https://github.com/metamaps/metamaps/blob/develop/doc/WindowsInstallation.md
|
|
||||||
|
|
2
Rakefile
Executable file → Normal file
|
@ -1,6 +1,4 @@
|
||||||
#!/usr/bin/env rake
|
#!/usr/bin/env rake
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
||||||
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
||||||
|
|
||||||
|
|
114
UbuntuInstallation.md
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
Firstly this walkthrough is done with a 14.04 32bit install of Ubuntu.
|
||||||
|
|
||||||
|
All commands that I could are terminal based.
|
||||||
|
|
||||||
|
Lets check if all updates for the system are installed first
|
||||||
|
|
||||||
|
in terminal type
|
||||||
|
|
||||||
|
sudo apt-get update
|
||||||
|
|
||||||
|
now we need to install git
|
||||||
|
|
||||||
|
sudo apt-get install git
|
||||||
|
|
||||||
|
lets get our RVM installed (Ruby Version Manager) now this is fun because the package you will get from apt-get is outdated.
|
||||||
|
|
||||||
|
so we are going to use CURL to get RVM
|
||||||
|
|
||||||
|
sudo apt-get install curl
|
||||||
|
|
||||||
|
then lets install RVM with curl like this
|
||||||
|
|
||||||
|
curl -L get.rvm.io | bash -s stable
|
||||||
|
|
||||||
|
PATH=$PATH:$HOME/.rvm/bin
|
||||||
|
|
||||||
|
[[ -s "$HOME/.profile" ]] && source "$HOME/.profile"
|
||||||
|
|
||||||
|
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
|
||||||
|
|
||||||
|
source ~/.rvm/scripts/rvm
|
||||||
|
|
||||||
|
now we can actually install RVM
|
||||||
|
|
||||||
|
rvm requirements
|
||||||
|
|
||||||
|
running this will check your system for requirements as well so you will need to put your system password in.
|
||||||
|
|
||||||
|
alright now we can download metamaps from the master using git
|
||||||
|
|
||||||
|
git clone https://github.com/metamaps/metamaps_gen002.git
|
||||||
|
|
||||||
|
now there is a couple other things we are going to need which is nodejs, postgresql, libpq-dev and redis-server
|
||||||
|
|
||||||
|
sudo apt-get install nodejs
|
||||||
|
|
||||||
|
sudo apt-get install postgresql
|
||||||
|
|
||||||
|
sudo apt-get install libpq-dev
|
||||||
|
|
||||||
|
sudo apt-get install redis-server
|
||||||
|
|
||||||
|
Furthermore, if you want to be able to work on profile picture uploading, or use it
|
||||||
|
you'll need ImageMagick. On Ubuntu, you can just go find ImageMagick in the Ubuntu Software Centre
|
||||||
|
|
||||||
|
Install the specific version of ruby needed this will take some time
|
||||||
|
|
||||||
|
rvm install ruby-2.1.3
|
||||||
|
|
||||||
|
Now we also need to rename your database file which is in ./config/database.default.yml to database.yml
|
||||||
|
|
||||||
|
now run inside your metamaps_gen002 folder
|
||||||
|
|
||||||
|
bundle install
|
||||||
|
|
||||||
|
in your top lvl directory for metamaps this is a lengthy process so you might want to go and make a coffee or something :)
|
||||||
|
|
||||||
|
alright now we need to make sure your postgres password is the same as it is listed in the DB file so we are going to set it by
|
||||||
|
|
||||||
|
sudo -u postgres psql
|
||||||
|
|
||||||
|
Select postgres like this
|
||||||
|
|
||||||
|
\password postgres
|
||||||
|
|
||||||
|
set the password to 3112
|
||||||
|
|
||||||
|
Then to quit
|
||||||
|
|
||||||
|
\q
|
||||||
|
|
||||||
|
now we can run the rake install and db creation
|
||||||
|
|
||||||
|
rake db:create
|
||||||
|
|
||||||
|
rake db:schema:load
|
||||||
|
|
||||||
|
rake db:fixtures:load
|
||||||
|
|
||||||
|
Execute the server:
|
||||||
|
|
||||||
|
rails s
|
||||||
|
|
||||||
|
and dont forget to run the other server for realtime...
|
||||||
|
open a new terminal
|
||||||
|
navigate to ./realtime and run
|
||||||
|
|
||||||
|
sudo apt-get install npm
|
||||||
|
npm install
|
||||||
|
nodejs realtime-server.js
|
||||||
|
|
||||||
|
Now you're all set enjoy your personal server of metamaps :)
|
||||||
|
|
||||||
|
Navigate your browser to localhost:3000 once you have the server running
|
||||||
|
|
||||||
|
Sign in with the default account
|
||||||
|
|
||||||
|
email: user@user.com
|
||||||
|
|
||||||
|
password: toolsplusconsciousness
|
||||||
|
|
||||||
|
OR create a new account at /join, and use access code 'qwertyui'
|
||||||
|
|
||||||
|
Start mapping and programming!
|
20
Vagrantfile
vendored
|
@ -9,16 +9,14 @@ sudo apt-get install git curl -y
|
||||||
|
|
||||||
# rvm and ruby
|
# rvm and ruby
|
||||||
su - vagrant -c 'curl -sSL https://rvm.io/mpapis.asc | gpg --import -'
|
su - vagrant -c 'curl -sSL https://rvm.io/mpapis.asc | gpg --import -'
|
||||||
su - vagrant -c 'curl -sSL https://get.rvm.io | bash -s stable --ruby=2.3.0'
|
su - vagrant -c 'curl -sSL https://get.rvm.io | bash -s stable --ruby=2.1.3'
|
||||||
|
|
||||||
# install some other deps
|
# install some other deps
|
||||||
sudo apt-get install nodejs -y
|
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
|
|
||||||
sudo apt-get install imagemagick --fix-missing
|
|
||||||
|
|
||||||
# Install node
|
# Install node
|
||||||
ln -fs /usr/bin/nodejs /usr/bin/node
|
ln -fs /usr/bin/nodejs /usr/bin/node
|
||||||
|
@ -31,15 +29,15 @@ sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '3112';"
|
||||||
|
|
||||||
SCRIPT
|
SCRIPT
|
||||||
|
|
||||||
VAGRANTFILE_API_VERSION = '2'
|
VAGRANTFILE_API_VERSION = "2"
|
||||||
|
|
||||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||||
config.vm.box = 'trusty64'
|
config.vm.box = "trusty64"
|
||||||
config.vm.box_url = 'http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box'
|
config.vm.box_url = "http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box"
|
||||||
config.vm.network :forwarded_port, guest: 3000, host: 3000
|
config.vm.network :forwarded_port, guest: 3000, host: 3000
|
||||||
config.vm.network :forwarded_port, guest: 5000, host: 5000
|
config.vm.network :forwarded_port, guest: 5001, host: 5001
|
||||||
config.vm.network 'private_network', ip: '10.0.1.11'
|
config.vm.network "private_network", ip: "10.0.1.11"
|
||||||
config.vm.synced_folder '.', '/vagrant', nfs: true
|
config.vm.synced_folder ".", "/vagrant", :nfs => true
|
||||||
|
|
||||||
config.vm.provision 'shell', inline: $script
|
config.vm.provision "shell", inline: $script
|
||||||
end
|
end
|
||||||
|
|
49
WindowsInstallation.md
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
First off, Metamaps runs on Ruby On Rails. Ruby 2.1.3 and Rails 3.2. You'll need to get Ruby and Rails installed on your computer if you don't already have it. Go to here for Ruby http://rubyinstaller.org/downloads/
|
||||||
|
|
||||||
|
You'll also need GIT: http://git-scm.com/download/win
|
||||||
|
|
||||||
|
It uses postgreSQL 9.2 as a database. You can install that for your computer from here: http://www.enterprisedb.com/products-services-training/pgdownload . During installation you can choose whatever database password you like. Make sure to note it down!
|
||||||
|
|
||||||
|
Once you install those, open a 'command prompt with ruby'.
|
||||||
|
|
||||||
|
to install rails
|
||||||
|
gem install rails -v 3.2
|
||||||
|
|
||||||
|
also download node.js, which is also needed http://nodejs.org/download/
|
||||||
|
|
||||||
|
Navigate to the folder that you want to download the metamaps files to and run the following: (use your forked git repository address if it's different than this repo. You will also need to go to your Github account settings and add the SSH key that was placed in your clipboard earlier)
|
||||||
|
|
||||||
|
git clone https://github.com/metamaps/metamaps_gen002.git --branch develop
|
||||||
|
cd metamaps_gen002
|
||||||
|
|
||||||
|
Now you're in the main directory.
|
||||||
|
|
||||||
|
Install all the gems needed for Metamaps by running
|
||||||
|
|
||||||
|
bundle install
|
||||||
|
|
||||||
|
Setting up the database:
|
||||||
|
|
||||||
|
1) Copy /config/database.yml.default and rename the copy to /config/database.yml then edit database.yml with your text editor and set the password to whatever you chose when you set up the PostGres database.
|
||||||
|
|
||||||
|
2) In a terminal:
|
||||||
|
|
||||||
|
rake db:create
|
||||||
|
rake db:schema:load
|
||||||
|
rake db:fixtures:load
|
||||||
|
|
||||||
|
Running the server:
|
||||||
|
|
||||||
|
rails s
|
||||||
|
|
||||||
|
Navigate your browser to localhost:3000 once you have the server running
|
||||||
|
|
||||||
|
Sign in with the default account
|
||||||
|
|
||||||
|
email: user@user.com
|
||||||
|
|
||||||
|
password: toolsplusconsciousness
|
||||||
|
|
||||||
|
OR create a new account at /join, and use access code 'qwertyui'
|
||||||
|
|
||||||
|
Start mapping and programming!
|
|
@ -1,7 +0,0 @@
|
||||||
// eslint-disable spaced-comment
|
|
||||||
// JS and CSS bundles
|
|
||||||
//= link_directory ../javascripts .js
|
|
||||||
//= link_directory ../stylesheets .css
|
|
||||||
|
|
||||||
// Other
|
|
||||||
//= link_tree ../images
|
|
BIN
app/assets/images/.DS_Store
vendored
Normal file
Before Width: | Height: | Size: 322 B |
BIN
app/assets/images/arrowperms_sprite.png
Normal file
After Width: | Height: | Size: 543 B |
Before Width: | Height: | Size: 854 B |
Before Width: | Height: | Size: 780 B |
Before Width: | Height: | Size: 466 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 220 B |
BIN
app/assets/images/exploremaps_sprite.png
Normal file → Executable file
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 223 B |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3 KiB |
Before Width: | Height: | Size: 667 B |
Before Width: | Height: | Size: 822 B |
Before Width: | Height: | Size: 418 B |
Before Width: | Height: | Size: 717 B |
Before Width: | Height: | Size: 739 B |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 331 B |
BIN
app/assets/images/user_sprite.png
Normal file → Executable file
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 421 B |
|
@ -1,21 +0,0 @@
|
||||||
/* global Metamaps */
|
|
||||||
|
|
||||||
/* erb variables from rails */
|
|
||||||
Metamaps.ServerData = Metamaps.ServerData || {}
|
|
||||||
Metamaps.ServerData['junto_spinner_darkgrey.gif'] = '<%= asset_path('junto_spinner_darkgrey.gif') %>'
|
|
||||||
Metamaps.ServerData['user.png'] = '<%= asset_path('user.png') %>'
|
|
||||||
Metamaps.ServerData['icons/wildcard.png'] = '<%= asset_path('icons/wildcard.png') %>'
|
|
||||||
Metamaps.ServerData['topic_description_signifier.png'] = '<%= asset_path('topic_description_signifier.png') %>'
|
|
||||||
Metamaps.ServerData['topic_link_signifier.png'] = '<%= asset_path('topic_link_signifier.png') %>'
|
|
||||||
Metamaps.ServerData['synapse16.png'] = '<%= asset_path('synapse16.png') %>'
|
|
||||||
Metamaps.ServerData['sounds/MM_sounds.mp3'] = '<%= asset_path 'sounds/MM_sounds.mp3' %>'
|
|
||||||
Metamaps.ServerData['sounds/MM_sounds.ogg'] = '<%= asset_path 'sounds/MM_sounds.ogg' %>'
|
|
||||||
Metamaps.ServerData['exploremaps_sprite.png'] = '<%= asset_path 'exploremaps_sprite.png' %>'
|
|
||||||
Metamaps.ServerData['map_control_sprite.png'] = '<%= asset_path 'map_control_sprite.png' %>'
|
|
||||||
Metamaps.ServerData['user_sprite.png'] = '<%= asset_path 'user_sprite.png' %>'
|
|
||||||
Metamaps.ServerData.Metacodes = <%= Metacode.all.to_json.gsub(%r[(icon.*?)(\"},)], '\1?purple=stupid\2').html_safe %>
|
|
||||||
Metamaps.ServerData.REALTIME_SERVER = '<%= ENV['REALTIME_SERVER'] %>'
|
|
||||||
Metamaps.ServerData.RAILS_ENV = '<%= ENV['RAILS_ENV'] %>'
|
|
||||||
Metamaps.ServerData.VERSION = '<%= METAMAPS_VERSION %>'
|
|
||||||
Metamaps.ServerData.BUILD = '<%= METAMAPS_BUILD %>'
|
|
||||||
Metamaps.ServerData.LAST_UPDATED = '<%= METAMAPS_LAST_UPDATED %>'
|
|
|
@ -1,23 +0,0 @@
|
||||||
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
||||||
// listed below.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
||||||
// the compiled file.
|
|
||||||
//
|
|
||||||
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
|
||||||
// GO AFTER THE REQUIRES BELOW.
|
|
||||||
//
|
|
||||||
/* eslint-disable spaced-comment */
|
|
||||||
//= require jquery
|
|
||||||
//= require jquery-ui
|
|
||||||
//= require jquery_ujs
|
|
||||||
//= require action_cable
|
|
||||||
//= require_directory ./lib
|
|
||||||
//= require ./cloudcarousel-secret
|
|
||||||
//= require ./metamaps.secret.bundle
|
|
||||||
//= require ./Metamaps.ServerData
|
|
||||||
//= require homepageVimeoFallback
|
|
||||||
/* eslint-enable spaced-comment */
|
|
|
@ -1,22 +1,28 @@
|
||||||
// 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.
|
||||||
//
|
//
|
||||||
/* eslint-disable spaced-comment */
|
//= require jquery
|
||||||
//= require jquery
|
//= require jquery-ui
|
||||||
//= require jquery-ui
|
//= require jquery_ujs
|
||||||
//= require jquery_ujs
|
//= require ./orderedLibraries/underscore
|
||||||
//= require action_cable
|
//= require ./orderedLibraries/backbone
|
||||||
//= require_directory ./lib
|
//= require_directory ./lib
|
||||||
//= require ./webpacked/metamaps.bundle
|
//= require ./src/Metamaps.GlobalUI
|
||||||
//= require ./Metamaps.ServerData
|
//= require ./src/Metamaps.Router
|
||||||
//= require homepageVimeoFallback
|
//= require ./src/Metamaps.Backbone
|
||||||
/* eslint-enable spaced-comment */
|
//= require ./src/Metamaps.Views
|
||||||
|
//= require ./src/JIT
|
||||||
|
//= require ./src/Metamaps
|
||||||
|
//= require ./src/Metamaps.JIT
|
||||||
|
//= require_directory ./shims
|
||||||
|
//= require_directory ./require
|
||||||
|
//= require_directory ./famous
|
|
@ -1,438 +0,0 @@
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CloudCarousel V1.0.5
|
|
||||||
// (c) 2011 by R Cecco. <http://www.professorcloud.com>
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Reflection code based on plugin by Christophe Beyls <http://www.digitalia.be>
|
|
||||||
//
|
|
||||||
// Please retain this copyright header in all versions of the software
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
var matched, browser;
|
|
||||||
|
|
||||||
jQuery.uaMatch = function( ua ) {
|
|
||||||
ua = ua.toLowerCase();
|
|
||||||
|
|
||||||
var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
|
|
||||||
/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
|
|
||||||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
|
|
||||||
/(msie) ([\w.]+)/.exec( ua ) ||
|
|
||||||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
|
|
||||||
[];
|
|
||||||
|
|
||||||
return {
|
|
||||||
browser: match[ 1 ] || "",
|
|
||||||
version: match[ 2 ] || "0"
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
matched = jQuery.uaMatch( navigator.userAgent );
|
|
||||||
browser = {};
|
|
||||||
|
|
||||||
if ( matched.browser ) {
|
|
||||||
browser[ matched.browser ] = true;
|
|
||||||
browser.version = matched.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chrome is Webkit, but Webkit is also Safari.
|
|
||||||
if ( browser.chrome ) {
|
|
||||||
browser.webkit = true;
|
|
||||||
} else if ( browser.webkit ) {
|
|
||||||
browser.safari = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
jQuery.browser = browser;
|
|
||||||
|
|
||||||
(function($) {
|
|
||||||
|
|
||||||
// START Reflection object.
|
|
||||||
// Creates a reflection for underneath an image.
|
|
||||||
// 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.
|
|
||||||
function Reflection(img, reflHeight, opacity) {
|
|
||||||
|
|
||||||
var reflection, cntx, imageWidth = img.width, imageHeight = img.width, gradient, parent;
|
|
||||||
|
|
||||||
parent = $(img.parentNode);
|
|
||||||
this.element = reflection = parent.append("<canvas class='reflection' style='position:absolute'/>").find(':last')[0];
|
|
||||||
if ( !reflection.getContext && $.browser.msie) {
|
|
||||||
this.element = reflection = parent.append("<img class='reflection' style='position:absolute'/>").find(':last')[0];
|
|
||||||
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) + ")";
|
|
||||||
|
|
||||||
} else {
|
|
||||||
cntx = reflection.getContext("2d");
|
|
||||||
try {
|
|
||||||
|
|
||||||
|
|
||||||
$(reflection).attr({width: imageWidth, height: reflHeight});
|
|
||||||
cntx.save();
|
|
||||||
cntx.translate(0, imageHeight-1);
|
|
||||||
cntx.scale(1, -1);
|
|
||||||
cntx.drawImage(img, 0, 0, imageWidth, imageHeight);
|
|
||||||
cntx.restore();
|
|
||||||
cntx.globalCompositeOperation = "destination-out";
|
|
||||||
gradient = cntx.createLinearGradient(0, 0, 0, reflHeight);
|
|
||||||
gradient.addColorStop(0, "rgba(255, 255, 255, " + (1 - opacity) + ")");
|
|
||||||
gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
|
|
||||||
cntx.fillStyle = gradient;
|
|
||||||
cntx.fillRect(0, 0, imageWidth, reflHeight);
|
|
||||||
} catch(e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Store a copy of the alt and title attrs into the reflection
|
|
||||||
$(reflection).attr({ 'alt': $(img).attr('alt'), title: $(img).attr('title')} );
|
|
||||||
|
|
||||||
} //END Reflection object
|
|
||||||
|
|
||||||
// START Item object.
|
|
||||||
// A wrapper object for items within the carousel.
|
|
||||||
var Item = function(imgIn, options)
|
|
||||||
{
|
|
||||||
this.orgWidth = imgIn.width;
|
|
||||||
this.orgHeight = imgIn.height;
|
|
||||||
this.image = imgIn;
|
|
||||||
this.reflection = null;
|
|
||||||
this.alt = imgIn.alt;
|
|
||||||
this.title = imgIn.title;
|
|
||||||
this.imageOK = false;
|
|
||||||
this.options = options;
|
|
||||||
|
|
||||||
this.imageOK = true;
|
|
||||||
|
|
||||||
if (this.options.reflHeight > 0)
|
|
||||||
{
|
|
||||||
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!
|
|
||||||
};// END Item object
|
|
||||||
|
|
||||||
|
|
||||||
// Controller object.
|
|
||||||
// This handles moving all the items, dealing with mouse clicks etc.
|
|
||||||
var Controller = function(container, images, options)
|
|
||||||
{
|
|
||||||
var items = [], funcSin = Math.sin, funcCos = Math.cos, ctx=this;
|
|
||||||
this.controlTimer = 0;
|
|
||||||
this.stopped = false;
|
|
||||||
//this.imagesLoaded = 0;
|
|
||||||
this.container = container;
|
|
||||||
this.xRadius = options.xRadius;
|
|
||||||
this.yRadius = options.yRadius;
|
|
||||||
this.showFrontTextTimer = 0;
|
|
||||||
this.autoRotateTimer = 0;
|
|
||||||
if (options.xRadius === 0)
|
|
||||||
{
|
|
||||||
this.xRadius = ($(container).width()/2.3);
|
|
||||||
}
|
|
||||||
if (options.yRadius === 0)
|
|
||||||
{
|
|
||||||
this.yRadius = ($(container).height()/6);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.xCentre = options.xPos;
|
|
||||||
this.yCentre = options.yPos;
|
|
||||||
this.frontIndex = 0; // Index of the item at the front
|
|
||||||
|
|
||||||
// Start with the first item at the front.
|
|
||||||
this.rotation = this.destRotation = Math.PI/2;
|
|
||||||
this.timeDelay = 1000/options.FPS;
|
|
||||||
|
|
||||||
// Turn on the infoBox
|
|
||||||
if(options.altBox !== null)
|
|
||||||
{
|
|
||||||
$(options.altBox).css('display','block');
|
|
||||||
$(options.titleBox).css('display','block');
|
|
||||||
}
|
|
||||||
// Turn on relative position for container to allow absolutely positioned elements
|
|
||||||
// within it to work.
|
|
||||||
$(container).css({ position:'relative', overflow:'hidden'} );
|
|
||||||
|
|
||||||
$(options.buttonLeft).css('display','inline');
|
|
||||||
$(options.buttonRight).css('display','inline');
|
|
||||||
|
|
||||||
// Setup the buttons.
|
|
||||||
$(options.buttonLeft).bind('mouseup',this,function(event){
|
|
||||||
event.data.rotate(-1);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
$(options.buttonRight).bind('mouseup',this,function(event){
|
|
||||||
event.data.rotate(1);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// START METAMAPS CODE
|
|
||||||
// Add code that makes tab and shift+tab scroll through metacodes
|
|
||||||
$('.new_topic').bind('keydown',this,function(event){
|
|
||||||
if (event.keyCode == 9 && event.shiftKey) {
|
|
||||||
$(container).show()
|
|
||||||
event.data.rotate(-1);
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
} else if (event.keyCode == 9) {
|
|
||||||
$(container).show()
|
|
||||||
event.data.rotate(1);
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// END METAMAPS CODE
|
|
||||||
|
|
||||||
// You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel
|
|
||||||
if (options.mouseWheel)
|
|
||||||
{
|
|
||||||
// START METAMAPS CODE
|
|
||||||
/*$('body').bind('mousewheel',this,function(event, delta) {
|
|
||||||
if (Metamaps.Create.newTopic.beingCreated &&
|
|
||||||
!Metamaps.Create.isSwitchingSet &&
|
|
||||||
!Metamaps.Create.newTopic.pinned) {
|
|
||||||
event.data.rotate(delta);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
// END METAMAPS CODE
|
|
||||||
// ORIGINAL CODE
|
|
||||||
// $(container).bind('mousewheel',this,function(event, delta) {
|
|
||||||
// event.data.rotate(delta);
|
|
||||||
// return false;
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
}
|
|
||||||
$(container).unbind('mouseover click').bind('mouseover click',this,function(event){
|
|
||||||
|
|
||||||
clearInterval(event.data.autoRotateTimer); // Stop auto rotation if mouse over.
|
|
||||||
var text = $(event.target).attr('alt');
|
|
||||||
// If we have moved over a carousel item, then show the alt and title text.
|
|
||||||
|
|
||||||
if ( text !== undefined && text !== null )
|
|
||||||
{
|
|
||||||
|
|
||||||
clearTimeout(event.data.showFrontTextTimer);
|
|
||||||
$(options.altBox).html( ($(event.target).attr('alt') ));
|
|
||||||
//$(options.titleBox).html( ($(event.target).attr('title') ));
|
|
||||||
if ( options.bringToFront && event.type == 'click' )
|
|
||||||
{
|
|
||||||
$(options.titleBox).html( ($(event.target).attr('title') ));
|
|
||||||
// START METAMAPS CODE
|
|
||||||
Metamaps.Create.newTopic.metacode = $(event.target).attr('data-id');
|
|
||||||
// END METAMAPS CODE
|
|
||||||
var idx = $(event.target).data('itemIndex');
|
|
||||||
var frontIndex = event.data.frontIndex;
|
|
||||||
//var diff = idx - frontIndex;
|
|
||||||
var diff = (idx - frontIndex) % images.length;
|
|
||||||
if (Math.abs(diff) > images.length / 2) {
|
|
||||||
diff += (diff > 0 ? -images.length : images.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
event.data.rotate(-diff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// START METAMAPS CODE - initialize newTopic.metacode
|
|
||||||
var first = $(this.container).find('img').get(0)
|
|
||||||
Metamaps.Create.newTopic.metacode = $(first).data('id')
|
|
||||||
// END METAMAPS CODE
|
|
||||||
|
|
||||||
// If we have moved out of a carousel item (or the container itself),
|
|
||||||
// restore the text of the front item in 1 second.
|
|
||||||
$(container).bind('mouseout',this,function(event){
|
|
||||||
var context = event.data;
|
|
||||||
clearTimeout(context.showFrontTextTimer);
|
|
||||||
context.showFrontTextTimer = setTimeout( function(){context.showFrontText();},1000);
|
|
||||||
context.autoRotate(); // Start auto rotation.
|
|
||||||
});
|
|
||||||
|
|
||||||
// Prevent items from being selected as mouse is moved and clicked in the container.
|
|
||||||
$(container).bind('mousedown',this,function(event){
|
|
||||||
|
|
||||||
event.data.container.focus();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
container.onselectstart = function () { return false; }; // For IE.
|
|
||||||
|
|
||||||
this.innerWrapper = $(container).wrapInner('<div style="position:absolute;width:100%;height:100%;"/>').children()[0];
|
|
||||||
|
|
||||||
// Shows the text from the front most item.
|
|
||||||
this.showFrontText = function()
|
|
||||||
{
|
|
||||||
if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet.
|
|
||||||
// METAMAPS CODE
|
|
||||||
Metamaps.Create.newTopic.setMetacode($(items[this.frontIndex].image).attr('data-id'))
|
|
||||||
// NOT METAMAPS CODE
|
|
||||||
//$(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));
|
|
||||||
//$(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));
|
|
||||||
};
|
|
||||||
|
|
||||||
this.go = function()
|
|
||||||
{
|
|
||||||
if(this.controlTimer !== 0) { return; }
|
|
||||||
var context = this;
|
|
||||||
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.stop = function()
|
|
||||||
{
|
|
||||||
clearTimeout(this.controlTimer);
|
|
||||||
this.controlTimer = 0;
|
|
||||||
// METAMAPS CODE
|
|
||||||
$(container).hide()
|
|
||||||
// END METAMAPS CODE
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Starts the rotation of the carousel. Direction is the number (+-) of carousel items to rotate by.
|
|
||||||
this.rotate = function(direction)
|
|
||||||
{
|
|
||||||
this.frontIndex -= direction;
|
|
||||||
if (this.frontIndex == -1) this.frontIndex = items.length - 1;
|
|
||||||
this.frontIndex %= items.length;
|
|
||||||
this.destRotation += ( Math.PI / items.length ) * ( 2*direction );
|
|
||||||
this.showFrontText();
|
|
||||||
this.go();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
this.autoRotate = function()
|
|
||||||
{
|
|
||||||
if ( options.autoRotate !== 'no' )
|
|
||||||
{
|
|
||||||
var dir = (options.autoRotate === 'right')? 1 : -1;
|
|
||||||
this.autoRotateTimer = setInterval( function(){ctx.rotate(dir); }, options.autoRotateDelay );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is the main loop function that moves everything.
|
|
||||||
this.updateAll = function()
|
|
||||||
{
|
|
||||||
var minScale = options.minScale; // This is the smallest scale applied to the furthest item.
|
|
||||||
var smallRange = (1-minScale) * 0.5;
|
|
||||||
var w,h,x,y,scale,item,sinVal;
|
|
||||||
|
|
||||||
var change = (this.destRotation - this.rotation);
|
|
||||||
var absChange = Math.abs(change);
|
|
||||||
|
|
||||||
this.rotation += change * options.speed;
|
|
||||||
if ( absChange < 0.001 ) { this.rotation = this.destRotation; }
|
|
||||||
var itemsLen = items.length;
|
|
||||||
var spacing = (Math.PI / itemsLen) * 2;
|
|
||||||
//var wrapStyle = null;
|
|
||||||
var radians = this.rotation;
|
|
||||||
var isMSIE = $.browser.msie;
|
|
||||||
|
|
||||||
// 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
|
|
||||||
this.innerWrapper.style.display = 'none';
|
|
||||||
|
|
||||||
var style;
|
|
||||||
var px = 'px', reflHeight;
|
|
||||||
var context = this;
|
|
||||||
for (var i = 0; i<itemsLen ;i++)
|
|
||||||
{
|
|
||||||
item = items[i];
|
|
||||||
|
|
||||||
sinVal = funcSin(radians);
|
|
||||||
|
|
||||||
scale = ((sinVal+1) * smallRange) + minScale;
|
|
||||||
|
|
||||||
x = this.xCentre + (( (funcCos(radians) * this.xRadius) - (item.orgWidth*0.5)) * scale);
|
|
||||||
y = this.yCentre + (( (sinVal * this.yRadius) ) * scale);
|
|
||||||
|
|
||||||
if (item.imageOK)
|
|
||||||
{
|
|
||||||
var img = item.image;
|
|
||||||
|
|
||||||
img.style.zIndex = "" + (scale * 100)>>0; // >>0 = Math.foor(). Firefox doesn't like fractional decimals in z-index.
|
|
||||||
w = img.width = item.orgWidth * scale;
|
|
||||||
h = img.height = item.orgHeight * scale;
|
|
||||||
img.style.left = x + px ;
|
|
||||||
img.style.top = y + px;
|
|
||||||
if (item.reflection !== null)
|
|
||||||
{
|
|
||||||
reflHeight = options.reflHeight * scale;
|
|
||||||
style = item.reflection.element.style;
|
|
||||||
style.left = x + px;
|
|
||||||
style.top = y + h + options.reflGap * scale + px;
|
|
||||||
style.width = w + px;
|
|
||||||
if (isMSIE)
|
|
||||||
{
|
|
||||||
style.filter.finishy = (reflHeight / h * 100);
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
style.height = reflHeight + px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
radians += spacing;
|
|
||||||
}
|
|
||||||
// Turn display back on.
|
|
||||||
this.innerWrapper.style.display = 'block';
|
|
||||||
|
|
||||||
// If we have a preceptable change in rotation then loop again next frame.
|
|
||||||
if ( absChange >= 0.001 )
|
|
||||||
{
|
|
||||||
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
// Otherwise just stop completely.
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
}; // END updateAll
|
|
||||||
|
|
||||||
// Create an Item object for each image
|
|
||||||
// func = function(){return;ctx.updateAll();} ;
|
|
||||||
|
|
||||||
// Check if images have loaded. We need valid widths and heights for the reflections.
|
|
||||||
this.checkImagesLoaded = function()
|
|
||||||
{
|
|
||||||
var i;
|
|
||||||
for(i=0;i<images.length;i++) {
|
|
||||||
if ( (images[i].width === undefined) || ( (images[i].complete !== undefined) && (!images[i].complete) ))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(i=0;i<images.length;i++) {
|
|
||||||
items.push( new Item( images[i], options ) );
|
|
||||||
$(images[i]).data('itemIndex',i);
|
|
||||||
}
|
|
||||||
// If all images have valid widths and heights, we can stop checking.
|
|
||||||
clearInterval(this.tt);
|
|
||||||
// METAMAPS COMMENT this.showFrontText();
|
|
||||||
this.autoRotate();
|
|
||||||
this.updateAll();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
this.tt = setInterval( function(){ctx.checkImagesLoaded();},50);
|
|
||||||
}; // END Controller object
|
|
||||||
|
|
||||||
// The jQuery plugin part. Iterates through items specified in selector and inits a Controller class for each one.
|
|
||||||
$.fn.CloudCarousel = function(options) {
|
|
||||||
|
|
||||||
this.each( function() {
|
|
||||||
|
|
||||||
options = $.extend({}, {
|
|
||||||
reflHeight:0,
|
|
||||||
reflOpacity:0.5,
|
|
||||||
reflGap:0,
|
|
||||||
minScale:0.5,
|
|
||||||
xPos:0,
|
|
||||||
yPos:0,
|
|
||||||
xRadius:0,
|
|
||||||
yRadius:0,
|
|
||||||
altBox:null,
|
|
||||||
titleBox:null,
|
|
||||||
FPS: 30,
|
|
||||||
autoRotate: 'no',
|
|
||||||
autoRotateDelay: 1500,
|
|
||||||
speed:0.2,
|
|
||||||
mouseWheel: false,
|
|
||||||
bringToFront: false
|
|
||||||
},options );
|
|
||||||
// Create a Controller for each carousel.
|
|
||||||
$(this).data('cloudcarousel', new Controller( this, $('.cloudcarousel',$(this)), options) );
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
})(jQuery);
|
|
50
app/assets/javascripts/famous/famous.min.js
vendored
Normal file
|
@ -1,29 +0,0 @@
|
||||||
/* global $ */
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
if (window.location.pathname === '/') {
|
|
||||||
$.ajax({
|
|
||||||
type: 'GET',
|
|
||||||
url: 'https://i.vimeocdn.com/video/',
|
|
||||||
error: function(e) {
|
|
||||||
$('.homeVideo').hide()
|
|
||||||
$('.homeVideo').replaceWith($('<video/>', {
|
|
||||||
poster: '<%= asset_path('metamaps-intro-poster.webp') %>',
|
|
||||||
width: '560',
|
|
||||||
height: '315',
|
|
||||||
class: 'homeVideo',
|
|
||||||
controls: ''
|
|
||||||
}))
|
|
||||||
$('.homeVideo').append($('<source/>', {
|
|
||||||
src: 'https://metamaps.cc/videos/metamaps-intro.mp4',
|
|
||||||
type: 'video/mp4'
|
|
||||||
}))
|
|
||||||
$('.homeVideo').append(
|
|
||||||
'<p>You can watch our instruction video at ' +
|
|
||||||
'<a href="https://metamaps.cc/videos/metamaps-intro.mp4">' +
|
|
||||||
'https://metamaps.cc/videos/metamaps-intro.mp4</a>.'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}// if
|
|
||||||
})
|
|
BIN
app/assets/javascripts/lib/WebSocketMain.swf
Normal file
BIN
app/assets/javascripts/lib/WebSocketMainInsecure.swf
Normal file
|
@ -1,161 +0,0 @@
|
||||||
// AjaxQ jQuery Plugin
|
|
||||||
// Copyright (c) 2012 Foliotek Inc.
|
|
||||||
// MIT License
|
|
||||||
// https://github.com/Foliotek/ajaxq
|
|
||||||
// Uses CommonJS, AMD or browser globals to create a jQuery plugin.
|
|
||||||
|
|
||||||
(function (factory) {
|
|
||||||
if (typeof define === 'function' && define.amd) {
|
|
||||||
// AMD. Register as an anonymous module.
|
|
||||||
define(['jquery'], factory);
|
|
||||||
} else if (typeof module === 'object' && module.exports) {
|
|
||||||
// Node/CommonJS
|
|
||||||
module.exports = factory(require('jquery'));
|
|
||||||
} else {
|
|
||||||
// Browser globals
|
|
||||||
factory(jQuery);
|
|
||||||
}
|
|
||||||
}(function ($) {
|
|
||||||
var queues = {};
|
|
||||||
var activeReqs = {};
|
|
||||||
|
|
||||||
// Register an $.ajaxq function, which follows the $.ajax interface, but allows a queue name which will force only one request per queue to fire.
|
|
||||||
// opts can be the regular $.ajax settings plainObject, or a callback returning the settings object, to be evaluated just prior to the actual call to $.ajax.
|
|
||||||
$.ajaxq = function(qname, opts) {
|
|
||||||
|
|
||||||
if (typeof opts === "undefined") {
|
|
||||||
throw ("AjaxQ: queue name is not provided");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Will return a Deferred promise object extended with success/error/callback, so that this function matches the interface of $.ajax
|
|
||||||
var deferred = $.Deferred(),
|
|
||||||
promise = deferred.promise();
|
|
||||||
|
|
||||||
promise.success = promise.done;
|
|
||||||
promise.error = promise.fail;
|
|
||||||
promise.complete = promise.always;
|
|
||||||
|
|
||||||
// Check whether options are to be evaluated at call time or not.
|
|
||||||
var deferredOpts = typeof opts === 'function';
|
|
||||||
// Create a deep copy of the arguments, and enqueue this request.
|
|
||||||
var clonedOptions = !deferredOpts ? $.extend(true, {}, opts) : null;
|
|
||||||
enqueue(function() {
|
|
||||||
// Send off the ajax request now that the item has been removed from the queue
|
|
||||||
var jqXHR = $.ajax.apply(window, [deferredOpts ? opts() : clonedOptions]);
|
|
||||||
|
|
||||||
// Notify the returned deferred object with the correct context when the jqXHR is done or fails
|
|
||||||
// Note that 'always' will automatically be fired once one of these are called: http://api.jquery.com/category/deferred-object/.
|
|
||||||
jqXHR.done(function() {
|
|
||||||
deferred.resolve.apply(this, arguments);
|
|
||||||
});
|
|
||||||
jqXHR.fail(function() {
|
|
||||||
deferred.reject.apply(this, arguments);
|
|
||||||
});
|
|
||||||
|
|
||||||
jqXHR.always(dequeue); // make sure to dequeue the next request AFTER the done and fail callbacks are fired
|
|
||||||
|
|
||||||
return jqXHR;
|
|
||||||
});
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
|
|
||||||
|
|
||||||
// If there is no queue, create an empty one and instantly process this item.
|
|
||||||
// Otherwise, just add this item onto it for later processing.
|
|
||||||
function enqueue(cb) {
|
|
||||||
if (!queues[qname]) {
|
|
||||||
queues[qname] = [];
|
|
||||||
var xhr = cb();
|
|
||||||
activeReqs[qname] = xhr;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
queues[qname].push(cb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the next callback from the queue and fire it off.
|
|
||||||
// If the queue was empty (this was the last item), delete it from memory so the next one can be instantly processed.
|
|
||||||
function dequeue() {
|
|
||||||
if (!queues[qname]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var nextCallback = queues[qname].shift();
|
|
||||||
if (nextCallback) {
|
|
||||||
var xhr = nextCallback();
|
|
||||||
activeReqs[qname] = xhr;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
delete queues[qname];
|
|
||||||
delete activeReqs[qname];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Register a $.postq and $.getq method to provide shortcuts for $.get and $.post
|
|
||||||
// Copied from jQuery source to make sure the functions share the same defaults as $.get and $.post.
|
|
||||||
$.each( [ "getq", "postq" ], function( i, method ) {
|
|
||||||
$[ method ] = function( qname, url, data, callback, type ) {
|
|
||||||
|
|
||||||
if ( $.isFunction( data ) ) {
|
|
||||||
type = type || callback;
|
|
||||||
callback = data;
|
|
||||||
data = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $.ajaxq(qname, {
|
|
||||||
type: method === "postq" ? "post" : "get",
|
|
||||||
url: url,
|
|
||||||
data: data,
|
|
||||||
success: callback,
|
|
||||||
dataType: type
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
var isQueueRunning = function(qname) {
|
|
||||||
return (queues.hasOwnProperty(qname) && queues[qname].length > 0) || activeReqs.hasOwnProperty(qname);
|
|
||||||
};
|
|
||||||
|
|
||||||
var isAnyQueueRunning = function() {
|
|
||||||
for (var i in queues) {
|
|
||||||
if (isQueueRunning(i)) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$.ajaxq.isRunning = function(qname) {
|
|
||||||
if (qname) return isQueueRunning(qname);
|
|
||||||
else return isAnyQueueRunning();
|
|
||||||
};
|
|
||||||
|
|
||||||
$.ajaxq.getActiveRequest = function(qname) {
|
|
||||||
if (!qname) throw ("AjaxQ: queue name is required");
|
|
||||||
|
|
||||||
return activeReqs[qname];
|
|
||||||
};
|
|
||||||
|
|
||||||
$.ajaxq.abort = function(qname) {
|
|
||||||
if (!qname) throw ("AjaxQ: queue name is required");
|
|
||||||
|
|
||||||
var current = $.ajaxq.getActiveRequest(qname);
|
|
||||||
delete queues[qname];
|
|
||||||
delete activeReqs[qname];
|
|
||||||
if (current) current.abort();
|
|
||||||
};
|
|
||||||
|
|
||||||
$.ajaxq.clear = function(qname) {
|
|
||||||
if (!qname) {
|
|
||||||
for (var i in queues) {
|
|
||||||
if (queues.hasOwnProperty(i)) {
|
|
||||||
queues[i] = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (queues[qname]) {
|
|
||||||
queues[qname] = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}));
|
|
|
@ -1,685 +0,0 @@
|
||||||
/*
|
|
||||||
* BestInPlace (for jQuery)
|
|
||||||
* version: 3.0.0.alpha (2014)
|
|
||||||
*
|
|
||||||
* By Bernat Farrero based on the work of Jan Varwig.
|
|
||||||
* Examples at http://bernatfarrero.com
|
|
||||||
*
|
|
||||||
* Licensed under the MIT:
|
|
||||||
* http://www.opensource.org/licenses/mit-license.php
|
|
||||||
*
|
|
||||||
* @requires jQuery
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
*
|
|
||||||
* Attention.
|
|
||||||
* The format of the JSON object given to the select inputs is the following:
|
|
||||||
* [["key", "value"],["key", "value"]]
|
|
||||||
* The format of the JSON object given to the checkbox inputs is the following:
|
|
||||||
* ["falseValue", "trueValue"]
|
|
||||||
|
|
||||||
*/
|
|
||||||
//= require jquery.autosize
|
|
||||||
|
|
||||||
function BestInPlaceEditor(e) {
|
|
||||||
'use strict';
|
|
||||||
this.element = e;
|
|
||||||
this.initOptions();
|
|
||||||
this.bindForm();
|
|
||||||
this.initPlaceHolder();
|
|
||||||
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
BestInPlaceEditor.prototype = {
|
|
||||||
// Public Interface Functions //////////////////////////////////////////////
|
|
||||||
|
|
||||||
activate: function () {
|
|
||||||
'use strict';
|
|
||||||
var to_display;
|
|
||||||
if (this.isPlaceHolder()) {
|
|
||||||
to_display = "";
|
|
||||||
} else if (this.original_content) {
|
|
||||||
to_display = this.original_content;
|
|
||||||
} else {
|
|
||||||
switch (this.formType) {
|
|
||||||
case 'input':
|
|
||||||
case 'textarea':
|
|
||||||
if (this.display_raw) {
|
|
||||||
to_display = this.element.html().replace(/&/gi, '&');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var value = this.element.data('bipValue');
|
|
||||||
if (typeof value === 'undefined') {
|
|
||||||
to_display = '';
|
|
||||||
} else if (typeof value === 'string') {
|
|
||||||
to_display = this.element.data('bipValue').replace(/&/gi, '&');
|
|
||||||
} else {
|
|
||||||
to_display = this.element.data('bipValue');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'select':
|
|
||||||
to_display = this.element.html();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.oldValue = this.isPlaceHolder() ? "" : this.element.html();
|
|
||||||
this.display_value = to_display;
|
|
||||||
jQuery(this.activator).unbind("click", this.clickHandler);
|
|
||||||
this.activateForm();
|
|
||||||
this.element.trigger(jQuery.Event("best_in_place:activate"));
|
|
||||||
},
|
|
||||||
|
|
||||||
abort: function () {
|
|
||||||
'use strict';
|
|
||||||
this.activateText(this.oldValue);
|
|
||||||
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
|
||||||
this.element.trigger(jQuery.Event("best_in_place:abort"));
|
|
||||||
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
|
||||||
},
|
|
||||||
|
|
||||||
abortIfConfirm: function () {
|
|
||||||
'use strict';
|
|
||||||
if (!this.useConfirm) {
|
|
||||||
this.abort();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (confirm(BestInPlaceEditor.defaults.locales[''].confirmMessage)) {
|
|
||||||
this.abort();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
update: function () {
|
|
||||||
'use strict';
|
|
||||||
var editor = this,
|
|
||||||
value = this.getValue();
|
|
||||||
|
|
||||||
// Avoid request if no change is made
|
|
||||||
if (this.formType in {"input": 1, "textarea": 1} && value === this.oldValue) {
|
|
||||||
this.abort();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.ajax({
|
|
||||||
"type": this.requestMethod(),
|
|
||||||
"dataType": BestInPlaceEditor.defaults.ajaxDataType,
|
|
||||||
"data": editor.requestData(),
|
|
||||||
"success": function (data, status, xhr) {
|
|
||||||
editor.loadSuccessCallback(data, status, xhr);
|
|
||||||
},
|
|
||||||
"error": function (request, error) {
|
|
||||||
editor.loadErrorCallback(request, error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
switch (this.formType) {
|
|
||||||
case "select":
|
|
||||||
this.previousCollectionValue = value;
|
|
||||||
|
|
||||||
// search for the text for the span
|
|
||||||
$.each(this.values, function(index, arr){ if (String(arr[0]) === String(value)) editor.element.html(arr[1]); });
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "checkbox":
|
|
||||||
$.each(this.values, function(index, arr){ if (String(arr[0]) === String(value)) editor.element.html(arr[1]); });
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (value !== "") {
|
|
||||||
if (this.display_raw) {
|
|
||||||
editor.element.html(value);
|
|
||||||
} else {
|
|
||||||
editor.element.text(value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
editor.element.html(this.placeHolder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.element.data('bipValue', value);
|
|
||||||
editor.element.attr('data-bip-value', value);
|
|
||||||
|
|
||||||
editor.element.trigger(jQuery.Event("best_in_place:update"));
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
activateForm: function () {
|
|
||||||
'use strict';
|
|
||||||
alert(BestInPlaceEditor.defaults.locales[''].uninitializedForm);
|
|
||||||
},
|
|
||||||
|
|
||||||
activateText: function (value) {
|
|
||||||
'use strict';
|
|
||||||
this.element.html(value);
|
|
||||||
if (this.isPlaceHolder()) {
|
|
||||||
this.element.html(this.placeHolder);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Helper Functions ////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
initOptions: function () {
|
|
||||||
// Try parent supplied info
|
|
||||||
'use strict';
|
|
||||||
var self = this;
|
|
||||||
self.element.parents().each(function () {
|
|
||||||
var $parent = jQuery(this);
|
|
||||||
self.url = self.url || $parent.data("bipUrl");
|
|
||||||
self.activator = self.activator || $parent.data("bipActivator");
|
|
||||||
self.okButton = self.okButton || $parent.data("bipOkButton");
|
|
||||||
self.okButtonClass = self.okButtonClass || $parent.data("bipOkButtonClass");
|
|
||||||
self.cancelButton = self.cancelButton || $parent.data("bipCancelButton");
|
|
||||||
self.cancelButtonClass = self.cancelButtonClass || $parent.data("bipCancelButtonClass");
|
|
||||||
self.skipBlur = self.skipBlur || $parent.data("bipSkipBlur");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load own attributes (overrides all others)
|
|
||||||
self.url = self.element.data("bipUrl") || self.url || document.location.pathname;
|
|
||||||
self.collection = self.element.data("bipCollection") || self.collection;
|
|
||||||
self.formType = self.element.data("bipType") || "input";
|
|
||||||
self.objectName = self.element.data("bipObject") || self.objectName;
|
|
||||||
self.attributeName = self.element.data("bipAttribute") || self.attributeName;
|
|
||||||
self.activator = self.element.data("bipActivator") || self.element;
|
|
||||||
self.okButton = self.element.data("bipOkButton") || self.okButton;
|
|
||||||
self.okButtonClass = self.element.data("bipOkButtonClass") || self.okButtonClass || BestInPlaceEditor.defaults.okButtonClass;
|
|
||||||
self.cancelButton = self.element.data("bipCancelButton") || self.cancelButton;
|
|
||||||
self.cancelButtonClass = self.element.data("bipCancelButtonClass") || self.cancelButtonClass || BestInPlaceEditor.defaults.cancelButtonClass;
|
|
||||||
self.skipBlur = self.element.data("bipSkipBlur") || self.skipBlur || BestInPlaceEditor.defaults.skipBlur;
|
|
||||||
self.isNewObject = self.element.data("bipNewObject");
|
|
||||||
self.dataExtraPayload = self.element.data("bipExtraPayload");
|
|
||||||
|
|
||||||
// Fix for default values of 0
|
|
||||||
if (self.element.data("bipPlaceholder") == null) {
|
|
||||||
self.placeHolder = BestInPlaceEditor.defaults.locales[''].placeHolder;
|
|
||||||
} else {
|
|
||||||
self.placeHolder = self.element.data("bipPlaceholder");
|
|
||||||
}
|
|
||||||
|
|
||||||
self.inner_class = self.element.data("bipInnerClass");
|
|
||||||
self.html_attrs = self.element.data("bipHtmlAttrs");
|
|
||||||
self.original_content = self.element.data("bipOriginalContent") || self.original_content;
|
|
||||||
|
|
||||||
// if set the input won't be satinized
|
|
||||||
self.display_raw = self.element.data("bip-raw");
|
|
||||||
|
|
||||||
self.useConfirm = self.element.data("bip-confirm");
|
|
||||||
|
|
||||||
if (self.formType === "select" || self.formType === "checkbox") {
|
|
||||||
self.values = self.collection;
|
|
||||||
self.collectionValue = self.element.data("bipValue") || self.collectionValue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
bindForm: function () {
|
|
||||||
'use strict';
|
|
||||||
this.activateForm = BestInPlaceEditor.forms[this.formType].activateForm;
|
|
||||||
this.getValue = BestInPlaceEditor.forms[this.formType].getValue;
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
initPlaceHolder: function () {
|
|
||||||
'use strict';
|
|
||||||
// TODO add placeholder for select and checkbox
|
|
||||||
if (this.element.html() === "") {
|
|
||||||
this.element.addClass('bip-placeholder');
|
|
||||||
this.element.html(this.placeHolder);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isPlaceHolder: function () {
|
|
||||||
'use strict';
|
|
||||||
// TODO: It only work when form is deactivated.
|
|
||||||
// Condition will fail when form is activated
|
|
||||||
return this.element.html() === "" || this.element.html() === this.placeHolder;
|
|
||||||
},
|
|
||||||
|
|
||||||
getValue: function () {
|
|
||||||
'use strict';
|
|
||||||
alert(BestInPlaceEditor.defaults.locales[''].uninitializedForm);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Trim and Strips HTML from text
|
|
||||||
sanitizeValue: function (s) {
|
|
||||||
'use strict';
|
|
||||||
return jQuery.trim(s);
|
|
||||||
},
|
|
||||||
|
|
||||||
requestMethod: function() {
|
|
||||||
'use strict';
|
|
||||||
return this.isNewObject ? 'post' : BestInPlaceEditor.defaults.ajaxMethod;
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Generate the data sent in the POST request */
|
|
||||||
requestData: function () {
|
|
||||||
'use strict';
|
|
||||||
// To prevent xss attacks, a csrf token must be defined as a meta attribute
|
|
||||||
var csrf_token = jQuery('meta[name=csrf-token]').attr('content'),
|
|
||||||
csrf_param = jQuery('meta[name=csrf-param]').attr('content');
|
|
||||||
|
|
||||||
var data = {}
|
|
||||||
data['_method'] = this.requestMethod()
|
|
||||||
|
|
||||||
data[this.objectName] = this.dataExtraPayload || {}
|
|
||||||
|
|
||||||
data[this.objectName][this.attributeName] = this.getValue()
|
|
||||||
|
|
||||||
if (csrf_param !== undefined && csrf_token !== undefined) {
|
|
||||||
data[csrf_param] = csrf_token
|
|
||||||
}
|
|
||||||
return jQuery.param(data);
|
|
||||||
},
|
|
||||||
|
|
||||||
ajax: function (options) {
|
|
||||||
'use strict';
|
|
||||||
options.url = this.url;
|
|
||||||
options.beforeSend = function (xhr) {
|
|
||||||
xhr.setRequestHeader("Accept", "application/json");
|
|
||||||
};
|
|
||||||
return jQuery.ajax(options);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Handlers ////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
loadSuccessCallback: function (data, status, xhr) {
|
|
||||||
'use strict';
|
|
||||||
data = jQuery.trim(data);
|
|
||||||
//Update original content with current text.
|
|
||||||
if (this.display_raw) {
|
|
||||||
this.original_content = this.element.html();
|
|
||||||
} else {
|
|
||||||
this.original_content = this.element.text();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data && data !== "") {
|
|
||||||
var response = jQuery.parseJSON(data);
|
|
||||||
if (response !== null && response.hasOwnProperty("display_as")) {
|
|
||||||
this.element.data('bip-original-content', this.element.text());
|
|
||||||
this.element.html(response.display_as);
|
|
||||||
}
|
|
||||||
if (this.isNewObject && response && response[this.objectName]) {
|
|
||||||
if (response[this.objectName]["id"]) {
|
|
||||||
this.isNewObject = false
|
|
||||||
this.url += "/" + response[this.objectName]["id"] // in REST a POST /thing url should become PUT /thing/123
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.element.toggleClass('bip-placeholder', this.isPlaceHolder());
|
|
||||||
|
|
||||||
this.element.trigger(jQuery.Event("best_in_place:success"), [data, status, xhr]);
|
|
||||||
this.element.trigger(jQuery.Event("ajax:success"), [data, status, xhr]);
|
|
||||||
|
|
||||||
// Binding back after being clicked
|
|
||||||
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
|
||||||
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
|
||||||
|
|
||||||
if (this.collectionValue !== null && this.formType === "select") {
|
|
||||||
this.collectionValue = this.previousCollectionValue;
|
|
||||||
this.previousCollectionValue = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
loadErrorCallback: function (request, error) {
|
|
||||||
'use strict';
|
|
||||||
this.activateText(this.oldValue);
|
|
||||||
|
|
||||||
this.element.trigger(jQuery.Event("best_in_place:error"), [request, error]);
|
|
||||||
this.element.trigger(jQuery.Event("ajax:error"), request, error);
|
|
||||||
|
|
||||||
// Binding back after being clicked
|
|
||||||
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
|
||||||
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
|
||||||
},
|
|
||||||
|
|
||||||
clickHandler: function (event) {
|
|
||||||
'use strict';
|
|
||||||
event.preventDefault();
|
|
||||||
event.data.editor.activate();
|
|
||||||
},
|
|
||||||
|
|
||||||
setHtmlAttributes: function () {
|
|
||||||
'use strict';
|
|
||||||
var formField = this.element.find(this.formType);
|
|
||||||
|
|
||||||
if (this.html_attrs) {
|
|
||||||
var attrs = this.html_attrs;
|
|
||||||
$.each(attrs, function (key, val) {
|
|
||||||
formField.attr(key, val);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
placeButtons: function (output, field) {
|
|
||||||
'use strict';
|
|
||||||
if (field.okButton) {
|
|
||||||
output.append(
|
|
||||||
jQuery(document.createElement('input'))
|
|
||||||
.attr('type', 'submit')
|
|
||||||
.attr('class', field.okButtonClass)
|
|
||||||
.attr('value', field.okButton)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (field.cancelButton) {
|
|
||||||
output.append(
|
|
||||||
jQuery(document.createElement('input'))
|
|
||||||
.attr('type', 'button')
|
|
||||||
.attr('class', field.cancelButtonClass)
|
|
||||||
.attr('value', field.cancelButton)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Button cases:
|
|
||||||
// If no buttons, then blur saves, ESC cancels
|
|
||||||
// If just Cancel button, then blur saves, ESC or clicking Cancel cancels (careful of blur event!)
|
|
||||||
// If just OK button, then clicking OK saves (careful of blur event!), ESC or blur cancels
|
|
||||||
// If both buttons, then clicking OK saves, ESC or clicking Cancel or blur cancels
|
|
||||||
BestInPlaceEditor.forms = {
|
|
||||||
"input": {
|
|
||||||
activateForm: function () {
|
|
||||||
'use strict';
|
|
||||||
var output = jQuery(document.createElement('form'))
|
|
||||||
.addClass('form_in_place')
|
|
||||||
.attr('action', 'javascript:void(0);')
|
|
||||||
.attr('style', 'display:inline');
|
|
||||||
var input_elt = jQuery(document.createElement('input'))
|
|
||||||
.attr('type', 'text')
|
|
||||||
.attr('name', this.attributeName)
|
|
||||||
.val(this.display_value);
|
|
||||||
|
|
||||||
// Add class to form input
|
|
||||||
if (this.inner_class) {
|
|
||||||
input_elt.addClass(this.inner_class);
|
|
||||||
}
|
|
||||||
|
|
||||||
output.append(input_elt);
|
|
||||||
this.placeButtons(output, this);
|
|
||||||
|
|
||||||
this.element.html(output);
|
|
||||||
this.setHtmlAttributes();
|
|
||||||
|
|
||||||
this.element.find("input[type='text']")[0].select();
|
|
||||||
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
|
|
||||||
if (this.cancelButton) {
|
|
||||||
this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.input.cancelButtonHandler);
|
|
||||||
}
|
|
||||||
if (!this.okButton) {
|
|
||||||
this.element.find("input[type='text']").bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler);
|
|
||||||
}
|
|
||||||
this.element.find("input[type='text']").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
|
|
||||||
this.blurTimer = null;
|
|
||||||
this.userClicked = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
getValue: function () {
|
|
||||||
'use strict';
|
|
||||||
return this.sanitizeValue(this.element.find("input").val());
|
|
||||||
},
|
|
||||||
|
|
||||||
// When buttons are present, use a timer on the blur event to give precedence to clicks
|
|
||||||
inputBlurHandler: function (event) {
|
|
||||||
'use strict';
|
|
||||||
if (event.data.editor.okButton) {
|
|
||||||
event.data.editor.blurTimer = setTimeout(function () {
|
|
||||||
if (!event.data.editor.userClicked) {
|
|
||||||
event.data.editor.abort();
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
} else {
|
|
||||||
if (event.data.editor.cancelButton) {
|
|
||||||
event.data.editor.blurTimer = setTimeout(function () {
|
|
||||||
if (!event.data.editor.userClicked) {
|
|
||||||
event.data.editor.update();
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
} else {
|
|
||||||
event.data.editor.update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
submitHandler: function (event) {
|
|
||||||
'use strict';
|
|
||||||
event.data.editor.userClicked = true;
|
|
||||||
clearTimeout(event.data.editor.blurTimer);
|
|
||||||
event.data.editor.update();
|
|
||||||
},
|
|
||||||
|
|
||||||
cancelButtonHandler: function (event) {
|
|
||||||
'use strict';
|
|
||||||
event.data.editor.userClicked = true;
|
|
||||||
clearTimeout(event.data.editor.blurTimer);
|
|
||||||
event.data.editor.abort();
|
|
||||||
event.stopPropagation(); // Without this, click isn't handled
|
|
||||||
},
|
|
||||||
|
|
||||||
keyupHandler: function (event) {
|
|
||||||
'use strict';
|
|
||||||
if (event.keyCode === 27) {
|
|
||||||
event.data.editor.abort();
|
|
||||||
event.stopImmediatePropagation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"select": {
|
|
||||||
activateForm: function () {
|
|
||||||
'use strict';
|
|
||||||
var output = jQuery(document.createElement('form'))
|
|
||||||
.attr('action', 'javascript:void(0)')
|
|
||||||
.attr('style', 'display:inline'),
|
|
||||||
selected = '',
|
|
||||||
select_elt = jQuery(document.createElement('select'))
|
|
||||||
.attr('class', this.inner_class !== null ? this.inner_class : ''),
|
|
||||||
currentCollectionValue = this.collectionValue,
|
|
||||||
key, value,
|
|
||||||
a = this.values;
|
|
||||||
|
|
||||||
$.each(a, function(index, arr){
|
|
||||||
key = arr[0];
|
|
||||||
value = arr[1];
|
|
||||||
var option_elt = jQuery(document.createElement('option'))
|
|
||||||
.val(key)
|
|
||||||
.html(value);
|
|
||||||
|
|
||||||
if (currentCollectionValue) {
|
|
||||||
if (String(key) === String(currentCollectionValue)) option_elt.attr('selected', 'selected');
|
|
||||||
}
|
|
||||||
select_elt.append(option_elt);
|
|
||||||
});
|
|
||||||
output.append(select_elt);
|
|
||||||
|
|
||||||
this.element.html(output);
|
|
||||||
this.setHtmlAttributes();
|
|
||||||
this.element.find("select").bind('change', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
|
||||||
this.element.find("select").bind('blur', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
|
||||||
this.element.find("select").bind('keyup', {editor: this}, BestInPlaceEditor.forms.select.keyupHandler);
|
|
||||||
this.element.find("select")[0].focus();
|
|
||||||
|
|
||||||
// automatically click on the select so you
|
|
||||||
// don't have to click twice
|
|
||||||
try {
|
|
||||||
var e = document.createEvent("MouseEvents");
|
|
||||||
e.initMouseEvent("mousedown", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
|
||||||
this.element.find("select")[0].dispatchEvent(e);
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
// browser doesn't support this, e.g. IE8
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getValue: function () {
|
|
||||||
'use strict';
|
|
||||||
return this.sanitizeValue(this.element.find("select").val());
|
|
||||||
},
|
|
||||||
|
|
||||||
blurHandler: function (event) {
|
|
||||||
'use strict';
|
|
||||||
event.data.editor.update();
|
|
||||||
},
|
|
||||||
|
|
||||||
keyupHandler: function (event) {
|
|
||||||
'use strict';
|
|
||||||
if (event.keyCode === 27) {
|
|
||||||
event.data.editor.abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"checkbox": {
|
|
||||||
activateForm: function () {
|
|
||||||
'use strict';
|
|
||||||
this.collectionValue = !this.getValue();
|
|
||||||
this.setHtmlAttributes();
|
|
||||||
this.update();
|
|
||||||
},
|
|
||||||
|
|
||||||
getValue: function () {
|
|
||||||
'use strict';
|
|
||||||
return this.collectionValue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"textarea": {
|
|
||||||
activateForm: function () {
|
|
||||||
'use strict';
|
|
||||||
// grab width and height of text
|
|
||||||
var width = this.element.css('width');
|
|
||||||
var height = this.element.css('height');
|
|
||||||
|
|
||||||
// construct form
|
|
||||||
var output = jQuery(document.createElement('form'))
|
|
||||||
.addClass('form_in_place')
|
|
||||||
.attr('action', 'javascript:void(0);')
|
|
||||||
.attr('style', 'display:inline');
|
|
||||||
var textarea_elt = jQuery(document.createElement('textarea'))
|
|
||||||
.attr('name', this.attributeName)
|
|
||||||
.val(this.sanitizeValue(this.display_value));
|
|
||||||
|
|
||||||
if (this.inner_class !== null) {
|
|
||||||
textarea_elt.addClass(this.inner_class);
|
|
||||||
}
|
|
||||||
|
|
||||||
output.append(textarea_elt);
|
|
||||||
|
|
||||||
this.placeButtons(output, this);
|
|
||||||
|
|
||||||
this.element.html(output);
|
|
||||||
this.setHtmlAttributes();
|
|
||||||
|
|
||||||
// set width and height of textarea
|
|
||||||
jQuery(this.element.find("textarea")[0]).css({'min-width': width, 'min-height': height});
|
|
||||||
jQuery(this.element.find("textarea")[0]).autosize();
|
|
||||||
|
|
||||||
this.element.find("textarea")[0].focus();
|
|
||||||
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.textarea.submitHandler);
|
|
||||||
|
|
||||||
if (this.cancelButton) {
|
|
||||||
this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.textarea.cancelButtonHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.skipBlur) {
|
|
||||||
this.element.find("textarea").bind('blur', {editor: this}, BestInPlaceEditor.forms.textarea.blurHandler);
|
|
||||||
}
|
|
||||||
this.element.find("textarea").bind('keyup', {editor: this}, BestInPlaceEditor.forms.textarea.keyupHandler);
|
|
||||||
this.blurTimer = null;
|
|
||||||
this.userClicked = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
getValue: function () {
|
|
||||||
'use strict';
|
|
||||||
return this.sanitizeValue(this.element.find("textarea").val());
|
|
||||||
},
|
|
||||||
|
|
||||||
// When buttons are present, use a timer on the blur event to give precedence to clicks
|
|
||||||
blurHandler: function (event) {
|
|
||||||
'use strict';
|
|
||||||
if (event.data.editor.okButton) {
|
|
||||||
event.data.editor.blurTimer = setTimeout(function () {
|
|
||||||
if (!event.data.editor.userClicked) {
|
|
||||||
event.data.editor.abortIfConfirm();
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
} else {
|
|
||||||
if (event.data.editor.cancelButton) {
|
|
||||||
event.data.editor.blurTimer = setTimeout(function () {
|
|
||||||
if (!event.data.editor.userClicked) {
|
|
||||||
event.data.editor.update();
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
} else {
|
|
||||||
event.data.editor.update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
submitHandler: function (event) {
|
|
||||||
'use strict';
|
|
||||||
event.data.editor.userClicked = true;
|
|
||||||
clearTimeout(event.data.editor.blurTimer);
|
|
||||||
event.data.editor.update();
|
|
||||||
},
|
|
||||||
|
|
||||||
cancelButtonHandler: function (event) {
|
|
||||||
'use strict';
|
|
||||||
event.data.editor.userClicked = true;
|
|
||||||
clearTimeout(event.data.editor.blurTimer);
|
|
||||||
event.data.editor.abortIfConfirm();
|
|
||||||
event.stopPropagation(); // Without this, click isn't handled
|
|
||||||
},
|
|
||||||
|
|
||||||
keyupHandler: function (event) {
|
|
||||||
'use strict';
|
|
||||||
if (event.keyCode === 27) {
|
|
||||||
event.data.editor.abortIfConfirm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BestInPlaceEditor.defaults = {
|
|
||||||
locales: {},
|
|
||||||
ajaxMethod: "put", //TODO Change to patch when support to 3.2 is dropped
|
|
||||||
ajaxDataType: 'text',
|
|
||||||
okButtonClass: '',
|
|
||||||
cancelButtonClass: '',
|
|
||||||
skipBlur: false
|
|
||||||
};
|
|
||||||
|
|
||||||
// Default locale
|
|
||||||
BestInPlaceEditor.defaults.locales[''] = {
|
|
||||||
confirmMessage: "Are you sure you want to discard your changes?",
|
|
||||||
uninitializedForm: "The form was not properly initialized. getValue is unbound",
|
|
||||||
placeHolder: '-'
|
|
||||||
};
|
|
||||||
|
|
||||||
jQuery.fn.best_in_place = function () {
|
|
||||||
'use strict';
|
|
||||||
function setBestInPlace(element) {
|
|
||||||
if (!element.data('bestInPlaceEditor')) {
|
|
||||||
element.data('bestInPlaceEditor', new BestInPlaceEditor(element));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jQuery(this.context).delegate(this.selector, 'click', function () {
|
|
||||||
var el = jQuery(this);
|
|
||||||
if (setBestInPlace(el)) {
|
|
||||||
el.click();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.each(function () {
|
|
||||||
setBestInPlace(jQuery(this));
|
|
||||||
});
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
780
app/assets/javascripts/lib/bip.js
Normal file
|
@ -0,0 +1,780 @@
|
||||||
|
/*
|
||||||
|
BestInPlace (for jQuery)
|
||||||
|
version: 0.1.0 (01/01/2011)
|
||||||
|
@requires jQuery >= v1.4
|
||||||
|
@requires jQuery.purr to display pop-up windows
|
||||||
|
|
||||||
|
By Bernat Farrero based on the work of Jan Varwig.
|
||||||
|
Examples at http://bernatfarrero.com
|
||||||
|
|
||||||
|
Licensed under the MIT:
|
||||||
|
http://www.opensource.org/licenses/mit-license.php
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
Attention.
|
||||||
|
The format of the JSON object given to the select inputs is the following:
|
||||||
|
[["key", "value"],["key", "value"]]
|
||||||
|
The format of the JSON object given to the checkbox inputs is the following:
|
||||||
|
["falseValue", "trueValue"]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
function BestInPlaceEditor(e) {
|
||||||
|
this.element = e;
|
||||||
|
this.initOptions();
|
||||||
|
this.bindForm();
|
||||||
|
this.initNil();
|
||||||
|
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
BestInPlaceEditor.prototype = {
|
||||||
|
// Public Interface Functions //////////////////////////////////////////////
|
||||||
|
|
||||||
|
activate : function() {
|
||||||
|
var to_display = "";
|
||||||
|
if (this.isNil()) {
|
||||||
|
to_display = "";
|
||||||
|
}
|
||||||
|
else if (this.original_content) {
|
||||||
|
to_display = this.original_content;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.sanitize) {
|
||||||
|
to_display = this.element.text();
|
||||||
|
} else {
|
||||||
|
to_display = this.element.html();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.oldValue = this.isNil() ? "" : this.element.html();
|
||||||
|
this.display_value = to_display;
|
||||||
|
jQuery(this.activator).unbind("click", this.clickHandler);
|
||||||
|
this.activateForm();
|
||||||
|
this.element.trigger(jQuery.Event("best_in_place:activate"));
|
||||||
|
},
|
||||||
|
|
||||||
|
abort : function() {
|
||||||
|
this.activateText(this.oldValue);
|
||||||
|
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
||||||
|
this.element.trigger(jQuery.Event("best_in_place:abort"));
|
||||||
|
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
||||||
|
},
|
||||||
|
|
||||||
|
abortIfConfirm : function () {
|
||||||
|
if (!this.useConfirm) {
|
||||||
|
this.abort();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (confirm("Are you sure you want to discard your changes?")) {
|
||||||
|
this.abort();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
update : function() {
|
||||||
|
var editor = this;
|
||||||
|
if (this.formType in {"input":1, "textarea":1} && this.getValue() == this.oldValue)
|
||||||
|
{ // Avoid request if no change is made
|
||||||
|
this.abort();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
editor.ajax({
|
||||||
|
"type" : "post",
|
||||||
|
"dataType" : "text",
|
||||||
|
"data" : editor.requestData(),
|
||||||
|
"success" : function(data){ editor.loadSuccessCallback(data); },
|
||||||
|
"error" : function(request, error){ editor.loadErrorCallback(request, error); }
|
||||||
|
});
|
||||||
|
if (this.formType == "select") {
|
||||||
|
var value = this.getValue();
|
||||||
|
this.previousCollectionValue = value;
|
||||||
|
|
||||||
|
jQuery.each(this.values, function(i, v) {
|
||||||
|
if (value == v[0]) {
|
||||||
|
editor.element.html(v[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else if (this.formType == "checkbox") {
|
||||||
|
editor.element.html(this.getValue() ? this.values[1] : this.values[0]);
|
||||||
|
} else {
|
||||||
|
if (this.getValue() !== "") {
|
||||||
|
editor.element.text(this.getValue());
|
||||||
|
} else {
|
||||||
|
editor.element.html(this.nil);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
editor.element.trigger(jQuery.Event("best_in_place:update"));
|
||||||
|
},
|
||||||
|
|
||||||
|
activateForm : function() {
|
||||||
|
alert("The form was not properly initialized. activateForm is unbound");
|
||||||
|
},
|
||||||
|
|
||||||
|
activateText : function(value){
|
||||||
|
this.element.html(value);
|
||||||
|
if(this.isNil()) this.element.html(this.nil);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Helper Functions ////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
initOptions : function() {
|
||||||
|
// Try parent supplied info
|
||||||
|
var self = this;
|
||||||
|
self.element.parents().each(function(){
|
||||||
|
$parent = jQuery(this);
|
||||||
|
self.url = self.url || $parent.attr("data-url");
|
||||||
|
self.collection = self.collection || $parent.attr("data-collection");
|
||||||
|
self.formType = self.formType || $parent.attr("data-type");
|
||||||
|
self.objectName = self.objectName || $parent.attr("data-object");
|
||||||
|
self.attributeName = self.attributeName || $parent.attr("data-attribute");
|
||||||
|
self.activator = self.activator || $parent.attr("data-activator");
|
||||||
|
self.okButton = self.okButton || $parent.attr("data-ok-button");
|
||||||
|
self.okButtonClass = self.okButtonClass || $parent.attr("data-ok-button-class");
|
||||||
|
self.cancelButton = self.cancelButton || $parent.attr("data-cancel-button");
|
||||||
|
self.cancelButtonClass = self.cancelButtonClass || $parent.attr("data-cancel-button-class");
|
||||||
|
self.nil = self.nil || $parent.attr("data-nil");
|
||||||
|
self.inner_class = self.inner_class || $parent.attr("data-inner-class");
|
||||||
|
self.html_attrs = self.html_attrs || $parent.attr("data-html-attrs");
|
||||||
|
self.original_content = self.original_content || $parent.attr("data-original-content");
|
||||||
|
self.collectionValue = self.collectionValue || $parent.attr("data-value");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Try Rails-id based if parents did not explicitly supply something
|
||||||
|
self.element.parents().each(function(){
|
||||||
|
var res = this.id.match(/^(\w+)_(\d+)$/i);
|
||||||
|
if (res) {
|
||||||
|
self.objectName = self.objectName || res[1];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load own attributes (overrides all others)
|
||||||
|
self.url = self.element.attr("data-url") || self.url || document.location.pathname;
|
||||||
|
self.collection = self.element.attr("data-collection") || self.collection;
|
||||||
|
self.formType = self.element.attr("data-type") || self.formtype || "input";
|
||||||
|
self.objectName = self.element.attr("data-object") || self.objectName;
|
||||||
|
self.attributeName = self.element.attr("data-attribute") || self.attributeName;
|
||||||
|
self.activator = self.element.attr("data-activator") || self.element;
|
||||||
|
self.okButton = self.element.attr("data-ok-button") || self.okButton;
|
||||||
|
self.okButtonClass = self.element.attr("data-ok-button-class") || self.okButtonClass || "";
|
||||||
|
self.cancelButton = self.element.attr("data-cancel-button") || self.cancelButton;
|
||||||
|
self.cancelButtonClass = self.element.attr("data-cancel-button-class") || self.cancelButtonClass || "";
|
||||||
|
self.nil = self.element.attr("data-nil") || self.nil || "—";
|
||||||
|
self.inner_class = self.element.attr("data-inner-class") || self.inner_class || null;
|
||||||
|
self.html_attrs = self.element.attr("data-html-attrs") || self.html_attrs;
|
||||||
|
self.original_content = self.element.attr("data-original-content") || self.original_content;
|
||||||
|
self.collectionValue = self.element.attr("data-value") || self.collectionValue;
|
||||||
|
|
||||||
|
if (!self.element.attr("data-sanitize")) {
|
||||||
|
self.sanitize = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.sanitize = (self.element.attr("data-sanitize") == "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self.element.attr("data-use-confirm")) {
|
||||||
|
self.useConfirm = true;
|
||||||
|
} else {
|
||||||
|
self.useConfirm = (self.element.attr("data-use-confirm") != "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((self.formType == "select" || self.formType == "checkbox") && self.collection !== null)
|
||||||
|
{
|
||||||
|
self.values = jQuery.parseJSON(self.collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
bindForm : function() {
|
||||||
|
this.activateForm = BestInPlaceEditor.forms[this.formType].activateForm;
|
||||||
|
this.getValue = BestInPlaceEditor.forms[this.formType].getValue;
|
||||||
|
},
|
||||||
|
|
||||||
|
initNil: function() {
|
||||||
|
if (this.element.html() === "")
|
||||||
|
{
|
||||||
|
this.element.html(this.nil);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
isNil: function() {
|
||||||
|
// TODO: It only work when form is deactivated.
|
||||||
|
// Condition will fail when form is activated
|
||||||
|
return this.element.html() === "" || this.element.html() === this.nil;
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue : function() {
|
||||||
|
alert("The form was not properly initialized. getValue is unbound");
|
||||||
|
},
|
||||||
|
|
||||||
|
// Trim and Strips HTML from text
|
||||||
|
sanitizeValue : function(s) {
|
||||||
|
return jQuery.trim(s);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Generate the data sent in the POST request */
|
||||||
|
requestData : function() {
|
||||||
|
// To prevent xss attacks, a csrf token must be defined as a meta attribute
|
||||||
|
csrf_token = jQuery('meta[name=csrf-token]').attr('content');
|
||||||
|
csrf_param = jQuery('meta[name=csrf-param]').attr('content');
|
||||||
|
|
||||||
|
var data = "_method=put";
|
||||||
|
data += "&" + this.objectName + '[' + this.attributeName + ']=' + encodeURIComponent(this.getValue());
|
||||||
|
|
||||||
|
if (csrf_param !== undefined && csrf_token !== undefined) {
|
||||||
|
data += "&" + csrf_param + "=" + encodeURIComponent(csrf_token);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
|
||||||
|
ajax : function(options) {
|
||||||
|
options.url = this.url;
|
||||||
|
options.beforeSend = function(xhr){ xhr.setRequestHeader("Accept", "application/json"); };
|
||||||
|
return jQuery.ajax(options);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Handlers ////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
loadSuccessCallback : function(data) {
|
||||||
|
data = jQuery.trim(data);
|
||||||
|
|
||||||
|
if(data && data!=""){
|
||||||
|
var response = jQuery.parseJSON(jQuery.trim(data));
|
||||||
|
if (response !== null && response.hasOwnProperty("display_as")) {
|
||||||
|
this.element.attr("data-original-content", this.element.text());
|
||||||
|
this.original_content = this.element.text();
|
||||||
|
this.element.html(response["display_as"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.element.trigger(jQuery.Event("best_in_place:success"), data);
|
||||||
|
this.element.trigger(jQuery.Event("ajax:success"), data);
|
||||||
|
} else {
|
||||||
|
this.element.trigger(jQuery.Event("best_in_place:success"));
|
||||||
|
this.element.trigger(jQuery.Event("ajax:success"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binding back after being clicked
|
||||||
|
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
||||||
|
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
||||||
|
|
||||||
|
if (this.collectionValue !== null && this.formType == "select") {
|
||||||
|
this.collectionValue = this.previousCollectionValue;
|
||||||
|
this.previousCollectionValue = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
loadErrorCallback : function(request, error) {
|
||||||
|
this.activateText(this.oldValue);
|
||||||
|
|
||||||
|
this.element.trigger(jQuery.Event("best_in_place:error"), [request, error]);
|
||||||
|
this.element.trigger(jQuery.Event("ajax:error"), request, error);
|
||||||
|
|
||||||
|
// Binding back after being clicked
|
||||||
|
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
||||||
|
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
||||||
|
},
|
||||||
|
|
||||||
|
clickHandler : function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.data.editor.activate();
|
||||||
|
},
|
||||||
|
|
||||||
|
setHtmlAttributes : function() {
|
||||||
|
var formField = this.element.find(this.formType);
|
||||||
|
|
||||||
|
if(this.html_attrs){
|
||||||
|
var attrs = jQuery.parseJSON(this.html_attrs);
|
||||||
|
for(var key in attrs){
|
||||||
|
formField.attr(key, attrs[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Button cases:
|
||||||
|
// If no buttons, then blur saves, ESC cancels
|
||||||
|
// If just Cancel button, then blur saves, ESC or clicking Cancel cancels (careful of blur event!)
|
||||||
|
// If just OK button, then clicking OK saves (careful of blur event!), ESC or blur cancels
|
||||||
|
// If both buttons, then clicking OK saves, ESC or clicking Cancel or blur cancels
|
||||||
|
BestInPlaceEditor.forms = {
|
||||||
|
"input" : {
|
||||||
|
activateForm : function() {
|
||||||
|
var output = jQuery(document.createElement('form'))
|
||||||
|
.addClass('form_in_place')
|
||||||
|
.attr('action', 'javascript:void(0);')
|
||||||
|
.attr('style', 'display:inline');
|
||||||
|
var input_elt = jQuery(document.createElement('input'))
|
||||||
|
.attr('type', 'text')
|
||||||
|
.attr('name', this.attributeName)
|
||||||
|
.val(this.display_value);
|
||||||
|
if(this.inner_class !== null) {
|
||||||
|
input_elt.addClass(this.inner_class);
|
||||||
|
}
|
||||||
|
output.append(input_elt);
|
||||||
|
if(this.okButton) {
|
||||||
|
output.append(
|
||||||
|
jQuery(document.createElement('input'))
|
||||||
|
.attr('type', 'submit')
|
||||||
|
.attr('class', this.okButtonClass)
|
||||||
|
.attr('value', this.okButton)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if(this.cancelButton) {
|
||||||
|
output.append(
|
||||||
|
jQuery(document.createElement('input'))
|
||||||
|
.attr('type', 'button')
|
||||||
|
.attr('class', this.cancelButtonClass)
|
||||||
|
.attr('value', this.cancelButton)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.element.html(output);
|
||||||
|
this.setHtmlAttributes();
|
||||||
|
// START METAMAPS CODE
|
||||||
|
//this.element.find("input[type='text']")[0].select();
|
||||||
|
this.element.find("input[type='text']")[0].focus();
|
||||||
|
// END METAMAPS CODE
|
||||||
|
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
|
||||||
|
if (this.cancelButton) {
|
||||||
|
this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.input.cancelButtonHandler);
|
||||||
|
}
|
||||||
|
this.element.find("input[type='text']").bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler);
|
||||||
|
// START METAMAPS CODE
|
||||||
|
this.element.find("input[type='text']").bind('keydown', {editor: this}, BestInPlaceEditor.forms.input.keydownHandler);
|
||||||
|
// END METAMAPS CODE
|
||||||
|
this.element.find("input[type='text']").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
|
||||||
|
this.blurTimer = null;
|
||||||
|
this.userClicked = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue : function() {
|
||||||
|
return this.sanitizeValue(this.element.find("input").val());
|
||||||
|
},
|
||||||
|
|
||||||
|
// When buttons are present, use a timer on the blur event to give precedence to clicks
|
||||||
|
inputBlurHandler : function(event) {
|
||||||
|
if (event.data.editor.okButton) {
|
||||||
|
event.data.editor.blurTimer = setTimeout(function () {
|
||||||
|
if (!event.data.editor.userClicked) {
|
||||||
|
event.data.editor.abort();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
if (event.data.editor.cancelButton) {
|
||||||
|
event.data.editor.blurTimer = setTimeout(function () {
|
||||||
|
if (!event.data.editor.userClicked) {
|
||||||
|
event.data.editor.update();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
event.data.editor.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
submitHandler : function(event) {
|
||||||
|
event.data.editor.userClicked = true;
|
||||||
|
clearTimeout(event.data.editor.blurTimer);
|
||||||
|
event.data.editor.update();
|
||||||
|
},
|
||||||
|
|
||||||
|
cancelButtonHandler : function(event) {
|
||||||
|
event.data.editor.userClicked = true;
|
||||||
|
clearTimeout(event.data.editor.blurTimer);
|
||||||
|
event.data.editor.abort();
|
||||||
|
event.stopPropagation(); // Without this, click isn't handled
|
||||||
|
},
|
||||||
|
|
||||||
|
keyupHandler : function(event) {
|
||||||
|
if (event.keyCode == 27) {
|
||||||
|
event.data.editor.abort();
|
||||||
|
}
|
||||||
|
// START METAMAPS CODE
|
||||||
|
else if (event.keyCode == 13 && !event.shiftKey) {
|
||||||
|
event.data.editor.update();
|
||||||
|
}
|
||||||
|
// END METAMAPS CODE
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"date" : {
|
||||||
|
activateForm : function() {
|
||||||
|
var that = this,
|
||||||
|
output = jQuery(document.createElement('form'))
|
||||||
|
.addClass('form_in_place')
|
||||||
|
.attr('action', 'javascript:void(0);')
|
||||||
|
.attr('style', 'display:inline'),
|
||||||
|
input_elt = jQuery(document.createElement('input'))
|
||||||
|
.attr('type', 'text')
|
||||||
|
.attr('name', this.attributeName)
|
||||||
|
.attr('value', this.sanitizeValue(this.display_value));
|
||||||
|
if(this.inner_class !== null) {
|
||||||
|
input_elt.addClass(this.inner_class);
|
||||||
|
}
|
||||||
|
output.append(input_elt)
|
||||||
|
|
||||||
|
this.element.html(output);
|
||||||
|
this.setHtmlAttributes();
|
||||||
|
this.element.find('input')[0].select();
|
||||||
|
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
|
||||||
|
this.element.find("input").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
|
||||||
|
|
||||||
|
this.element.find('input')
|
||||||
|
.datepicker({
|
||||||
|
onClose: function() {
|
||||||
|
that.update();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.datepicker('show');
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue : function() {
|
||||||
|
return this.sanitizeValue(this.element.find("input").val());
|
||||||
|
},
|
||||||
|
|
||||||
|
submitHandler : function(event) {
|
||||||
|
event.data.editor.update();
|
||||||
|
},
|
||||||
|
|
||||||
|
// START METAMAPS CODE
|
||||||
|
keydownHandler : function(event) {
|
||||||
|
if (event.keyCode == 13 && !event.shiftKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// END METAMAPS CODE
|
||||||
|
|
||||||
|
keyupHandler : function(event) {
|
||||||
|
if (event.keyCode == 27) {
|
||||||
|
event.data.editor.abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"select" : {
|
||||||
|
activateForm : function() {
|
||||||
|
var output = jQuery(document.createElement('form'))
|
||||||
|
.attr('action', 'javascript:void(0)')
|
||||||
|
.attr('style', 'display:inline');
|
||||||
|
selected = '',
|
||||||
|
oldValue = this.oldValue,
|
||||||
|
select_elt = jQuery(document.createElement('select'))
|
||||||
|
.attr('class', this.inned_class !== null ? this.inner_class : '' ),
|
||||||
|
currentCollectionValue = this.collectionValue;
|
||||||
|
|
||||||
|
jQuery.each(this.values, function (index, value) {
|
||||||
|
var option_elt = jQuery(document.createElement('option'))
|
||||||
|
// .attr('value', value[0])
|
||||||
|
.val(value[0])
|
||||||
|
.html(value[1]);
|
||||||
|
if(value[0] == currentCollectionValue) {
|
||||||
|
option_elt.attr('selected', 'selected');
|
||||||
|
}
|
||||||
|
select_elt.append(option_elt);
|
||||||
|
});
|
||||||
|
output.append(select_elt);
|
||||||
|
|
||||||
|
this.element.html(output);
|
||||||
|
this.setHtmlAttributes();
|
||||||
|
this.element.find("select").bind('change', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
||||||
|
this.element.find("select").bind('blur', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
|
||||||
|
this.element.find("select").bind('keyup', {editor: this}, BestInPlaceEditor.forms.select.keyupHandler);
|
||||||
|
this.element.find("select")[0].focus();
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue : function() {
|
||||||
|
return this.sanitizeValue(this.element.find("select").val());
|
||||||
|
// return this.element.find("select").val();
|
||||||
|
},
|
||||||
|
|
||||||
|
blurHandler : function(event) {
|
||||||
|
event.data.editor.update();
|
||||||
|
},
|
||||||
|
|
||||||
|
keyupHandler : function(event) {
|
||||||
|
if (event.keyCode == 27) event.data.editor.abort();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"checkbox" : {
|
||||||
|
activateForm : function() {
|
||||||
|
this.collectionValue = !this.getValue();
|
||||||
|
this.setHtmlAttributes();
|
||||||
|
this.update();
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue : function() {
|
||||||
|
return this.collectionValue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"textarea" : {
|
||||||
|
activateForm : function() {
|
||||||
|
// grab width and height of text
|
||||||
|
width = this.element.css('width');
|
||||||
|
height = this.element.css('height');
|
||||||
|
|
||||||
|
// construct form
|
||||||
|
var output = jQuery(document.createElement('form'))
|
||||||
|
.attr('action', 'javascript:void(0)')
|
||||||
|
.attr('style', 'display:inline')
|
||||||
|
.append(jQuery(document.createElement('textarea'))
|
||||||
|
.val(this.sanitizeValue(this.display_value)));
|
||||||
|
if(this.okButton) {
|
||||||
|
output.append(
|
||||||
|
jQuery(document.createElement('input'))
|
||||||
|
.attr('type', 'submit')
|
||||||
|
.attr('value', this.okButton)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if(this.cancelButton) {
|
||||||
|
output.append(
|
||||||
|
jQuery(document.createElement('input'))
|
||||||
|
.attr('type', 'button')
|
||||||
|
.attr('value', this.cancelButton)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.element.html(output);
|
||||||
|
this.setHtmlAttributes();
|
||||||
|
|
||||||
|
// set width and height of textarea
|
||||||
|
jQuery(this.element.find("textarea")[0]).css({ 'min-width': width, 'min-height': height });
|
||||||
|
jQuery(this.element.find("textarea")[0]).elastic();
|
||||||
|
|
||||||
|
this.element.find("textarea")[0].focus();
|
||||||
|
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.textarea.submitHandler);
|
||||||
|
if (this.cancelButton) {
|
||||||
|
this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.textarea.cancelButtonHandler);
|
||||||
|
}
|
||||||
|
this.element.find("textarea").bind('blur', {editor: this}, BestInPlaceEditor.forms.textarea.blurHandler);
|
||||||
|
// START METAMAPS CODE
|
||||||
|
this.element.find("textarea").bind('keydown', {editor: this}, BestInPlaceEditor.forms.textarea.keydownHandler);
|
||||||
|
// END METAMAPS CODE
|
||||||
|
this.element.find("textarea").bind('keyup', {editor: this}, BestInPlaceEditor.forms.textarea.keyupHandler);
|
||||||
|
this.blurTimer = null;
|
||||||
|
this.userClicked = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue : function() {
|
||||||
|
return this.sanitizeValue(this.element.find("textarea").val());
|
||||||
|
},
|
||||||
|
|
||||||
|
// When buttons are present, use a timer on the blur event to give precedence to clicks
|
||||||
|
blurHandler : function(event) {
|
||||||
|
if (event.data.editor.okButton) {
|
||||||
|
event.data.editor.blurTimer = setTimeout(function () {
|
||||||
|
if (!event.data.editor.userClicked) {
|
||||||
|
event.data.editor.abortIfConfirm();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
if (event.data.editor.cancelButton) {
|
||||||
|
event.data.editor.blurTimer = setTimeout(function () {
|
||||||
|
if (!event.data.editor.userClicked) {
|
||||||
|
event.data.editor.update();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
event.data.editor.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
submitHandler : function(event) {
|
||||||
|
event.data.editor.userClicked = true;
|
||||||
|
clearTimeout(event.data.editor.blurTimer);
|
||||||
|
event.data.editor.update();
|
||||||
|
},
|
||||||
|
|
||||||
|
cancelButtonHandler : function(event) {
|
||||||
|
event.data.editor.userClicked = true;
|
||||||
|
clearTimeout(event.data.editor.blurTimer);
|
||||||
|
event.data.editor.abortIfConfirm();
|
||||||
|
event.stopPropagation(); // Without this, click isn't handled
|
||||||
|
},
|
||||||
|
|
||||||
|
// START METAMAPS CODE
|
||||||
|
keydownHandler : function(event) {
|
||||||
|
if (event.keyCode == 13 && !event.shiftKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// END METAMAPS CODE
|
||||||
|
|
||||||
|
keyupHandler : function(event) {
|
||||||
|
if (event.keyCode == 27) {
|
||||||
|
event.data.editor.abortIfConfirm();
|
||||||
|
}
|
||||||
|
// START METAMAPS CODE
|
||||||
|
else if (event.keyCode == 13 && !event.shiftKey) {
|
||||||
|
event.data.editor.update();
|
||||||
|
}
|
||||||
|
// END METAMAPS CODE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
jQuery.fn.best_in_place = function() {
|
||||||
|
|
||||||
|
function setBestInPlace(element) {
|
||||||
|
if (!element.data('bestInPlaceEditor')) {
|
||||||
|
element.data('bestInPlaceEditor', new BestInPlaceEditor(element));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jQuery(this.context).delegate(this.selector, 'click', function () {
|
||||||
|
var el = jQuery(this);
|
||||||
|
if (setBestInPlace(el))
|
||||||
|
el.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.each(function () {
|
||||||
|
setBestInPlace(jQuery(this));
|
||||||
|
});
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Elastic
|
||||||
|
* @descripton Elastic is Jquery plugin that grow and shrink your textareas automaticliy
|
||||||
|
* @version 1.6.5
|
||||||
|
* @requires Jquery 1.2.6+
|
||||||
|
*
|
||||||
|
* @author Jan Jarfalk
|
||||||
|
* @author-email jan.jarfalk@unwrongest.com
|
||||||
|
* @author-website http://www.unwrongest.com
|
||||||
|
*
|
||||||
|
* @licens MIT License - http://www.opensource.org/licenses/mit-license.php
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function(jQuery){
|
||||||
|
if (typeof jQuery.fn.elastic !== 'undefined') return;
|
||||||
|
|
||||||
|
jQuery.fn.extend({
|
||||||
|
elastic: function() {
|
||||||
|
// We will create a div clone of the textarea
|
||||||
|
// by copying these attributes from the textarea to the div.
|
||||||
|
var mimics = [
|
||||||
|
'paddingTop',
|
||||||
|
'paddingRight',
|
||||||
|
'paddingBottom',
|
||||||
|
'paddingLeft',
|
||||||
|
'fontSize',
|
||||||
|
'lineHeight',
|
||||||
|
'fontFamily',
|
||||||
|
'width',
|
||||||
|
'fontWeight'];
|
||||||
|
|
||||||
|
return this.each( function() {
|
||||||
|
|
||||||
|
// Elastic only works on textareas
|
||||||
|
if ( this.type != 'textarea' ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var $textarea = jQuery(this),
|
||||||
|
$twin = jQuery('<div />').css({'position': 'absolute','display':'none','word-wrap':'break-word'}),
|
||||||
|
lineHeight = parseInt($textarea.css('line-height'),10) || parseInt($textarea.css('font-size'),'10'),
|
||||||
|
minheight = parseInt($textarea.css('height'),10) || lineHeight*3,
|
||||||
|
maxheight = parseInt($textarea.css('max-height'),10) || Number.MAX_VALUE,
|
||||||
|
goalheight = 0,
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
// Opera returns max-height of -1 if not set
|
||||||
|
if (maxheight < 0) { maxheight = Number.MAX_VALUE; }
|
||||||
|
|
||||||
|
// Append the twin to the DOM
|
||||||
|
// We are going to meassure the height of this, not the textarea.
|
||||||
|
$twin.appendTo($textarea.parent());
|
||||||
|
|
||||||
|
// Copy the essential styles (mimics) from the textarea to the twin
|
||||||
|
i = mimics.length;
|
||||||
|
while(i--){
|
||||||
|
$twin.css(mimics[i].toString(),$textarea.css(mimics[i].toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sets a given height and overflow state on the textarea
|
||||||
|
function setHeightAndOverflow(height, overflow){
|
||||||
|
curratedHeight = Math.floor(parseInt(height,10));
|
||||||
|
if($textarea.height() != curratedHeight){
|
||||||
|
$textarea.css({'height': curratedHeight + 'px','overflow':overflow});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function will update the height of the textarea if necessary
|
||||||
|
function update() {
|
||||||
|
|
||||||
|
// Get curated content from the textarea.
|
||||||
|
var textareaContent = $textarea.val().replace(/&/g,'&').replace(/ /g, ' ').replace(/<|>/g, '>').replace(/\n/g, '<br />');
|
||||||
|
|
||||||
|
// Compare curated content with curated twin.
|
||||||
|
var twinContent = $twin.html().replace(/<br>/ig,'<br />');
|
||||||
|
|
||||||
|
if(textareaContent+' ' != twinContent){
|
||||||
|
|
||||||
|
// Add an extra white space so new rows are added when you are at the end of a row.
|
||||||
|
$twin.html(textareaContent+' ');
|
||||||
|
|
||||||
|
// Change textarea height if twin plus the height of one line differs more than 3 pixel from textarea height
|
||||||
|
if(Math.abs($twin.height() + lineHeight - $textarea.height()) > 3){
|
||||||
|
|
||||||
|
var goalheight = $twin.height()+lineHeight;
|
||||||
|
if(goalheight >= maxheight) {
|
||||||
|
setHeightAndOverflow(maxheight,'auto');
|
||||||
|
} else if(goalheight <= minheight) {
|
||||||
|
setHeightAndOverflow(minheight,'hidden');
|
||||||
|
} else {
|
||||||
|
setHeightAndOverflow(goalheight,'hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide scrollbars
|
||||||
|
$textarea.css({'overflow':'hidden'});
|
||||||
|
|
||||||
|
// Update textarea size on keyup, change, cut and paste
|
||||||
|
$textarea.bind('keyup change cut paste', function(){
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Compact textarea on blur
|
||||||
|
// Lets animate this....
|
||||||
|
$textarea.bind('blur',function(){
|
||||||
|
if($twin.height() < maxheight){
|
||||||
|
if($twin.height() > minheight) {
|
||||||
|
$textarea.height($twin.height());
|
||||||
|
} else {
|
||||||
|
$textarea.height(minheight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// And this line is to catch the browser paste event
|
||||||
|
$textarea.on("input paste", function(e){ setTimeout( update, 250); });
|
||||||
|
|
||||||
|
// Run update once when elastic is initialized
|
||||||
|
update();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})(jQuery);
|
|
@ -1,2 +0,0 @@
|
||||||
!function(t){"use strict";var e=t.HTMLCanvasElement&&t.HTMLCanvasElement.prototype,o=t.Blob&&function(){try{return Boolean(new Blob)}catch(t){return!1}}(),n=o&&t.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(t){return!1}}(),r=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||t.MSBlobBuilder,a=/^data:((.*?)(;charset=.*?)?)(;base64)?,/,i=(o||r)&&t.atob&&t.ArrayBuffer&&t.Uint8Array&&function(t){var e,i,l,u,b,c,d,B,f;if(e=t.match(a),!e)throw new Error("invalid data URI");for(i=e[2]?e[1]:"text/plain"+(e[3]||";charset=US-ASCII"),l=!!e[4],u=t.slice(e[0].length),b=l?atob(u):decodeURIComponent(u),c=new ArrayBuffer(b.length),d=new Uint8Array(c),B=0;B<b.length;B+=1)d[B]=b.charCodeAt(B);return o?new Blob([n?d:c],{type:i}):(f=new r,f.append(c),f.getBlob(i))};t.HTMLCanvasElement&&!e.toBlob&&(e.mozGetAsFile?e.toBlob=function(t,o,n){t(n&&e.toDataURL&&i?i(this.toDataURL(o,n)):this.mozGetAsFile("blob",o))}:e.toDataURL&&i&&(e.toBlob=function(t,e,o){t(i(this.toDataURL(e,o)))})),"function"==typeof define&&define.amd?define(function(){return i}):"object"==typeof module&&module.exports?module.exports=i:t.dataURLtoBlob=i}(window);
|
|
||||||
//# sourceMappingURL=canvas-to-blob.min.js.map
|
|
|
@ -1,431 +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;
|
||||||
});
|
});
|
||||||
|
|
||||||
// START METAMAPS CODE
|
// 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.data.rotate(-1);
|
||||||
if (event.shiftKey) {
|
event.preventDefault();
|
||||||
event.data.rotate(-1)
|
event.stopPropagation();
|
||||||
} else {
|
} else if (event.keyCode == 9) {
|
||||||
event.data.rotate(1)
|
event.data.rotate(1);
|
||||||
}
|
event.preventDefault();
|
||||||
event.preventDefault();
|
event.stopPropagation();
|
||||||
event.stopPropagation();
|
}
|
||||||
Metamaps.Create.newTopic.metacode = $(items[event.data.frontIndex].image).attr('data-id');
|
});
|
||||||
}
|
|
||||||
});
|
// You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel
|
||||||
// END METAMAPS CODE
|
if (options.mouseWheel)
|
||||||
|
{
|
||||||
// You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel
|
// START METAMAPS CODE
|
||||||
if (options.mouseWheel)
|
$('body').bind('mousewheel',this,function(event, delta) {
|
||||||
{
|
if (Metamaps.Create.newTopic.beingCreated && !Metamaps.Create.isSwitchingSet) {
|
||||||
// START METAMAPS CODE
|
event.data.rotate(delta);
|
||||||
$('body').bind('mousewheel',this,function(event, delta) {
|
return false;
|
||||||
if (Metamaps.Create.newTopic.beingCreated &&
|
}
|
||||||
!Metamaps.Create.isSwitchingSet &&
|
});
|
||||||
!Metamaps.Create.newTopic.pinned) {
|
// END METAMAPS CODE
|
||||||
event.data.rotate(delta);
|
/* ORIGINAL CODE
|
||||||
return false;
|
$(container).bind('mousewheel',this,function(event, delta) {
|
||||||
}
|
event.data.rotate(delta);
|
||||||
});
|
return false;
|
||||||
// END METAMAPS CODE
|
});
|
||||||
// ORIGINAL CODE
|
*/
|
||||||
// $(container).bind('mousewheel',this,function(event, delta) {
|
}
|
||||||
// event.data.rotate(delta);
|
$(container).bind('mouseover click',this,function(event){
|
||||||
// return false;
|
|
||||||
// });
|
clearInterval(event.data.autoRotateTimer); // Stop auto rotation if mouse over.
|
||||||
//
|
var text = $(event.target).attr('alt');
|
||||||
}
|
// If we have moved over a carousel item, then show the alt and title text.
|
||||||
$(container).unbind('mouseover click').bind('mouseover click',this,function(event){
|
|
||||||
|
if ( text !== undefined && text !== null )
|
||||||
clearInterval(event.data.autoRotateTimer); // Stop auto rotation if mouse over.
|
{
|
||||||
var text = $(event.target).attr('alt');
|
|
||||||
// If we have moved over a carousel item, then show the alt and title text.
|
clearTimeout(event.data.showFrontTextTimer);
|
||||||
|
$(options.altBox).html( ($(event.target).attr('alt') ));
|
||||||
if ( text !== undefined && text !== null )
|
//$(options.titleBox).html( ($(event.target).attr('title') ));
|
||||||
{
|
if ( options.bringToFront && event.type == 'click' )
|
||||||
|
{
|
||||||
clearTimeout(event.data.showFrontTextTimer);
|
$(options.titleBox).html( ($(event.target).attr('title') ));
|
||||||
$(options.altBox).html( ($(event.target).attr('alt') ));
|
// METAMAPS CODE
|
||||||
//$(options.titleBox).html( ($(event.target).attr('title') ));
|
Metamaps.Create.newTopic.metacode = $(event.target).attr('data-id');
|
||||||
if ( options.bringToFront && event.type == 'click' )
|
// NOT METAMAPS CODE
|
||||||
{
|
var idx = $(event.target).data('itemIndex');
|
||||||
$(options.titleBox).html( ($(event.target).attr('title') ));
|
var frontIndex = event.data.frontIndex;
|
||||||
// START METAMAPS CODE
|
//var diff = idx - frontIndex;
|
||||||
Metamaps.Create.newTopic.metacode = $(event.target).attr('data-id');
|
var diff = (idx - frontIndex) % images.length;
|
||||||
// END METAMAPS CODE
|
if (Math.abs(diff) > images.length / 2) {
|
||||||
var idx = $(event.target).data('itemIndex');
|
diff += (diff > 0 ? -images.length : images.length);
|
||||||
var frontIndex = event.data.frontIndex;
|
}
|
||||||
//var diff = idx - frontIndex;
|
|
||||||
var diff = (idx - frontIndex) % images.length;
|
event.data.rotate(-diff);
|
||||||
if (Math.abs(diff) > images.length / 2) {
|
}
|
||||||
diff += (diff > 0 ? -images.length : images.length);
|
}
|
||||||
}
|
});
|
||||||
|
// If we have moved out of a carousel item (or the container itself),
|
||||||
event.data.rotate(-diff);
|
// restore the text of the front item in 1 second.
|
||||||
}
|
$(container).bind('mouseout',this,function(event){
|
||||||
}
|
var context = event.data;
|
||||||
});
|
clearTimeout(context.showFrontTextTimer);
|
||||||
// START METAMAPS CODE - initialize newTopic.metacode
|
context.showFrontTextTimer = setTimeout( function(){context.showFrontText();},1000);
|
||||||
var first = $(this.container).find('img').get(0)
|
context.autoRotate(); // Start auto rotation.
|
||||||
Metamaps.Create.newTopic.metacode = $(first).data('id')
|
});
|
||||||
// END METAMAPS CODE
|
|
||||||
|
// Prevent items from being selected as mouse is moved and clicked in the container.
|
||||||
// If we have moved out of a carousel item (or the container itself),
|
$(container).bind('mousedown',this,function(event){
|
||||||
// restore the text of the front item in 1 second.
|
|
||||||
$(container).bind('mouseout',this,function(event){
|
event.data.container.focus();
|
||||||
var context = event.data;
|
return false;
|
||||||
clearTimeout(context.showFrontTextTimer);
|
});
|
||||||
context.showFrontTextTimer = setTimeout( function(){context.showFrontText();},1000);
|
container.onselectstart = function () { return false; }; // For IE.
|
||||||
context.autoRotate(); // Start auto rotation.
|
|
||||||
});
|
this.innerWrapper = $(container).wrapInner('<div style="position:absolute;width:100%;height:100%;"/>').children()[0];
|
||||||
|
|
||||||
// Prevent items from being selected as mouse is moved and clicked in the container.
|
// Shows the text from the front most item.
|
||||||
$(container).bind('mousedown',this,function(event){
|
this.showFrontText = function()
|
||||||
|
{
|
||||||
event.data.container.focus();
|
if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet.
|
||||||
return false;
|
// METAMAPS CODE
|
||||||
});
|
Metamaps.Create.newTopic.metacode = $(items[this.frontIndex].image).attr('data-id');
|
||||||
container.onselectstart = function () { return false; }; // For IE.
|
//$('img.cloudcarousel').css({"background":"none", "width":"","height":""});
|
||||||
|
//$(items[this.frontIndex].image).css({"width":"45px","height":"45px"});
|
||||||
this.innerWrapper = $(container).wrapInner('<div style="position:absolute;width:100%;height:100%;"/>').children()[0];
|
// NOT METAMAPS CODE
|
||||||
|
$(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));
|
||||||
// Shows the text from the front most item.
|
$(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));
|
||||||
this.showFrontText = function()
|
};
|
||||||
{
|
|
||||||
if ( items[this.frontIndex] === undefined ) { return; } // Images might not have loaded yet.
|
this.go = function()
|
||||||
$(options.titleBox).html( $(items[this.frontIndex].image).attr('title'));
|
{
|
||||||
$(options.altBox).html( $(items[this.frontIndex].image).attr('alt'));
|
if(this.controlTimer !== 0) { return; }
|
||||||
};
|
var context = this;
|
||||||
|
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
|
||||||
this.go = function()
|
};
|
||||||
{
|
|
||||||
if(this.controlTimer !== 0) { return; }
|
this.stop = function()
|
||||||
var context = this;
|
{
|
||||||
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
|
clearTimeout(this.controlTimer);
|
||||||
};
|
this.controlTimer = 0;
|
||||||
|
};
|
||||||
this.stop = function()
|
|
||||||
{
|
|
||||||
clearTimeout(this.controlTimer);
|
// Starts the rotation of the carousel. Direction is the number (+-) of carousel items to rotate by.
|
||||||
this.controlTimer = 0;
|
this.rotate = function(direction)
|
||||||
};
|
{
|
||||||
|
this.frontIndex -= direction;
|
||||||
|
if (this.frontIndex == -1) this.frontIndex = items.length - 1;
|
||||||
// Starts the rotation of the carousel. Direction is the number (+-) of carousel items to rotate by.
|
this.frontIndex %= items.length;
|
||||||
this.rotate = function(direction)
|
this.destRotation += ( Math.PI / items.length ) * ( 2*direction );
|
||||||
{
|
this.showFrontText();
|
||||||
this.frontIndex -= direction;
|
this.go();
|
||||||
if (this.frontIndex == -1) this.frontIndex = items.length - 1;
|
};
|
||||||
this.frontIndex %= items.length;
|
|
||||||
this.destRotation += ( Math.PI / items.length ) * ( 2*direction );
|
|
||||||
this.showFrontText();
|
this.autoRotate = function()
|
||||||
this.go();
|
{
|
||||||
};
|
if ( options.autoRotate !== 'no' )
|
||||||
|
{
|
||||||
|
var dir = (options.autoRotate === 'right')? 1 : -1;
|
||||||
this.autoRotate = function()
|
this.autoRotateTimer = setInterval( function(){ctx.rotate(dir); }, options.autoRotateDelay );
|
||||||
{
|
}
|
||||||
if ( options.autoRotate !== 'no' )
|
};
|
||||||
{
|
|
||||||
var dir = (options.autoRotate === 'right')? 1 : -1;
|
// This is the main loop function that moves everything.
|
||||||
this.autoRotateTimer = setInterval( function(){ctx.rotate(dir); }, options.autoRotateDelay );
|
this.updateAll = function()
|
||||||
}
|
{
|
||||||
};
|
var minScale = options.minScale; // This is the smallest scale applied to the furthest item.
|
||||||
|
var smallRange = (1-minScale) * 0.5;
|
||||||
// This is the main loop function that moves everything.
|
var w,h,x,y,scale,item,sinVal;
|
||||||
this.updateAll = function()
|
|
||||||
{
|
var change = (this.destRotation - this.rotation);
|
||||||
var minScale = options.minScale; // This is the smallest scale applied to the furthest item.
|
var absChange = Math.abs(change);
|
||||||
var smallRange = (1-minScale) * 0.5;
|
|
||||||
var w,h,x,y,scale,item,sinVal;
|
this.rotation += change * options.speed;
|
||||||
|
if ( absChange < 0.001 ) { this.rotation = this.destRotation; }
|
||||||
var change = (this.destRotation - this.rotation);
|
var itemsLen = items.length;
|
||||||
var absChange = Math.abs(change);
|
var spacing = (Math.PI / itemsLen) * 2;
|
||||||
|
//var wrapStyle = null;
|
||||||
this.rotation += change * options.speed;
|
var radians = this.rotation;
|
||||||
if ( absChange < 0.001 ) { this.rotation = this.destRotation; }
|
var isMSIE = $.browser.msie;
|
||||||
var itemsLen = items.length;
|
|
||||||
var spacing = (Math.PI / itemsLen) * 2;
|
// Turn off display. This can reduce repaints/reflows when making style and position changes in the loop.
|
||||||
//var wrapStyle = null;
|
// See http://dev.opera.com/articles/view/efficient-javascript/?page=3
|
||||||
var radians = this.rotation;
|
this.innerWrapper.style.display = 'none';
|
||||||
var isMSIE = $.browser.msie;
|
|
||||||
|
var style;
|
||||||
// Turn off display. This can reduce repaints/reflows when making style and position changes in the loop.
|
var px = 'px', reflHeight;
|
||||||
// See http://dev.opera.com/articles/view/efficient-javascript/?page=3
|
var context = this;
|
||||||
this.innerWrapper.style.display = 'none';
|
for (var i = 0; i<itemsLen ;i++)
|
||||||
|
{
|
||||||
var style;
|
item = items[i];
|
||||||
var px = 'px', reflHeight;
|
|
||||||
var context = this;
|
sinVal = funcSin(radians);
|
||||||
for (var i = 0; i<itemsLen ;i++)
|
|
||||||
{
|
scale = ((sinVal+1) * smallRange) + minScale;
|
||||||
item = items[i];
|
|
||||||
|
x = this.xCentre + (( (funcCos(radians) * this.xRadius) - (item.orgWidth*0.5)) * scale);
|
||||||
sinVal = funcSin(radians);
|
y = this.yCentre + (( (sinVal * this.yRadius) ) * scale);
|
||||||
|
|
||||||
scale = ((sinVal+1) * smallRange) + minScale;
|
if (item.imageOK)
|
||||||
|
{
|
||||||
x = this.xCentre + (( (funcCos(radians) * this.xRadius) - (item.orgWidth*0.5)) * scale);
|
var img = item.image;
|
||||||
y = this.yCentre + (( (sinVal * this.yRadius) ) * scale);
|
|
||||||
|
img.style.zIndex = "" + (scale * 100)>>0; // >>0 = Math.foor(). Firefox doesn't like fractional decimals in z-index.
|
||||||
if (item.imageOK)
|
w = img.width = item.orgWidth * scale;
|
||||||
{
|
h = img.height = item.orgHeight * scale;
|
||||||
var img = item.image;
|
img.style.left = x + px ;
|
||||||
|
img.style.top = y + px;
|
||||||
img.style.zIndex = "" + (scale * 100)>>0; // >>0 = Math.foor(). Firefox doesn't like fractional decimals in z-index.
|
if (item.reflection !== null)
|
||||||
w = img.width = item.orgWidth * scale;
|
{
|
||||||
h = img.height = item.orgHeight * scale;
|
reflHeight = options.reflHeight * scale;
|
||||||
img.style.left = x + px ;
|
style = item.reflection.element.style;
|
||||||
img.style.top = y + px;
|
style.left = x + px;
|
||||||
if (item.reflection !== null)
|
style.top = y + h + options.reflGap * scale + px;
|
||||||
{
|
style.width = w + px;
|
||||||
reflHeight = options.reflHeight * scale;
|
if (isMSIE)
|
||||||
style = item.reflection.element.style;
|
{
|
||||||
style.left = x + px;
|
style.filter.finishy = (reflHeight / h * 100);
|
||||||
style.top = y + h + options.reflGap * scale + px;
|
}else
|
||||||
style.width = w + px;
|
{
|
||||||
if (isMSIE)
|
style.height = reflHeight + px;
|
||||||
{
|
}
|
||||||
style.filter.finishy = (reflHeight / h * 100);
|
}
|
||||||
}else
|
}
|
||||||
{
|
radians += spacing;
|
||||||
style.height = reflHeight + px;
|
}
|
||||||
}
|
// Turn display back on.
|
||||||
}
|
this.innerWrapper.style.display = 'block';
|
||||||
}
|
|
||||||
radians += spacing;
|
// If we have a preceptable change in rotation then loop again next frame.
|
||||||
}
|
if ( absChange >= 0.001 )
|
||||||
// Turn display back on.
|
{
|
||||||
this.innerWrapper.style.display = 'block';
|
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
|
||||||
|
}else
|
||||||
// If we have a preceptable change in rotation then loop again next frame.
|
{
|
||||||
if ( absChange >= 0.001 )
|
// Otherwise just stop completely.
|
||||||
{
|
this.stop();
|
||||||
this.controlTimer = setTimeout( function(){context.updateAll();},this.timeDelay);
|
}
|
||||||
}else
|
}; // END updateAll
|
||||||
{
|
|
||||||
// Otherwise just stop completely.
|
// Create an Item object for each image
|
||||||
this.stop();
|
// func = function(){return;ctx.updateAll();} ;
|
||||||
}
|
|
||||||
}; // END updateAll
|
// Check if images have loaded. We need valid widths and heights for the reflections.
|
||||||
|
this.checkImagesLoaded = function()
|
||||||
// Create an Item object for each image
|
{
|
||||||
// func = function(){return;ctx.updateAll();} ;
|
var i;
|
||||||
|
for(i=0;i<images.length;i++) {
|
||||||
// Check if images have loaded. We need valid widths and heights for the reflections.
|
if ( (images[i].width === undefined) || ( (images[i].complete !== undefined) && (!images[i].complete) ))
|
||||||
this.checkImagesLoaded = function()
|
{
|
||||||
{
|
return;
|
||||||
var i;
|
}
|
||||||
for(i=0;i<images.length;i++) {
|
}
|
||||||
if ( (images[i].width === undefined) || ( (images[i].complete !== undefined) && (!images[i].complete) ))
|
for(i=0;i<images.length;i++) {
|
||||||
{
|
items.push( new Item( images[i], options ) );
|
||||||
return;
|
$(images[i]).data('itemIndex',i);
|
||||||
}
|
}
|
||||||
}
|
// If all images have valid widths and heights, we can stop checking.
|
||||||
for(i=0;i<images.length;i++) {
|
clearInterval(this.tt);
|
||||||
items.push( new Item( images[i], options ) );
|
this.showFrontText();
|
||||||
$(images[i]).data('itemIndex',i);
|
this.autoRotate();
|
||||||
}
|
this.updateAll();
|
||||||
// If all images have valid widths and heights, we can stop checking.
|
|
||||||
clearInterval(this.tt);
|
};
|
||||||
this.showFrontText();
|
|
||||||
this.autoRotate();
|
this.tt = setInterval( function(){ctx.checkImagesLoaded();},50);
|
||||||
this.updateAll();
|
}; // END Controller object
|
||||||
|
|
||||||
};
|
// The jQuery plugin part. Iterates through items specified in selector and inits a Controller class for each one.
|
||||||
|
$.fn.CloudCarousel = function(options) {
|
||||||
this.tt = setInterval( function(){ctx.checkImagesLoaded();},50);
|
|
||||||
}; // END Controller object
|
this.each( function() {
|
||||||
|
|
||||||
// The jQuery plugin part. Iterates through items specified in selector and inits a Controller class for each one.
|
options = $.extend({}, {
|
||||||
$.fn.CloudCarousel = function(options) {
|
reflHeight:0,
|
||||||
|
reflOpacity:0.5,
|
||||||
this.each( function() {
|
reflGap:0,
|
||||||
|
minScale:0.5,
|
||||||
options = $.extend({}, {
|
xPos:0,
|
||||||
reflHeight:0,
|
yPos:0,
|
||||||
reflOpacity:0.5,
|
xRadius:0,
|
||||||
reflGap:0,
|
yRadius:0,
|
||||||
minScale:0.5,
|
altBox:null,
|
||||||
xPos:0,
|
titleBox:null,
|
||||||
yPos:0,
|
FPS: 30,
|
||||||
xRadius:0,
|
autoRotate: 'no',
|
||||||
yRadius:0,
|
autoRotateDelay: 1500,
|
||||||
altBox:null,
|
speed:0.2,
|
||||||
titleBox:null,
|
mouseWheel: false,
|
||||||
FPS: 30,
|
bringToFront: false
|
||||||
autoRotate: 'no',
|
},options );
|
||||||
autoRotateDelay: 1500,
|
// Create a Controller for each carousel.
|
||||||
speed:0.2,
|
$(this).data('cloudcarousel', new Controller( this, $('.cloudcarousel',$(this)), options) );
|
||||||
mouseWheel: false,
|
});
|
||||||
bringToFront: false
|
return this;
|
||||||
},options );
|
};
|
||||||
// Create a Controller for each carousel.
|
|
||||||
$(this).data('cloudcarousel', new Controller( this, $('.cloudcarousel',$(this)), options) );
|
})(jQuery);
|
||||||
});
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
})(jQuery);
|
|
25
app/assets/javascripts/lib/jquery-ui-1.8.23.custom.min.js
vendored
Normal file
180
app/assets/javascripts/lib/jquery.purr.js
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
/**
|
||||||
|
* jquery.purr.js
|
||||||
|
* Copyright (c) 2008 Net Perspective (net-perspective.com)
|
||||||
|
* Licensed under the MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
|
*
|
||||||
|
* @author R.A. Ray
|
||||||
|
* @projectDescription jQuery plugin for dynamically displaying unobtrusive messages in the browser. Mimics the behavior of the MacOS program "Growl."
|
||||||
|
* @version 0.1.0
|
||||||
|
*
|
||||||
|
* @requires jquery.js (tested with 1.2.6)
|
||||||
|
*
|
||||||
|
* @param fadeInSpeed int - Duration of fade in animation in miliseconds
|
||||||
|
* default: 500
|
||||||
|
* @param fadeOutSpeed int - Duration of fade out animationin miliseconds
|
||||||
|
default: 500
|
||||||
|
* @param removeTimer int - Timeout, in miliseconds, before notice is removed once it is the top non-sticky notice in the list
|
||||||
|
default: 4000
|
||||||
|
* @param isSticky bool - Whether the notice should fade out on its own or wait to be manually closed
|
||||||
|
default: false
|
||||||
|
* @param usingTransparentPNG bool - Whether or not the notice is using transparent .png images in its styling
|
||||||
|
default: false
|
||||||
|
*/
|
||||||
|
|
||||||
|
( function( $ ) {
|
||||||
|
|
||||||
|
$.purr = function ( notice, options )
|
||||||
|
{
|
||||||
|
// Convert notice to a jQuery object
|
||||||
|
notice = $( notice );
|
||||||
|
|
||||||
|
// Add a class to denote the notice as not sticky
|
||||||
|
if ( !options.isSticky )
|
||||||
|
{
|
||||||
|
notice.addClass( 'not-sticky' );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the container element from the page
|
||||||
|
var cont = document.getElementById( 'purr-container' );
|
||||||
|
|
||||||
|
// If the container doesn't yet exist, we need to create it
|
||||||
|
if ( !cont )
|
||||||
|
{
|
||||||
|
cont = '<div id="purr-container"></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert cont to a jQuery object
|
||||||
|
cont = $( cont );
|
||||||
|
|
||||||
|
// Add the container to the page
|
||||||
|
$( 'body' ).append( cont );
|
||||||
|
|
||||||
|
notify();
|
||||||
|
|
||||||
|
function notify ()
|
||||||
|
{
|
||||||
|
// Set up the close button
|
||||||
|
var close = document.createElement( 'a' );
|
||||||
|
$( close ).attr(
|
||||||
|
{
|
||||||
|
className: 'close',
|
||||||
|
href: '#close',
|
||||||
|
innerHTML: 'Close'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.appendTo( notice )
|
||||||
|
.click( function ()
|
||||||
|
{
|
||||||
|
removeNotice();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add the notice to the page and keep it hidden initially
|
||||||
|
notice.appendTo( cont )
|
||||||
|
.hide();
|
||||||
|
|
||||||
|
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
|
||||||
|
// notice style, we'll just skip the fading in.
|
||||||
|
notice.show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Fade in the notice we just added
|
||||||
|
notice.fadeIn( options.fadeInSpeed );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the removal interval for the added notice if that notice is not a sticky
|
||||||
|
if ( !options.isSticky )
|
||||||
|
{
|
||||||
|
var topSpotInt = setInterval( function ()
|
||||||
|
{
|
||||||
|
// Check to see if our notice is the first non-sticky notice in the list
|
||||||
|
if ( notice.prevAll( '.not-sticky' ).length == 0 )
|
||||||
|
{
|
||||||
|
// Stop checking once the condition is met
|
||||||
|
clearInterval( topSpotInt );
|
||||||
|
|
||||||
|
// Call the close action after the timeout set in options
|
||||||
|
setTimeout( function ()
|
||||||
|
{
|
||||||
|
removeNotice();
|
||||||
|
}, options.removeTimer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, 200 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeNotice ()
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
if ( jQuery.browser.msie && options.usingTransparentPNG )
|
||||||
|
{
|
||||||
|
notice.css( { opacity: 0 } )
|
||||||
|
.animate(
|
||||||
|
{
|
||||||
|
height: '0px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: options.fadeOutSpeed,
|
||||||
|
complete: function ()
|
||||||
|
{
|
||||||
|
notice.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fade the object out before reducing its height to produce the sliding effect
|
||||||
|
notice.animate(
|
||||||
|
{
|
||||||
|
opacity: '0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: options.fadeOutSpeed,
|
||||||
|
complete: function ()
|
||||||
|
{
|
||||||
|
notice.animate(
|
||||||
|
{
|
||||||
|
height: '0px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: options.fadeOutSpeed,
|
||||||
|
complete: function ()
|
||||||
|
{
|
||||||
|
notice.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.purr = function ( options )
|
||||||
|
{
|
||||||
|
options = options || {};
|
||||||
|
options.fadeInSpeed = options.fadeInSpeed || 500;
|
||||||
|
options.fadeOutSpeed = options.fadeOutSpeed || 500;
|
||||||
|
options.removeTimer = options.removeTimer || 4000;
|
||||||
|
options.isSticky = options.isSticky || false;
|
||||||
|
options.usingTransparentPNG = options.usingTransparentPNG || false;
|
||||||
|
|
||||||
|
this.each( function()
|
||||||
|
{
|
||||||
|
new $.purr( this, options );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
})( jQuery );
|
||||||
|
|
3871
app/assets/javascripts/lib/socket.io.js
Normal file
1165
app/assets/javascripts/lib/typeahead.js
Normal file
41
app/assets/javascripts/lib/uservoice.js
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
var USERVOICE;
|
||||||
|
if(USERVOICE == undefined) {
|
||||||
|
USERVOICE = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
USERVOICE.load = function (name, id, email, sso_token) {
|
||||||
|
// Include the UserVoice JavaScript SDK (only needed once on a page)
|
||||||
|
UserVoice=window.UserVoice||[];(function(){var uv=document.createElement('script');uv.type='text/javascript';uv.async=true;uv.src='//widget.uservoice.com/wybK0nSMNuhlWkIKzTyWg.js';var s=document.getElementsByTagName('script')[0];s.parentNode.insertBefore(uv,s)})();
|
||||||
|
|
||||||
|
//
|
||||||
|
// UserVoice Javascript SDK developer documentation:
|
||||||
|
// https://www.uservoice.com/o/javascript-sdk
|
||||||
|
//
|
||||||
|
|
||||||
|
// Set colors
|
||||||
|
UserVoice.push(['set', {
|
||||||
|
accent_color: '#448dd6',
|
||||||
|
trigger_color: 'white',
|
||||||
|
trigger_background_color: 'rgba(46, 49, 51, 0.6)'
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// Identify the user and pass traits
|
||||||
|
// To enable, replace sample data with actual user traits and uncomment the line
|
||||||
|
if (name) {
|
||||||
|
UserVoice.push(['setSSO', sso_token]);
|
||||||
|
UserVoice.push(['identify', {
|
||||||
|
'email': email, // User’s email address
|
||||||
|
'name': name, // User’s real name
|
||||||
|
'id': id, // Optional: Unique id of the user
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add default trigger to the bottom-left corner of the window:
|
||||||
|
UserVoice.push(['addTrigger', { mode: 'contact', trigger_position: 'bottom-left' }]);
|
||||||
|
|
||||||
|
// Or, use your own custom trigger:
|
||||||
|
//UserVoice.push(['addTrigger', '#barometer_tab', { mode: 'contact' }]);
|
||||||
|
|
||||||
|
// Autoprompt for Satisfaction and SmartVote (only displayed under certain conditions)
|
||||||
|
UserVoice.push(['autoprompt', {}]);
|
||||||
|
};
|
1571
app/assets/javascripts/orderedLibraries/backbone.js
Normal file
1227
app/assets/javascripts/orderedLibraries/underscore.js
Normal file
36
app/assets/javascripts/require/require.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
RequireJS 2.1.11 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
|
||||||
|
Available via the MIT or new BSD license.
|
||||||
|
see: http://github.com/jrburke/requirejs for details
|
||||||
|
*/
|
||||||
|
var requirejs,require,define;
|
||||||
|
(function(ca){function G(b){return"[object Function]"===M.call(b)}function H(b){return"[object Array]"===M.call(b)}function v(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function U(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function s(b,c){return ga.call(b,c)}function j(b,c){return s(b,c)&&b[c]}function B(b,c){for(var d in b)if(s(b,d)&&c(b[d],d))break}function V(b,c,d,g){c&&B(c,function(c,h){if(d||!s(b,h))g&&"object"===typeof c&&c&&!H(c)&&!G(c)&&!(c instanceof
|
||||||
|
RegExp)?(b[h]||(b[h]={}),V(b[h],c,d,g)):b[h]=c});return b}function t(b,c){return function(){return c.apply(b,arguments)}}function da(b){throw b;}function ea(b){if(!b)return b;var c=ca;v(b.split("."),function(b){c=c[b]});return c}function C(b,c,d,g){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=g;d&&(c.originalError=d);return c}function ha(b){function c(a,e,b){var f,n,c,d,g,h,i,I=e&&e.split("/");n=I;var m=l.map,k=m&&m["*"];if(a&&"."===a.charAt(0))if(e){n=
|
||||||
|
I.slice(0,I.length-1);a=a.split("/");e=a.length-1;l.nodeIdCompat&&R.test(a[e])&&(a[e]=a[e].replace(R,""));n=a=n.concat(a);d=n.length;for(e=0;e<d;e++)if(c=n[e],"."===c)n.splice(e,1),e-=1;else if(".."===c)if(1===e&&(".."===n[2]||".."===n[0]))break;else 0<e&&(n.splice(e-1,2),e-=2);a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if(b&&m&&(I||k)){n=a.split("/");e=n.length;a:for(;0<e;e-=1){d=n.slice(0,e).join("/");if(I)for(c=I.length;0<c;c-=1)if(b=j(m,I.slice(0,c).join("/")))if(b=j(b,d)){f=b;
|
||||||
|
g=e;break a}!h&&(k&&j(k,d))&&(h=j(k,d),i=e)}!f&&h&&(f=h,g=i);f&&(n.splice(0,g,f),a=n.join("/"))}return(f=j(l.pkgs,a))?f:a}function d(a){z&&v(document.getElementsByTagName("script"),function(e){if(e.getAttribute("data-requiremodule")===a&&e.getAttribute("data-requirecontext")===i.contextName)return e.parentNode.removeChild(e),!0})}function g(a){var e=j(l.paths,a);if(e&&H(e)&&1<e.length)return e.shift(),i.require.undef(a),i.require([a]),!0}function u(a){var e,b=a?a.indexOf("!"):-1;-1<b&&(e=a.substring(0,
|
||||||
|
b),a=a.substring(b+1,a.length));return[e,a]}function m(a,e,b,f){var n,d,g=null,h=e?e.name:null,l=a,m=!0,k="";a||(m=!1,a="_@r"+(M+=1));a=u(a);g=a[0];a=a[1];g&&(g=c(g,h,f),d=j(p,g));a&&(g?k=d&&d.normalize?d.normalize(a,function(a){return c(a,h,f)}):c(a,h,f):(k=c(a,h,f),a=u(k),g=a[0],k=a[1],b=!0,n=i.nameToUrl(k)));b=g&&!d&&!b?"_unnormalized"+(Q+=1):"";return{prefix:g,name:k,parentMap:e,unnormalized:!!b,url:n,originalName:l,isDefine:m,id:(g?g+"!"+k:k)+b}}function q(a){var e=a.id,b=j(k,e);b||(b=k[e]=new i.Module(a));
|
||||||
|
return b}function r(a,e,b){var f=a.id,n=j(k,f);if(s(p,f)&&(!n||n.defineEmitComplete))"defined"===e&&b(p[f]);else if(n=q(a),n.error&&"error"===e)b(n.error);else n.on(e,b)}function w(a,e){var b=a.requireModules,f=!1;if(e)e(a);else if(v(b,function(e){if(e=j(k,e))e.error=a,e.events.error&&(f=!0,e.emit("error",a))}),!f)h.onError(a)}function x(){S.length&&(ia.apply(A,[A.length,0].concat(S)),S=[])}function y(a){delete k[a];delete W[a]}function F(a,e,b){var f=a.map.id;a.error?a.emit("error",a.error):(e[f]=
|
||||||
|
!0,v(a.depMaps,function(f,c){var d=f.id,g=j(k,d);g&&(!a.depMatched[c]&&!b[d])&&(j(e,d)?(a.defineDep(c,p[d]),a.check()):F(g,e,b))}),b[f]=!0)}function D(){var a,e,b=(a=1E3*l.waitSeconds)&&i.startTime+a<(new Date).getTime(),f=[],c=[],h=!1,k=!0;if(!X){X=!0;B(W,function(a){var i=a.map,m=i.id;if(a.enabled&&(i.isDefine||c.push(a),!a.error))if(!a.inited&&b)g(m)?h=e=!0:(f.push(m),d(m));else if(!a.inited&&(a.fetched&&i.isDefine)&&(h=!0,!i.prefix))return k=!1});if(b&&f.length)return a=C("timeout","Load timeout for modules: "+
|
||||||
|
f,null,f),a.contextName=i.contextName,w(a);k&&v(c,function(a){F(a,{},{})});if((!b||e)&&h)if((z||fa)&&!Y)Y=setTimeout(function(){Y=0;D()},50);X=!1}}function E(a){s(p,a[0])||q(m(a[0],null,!0)).init(a[1],a[2])}function K(a){var a=a.currentTarget||a.srcElement,e=i.onScriptLoad;a.detachEvent&&!Z?a.detachEvent("onreadystatechange",e):a.removeEventListener("load",e,!1);e=i.onScriptError;(!a.detachEvent||Z)&&a.removeEventListener("error",e,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function L(){var a;
|
||||||
|
for(x();A.length;){a=A.shift();if(null===a[0])return w(C("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));E(a)}}var X,$,i,N,Y,l={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},k={},W={},aa={},A=[],p={},T={},ba={},M=1,Q=1;N={require:function(a){return a.require?a.require:a.require=i.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?p[a.map.id]=a.exports:a.exports=p[a.map.id]={}},module:function(a){return a.module?
|
||||||
|
a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return j(l.config,a.map.id)||{}},exports:a.exports||(a.exports={})}}};$=function(a){this.events=j(aa,a.id)||{};this.map=a;this.shim=j(l.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};$.prototype={init:function(a,e,b,f){f=f||{};if(!this.inited){this.factory=e;if(b)this.on("error",b);else this.events.error&&(b=t(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=
|
||||||
|
b;this.inited=!0;this.ignore=f.ignore;f.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,e){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=e)},fetch:function(){if(!this.fetched){this.fetched=!0;i.startTime=(new Date).getTime();var a=this.map;if(this.shim)i.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],t(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=
|
||||||
|
this.map.url;T[a]||(T[a]=!0,i.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,e,b=this.map.id;e=this.depExports;var f=this.exports,c=this.factory;if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(G(c)){if(this.events.error&&this.map.isDefine||h.onError!==da)try{f=i.execCb(b,c,e,f)}catch(d){a=d}else f=i.execCb(b,c,e,f);this.map.isDefine&&void 0===f&&((e=this.module)?f=e.exports:this.usingExports&&
|
||||||
|
(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=c;this.exports=f;if(this.map.isDefine&&!this.ignore&&(p[b]=f,h.onResourceLoad))h.onResourceLoad(i,this.map,this.depMaps);y(b);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=
|
||||||
|
this.map,b=a.id,d=m(a.prefix);this.depMaps.push(d);r(d,"defined",t(this,function(f){var d,g;g=j(ba,this.map.id);var J=this.map.name,u=this.map.parentMap?this.map.parentMap.name:null,p=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(J=f.normalize(J,function(a){return c(a,u,!0)})||""),f=m(a.prefix+"!"+J,this.map.parentMap),r(f,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),g=j(k,f.id)){this.depMaps.push(f);
|
||||||
|
if(this.events.error)g.on("error",t(this,function(a){this.emit("error",a)}));g.enable()}}else g?(this.map.url=i.nameToUrl(g),this.load()):(d=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),d.error=t(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),d.fromText=t(this,function(f,c){var g=a.name,J=m(g),k=O;c&&(f=c);k&&(O=!1);q(J);s(l.config,b)&&(l.config[g]=l.config[b]);try{h.exec(f)}catch(j){return w(C("fromtexteval",
|
||||||
|
"fromText eval for "+b+" failed: "+j,j,[b]))}k&&(O=!0);this.depMaps.push(J);i.completeLoad(g);p([g],d)}),f.load(a.name,p,d,l))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){W[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,t(this,function(a,b){var c,f;if("string"===typeof a){a=m(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=j(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;r(a,"defined",t(this,function(a){this.defineDep(b,
|
||||||
|
a);this.check()}));this.errback&&r(a,"error",t(this,this.errback))}c=a.id;f=k[c];!s(N,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,t(this,function(a){var b=j(k,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:l,contextName:b,registry:k,defined:p,urlFetched:T,defQueue:A,Module:$,makeModuleMap:m,
|
||||||
|
nextTick:h.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=l.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(l[b]||(l[b]={}),V(l[b],a,!0,!0)):l[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(ba[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),l.shim=b);a.packages&&v(a.packages,function(a){var b,
|
||||||
|
a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(l.paths[b]=a.location);l.pkgs[b]=a.name+"/"+(a.main||"main").replace(ja,"").replace(R,"")});B(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=m(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ca,arguments));return b||a.exports&&ea(a.exports)}},makeRequire:function(a,e){function g(f,c,d){var j,l;e.enableBuildCallback&&(c&&G(c))&&(c.__requireJsBuild=
|
||||||
|
!0);if("string"===typeof f){if(G(c))return w(C("requireargs","Invalid require call"),d);if(a&&s(N,f))return N[f](k[a.id]);if(h.get)return h.get(i,f,a,g);j=m(f,a,!1,!0);j=j.id;return!s(p,j)?w(C("notloaded",'Module name "'+j+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[j]}L();i.nextTick(function(){L();l=q(m(null,a));l.skipMap=e.skipMap;l.init(f,c,d,{enabled:!0});D()});return g}e=e||{};V(g,{isBrowser:z,toUrl:function(b){var e,d=b.lastIndexOf("."),g=b.split("/")[0];if(-1!==
|
||||||
|
d&&(!("."===g||".."===g)||1<d))e=b.substring(d,b.length),b=b.substring(0,d);return i.nameToUrl(c(b,a&&a.id,!0),e,!0)},defined:function(b){return s(p,m(b,a,!1,!0).id)},specified:function(b){b=m(b,a,!1,!0).id;return s(p,b)||s(k,b)}});a||(g.undef=function(b){x();var c=m(b,a,!0),e=j(k,b);d(b);delete p[b];delete T[c.url];delete aa[b];U(A,function(a,c){a[0]===b&&A.splice(c,1)});e&&(e.events.defined&&(aa[b]=e.events),y(b))});return g},enable:function(a){j(k,a.id)&&q(a).enable()},completeLoad:function(a){var b,
|
||||||
|
c,f=j(l.shim,a)||{},d=f.exports;for(x();A.length;){c=A.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);E(c)}c=j(k,a);if(!b&&!s(p,a)&&c&&!c.inited){if(l.enforceDefine&&(!d||!ea(d)))return g(a)?void 0:w(C("nodefine","No define call for "+a,null,[a]));E([a,f.deps||[],f.exportsFn])}D()},nameToUrl:function(a,b,c){var f,d,g;(f=j(l.pkgs,a))&&(a=f);if(f=j(ba,a))return i.nameToUrl(f,b,c);if(h.jsExtRegExp.test(a))f=a+(b||"");else{f=l.paths;a=a.split("/");for(d=a.length;0<d;d-=1)if(g=a.slice(0,
|
||||||
|
d).join("/"),g=j(f,g)){H(g)&&(g=g[0]);a.splice(0,d,g);break}f=a.join("/");f+=b||(/^data\:|\?/.test(f)||c?"":".js");f=("/"===f.charAt(0)||f.match(/^[\w\+\.\-]+:/)?"":l.baseUrl)+f}return l.urlArgs?f+((-1===f.indexOf("?")?"?":"&")+l.urlArgs):f},load:function(a,b){h.load(i,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||ka.test((a.currentTarget||a.srcElement).readyState))P=null,a=K(a),i.completeLoad(a.id)},onScriptError:function(a){var b=K(a);if(!g(b.id))return w(C("scripterror",
|
||||||
|
"Script error for: "+b.id,a,[b.id]))}};i.require=i.makeRequire();return i}var h,x,y,D,K,E,P,L,q,Q,la=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ma=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,R=/\.js$/,ja=/^\.\//;x=Object.prototype;var M=x.toString,ga=x.hasOwnProperty,ia=Array.prototype.splice,z=!!("undefined"!==typeof window&&"undefined"!==typeof navigator&&window.document),fa=!z&&"undefined"!==typeof importScripts,ka=z&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,
|
||||||
|
Z="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),F={},r={},S=[],O=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(G(requirejs))return;r=requirejs;requirejs=void 0}"undefined"!==typeof require&&!G(require)&&(r=require,require=void 0);h=requirejs=function(b,c,d,g){var u,m="_";!H(b)&&"string"!==typeof b&&(u=b,H(c)?(b=c,c=d,d=g):b=[]);u&&u.context&&(m=u.context);(g=j(F,m))||(g=F[m]=h.s.newContext(m));u&&g.configure(u);return g.require(b,c,d)};h.config=function(b){return h(b)};
|
||||||
|
h.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=h);h.version="2.1.11";h.jsExtRegExp=/^\/|:|\?|\.js$/;h.isBrowser=z;x=h.s={contexts:F,newContext:ha};h({});v(["toUrl","undef","defined","specified"],function(b){h[b]=function(){var c=F._;return c.require[b].apply(c,arguments)}});if(z&&(y=x.head=document.getElementsByTagName("head")[0],D=document.getElementsByTagName("base")[0]))y=x.head=D.parentNode;h.onError=da;h.createNode=function(b){var c=
|
||||||
|
b.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");c.type=b.scriptType||"text/javascript";c.charset="utf-8";c.async=!0;return c};h.load=function(b,c,d){var g=b&&b.config||{};if(z)return g=h.createNode(g,c,d),g.setAttribute("data-requirecontext",b.contextName),g.setAttribute("data-requiremodule",c),g.attachEvent&&!(g.attachEvent.toString&&0>g.attachEvent.toString().indexOf("[native code"))&&!Z?(O=!0,g.attachEvent("onreadystatechange",b.onScriptLoad)):
|
||||||
|
(g.addEventListener("load",b.onScriptLoad,!1),g.addEventListener("error",b.onScriptError,!1)),g.src=d,L=g,D?y.insertBefore(g,D):y.appendChild(g),L=null,g;if(fa)try{importScripts(d),b.completeLoad(c)}catch(j){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,j,[c]))}};z&&!r.skipDataMain&&U(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(K=b.getAttribute("data-main"))return q=K,r.baseUrl||(E=q.split("/"),q=E.pop(),Q=E.length?E.join("/")+"/":"./",r.baseUrl=
|
||||||
|
Q),q=q.replace(R,""),h.jsExtRegExp.test(q)&&(q=K),r.deps=r.deps?r.deps.concat(q):[q],!0});define=function(b,c,d){var g,h;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(la,"").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(O){if(!(g=L))P&&"interactive"===P.readyState||U(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),g=P;g&&(b||
|
||||||
|
(b=g.getAttribute("data-requiremodule")),h=F[g.getAttribute("data-requirecontext")])}(h?h.defQueue:S).push([b,c,d])};define.amd={jQuery:!0};h.exec=function(b){return eval(b)};h(r)}})(this);
|
138
app/assets/javascripts/shims/classList.js
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* classList.js: Cross-browser full element.classList implementation.
|
||||||
|
* 2011-06-15
|
||||||
|
*
|
||||||
|
* By Eli Grey, http://eligrey.com
|
||||||
|
* Public Domain.
|
||||||
|
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*global self, document, DOMException */
|
||||||
|
|
||||||
|
/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
|
||||||
|
|
||||||
|
if (typeof document !== "undefined" && !("classList" in document.createElement("a"))) {
|
||||||
|
|
||||||
|
(function (view) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var
|
||||||
|
classListProp = "classList"
|
||||||
|
, protoProp = "prototype"
|
||||||
|
, elemCtrProto = (view.HTMLElement || view.Element)[protoProp]
|
||||||
|
, objCtr = Object
|
||||||
|
, strTrim = String[protoProp].trim || function () {
|
||||||
|
return this.replace(/^\s+|\s+$/g, "");
|
||||||
|
}
|
||||||
|
, arrIndexOf = Array[protoProp].indexOf || function (item) {
|
||||||
|
var
|
||||||
|
i = 0
|
||||||
|
, len = this.length
|
||||||
|
;
|
||||||
|
for (; i < len; i++) {
|
||||||
|
if (i in this && this[i] === item) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Vendors: please allow content code to instantiate DOMExceptions
|
||||||
|
, DOMEx = function (type, message) {
|
||||||
|
this.name = type;
|
||||||
|
this.code = DOMException[type];
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
, checkTokenAndGetIndex = function (classList, token) {
|
||||||
|
if (token === "") {
|
||||||
|
throw new DOMEx(
|
||||||
|
"SYNTAX_ERR"
|
||||||
|
, "An invalid or illegal string was specified"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (/\s/.test(token)) {
|
||||||
|
throw new DOMEx(
|
||||||
|
"INVALID_CHARACTER_ERR"
|
||||||
|
, "String contains an invalid character"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return arrIndexOf.call(classList, token);
|
||||||
|
}
|
||||||
|
, ClassList = function (elem) {
|
||||||
|
var
|
||||||
|
trimmedClasses = strTrim.call(elem.className)
|
||||||
|
, classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
|
||||||
|
, i = 0
|
||||||
|
, len = classes.length
|
||||||
|
;
|
||||||
|
for (; i < len; i++) {
|
||||||
|
this.push(classes[i]);
|
||||||
|
}
|
||||||
|
this._updateClassName = function () {
|
||||||
|
elem.className = this.toString();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
, classListProto = ClassList[protoProp] = []
|
||||||
|
, classListGetter = function () {
|
||||||
|
return new ClassList(this);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
// Most DOMException implementations don't allow calling DOMException's toString()
|
||||||
|
// on non-DOMExceptions. Error's toString() is sufficient here.
|
||||||
|
DOMEx[protoProp] = Error[protoProp];
|
||||||
|
classListProto.item = function (i) {
|
||||||
|
return this[i] || null;
|
||||||
|
};
|
||||||
|
classListProto.contains = function (token) {
|
||||||
|
token += "";
|
||||||
|
return checkTokenAndGetIndex(this, token) !== -1;
|
||||||
|
};
|
||||||
|
classListProto.add = function (token) {
|
||||||
|
token += "";
|
||||||
|
if (checkTokenAndGetIndex(this, token) === -1) {
|
||||||
|
this.push(token);
|
||||||
|
this._updateClassName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
classListProto.remove = function (token) {
|
||||||
|
token += "";
|
||||||
|
var index = checkTokenAndGetIndex(this, token);
|
||||||
|
if (index !== -1) {
|
||||||
|
this.splice(index, 1);
|
||||||
|
this._updateClassName();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
classListProto.toggle = function (token) {
|
||||||
|
token += "";
|
||||||
|
if (checkTokenAndGetIndex(this, token) === -1) {
|
||||||
|
this.add(token);
|
||||||
|
} else {
|
||||||
|
this.remove(token);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
classListProto.toString = function () {
|
||||||
|
return this.join(" ");
|
||||||
|
};
|
||||||
|
|
||||||
|
if (objCtr.defineProperty) {
|
||||||
|
var classListPropDesc = {
|
||||||
|
get: classListGetter
|
||||||
|
, enumerable: true
|
||||||
|
, configurable: true
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
|
||||||
|
} catch (ex) { // IE 8 doesn't support enumerable:true
|
||||||
|
if (ex.number === -0x7FF5EC54) {
|
||||||
|
classListPropDesc.enumerable = false;
|
||||||
|
objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (objCtr[protoProp].__defineGetter__) {
|
||||||
|
elemCtrProto.__defineGetter__(classListProp, classListGetter);
|
||||||
|
}
|
||||||
|
|
||||||
|
}(self));
|
||||||
|
|
||||||
|
}
|
23
app/assets/javascripts/shims/functionPrototypeBind.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
if (!Function.prototype.bind) {
|
||||||
|
Function.prototype.bind = function (oThis) {
|
||||||
|
if (typeof this !== "function") {
|
||||||
|
// closest thing possible to the ECMAScript 5 internal IsCallable function
|
||||||
|
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
|
||||||
|
}
|
||||||
|
|
||||||
|
var aArgs = Array.prototype.slice.call(arguments, 1),
|
||||||
|
fToBind = this,
|
||||||
|
fNOP = function () {},
|
||||||
|
fBound = function () {
|
||||||
|
return fToBind.apply(this instanceof fNOP && oThis
|
||||||
|
? this
|
||||||
|
: oThis,
|
||||||
|
aArgs.concat(Array.prototype.slice.call(arguments)));
|
||||||
|
};
|
||||||
|
|
||||||
|
fNOP.prototype = this.prototype;
|
||||||
|
fBound.prototype = new fNOP();
|
||||||
|
|
||||||
|
return fBound;
|
||||||
|
};
|
||||||
|
}
|
13
app/assets/javascripts/shims/requestAnimationFrame.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// adds requestAnimationFrame functionality
|
||||||
|
// Source: http://strd6.com/2011/05/better-window-requestanimationframe-shim/
|
||||||
|
|
||||||
|
window.requestAnimationFrame || (window.requestAnimationFrame =
|
||||||
|
window.webkitRequestAnimationFrame ||
|
||||||
|
window.mozRequestAnimationFrame ||
|
||||||
|
window.oRequestAnimationFrame ||
|
||||||
|
window.msRequestAnimationFrame ||
|
||||||
|
function(callback, element) {
|
||||||
|
return window.setTimeout(function() {
|
||||||
|
callback(+new Date());
|
||||||
|
}, 1000 / 60);
|
||||||
|
});
|
227
app/assets/javascripts/src/Metamaps.Backbone.js
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
Metamaps.Backbone = {};
|
||||||
|
Metamaps.Backbone.Map = Backbone.Model.extend({
|
||||||
|
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'],
|
||||||
|
toJSON: function (options) {
|
||||||
|
return _.omit(this.attributes, this.blacklist);
|
||||||
|
},
|
||||||
|
save: function (key, val, options) {
|
||||||
|
|
||||||
|
var attrs;
|
||||||
|
|
||||||
|
// Handle both `"key", value` and `{key: value}` -style arguments.
|
||||||
|
if (key == null || typeof key === 'object') {
|
||||||
|
attrs = key;
|
||||||
|
options = val;
|
||||||
|
} else {
|
||||||
|
(attrs = {})[key] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newOptions = options || {};
|
||||||
|
var s = newOptions.success;
|
||||||
|
|
||||||
|
newOptions.success = function (model, response, opt) {
|
||||||
|
if (s) s(model, response, opt);
|
||||||
|
model.trigger('saved');
|
||||||
|
};
|
||||||
|
return Backbone.Model.prototype.save.call(this, attrs, newOptions);
|
||||||
|
},
|
||||||
|
initialize: function () {
|
||||||
|
this.on('changeByOther', this.updateView);
|
||||||
|
this.on('saved', this.savedEvent);
|
||||||
|
},
|
||||||
|
savedEvent: function() {
|
||||||
|
Metamaps.Realtime.sendMapChange(this);
|
||||||
|
},
|
||||||
|
authorizeToEdit: function (mapper) {
|
||||||
|
if (mapper && (this.get('permission') === "commons" || this.get('user_id') === mapper.get('id'))) return true;
|
||||||
|
else return false;
|
||||||
|
},
|
||||||
|
authorizePermissionChange: function (mapper) {
|
||||||
|
if (mapper && this.get('user_id') === mapper.get('id')) return true;
|
||||||
|
else return false;
|
||||||
|
},
|
||||||
|
getUser: function () {
|
||||||
|
return Metamaps.Mapper.get(this.get('user_id'));
|
||||||
|
},
|
||||||
|
fetchContained: function () {
|
||||||
|
var bb = Metamaps.Backbone;
|
||||||
|
var that = this;
|
||||||
|
var start = function (data) {
|
||||||
|
that.set('mappers', new bb.MapperCollection(data.mappers));
|
||||||
|
that.set('topics', new bb.TopicCollection(data.topics));
|
||||||
|
that.set('synapses', new bb.SynapseCollection(data.synapses));
|
||||||
|
that.set('mappings', new bb.MappingCollection(data.mappings));
|
||||||
|
};
|
||||||
|
|
||||||
|
var e = $.ajax({
|
||||||
|
url: "/maps/" + this.id + "/contains.json",
|
||||||
|
success: start,
|
||||||
|
error: errorFunc,
|
||||||
|
async: false
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getTopics: function () {
|
||||||
|
if (!this.get('topics')) {
|
||||||
|
this.fetchContained();
|
||||||
|
}
|
||||||
|
return this.get('topics');
|
||||||
|
},
|
||||||
|
getSynapses: function () {
|
||||||
|
if (!this.get('synapses')) {
|
||||||
|
this.fetchContained();
|
||||||
|
}
|
||||||
|
return this.get('synapses');
|
||||||
|
},
|
||||||
|
getMappings: function () {
|
||||||
|
if (!this.get('mappings')) {
|
||||||
|
this.fetchContained();
|
||||||
|
}
|
||||||
|
return this.get('mappings');
|
||||||
|
},
|
||||||
|
getMappers: function () {
|
||||||
|
if (!this.get('mappers')) {
|
||||||
|
this.fetchContained();
|
||||||
|
}
|
||||||
|
return this.get('mappers');
|
||||||
|
},
|
||||||
|
attrForCards: function () {
|
||||||
|
function capitalize(string) {
|
||||||
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var n = this.get('name');
|
||||||
|
var d = this.get('desc');
|
||||||
|
|
||||||
|
var maxNameLength = 32;
|
||||||
|
var maxDescLength = 118;
|
||||||
|
var truncatedName = n ? (n.length > maxNameLength ? n.substring(0, maxNameLength) + "..." : n) : "";
|
||||||
|
var truncatedDesc = d ? (d.length > maxDescLength ? d.substring(0, maxDescLength) + "..." : d) : "";
|
||||||
|
|
||||||
|
var obj = {
|
||||||
|
id: this.id,
|
||||||
|
name: truncatedName,
|
||||||
|
fullName: n,
|
||||||
|
desc: truncatedDesc,
|
||||||
|
permission: this.get("permission") ? capitalize(this.get("permission")) : "Commons",
|
||||||
|
editPermission: this.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEdit' : 'cannotEdit',
|
||||||
|
contributor_count_number: '<span class="cCountColor">' + this.get('contributor_count') + '</span>',
|
||||||
|
contributor_count_string: this.get('contributor_count') == 1 ? ' contributor' : ' contributors',
|
||||||
|
topic_count_number: '<span class="tCountColor">' + this.get('topic_count') + '</span>',
|
||||||
|
topic_count_string: this.get('topic_count') == 1 ? ' topic' : ' topics',
|
||||||
|
synapse_count_number: '<span class="sCountColor">' + this.get('synapse_count') + '</span>',
|
||||||
|
synapse_count_string: this.get('synapse_count') == 1 ? ' synapse' : ' synapses',
|
||||||
|
screenshot: '<img src="' + this.get('screenshot_url') + '" />'
|
||||||
|
};
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
updateView: function() {
|
||||||
|
var map = Metamaps.Active.Map;
|
||||||
|
var isActiveMap = this.id === map.id;
|
||||||
|
var authorized = map && map.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEditMap' : '';
|
||||||
|
var commonsMap = map && map.get('permission') === 'commons' ? 'commonsMap' : '';
|
||||||
|
if (isActiveMap) {
|
||||||
|
Metamaps.Map.InfoBox.updateNameDescPerm(this.get('name'), this.get('desc'), this.get('permission'));
|
||||||
|
this.updateMapWrapper();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateMapWrapper: function() {
|
||||||
|
var map = Metamaps.Active.Map;
|
||||||
|
var isActiveMap = this.id === map.id;
|
||||||
|
var authorized = map && map.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEditMap' : '';
|
||||||
|
var commonsMap = map && map.get('permission') === 'commons' ? 'commonsMap' : '';
|
||||||
|
if (isActiveMap) {
|
||||||
|
$('.wrapper').removeClass('canEditMap commonsMap').addClass(authorized + ' ' + commonsMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Metamaps.Backbone.MapsCollection = Backbone.Collection.extend({
|
||||||
|
model: Metamaps.Backbone.Map,
|
||||||
|
initialize: function(models, options) {
|
||||||
|
this.id = options.id;
|
||||||
|
this.sortBy = options.sortBy;
|
||||||
|
|
||||||
|
if (options.mapperId) {
|
||||||
|
this.mapperId = options.mapperId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this.page represents the NEXT page to fetch
|
||||||
|
this.page = models.length > 0 ? (models.length < 20 ? "loadedAll" : 2) : 1;
|
||||||
|
},
|
||||||
|
url: function() {
|
||||||
|
if (!this.mapperId) {
|
||||||
|
return '/explore/' + this.id + '.json';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return '/explore/mapper/' + this.mapperId + '.json';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
comparator: function (a, b) {
|
||||||
|
a = a.get(this.sortBy);
|
||||||
|
b = b.get(this.sortBy);
|
||||||
|
var temp;
|
||||||
|
if (this.sortBy === 'name') {
|
||||||
|
a = a ? a.toLowerCase() : "";
|
||||||
|
b = b ? b.toLowerCase() : "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// this is for updated_at and created_at
|
||||||
|
temp = a;
|
||||||
|
a = b;
|
||||||
|
b = temp;
|
||||||
|
a = (new Date(a)).getTime();
|
||||||
|
b = (new Date(b)).getTime();
|
||||||
|
}
|
||||||
|
return a > b ? 1 : a < b ? -1 : 0;
|
||||||
|
},
|
||||||
|
getMaps: function (cb) {
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
Metamaps.Loading.show();
|
||||||
|
|
||||||
|
if (this.page != "loadedAll") {
|
||||||
|
var numBefore = this.length;
|
||||||
|
this.fetch({
|
||||||
|
remove: false,
|
||||||
|
silent: true,
|
||||||
|
data: { page: this.page },
|
||||||
|
success: function (collection, response, options) {
|
||||||
|
// you can pass additional options to the event you trigger here as well
|
||||||
|
if (collection.length - numBefore < 20) {
|
||||||
|
self.page = "loadedAll";
|
||||||
|
}
|
||||||
|
else self.page += 1;
|
||||||
|
self.trigger('successOnFetch', cb);
|
||||||
|
},
|
||||||
|
error: function (collection, response, options) {
|
||||||
|
// you can pass additional options to the event you trigger here as well
|
||||||
|
self.trigger('errorOnFetch');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.trigger('successOnFetch', cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
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'
|
||||||
|
});
|
661
app/assets/javascripts/src/Metamaps.GlobalUI.js
Normal file
|
@ -0,0 +1,661 @@
|
||||||
|
var Metamaps = {}; // this variable declaration defines a Javascript object that will contain all the variables and functions used by us, broken down into 'sub-modules' that look something like this
|
||||||
|
/*
|
||||||
|
|
||||||
|
* unless you are on a page with the Javascript InfoVis Toolkit (Topic or Map) the only section in the metamaps
|
||||||
|
* object will be these
|
||||||
|
GlobalUI
|
||||||
|
Active
|
||||||
|
Maps
|
||||||
|
Mappers
|
||||||
|
Backbone
|
||||||
|
|
||||||
|
* all these get added when you are on a page with the Javascript Infovis Toolkit
|
||||||
|
Settings
|
||||||
|
Touch
|
||||||
|
Mouse
|
||||||
|
Selected
|
||||||
|
Metacodes
|
||||||
|
Topics
|
||||||
|
Synapses
|
||||||
|
Mappings
|
||||||
|
Create
|
||||||
|
TopicCard
|
||||||
|
SynapseCard
|
||||||
|
Visualize
|
||||||
|
Util
|
||||||
|
Realtime
|
||||||
|
Control
|
||||||
|
Filter
|
||||||
|
Listeners
|
||||||
|
Organize
|
||||||
|
Map
|
||||||
|
Mapper
|
||||||
|
Topic
|
||||||
|
Synapse
|
||||||
|
JIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
Metamaps.Active = {
|
||||||
|
Map: null,
|
||||||
|
Topic: null,
|
||||||
|
Mapper: null
|
||||||
|
};
|
||||||
|
Metamaps.Maps = {};
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
for (var prop in Metamaps) {
|
||||||
|
|
||||||
|
// this runs the init function within each sub-object on the Metamaps one
|
||||||
|
if (Metamaps.hasOwnProperty(prop) &&
|
||||||
|
Metamaps[prop].hasOwnProperty('init') &&
|
||||||
|
typeof (Metamaps[prop].init) == 'function'
|
||||||
|
) {
|
||||||
|
Metamaps[prop].init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the famous ui
|
||||||
|
var callFamous = function(){
|
||||||
|
if (Metamaps.Famous) {
|
||||||
|
Metamaps.Famous.build();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setTimeout(callFamous, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callFamous();
|
||||||
|
});
|
||||||
|
|
||||||
|
Metamaps.GlobalUI = {
|
||||||
|
notifyTimeout: null,
|
||||||
|
lightbox: null,
|
||||||
|
init: function () {
|
||||||
|
var self = Metamaps.GlobalUI;
|
||||||
|
|
||||||
|
self.Search.init();
|
||||||
|
self.CreateMap.init();
|
||||||
|
self.Account.init();
|
||||||
|
|
||||||
|
//bind lightbox clicks
|
||||||
|
$('.openLightbox').click(function (event) {
|
||||||
|
self.openLightbox($(this).attr('data-open'));
|
||||||
|
event.preventDefault();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#lightbox_screen, #lightbox_close').click(self.closeLightbox);
|
||||||
|
|
||||||
|
// initialize global backbone models and collections
|
||||||
|
if (Metamaps.Active.Mapper) Metamaps.Active.Mapper = new Metamaps.Backbone.Mapper(Metamaps.Active.Mapper);
|
||||||
|
|
||||||
|
var myCollection = Metamaps.Maps.Mine ? Metamaps.Maps.Mine : [];
|
||||||
|
var mapperCollection = [];
|
||||||
|
var mapperOptionsObj = {id: 'mapper', sortBy: 'updated_at' };
|
||||||
|
if (Metamaps.Maps.Mapper) {
|
||||||
|
mapperCollection = Metamaps.Maps.Mapper.models;
|
||||||
|
mapperOptionsObj.mapperId = Metamaps.Maps.Mapper.id;
|
||||||
|
}
|
||||||
|
var featuredCollection = Metamaps.Maps.Featured ? Metamaps.Maps.Featured : [];
|
||||||
|
var activeCollection = Metamaps.Maps.Active ? Metamaps.Maps.Active : [];
|
||||||
|
Metamaps.Maps.Mine = new Metamaps.Backbone.MapsCollection(myCollection, {id: 'mine', sortBy: 'updated_at' });
|
||||||
|
// 'Mapper' refers to another mapper
|
||||||
|
Metamaps.Maps.Mapper = new Metamaps.Backbone.MapsCollection(mapperCollection, mapperOptionsObj);
|
||||||
|
Metamaps.Maps.Featured = new Metamaps.Backbone.MapsCollection(featuredCollection, {id: 'featured', sortBy: 'updated_at' });
|
||||||
|
Metamaps.Maps.Active = new Metamaps.Backbone.MapsCollection(activeCollection, {id: 'active', sortBy: 'updated_at' });
|
||||||
|
},
|
||||||
|
openLightbox: function (which) {
|
||||||
|
var self = Metamaps.GlobalUI;
|
||||||
|
|
||||||
|
$('.lightboxContent').hide();
|
||||||
|
$('#' + which).show();
|
||||||
|
|
||||||
|
self.lightbox = which;
|
||||||
|
|
||||||
|
$('#lightbox_overlay').show();
|
||||||
|
|
||||||
|
var heightOfContent = '-' + ($('#lightbox_main').height() / 2) + 'px';
|
||||||
|
// animate the content in from the bottom
|
||||||
|
$('#lightbox_main').animate({
|
||||||
|
'top': '50%',
|
||||||
|
'margin-top': heightOfContent
|
||||||
|
}, 200, 'easeOutCubic');
|
||||||
|
|
||||||
|
// fade the black overlay in
|
||||||
|
$('#lightbox_screen').animate({
|
||||||
|
'opacity': '0.42'
|
||||||
|
}, 200);
|
||||||
|
|
||||||
|
if (which == "switchMetacodes") {
|
||||||
|
Metamaps.Create.isSwitchingSet = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
closeLightbox: function (event) {
|
||||||
|
var self = Metamaps.GlobalUI;
|
||||||
|
|
||||||
|
if (event) event.preventDefault();
|
||||||
|
|
||||||
|
// animate the lightbox content offscreen
|
||||||
|
$('#lightbox_main').animate({
|
||||||
|
'top': '100%',
|
||||||
|
'margin-top': '0'
|
||||||
|
}, 200, 'easeInCubic');
|
||||||
|
|
||||||
|
// fade the black overlay out
|
||||||
|
$('#lightbox_screen').animate({
|
||||||
|
'opacity': '0.0'
|
||||||
|
}, 200, function () {
|
||||||
|
$('#lightbox_overlay').hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (self.lightbox === 'forkmap') Metamaps.GlobalUI.CreateMap.reset('fork_map');
|
||||||
|
if (self.lightbox === 'newmap') Metamaps.GlobalUI.CreateMap.reset('new_map');
|
||||||
|
if (Metamaps.Create && Metamaps.Create.isSwitchingSet) {
|
||||||
|
Metamaps.Create.cancelMetacodeSetSwitch();
|
||||||
|
}
|
||||||
|
self.lightbox = null;
|
||||||
|
},
|
||||||
|
notifyUser: function (message, leaveOpen) {
|
||||||
|
var self = Metamaps.GlobalUI;
|
||||||
|
|
||||||
|
Metamaps.Famous.toast.surf.setContent(message);
|
||||||
|
Metamaps.Famous.toast.show();
|
||||||
|
clearTimeout(self.notifyTimeOut);
|
||||||
|
if (!leaveOpen) {
|
||||||
|
self.notifyTimeOut = setTimeout(function () {
|
||||||
|
Metamaps.Famous.toast.hide();
|
||||||
|
}, 8000);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearNotify: function() {
|
||||||
|
var self = Metamaps.GlobalUI;
|
||||||
|
|
||||||
|
clearTimeout(self.notifyTimeOut);
|
||||||
|
Metamaps.Famous.toast.hide();
|
||||||
|
},
|
||||||
|
shareInvite: function(inviteLink) {
|
||||||
|
window.prompt("To copy the invite link, press: Ctrl+C, Enter", inviteLink);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.CreateMap = {
|
||||||
|
newMap: null,
|
||||||
|
emptyMapForm: "",
|
||||||
|
emptyForkMapForm: "",
|
||||||
|
topicsToMap: [],
|
||||||
|
synapsesToMap: [],
|
||||||
|
init: function () {
|
||||||
|
var self = Metamaps.GlobalUI.CreateMap;
|
||||||
|
|
||||||
|
self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' });
|
||||||
|
|
||||||
|
self.bindFormEvents();
|
||||||
|
|
||||||
|
self.emptyMapForm = $('#new_map').html();
|
||||||
|
|
||||||
|
},
|
||||||
|
bindFormEvents: function () {
|
||||||
|
var self = Metamaps.GlobalUI.CreateMap;
|
||||||
|
|
||||||
|
$('.new_map button.cancel').unbind().bind('click', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
Metamaps.GlobalUI.closeLightbox();
|
||||||
|
});
|
||||||
|
$('.new_map button.submitMap').unbind().bind('click', self.submit);
|
||||||
|
|
||||||
|
// bind permission changer events on the createMap form
|
||||||
|
$('.permIcon').unbind().bind('click', self.switchPermission);
|
||||||
|
},
|
||||||
|
closeSuccess: function () {
|
||||||
|
$('#mapCreatedSuccess').fadeOut(300, function(){
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
generateSuccessMessage: function (id) {
|
||||||
|
var stringStart = "<div id='mapCreatedSuccess'><h6>SUCCESS!</h6>Your map has been created. Do you want to: <a id='mapGo' href='/maps/";
|
||||||
|
stringStart += id;
|
||||||
|
stringStart += "' onclick='Metamaps.GlobalUI.CreateMap.closeSuccess();'>Go to your new map</a>";
|
||||||
|
stringStart += "<span>OR</span><a id='mapStay' href='#' onclick='Metamaps.GlobalUI.CreateMap.closeSuccess(); return false;'>Stay on this ";
|
||||||
|
var page = Metamaps.Active.Map ? 'map' : 'page';
|
||||||
|
var stringEnd = "</a></div>";
|
||||||
|
return stringStart + page + stringEnd;
|
||||||
|
},
|
||||||
|
switchPermission: function () {
|
||||||
|
var self = Metamaps.GlobalUI.CreateMap;
|
||||||
|
|
||||||
|
self.newMap.set('permission', $(this).attr('data-permission'));
|
||||||
|
$(this).siblings('.permIcon').find('.mapPermIcon').removeClass('selected');
|
||||||
|
$(this).find('.mapPermIcon').addClass('selected');
|
||||||
|
|
||||||
|
var permText = $(this).find('.tip').html();
|
||||||
|
$(this).parents('.new_map').find('.permText').html(permText);
|
||||||
|
},
|
||||||
|
submit: function (event) {
|
||||||
|
if (event) event.preventDefault();
|
||||||
|
|
||||||
|
var self = Metamaps.GlobalUI.CreateMap;
|
||||||
|
|
||||||
|
if (Metamaps.GlobalUI.lightbox === 'forkmap') {
|
||||||
|
self.newMap.set('topicsToMap', self.topicsToMap);
|
||||||
|
self.newMap.set('synapsesToMap', self.synapsesToMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map';
|
||||||
|
var $form = $(formId);
|
||||||
|
|
||||||
|
self.newMap.set('name', $form.find('#map_name').val());
|
||||||
|
self.newMap.set('desc', $form.find('#map_desc').val());
|
||||||
|
|
||||||
|
if (self.newMap.get('name').length===0){
|
||||||
|
self.throwMapNameError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.newMap.save(null, {
|
||||||
|
success: self.success
|
||||||
|
// TODO add error message
|
||||||
|
});
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.closeLightbox();
|
||||||
|
Metamaps.GlobalUI.notifyUser('Working...');
|
||||||
|
},
|
||||||
|
throwMapNameError: function () {
|
||||||
|
var self = Metamaps.GlobalUI.CreateMap;
|
||||||
|
|
||||||
|
var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map';
|
||||||
|
var $form = $(formId);
|
||||||
|
|
||||||
|
var message = $("<div class='feedback_message'>Please enter a map name...</div>");
|
||||||
|
|
||||||
|
$form.find('#map_name').after(message);
|
||||||
|
setTimeout(function(){
|
||||||
|
message.fadeOut('fast', function(){
|
||||||
|
message.remove();
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
},
|
||||||
|
success: function (model) {
|
||||||
|
var self = Metamaps.GlobalUI.CreateMap;
|
||||||
|
|
||||||
|
//push the new map onto the collection of 'my maps'
|
||||||
|
Metamaps.Maps.Mine.add(model);
|
||||||
|
|
||||||
|
var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map';
|
||||||
|
var form = $(formId);
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.clearNotify();
|
||||||
|
$('#wrapper').append(self.generateSuccessMessage(model.id));
|
||||||
|
|
||||||
|
},
|
||||||
|
reset: function (id) {
|
||||||
|
var self = Metamaps.GlobalUI.CreateMap;
|
||||||
|
|
||||||
|
var form = $('#' + id);
|
||||||
|
|
||||||
|
if (id === "fork_map") {
|
||||||
|
self.topicsToMap = [];
|
||||||
|
self.synapsesToMap = [];
|
||||||
|
form.html(self.emptyForkMapForm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
form.html(self.emptyMapForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.bindFormEvents();
|
||||||
|
self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' });
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.Account = {
|
||||||
|
isOpen: false,
|
||||||
|
changing: false,
|
||||||
|
init: function () {
|
||||||
|
var self = Metamaps.GlobalUI.Account;
|
||||||
|
|
||||||
|
$('.sidebarAccountIcon').click(self.toggleBox);
|
||||||
|
$('.sidebarAccountBox').click(function(event){
|
||||||
|
event.stopPropagation();
|
||||||
|
});
|
||||||
|
$('body').click(self.close);
|
||||||
|
},
|
||||||
|
toggleBox: function (event) {
|
||||||
|
var self = Metamaps.GlobalUI.Account;
|
||||||
|
|
||||||
|
if (self.isOpen) self.close();
|
||||||
|
else self.open();
|
||||||
|
|
||||||
|
event.stopPropagation();
|
||||||
|
},
|
||||||
|
open: function () {
|
||||||
|
var self = Metamaps.GlobalUI.Account;
|
||||||
|
|
||||||
|
Metamaps.Realtime.close();
|
||||||
|
Metamaps.Filter.close();
|
||||||
|
$('.sidebarAccountIcon .tooltipsUnder').addClass('hide');
|
||||||
|
|
||||||
|
|
||||||
|
if (!self.isOpen && !self.changing) {
|
||||||
|
self.changing = true;
|
||||||
|
$('.sidebarAccountBox').fadeIn(200, function () {
|
||||||
|
self.changing = false;
|
||||||
|
self.isOpen = true;
|
||||||
|
$('.sidebarAccountBox #user_email').focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
var self = Metamaps.GlobalUI.Account;
|
||||||
|
|
||||||
|
$('.sidebarAccountIcon .tooltipsUnder').removeClass('hide');
|
||||||
|
if (!self.changing) {
|
||||||
|
self.changing = true;
|
||||||
|
$('.sidebarAccountBox #user_email').blur();
|
||||||
|
$('.sidebarAccountBox').fadeOut(200, function () {
|
||||||
|
self.changing = false;
|
||||||
|
self.isOpen = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.Search = {
|
||||||
|
locked: false,
|
||||||
|
isOpen: false,
|
||||||
|
timeOut: null,
|
||||||
|
changing: false,
|
||||||
|
optionsInitialized: false,
|
||||||
|
init: function () {
|
||||||
|
var self = Metamaps.GlobalUI.Search;
|
||||||
|
|
||||||
|
var loader = new CanvasLoader('searchLoading');
|
||||||
|
loader.setColor('#4fb5c0'); // default is '#000000'
|
||||||
|
loader.setDiameter(24); // default is 40
|
||||||
|
loader.setDensity(41); // default is 40
|
||||||
|
loader.setRange(0.9); // default is 1.3
|
||||||
|
loader.show(); // Hidden by default
|
||||||
|
|
||||||
|
// bind the hover events
|
||||||
|
$(".sidebarSearch").hover(function () {
|
||||||
|
self.open()
|
||||||
|
}, function () {
|
||||||
|
self.close(800, false)
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.sidebarSearchIcon').click(function (e) {
|
||||||
|
$('.sidebarSearchField').focus();
|
||||||
|
});
|
||||||
|
$('.sidebarSearch').click(function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
$('body').click(function (e) {
|
||||||
|
self.close(0, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// open if the search is closed and user hits ctrl+/
|
||||||
|
// close if they hit ESC
|
||||||
|
$('body').bind('keyup', function (e) {
|
||||||
|
switch (e.which) {
|
||||||
|
case 191:
|
||||||
|
if ((e.ctrlKey && !self.isOpen) || (e.ctrlKey && self.locked)) {
|
||||||
|
self.open(true); // true for focus
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 27:
|
||||||
|
if (self.isOpen) {
|
||||||
|
self.close(0, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break; //console.log(e.which);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.startTypeahead();
|
||||||
|
},
|
||||||
|
lock: function() {
|
||||||
|
var self = Metamaps.GlobalUI.Search;
|
||||||
|
self.locked = true;
|
||||||
|
},
|
||||||
|
unlock: function() {
|
||||||
|
var self = Metamaps.GlobalUI.Search;
|
||||||
|
self.locked = false;
|
||||||
|
},
|
||||||
|
open: function (focus) {
|
||||||
|
var self = Metamaps.GlobalUI.Search;
|
||||||
|
|
||||||
|
clearTimeout(self.timeOut);
|
||||||
|
if (!self.isOpen && !self.changing && !self.locked) {
|
||||||
|
self.changing = true;
|
||||||
|
$('.sidebarSearch .twitter-typeahead, .sidebarSearch .tt-hint, .sidebarSearchField').animate({
|
||||||
|
width: '400px'
|
||||||
|
}, 300, function () {
|
||||||
|
if (focus) $('.sidebarSearchField').focus();
|
||||||
|
$('.sidebarSearchField, .sidebarSearch .tt-hint').css({
|
||||||
|
padding: '7px 10px 3px 10px',
|
||||||
|
width: '380px'
|
||||||
|
});
|
||||||
|
self.changing = false;
|
||||||
|
self.isOpen = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
close: function (closeAfter, bypass) {
|
||||||
|
var self = Metamaps.GlobalUI.Search;
|
||||||
|
|
||||||
|
self.timeOut = setTimeout(function () {
|
||||||
|
if (!self.locked && !self.changing && self.isOpen && (bypass || $('.sidebarSearchField').val() == '')) {
|
||||||
|
self.changing = true;
|
||||||
|
$('.sidebarSearchField, .sidebarSearch .tt-hint').css({
|
||||||
|
padding: '7px 0 3px 0',
|
||||||
|
width: '400px'
|
||||||
|
});
|
||||||
|
$('.sidebarSearch .twitter-typeahead, .sidebarSearch .tt-hint, .sidebarSearchField').animate({
|
||||||
|
width: '0'
|
||||||
|
}, 300, function () {
|
||||||
|
$('.sidebarSearchField').typeahead('setQuery', '');
|
||||||
|
$('.sidebarSearchField').blur();
|
||||||
|
self.changing = false;
|
||||||
|
self.isOpen = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, closeAfter);
|
||||||
|
},
|
||||||
|
startTypeahead: function () {
|
||||||
|
var self = Metamaps.GlobalUI.Search;
|
||||||
|
|
||||||
|
var mapheader = Metamaps.Active.Mapper ? '<div class="searchMapsHeader searchHeader"><h3 class="search-heading">Maps</h3><input type="checkbox" class="limitToMe" id="limitMapsToMe"></input><label for="limitMapsToMe" class="limitToMeLabel">added by me</label><div class="minimizeResults minimizeMapResults"></div><div class="clearfloat"></div></div>' : '<div class="searchMapsHeader searchHeader"><h3 class="search-heading">Maps</h3><div class="minimizeResults minimizeMapResults"></div><div class="clearfloat"></div></div>';
|
||||||
|
var topicheader = Metamaps.Active.Mapper ? '<div class="searchTopicsHeader searchHeader"><h3 class="search-heading">Topics</h3><input type="checkbox" class="limitToMe" id="limitTopicsToMe"></input><label for="limitTopicsToMe" class="limitToMeLabel">added by me</label><div class="minimizeResults minimizeTopicResults"></div><div class="clearfloat"></div></div>' : '<div class="searchTopicsHeader searchHeader"><h3 class="search-heading">Topics</h3><div class="minimizeResults minimizeTopicResults"></div><div class="clearfloat"></div></div>';
|
||||||
|
var mapperheader = '<div class="searchMappersHeader searchHeader"><h3 class="search-heading">Mappers</h3><div class="minimizeResults minimizeMapperResults"></div><div class="clearfloat"></div></div>';
|
||||||
|
|
||||||
|
var topics = {
|
||||||
|
name: 'topics',
|
||||||
|
limit: 9999,
|
||||||
|
dupChecker: function (datum1, datum2) {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
template: $('#topicSearchTemplate').html(),
|
||||||
|
remote: {
|
||||||
|
url: '/search/topics?term=%QUERY',
|
||||||
|
replace: function () {
|
||||||
|
var q = '/search/topics?term=' + $('.sidebarSearchField').val();
|
||||||
|
if (Metamaps.Active.Mapper && $("#limitTopicsToMe").is(':checked')) {
|
||||||
|
q += "&user=" + Metamaps.Active.Mapper.id.toString();
|
||||||
|
}
|
||||||
|
return q;
|
||||||
|
},
|
||||||
|
filter: function (dataset) {
|
||||||
|
if (dataset.length == 0) {
|
||||||
|
dataset.push({
|
||||||
|
value: "No results",
|
||||||
|
label: "No results",
|
||||||
|
typeImageURL: "/assets/icons/wildcard.png",
|
||||||
|
rtype: "noresult"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return dataset;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
engine: Hogan,
|
||||||
|
header: topicheader
|
||||||
|
};
|
||||||
|
|
||||||
|
var maps = {
|
||||||
|
name: 'maps',
|
||||||
|
limit: 9999,
|
||||||
|
dupChecker: function (datum1, datum2) {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
template: $('#mapSearchTemplate').html(),
|
||||||
|
remote: {
|
||||||
|
url: '/search/maps?term=%QUERY',
|
||||||
|
replace: function () {
|
||||||
|
var q = '/search/maps?term=' + $('.sidebarSearchField').val();
|
||||||
|
if (Metamaps.Active.Mapper && $("#limitMapsToMe").is(':checked')) {
|
||||||
|
q += "&user=" + Metamaps.Active.Mapper.id.toString();
|
||||||
|
}
|
||||||
|
return q;
|
||||||
|
},
|
||||||
|
filter: function (dataset) {
|
||||||
|
if (dataset.length == 0) {
|
||||||
|
dataset.push({
|
||||||
|
value: "No results",
|
||||||
|
label: "No results",
|
||||||
|
rtype: "noresult"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return dataset;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
engine: Hogan,
|
||||||
|
header: mapheader
|
||||||
|
};
|
||||||
|
|
||||||
|
var mappers = {
|
||||||
|
name: 'mappers',
|
||||||
|
limit: 9999,
|
||||||
|
dupChecker: function (datum1, datum2) {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
template: $('#mapperSearchTemplate').html(),
|
||||||
|
remote: {
|
||||||
|
url: '/search/mappers?term=%QUERY',
|
||||||
|
filter: function (dataset) {
|
||||||
|
if (dataset.length == 0) {
|
||||||
|
dataset.push({
|
||||||
|
profile: "/assets/user.png",
|
||||||
|
|
||||||
|
value: "No results",
|
||||||
|
label: "No results",
|
||||||
|
rtype: "noresult"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return dataset;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
engine: Hogan,
|
||||||
|
header: mapperheader
|
||||||
|
};
|
||||||
|
$('.sidebarSearchField').typeahead([topics, maps, mappers]);
|
||||||
|
|
||||||
|
//Set max height of the search results box to prevent it from covering bottom left footer
|
||||||
|
$('.sidebarSearchField').bind('typeahead:suggestionsRendered', function (event) {
|
||||||
|
self.initSearchOptions();
|
||||||
|
self.hideLoader();
|
||||||
|
var h = $(window).height();
|
||||||
|
$(".tt-dropdown-menu").css('max-height', h - 100);
|
||||||
|
});
|
||||||
|
$(window).resize(function () {
|
||||||
|
var h = $(window).height();
|
||||||
|
$(".tt-dropdown-menu").css('max-height', h - 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
// tell the autocomplete to launch a new tab with the topic, map, or mapper you clicked on
|
||||||
|
$('.sidebarSearchField').bind('typeahead:selected', self.handleResultClick);
|
||||||
|
|
||||||
|
// don't do it, if they clicked on a 'addToMap' button
|
||||||
|
$('.sidebarSearch button.addToMap').click(function (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
// make sure that when you click on 'limit to me' or 'toggle section' it works
|
||||||
|
$('.sidebarSearchField').bind('typeahead:queryChanged', function(){
|
||||||
|
if ($(this).val() === "") {
|
||||||
|
self.hideLoader();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.showLoader();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
handleResultClick: function (event, datum, dataset) {
|
||||||
|
var self = Metamaps.GlobalUI.Search;
|
||||||
|
|
||||||
|
self.hideLoader();
|
||||||
|
|
||||||
|
if (datum.rtype != "noresult") {
|
||||||
|
self.close(0, true);
|
||||||
|
var win;
|
||||||
|
if (dataset == "topics") {
|
||||||
|
Metamaps.Router.topics(datum.id);
|
||||||
|
} else if (dataset == "maps") {
|
||||||
|
Metamaps.Router.maps(datum.id);
|
||||||
|
} else if (dataset == "mappers") {
|
||||||
|
Metamaps.Router.explore("mapper", datum.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initSearchOptions: function () {
|
||||||
|
var self = Metamaps.GlobalUI.Search;
|
||||||
|
|
||||||
|
function toggleResultSet(set) {
|
||||||
|
var s = $('.tt-dataset-' + set + ' .tt-suggestions');
|
||||||
|
if (s.css('height') == '0px') {
|
||||||
|
s.css({
|
||||||
|
'height': 'auto',
|
||||||
|
'overflow': 'visible'
|
||||||
|
});
|
||||||
|
$(this).removeClass('maximizeResults').addClass('minimizeResults');
|
||||||
|
} else {
|
||||||
|
s.css({
|
||||||
|
'height': '0',
|
||||||
|
'overflow': 'hidden'
|
||||||
|
});
|
||||||
|
$(this).removeClass('minimizeResults').addClass('maximizeResults');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.limitToMe').unbind().bind("change", function (e) {
|
||||||
|
// set the value of the search equal to itself to retrigger the autocomplete event
|
||||||
|
self.isOpen = false;
|
||||||
|
$('.sidebarSearchField').typeahead('setQuery', $('.sidebarSearchField').val());
|
||||||
|
setTimeout(function () {
|
||||||
|
self.isOpen = true;
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
|
||||||
|
// when the user clicks minimize section, hide the results for that section
|
||||||
|
$('.minimizeMapperResults').unbind().click(function (e) {
|
||||||
|
toggleResultSet.call(this, 'mappers');
|
||||||
|
});
|
||||||
|
$('.minimizeTopicResults').unbind().click(function (e) {
|
||||||
|
toggleResultSet.call(this, 'topics');
|
||||||
|
});
|
||||||
|
$('.minimizeMapResults').unbind().click(function (e) {
|
||||||
|
toggleResultSet.call(this, 'maps');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
hideLoader: function () {
|
||||||
|
$('#searchLoading').hide();
|
||||||
|
},
|
||||||
|
showLoader: function () {
|
||||||
|
$('#searchLoading').show();
|
||||||
|
}
|
||||||
|
};
|
1950
app/assets/javascripts/src/Metamaps.JIT.js
Normal file
262
app/assets/javascripts/src/Metamaps.Router.js
Normal file
|
@ -0,0 +1,262 @@
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
Metamaps.currentPage = "";
|
||||||
|
|
||||||
|
var Router = Backbone.Router.extend({
|
||||||
|
routes: {
|
||||||
|
"": "home", // #home
|
||||||
|
"explore/:section": "explore", // #explore/active
|
||||||
|
"explore/:section/:id": "explore", // #explore/mapper/1234
|
||||||
|
"maps/:id": "maps" // #maps/7
|
||||||
|
},
|
||||||
|
home: function () {
|
||||||
|
clearTimeout(Metamaps.routerTimeoutId);
|
||||||
|
|
||||||
|
if (Metamaps.Active.Mapper) document.title = 'Explore Active Maps | Metamaps';
|
||||||
|
else document.title = 'Home | Metamaps';
|
||||||
|
|
||||||
|
Metamaps.currentSection = "";
|
||||||
|
Metamaps.currentPage = "";
|
||||||
|
$('.wrapper').removeClass('mapPage topicPage');
|
||||||
|
|
||||||
|
var classes = Metamaps.Active.Mapper ? "homePage explorePage" : "homePage";
|
||||||
|
$('.wrapper').addClass(classes);
|
||||||
|
|
||||||
|
var navigate = function() {
|
||||||
|
Metamaps.routerTimeoutId = setTimeout(function() {
|
||||||
|
Metamaps.Router.navigate("");
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
// all this only for the logged in home page
|
||||||
|
if (Metamaps.Active.Mapper) {
|
||||||
|
|
||||||
|
Metamaps.Famous.yield.hide();
|
||||||
|
|
||||||
|
Metamaps.Famous.explore.set('active');
|
||||||
|
Metamaps.Famous.maps.resetScroll(); // sets the scroll back to the top
|
||||||
|
Metamaps.Famous.explore.show();
|
||||||
|
|
||||||
|
Metamaps.Famous.maps.show();
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.Search.open();
|
||||||
|
Metamaps.GlobalUI.Search.lock();
|
||||||
|
|
||||||
|
Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps.Active );
|
||||||
|
if (Metamaps.Maps.Active.length === 0) {
|
||||||
|
Metamaps.Maps.Active.getMaps(navigate); // this will trigger an explore maps render
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Metamaps.Views.exploreMaps.render(navigate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// logged out home page
|
||||||
|
else {
|
||||||
|
|
||||||
|
Metamaps.Famous.yield.show();
|
||||||
|
|
||||||
|
Metamaps.Famous.explore.hide();
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.Search.unlock();
|
||||||
|
Metamaps.GlobalUI.Search.close(0, true);
|
||||||
|
|
||||||
|
Metamaps.Famous.maps.hide();
|
||||||
|
Metamaps.routerTimeoutId = setTimeout(navigate, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
Metamaps.Famous.viz.hide();
|
||||||
|
Metamaps.Map.end();
|
||||||
|
Metamaps.Topic.end();
|
||||||
|
Metamaps.Active.Map = null;
|
||||||
|
Metamaps.Active.Topic = null;
|
||||||
|
},
|
||||||
|
explore: function (section, id) {
|
||||||
|
clearTimeout(Metamaps.routerTimeoutId);
|
||||||
|
|
||||||
|
// just capitalize the variable section
|
||||||
|
// either 'featured', 'mapper', or 'active'
|
||||||
|
var capitalize = section.charAt(0).toUpperCase() + section.slice(1);
|
||||||
|
|
||||||
|
if (section === "featured" || section === "active") {
|
||||||
|
document.title = 'Explore ' + capitalize + ' Maps | Metamaps';
|
||||||
|
}
|
||||||
|
else if (section === "mapper") {
|
||||||
|
$.ajax({
|
||||||
|
url: "/users/" + id + ".json",
|
||||||
|
success: function (response) {
|
||||||
|
document.title = response.name + ' | Metamaps';
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (section === "mine") {
|
||||||
|
document.title = 'Explore My Maps | Metamaps';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.wrapper').removeClass('homePage mapPage topicPage');
|
||||||
|
$('.wrapper').addClass('explorePage');
|
||||||
|
|
||||||
|
Metamaps.currentSection = "explore";
|
||||||
|
Metamaps.currentPage = section;
|
||||||
|
|
||||||
|
// this will mean it's a mapper page being loaded
|
||||||
|
if (id) {
|
||||||
|
if (Metamaps.Maps.Mapper.mapperId !== id) {
|
||||||
|
// empty the collection if we are trying to load the maps
|
||||||
|
// collection of a different mapper than we had previously
|
||||||
|
Metamaps.Maps.Mapper.reset();
|
||||||
|
Metamaps.Maps.Mapper.page = 1;
|
||||||
|
}
|
||||||
|
Metamaps.Maps.Mapper.mapperId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] );
|
||||||
|
|
||||||
|
var navigate = function(){
|
||||||
|
var path = "/explore/" + Metamaps.currentPage;
|
||||||
|
|
||||||
|
// alter url if for mapper profile page
|
||||||
|
if (Metamaps.currentPage == "mapper") {
|
||||||
|
path += "/" + Metamaps.Maps.Mapper.mapperId;
|
||||||
|
}
|
||||||
|
|
||||||
|
Metamaps.Router.navigate(path);
|
||||||
|
};
|
||||||
|
var navigateTimeout = function() {
|
||||||
|
Metamaps.routerTimeoutId = setTimeout(navigate, 300);
|
||||||
|
};
|
||||||
|
if (Metamaps.Maps[capitalize].length === 0) {
|
||||||
|
Metamaps.Loading.show();
|
||||||
|
setTimeout(function(){
|
||||||
|
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
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (id) {
|
||||||
|
Metamaps.Views.exploreMaps.fetchUserThenRender(navigateTimeout);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Metamaps.Views.exploreMaps.render(navigateTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.Search.open();
|
||||||
|
Metamaps.GlobalUI.Search.lock();
|
||||||
|
|
||||||
|
Metamaps.Famous.yield.hide();
|
||||||
|
|
||||||
|
Metamaps.Famous.maps.resetScroll(); // sets the scroll back to the top
|
||||||
|
Metamaps.Famous.maps.show();
|
||||||
|
Metamaps.Famous.explore.set(section, id);
|
||||||
|
Metamaps.Famous.explore.show();
|
||||||
|
|
||||||
|
Metamaps.Famous.viz.hide();
|
||||||
|
Metamaps.Map.end();
|
||||||
|
Metamaps.Topic.end();
|
||||||
|
Metamaps.Active.Map = null;
|
||||||
|
Metamaps.Active.Topic = null;
|
||||||
|
},
|
||||||
|
maps: function (id) {
|
||||||
|
clearTimeout(Metamaps.routerTimeoutId);
|
||||||
|
|
||||||
|
document.title = 'Map ' + id + ' | Metamaps';
|
||||||
|
|
||||||
|
Metamaps.currentSection = "map";
|
||||||
|
Metamaps.currentPage = id;
|
||||||
|
|
||||||
|
$('.wrapper').removeClass('homePage explorePage topicPage');
|
||||||
|
$('.wrapper').addClass('mapPage');
|
||||||
|
// another class will be added to wrapper if you
|
||||||
|
// can edit this map '.canEditMap'
|
||||||
|
|
||||||
|
Metamaps.Famous.yield.hide();
|
||||||
|
Metamaps.Famous.maps.hide();
|
||||||
|
Metamaps.Famous.explore.hide();
|
||||||
|
|
||||||
|
// clear the visualization, if there was one, before showing its div again
|
||||||
|
if (Metamaps.Visualize.mGraph) {
|
||||||
|
Metamaps.Visualize.mGraph.graph.empty();
|
||||||
|
Metamaps.Visualize.mGraph.plot();
|
||||||
|
Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas);
|
||||||
|
}
|
||||||
|
Metamaps.Famous.viz.show();
|
||||||
|
Metamaps.Topic.end();
|
||||||
|
Metamaps.Active.Topic = null;
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.Search.unlock();
|
||||||
|
Metamaps.GlobalUI.Search.close(0, true);
|
||||||
|
|
||||||
|
Metamaps.Loading.show();
|
||||||
|
Metamaps.Map.end();
|
||||||
|
Metamaps.Map.launch(id);
|
||||||
|
},
|
||||||
|
topics: function (id) {
|
||||||
|
clearTimeout(Metamaps.routerTimeoutId);
|
||||||
|
|
||||||
|
document.title = 'Topic ' + id + ' | Metamaps';
|
||||||
|
|
||||||
|
Metamaps.currentSection = "topic";
|
||||||
|
Metamaps.currentPage = id;
|
||||||
|
|
||||||
|
$('.wrapper').removeClass('homePage explorePage mapPage');
|
||||||
|
$('.wrapper').addClass('topicPage');
|
||||||
|
|
||||||
|
Metamaps.Famous.yield.hide();
|
||||||
|
Metamaps.Famous.maps.hide();
|
||||||
|
Metamaps.Famous.explore.hide();
|
||||||
|
|
||||||
|
// clear the visualization, if there was one, before showing its div again
|
||||||
|
if (Metamaps.Visualize.mGraph) {
|
||||||
|
Metamaps.Visualize.mGraph.graph.empty();
|
||||||
|
Metamaps.Visualize.mGraph.plot();
|
||||||
|
Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas);
|
||||||
|
}
|
||||||
|
Metamaps.Famous.viz.show();
|
||||||
|
Metamaps.Map.end();
|
||||||
|
Metamaps.Active.Map = null;
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.Search.unlock();
|
||||||
|
Metamaps.GlobalUI.Search.close(0, true);
|
||||||
|
|
||||||
|
Metamaps.Topic.end();
|
||||||
|
Metamaps.Topic.launch(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Metamaps.Router = new Router();
|
||||||
|
|
||||||
|
|
||||||
|
Metamaps.Router.intercept = function (evt) {
|
||||||
|
var segments;
|
||||||
|
|
||||||
|
var href = {
|
||||||
|
prop: $(this).prop("href"),
|
||||||
|
attr: $(this).attr("href")
|
||||||
|
};
|
||||||
|
var root = location.protocol + "//" + location.host + Backbone.history.options.root;
|
||||||
|
|
||||||
|
if (href.prop && href.prop === root) href.attr = "";
|
||||||
|
|
||||||
|
if (href.prop && href.prop.slice(0, root.length) === root) {
|
||||||
|
evt.preventDefault();
|
||||||
|
|
||||||
|
segments = href.attr.split('/');
|
||||||
|
segments.splice(0,1); // pop off the element created by the first /
|
||||||
|
|
||||||
|
if (href.attr === "") Metamaps.Router.home();
|
||||||
|
else {
|
||||||
|
Metamaps.Router[segments[0]](segments[1], segments[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Metamaps.Router.init = function () {
|
||||||
|
Backbone.history.start({
|
||||||
|
silent: true,
|
||||||
|
pushState: true,
|
||||||
|
root: '/'
|
||||||
|
});
|
||||||
|
$(document).on("click", "a:not([data-bypass])", Metamaps.Router.intercept);
|
||||||
|
};
|
||||||
|
})();
|
133
app/assets/javascripts/src/Metamaps.Views.js
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
(function () {
|
||||||
|
Metamaps.Views = {};
|
||||||
|
|
||||||
|
var initialized = false;
|
||||||
|
|
||||||
|
Metamaps.Views.init = function () {
|
||||||
|
|
||||||
|
Metamaps.Views.MapperCard = Backbone.View.extend({
|
||||||
|
|
||||||
|
template: Hogan.compile( $('#mapperCardTemplate').html() ),
|
||||||
|
|
||||||
|
tagNamea: "div",
|
||||||
|
|
||||||
|
className: "mapper",
|
||||||
|
|
||||||
|
render: function () {
|
||||||
|
this.$el.html( this.template.render(this.model) );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Metamaps.Views.MapCard = Backbone.View.extend({
|
||||||
|
|
||||||
|
template: Hogan.compile( $('#mapCardTemplate').html() ),
|
||||||
|
|
||||||
|
tagName: "div",
|
||||||
|
|
||||||
|
className: "map",
|
||||||
|
|
||||||
|
id: function() {
|
||||||
|
return this.model.id;
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.listenTo(this.model, "change", this.render);
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function () {
|
||||||
|
this.$el.html( this.template.render(this.model.attrForCards()) );
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var mapsWrapper = Backbone.View.extend({
|
||||||
|
|
||||||
|
initialize: function (opts) {
|
||||||
|
|
||||||
|
},
|
||||||
|
setCollection: function (collection) {
|
||||||
|
if (this.collection) this.stopListening(this.collection);
|
||||||
|
this.collection = collection;
|
||||||
|
this.listenTo(this.collection, 'add', this.render);
|
||||||
|
this.listenTo(this.collection, 'successOnFetch', this.handleSuccess);
|
||||||
|
this.listenTo(this.collection, 'errorOnFetch', this.handleError);
|
||||||
|
},
|
||||||
|
render: function (mapperObj, cb) {
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
if (typeof mapperObj === "function") {
|
||||||
|
var cb = mapperObj;
|
||||||
|
mapperObj = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.el.innerHTML = "";
|
||||||
|
|
||||||
|
// in case it is a page where we have to display the mapper card
|
||||||
|
if (mapperObj) {
|
||||||
|
var view = new Metamaps.Views.MapperCard({ model: mapperObj });
|
||||||
|
|
||||||
|
that.el.appendChild( view.render().el );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.collection.each(function (map) {
|
||||||
|
var view = new Metamaps.Views.MapCard({ model: map });
|
||||||
|
|
||||||
|
that.el.appendChild( view.render().el );
|
||||||
|
});
|
||||||
|
this.$el.append('<div class="clearfloat"></div>');
|
||||||
|
var m = Metamaps.Famous.maps.surf;
|
||||||
|
m.setContent(this.el);
|
||||||
|
|
||||||
|
var updateHeight = function(){
|
||||||
|
var height = $(that.el).height() + 32 + 56;
|
||||||
|
m.setSize([undefined, height]);
|
||||||
|
Metamaps.Famous.maps.lock = false;
|
||||||
|
if (cb) cb();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
m.deploy(m._currTarget);
|
||||||
|
initialized = true;
|
||||||
|
setTimeout(updateHeight, 100);
|
||||||
|
} else {
|
||||||
|
setTimeout(updateHeight, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
Metamaps.Loading.hide();
|
||||||
|
},
|
||||||
|
handleSuccess: function (cb) {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
if (this.collection && this.collection.id === "mapper") {
|
||||||
|
this.fetchUserThenRender(cb);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.render(cb);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleError: function () {
|
||||||
|
console.log('error loading maps!'); //TODO
|
||||||
|
},
|
||||||
|
fetchUserThenRender: function (cb) {
|
||||||
|
var that = this;
|
||||||
|
// first load the mapper object and then call the render function
|
||||||
|
$.ajax({
|
||||||
|
url: "/users/" + this.collection.mapperId + "/details.json",
|
||||||
|
success: function (response) {
|
||||||
|
that.render(response, cb);
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
that.render(cb);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Metamaps.Views.exploreMaps = new mapsWrapper();
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
5132
app/assets/javascripts/src/Metamaps.js
Normal file
|
@ -1,12 +0,0 @@
|
||||||
/*
|
|
||||||
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
||||||
* listed below.
|
|
||||||
*
|
|
||||||
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
||||||
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
|
||||||
*
|
|
||||||
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
|
||||||
* compiled file, but it's generally better to create a new file per style scope.
|
|
||||||
*
|
|
||||||
*= require ./special
|
|
||||||
*/
|
|
|
@ -1,109 +0,0 @@
|
||||||
#metacodeSelector {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.metacodeSelect {
|
|
||||||
border-top: 1px solid #DDD;
|
|
||||||
padding: 0;
|
|
||||||
background: #FFF;
|
|
||||||
|
|
||||||
.metacodeFilterInput {
|
|
||||||
width: 100px;
|
|
||||||
outline: none;
|
|
||||||
border: 0;
|
|
||||||
padding: 8px;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 14px;
|
|
||||||
color: #424242;
|
|
||||||
font-family: 'din-medium', helvetica, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metacodeList {
|
|
||||||
list-style: none;
|
|
||||||
background: #FFF;
|
|
||||||
|
|
||||||
li {
|
|
||||||
padding: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover, &.keySelect {
|
|
||||||
background: #4CAF50;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
padding-right: 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.selectedMetacode {
|
|
||||||
float: left;
|
|
||||||
background: #FFF;
|
|
||||||
border-top-left-radius: 2px;
|
|
||||||
border-bottom-left-radius: 2px;
|
|
||||||
padding: 5px 10px 5px 6px;
|
|
||||||
vertical-align: top;
|
|
||||||
border-right: 1px solid #DDD;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.selectedMetacode:hover, .selectedMetacode.isBeingSelected {
|
|
||||||
background: #EDEDED;
|
|
||||||
}
|
|
||||||
.selectedMetacode img {
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.selectedMetacode span {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.selectedMetacode .downArrow {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 8px 6px 0 6px;
|
|
||||||
border-color: #777 transparent transparent transparent;
|
|
||||||
margin-left: 2px;
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
.new_topic {
|
|
||||||
margin: 0;
|
|
||||||
margin-top: -17px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
#new_topic .twitter-typeahead {
|
|
||||||
position: relative !important;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
.new_topic #topic_name,
|
|
||||||
.new_topic .tt-hint {
|
|
||||||
border-radius: none;
|
|
||||||
border-top-right-radius: 2px;
|
|
||||||
border-bottom-right-radius: 2px;
|
|
||||||
}
|
|
||||||
.openMetacodeSwitcher {
|
|
||||||
top: -16px;
|
|
||||||
left: -16px;
|
|
||||||
}
|
|
||||||
#metacodeImg {
|
|
||||||
height: 120px;
|
|
||||||
width: 380px;
|
|
||||||
display: none;
|
|
||||||
position: absolute !important;
|
|
||||||
top: -30px;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
#metacodeImgTitle {
|
|
||||||
display: none;
|
|
||||||
float: left;
|
|
||||||
width: 120px;
|
|
||||||
text-align: center;
|
|
||||||
margin-left: 110px;
|
|
||||||
}
|
|
63
app/assets/stylesheets/admin.css
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
|
@ -1,187 +0,0 @@
|
||||||
.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.6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.centerContent {
|
|
||||||
width: 760px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 80px 0 60px 20px;
|
|
||||||
background: rgba(125, 125, 125, 0.4);
|
|
||||||
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(125, 125, 125, 0.2);
|
|
||||||
}
|
|
||||||
tr:nth-child(even) {
|
|
||||||
background: rgba(125, 125, 125, 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;
|
|
||||||
}
|
|
||||||
}
|
|