Merge branch 'new_design'
This commit is contained in:
commit
650e1951a8
|
@ -13,3 +13,5 @@
|
|||
/config/mongoid.yml
|
||||
/public/assets/*
|
||||
*.old
|
||||
*.bak
|
||||
.byebug_history
|
||||
|
|
36
Gemfile
36
Gemfile
|
@ -1,55 +1,65 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '4.2.5.2'
|
||||
gem 'sass-rails'
|
||||
ruby '2.2.3'
|
||||
|
||||
gem 'rails', '>= 5.0.0.beta3', '< 5.1'
|
||||
gem 'sass-rails', '~> 5.0'
|
||||
gem 'coffee-rails', '~> 4.1.0'
|
||||
gem 'uglifier', '>= 2.7.2'
|
||||
|
||||
gem 'jquery-rails'
|
||||
gem 'foundation-rails', '~> 5.5.1'
|
||||
gem 'foundation-rails', '~> 6.2.1'
|
||||
gem 'foundation-icons-sass-rails'
|
||||
gem 'font-awesome-sass'
|
||||
gem 'carrierwave'
|
||||
gem 'kaminari', git: 'git@github.com:amatsuda/kaminari.git'
|
||||
gem 'turbolinks', '~> 5.x'
|
||||
gem 'js_cookie_rails'
|
||||
|
||||
gem 'rails-i18n', '~> 5.0.0.beta3'
|
||||
|
||||
gem 'jbuilder'
|
||||
gem 'pg'
|
||||
|
||||
gem 'mongoid'
|
||||
gem 'mongoid-tree'
|
||||
gem 'mongoid-pagination'
|
||||
gem 'redcarpet'
|
||||
gem 'rouge'
|
||||
gem 'slim-rails'
|
||||
gem 'simple_form'
|
||||
gem 'mini_magick'
|
||||
gem 'carrierwave-mongoid'
|
||||
gem 'html_truncator'
|
||||
gem 'nokogiri'
|
||||
gem 'angularjs-rails'
|
||||
gem 'figaro'
|
||||
gem 'rqrcode-with-patches', require: 'rqrcode'
|
||||
gem 'chunky_png'
|
||||
gem 'sidekiq'
|
||||
gem 'redis-namespace'
|
||||
gem 'rest-client'
|
||||
gem 'unicorn'
|
||||
gem 'newrelic_rpm'
|
||||
|
||||
gem 'puma'
|
||||
|
||||
gem 'mina', require: false
|
||||
gem 'mina-multistage', require: false
|
||||
gem 'mina-sidekiq', require: false
|
||||
gem 'mina-unicorn', require: false
|
||||
gem 'mina-puma', require: false
|
||||
|
||||
group :development do
|
||||
gem 'spring'
|
||||
gem 'quiet_assets'
|
||||
gem 'guard'
|
||||
gem 'guard-rails'
|
||||
gem 'guard-rspec', require: false
|
||||
gem 'guard-bundler', require: false
|
||||
gem 'listen', '~> 3.0.5'
|
||||
gem 'spring'
|
||||
gem 'spring-watcher-listen', '~> 2.0.0'
|
||||
|
||||
gem 'byebug'
|
||||
|
||||
gem 'rack-cors', :require => 'rack/cors'
|
||||
end
|
||||
|
||||
group :test do
|
||||
gem 'capybara'
|
||||
gem 'mongoid-rspec', :require => false
|
||||
gem 'database_cleaner'
|
||||
gem 'rspec-sidekiq'
|
||||
gem "codeclimate-test-reporter", group: :test, require: nil
|
||||
|
@ -59,5 +69,5 @@ group :test, :development do
|
|||
gem "rspec-rails", ">= 2.8.1"
|
||||
gem 'pry-rails'
|
||||
gem 'pry-nav'
|
||||
gem 'factory_girl_rails'
|
||||
#gem 'factory_girl_rails'
|
||||
end
|
||||
|
|
262
Gemfile.lock
262
Gemfile.lock
|
@ -1,62 +1,71 @@
|
|||
GIT
|
||||
remote: git@github.com:amatsuda/kaminari.git
|
||||
revision: 0e21d52feca1f79a9aca83613cf053eb5273827e
|
||||
specs:
|
||||
kaminari (1.0.0.alpha)
|
||||
actionpack (>= 3.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (4.2.5.2)
|
||||
actionpack (= 4.2.5.2)
|
||||
actionview (= 4.2.5.2)
|
||||
activejob (= 4.2.5.2)
|
||||
actioncable (5.0.0.beta3)
|
||||
actionpack (= 5.0.0.beta3)
|
||||
nio4r (~> 1.2)
|
||||
websocket-driver (~> 0.6.1)
|
||||
actionmailer (5.0.0.beta3)
|
||||
actionpack (= 5.0.0.beta3)
|
||||
actionview (= 5.0.0.beta3)
|
||||
activejob (= 5.0.0.beta3)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
actionpack (4.2.5.2)
|
||||
actionview (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
rack (~> 1.6)
|
||||
rack-test (~> 0.6.2)
|
||||
actionpack (5.0.0.beta3)
|
||||
actionview (= 5.0.0.beta3)
|
||||
activesupport (= 5.0.0.beta3)
|
||||
rack (~> 2.x)
|
||||
rack-test (~> 0.6.3)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
actionview (5.0.0.beta3)
|
||||
activesupport (= 5.0.0.beta3)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
activejob (4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
globalid (>= 0.3.0)
|
||||
activemodel (4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.5.2)
|
||||
activemodel (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
arel (~> 6.0)
|
||||
activesupport (4.2.5.2)
|
||||
activejob (5.0.0.beta3)
|
||||
activesupport (= 5.0.0.beta3)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (5.0.0.beta3)
|
||||
activesupport (= 5.0.0.beta3)
|
||||
activerecord (5.0.0.beta3)
|
||||
activemodel (= 5.0.0.beta3)
|
||||
activesupport (= 5.0.0.beta3)
|
||||
arel (~> 7.0)
|
||||
activesupport (5.0.0.beta3)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.4.0)
|
||||
angularjs-rails (1.5.0)
|
||||
arel (6.0.3)
|
||||
bson (4.0.4)
|
||||
arel (7.0.0)
|
||||
babel-source (5.8.35)
|
||||
babel-transpiler (0.7.0)
|
||||
babel-source (>= 4.0, < 6)
|
||||
execjs (~> 2.0)
|
||||
builder (3.2.2)
|
||||
capybara (2.6.2)
|
||||
byebug (8.2.4)
|
||||
capybara (2.7.0)
|
||||
addressable
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-test (>= 0.5.4)
|
||||
xpath (~> 2.0)
|
||||
carrierwave (0.10.0)
|
||||
carrierwave (0.11.0)
|
||||
activemodel (>= 3.2.0)
|
||||
activesupport (>= 3.2.0)
|
||||
json (>= 1.7)
|
||||
mime-types (>= 1.16)
|
||||
carrierwave-mongoid (0.8.1)
|
||||
carrierwave (>= 0.8.0, < 0.11.0)
|
||||
mongoid (>= 3.0, < 6.0)
|
||||
mongoid-grid_fs (>= 1.3, < 3.0)
|
||||
chunky_png (1.3.5)
|
||||
codeclimate-test-reporter (0.5.0)
|
||||
simplecov (>= 0.7.1, < 1.0.0)
|
||||
|
@ -70,18 +79,13 @@ GEM
|
|||
coffee-script-source (1.10.0)
|
||||
concurrent-ruby (1.0.1)
|
||||
connection_pool (2.2.0)
|
||||
database_cleaner (1.5.1)
|
||||
database_cleaner (1.5.2)
|
||||
diff-lcs (1.2.5)
|
||||
docile (1.1.5)
|
||||
domain_name (0.5.20160309)
|
||||
domain_name (0.5.20160310)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
erubis (2.7.0)
|
||||
execjs (2.6.0)
|
||||
factory_girl (4.5.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_girl_rails (4.6.0)
|
||||
factory_girl (~> 4.5.0)
|
||||
railties (>= 3.0.0)
|
||||
ffi (1.9.10)
|
||||
figaro (1.1.1)
|
||||
thor (~> 0.14)
|
||||
|
@ -91,9 +95,10 @@ GEM
|
|||
foundation-icons-sass-rails (3.0.0)
|
||||
railties (>= 3.1.1)
|
||||
sass-rails (>= 3.1.1)
|
||||
foundation-rails (5.5.3.2)
|
||||
foundation-rails (6.2.1.0)
|
||||
railties (>= 3.1.0)
|
||||
sass (>= 3.3.0, < 3.5)
|
||||
sprockets-es6 (>= 0.9.0)
|
||||
globalid (0.3.6)
|
||||
activesupport (>= 4.1.0)
|
||||
guard (2.13.0)
|
||||
|
@ -113,7 +118,7 @@ GEM
|
|||
guard-rails (0.7.2)
|
||||
guard (~> 2.11)
|
||||
guard-compat (~> 1.0)
|
||||
guard-rspec (4.6.4)
|
||||
guard-rspec (4.6.5)
|
||||
guard (~> 2.1)
|
||||
guard-compat (~> 1.1)
|
||||
rspec (>= 2.99.0, < 4.0)
|
||||
|
@ -129,16 +134,17 @@ GEM
|
|||
rails-dom-testing (>= 1, < 3)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
js_cookie_rails (1.0.1)
|
||||
railties (>= 3.1)
|
||||
json (1.8.3)
|
||||
kgio (2.10.0)
|
||||
listen (3.0.6)
|
||||
rb-fsevent (>= 0.9.3)
|
||||
rb-inotify (>= 0.9.7)
|
||||
loofah (2.0.3)
|
||||
nokogiri (>= 1.5.9)
|
||||
lumberjack (1.0.10)
|
||||
mail (2.6.3)
|
||||
mime-types (>= 1.16, < 3)
|
||||
mail (2.6.4)
|
||||
mime-types (>= 1.16, < 4)
|
||||
method_source (0.8.2)
|
||||
mime-types (2.99.1)
|
||||
mina (0.3.8)
|
||||
|
@ -146,42 +152,26 @@ GEM
|
|||
rake
|
||||
mina-multistage (1.0.2)
|
||||
mina (>= 0.2.1)
|
||||
mina-puma (0.3.0)
|
||||
mina
|
||||
puma (>= 2.13)
|
||||
mina-sidekiq (0.3.1)
|
||||
mina
|
||||
mina-unicorn (0.4.0)
|
||||
mini_magick (4.4.0)
|
||||
mini_magick (4.5.1)
|
||||
mini_portile2 (2.0.0)
|
||||
minitest (5.8.4)
|
||||
mongo (2.2.4)
|
||||
bson (~> 4.0)
|
||||
mongoid (5.1.1)
|
||||
activemodel (~> 4.0)
|
||||
mongo (~> 2.1)
|
||||
origin (~> 2.2)
|
||||
tzinfo (>= 0.3.37)
|
||||
mongoid-grid_fs (2.2.1)
|
||||
mime-types (>= 1.0, < 3.0)
|
||||
mongoid (>= 3.0, < 6.0)
|
||||
mongoid-pagination (0.2.0)
|
||||
activesupport
|
||||
mongoid
|
||||
mongoid-rspec (3.0.0)
|
||||
mongoid (~> 5.0)
|
||||
rake
|
||||
rspec (~> 3.3)
|
||||
mongoid-tree (2.0.1)
|
||||
mongoid (>= 4.0, < 6.0)
|
||||
multi_json (1.11.2)
|
||||
nenv (0.3.0)
|
||||
netrc (0.11.0)
|
||||
newrelic_rpm (3.15.0.314)
|
||||
newrelic_rpm (3.15.1.316)
|
||||
nio4r (1.2.1)
|
||||
nokogiri (1.6.7.2)
|
||||
mini_portile2 (~> 2.0.0.rc2)
|
||||
notiffany (0.0.8)
|
||||
nenv (~> 0.1)
|
||||
shellany (~> 0.0)
|
||||
open4 (1.3.4)
|
||||
origin (2.2.0)
|
||||
pg (0.18.4)
|
||||
pry (0.10.3)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.8.1)
|
||||
|
@ -190,23 +180,26 @@ GEM
|
|||
pry (>= 0.9.10, < 0.11.0)
|
||||
pry-rails (0.3.4)
|
||||
pry (>= 0.9.10)
|
||||
puma (3.4.0)
|
||||
quiet_assets (1.1.0)
|
||||
railties (>= 3.1, < 5.0)
|
||||
rack (1.6.4)
|
||||
rack (2.0.0.alpha)
|
||||
json
|
||||
rack-cors (0.4.0)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (4.2.5.2)
|
||||
actionmailer (= 4.2.5.2)
|
||||
actionpack (= 4.2.5.2)
|
||||
actionview (= 4.2.5.2)
|
||||
activejob (= 4.2.5.2)
|
||||
activemodel (= 4.2.5.2)
|
||||
activerecord (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
rails (5.0.0.beta3)
|
||||
actioncable (= 5.0.0.beta3)
|
||||
actionmailer (= 5.0.0.beta3)
|
||||
actionpack (= 5.0.0.beta3)
|
||||
actionview (= 5.0.0.beta3)
|
||||
activejob (= 5.0.0.beta3)
|
||||
activemodel (= 5.0.0.beta3)
|
||||
activerecord (= 5.0.0.beta3)
|
||||
activesupport (= 5.0.0.beta3)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.2.5.2)
|
||||
sprockets-rails
|
||||
railties (= 5.0.0.beta3)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
rails-dom-testing (1.0.7)
|
||||
|
@ -215,18 +208,21 @@ GEM
|
|||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
railties (4.2.5.2)
|
||||
actionpack (= 4.2.5.2)
|
||||
activesupport (= 4.2.5.2)
|
||||
rails-i18n (5.0.0.beta3)
|
||||
i18n (~> 0.7)
|
||||
railties (~> 5.0.0.beta1)
|
||||
railties (5.0.0.beta3)
|
||||
actionpack (= 5.0.0.beta3)
|
||||
activesupport (= 5.0.0.beta3)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
raindrops (0.16.0)
|
||||
rake (11.1.1)
|
||||
rake (11.1.2)
|
||||
rb-fsevent (0.9.7)
|
||||
rb-inotify (0.9.7)
|
||||
ffi (>= 0.5.0)
|
||||
redcarpet (3.3.4)
|
||||
redis (3.2.2)
|
||||
redis (3.3.0)
|
||||
redis-namespace (1.5.2)
|
||||
redis (~> 3.0, >= 3.0.4)
|
||||
rest-client (1.8.0)
|
||||
|
@ -236,31 +232,30 @@ GEM
|
|||
rouge (1.10.1)
|
||||
rqrcode-with-patches (0.6.0)
|
||||
chunky_png
|
||||
rspec (3.4.0)
|
||||
rspec-core (~> 3.4.0)
|
||||
rspec-expectations (~> 3.4.0)
|
||||
rspec-mocks (~> 3.4.0)
|
||||
rspec-core (3.4.4)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-expectations (3.4.0)
|
||||
rspec (3.1.0)
|
||||
rspec-core (~> 3.1.0)
|
||||
rspec-expectations (~> 3.1.0)
|
||||
rspec-mocks (~> 3.1.0)
|
||||
rspec-core (3.1.7)
|
||||
rspec-support (~> 3.1.0)
|
||||
rspec-expectations (3.1.2)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-mocks (3.4.1)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-rails (3.4.2)
|
||||
actionpack (>= 3.0, < 4.3)
|
||||
activesupport (>= 3.0, < 4.3)
|
||||
railties (>= 3.0, < 4.3)
|
||||
rspec-core (~> 3.4.0)
|
||||
rspec-expectations (~> 3.4.0)
|
||||
rspec-mocks (~> 3.4.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-support (~> 3.1.0)
|
||||
rspec-mocks (3.1.3)
|
||||
rspec-support (~> 3.1.0)
|
||||
rspec-rails (3.1.0)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.1.0)
|
||||
rspec-expectations (~> 3.1.0)
|
||||
rspec-mocks (~> 3.1.0)
|
||||
rspec-support (~> 3.1.0)
|
||||
rspec-sidekiq (2.2.0)
|
||||
rspec (~> 3.0, >= 3.0.0)
|
||||
sidekiq (>= 2.4.0)
|
||||
rspec-support (3.4.1)
|
||||
sass (3.4.21)
|
||||
rspec-support (3.1.2)
|
||||
sass (3.4.22)
|
||||
sass-rails (5.0.4)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
sass (~> 3.1)
|
||||
|
@ -290,10 +285,17 @@ GEM
|
|||
railties (>= 3.1, < 5.0)
|
||||
slim (~> 3.0)
|
||||
slop (3.6.0)
|
||||
spring (1.6.4)
|
||||
sprockets (3.5.2)
|
||||
spring (1.7.1)
|
||||
spring-watcher-listen (2.0.0)
|
||||
listen (>= 2.7, < 4.0)
|
||||
spring (~> 1.2)
|
||||
sprockets (3.6.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-es6 (0.9.0)
|
||||
babel-source (>= 5.8.11)
|
||||
babel-transpiler
|
||||
sprockets (>= 3.0.0)
|
||||
sprockets-rails (3.0.4)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
|
@ -302,18 +304,19 @@ GEM
|
|||
thor (0.19.1)
|
||||
thread_safe (0.3.5)
|
||||
tilt (2.0.2)
|
||||
turbolinks (5.0.0.beta2)
|
||||
turbolinks-source
|
||||
turbolinks-source (5.0.0.beta4)
|
||||
tzinfo (1.2.2)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (2.7.2)
|
||||
execjs (>= 0.3.0)
|
||||
json (>= 1.8.0)
|
||||
uglifier (3.0.0)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.2)
|
||||
unicorn (5.0.1)
|
||||
kgio (~> 2.6)
|
||||
rack
|
||||
raindrops (~> 0.7)
|
||||
websocket-driver (0.6.3)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.2)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
|
||||
|
@ -321,18 +324,17 @@ PLATFORMS
|
|||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
angularjs-rails
|
||||
byebug
|
||||
capybara
|
||||
carrierwave-mongoid
|
||||
carrierwave
|
||||
chunky_png
|
||||
codeclimate-test-reporter
|
||||
coffee-rails (~> 4.1.0)
|
||||
database_cleaner
|
||||
factory_girl_rails
|
||||
figaro
|
||||
font-awesome-sass
|
||||
foundation-icons-sass-rails
|
||||
foundation-rails (~> 5.5.1)
|
||||
foundation-rails (~> 6.2.1)
|
||||
guard
|
||||
guard-bundler
|
||||
guard-rails
|
||||
|
@ -340,22 +342,24 @@ DEPENDENCIES
|
|||
html_truncator
|
||||
jbuilder
|
||||
jquery-rails
|
||||
js_cookie_rails
|
||||
kaminari!
|
||||
listen (~> 3.0.5)
|
||||
mina
|
||||
mina-multistage
|
||||
mina-puma
|
||||
mina-sidekiq
|
||||
mina-unicorn
|
||||
mini_magick
|
||||
mongoid
|
||||
mongoid-pagination
|
||||
mongoid-rspec
|
||||
mongoid-tree
|
||||
newrelic_rpm
|
||||
nokogiri
|
||||
pg
|
||||
pry-nav
|
||||
pry-rails
|
||||
puma
|
||||
quiet_assets
|
||||
rack-cors
|
||||
rails (= 4.2.5.2)
|
||||
rails (>= 5.0.0.beta3, < 5.1)
|
||||
rails-i18n (~> 5.0.0.beta3)
|
||||
redcarpet
|
||||
redis-namespace
|
||||
rest-client
|
||||
|
@ -363,10 +367,14 @@ DEPENDENCIES
|
|||
rqrcode-with-patches
|
||||
rspec-rails (>= 2.8.1)
|
||||
rspec-sidekiq
|
||||
sass-rails
|
||||
sass-rails (~> 5.0)
|
||||
sidekiq
|
||||
simple_form
|
||||
slim-rails
|
||||
spring
|
||||
spring-watcher-listen (~> 2.0.0)
|
||||
turbolinks (~> 5.x)
|
||||
uglifier (>= 2.7.2)
|
||||
unicorn
|
||||
|
||||
BUNDLED WITH
|
||||
1.11.2
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
$(document).on 'turbolinks:load', ->
|
||||
if $('.about-page').length > 0
|
||||
$(window).scroll ()->
|
||||
if $(this).scrollTop() > 0
|
||||
$('.top-bar-wrapper').addClass('active')
|
||||
else
|
||||
$('.top-bar-wrapper').removeClass('active')
|
||||
|
||||
$('#about-top-bar').ddscrollSpy
|
||||
highlightclass: 'active'
|
||||
|
||||
$('.intro').ddscrollSpy
|
||||
highlightclass: 'active'
|
|
@ -3,16 +3,36 @@
|
|||
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
|
||||
#
|
||||
|
||||
$(document).ready ->
|
||||
$(document).on 'turbolinks:load', ->
|
||||
$('a#upload_photo').click ->
|
||||
$('input[type=file]').show().focus().click().hide()
|
||||
false
|
||||
|
||||
|
||||
$('#tabs').on 'change.zf.tabs', ()->
|
||||
if $('#preview:visible').length > 0
|
||||
$('#preview').text('Loading...')
|
||||
$.ajax
|
||||
url: '/admin/posts/preview'
|
||||
type: 'POST'
|
||||
data:
|
||||
content: $('#content-input').val()
|
||||
success: (data)->
|
||||
$('#preview').html(data)
|
||||
|
||||
$('a.tag').click (event)->
|
||||
event.preventDefault()
|
||||
new_labels = $(this).text()
|
||||
if $('#labels').val() == ''
|
||||
labels = new_labels
|
||||
else
|
||||
labels = $('#labels').val() + ", #{new_labels}"
|
||||
$('#labels').val(labels)
|
||||
|
||||
opt =
|
||||
type: 'POST'
|
||||
url: "/photos"
|
||||
success: (data,status,xhr)->
|
||||
txtBox = $("#post_content")
|
||||
txtBox = $("#content-input")
|
||||
caret_pos = txtBox.caret('pos')
|
||||
src_merged = "\n" + data + "\n"
|
||||
source = txtBox.val()
|
||||
|
@ -21,6 +41,5 @@ $(document).ready ->
|
|||
txtBox.caret('pos',caret_pos + src_merged.length)
|
||||
txtBox.scope().content = txtBox.val()
|
||||
txtBox.focus()
|
||||
|
||||
|
||||
$('input[type=file]').fileUpload opt
|
||||
|
|
|
@ -1,589 +0,0 @@
|
|||
/**
|
||||
* x is a value between 0 and 1, indicating where in the animation you are.
|
||||
*/
|
||||
var duScrollDefaultEasing = function (x) {
|
||||
'use strict';
|
||||
|
||||
if(x < 0.5) {
|
||||
return Math.pow(x*2, 2)/2;
|
||||
}
|
||||
return 1-Math.pow((1-x)*2, 2)/2;
|
||||
};
|
||||
|
||||
angular.module('duScroll', [
|
||||
'duScroll.scrollspy',
|
||||
'duScroll.smoothScroll',
|
||||
'duScroll.scrollContainer',
|
||||
'duScroll.spyContext',
|
||||
'duScroll.scrollHelpers'
|
||||
])
|
||||
//Default animation duration for smoothScroll directive
|
||||
.value('duScrollDuration', 350)
|
||||
//Scrollspy debounce interval, set to 0 to disable
|
||||
.value('duScrollSpyWait', 100)
|
||||
//Wether or not multiple scrollspies can be active at once
|
||||
.value('duScrollGreedy', false)
|
||||
//Default offset for smoothScroll directive
|
||||
.value('duScrollOffset', 0)
|
||||
//Default easing function for scroll animation
|
||||
.value('duScrollEasing', duScrollDefaultEasing);
|
||||
|
||||
|
||||
angular.module('duScroll.scrollHelpers', ['duScroll.requestAnimation'])
|
||||
.run(["$window", "$q", "cancelAnimation", "requestAnimation", "duScrollEasing", "duScrollDuration", "duScrollOffset", function($window, $q, cancelAnimation, requestAnimation, duScrollEasing, duScrollDuration, duScrollOffset) {
|
||||
'use strict';
|
||||
|
||||
var proto = angular.element.prototype;
|
||||
|
||||
var isDocument = function(el) {
|
||||
return (typeof HTMLDocument !== 'undefined' && el instanceof HTMLDocument) || (el.nodeType && el.nodeType === el.DOCUMENT_NODE);
|
||||
};
|
||||
|
||||
var isElement = function(el) {
|
||||
return (typeof HTMLElement !== 'undefined' && el instanceof HTMLElement) || (el.nodeType && el.nodeType === el.ELEMENT_NODE);
|
||||
};
|
||||
|
||||
var unwrap = function(el) {
|
||||
return isElement(el) || isDocument(el) ? el : el[0];
|
||||
};
|
||||
|
||||
proto.scrollTo = function(left, top, duration, easing) {
|
||||
var aliasFn;
|
||||
if(angular.isElement(left)) {
|
||||
aliasFn = this.scrollToElement;
|
||||
} else if(duration) {
|
||||
aliasFn = this.scrollToAnimated;
|
||||
}
|
||||
if(aliasFn) {
|
||||
return aliasFn.apply(this, arguments);
|
||||
}
|
||||
var el = unwrap(this);
|
||||
if(isDocument(el)) {
|
||||
return $window.scrollTo(left, top);
|
||||
}
|
||||
el.scrollLeft = left;
|
||||
el.scrollTop = top;
|
||||
};
|
||||
|
||||
var scrollAnimation, deferred;
|
||||
proto.scrollToAnimated = function(left, top, duration, easing) {
|
||||
if(duration && !easing) {
|
||||
easing = duScrollEasing;
|
||||
}
|
||||
var startLeft = this.scrollLeft(),
|
||||
startTop = this.scrollTop(),
|
||||
deltaLeft = Math.round(left - startLeft),
|
||||
deltaTop = Math.round(top - startTop);
|
||||
|
||||
var startTime = null;
|
||||
var el = this;
|
||||
|
||||
var cancelOnEvents = 'scroll mousedown mousewheel touchmove keydown';
|
||||
var cancelScrollAnimation = function($event) {
|
||||
if (!$event || $event.which > 0) {
|
||||
el.unbind(cancelOnEvents, cancelScrollAnimation);
|
||||
cancelAnimation(scrollAnimation);
|
||||
deferred.reject();
|
||||
scrollAnimation = null;
|
||||
}
|
||||
};
|
||||
|
||||
if(scrollAnimation) {
|
||||
cancelScrollAnimation();
|
||||
}
|
||||
deferred = $q.defer();
|
||||
|
||||
if(!deltaLeft && !deltaTop) {
|
||||
deferred.resolve();
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
var animationStep = function(timestamp) {
|
||||
if (startTime === null) {
|
||||
startTime = timestamp;
|
||||
}
|
||||
|
||||
var progress = timestamp - startTime;
|
||||
var percent = (progress >= duration ? 1 : easing(progress/duration));
|
||||
|
||||
el.scrollTo(
|
||||
startLeft + Math.ceil(deltaLeft * percent),
|
||||
startTop + Math.ceil(deltaTop * percent)
|
||||
);
|
||||
if(percent < 1) {
|
||||
scrollAnimation = requestAnimation(animationStep);
|
||||
} else {
|
||||
el.unbind(cancelOnEvents, cancelScrollAnimation);
|
||||
scrollAnimation = null;
|
||||
deferred.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
//Fix random mobile safari bug when scrolling to top by hitting status bar
|
||||
el.scrollTo(startLeft, startTop);
|
||||
|
||||
el.bind(cancelOnEvents, cancelScrollAnimation);
|
||||
|
||||
scrollAnimation = requestAnimation(animationStep);
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
proto.scrollToElement = function(target, offset, duration, easing) {
|
||||
var el = unwrap(this);
|
||||
if(!angular.isNumber(offset) || isNaN(offset)) {
|
||||
offset = duScrollOffset;
|
||||
}
|
||||
var top = this.scrollTop() + unwrap(target).getBoundingClientRect().top - offset;
|
||||
if(isElement(el)) {
|
||||
top -= el.getBoundingClientRect().top;
|
||||
}
|
||||
return this.scrollTo(0, top, duration, easing);
|
||||
};
|
||||
|
||||
var overloaders = {
|
||||
scrollLeft: function(value, duration, easing) {
|
||||
if(angular.isNumber(value)) {
|
||||
return this.scrollTo(value, this.scrollTop(), duration, easing);
|
||||
}
|
||||
var el = unwrap(this);
|
||||
if(isDocument(el)) {
|
||||
return $window.scrollX || document.documentElement.scrollLeft || document.body.scrollLeft;
|
||||
}
|
||||
return el.scrollLeft;
|
||||
},
|
||||
scrollTop: function(value, duration, easing) {
|
||||
if(angular.isNumber(value)) {
|
||||
return this.scrollTo(this.scrollTop(), value, duration, easing);
|
||||
}
|
||||
var el = unwrap(this);
|
||||
if(isDocument(el)) {
|
||||
return $window.scrollY || document.documentElement.scrollTop || document.body.scrollTop;
|
||||
}
|
||||
return el.scrollTop;
|
||||
}
|
||||
};
|
||||
|
||||
proto.scrollToElementAnimated = function(target, offset, duration, easing) {
|
||||
return this.scrollToElement(target, offset, duration || duScrollDuration, easing);
|
||||
};
|
||||
|
||||
proto.scrollTopAnimated = function(top, duration, easing) {
|
||||
return this.scrollTop(top, duration || duScrollDuration, easing);
|
||||
};
|
||||
|
||||
proto.scrollLeftAnimated = function(left, duration, easing) {
|
||||
return this.scrollLeft(left, duration || duScrollDuration, easing);
|
||||
};
|
||||
|
||||
//Add duration and easing functionality to existing jQuery getter/setters
|
||||
var overloadScrollPos = function(superFn, overloadFn) {
|
||||
return function(value, duration, easing) {
|
||||
if(duration) {
|
||||
return overloadFn.apply(this, arguments);
|
||||
}
|
||||
return superFn.apply(this, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
for(var methodName in overloaders) {
|
||||
proto[methodName] = (proto[methodName] ? overloadScrollPos(proto[methodName], overloaders[methodName]) : overloaders[methodName]);
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
//Adapted from https://gist.github.com/paulirish/1579671
|
||||
angular.module('duScroll.polyfill', [])
|
||||
.factory('polyfill', ["$window", function($window) {
|
||||
'use strict';
|
||||
|
||||
var vendors = ['webkit', 'moz', 'o', 'ms'];
|
||||
|
||||
return function(fnName, fallback) {
|
||||
if($window[fnName]) {
|
||||
return $window[fnName];
|
||||
}
|
||||
var suffix = fnName.substr(0, 1).toUpperCase() + fnName.substr(1);
|
||||
for(var key, i = 0; i < vendors.length; i++) {
|
||||
key = vendors[i]+suffix;
|
||||
if($window[key]) {
|
||||
return $window[key];
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
};
|
||||
}]);
|
||||
|
||||
angular.module('duScroll.requestAnimation', ['duScroll.polyfill'])
|
||||
.factory('requestAnimation', ["polyfill", "$timeout", function(polyfill, $timeout) {
|
||||
'use strict';
|
||||
|
||||
var lastTime = 0;
|
||||
var fallback = function(callback, element) {
|
||||
var currTime = new Date().getTime();
|
||||
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||||
var id = $timeout(function() { callback(currTime + timeToCall); },
|
||||
timeToCall);
|
||||
lastTime = currTime + timeToCall;
|
||||
return id;
|
||||
};
|
||||
|
||||
return polyfill('requestAnimationFrame', fallback);
|
||||
}])
|
||||
.factory('cancelAnimation', ["polyfill", "$timeout", function(polyfill, $timeout) {
|
||||
'use strict';
|
||||
|
||||
var fallback = function(promise) {
|
||||
$timeout.cancel(promise);
|
||||
};
|
||||
|
||||
return polyfill('cancelAnimationFrame', fallback);
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.spyAPI', ['duScroll.scrollContainerAPI'])
|
||||
.factory('spyAPI', ["$rootScope", "$timeout", "scrollContainerAPI", "duScrollGreedy", "duScrollSpyWait", function($rootScope, $timeout, scrollContainerAPI, duScrollGreedy, duScrollSpyWait) {
|
||||
'use strict';
|
||||
|
||||
var createScrollHandler = function(context) {
|
||||
var timer = false, queued = false;
|
||||
var handler = function() {
|
||||
queued = false;
|
||||
var container = context.container,
|
||||
containerEl = container[0],
|
||||
containerOffset = 0;
|
||||
|
||||
if (typeof HTMLElement !== 'undefined' && containerEl instanceof HTMLElement || containerEl.nodeType && containerEl.nodeType === containerEl.ELEMENT_NODE) {
|
||||
containerOffset = containerEl.getBoundingClientRect().top;
|
||||
}
|
||||
|
||||
var i, currentlyActive, toBeActive, spies, spy, pos;
|
||||
spies = context.spies;
|
||||
currentlyActive = context.currentlyActive;
|
||||
toBeActive = undefined;
|
||||
|
||||
for(i = 0; i < spies.length; i++) {
|
||||
spy = spies[i];
|
||||
pos = spy.getTargetPosition();
|
||||
if (!pos) continue;
|
||||
|
||||
if(pos.top + spy.offset - containerOffset < 20 && (pos.top*-1 + containerOffset) < pos.height) {
|
||||
if(!toBeActive || toBeActive.top < pos.top) {
|
||||
toBeActive = {
|
||||
top: pos.top,
|
||||
spy: spy
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if(toBeActive) {
|
||||
toBeActive = toBeActive.spy;
|
||||
}
|
||||
if(currentlyActive === toBeActive || (duScrollGreedy && !toBeActive)) return;
|
||||
if(currentlyActive) {
|
||||
currentlyActive.$element.removeClass('active');
|
||||
$rootScope.$broadcast('duScrollspy:becameInactive', currentlyActive.$element);
|
||||
}
|
||||
if(toBeActive) {
|
||||
toBeActive.$element.addClass('active');
|
||||
$rootScope.$broadcast('duScrollspy:becameActive', toBeActive.$element);
|
||||
}
|
||||
context.currentlyActive = toBeActive;
|
||||
};
|
||||
|
||||
if(!duScrollSpyWait) {
|
||||
return handler;
|
||||
}
|
||||
|
||||
//Debounce for potential performance savings
|
||||
return function() {
|
||||
if(!timer) {
|
||||
handler();
|
||||
timer = $timeout(function() {
|
||||
timer = false;
|
||||
if(queued) {
|
||||
handler();
|
||||
}
|
||||
}, duScrollSpyWait, false);
|
||||
} else {
|
||||
queued = true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var contexts = {};
|
||||
|
||||
var createContext = function($scope) {
|
||||
var id = $scope.$id;
|
||||
var context = {
|
||||
spies: []
|
||||
};
|
||||
|
||||
context.handler = createScrollHandler(context);
|
||||
contexts[id] = context;
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
destroyContext($scope);
|
||||
});
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
var destroyContext = function($scope) {
|
||||
var id = $scope.$id;
|
||||
var context = contexts[id], container = context.container;
|
||||
if(container) {
|
||||
container.off('scroll', context.handler);
|
||||
}
|
||||
delete contexts[id];
|
||||
};
|
||||
|
||||
var defaultContextId = createContext($rootScope);
|
||||
|
||||
var getContextForScope = function(scope) {
|
||||
if(contexts[scope.$id]) {
|
||||
return contexts[scope.$id];
|
||||
}
|
||||
if(scope.$parent) {
|
||||
return getContextForScope(scope.$parent);
|
||||
}
|
||||
return contexts[defaultContextId];
|
||||
};
|
||||
|
||||
var getContextForSpy = function(spy) {
|
||||
var context, contextId, scope = spy.$element.scope();
|
||||
if(scope) {
|
||||
return getContextForScope(scope);
|
||||
}
|
||||
//No scope, most likely destroyed
|
||||
for(contextId in contexts) {
|
||||
context = contexts[contextId];
|
||||
if(context.spies.indexOf(spy) !== -1) {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var isElementInDocument = function(element) {
|
||||
while (element.parentNode) {
|
||||
element = element.parentNode;
|
||||
if (element === document) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var addSpy = function(spy) {
|
||||
var context = getContextForSpy(spy);
|
||||
if (!context) return;
|
||||
context.spies.push(spy);
|
||||
if (!context.container || !isElementInDocument(context.container)) {
|
||||
if(context.container) {
|
||||
context.container.off('scroll', context.handler);
|
||||
}
|
||||
context.container = scrollContainerAPI.getContainer(spy.$element.scope());
|
||||
context.container.on('scroll', context.handler).triggerHandler('scroll');
|
||||
}
|
||||
};
|
||||
|
||||
var removeSpy = function(spy) {
|
||||
var context = getContextForSpy(spy);
|
||||
if(spy === context.currentlyActive) {
|
||||
context.currentlyActive = null;
|
||||
}
|
||||
var i = context.spies.indexOf(spy);
|
||||
if(i !== -1) {
|
||||
context.spies.splice(i, 1);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
addSpy: addSpy,
|
||||
removeSpy: removeSpy,
|
||||
createContext: createContext,
|
||||
destroyContext: destroyContext,
|
||||
getContextForScope: getContextForScope
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.scrollContainerAPI', [])
|
||||
.factory('scrollContainerAPI', ["$document", function($document) {
|
||||
'use strict';
|
||||
|
||||
var containers = {};
|
||||
|
||||
var setContainer = function(scope, element) {
|
||||
var id = scope.$id;
|
||||
containers[id] = element;
|
||||
return id;
|
||||
};
|
||||
|
||||
var getContainerId = function(scope) {
|
||||
if(containers[scope.$id]) {
|
||||
return scope.$id;
|
||||
}
|
||||
if(scope.$parent) {
|
||||
return getContainerId(scope.$parent);
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
var getContainer = function(scope) {
|
||||
var id = getContainerId(scope);
|
||||
return id ? containers[id] : $document;
|
||||
};
|
||||
|
||||
var removeContainer = function(scope) {
|
||||
var id = getContainerId(scope);
|
||||
if(id) {
|
||||
delete containers[id];
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
getContainerId: getContainerId,
|
||||
getContainer: getContainer,
|
||||
setContainer: setContainer,
|
||||
removeContainer: removeContainer
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.smoothScroll', ['duScroll.scrollHelpers', 'duScroll.scrollContainerAPI'])
|
||||
.directive('duSmoothScroll', ["duScrollDuration", "duScrollOffset", "scrollContainerAPI", function(duScrollDuration, duScrollOffset, scrollContainerAPI) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
link : function($scope, $element, $attr) {
|
||||
$element.on('click', function(e) {
|
||||
if(!$attr.href || $attr.href.indexOf('#') === -1) return;
|
||||
|
||||
var target = document.getElementById($attr.href.replace(/.*(?=#[^\s]+$)/, '').substring(1));
|
||||
if(!target || !target.getBoundingClientRect) return;
|
||||
|
||||
if (e.stopPropagation) e.stopPropagation();
|
||||
if (e.preventDefault) e.preventDefault();
|
||||
|
||||
var offset = $attr.offset ? parseInt($attr.offset, 10) : duScrollOffset;
|
||||
var duration = $attr.duration ? parseInt($attr.duration, 10) : duScrollDuration;
|
||||
var container = scrollContainerAPI.getContainer($scope);
|
||||
|
||||
container.scrollToElement(
|
||||
angular.element(target),
|
||||
isNaN(offset) ? 0 : offset,
|
||||
isNaN(duration) ? 0 : duration
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.spyContext', ['duScroll.spyAPI'])
|
||||
.directive('duSpyContext', ["spyAPI", function(spyAPI) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: true,
|
||||
compile: function compile(tElement, tAttrs, transclude) {
|
||||
return {
|
||||
pre: function preLink($scope, iElement, iAttrs, controller) {
|
||||
spyAPI.createContext($scope);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.scrollContainer', ['duScroll.scrollContainerAPI'])
|
||||
.directive('duScrollContainer', ["scrollContainerAPI", function(scrollContainerAPI){
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: true,
|
||||
compile: function compile(tElement, tAttrs, transclude) {
|
||||
return {
|
||||
pre: function preLink($scope, iElement, iAttrs, controller) {
|
||||
iAttrs.$observe('duScrollContainer', function(element) {
|
||||
if(angular.isString(element)) {
|
||||
element = document.getElementById(element);
|
||||
}
|
||||
|
||||
element = (angular.isElement(element) ? angular.element(element) : iElement);
|
||||
scrollContainerAPI.setContainer($scope, element);
|
||||
$scope.$on('$destroy', function() {
|
||||
scrollContainerAPI.removeContainer($scope);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.scrollspy', ['duScroll.spyAPI'])
|
||||
.directive('duScrollspy', ["spyAPI", "duScrollOffset", "$timeout", "$rootScope", function(spyAPI, duScrollOffset, $timeout, $rootScope) {
|
||||
'use strict';
|
||||
|
||||
var Spy = function(targetElementOrId, $element, offset) {
|
||||
if(angular.isElement(targetElementOrId)) {
|
||||
this.target = targetElementOrId;
|
||||
} else if(angular.isString(targetElementOrId)) {
|
||||
this.targetId = targetElementOrId;
|
||||
}
|
||||
this.$element = $element;
|
||||
this.offset = offset;
|
||||
};
|
||||
|
||||
Spy.prototype.getTargetElement = function() {
|
||||
if (!this.target && this.targetId) {
|
||||
this.target = document.getElementById(this.targetId);
|
||||
}
|
||||
return this.target;
|
||||
};
|
||||
|
||||
Spy.prototype.getTargetPosition = function() {
|
||||
var target = this.getTargetElement();
|
||||
if(target) {
|
||||
return target.getBoundingClientRect();
|
||||
}
|
||||
};
|
||||
|
||||
Spy.prototype.flushTargetCache = function() {
|
||||
if(this.targetId) {
|
||||
this.target = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
link: function ($scope, $element, $attr) {
|
||||
var href = $attr.ngHref || $attr.href;
|
||||
var targetId;
|
||||
|
||||
if (href && href.indexOf('#') !== -1) {
|
||||
targetId = href.replace(/.*(?=#[^\s]+$)/, '').substring(1);
|
||||
} else if($attr.duScrollspy) {
|
||||
targetId = $attr.duScrollspy;
|
||||
}
|
||||
if(!targetId) return;
|
||||
|
||||
// Run this in the next execution loop so that the scroll context has a chance
|
||||
// to initialize
|
||||
$timeout(function() {
|
||||
var spy = new Spy(targetId, $element, -($attr.offset ? parseInt($attr.offset, 10) : duScrollOffset));
|
||||
spyAPI.addSpy(spy);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
spyAPI.removeSpy(spy);
|
||||
});
|
||||
$scope.$on('$locationChangeSuccess', spy.flushTargetCache.bind(spy));
|
||||
$rootScope.$on('$stateChangeSuccess', spy.flushTargetCache.bind(spy));
|
||||
}, 0, false);
|
||||
}
|
||||
};
|
||||
}]);
|
|
@ -1,15 +0,0 @@
|
|||
#= require angular
|
||||
#= require angular-cookies
|
||||
#= require angular-resource
|
||||
#= require angular-sanitize
|
||||
#= require angular-scroll
|
||||
#= require_self
|
||||
#= require_tree ./angularjs
|
||||
|
||||
@app = angular.module('app', ['ngCookies', 'ngSanitize', 'duScroll'])
|
||||
@app.value('duScrollOffset', 30)
|
||||
|
||||
@app.config(["$httpProvider", (provider) ->
|
||||
provider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')
|
||||
provider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
|
||||
])
|
|
@ -1,36 +0,0 @@
|
|||
@app.controller 'AboutController', [ '$scope', '$timeout', '$http', ($scope, $timeout, $http)->
|
||||
$scope.type = null
|
||||
|
||||
$scope.click = (v)->
|
||||
if $scope.type == v
|
||||
$scope.type = null
|
||||
return
|
||||
$scope.type = v
|
||||
$scope.weixin_click = ->
|
||||
$scope.weixin = !$scope.weixin
|
||||
|
||||
#订阅功能
|
||||
|
||||
$scope.email = ''
|
||||
$scope.subscribe_success = null
|
||||
|
||||
$scope.email_validate = ->
|
||||
$scope.email.match(/@/)
|
||||
|
||||
$scope.subscribe = ()->
|
||||
$http
|
||||
url: '/subscribes'
|
||||
method: 'POST'
|
||||
params:
|
||||
email: $scope.email
|
||||
.success (res)->
|
||||
if res.success
|
||||
$scope.email = ''
|
||||
$scope.subscribe_success = true
|
||||
else
|
||||
$scope.subscribe_success = false
|
||||
$scope.subscribe_fail_msg = res.message
|
||||
$timeout ->
|
||||
$scope.subscribe_success = null
|
||||
, 3000
|
||||
]
|
|
@ -1,14 +0,0 @@
|
|||
@app.controller 'AboutScrollController', [ '$scope', '$document', ($scope, $document)->
|
||||
|
||||
about_id = angular.element(document.getElementById('about'))
|
||||
|
||||
$document.on 'scroll', ()=>
|
||||
$scope.$apply()
|
||||
|
||||
$scope.is_top = ()->
|
||||
$document.scrollTop() <= 0
|
||||
|
||||
|
||||
$scope.to_about = ()->
|
||||
$document.scrollToElementAnimated(about_id)
|
||||
]
|
|
@ -1,35 +0,0 @@
|
|||
@app.controller 'AdminPostsController', [ '$scope', '$http', '$location', '$timeout', '$cookies', '$sce', ($scope, $http, $location, $timeout, $cookies, $sce)->
|
||||
|
||||
$scope.body_active = true
|
||||
|
||||
$scope.init = (id)->
|
||||
url = '/admin/posts/' + id + '.json'
|
||||
$http
|
||||
url: url
|
||||
method: 'GET'
|
||||
.success (res)->
|
||||
$scope.title = res.title
|
||||
$scope.type = res.type
|
||||
$scope.labels = res.labels
|
||||
$scope.content = res.content
|
||||
|
||||
$scope.changeToBody = ->
|
||||
$scope.body_active = true
|
||||
|
||||
$scope.changeToPreview = ->
|
||||
$scope.body_active = false
|
||||
$scope.previewHTML = 'Loading...'
|
||||
$http.post '/admin/posts/preview', { content: $scope.content }
|
||||
.success (res)->
|
||||
$scope.previewHTML = res
|
||||
|
||||
$scope.trustAsPreviewHTML = ()->
|
||||
$sce.trustAsHtml($scope.previewHTML)
|
||||
|
||||
$scope.addTag = (e)->
|
||||
new_labels= $(e.target).text()
|
||||
if $scope.labels
|
||||
$scope.labels += ", #{new_labels}"
|
||||
else
|
||||
$scope.labels = new_labels
|
||||
]
|
|
@ -1,21 +0,0 @@
|
|||
@app.controller 'AdminSessionsController', [ '$scope', '$http', '$timeout', '$cookies', ($scope, $http, $timeout, $cookies)->
|
||||
url = '/admin/sessions'
|
||||
|
||||
$scope.login = ->
|
||||
$http
|
||||
url: url
|
||||
method: 'POST'
|
||||
data:
|
||||
username: $scope.username
|
||||
password: $scope.password
|
||||
.success (res)->
|
||||
if res.success
|
||||
urlback = $cookies.urlback || '/admin'
|
||||
window.location = urlback
|
||||
else
|
||||
$scope.password = ''
|
||||
$scope.error_msg = res.message
|
||||
$timeout ->
|
||||
$scope.error_msg = null
|
||||
, 5000
|
||||
]
|
|
@ -1,43 +0,0 @@
|
|||
@app.controller 'ArchivesController',[ '$scope', '$http', '$location', '$timeout', '$cookies', ($scope, $http, $location, $timeout, $cookies)->
|
||||
url = window.location.pathname + ".json"
|
||||
start_with = $cookies.start_with if window.location.pathname == $cookies.start_with_type
|
||||
$http
|
||||
url: url
|
||||
method: 'GET'
|
||||
params:
|
||||
start_with: start_with
|
||||
all: true
|
||||
.success (res)->
|
||||
$scope.update_start_with(res.start_with)
|
||||
$scope.posts = res.posts
|
||||
|
||||
$scope.no_more_flag = false
|
||||
$scope.loading_flag = false
|
||||
|
||||
$scope.load = ()->
|
||||
$scope.loading_flag = true
|
||||
$http(
|
||||
url: url
|
||||
method: 'GET'
|
||||
params:
|
||||
start_with: $scope.start_with
|
||||
type: $scope.type
|
||||
).success (res)->
|
||||
$scope.no_more_flag = true if res.posts.length == 0
|
||||
$scope.update_start_with(res.start_with)
|
||||
$scope.posts = $scope.posts.concat(res.posts)
|
||||
$timeout ->
|
||||
$scope.loading_flag = false
|
||||
, 500
|
||||
$timeout ->
|
||||
$scope.no_more_flag = false
|
||||
, 3000
|
||||
|
||||
$scope.visit = (id)->
|
||||
"/blogs/" + id
|
||||
|
||||
$scope.update_start_with = (start_with)->
|
||||
$scope.start_with = start_with
|
||||
$cookies.start_with_type = window.location.pathname
|
||||
$cookies.start_with = start_with
|
||||
]
|
|
@ -1,35 +0,0 @@
|
|||
@app.controller 'CommentsController', ['$scope', '$http', '$location', '$timeout', '$cookies', ($scope, $http, $location, $timeout, $cookies)->
|
||||
url = window.location.pathname + "/comments.json"
|
||||
|
||||
$scope.name = $cookies.name
|
||||
$scope.email = $cookies.email
|
||||
|
||||
$http.get(url).success (data)->
|
||||
$scope.comments = data
|
||||
|
||||
$scope.publish_success = null
|
||||
|
||||
$scope.submit = ->
|
||||
$scope.submitting = true
|
||||
$cookies.name = $scope.name
|
||||
$cookies.email = $scope.email
|
||||
comment = { content: $scope.content, name: $scope.name, email: $scope.email }
|
||||
$http.post(url, comment)
|
||||
.success (res)->
|
||||
if res.success
|
||||
$scope.publish_success = true
|
||||
$scope.content = ''
|
||||
$scope.comments.unshift(res.data)
|
||||
else
|
||||
$scope.publish_success = false
|
||||
$scope.publish_fail_msg = res.message
|
||||
.error (data, status)->
|
||||
$scope.publish_success = false
|
||||
$scope.publish_fail_msg = 'Network Error, Retry for a moment, Status Code: ' + status
|
||||
.finally ->
|
||||
$scope.submitting = false
|
||||
$scope.timeout = $timeout ->
|
||||
$timeout.cancel($scope.timeout)
|
||||
$scope.publish_success = null
|
||||
, 5*1000
|
||||
]
|
|
@ -1,9 +0,0 @@
|
|||
@app.directive 'ngInitial', ->
|
||||
restrict: 'A',
|
||||
controller: [
|
||||
'$scope', '$element', '$attrs', '$parse', ($scope, $element, $attrs, $parse)->
|
||||
val = $attrs.ngInitial || $attrs.value || $attrs.$$element.text()
|
||||
getter = $parse($attrs.ngModel)
|
||||
setter = getter.assign
|
||||
setter($scope, val)
|
||||
]
|
|
@ -1,38 +0,0 @@
|
|||
@app.controller 'LikesController', ['$scope', '$http', '$location', '$cookies', ($scope, $http, $location, $cookies)->
|
||||
url = window.location.pathname + "/likes"
|
||||
|
||||
$http.get url
|
||||
.success (res)->
|
||||
$scope.count = res.count
|
||||
|
||||
$scope.like = $cookies.like
|
||||
|
||||
if $scope.like
|
||||
$http
|
||||
url: window.location.pathname + "/likes/#{$scope.like}/is_liked"
|
||||
method: 'GET'
|
||||
.success (res)->
|
||||
if res == true
|
||||
$scope.is_liked = true
|
||||
else
|
||||
$scope.is_liked = false
|
||||
else
|
||||
$scope.is_liked = false
|
||||
|
||||
$scope.submit = ->
|
||||
$http.post url
|
||||
.success (res)->
|
||||
if res.success
|
||||
$scope.like = $cookies.like = res.id
|
||||
$scope.count = res.count
|
||||
$scope.is_liked = true
|
||||
|
||||
$scope.cancel = ->
|
||||
$http.delete url + "/" + $scope.like
|
||||
.success (res)->
|
||||
$scope.count = res.count
|
||||
$scope.is_liked = false
|
||||
# anyway, clear cookie
|
||||
delete $cookies["like"]
|
||||
$scope.like = null
|
||||
]
|
|
@ -1,4 +0,0 @@
|
|||
@app.controller 'QRCodesController', [ '$scope', ($scope)->
|
||||
$scope.show = ->
|
||||
$scope.qrcode = ! $scope.qrcode
|
||||
]
|
|
@ -1,10 +0,0 @@
|
|||
@app.controller 'SubscribesController', [ '$scope', '$http', ($scope, $http)->
|
||||
$scope.cancel = ()->
|
||||
$http
|
||||
url: '/subscribes/cancel'
|
||||
method: 'POST'
|
||||
params:
|
||||
email: $scope.email
|
||||
.success (res)->
|
||||
window.location = '/'
|
||||
]
|
|
@ -1,13 +1,11 @@
|
|||
//= require jquery
|
||||
//= require jquery_ujs
|
||||
//= require foundation/foundation
|
||||
//= require foundation/foundation.alert
|
||||
//= require foundation/foundation.topbar
|
||||
//= require foundation/foundation.offcanvas
|
||||
//= require foundation/foundation.magellan
|
||||
//= require angularjs
|
||||
//= require turbolinks
|
||||
//= require foundation
|
||||
//= require js.cookie
|
||||
//= require 'jquery.html5-fileupload'
|
||||
//= require_tree .
|
||||
|
||||
|
||||
$(function(){ $(document).foundation(); });
|
||||
$(document).on('turbolinks:load', function(){
|
||||
$(document).foundation();
|
||||
});
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
$(document).on 'turbolinks:load', ->
|
||||
$('#alert-container .close-button').click ()->
|
||||
$('#alert-container').hide()
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* DD ScrollSpy Menu Script (c) Dynamic Drive (www.dynamicdrive.com)
|
||||
* Last updated: Aug 1st, 14'
|
||||
* Visit http://www.dynamicdrive.com/ for this script and 100s more.
|
||||
*/
|
||||
|
||||
// Aug 1st, 14': Updated to v1.2, which supports showing a progress bar inside each menu item (except in iOS devices). Other minor improvements.
|
||||
|
||||
if (!Array.prototype.filter){
|
||||
Array.prototype.filter = function(fun /*, thisp */){
|
||||
"use strict";
|
||||
|
||||
if (this == null)
|
||||
throw new TypeError();
|
||||
|
||||
var t = Object(this);
|
||||
var len = t.length >>> 0;
|
||||
if (typeof fun != "function")
|
||||
throw new TypeError();
|
||||
|
||||
var res = [];
|
||||
var thisp = arguments[1];
|
||||
for (var i = 0; i < len; i++){
|
||||
if (i in t){
|
||||
var val = t[i]; // in case fun mutates this
|
||||
if (fun.call(thisp, val, i, t))
|
||||
res.push(val);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
(function($){
|
||||
|
||||
var defaults = {
|
||||
spytarget: window,
|
||||
scrolltopoffset: 0,
|
||||
scrollbehavior: 'smooth',
|
||||
scrollduration: 500,
|
||||
highlightclass: 'selected',
|
||||
enableprogress: '',
|
||||
mincontentheight: 30
|
||||
}
|
||||
|
||||
var isiOS = /iPhone|iPad|iPod/i.test(navigator.userAgent) // detect iOS devices
|
||||
|
||||
function inrange(el, range, field){ // check if "playing field" is inside range
|
||||
var rangespan = range[1]-range[0], fieldspan = field[1]-field[0]
|
||||
if ( (range[0]-field[0]) >= 0 && (range[0]-field[0]) < fieldspan ){ // if top of range is on field
|
||||
return true
|
||||
}
|
||||
else{
|
||||
if ( (range[0]-field[0]) <= 0 && (range[0]+rangespan) > field[0] ){ // if part of range overlaps field
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
$.fn.ddscrollSpy = function(options){
|
||||
var $window = $(window)
|
||||
var $body=(window.opera)? (document.compatMode=="CSS1Compat"? $('html') : $('body')) : $('html,body')
|
||||
|
||||
|
||||
return this.each(function(){
|
||||
var o = $.extend({}, defaults, options)
|
||||
o.enableprogress = (isiOS)? '' : o.enableprogress // disable enableprogress in iOS
|
||||
var targets = [], curtarget = ''
|
||||
var cantscrollpastindex = -1 // index of target content that can't be scrolled past completely when scrollbar is at the end of the doc
|
||||
var $spytarget = $( o.spytarget ).eq(0)
|
||||
var spyheight = $spytarget.outerHeight()
|
||||
var spyscrollheight = (o.spytarget == window)? $body.get(0).scrollHeight : $spytarget.get(0).scrollHeight
|
||||
var $menu = $(this)
|
||||
var totaltargetsheight = 0 // total height of target contents
|
||||
function spyonmenuitems($menu){
|
||||
var $menuitems = $menu.find('a[href^="#"]')
|
||||
targets = []
|
||||
curtarget = ''
|
||||
totaltargetsheight = 0
|
||||
$menuitems.each(function(i){
|
||||
var $item = $(this)
|
||||
var $target = $( $item.attr('href') )
|
||||
var target = $target.get(0)
|
||||
var $progress = null // progress DIV that gets dynamically added inside menu A element if o.enableprogress enabled
|
||||
if ($target.length == 0) // if no matching links found
|
||||
return true
|
||||
$item
|
||||
.off('click.goto')
|
||||
.on('click.goto', function(e){
|
||||
if ( o.spytarget == window && (o.scrollbehavior == 'jump' || !history.pushState))
|
||||
window.location.hash = $item.attr('href')
|
||||
if (o.scrollbehavior == 'smooth' || o.scrolltopoffset !=0){
|
||||
var $scrollparent = (o.spytarget == window)? $body : $spytarget
|
||||
var addoffset = 1 // add 1 pixel to scrollTop when scrolling to an element to make sure the browser always returns the correct target element (strange bug)
|
||||
if (o.scrollbehavior == 'smooth' && (history.pushState || o.spytarget != window)){
|
||||
$scrollparent.animate( {scrollTop: targets[i].offsettop + addoffset}, o.scrollduration, function(){
|
||||
if (o.spytarget == window && history.pushState){
|
||||
//history.pushState(null, null, $item.attr('href'))
|
||||
}
|
||||
})
|
||||
}
|
||||
else{
|
||||
$scrollparent.prop('scrollTop', targets[i].offsettop + addoffset)
|
||||
}
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
if (o.enableprogress){ // if o.enableprogress enabled
|
||||
if ($item.find('div.' + o.enableprogress).length == 0){ //if no progress DIV found inside menu item
|
||||
$item.css({position: 'relative', overflow: 'hidden'}) // add some required style to parent A element
|
||||
$('<div class="' + o.enableprogress + '" style="position:absolute; left: -100%" />').appendTo($item)
|
||||
}
|
||||
$progress = $item.find('div.' + o.enableprogress)
|
||||
}
|
||||
var targetoffset = (o.spytarget == window)? $target.offset().top : (target.offsetParent == o.spytarget)? target.offsetTop : target.offsetTop - o.spytarget.offsetTop
|
||||
targetoffset += o.scrolltopoffset
|
||||
var targetheight = ( parseInt($target.data('spyrange')) > 0 )? parseInt($target.data('spyrange')) : ( $target.outerHeight() || o.mincontentheight)
|
||||
var offsetbottom = targetoffset + targetheight
|
||||
if (cantscrollpastindex == -1 && offsetbottom > (spyscrollheight - spyheight)){ // determine index of first target which can't be scrolled past
|
||||
cantscrollpastindex = i
|
||||
}
|
||||
targets.push( {$menuitem: $item, $des: $target, offsettop: targetoffset, height: targetheight, $progress: $progress, index: i} )
|
||||
})
|
||||
if (targets.length > 0)
|
||||
totaltargetsheight = targets[targets.length-1].offsettop + targets[targets.length-1].height
|
||||
}
|
||||
|
||||
function highlightitem(){
|
||||
if (targets.length == 0)
|
||||
return
|
||||
var prevtarget = curtarget
|
||||
var scrolltop = $spytarget.scrollTop()
|
||||
var cantscrollpasttarget = false
|
||||
var shortlist = targets.filter(function(el, index){ // filter target elements that are currently visible on screen
|
||||
return inrange(el, [el.offsettop, el.offsettop + el.height], [scrolltop, scrolltop + spyheight])
|
||||
})
|
||||
if (shortlist.length > 0){
|
||||
curtarget = shortlist.shift() // select the first element that's visible on screen
|
||||
if (prevtarget && prevtarget != curtarget)
|
||||
prevtarget.$menuitem.removeClass(o.highlightclass)
|
||||
if (!curtarget.$menuitem.hasClass(o.highlightclass)) // if there was a previously selected menu link and it's not the same as current
|
||||
curtarget.$menuitem.addClass(o.highlightclass) // highlight its menu item
|
||||
if (curtarget.index >= cantscrollpastindex && scrolltop >= (spyscrollheight - spyheight)){ // if we're at target that can't be scrolled past and we're at end of document
|
||||
if (o.enableprogress){ // if o.enableprogress enabled
|
||||
for (var i=0; i<targets.length; i++){ // highlight everything
|
||||
targets[i].$menuitem.find('div.' + o.enableprogress).css('left', 0)
|
||||
}
|
||||
}
|
||||
curtarget.$menuitem.removeClass(o.highlightclass)
|
||||
curtarget = targets[targets.length-1]
|
||||
if (!curtarget.$menuitem.hasClass(o.highlightclass))
|
||||
curtarget.$menuitem.addClass(o.highlightclass)
|
||||
return
|
||||
}
|
||||
if (o.enableprogress){ // if o.enableprogress enabled
|
||||
var scrollpct = ((scrolltop-curtarget.offsettop) / curtarget.height) * 100
|
||||
curtarget.$menuitem.find('div.' + o.enableprogress).css('left', -100 + scrollpct + '%')
|
||||
for (var i=0; i<targets.length; i++){
|
||||
if (i < curtarget.index){
|
||||
targets[i].$menuitem.find('div.' + o.enableprogress).css('left', 0)
|
||||
}
|
||||
else if (i > curtarget.index){
|
||||
targets[i].$menuitem.find('div.' + o.enableprogress).css('left', '-100%')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (scrolltop > totaltargetsheight){ // if no target content visible on screen but scroll bar has scrolled past very last content already
|
||||
if (o.enableprogress){ // if o.enableprogress enabled
|
||||
curtarget.$menuitem.removeClass(o.highlightclass)
|
||||
for (var i=0; i<targets.length; i++){
|
||||
targets[i].$menuitem.find('div.' + o.enableprogress).css('left', 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updatetargetpos(){
|
||||
if (targets.length == 0)
|
||||
return
|
||||
var $menu = targets[0].$menu
|
||||
spyheight = $spytarget.outerHeight()
|
||||
spyscrollheight = (o.spytarget == window)? $body.get(0).scrollHeight : $spytarget.get(0).scrollHeight
|
||||
totaltargetsheight = 0
|
||||
cantscrollpastindex = -1
|
||||
for (var i = 0; i < targets.length; i++){
|
||||
var $target = targets[i].$des
|
||||
var target = $target.get(0)
|
||||
var targetoffset = (o.spytarget == window)? $target.offset().top : (target.offsetParent == o.spytarget)? target.offsetTop : target.offsetTop - o.spytarget.offsetTop
|
||||
targetoffset += o.scrolltopoffset
|
||||
targets[i].offsettop = targetoffset
|
||||
targets[i].height = ( parseInt($target.data('spyrange')) > 0 )? parseInt($target.data('spyrange')) : ( $target.outerHeight() || o.mincontentheight)
|
||||
if (o.enableprogress){ // if o.enableprogress enabled
|
||||
var offsetbottom = targetoffset + targets[i].height // recalculate cantscrollpastindex
|
||||
if (cantscrollpastindex == -1 && offsetbottom > (spyscrollheight - spyheight)){
|
||||
cantscrollpastindex = i
|
||||
}
|
||||
}
|
||||
}
|
||||
totaltargetsheight = targets[targets.length-1].offsettop + targets[targets.length-1].height
|
||||
}
|
||||
|
||||
spyonmenuitems($menu)
|
||||
|
||||
$menu.on('updatespy', function(){
|
||||
spyonmenuitems($menu)
|
||||
highlightitem()
|
||||
})
|
||||
|
||||
$spytarget.on('scroll resize', function(){
|
||||
highlightitem()
|
||||
})
|
||||
|
||||
highlightitem()
|
||||
|
||||
$window.on('load resize', function(){
|
||||
updatetargetpos()
|
||||
})
|
||||
|
||||
}) // end return
|
||||
}
|
||||
|
||||
})(jQuery);
|
|
@ -8,13 +8,6 @@
|
|||
*/
|
||||
|
||||
|
||||
/*
|
||||
本插件操作 textarea 或者 input 内的插入符
|
||||
只实现了获得插入符在文本框中的位置,我设置
|
||||
插入符的位置.
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
(function(factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
|
@ -85,7 +78,7 @@
|
|||
/ \
|
||||
< I really [[HATE] IE []]>
|
||||
\_endRange end-point.
|
||||
|
||||
|
||||
" > -1" mean the start end-point will be the same or right to the end end-point
|
||||
* simplelly, all in the end.
|
||||
*/
|
||||
|
@ -99,7 +92,7 @@
|
|||
I really[ [HATE] IE ]>
|
||||
<-[
|
||||
I reall[y [HATE] IE ]>
|
||||
|
||||
|
||||
will return how many unit have moved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
$(document).on 'turbolinks:load', ->
|
||||
|
||||
$('.like-button').click ->
|
||||
if $(this).hasClass('liked')
|
||||
$.ajax
|
||||
url: $(this).data('url') + '/' + Cookies.get('like')
|
||||
type: 'DELETE'
|
||||
success: (res)=>
|
||||
$(this).removeClass('liked')
|
||||
$(this).children('.count').text(res.count)
|
||||
Cookies.remove('like')
|
||||
else
|
||||
$.ajax
|
||||
url: $(this).data('url')
|
||||
type: 'POST'
|
||||
success: (res)=>
|
||||
$(this).addClass('liked')
|
||||
$(this).children('.count').text(res.count)
|
||||
Cookies.set('like', res.id)
|
|
@ -0,0 +1,614 @@
|
|||
/**
|
||||
* @fileoverview
|
||||
* - Using the 'QRCode for Javascript library'
|
||||
* - Fixed dataset of 'QRCode for Javascript library' for support full-spec.
|
||||
* - this library has no dependencies.
|
||||
*
|
||||
* @author davidshimjs
|
||||
* @see <a href="http://www.d-project.com/" target="_blank">http://www.d-project.com/</a>
|
||||
* @see <a href="http://jeromeetienne.github.com/jquery-qrcode/" target="_blank">http://jeromeetienne.github.com/jquery-qrcode/</a>
|
||||
*/
|
||||
var QRCode;
|
||||
|
||||
(function () {
|
||||
//---------------------------------------------------------------------
|
||||
// QRCode for JavaScript
|
||||
//
|
||||
// Copyright (c) 2009 Kazuhiko Arase
|
||||
//
|
||||
// URL: http://www.d-project.com/
|
||||
//
|
||||
// Licensed under the MIT license:
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
// The word "QR Code" is registered trademark of
|
||||
// DENSO WAVE INCORPORATED
|
||||
// http://www.denso-wave.com/qrcode/faqpatent-e.html
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
function QR8bitByte(data) {
|
||||
this.mode = QRMode.MODE_8BIT_BYTE;
|
||||
this.data = data;
|
||||
this.parsedData = [];
|
||||
|
||||
// Added to support UTF-8 Characters
|
||||
for (var i = 0, l = this.data.length; i < l; i++) {
|
||||
var byteArray = [];
|
||||
var code = this.data.charCodeAt(i);
|
||||
|
||||
if (code > 0x10000) {
|
||||
byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18);
|
||||
byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12);
|
||||
byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6);
|
||||
byteArray[3] = 0x80 | (code & 0x3F);
|
||||
} else if (code > 0x800) {
|
||||
byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12);
|
||||
byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6);
|
||||
byteArray[2] = 0x80 | (code & 0x3F);
|
||||
} else if (code > 0x80) {
|
||||
byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6);
|
||||
byteArray[1] = 0x80 | (code & 0x3F);
|
||||
} else {
|
||||
byteArray[0] = code;
|
||||
}
|
||||
|
||||
this.parsedData.push(byteArray);
|
||||
}
|
||||
|
||||
this.parsedData = Array.prototype.concat.apply([], this.parsedData);
|
||||
|
||||
if (this.parsedData.length != this.data.length) {
|
||||
this.parsedData.unshift(191);
|
||||
this.parsedData.unshift(187);
|
||||
this.parsedData.unshift(239);
|
||||
}
|
||||
}
|
||||
|
||||
QR8bitByte.prototype = {
|
||||
getLength: function (buffer) {
|
||||
return this.parsedData.length;
|
||||
},
|
||||
write: function (buffer) {
|
||||
for (var i = 0, l = this.parsedData.length; i < l; i++) {
|
||||
buffer.put(this.parsedData[i], 8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function QRCodeModel(typeNumber, errorCorrectLevel) {
|
||||
this.typeNumber = typeNumber;
|
||||
this.errorCorrectLevel = errorCorrectLevel;
|
||||
this.modules = null;
|
||||
this.moduleCount = 0;
|
||||
this.dataCache = null;
|
||||
this.dataList = [];
|
||||
}
|
||||
|
||||
QRCodeModel.prototype={addData:function(data){var newData=new QR8bitByte(data);this.dataList.push(newData);this.dataCache=null;},isDark:function(row,col){if(row<0||this.moduleCount<=row||col<0||this.moduleCount<=col){throw new Error(row+","+col);}
|
||||
return this.modules[row][col];},getModuleCount:function(){return this.moduleCount;},make:function(){this.makeImpl(false,this.getBestMaskPattern());},makeImpl:function(test,maskPattern){this.moduleCount=this.typeNumber*4+17;this.modules=new Array(this.moduleCount);for(var row=0;row<this.moduleCount;row++){this.modules[row]=new Array(this.moduleCount);for(var col=0;col<this.moduleCount;col++){this.modules[row][col]=null;}}
|
||||
this.setupPositionProbePattern(0,0);this.setupPositionProbePattern(this.moduleCount-7,0);this.setupPositionProbePattern(0,this.moduleCount-7);this.setupPositionAdjustPattern();this.setupTimingPattern();this.setupTypeInfo(test,maskPattern);if(this.typeNumber>=7){this.setupTypeNumber(test);}
|
||||
if(this.dataCache==null){this.dataCache=QRCodeModel.createData(this.typeNumber,this.errorCorrectLevel,this.dataList);}
|
||||
this.mapData(this.dataCache,maskPattern);},setupPositionProbePattern:function(row,col){for(var r=-1;r<=7;r++){if(row+r<=-1||this.moduleCount<=row+r)continue;for(var c=-1;c<=7;c++){if(col+c<=-1||this.moduleCount<=col+c)continue;if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}},getBestMaskPattern:function(){var minLostPoint=0;var pattern=0;for(var i=0;i<8;i++){this.makeImpl(true,i);var lostPoint=QRUtil.getLostPoint(this);if(i==0||minLostPoint>lostPoint){minLostPoint=lostPoint;pattern=i;}}
|
||||
return pattern;},createMovieClip:function(target_mc,instance_name,depth){var qr_mc=target_mc.createEmptyMovieClip(instance_name,depth);var cs=1;this.make();for(var row=0;row<this.modules.length;row++){var y=row*cs;for(var col=0;col<this.modules[row].length;col++){var x=col*cs;var dark=this.modules[row][col];if(dark){qr_mc.beginFill(0,100);qr_mc.moveTo(x,y);qr_mc.lineTo(x+cs,y);qr_mc.lineTo(x+cs,y+cs);qr_mc.lineTo(x,y+cs);qr_mc.endFill();}}}
|
||||
return qr_mc;},setupTimingPattern:function(){for(var r=8;r<this.moduleCount-8;r++){if(this.modules[r][6]!=null){continue;}
|
||||
this.modules[r][6]=(r%2==0);}
|
||||
for(var c=8;c<this.moduleCount-8;c++){if(this.modules[6][c]!=null){continue;}
|
||||
this.modules[6][c]=(c%2==0);}},setupPositionAdjustPattern:function(){var pos=QRUtil.getPatternPosition(this.typeNumber);for(var i=0;i<pos.length;i++){for(var j=0;j<pos.length;j++){var row=pos[i];var col=pos[j];if(this.modules[row][col]!=null){continue;}
|
||||
for(var r=-2;r<=2;r++){for(var c=-2;c<=2;c++){if(r==-2||r==2||c==-2||c==2||(r==0&&c==0)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}}}},setupTypeNumber:function(test){var bits=QRUtil.getBCHTypeNumber(this.typeNumber);for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[Math.floor(i/3)][i%3+this.moduleCount-8-3]=mod;}
|
||||
for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[i%3+this.moduleCount-8-3][Math.floor(i/3)]=mod;}},setupTypeInfo:function(test,maskPattern){var data=(this.errorCorrectLevel<<3)|maskPattern;var bits=QRUtil.getBCHTypeInfo(data);for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<6){this.modules[i][8]=mod;}else if(i<8){this.modules[i+1][8]=mod;}else{this.modules[this.moduleCount-15+i][8]=mod;}}
|
||||
for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<8){this.modules[8][this.moduleCount-i-1]=mod;}else if(i<9){this.modules[8][15-i-1+1]=mod;}else{this.modules[8][15-i-1]=mod;}}
|
||||
this.modules[this.moduleCount-8][8]=(!test);},mapData:function(data,maskPattern){var inc=-1;var row=this.moduleCount-1;var bitIndex=7;var byteIndex=0;for(var col=this.moduleCount-1;col>0;col-=2){if(col==6)col--;while(true){for(var c=0;c<2;c++){if(this.modules[row][col-c]==null){var dark=false;if(byteIndex<data.length){dark=(((data[byteIndex]>>>bitIndex)&1)==1);}
|
||||
var mask=QRUtil.getMask(maskPattern,row,col-c);if(mask){dark=!dark;}
|
||||
this.modules[row][col-c]=dark;bitIndex--;if(bitIndex==-1){byteIndex++;bitIndex=7;}}}
|
||||
row+=inc;if(row<0||this.moduleCount<=row){row-=inc;inc=-inc;break;}}}}};QRCodeModel.PAD0=0xEC;QRCodeModel.PAD1=0x11;QRCodeModel.createData=function(typeNumber,errorCorrectLevel,dataList){var rsBlocks=QRRSBlock.getRSBlocks(typeNumber,errorCorrectLevel);var buffer=new QRBitBuffer();for(var i=0;i<dataList.length;i++){var data=dataList[i];buffer.put(data.mode,4);buffer.put(data.getLength(),QRUtil.getLengthInBits(data.mode,typeNumber));data.write(buffer);}
|
||||
var totalDataCount=0;for(var i=0;i<rsBlocks.length;i++){totalDataCount+=rsBlocks[i].dataCount;}
|
||||
if(buffer.getLengthInBits()>totalDataCount*8){throw new Error("code length overflow. ("
|
||||
+buffer.getLengthInBits()
|
||||
+">"
|
||||
+totalDataCount*8
|
||||
+")");}
|
||||
if(buffer.getLengthInBits()+4<=totalDataCount*8){buffer.put(0,4);}
|
||||
while(buffer.getLengthInBits()%8!=0){buffer.putBit(false);}
|
||||
while(true){if(buffer.getLengthInBits()>=totalDataCount*8){break;}
|
||||
buffer.put(QRCodeModel.PAD0,8);if(buffer.getLengthInBits()>=totalDataCount*8){break;}
|
||||
buffer.put(QRCodeModel.PAD1,8);}
|
||||
return QRCodeModel.createBytes(buffer,rsBlocks);};QRCodeModel.createBytes=function(buffer,rsBlocks){var offset=0;var maxDcCount=0;var maxEcCount=0;var dcdata=new Array(rsBlocks.length);var ecdata=new Array(rsBlocks.length);for(var r=0;r<rsBlocks.length;r++){var dcCount=rsBlocks[r].dataCount;var ecCount=rsBlocks[r].totalCount-dcCount;maxDcCount=Math.max(maxDcCount,dcCount);maxEcCount=Math.max(maxEcCount,ecCount);dcdata[r]=new Array(dcCount);for(var i=0;i<dcdata[r].length;i++){dcdata[r][i]=0xff&buffer.buffer[i+offset];}
|
||||
offset+=dcCount;var rsPoly=QRUtil.getErrorCorrectPolynomial(ecCount);var rawPoly=new QRPolynomial(dcdata[r],rsPoly.getLength()-1);var modPoly=rawPoly.mod(rsPoly);ecdata[r]=new Array(rsPoly.getLength()-1);for(var i=0;i<ecdata[r].length;i++){var modIndex=i+modPoly.getLength()-ecdata[r].length;ecdata[r][i]=(modIndex>=0)?modPoly.get(modIndex):0;}}
|
||||
var totalCodeCount=0;for(var i=0;i<rsBlocks.length;i++){totalCodeCount+=rsBlocks[i].totalCount;}
|
||||
var data=new Array(totalCodeCount);var index=0;for(var i=0;i<maxDcCount;i++){for(var r=0;r<rsBlocks.length;r++){if(i<dcdata[r].length){data[index++]=dcdata[r][i];}}}
|
||||
for(var i=0;i<maxEcCount;i++){for(var r=0;r<rsBlocks.length;r++){if(i<ecdata[r].length){data[index++]=ecdata[r][i];}}}
|
||||
return data;};var QRMode={MODE_NUMBER:1<<0,MODE_ALPHA_NUM:1<<1,MODE_8BIT_BYTE:1<<2,MODE_KANJI:1<<3};var QRErrorCorrectLevel={L:1,M:0,Q:3,H:2};var QRMaskPattern={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var QRUtil={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:(1<<10)|(1<<8)|(1<<5)|(1<<4)|(1<<2)|(1<<1)|(1<<0),G18:(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<5)|(1<<2)|(1<<0),G15_MASK:(1<<14)|(1<<12)|(1<<10)|(1<<4)|(1<<1),getBCHTypeInfo:function(data){var d=data<<10;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)>=0){d^=(QRUtil.G15<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)));}
|
||||
return((data<<10)|d)^QRUtil.G15_MASK;},getBCHTypeNumber:function(data){var d=data<<12;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)>=0){d^=(QRUtil.G18<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)));}
|
||||
return(data<<12)|d;},getBCHDigit:function(data){var digit=0;while(data!=0){digit++;data>>>=1;}
|
||||
return digit;},getPatternPosition:function(typeNumber){return QRUtil.PATTERN_POSITION_TABLE[typeNumber-1];},getMask:function(maskPattern,i,j){switch(maskPattern){case QRMaskPattern.PATTERN000:return(i+j)%2==0;case QRMaskPattern.PATTERN001:return i%2==0;case QRMaskPattern.PATTERN010:return j%3==0;case QRMaskPattern.PATTERN011:return(i+j)%3==0;case QRMaskPattern.PATTERN100:return(Math.floor(i/2)+Math.floor(j/3))%2==0;case QRMaskPattern.PATTERN101:return(i*j)%2+(i*j)%3==0;case QRMaskPattern.PATTERN110:return((i*j)%2+(i*j)%3)%2==0;case QRMaskPattern.PATTERN111:return((i*j)%3+(i+j)%2)%2==0;default:throw new Error("bad maskPattern:"+maskPattern);}},getErrorCorrectPolynomial:function(errorCorrectLength){var a=new QRPolynomial([1],0);for(var i=0;i<errorCorrectLength;i++){a=a.multiply(new QRPolynomial([1,QRMath.gexp(i)],0));}
|
||||
return a;},getLengthInBits:function(mode,type){if(1<=type&&type<10){switch(mode){case QRMode.MODE_NUMBER:return 10;case QRMode.MODE_ALPHA_NUM:return 9;case QRMode.MODE_8BIT_BYTE:return 8;case QRMode.MODE_KANJI:return 8;default:throw new Error("mode:"+mode);}}else if(type<27){switch(mode){case QRMode.MODE_NUMBER:return 12;case QRMode.MODE_ALPHA_NUM:return 11;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 10;default:throw new Error("mode:"+mode);}}else if(type<41){switch(mode){case QRMode.MODE_NUMBER:return 14;case QRMode.MODE_ALPHA_NUM:return 13;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 12;default:throw new Error("mode:"+mode);}}else{throw new Error("type:"+type);}},getLostPoint:function(qrCode){var moduleCount=qrCode.getModuleCount();var lostPoint=0;for(var row=0;row<moduleCount;row++){for(var col=0;col<moduleCount;col++){var sameCount=0;var dark=qrCode.isDark(row,col);for(var r=-1;r<=1;r++){if(row+r<0||moduleCount<=row+r){continue;}
|
||||
for(var c=-1;c<=1;c++){if(col+c<0||moduleCount<=col+c){continue;}
|
||||
if(r==0&&c==0){continue;}
|
||||
if(dark==qrCode.isDark(row+r,col+c)){sameCount++;}}}
|
||||
if(sameCount>5){lostPoint+=(3+sameCount-5);}}}
|
||||
for(var row=0;row<moduleCount-1;row++){for(var col=0;col<moduleCount-1;col++){var count=0;if(qrCode.isDark(row,col))count++;if(qrCode.isDark(row+1,col))count++;if(qrCode.isDark(row,col+1))count++;if(qrCode.isDark(row+1,col+1))count++;if(count==0||count==4){lostPoint+=3;}}}
|
||||
for(var row=0;row<moduleCount;row++){for(var col=0;col<moduleCount-6;col++){if(qrCode.isDark(row,col)&&!qrCode.isDark(row,col+1)&&qrCode.isDark(row,col+2)&&qrCode.isDark(row,col+3)&&qrCode.isDark(row,col+4)&&!qrCode.isDark(row,col+5)&&qrCode.isDark(row,col+6)){lostPoint+=40;}}}
|
||||
for(var col=0;col<moduleCount;col++){for(var row=0;row<moduleCount-6;row++){if(qrCode.isDark(row,col)&&!qrCode.isDark(row+1,col)&&qrCode.isDark(row+2,col)&&qrCode.isDark(row+3,col)&&qrCode.isDark(row+4,col)&&!qrCode.isDark(row+5,col)&&qrCode.isDark(row+6,col)){lostPoint+=40;}}}
|
||||
var darkCount=0;for(var col=0;col<moduleCount;col++){for(var row=0;row<moduleCount;row++){if(qrCode.isDark(row,col)){darkCount++;}}}
|
||||
var ratio=Math.abs(100*darkCount/moduleCount/moduleCount-50)/5;lostPoint+=ratio*10;return lostPoint;}};var QRMath={glog:function(n){if(n<1){throw new Error("glog("+n+")");}
|
||||
return QRMath.LOG_TABLE[n];},gexp:function(n){while(n<0){n+=255;}
|
||||
while(n>=256){n-=255;}
|
||||
return QRMath.EXP_TABLE[n];},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)};for(var i=0;i<8;i++){QRMath.EXP_TABLE[i]=1<<i;}
|
||||
for(var i=8;i<256;i++){QRMath.EXP_TABLE[i]=QRMath.EXP_TABLE[i-4]^QRMath.EXP_TABLE[i-5]^QRMath.EXP_TABLE[i-6]^QRMath.EXP_TABLE[i-8];}
|
||||
for(var i=0;i<255;i++){QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]]=i;}
|
||||
function QRPolynomial(num,shift){if(num.length==undefined){throw new Error(num.length+"/"+shift);}
|
||||
var offset=0;while(offset<num.length&&num[offset]==0){offset++;}
|
||||
this.num=new Array(num.length-offset+shift);for(var i=0;i<num.length-offset;i++){this.num[i]=num[i+offset];}}
|
||||
QRPolynomial.prototype={get:function(index){return this.num[index];},getLength:function(){return this.num.length;},multiply:function(e){var num=new Array(this.getLength()+e.getLength()-1);for(var i=0;i<this.getLength();i++){for(var j=0;j<e.getLength();j++){num[i+j]^=QRMath.gexp(QRMath.glog(this.get(i))+QRMath.glog(e.get(j)));}}
|
||||
return new QRPolynomial(num,0);},mod:function(e){if(this.getLength()-e.getLength()<0){return this;}
|
||||
var ratio=QRMath.glog(this.get(0))-QRMath.glog(e.get(0));var num=new Array(this.getLength());for(var i=0;i<this.getLength();i++){num[i]=this.get(i);}
|
||||
for(var i=0;i<e.getLength();i++){num[i]^=QRMath.gexp(QRMath.glog(e.get(i))+ratio);}
|
||||
return new QRPolynomial(num,0).mod(e);}};function QRRSBlock(totalCount,dataCount){this.totalCount=totalCount;this.dataCount=dataCount;}
|
||||
QRRSBlock.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]];QRRSBlock.getRSBlocks=function(typeNumber,errorCorrectLevel){var rsBlock=QRRSBlock.getRsBlockTable(typeNumber,errorCorrectLevel);if(rsBlock==undefined){throw new Error("bad rs block @ typeNumber:"+typeNumber+"/errorCorrectLevel:"+errorCorrectLevel);}
|
||||
var length=rsBlock.length/3;var list=[];for(var i=0;i<length;i++){var count=rsBlock[i*3+0];var totalCount=rsBlock[i*3+1];var dataCount=rsBlock[i*3+2];for(var j=0;j<count;j++){list.push(new QRRSBlock(totalCount,dataCount));}}
|
||||
return list;};QRRSBlock.getRsBlockTable=function(typeNumber,errorCorrectLevel){switch(errorCorrectLevel){case QRErrorCorrectLevel.L:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+0];case QRErrorCorrectLevel.M:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+1];case QRErrorCorrectLevel.Q:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+2];case QRErrorCorrectLevel.H:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+3];default:return undefined;}};function QRBitBuffer(){this.buffer=[];this.length=0;}
|
||||
QRBitBuffer.prototype={get:function(index){var bufIndex=Math.floor(index/8);return((this.buffer[bufIndex]>>>(7-index%8))&1)==1;},put:function(num,length){for(var i=0;i<length;i++){this.putBit(((num>>>(length-i-1))&1)==1);}},getLengthInBits:function(){return this.length;},putBit:function(bit){var bufIndex=Math.floor(this.length/8);if(this.buffer.length<=bufIndex){this.buffer.push(0);}
|
||||
if(bit){this.buffer[bufIndex]|=(0x80>>>(this.length%8));}
|
||||
this.length++;}};var QRCodeLimitLength=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]];
|
||||
|
||||
function _isSupportCanvas() {
|
||||
return typeof CanvasRenderingContext2D != "undefined";
|
||||
}
|
||||
|
||||
// android 2.x doesn't support Data-URI spec
|
||||
function _getAndroid() {
|
||||
var android = false;
|
||||
var sAgent = navigator.userAgent;
|
||||
|
||||
if (/android/i.test(sAgent)) { // android
|
||||
android = true;
|
||||
var aMat = sAgent.toString().match(/android ([0-9]\.[0-9])/i);
|
||||
|
||||
if (aMat && aMat[1]) {
|
||||
android = parseFloat(aMat[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return android;
|
||||
}
|
||||
|
||||
var svgDrawer = (function() {
|
||||
|
||||
var Drawing = function (el, htOption) {
|
||||
this._el = el;
|
||||
this._htOption = htOption;
|
||||
};
|
||||
|
||||
Drawing.prototype.draw = function (oQRCode) {
|
||||
var _htOption = this._htOption;
|
||||
var _el = this._el;
|
||||
var nCount = oQRCode.getModuleCount();
|
||||
var nWidth = Math.floor(_htOption.width / nCount);
|
||||
var nHeight = Math.floor(_htOption.height / nCount);
|
||||
|
||||
this.clear();
|
||||
|
||||
function makeSVG(tag, attrs) {
|
||||
var el = document.createElementNS('http://www.w3.org/2000/svg', tag);
|
||||
for (var k in attrs)
|
||||
if (attrs.hasOwnProperty(k)) el.setAttribute(k, attrs[k]);
|
||||
return el;
|
||||
}
|
||||
|
||||
var svg = makeSVG("svg" , {'viewBox': '0 0 ' + String(nCount) + " " + String(nCount), 'width': '100%', 'height': '100%', 'fill': _htOption.colorLight});
|
||||
svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
|
||||
_el.appendChild(svg);
|
||||
|
||||
svg.appendChild(makeSVG("rect", {"fill": _htOption.colorLight, "width": "100%", "height": "100%"}));
|
||||
svg.appendChild(makeSVG("rect", {"fill": _htOption.colorDark, "width": "1", "height": "1", "id": "template"}));
|
||||
|
||||
for (var row = 0; row < nCount; row++) {
|
||||
for (var col = 0; col < nCount; col++) {
|
||||
if (oQRCode.isDark(row, col)) {
|
||||
var child = makeSVG("use", {"x": String(col), "y": String(row)});
|
||||
child.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#template")
|
||||
svg.appendChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Drawing.prototype.clear = function () {
|
||||
while (this._el.hasChildNodes())
|
||||
this._el.removeChild(this._el.lastChild);
|
||||
};
|
||||
return Drawing;
|
||||
})();
|
||||
|
||||
var useSVG = document.documentElement.tagName.toLowerCase() === "svg";
|
||||
|
||||
// Drawing in DOM by using Table tag
|
||||
var Drawing = useSVG ? svgDrawer : !_isSupportCanvas() ? (function () {
|
||||
var Drawing = function (el, htOption) {
|
||||
this._el = el;
|
||||
this._htOption = htOption;
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw the QRCode
|
||||
*
|
||||
* @param {QRCode} oQRCode
|
||||
*/
|
||||
Drawing.prototype.draw = function (oQRCode) {
|
||||
var _htOption = this._htOption;
|
||||
var _el = this._el;
|
||||
var nCount = oQRCode.getModuleCount();
|
||||
var nWidth = Math.floor(_htOption.width / nCount);
|
||||
var nHeight = Math.floor(_htOption.height / nCount);
|
||||
var aHTML = ['<table style="border:0;border-collapse:collapse;">'];
|
||||
|
||||
for (var row = 0; row < nCount; row++) {
|
||||
aHTML.push('<tr>');
|
||||
|
||||
for (var col = 0; col < nCount; col++) {
|
||||
aHTML.push('<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:' + nWidth + 'px;height:' + nHeight + 'px;background-color:' + (oQRCode.isDark(row, col) ? _htOption.colorDark : _htOption.colorLight) + ';"></td>');
|
||||
}
|
||||
|
||||
aHTML.push('</tr>');
|
||||
}
|
||||
|
||||
aHTML.push('</table>');
|
||||
_el.innerHTML = aHTML.join('');
|
||||
|
||||
// Fix the margin values as real size.
|
||||
var elTable = _el.childNodes[0];
|
||||
var nLeftMarginTable = (_htOption.width - elTable.offsetWidth) / 2;
|
||||
var nTopMarginTable = (_htOption.height - elTable.offsetHeight) / 2;
|
||||
|
||||
if (nLeftMarginTable > 0 && nTopMarginTable > 0) {
|
||||
elTable.style.margin = nTopMarginTable + "px " + nLeftMarginTable + "px";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the QRCode
|
||||
*/
|
||||
Drawing.prototype.clear = function () {
|
||||
this._el.innerHTML = '';
|
||||
};
|
||||
|
||||
return Drawing;
|
||||
})() : (function () { // Drawing in Canvas
|
||||
function _onMakeImage() {
|
||||
this._elImage.src = this._elCanvas.toDataURL("image/png");
|
||||
this._elImage.style.display = "block";
|
||||
this._elCanvas.style.display = "none";
|
||||
}
|
||||
|
||||
// Android 2.1 bug workaround
|
||||
// http://code.google.com/p/android/issues/detail?id=5141
|
||||
if (this._android && this._android <= 2.1) {
|
||||
var factor = 1 / window.devicePixelRatio;
|
||||
var drawImage = CanvasRenderingContext2D.prototype.drawImage;
|
||||
CanvasRenderingContext2D.prototype.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) {
|
||||
if (("nodeName" in image) && /img/i.test(image.nodeName)) {
|
||||
for (var i = arguments.length - 1; i >= 1; i--) {
|
||||
arguments[i] = arguments[i] * factor;
|
||||
}
|
||||
} else if (typeof dw == "undefined") {
|
||||
arguments[1] *= factor;
|
||||
arguments[2] *= factor;
|
||||
arguments[3] *= factor;
|
||||
arguments[4] *= factor;
|
||||
}
|
||||
|
||||
drawImage.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the user's browser supports Data URI or not
|
||||
*
|
||||
* @private
|
||||
* @param {Function} fSuccess Occurs if it supports Data URI
|
||||
* @param {Function} fFail Occurs if it doesn't support Data URI
|
||||
*/
|
||||
function _safeSetDataURI(fSuccess, fFail) {
|
||||
var self = this;
|
||||
self._fFail = fFail;
|
||||
self._fSuccess = fSuccess;
|
||||
|
||||
// Check it just once
|
||||
if (self._bSupportDataURI === null) {
|
||||
var el = document.createElement("img");
|
||||
var fOnError = function() {
|
||||
self._bSupportDataURI = false;
|
||||
|
||||
if (self._fFail) {
|
||||
self._fFail.call(self);
|
||||
}
|
||||
};
|
||||
var fOnSuccess = function() {
|
||||
self._bSupportDataURI = true;
|
||||
|
||||
if (self._fSuccess) {
|
||||
self._fSuccess.call(self);
|
||||
}
|
||||
};
|
||||
|
||||
el.onabort = fOnError;
|
||||
el.onerror = fOnError;
|
||||
el.onload = fOnSuccess;
|
||||
el.src = "data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; // the Image contains 1px data.
|
||||
return;
|
||||
} else if (self._bSupportDataURI === true && self._fSuccess) {
|
||||
self._fSuccess.call(self);
|
||||
} else if (self._bSupportDataURI === false && self._fFail) {
|
||||
self._fFail.call(self);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Drawing QRCode by using canvas
|
||||
*
|
||||
* @constructor
|
||||
* @param {HTMLElement} el
|
||||
* @param {Object} htOption QRCode Options
|
||||
*/
|
||||
var Drawing = function (el, htOption) {
|
||||
this._bIsPainted = false;
|
||||
this._android = _getAndroid();
|
||||
|
||||
this._htOption = htOption;
|
||||
this._elCanvas = document.createElement("canvas");
|
||||
this._elCanvas.width = htOption.width;
|
||||
this._elCanvas.height = htOption.height;
|
||||
el.appendChild(this._elCanvas);
|
||||
this._el = el;
|
||||
this._oContext = this._elCanvas.getContext("2d");
|
||||
this._bIsPainted = false;
|
||||
this._elImage = document.createElement("img");
|
||||
this._elImage.alt = "Scan me!";
|
||||
this._elImage.style.display = "none";
|
||||
this._el.appendChild(this._elImage);
|
||||
this._bSupportDataURI = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw the QRCode
|
||||
*
|
||||
* @param {QRCode} oQRCode
|
||||
*/
|
||||
Drawing.prototype.draw = function (oQRCode) {
|
||||
var _elImage = this._elImage;
|
||||
var _oContext = this._oContext;
|
||||
var _htOption = this._htOption;
|
||||
|
||||
var nCount = oQRCode.getModuleCount();
|
||||
var nWidth = _htOption.width / nCount;
|
||||
var nHeight = _htOption.height / nCount;
|
||||
var nRoundedWidth = Math.round(nWidth);
|
||||
var nRoundedHeight = Math.round(nHeight);
|
||||
|
||||
_elImage.style.display = "none";
|
||||
this.clear();
|
||||
|
||||
for (var row = 0; row < nCount; row++) {
|
||||
for (var col = 0; col < nCount; col++) {
|
||||
var bIsDark = oQRCode.isDark(row, col);
|
||||
var nLeft = col * nWidth;
|
||||
var nTop = row * nHeight;
|
||||
_oContext.strokeStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight;
|
||||
_oContext.lineWidth = 1;
|
||||
_oContext.fillStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight;
|
||||
_oContext.fillRect(nLeft, nTop, nWidth, nHeight);
|
||||
|
||||
// 안티 앨리어싱 방지 처리
|
||||
_oContext.strokeRect(
|
||||
Math.floor(nLeft) + 0.5,
|
||||
Math.floor(nTop) + 0.5,
|
||||
nRoundedWidth,
|
||||
nRoundedHeight
|
||||
);
|
||||
|
||||
_oContext.strokeRect(
|
||||
Math.ceil(nLeft) - 0.5,
|
||||
Math.ceil(nTop) - 0.5,
|
||||
nRoundedWidth,
|
||||
nRoundedHeight
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this._bIsPainted = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Make the image from Canvas if the browser supports Data URI.
|
||||
*/
|
||||
Drawing.prototype.makeImage = function () {
|
||||
if (this._bIsPainted) {
|
||||
_safeSetDataURI.call(this, _onMakeImage);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return whether the QRCode is painted or not
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Drawing.prototype.isPainted = function () {
|
||||
return this._bIsPainted;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the QRCode
|
||||
*/
|
||||
Drawing.prototype.clear = function () {
|
||||
this._oContext.clearRect(0, 0, this._elCanvas.width, this._elCanvas.height);
|
||||
this._bIsPainted = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Number} nNumber
|
||||
*/
|
||||
Drawing.prototype.round = function (nNumber) {
|
||||
if (!nNumber) {
|
||||
return nNumber;
|
||||
}
|
||||
|
||||
return Math.floor(nNumber * 1000) / 1000;
|
||||
};
|
||||
|
||||
return Drawing;
|
||||
})();
|
||||
|
||||
/**
|
||||
* Get the type by string length
|
||||
*
|
||||
* @private
|
||||
* @param {String} sText
|
||||
* @param {Number} nCorrectLevel
|
||||
* @return {Number} type
|
||||
*/
|
||||
function _getTypeNumber(sText, nCorrectLevel) {
|
||||
var nType = 1;
|
||||
var length = _getUTF8Length(sText);
|
||||
|
||||
for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
|
||||
var nLimit = 0;
|
||||
|
||||
switch (nCorrectLevel) {
|
||||
case QRErrorCorrectLevel.L :
|
||||
nLimit = QRCodeLimitLength[i][0];
|
||||
break;
|
||||
case QRErrorCorrectLevel.M :
|
||||
nLimit = QRCodeLimitLength[i][1];
|
||||
break;
|
||||
case QRErrorCorrectLevel.Q :
|
||||
nLimit = QRCodeLimitLength[i][2];
|
||||
break;
|
||||
case QRErrorCorrectLevel.H :
|
||||
nLimit = QRCodeLimitLength[i][3];
|
||||
break;
|
||||
}
|
||||
|
||||
if (length <= nLimit) {
|
||||
break;
|
||||
} else {
|
||||
nType++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nType > QRCodeLimitLength.length) {
|
||||
throw new Error("Too long data");
|
||||
}
|
||||
|
||||
return nType;
|
||||
}
|
||||
|
||||
function _getUTF8Length(sText) {
|
||||
var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a');
|
||||
return replacedText.length + (replacedText.length != sText ? 3 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @class QRCode
|
||||
* @constructor
|
||||
* @example
|
||||
* new QRCode(document.getElementById("test"), "http://jindo.dev.naver.com/collie");
|
||||
*
|
||||
* @example
|
||||
* var oQRCode = new QRCode("test", {
|
||||
* text : "http://naver.com",
|
||||
* width : 128,
|
||||
* height : 128
|
||||
* });
|
||||
*
|
||||
* oQRCode.clear(); // Clear the QRCode.
|
||||
* oQRCode.makeCode("http://map.naver.com"); // Re-create the QRCode.
|
||||
*
|
||||
* @param {HTMLElement|String} el target element or 'id' attribute of element.
|
||||
* @param {Object|String} vOption
|
||||
* @param {String} vOption.text QRCode link data
|
||||
* @param {Number} [vOption.width=256]
|
||||
* @param {Number} [vOption.height=256]
|
||||
* @param {String} [vOption.colorDark="#000000"]
|
||||
* @param {String} [vOption.colorLight="#ffffff"]
|
||||
* @param {QRCode.CorrectLevel} [vOption.correctLevel=QRCode.CorrectLevel.H] [L|M|Q|H]
|
||||
*/
|
||||
QRCode = function (el, vOption) {
|
||||
this._htOption = {
|
||||
width : 256,
|
||||
height : 256,
|
||||
typeNumber : 4,
|
||||
colorDark : "#000000",
|
||||
colorLight : "#ffffff",
|
||||
correctLevel : QRErrorCorrectLevel.H
|
||||
};
|
||||
|
||||
if (typeof vOption === 'string') {
|
||||
vOption = {
|
||||
text : vOption
|
||||
};
|
||||
}
|
||||
|
||||
// Overwrites options
|
||||
if (vOption) {
|
||||
for (var i in vOption) {
|
||||
this._htOption[i] = vOption[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof el == "string") {
|
||||
el = document.getElementById(el);
|
||||
}
|
||||
|
||||
if (this._htOption.useSVG) {
|
||||
Drawing = svgDrawer;
|
||||
}
|
||||
|
||||
this._android = _getAndroid();
|
||||
this._el = el;
|
||||
this._oQRCode = null;
|
||||
this._oDrawing = new Drawing(this._el, this._htOption);
|
||||
|
||||
if (this._htOption.text) {
|
||||
this.makeCode(this._htOption.text);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Make the QRCode
|
||||
*
|
||||
* @param {String} sText link data
|
||||
*/
|
||||
QRCode.prototype.makeCode = function (sText) {
|
||||
this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel);
|
||||
this._oQRCode.addData(sText);
|
||||
this._oQRCode.make();
|
||||
this._el.title = sText;
|
||||
this._oDrawing.draw(this._oQRCode);
|
||||
this.makeImage();
|
||||
};
|
||||
|
||||
/**
|
||||
* Make the Image from Canvas element
|
||||
* - It occurs automatically
|
||||
* - Android below 3 doesn't support Data-URI spec.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
QRCode.prototype.makeImage = function () {
|
||||
if (typeof this._oDrawing.makeImage == "function" && (!this._android || this._android >= 3)) {
|
||||
this._oDrawing.makeImage();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the QRCode
|
||||
*/
|
||||
QRCode.prototype.clear = function () {
|
||||
this._oDrawing.clear();
|
||||
};
|
||||
|
||||
/**
|
||||
* @name QRCode.CorrectLevel
|
||||
*/
|
||||
QRCode.CorrectLevel = QRErrorCorrectLevel;
|
||||
})();
|
|
@ -0,0 +1,13 @@
|
|||
$(document).on 'turbolinks:load', ->
|
||||
|
||||
if $('#qrcode-home').length > 0
|
||||
$('#qrcode-home').empty()
|
||||
new QRCode( $('#qrcode-home')[0], $('#qrcode-home').data('url') )
|
||||
|
||||
if $('#image-tag').length > 0
|
||||
$('#image-tag').empty()
|
||||
new QRCode( $('#image-tag')[0], $('#image-tag').data('url') )
|
||||
|
||||
$('#qrcode-link').click (event)->
|
||||
event.preventDefault()
|
||||
$('.social-share').toggle()
|
|
@ -0,0 +1,567 @@
|
|||
// Foundation for Sites Settings
|
||||
// -----------------------------
|
||||
//
|
||||
// Table of Contents:
|
||||
//
|
||||
// 1. Global
|
||||
// 2. Breakpoints
|
||||
// 3. The Grid
|
||||
// 4. Base Typography
|
||||
// 5. Typography Helpers
|
||||
// 6. Abide
|
||||
// 7. Accordion
|
||||
// 8. Accordion Menu
|
||||
// 9. Badge
|
||||
// 10. Breadcrumbs
|
||||
// 11. Button
|
||||
// 12. Button Group
|
||||
// 13. Callout
|
||||
// 14. Close Button
|
||||
// 15. Drilldown
|
||||
// 16. Dropdown
|
||||
// 17. Dropdown Menu
|
||||
// 18. Flex Video
|
||||
// 19. Forms
|
||||
// 20. Label
|
||||
// 21. Media Object
|
||||
// 22. Menu
|
||||
// 23. Meter
|
||||
// 24. Off-canvas
|
||||
// 25. Orbit
|
||||
// 26. Pagination
|
||||
// 27. Progress Bar
|
||||
// 28. Reveal
|
||||
// 29. Slider
|
||||
// 30. Switch
|
||||
// 31. Table
|
||||
// 32. Tabs
|
||||
// 33. Thumbnail
|
||||
// 34. Title Bar
|
||||
// 35. Tooltip
|
||||
// 36. Top Bar
|
||||
|
||||
@import 'util/util';
|
||||
|
||||
// 1. Global
|
||||
// ---------
|
||||
|
||||
$global-font-size: 100%;
|
||||
$global-width: rem-calc(1200);
|
||||
$global-lineheight: 1.5;
|
||||
$foundation-palette: (
|
||||
primary: #2199e8,
|
||||
secondary: #777,
|
||||
success: #3adb76,
|
||||
warning: #ffae00,
|
||||
alert: #ec5840,
|
||||
);
|
||||
$light-gray: #e6e6e6;
|
||||
$medium-gray: #cacaca;
|
||||
$dark-gray: #8a8a8a;
|
||||
$black: #0a0a0a;
|
||||
$white: #fefefe;
|
||||
$body-background: $white;
|
||||
$body-font-color: $black;
|
||||
$body-font-family: 'Helvetica Neue', 'Microsoft Yahei', Helvetica, Roboto, 'WenQuanYi Micro Hei', Arial, sans-serif;
|
||||
$body-antialiased: true;
|
||||
$global-margin: 1rem;
|
||||
$global-padding: 1rem;
|
||||
$global-weight-normal: normal;
|
||||
$global-weight-bold: bold;
|
||||
$global-radius: 0;
|
||||
$global-text-direction: ltr;
|
||||
$global-flexbox: false;
|
||||
$print-transparent-backgrounds: true;
|
||||
|
||||
@include add-foundation-colors;
|
||||
|
||||
// 2. Breakpoints
|
||||
// --------------
|
||||
|
||||
$breakpoints: (
|
||||
small: 0,
|
||||
medium: 640px,
|
||||
large: 1024px,
|
||||
xlarge: 1200px,
|
||||
xxlarge: 1440px,
|
||||
);
|
||||
$breakpoint-classes: (small medium large);
|
||||
|
||||
// 3. The Grid
|
||||
// -----------
|
||||
|
||||
$grid-row-width: $global-width;
|
||||
$grid-column-count: 12;
|
||||
$grid-column-gutter: (
|
||||
small: 20px,
|
||||
medium: 30px,
|
||||
);
|
||||
$grid-column-align-edge: true;
|
||||
$block-grid-max: 8;
|
||||
|
||||
// 4. Base Typography
|
||||
// ------------------
|
||||
|
||||
$header-font-family: $body-font-family;
|
||||
$header-font-weight: $global-weight-normal;
|
||||
$header-font-style: normal;
|
||||
$font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace;
|
||||
$header-sizes: (
|
||||
small: (
|
||||
'h1': 24,
|
||||
'h2': 20,
|
||||
'h3': 19,
|
||||
'h4': 18,
|
||||
'h5': 17,
|
||||
'h6': 16,
|
||||
),
|
||||
medium: (
|
||||
'h1': 48,
|
||||
'h2': 40,
|
||||
'h3': 31,
|
||||
'h4': 25,
|
||||
'h5': 20,
|
||||
'h6': 16,
|
||||
),
|
||||
);
|
||||
$header-color: inherit;
|
||||
$header-lineheight: 1.4;
|
||||
$header-margin-bottom: 0.5rem;
|
||||
$header-text-rendering: optimizeLegibility;
|
||||
$small-font-size: 80%;
|
||||
$header-small-font-color: $medium-gray;
|
||||
$paragraph-lineheight: 1.6;
|
||||
$paragraph-margin-bottom: 1rem;
|
||||
$paragraph-text-rendering: optimizeLegibility;
|
||||
$code-color: $black;
|
||||
$code-font-family: $font-family-monospace;
|
||||
$code-font-weight: $global-weight-normal;
|
||||
$code-background: $light-gray;
|
||||
$code-border: 1px solid $medium-gray;
|
||||
$code-padding: rem-calc(2 5 1);
|
||||
$anchor-color: $primary-color;
|
||||
$anchor-color-hover: scale-color($anchor-color, $lightness: -14%);
|
||||
$anchor-text-decoration: none;
|
||||
$anchor-text-decoration-hover: none;
|
||||
$hr-width: $global-width;
|
||||
$hr-border: 1px solid $medium-gray;
|
||||
$hr-margin: rem-calc(20) auto;
|
||||
$list-lineheight: $paragraph-lineheight;
|
||||
$list-margin-bottom: $paragraph-margin-bottom;
|
||||
$list-style-type: disc;
|
||||
$list-style-position: outside;
|
||||
$list-side-margin: 1.25rem;
|
||||
$list-nested-side-margin: 1.25rem;
|
||||
$defnlist-margin-bottom: 1rem;
|
||||
$defnlist-term-weight: $global-weight-bold;
|
||||
$defnlist-term-margin-bottom: 0.3rem;
|
||||
$blockquote-color: $dark-gray;
|
||||
$blockquote-padding: rem-calc(9 20 0 19);
|
||||
$blockquote-border: 1px solid $medium-gray;
|
||||
$cite-font-size: rem-calc(13);
|
||||
$cite-color: $dark-gray;
|
||||
$keystroke-font: $font-family-monospace;
|
||||
$keystroke-color: $black;
|
||||
$keystroke-background: $light-gray;
|
||||
$keystroke-padding: rem-calc(2 4 0);
|
||||
$keystroke-radius: $global-radius;
|
||||
$abbr-underline: 1px dotted $black;
|
||||
|
||||
// 5. Typography Helpers
|
||||
// ---------------------
|
||||
|
||||
$lead-font-size: $global-font-size * 1.25;
|
||||
$lead-lineheight: 1.6;
|
||||
$subheader-lineheight: 1.4;
|
||||
$subheader-color: $dark-gray;
|
||||
$subheader-font-weight: $global-weight-normal;
|
||||
$subheader-margin-top: 0.2rem;
|
||||
$subheader-margin-bottom: 0.5rem;
|
||||
$stat-font-size: 2.5rem;
|
||||
|
||||
// 6. Abide
|
||||
// --------
|
||||
|
||||
$abide-inputs: true;
|
||||
$abide-labels: true;
|
||||
$input-background-invalid: map-get($foundation-palette, alert);
|
||||
$form-label-color-invalid: map-get($foundation-palette, alert);
|
||||
$input-error-color: map-get($foundation-palette, alert);
|
||||
$input-error-font-size: rem-calc(12);
|
||||
$input-error-font-weight: $global-weight-bold;
|
||||
|
||||
// 7. Accordion
|
||||
// ------------
|
||||
|
||||
$accordion-background: $white;
|
||||
$accordion-plusminus: true;
|
||||
$accordion-item-color: foreground($accordion-background, $primary-color);
|
||||
$accordion-item-background-hover: $light-gray;
|
||||
$accordion-item-padding: 1.25rem 1rem;
|
||||
$accordion-content-background: $white;
|
||||
$accordion-content-border: 1px solid $light-gray;
|
||||
$accordion-content-color: foreground($accordion-background, $primary-color);
|
||||
$accordion-content-padding: 1rem;
|
||||
|
||||
// 8. Accordion Menu
|
||||
// -----------------
|
||||
|
||||
$accordionmenu-arrows: true;
|
||||
$accordionmenu-arrow-color: $primary-color;
|
||||
|
||||
// 9. Badge
|
||||
// --------
|
||||
|
||||
$badge-background: $primary-color;
|
||||
$badge-color: foreground($badge-background);
|
||||
$badge-padding: 0.3em;
|
||||
$badge-minwidth: 2.1em;
|
||||
$badge-font-size: 0.6rem;
|
||||
|
||||
// 10. Breadcrumbs
|
||||
// ---------------
|
||||
|
||||
$breadcrumbs-margin: 0 0 $global-margin 0;
|
||||
$breadcrumbs-item-font-size: rem-calc(11);
|
||||
$breadcrumbs-item-color: $primary-color;
|
||||
$breadcrumbs-item-color-current: $black;
|
||||
$breadcrumbs-item-color-disabled: $medium-gray;
|
||||
$breadcrumbs-item-margin: 0.75rem;
|
||||
$breadcrumbs-item-uppercase: true;
|
||||
$breadcrumbs-item-slash: true;
|
||||
|
||||
// 11. Button
|
||||
// ----------
|
||||
|
||||
$button-padding: 1rem 2rem 1.0625rem 2rem;
|
||||
$button-margin: 0 0 $global-margin 0;
|
||||
$button-fill: solid;
|
||||
$button-background: $primary-color;
|
||||
$button-background-hover: scale-color($button-background, $lightness: -15%);
|
||||
$button-color: $white;
|
||||
$button-color-alt: $black;
|
||||
$button-radius: $global-radius;
|
||||
$button-sizes: (
|
||||
tiny: 0.6rem,
|
||||
small: 0.75rem,
|
||||
default: 0.9rem,
|
||||
large: 1.25rem,
|
||||
);
|
||||
$button-opacity-disabled: 0.25;
|
||||
|
||||
// 12. Button Group
|
||||
// ----------------
|
||||
|
||||
$buttongroup-margin: 1rem;
|
||||
$buttongroup-spacing: 1px;
|
||||
$buttongroup-child-selector: '.button';
|
||||
$buttongroup-expand-max: 6;
|
||||
|
||||
// 13. Callout
|
||||
// -----------
|
||||
|
||||
$callout-background: $white;
|
||||
$callout-background-fade: 85%;
|
||||
$callout-border: 1px solid rgba($black, 0.25);
|
||||
$callout-margin: 0 0 1rem 0;
|
||||
$callout-padding: 1rem;
|
||||
$callout-font-color: $body-font-color;
|
||||
$callout-font-color-alt: $body-background;
|
||||
$callout-radius: $global-radius;
|
||||
$callout-link-tint: 30%;
|
||||
|
||||
// 14. Close Button
|
||||
// ----------------
|
||||
|
||||
$closebutton-position: right top;
|
||||
$closebutton-offset-horizontal: 1rem;
|
||||
$closebutton-offset-vertical: 0.5rem;
|
||||
$closebutton-size: 2em;
|
||||
$closebutton-lineheight: 1;
|
||||
$closebutton-color: $dark-gray;
|
||||
$closebutton-color-hover: $black;
|
||||
|
||||
// 15. Drilldown
|
||||
// -------------
|
||||
|
||||
$drilldown-transition: transform 0.15s linear;
|
||||
$drilldown-arrows: true;
|
||||
$drilldown-arrow-color: $primary-color;
|
||||
$drilldown-background: $white;
|
||||
|
||||
// 16. Dropdown
|
||||
// ------------
|
||||
|
||||
$dropdown-padding: 1rem;
|
||||
$dropdown-border: 1px solid $medium-gray;
|
||||
$dropdown-font-size: 1rem;
|
||||
$dropdown-width: 300px;
|
||||
$dropdown-radius: $global-radius;
|
||||
$dropdown-sizes: (
|
||||
tiny: 100px,
|
||||
small: 200px,
|
||||
large: 400px,
|
||||
);
|
||||
|
||||
// 17. Dropdown Menu
|
||||
// -----------------
|
||||
|
||||
$dropdownmenu-arrows: true;
|
||||
$dropdownmenu-arrow-color: $anchor-color;
|
||||
$dropdownmenu-min-width: 200px;
|
||||
$dropdownmenu-background: $white;
|
||||
$dropdownmenu-border: 1px solid $medium-gray;
|
||||
|
||||
// 18. Flex Video
|
||||
// --------------
|
||||
|
||||
$flexvideo-margin-bottom: rem-calc(16);
|
||||
$flexvideo-ratio: 4 by 3;
|
||||
$flexvideo-ratio-widescreen: 16 by 9;
|
||||
|
||||
// 19. Forms
|
||||
// ---------
|
||||
|
||||
$fieldset-border: 1px solid $medium-gray;
|
||||
$fieldset-padding: rem-calc(20);
|
||||
$fieldset-margin: rem-calc(18 0);
|
||||
$legend-padding: rem-calc(0 3);
|
||||
$form-spacing: rem-calc(16);
|
||||
$helptext-color: $black;
|
||||
$helptext-font-size: rem-calc(13);
|
||||
$helptext-font-style: italic;
|
||||
$input-prefix-color: $black;
|
||||
$input-prefix-background: $light-gray;
|
||||
$input-prefix-border: 1px solid $medium-gray;
|
||||
$input-prefix-padding: 1rem;
|
||||
$form-label-color: $black;
|
||||
$form-label-font-size: rem-calc(14);
|
||||
$form-label-font-weight: $global-weight-normal;
|
||||
$form-label-line-height: 1.8;
|
||||
$select-background: $white;
|
||||
$select-triangle-color: $dark-gray;
|
||||
$select-radius: $global-radius;
|
||||
$input-color: $black;
|
||||
$input-placeholder-color: $medium-gray;
|
||||
$input-font-family: inherit;
|
||||
$input-font-size: rem-calc(16);
|
||||
$input-background: $white;
|
||||
$input-background-focus: $white;
|
||||
$input-background-disabled: $light-gray;
|
||||
$input-border: 1px solid $medium-gray;
|
||||
$input-border-focus: 1px solid $dark-gray;
|
||||
$input-shadow: inset 0 1px 2px rgba($black, 0.1);
|
||||
$input-shadow-focus: 0 0 5px $medium-gray;
|
||||
$input-cursor-disabled: not-allowed;
|
||||
$input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out;
|
||||
$input-number-spinners: true;
|
||||
$input-radius: $global-radius;
|
||||
|
||||
// 20. Label
|
||||
// ---------
|
||||
|
||||
$label-background: $primary-color;
|
||||
$label-color: foreground($label-background);
|
||||
$label-font-size: 0.8rem;
|
||||
$label-padding: 0.33333rem 0.5rem;
|
||||
$label-radius: $global-radius;
|
||||
|
||||
// 21. Media Object
|
||||
// ----------------
|
||||
|
||||
$mediaobject-margin-bottom: $global-margin;
|
||||
$mediaobject-section-padding: $global-padding;
|
||||
$mediaobject-image-width-stacked: 100%;
|
||||
|
||||
// 22. Menu
|
||||
// --------
|
||||
|
||||
$menu-margin: 0;
|
||||
$menu-margin-nested: 1rem;
|
||||
$menu-item-padding: 0.7rem 1rem;
|
||||
$menu-item-color-active: $white;
|
||||
$menu-item-background-active: map-get($foundation-palette, primary);
|
||||
$menu-icon-spacing: 0.25rem;
|
||||
|
||||
// 23. Meter
|
||||
// ---------
|
||||
|
||||
$meter-height: 1rem;
|
||||
$meter-radius: $global-radius;
|
||||
$meter-background: $medium-gray;
|
||||
$meter-fill-good: $success-color;
|
||||
$meter-fill-medium: $warning-color;
|
||||
$meter-fill-bad: $alert-color;
|
||||
|
||||
// 24. Off-canvas
|
||||
// --------------
|
||||
|
||||
$offcanvas-size: 250px;
|
||||
$offcanvas-background: #474747;
|
||||
$offcanvas-zindex: -1;
|
||||
$offcanvas-transition-length: 0.5s;
|
||||
$offcanvas-transition-timing: ease;
|
||||
$offcanvas-fixed-reveal: true;
|
||||
$offcanvas-exit-background: rgba($white, 0.25);
|
||||
$maincontent-class: 'off-canvas-content';
|
||||
$maincontent-shadow: 0 0 10px rgba($black, 0.5);
|
||||
|
||||
// 25. Orbit
|
||||
// ---------
|
||||
|
||||
$orbit-bullet-background: $medium-gray;
|
||||
$orbit-bullet-background-active: $dark-gray;
|
||||
$orbit-bullet-diameter: 1.2rem;
|
||||
$orbit-bullet-margin: 0.1rem;
|
||||
$orbit-bullet-margin-top: 0.8rem;
|
||||
$orbit-bullet-margin-bottom: 0.8rem;
|
||||
$orbit-caption-background: rgba($black, 0.5);
|
||||
$orbit-caption-padding: 1rem;
|
||||
$orbit-control-background-hover: rgba($black, 0.5);
|
||||
$orbit-control-padding: 1rem;
|
||||
$orbit-control-zindex: 10;
|
||||
|
||||
// 26. Pagination
|
||||
// --------------
|
||||
|
||||
$pagination-font-size: rem-calc(14);
|
||||
$pagination-margin-bottom: $global-margin;
|
||||
$pagination-item-color: $black;
|
||||
$pagination-item-padding: rem-calc(3 10);
|
||||
$pagination-item-spacing: rem-calc(1);
|
||||
$pagination-radius: $global-radius;
|
||||
$pagination-item-background-hover: $light-gray;
|
||||
$pagination-item-background-current: $primary-color;
|
||||
$pagination-item-color-current: foreground($pagination-item-background-current);
|
||||
$pagination-item-color-disabled: $medium-gray;
|
||||
$pagination-ellipsis-color: $black;
|
||||
$pagination-mobile-items: false;
|
||||
$pagination-arrows: true;
|
||||
|
||||
// 27. Progress Bar
|
||||
// ----------------
|
||||
|
||||
$progress-height: 1rem;
|
||||
$progress-background: $medium-gray;
|
||||
$progress-margin-bottom: $global-margin;
|
||||
$progress-meter-background: $primary-color;
|
||||
$progress-radius: $global-radius;
|
||||
|
||||
// 28. Reveal
|
||||
// ----------
|
||||
|
||||
$reveal-background: $white;
|
||||
$reveal-width: 600px;
|
||||
$reveal-max-width: $global-width;
|
||||
$reveal-padding: $global-padding;
|
||||
$reveal-border: 1px solid $medium-gray;
|
||||
$reveal-radius: $global-radius;
|
||||
$reveal-zindex: 1005;
|
||||
$reveal-overlay-background: rgba($black, 0.45);
|
||||
|
||||
// 29. Slider
|
||||
// ----------
|
||||
|
||||
$slider-width-vertical: 0.5rem;
|
||||
$slider-transition: all 0.2s ease-in-out;
|
||||
$slider-height: 0.5rem;
|
||||
$slider-background: $light-gray;
|
||||
$slider-fill-background: $medium-gray;
|
||||
$slider-handle-height: 1.4rem;
|
||||
$slider-handle-width: 1.4rem;
|
||||
$slider-handle-background: $primary-color;
|
||||
$slider-opacity-disabled: 0.25;
|
||||
$slider-radius: $global-radius;
|
||||
|
||||
// 30. Switch
|
||||
// ----------
|
||||
|
||||
$switch-background: $medium-gray;
|
||||
$switch-background-active: $primary-color;
|
||||
$switch-height: 2rem;
|
||||
$switch-height-tiny: 1.5rem;
|
||||
$switch-height-small: 1.75rem;
|
||||
$switch-height-large: 2.5rem;
|
||||
$switch-radius: $global-radius;
|
||||
$switch-margin: $global-margin;
|
||||
$switch-paddle-background: $white;
|
||||
$switch-paddle-offset: 0.25rem;
|
||||
$switch-paddle-radius: $global-radius;
|
||||
$switch-paddle-transition: all 0.25s ease-out;
|
||||
|
||||
// 31. Table
|
||||
// ---------
|
||||
|
||||
$table-background: $white;
|
||||
$table-color-scale: 5%;
|
||||
$table-border: 1px solid smart-scale($table-background, $table-color-scale);
|
||||
$table-padding: rem-calc(8 10 10);
|
||||
$table-hover-scale: 2%;
|
||||
$table-row-hover: darken($table-background, $table-hover-scale);
|
||||
$table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale);
|
||||
$table-striped-background: smart-scale($table-background, $table-color-scale);
|
||||
$table-stripe: even;
|
||||
$table-head-background: smart-scale($table-background, $table-color-scale / 2);
|
||||
$table-foot-background: smart-scale($table-background, $table-color-scale);
|
||||
$table-head-font-color: $body-font-color;
|
||||
$show-header-for-stacked: false;
|
||||
|
||||
// 32. Tabs
|
||||
// --------
|
||||
|
||||
$tab-margin: 0;
|
||||
$tab-background: $white;
|
||||
$tab-background-active: $light-gray;
|
||||
$tab-item-font-size: rem-calc(16);
|
||||
$tab-item-background-hover: $white;
|
||||
$tab-item-padding: 1.25rem 1.5rem;
|
||||
$tab-expand-max: 6;
|
||||
$tab-content-background: $white;
|
||||
$tab-content-border: none;
|
||||
$tab-content-color: foreground($tab-background, $primary-color);
|
||||
$tab-content-padding: 1rem;
|
||||
|
||||
// 33. Thumbnail
|
||||
// -------------
|
||||
|
||||
$thumbnail-border: solid 4px $white;
|
||||
$thumbnail-margin-bottom: $global-margin;
|
||||
$thumbnail-shadow: 0 0 0 1px rgba($black, 0.2);
|
||||
$thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5);
|
||||
$thumbnail-transition: box-shadow 200ms ease-out;
|
||||
$thumbnail-radius: $global-radius;
|
||||
|
||||
// 34. Title Bar
|
||||
// -------------
|
||||
|
||||
$titlebar-background: $black;
|
||||
$titlebar-color: $white;
|
||||
$titlebar-padding: 0.5rem;
|
||||
$titlebar-text-font-weight: bold;
|
||||
$titlebar-icon-color: $white;
|
||||
$titlebar-icon-color-hover: $medium-gray;
|
||||
$titlebar-icon-spacing: 0.25rem;
|
||||
|
||||
// 35. Tooltip
|
||||
// -----------
|
||||
|
||||
$has-tip-font-weight: $global-weight-bold;
|
||||
$has-tip-border-bottom: dotted 1px $dark-gray;
|
||||
$tooltip-background-color: $black;
|
||||
$tooltip-color: $white;
|
||||
$tooltip-padding: 0.75rem;
|
||||
$tooltip-font-size: $small-font-size;
|
||||
$tooltip-pip-width: 0.75rem;
|
||||
$tooltip-pip-height: $tooltip-pip-width * 0.866;
|
||||
$tooltip-radius: $global-radius;
|
||||
|
||||
// 36. Top Bar
|
||||
// -----------
|
||||
|
||||
$topbar-padding: 0.5rem;
|
||||
$topbar-background: $black;
|
||||
$topbar-submenu-background: $topbar-background;
|
||||
$topbar-title-spacing: 1rem;
|
||||
$topbar-input-width: 200px;
|
||||
$topbar-unstack-breakpoint: medium;
|
||||
|
|
@ -23,6 +23,14 @@
|
|||
|
||||
|
||||
.about-page {
|
||||
.fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
@ -42,15 +50,19 @@
|
|||
.top-bar {
|
||||
background: 0 0;
|
||||
margin: 1.5rem 0;
|
||||
.name h1 {
|
||||
.name {
|
||||
font-size: 1.325rem;
|
||||
}
|
||||
}
|
||||
|
||||
.top-bar-section ul{
|
||||
.top-bar ul{
|
||||
& {
|
||||
background: 0 0;
|
||||
}
|
||||
li, li a {
|
||||
background: 0 0;
|
||||
font-size: 1rem;
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
li a:hover {
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
.dash-title {
|
||||
padding-top: 2rem;
|
||||
}
|
||||
|
||||
#dashboard-topbar {
|
||||
background-color: $light-gray;
|
||||
ul {
|
||||
background-color: $light-gray;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,14 @@
|
|||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
#post_content {
|
||||
#content-input {
|
||||
min-height: 20rem;
|
||||
}
|
||||
|
||||
.content-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.preview {
|
||||
min-height: 20rem;
|
||||
border: 1px solid #DDDDDD;
|
||||
|
@ -25,7 +29,7 @@
|
|||
|
||||
#upload_photo {
|
||||
float: right;
|
||||
margin-top: 2rem;
|
||||
margin-top: 1.875rem;
|
||||
}
|
||||
|
||||
tr {
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
.ng-dirty .ng-invalid, .ng-dirty .ng-required {
|
||||
border: 1px solid #FF7A7A !important;
|
||||
}
|
|
@ -1,18 +1,22 @@
|
|||
//.inner-wrap {
|
||||
//min-height: 100%;
|
||||
//}
|
||||
|
||||
@import 'font-awesome-sprockets';
|
||||
@import 'font-awesome';
|
||||
@import 'foundation_and_overrides';
|
||||
@import 'foundation-icons';
|
||||
|
||||
@import 'aboutme_welcome';
|
||||
@import 'archives';
|
||||
@import 'aboutme_welcome';
|
||||
@import 'archives';
|
||||
@import 'markdown';
|
||||
@import 'blogs';
|
||||
@import 'head';
|
||||
@import 'blogs';
|
||||
@import 'head';
|
||||
@import 'qrcodes';
|
||||
@import 'angularjs';
|
||||
@import 'comments';
|
||||
@import 'comments';
|
||||
@import 'highlight';
|
||||
@import 'footer';
|
||||
@import 'like_and_weixin';
|
||||
@import 'admin/*';
|
||||
|
||||
.turbolinks-progress-bar {
|
||||
height: 2px;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,10 @@
|
|||
padding-left: 0rem;
|
||||
}
|
||||
|
||||
#qrcode-home {
|
||||
padding: 1rem 2rem 1rem 0;
|
||||
}
|
||||
|
||||
.qrcode {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
|
@ -81,6 +85,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.social-share {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.subscribe-ul {
|
||||
list-style-type: none;
|
||||
margin-left: 0;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#alert-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.comment-field {
|
||||
background-color: #333333;
|
||||
padding-top: 3rem;
|
||||
|
@ -43,14 +47,17 @@
|
|||
color: #b3b3b3;
|
||||
}
|
||||
.comment-content {
|
||||
padding-bottom: 2.275rem;
|
||||
padding-bottom: 1rem;
|
||||
padding-left: 0.275rem;
|
||||
border-bottom: 1px dashed #8a8a8a;
|
||||
margin-bottom: 0;
|
||||
white-space: pre;
|
||||
|
||||
p {
|
||||
margin-bottom: 0.325rem;
|
||||
}
|
||||
}
|
||||
.name {
|
||||
padding-top: 0.5rem;
|
||||
padding-top: 1rem;
|
||||
padding-left: 0.275rem;
|
||||
}
|
||||
}
|
||||
|
@ -75,11 +82,11 @@
|
|||
}
|
||||
|
||||
.comment-wrapper {
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
&:hover {
|
||||
background-color: #444444;
|
||||
}
|
||||
|
||||
|
||||
.name {
|
||||
color: #DDDDDD;
|
||||
}
|
||||
|
@ -87,8 +94,7 @@
|
|||
.comment-content {
|
||||
word-wrap: break-word;
|
||||
color: #DDDDDD;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,35 @@
|
|||
.middle-text {
|
||||
text-align: center;
|
||||
z-index: 999;
|
||||
.my-topbar {
|
||||
a {
|
||||
color: #F7F7F7;
|
||||
|
||||
&:hover {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
&.title {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#offCanvas {
|
||||
min-height: 100%;
|
||||
a {
|
||||
color: #F7F7F7;
|
||||
&:hover {
|
||||
background-color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
padding: 3px 20px;
|
||||
background-color: #545454;
|
||||
color: #B9B9B9;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,3 +43,4 @@
|
|||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,5 @@
|
|||
.qrcode-image {
|
||||
table {
|
||||
border-width: 0;
|
||||
border-style: none;
|
||||
border-color: #0000ff;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
td {
|
||||
border-width: 0;
|
||||
border-style: none;
|
||||
border-color: #0000ff;
|
||||
border-collapse: collapse;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 0.3rem;
|
||||
height: 0.3rem;
|
||||
}
|
||||
td.black { background-color: #000; }
|
||||
td.white { background-color: #fff; }
|
||||
#image-tag {
|
||||
float: right;
|
||||
width: 200px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
|
|
@ -10,16 +10,6 @@ class Admin::PostsController < ApplicationController
|
|||
@post = Post.find( params[:id] )
|
||||
end
|
||||
|
||||
def show
|
||||
post = Post.find( params[:id] )
|
||||
render :json=> {
|
||||
title: post.title,
|
||||
type: post.type,
|
||||
labels: post.labels_content(true),
|
||||
content: post.content
|
||||
}
|
||||
end
|
||||
|
||||
def destroy
|
||||
@post = Post.find( params[:id] )
|
||||
if @post.destroy
|
||||
|
@ -32,7 +22,7 @@ class Admin::PostsController < ApplicationController
|
|||
end
|
||||
|
||||
def index
|
||||
@posts = Post.desc(:created_at)
|
||||
@posts = Post.order(created_at: :desc).page(params[:page])
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -71,7 +61,7 @@ class Admin::PostsController < ApplicationController
|
|||
private
|
||||
def initialize_or_create_labels(labels)
|
||||
@post.labels = []
|
||||
labels.split(",").each do |name|
|
||||
labels.split(",").map { |i| i.strip }.uniq.each do |name|
|
||||
label = Label.find_or_initialize_by(name: name.strip)
|
||||
label.save!
|
||||
@post.labels << label
|
||||
|
|
|
@ -6,15 +6,18 @@ class Admin::SessionsController < ApplicationController
|
|||
|
||||
def create
|
||||
if ENV['ADMIN_USER'].blank?
|
||||
render :json=> { success: false, message: t('admin.session.no_configuration') }
|
||||
flash.now[:alert] = t('admin.session.no_configuration')
|
||||
render :new
|
||||
elsif ENV['ADMIN_USER'] != params[:username]
|
||||
render :json=> { success: false, message: t('admin.session.username_error') }
|
||||
flash.now[:alert] = t('admin.session.username_error')
|
||||
render :new
|
||||
elsif ENV['ADMIN_PASSWORD'] != params[:password]
|
||||
render :json=> { success: false, message: t('admin.session.password_error') }
|
||||
flash.now[:alert] = t('admin.session.password_error')
|
||||
render :new
|
||||
else
|
||||
flash[:notice] = t('admin.session.login_success')
|
||||
session[:login] = true
|
||||
render :json=> { success: true }
|
||||
redirect_to admin_root_path
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,60 +1,5 @@
|
|||
class ArchivesController < ApplicationController
|
||||
def index
|
||||
type = map[params[:type]]
|
||||
limit = 10
|
||||
start_with = params[:start_with]
|
||||
@posts = Post.desc(:created_at)
|
||||
|
||||
if type
|
||||
@posts = @posts.where(type: type)
|
||||
@type = type
|
||||
end
|
||||
|
||||
# all 与 start_with 参数同在, 说明是要获取所有start_with之前的数据
|
||||
if params[:all] and params[:start_with]
|
||||
@posts = @posts.where(:created_at.gte => Time.at(start_with.to_i))
|
||||
else
|
||||
@posts = @posts.limit(limit)
|
||||
end
|
||||
|
||||
if !params[:all] and start_with
|
||||
@posts = @posts.where(:created_at.lt => Time.at(start_with.to_i))
|
||||
end
|
||||
|
||||
#update start_with
|
||||
unless @posts.empty?
|
||||
start_with = @posts[-1].created_at.to_i.to_s
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render :json => {
|
||||
posts: @posts.collect { |post| build_summary(post) },
|
||||
start_with: start_with
|
||||
}
|
||||
end
|
||||
format.html
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def map
|
||||
{
|
||||
"life"=> "生活",
|
||||
"tech"=> "技术",
|
||||
"creator"=> "创业"
|
||||
}
|
||||
end
|
||||
|
||||
def build_summary(post)
|
||||
{
|
||||
title: post.title,
|
||||
type: post.type_en,
|
||||
created_at: format_date(post.created_at),
|
||||
id: post.id.to_s,
|
||||
liked_count: post.liked_count,
|
||||
visited_count: post.visited_count,
|
||||
labels: post.labels_content
|
||||
}
|
||||
@posts = Post.order(created_at: :desc).page(params[:page])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
class BlogsController < ApplicationController
|
||||
|
||||
def index
|
||||
@newest = Post.desc(:created_at).first
|
||||
@recent = Post.desc(:created_at).to_a[1..3]
|
||||
@newest = Post.order(created_at: :desc).first
|
||||
@recent = Post.order(created_at: :desc).to_a[1..3]
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json
|
||||
|
@ -19,15 +19,16 @@ class BlogsController < ApplicationController
|
|||
def show
|
||||
@post = Post.find(params[:id])
|
||||
@post.visited
|
||||
@prev = Post.where(:created_at.lt => @post.created_at).desc(:created_at).where(:id.ne => @post.id).first
|
||||
@next = Post.where(:created_at.gt => @post.created_at).asc(:created_at).where(:id.ne => @post.id).first
|
||||
@comments = @post.comments
|
||||
@prev = Post.where('created_at < ?', @post.created_at).order(created_at: :desc).first
|
||||
@next = Post.where('created_at > ?', @post.created_at).order(created_at: :asc).first
|
||||
@comments = @post.comments.order(created_at: :desc)
|
||||
@likes_count = @post.likes.count
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def edit
|
||||
@post = Post.find( params[:id] )
|
||||
redirect_to edit_admin_post_path(@post)
|
||||
|
|
|
@ -8,19 +8,22 @@ class CommentsController < ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
cookies[:name] = comment_params[:name]
|
||||
cookies[:email] = comment_params[:email]
|
||||
@post = Post.find( params[:blog_id] )
|
||||
comment = @post.comments.build(comment_params)
|
||||
@comment = @post.comments.build(comment_params)
|
||||
|
||||
if comment.save
|
||||
render :json=> { success: true, data: build_json(comment) }
|
||||
if @comment.save
|
||||
@comments = @post.comments.order(created_at: :desc)
|
||||
render :create_ok
|
||||
else
|
||||
render :json=> { success: false, message: comment.errors.full_messages.join(", ") }
|
||||
render :create_fail
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def comment_params
|
||||
params.permit(:content, :name, :email)
|
||||
params.require(:comment).permit(:content, :name, :email)
|
||||
end
|
||||
|
||||
def build_json(comment)
|
||||
|
|
|
@ -6,15 +6,6 @@ class LikesController < ApplicationController
|
|||
render :json=> { success: true, count: post.liked_count }
|
||||
end
|
||||
|
||||
def is_liked
|
||||
post = Post.find( params[:blog_id] )
|
||||
if post.likes.where(id: params[:id]).first
|
||||
render text: true
|
||||
else
|
||||
render text: false
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
post = Post.find( params[:blog_id] )
|
||||
like = post.likes.build
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
module ApplicationHelper
|
||||
# some format function is defined in app/controllers/application_controller.rb
|
||||
end
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
class ApplicationRecord < ActiveRecord::Base
|
||||
self.abstract_class = true
|
||||
end
|
|
@ -1,17 +1,10 @@
|
|||
class Comment
|
||||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
|
||||
field :name, :type => String
|
||||
field :content, :type => String
|
||||
field :email, :type=>String
|
||||
|
||||
class Comment < ApplicationRecord
|
||||
belongs_to :post
|
||||
validates_presence_of :post_id
|
||||
|
||||
validates :name, presence: true
|
||||
validates :email, presence: true, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, message: I18n.t('comment_attributes.email') }
|
||||
validates :content, presence: true
|
||||
validates_presence_of :post_id
|
||||
|
||||
def reply_emails
|
||||
Comment.where(post_id: self.post_id).collect(&:email).uniq - [ self.email ] - Subscribe.unsubscribe_list
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
class Label
|
||||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
|
||||
field :name, :type => String
|
||||
|
||||
class Label < ApplicationRecord
|
||||
has_and_belongs_to_many :posts
|
||||
validates :name, presence: true
|
||||
end
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
class Like
|
||||
include Mongoid::Document
|
||||
|
||||
class Like < ApplicationRecord
|
||||
belongs_to :post
|
||||
validates_presence_of :post_id
|
||||
end
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
class Photo
|
||||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
field :image
|
||||
|
||||
class Photo < ApplicationRecord
|
||||
mount_uploader :image, PhotoUploader
|
||||
end
|
||||
|
|
|
@ -1,18 +1,5 @@
|
|||
# encoding : utf-8
|
||||
#
|
||||
require 'markdown'
|
||||
class Post
|
||||
TECH = "技术"
|
||||
LIFE = "生活"
|
||||
CREATOR = "创业"
|
||||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
include Mongoid::Pagination
|
||||
field :title, :type => String
|
||||
field :content, :type => String
|
||||
field :type, :type=> String
|
||||
field :visited_count, :type=>Integer, :default=>0
|
||||
|
||||
class Post < ActiveRecord::Base
|
||||
has_many :comments
|
||||
has_and_belongs_to_many :labels
|
||||
|
||||
|
@ -20,7 +7,6 @@ class Post
|
|||
|
||||
validates :title, :presence=>true, :uniqueness=> true
|
||||
validates :content, :presence=>true, :length => { :minimum=> 30 }
|
||||
validates :type, :presence=>true, :inclusion => { :in => [ TECH, LIFE, CREATOR ] }
|
||||
|
||||
after_create do
|
||||
if ENV['MAIL_SERVER'].present?
|
||||
|
@ -38,35 +24,21 @@ class Post
|
|||
md.render(content)
|
||||
end
|
||||
|
||||
def type_en
|
||||
map = {
|
||||
'技术' => 'Tech',
|
||||
'生活' => 'Life',
|
||||
'创业' => 'Creator',
|
||||
}
|
||||
|
||||
if I18n.locale == :en
|
||||
map[type]
|
||||
else
|
||||
type
|
||||
end
|
||||
end
|
||||
|
||||
def visited
|
||||
self.visited_count += 1
|
||||
self.save
|
||||
self.visited_count
|
||||
end
|
||||
|
||||
# 显示给首页截断数据
|
||||
# truncate content for home page display
|
||||
def sub_content
|
||||
HTML_Truncator.truncate(content_html, 300, length_in_chars: true)
|
||||
end
|
||||
|
||||
# 显示给 meta description
|
||||
# truncate content for meta description display
|
||||
def meta_content
|
||||
html = HTML_Truncator.truncate(content_html, 100, :length_in_chars => true, ellipsis: '')
|
||||
# 加上 div 以方便 Nokogiri 获取 text()
|
||||
# Easily get text for Nokogiri
|
||||
html = '<div>' + html + '</div>'
|
||||
Nokogiri.parse(html).text()
|
||||
end
|
||||
|
@ -80,4 +52,8 @@ class Post
|
|||
def liked_count
|
||||
self.likes.size
|
||||
end
|
||||
|
||||
def liked_by?(like_id)
|
||||
!! self.likes.where(id: like_id).first
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
class Subscribe
|
||||
include Mongoid::Document
|
||||
field :email, type: String
|
||||
field :enable, type: Mongoid::Boolean, default: true
|
||||
|
||||
class Subscribe < ApplicationRecord
|
||||
validates :email, presence: true, uniqueness: true, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, message: '地址无效' }
|
||||
|
||||
def self.subscribe_list
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
td
|
||||
= mail_to comment.email
|
||||
td
|
||||
p.pre #{comment.content}
|
||||
= simple_format(comment.content)
|
||||
td
|
||||
= format_time(comment.created_at)
|
||||
|
||||
|
|
|
@ -2,14 +2,11 @@
|
|||
= simple_form_for(@post, url: url, html: {novalidate: '' }) do |f|
|
||||
.row
|
||||
.large-6.columns
|
||||
= f.input :title, label: t('admin.posts_attributes.title'), "ng-model"=>"title", input_html: { name: 'title' }
|
||||
.row
|
||||
.small-6.large-3.columns
|
||||
= f.input :type, :as=>:select, :collection=> [ Post::TECH, Post::LIFE, Post::CREATOR ], label: t('admin.posts_attributes.type'), "ng-model"=>"type", input_html: { name: 'type' }
|
||||
= f.input :title, label: t('admin.posts_attributes.title'), input_html: { name: 'title' }
|
||||
.row
|
||||
.small-12.large-6.columns
|
||||
= label_tag :labels, t('admin.posts_attributes.labels')
|
||||
= text_field_tag :labels, @post.labels_content(true), "ng-model"=>"labels", "ng-initial" => ''
|
||||
= text_field_tag :labels, @post.labels_content(true)
|
||||
|
||||
.row
|
||||
.small-12.columns
|
||||
|
@ -17,22 +14,23 @@
|
|||
| #{t('admin.posts_attributes.already_labels')}
|
||||
span
|
||||
- Label.all.each do |label|
|
||||
a.tag href="#" ng-click="addTag($event)" #{label.name}
|
||||
a.tag href="#" #{label.name}
|
||||
|
||||
/ tabs and upload file field
|
||||
dl.tabs
|
||||
dd ng-class="{ active: body_active }"
|
||||
a href="" ng-click="changeToBody()" #{t('admin.posts_attributes.content')}
|
||||
dd ng-class="{ active: !body_active }"
|
||||
a href="#" ng-click="changeToPreview()" #{t('admin.posts_attributes.preview')}
|
||||
ul.tabs#tabs data-tabs=''
|
||||
li.tabs-title.is-active
|
||||
a href="#content" #{t('admin.posts_attributes.content')}
|
||||
li.tabs-title
|
||||
a href="#preview" #{t('admin.posts_attributes.preview')}
|
||||
= link_to t('admin.posts_attributes.upload_photo'), "#", :id=>'upload_photo'
|
||||
input[type="file" style="display: none;"]
|
||||
|
||||
.content-field ng-show="body_active" ng-model= 'content'
|
||||
= f.input :content, :as=> :text, :label => false, input_html: { name: 'content', "ng-model"=>'content', 'ng-initial'=>'' }
|
||||
.tabs-content data-tabs-content='tabs'
|
||||
.tabs-panel.content-field.is-active#content
|
||||
= f.input :content, :as=> :text, :label => false, input_html: { name: 'content', id: 'content-input' }
|
||||
|
||||
.preview.markdown ng-hide="body_active" ng-bind-html=" trustAsPreviewHTML() "
|
||||
.tabs-panel.preview.markdown#preview
|
||||
|
||||
.row
|
||||
.small-12.large-6.columns.posts-button
|
||||
button #{t('admin.posts_attributes.submit')}
|
||||
button.button type='submit' #{t('admin.posts_attributes.submit')}
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
td.admin-post-summary-field
|
||||
i.fi-calendar
|
||||
span #{format_time(post.created_at)}
|
||||
i.fi-list
|
||||
span #{ post.type_en }
|
||||
i.fi-pricetag-multiple
|
||||
span #{ post.labels_content }
|
||||
i.fi-torsos
|
||||
|
@ -27,3 +25,4 @@
|
|||
= link_to t('comment'), admin_post_comments_path(post.id), class: 'edit-post-link'
|
||||
= link_to t('edit'), edit_admin_post_path(post), class: 'edit-post-link'
|
||||
= link_to t('destroy'), admin_post_path(post), method: 'DELETE', 'data-confirm' => '确认删除?'
|
||||
== paginate @posts
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
.row ng-controller="AdminSessionsController"
|
||||
.small-12.large-8.columns
|
||||
h3.blog-title #{t('admin.session.title')}
|
||||
form ng-submit="login()"
|
||||
= form_tag admin_sessions_path
|
||||
.row
|
||||
.small-12.large-8.columns
|
||||
= label_tag 'username', t('admin.session.username')
|
||||
= text_field_tag 'username', nil, placeholder: t('admin.session.username_placeholder'), "ng-model"=>"username"
|
||||
= text_field_tag 'username', params[:username], placeholder: t('admin.session.username_placeholder')
|
||||
= label_tag 'username', t('admin.session.password')
|
||||
= password_field_tag 'password', nil, placeholder: t('admin.session.password_placeholder'), "ng-model"=>"password"
|
||||
= password_field_tag 'password', params[:password], placeholder: t('admin.session.password_placeholder')
|
||||
|
||||
p
|
||||
.alert-box.warning ng-show=" error_msg "
|
||||
|{{ error_msg }}
|
||||
|
||||
button #{t('admin.session.login_button')}
|
||||
button.button type='submit' #{t('admin.session.login_button')}
|
||||
|
|
|
@ -1,30 +1,22 @@
|
|||
- content_for(:title) do
|
||||
| #{@type ? @type : t('title.timeline')}
|
||||
.row ng-controller="ArchivesController" ng-cloak=""
|
||||
| #{t('title.timeline')}
|
||||
.row
|
||||
.small-12.large-9.large-centered.columns
|
||||
ul.archives-field ng-model="type" ng-init=" type= '#{@type}' "
|
||||
li ng-repeat=" post in posts "
|
||||
a.blog-title ng-href="{{ visit(post.id) }}"
|
||||
|{{ post.title }}
|
||||
p.tags-field
|
||||
i.fi-calendar
|
||||
span
|
||||
|{{ post.created_at }}
|
||||
i.fi-list-thumbnails
|
||||
span
|
||||
|{{ post.type }}
|
||||
i.fi-pricetag-multiple
|
||||
span
|
||||
|{{ post.labels }}
|
||||
i.fi-torsos
|
||||
span
|
||||
|{{ post.visited_count }}
|
||||
i.fi-heart
|
||||
span
|
||||
|{{ post.liked_count }}
|
||||
.no-more-field
|
||||
p ng-show="no_more_flag" #{t('nocontent')}
|
||||
|
||||
.load-more
|
||||
button.small ng-click="load()" ng-show="!loading_flag" Load More
|
||||
button.small ng-show="loading_flag" Loading
|
||||
ul.archives-field
|
||||
- @posts.each do |post|
|
||||
li
|
||||
= link_to post.title, blog_path(post), class: 'blog-title'
|
||||
p.tags-field
|
||||
i.fi-calendar
|
||||
span
|
||||
= format_date(post.created_at)
|
||||
i.fi-pricetag-multiple
|
||||
span
|
||||
= post.labels_content
|
||||
i.fi-torsos
|
||||
span
|
||||
= post.visited_count
|
||||
i.fi-heart
|
||||
span
|
||||
= post.liked_count
|
||||
= paginate @posts
|
||||
|
|
|
@ -1,21 +1,16 @@
|
|||
.row ng-controller="CommentsController" ng-cloak=""
|
||||
.row
|
||||
.small-12.large-9.large-centered.columns
|
||||
form novalidate='' name='form'
|
||||
= form_for Comment.new, url: blog_comments_path(@post), remote: true do |f|
|
||||
.row
|
||||
.small-12.large-12.columns
|
||||
= text_area_tag(:content, nil, placeholder: t('comment_placeholder.content'), 'ng-model'=> 'content', 'ng-required'=> true)
|
||||
= f.text_area :content, placeholder: t('comment_placeholder.content')
|
||||
.row
|
||||
.small-12.large-6.columns
|
||||
= text_field_tag(:name, nil, placeholder: t('comment_placeholder.name'), 'ng-model'=> 'name', 'ng-required'=> 'true')
|
||||
= text_field_tag(:email, nil, placeholder: t('comment_placeholder.email'), 'ng-model'=> 'email', 'ng-pattern'=>"/^.+@.+$/", 'ng-required'=>"true")
|
||||
button.comment-submit ng-click="submit()" ng-disabled="form.$invalid || submitting" {{ submitting && "#{t('comment_placeholder.submitting')}" || "#{t('comment_placeholder.submit')}" }}
|
||||
p.comment-success ng-show="publish_success" #{t('comment_placeholder.publish_success')}
|
||||
p.comment-fail ng-show="publish_success == false" #{t('comment_placeholder.publish_fail')}: {{ publish_fail_msg }}
|
||||
.comment-diag
|
||||
.comment-wrapper ng-repeat=" comment in comments "
|
||||
p.name
|
||||
|{{ comment.name + " • " }}
|
||||
span.created-at
|
||||
|{{ comment.created_at }}
|
||||
/ ignore "white-space: pre" 's effect
|
||||
<p class=comment-content>{{ comment.content }}</p>
|
||||
= f.text_field :name, value: cookies[:name], placeholder: t('comment_placeholder.name')
|
||||
= f.text_field :email, value: cookies[:email], placeholder: t('comment_placeholder.email')
|
||||
button.button.comment-submit type='submit' data-disable-with=t('comment_placeholder.submitting') #{t('comment_placeholder.submit')}
|
||||
#alert-container.alert.callout
|
||||
span.text
|
||||
button class="close-button" type='button'
|
||||
span ×
|
||||
= render partial: 'comments/comment_content', locals: { comments: comments }
|
||||
|
|
|
@ -8,21 +8,16 @@ p.ptag.published-at
|
|||
span #{format_date(post.created_at)}
|
||||
|
||||
= render 'common/copyright'
|
||||
|
||||
hr.blog-over
|
||||
p ng-controller="LikesController" ng-cloak=""
|
||||
button.like-button ng-show="! is_liked " ng-click="submit()"
|
||||
|{{ count }}
|
||||
p
|
||||
button.button.like-button class="#{'liked' if post.liked_by?(cookies[:like])}" type='button' data-url=blog_likes_path(post)
|
||||
span.count #{@likes_count}
|
||||
span Like
|
||||
button.like-button.liked ng-show=" is_liked " ng-click="cancel()"
|
||||
|{{ count }}
|
||||
span Like
|
||||
div ng-controller = "QRCodesController"
|
||||
.qrcode
|
||||
a href="#" ng-model="qrcode" ng-init="qrcode=false" ng-click="show()"
|
||||
i.fi-link
|
||||
| #{t('qr_code')}
|
||||
.qrcode
|
||||
a#qrcode-link href="#"
|
||||
i.fi-link
|
||||
| #{t('qr_code')}
|
||||
|
||||
.social-share ng-show='qrcode'
|
||||
.qrcode-wrapper
|
||||
= render partial: "qrcode", locals: { str: blog_url(post) }
|
||||
.social-share
|
||||
.qrcode-wrapper
|
||||
= render partial: "qrcode", locals: { str: blog_url(post) }
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
/ require: locals: { post : post }
|
||||
h2.blog-title #{post.title}
|
||||
p.ptag
|
||||
span
|
||||
i.fi-list-thumbnails
|
||||
span #{post.type_en}
|
||||
span
|
||||
i.fi-pricetag-multiple
|
||||
span #{post.labels_content}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
.qrcode-image
|
||||
= image_tag( qrcodes_path(str: str) )
|
||||
#image-tag data-url=str
|
||||
p #{t('qrcodetips')}
|
||||
|
|
|
@ -27,20 +27,11 @@
|
|||
.row.ng-cloak ng-controller='AboutController'
|
||||
.small-12.medium-6.large-12.columns
|
||||
ul.subscribe-ul
|
||||
- if ENV['MAIL_SERVER'].present?
|
||||
li
|
||||
= link_to t('subscribes.email'), '', "ng-click"=>"click('email')"
|
||||
.email-subscribe ng-show="type == 'email'"
|
||||
= text_field_tag 'email', nil, placeholder: 'your@email.com', 'ng-model'=>'email'
|
||||
button.small ng-click="subscribe()" ng-disabled="! email_validate()" #{t('subscribes.submit')}
|
||||
span.subscribe-success ng-show="subscribe_success" #{t('subscribes.submit_success')}
|
||||
span.subscribe-fail ng-show="subscribe_success == false" {{subscribe_fail_msg}}
|
||||
li
|
||||
= link_to t('subscribes.wechat'), '', "ng-click"=>"click('weixin')"
|
||||
.weixin-subscribe ng-show="type == 'weixin'"
|
||||
= render partial: "qrcode", locals: { str: root_url }
|
||||
a data-toggle="qrcode-home" #{t('subscribes.wechat') }
|
||||
#qrcode-home.weixin-subscribe.hide data-toggler='hide' data-url=root_url
|
||||
li
|
||||
= link_to t('subscribes.rss'), '', "ng-click"=>"click('rss')"
|
||||
.rss-subscribe ng-show="type == 'rss'"
|
||||
a data-toggle="rss-home" #{t('subscribes.rss') }
|
||||
#rss-home.rss-subscribe.hide data-toggler='hide'
|
||||
= link_to rss_blogs_path do
|
||||
- image_tag('rss.png')
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
- content_for(:meta) do
|
||||
meta name="description" content="#{@post.meta_content}"
|
||||
meta name="description" content=@post.meta_content
|
||||
meta name="keywords" content=@post.labels_content
|
||||
|
||||
- content_for(:title) do
|
||||
| #{@post.title}
|
||||
.row.blog-wrapper
|
||||
.small-12.large-9.large-centered.columns
|
||||
= render partial: "post", :locals=> { :post=> @post }
|
||||
= render partial: "post", :locals=> { post: @post }
|
||||
.comment-field
|
||||
= render partial: 'comment', locals: { comments: @comments, post: @post }
|
||||
p
|
||||
.row
|
||||
.small-12.large-9.large-centered.columns
|
||||
- if @prev
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
.comment-diag
|
||||
- comments.each do |comment|
|
||||
.comment-wrapper
|
||||
p.name
|
||||
| #{comment.name}
|
||||
| #{" • "}
|
||||
span.created-at
|
||||
| #{format_time(comment.created_at) }
|
||||
= render partial: 'comments/comment_pre', locals: { comment: comment }
|
|
@ -0,0 +1,2 @@
|
|||
.comment-content
|
||||
= simple_format(comment.content)
|
|
@ -0,0 +1,2 @@
|
|||
$('#alert-container .text').text(' <%= @comment.errors.full_messages.join(' ') %>' );
|
||||
$('#alert-container').removeClass('success').addClass('alert').show();
|
|
@ -0,0 +1,4 @@
|
|||
$('#comment_content').val('');
|
||||
$('#alert-container .text').text(' <%= t('comment_placeholder.publish_success') %>' );
|
||||
$('#alert-container').removeClass('alert').addClass('success').show();
|
||||
$('.comment-diag').replaceWith('<%= j render partial: 'comment_content', locals: { comments: @comments }%>');
|
|
@ -1,5 +1,5 @@
|
|||
- if (1.days.from_now).strftime('%-m-%-d') =~ /^1-[123]$/
|
||||
.new-year
|
||||
.alert-box data-alert=''
|
||||
.callout.primary data-closable=''
|
||||
| 我的朋友, 祝你元旦快乐
|
||||
a href='#' class='close' ×
|
||||
button.close-button type='button' data-close='' ×
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
- content_for(:title) do
|
||||
| #{t('title.about')}
|
||||
- content_for(:main) do
|
||||
.about-page ng-app='app' ng-controller='AboutScrollController'
|
||||
.top-bar-wrapper.contain-to-grid.fixed ng-class="{ active: ! is_top() }"
|
||||
.about-page
|
||||
.top-bar-wrapper.contain-to-grid.fixed
|
||||
.row
|
||||
.small-12.columns
|
||||
nav.top-bar data-topbar='' role='navigation'
|
||||
ul.title-area
|
||||
li.name
|
||||
h1
|
||||
a href='/' 回到博客
|
||||
section.top-bar-section
|
||||
ul.right
|
||||
nav#about-top-bar.top-bar
|
||||
.top-bar-left
|
||||
ul.menu
|
||||
li
|
||||
a href='#about' du-smooth-scroll='' du-scrollspy='' 关于
|
||||
a.name href='/' 回到博客
|
||||
.top-bar-right
|
||||
ul.menu
|
||||
li
|
||||
a href='#skill' du-smooth-scroll='' du-scrollspy='' 技能
|
||||
a href='#about' 关于
|
||||
li
|
||||
a href='#work' du-smooth-scroll='' du-scrollspy='' 作品
|
||||
a href='#skill' 技能
|
||||
li
|
||||
a href='#contact' du-smooth-scroll='' du-scrollspy='' 联系
|
||||
a href='#work' 作品
|
||||
li
|
||||
a href='#contact' 联系
|
||||
#intro
|
||||
header.intro
|
||||
.intro-heading
|
||||
|
@ -32,7 +32,7 @@
|
|||
| 懒, 是人类进步的动力
|
||||
br
|
||||
| 所谓技术, 就是让你的生活越来越懒
|
||||
a.circle href='#about' du-smooth-scroll=''
|
||||
a.circle href='#about'
|
||||
i.fa.fa-angle-double-down
|
||||
section#about
|
||||
.row
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
/ Non-link tag that stands for skipped pages...
|
||||
- available local variables
|
||||
current_page : a page object for the currently displayed page
|
||||
total_pages : total number of pages
|
||||
per_page : number of items to fetch per page
|
||||
remote : data-remote
|
||||
li.ellipsis
|
|
@ -0,0 +1,10 @@
|
|||
/ Link to the "Last" page
|
||||
- available local variables
|
||||
url : url to the last page
|
||||
current_page : a page object for the currently displayed page
|
||||
total_pages : total number of pages
|
||||
per_page : number of items to fetch per page
|
||||
remote : data-remote
|
||||
span.last
|
||||
== link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, :remote => remote
|
||||
'
|
|
@ -0,0 +1,10 @@
|
|||
/ Link to the "Next" page
|
||||
- available local variables
|
||||
url : url to the next page
|
||||
current_page : a page object for the currently displayed page
|
||||
total_pages : total number of pages
|
||||
per_page : number of items to fetch per page
|
||||
remote : data-remote
|
||||
li.pagination-next class="#{'disabled' if current_page.last?}"
|
||||
== link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, :rel => 'next', :remote => remote
|
||||
'
|
|
@ -0,0 +1,11 @@
|
|||
/ Link showing page number
|
||||
- available local variables
|
||||
page : a page object for "this" page
|
||||
url : url to this page
|
||||
current_page : a page object for the currently displayed page
|
||||
total_pages : total number of pages
|
||||
per_page : number of items to fetch per page
|
||||
remote : data-remote
|
||||
li class="page#{' current' if page.current?}"
|
||||
== link_to_unless page.current?, page, url, {:remote => remote, :rel => page.rel}
|
||||
'
|
|
@ -0,0 +1,17 @@
|
|||
/ The container tag
|
||||
- available local variables
|
||||
current_page : a page object for the currently displayed page
|
||||
total_pages : total number of pages
|
||||
per_page : number of items to fetch per page
|
||||
remote : data-remote
|
||||
paginator : the paginator that renders the pagination tags inside
|
||||
|
||||
== paginator.render do
|
||||
ul.pagination
|
||||
== prev_page_tag
|
||||
- each_page do |page|
|
||||
- if page.left_outer? || page.right_outer? || page.inside_window?
|
||||
== page_tag page
|
||||
- elsif !page.was_truncated?
|
||||
== gap_tag
|
||||
== next_page_tag
|
|
@ -0,0 +1,10 @@
|
|||
/ Link to the "Previous" page
|
||||
- available local variables
|
||||
url : url to the previous page
|
||||
current_page : a page object for the currently displayed page
|
||||
total_pages : total number of pages
|
||||
per_page : number of items to fetch per page
|
||||
remote : data-remote
|
||||
li.pagination-previous class="#{'disabled' if current_page.first?}"
|
||||
== link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, :rel => 'prev', :remote => remote
|
||||
'
|
|
@ -3,7 +3,7 @@
|
|||
.footer
|
||||
div
|
||||
span.link yafeilee.me
|
||||
span.time © 2012 - 2015
|
||||
span.time © 2012 - 2016
|
||||
.license
|
||||
| Designed by
|
||||
span
|
||||
|
|
|
@ -4,24 +4,24 @@ html
|
|||
meta name="viewport" content="width=device-width, initial-scale=1.0"
|
||||
title Admin Page for #{ENV['SITE_NAME']}
|
||||
= stylesheet_link_tag "application"
|
||||
= javascript_include_tag "vendor/modernizr"
|
||||
= javascript_include_tag "application"
|
||||
= csrf_meta_tags
|
||||
body
|
||||
nav.top-bar data-topbar=""
|
||||
ul.title-area
|
||||
li.name
|
||||
h1
|
||||
.title-bar data-responsive-toggle="example-menu" data-hide-for="medium"
|
||||
button class="menu-icon" type="button" data-toggle=''
|
||||
.title-bar-title Menu
|
||||
|
||||
.top-bar#dashboard-topbar
|
||||
.top-bar-left
|
||||
ul.menu
|
||||
li
|
||||
= link_to "Dashboard For #{ENV['SITE_NAME']}", admin_root_path
|
||||
li.toggle-topbar.menu-icon
|
||||
a href="#" Menu
|
||||
section.top-bar-section
|
||||
ul.left
|
||||
li
|
||||
= link_to t('admin.new_post'), new_admin_post_path
|
||||
li
|
||||
= link_to t('admin.posts'), admin_posts_path
|
||||
ul.right
|
||||
.top-bar-right
|
||||
ul.menu
|
||||
li
|
||||
= link_to t('admin.back'), root_path
|
||||
- if admin_username
|
||||
|
@ -29,9 +29,9 @@ html
|
|||
= link_to admin_username + ' [ ' + t('admin.logout') + ' ]', admin_session_path(1), method: 'DELETE'
|
||||
- flash.each do |name, msg|
|
||||
- if msg.is_a?(String)
|
||||
div class=("alert-box #{name.to_sym == :notice ? "success" : "alert"}") data-alert=""
|
||||
div class=("callout #{name.to_sym == :notice ? "success" : "alert"}") data-closable=""
|
||||
= content_tag :div, msg
|
||||
a.close href="#" ×
|
||||
button.close-button type='button' data-close='' ×
|
||||
.admin-main-field ng-app="app"
|
||||
= yield
|
||||
= render "layouts/footer"
|
||||
|
|
|
@ -6,43 +6,24 @@ html
|
|||
= yield(:meta)
|
||||
title
|
||||
= content_for?(:title) ? yield(:title) + " | #{ENV['SITE_NAME']}" : ENV['SITE_NAME']
|
||||
= stylesheet_link_tag "application", media: 'all'
|
||||
= stylesheet_link_tag "application", 'data-turbolinks-track' => "reload"
|
||||
= favicon_link_tag 'favicon.png', type: 'image/png'
|
||||
= javascript_include_tag "vendor/modernizr"
|
||||
= javascript_include_tag "application"
|
||||
= javascript_include_tag "application", 'data-turbolinks-track' => "reload"
|
||||
= csrf_meta_tags
|
||||
body
|
||||
body data-whatinput="mouse"
|
||||
- if content_for?(:main)
|
||||
= yield(:main)
|
||||
- else
|
||||
.off-canvas-wrap data-offcanvas=''
|
||||
.inner-wrap
|
||||
nav.tab-bar
|
||||
section.left-small
|
||||
a.left-off-canvas-toggle.menu-icon href="#"
|
||||
span
|
||||
h1.title.middle-text
|
||||
= link_to ENV['SITE_NAME'], root_path
|
||||
aslide.left-off-canvas-menu
|
||||
ul.off-canvas-list
|
||||
.off-canvas-wrapper
|
||||
.off-canvas-wrapper-inner data-off-canvas-wrapper=''
|
||||
.off-canvas.position-left id="offCanvas" data-off-canvas=''
|
||||
ul.vertical.menu
|
||||
li
|
||||
label Menu
|
||||
li
|
||||
= link_to root_path do
|
||||
i.fi-home
|
||||
| #{t('head.home')}
|
||||
li
|
||||
= link_to '/tech' do
|
||||
i.fi-social-evernote
|
||||
| #{t('head.tech')}
|
||||
li
|
||||
= link_to '/life' do
|
||||
i.fi-torsos-male-female
|
||||
| #{t('head.life')}
|
||||
li
|
||||
= link_to '/creator' do
|
||||
i.fi-lightbulb
|
||||
| #{t('head.creator')}
|
||||
li
|
||||
label Archive
|
||||
li
|
||||
|
@ -54,15 +35,32 @@ html
|
|||
= link_to about_path do
|
||||
i.fi-torso
|
||||
| #{t('head.about')}
|
||||
section.main-section ng-app="app"
|
||||
.off-canvas-content data-off-canvas-content=''
|
||||
.title-bar.hide-for-medium.my-topbar
|
||||
.title-bar-left
|
||||
button.menu-icon type='button' data-open='offCanvas'
|
||||
span.title-bar-title
|
||||
= link_to ENV['SITE_NAME'], root_path
|
||||
.top-bar.show-for-medium.my-topbar
|
||||
.top-bar-left
|
||||
ul.dropdown.menu data-dropdown-menu=''
|
||||
li
|
||||
= link_to ENV['SITE_NAME'], root_path, class: 'title'
|
||||
.top-bar-right
|
||||
ul.dropdown.menu data-dropdown-menu=''
|
||||
li
|
||||
= link_to t('head.home'), root_path
|
||||
li
|
||||
= link_to t('head.timeline'), archives_path
|
||||
li
|
||||
= link_to t('head.about'), about_path
|
||||
- flash.each do |name, msg|
|
||||
- if msg.is_a?(String)
|
||||
div class=("alert-box #{name == :notice ? "success" : "alert"}") data-alert=""
|
||||
div class=("callout #{name.to_sym == :notice ? "success" : "alert"}") data-closable=""
|
||||
= content_tag :div, msg
|
||||
a.close href="#" ×
|
||||
button.close-button type='button' data-close='' ×
|
||||
= render 'common/welcome_new_year'
|
||||
= yield
|
||||
= render "layouts/footer"
|
||||
a.exit-off-canvas
|
||||
|
||||
= render 'layouts/google_analytics'
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
require File.expand_path('../boot', __FILE__)
|
||||
|
||||
# Pick the frameworks you want:
|
||||
require "active_model/railtie"
|
||||
require "action_controller/railtie"
|
||||
require "action_mailer/railtie"
|
||||
require "action_view/railtie"
|
||||
require "sprockets/railtie"
|
||||
require "rails/test_unit/railtie"
|
||||
require 'rails/all'
|
||||
|
||||
Bundler.require(:default, Rails.env)
|
||||
|
||||
module WBlog
|
||||
class Application < Rails::Application
|
||||
|
||||
# Configure sensitive parameters which will be filtered from the log file.
|
||||
config.i18n.available_locales = [:en, :'zh-CN']
|
||||
#I18n.config.enforce_available_locales = true
|
||||
config.i18n.default_locale = (ENV['LOCALE'] || 'zh-CN').to_sym
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
development:
|
||||
adapter: postgresql
|
||||
host: localhost
|
||||
encoding: unicode
|
||||
database: wblog_development
|
||||
pool: 5
|
||||
|
||||
test:
|
||||
adapter: postgresql
|
||||
host: localhost
|
||||
encoding: unicode
|
||||
database: wblog_test
|
||||
pool: 5
|
||||
|
||||
production:
|
||||
adapter: postgresql
|
||||
host: localhost
|
||||
encoding: unicode
|
||||
database: wblog_production
|
||||
pool: 5
|
|
@ -0,0 +1,20 @@
|
|||
development:
|
||||
adapter: postgresql
|
||||
host: localhost
|
||||
encoding: unicode
|
||||
database: wblog_development
|
||||
pool: 5
|
||||
|
||||
test:
|
||||
adapter: postgresql
|
||||
host: localhost
|
||||
encoding: unicode
|
||||
database: wblog_test
|
||||
pool: 5
|
||||
|
||||
production:
|
||||
adapter: postgresql
|
||||
host: localhost
|
||||
encoding: unicode
|
||||
database: wblog_production
|
||||
pool: 5
|
|
@ -5,17 +5,19 @@ require 'mina/multistage'
|
|||
require 'mina/bundler'
|
||||
require 'mina/rails'
|
||||
require 'mina/git'
|
||||
require 'mina/rvm' # for rvm support. (http://rvm.io)
|
||||
require 'mina/unicorn'
|
||||
require 'mina/rvm'
|
||||
require 'mina/puma'
|
||||
require 'mina_sidekiq/tasks'
|
||||
|
||||
# Manually create these paths in shared/ (eg: shared/config/database.yml) in your server.
|
||||
# They will be linked in the 'deploy:link_shared_paths' step.
|
||||
set :shared_paths, ['config/mongoid.yml', 'config/application.yml', 'log', 'tmp', 'public/uploads', 'public/personal' ]
|
||||
set :shared_paths, ['config/database.yml', 'config/application.yml', 'log', 'tmp', 'public/uploads', 'public/personal' ]
|
||||
|
||||
# rvm path
|
||||
set :rvm_path, '/usr/local/rvm/scripts/rvm'
|
||||
|
||||
task :environment do
|
||||
queue! %[source /usr/local/rvm/scripts/rvm]
|
||||
queue! %[rvm use 2.0.0]
|
||||
invoke :'rvm:use[2.2.3]'
|
||||
end
|
||||
|
||||
task :setup => :environment do
|
||||
|
@ -24,7 +26,7 @@ task :setup => :environment do
|
|||
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/#{dir}"]
|
||||
end
|
||||
|
||||
['config/mongoid.yml', 'config/application.yml'].each do |file|
|
||||
['config/database.yml', 'config/application.yml'].each do |file|
|
||||
queue! %[touch "#{deploy_to}/shared/#{file}"]
|
||||
queue %[echo "-----> Be sure to edit 'shared/#{file}'."]
|
||||
end
|
||||
|
@ -47,8 +49,12 @@ task :deploy => :environment do
|
|||
invoke :'rails:assets_precompile'
|
||||
|
||||
to :launch do
|
||||
invoke :'unicorn:restart'
|
||||
# Insure puma is start when restart it
|
||||
invoke :'puma:start'
|
||||
invoke :'puma:phased_restart'
|
||||
invoke :'sidekiq:restart'
|
||||
end
|
||||
|
||||
invoke :'deploy:cleanup'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
set :domain, 'yafeilee.me'
|
||||
set :deploy_to, '/home/ruby/wblog_en'
|
||||
set :repository, 'git@github.com:windy/wblog.git'
|
||||
set :branch, 'master'
|
||||
set :branch, 'new_design'
|
||||
set :user, 'ruby'
|
||||
set :unicorn_config, -> { "#{deploy_to}/#{current_path}/config/unicorn/en.rb" }
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
set :domain, 'yafeilee.me'
|
||||
set :deploy_to, '/home/ruby/wblog'
|
||||
set :repository, 'git@github.com:windy/wblog.git'
|
||||
set :branch, 'master'
|
||||
set :branch, 'new_design'
|
||||
set :user, 'ruby'
|
||||
set :unicorn_config, -> { "#{deploy_to}/#{current_path}/config/unicorn/zh.rb" }
|
||||
|
|
|
@ -20,7 +20,7 @@ WBlog::Application.configure do
|
|||
# config.action_dispatch.rack_cache = true
|
||||
|
||||
# Disable Rails's static asset server (Apache or nginx will already do this).
|
||||
config.serve_static_files = false
|
||||
config.public_file_server.enabled = false
|
||||
|
||||
# Compress JavaScripts and CSS.
|
||||
config.assets.js_compressor = :uglifier
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
Kaminari.configure do |config|
|
||||
config.default_per_page = 10
|
||||
# config.max_per_page = nil
|
||||
config.window = 2
|
||||
# config.outer_window = 0
|
||||
config.left = 0
|
||||
config.right = 0
|
||||
# config.page_method_name = :page
|
||||
# config.param_name = :page
|
||||
end
|
|
@ -44,7 +44,7 @@ zh-CN:
|
|||
comment_placeholder:
|
||||
content: '发表你的评论...'
|
||||
name: '名字'
|
||||
email: '邮箱'
|
||||
email: '邮箱, your@example.com'
|
||||
submit: '提交'
|
||||
submitting: '提交中'
|
||||
publish_success: '发表成功'
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
development:
|
||||
clients:
|
||||
default:
|
||||
database: w_blog_development
|
||||
hosts:
|
||||
- localhost:27017
|
||||
options:
|
||||
|
||||
production:
|
||||
clients:
|
||||
default:
|
||||
database: w_blog_production
|
||||
hosts:
|
||||
- localhost:27017
|
||||
options:
|
||||
|
||||
test:
|
||||
clients:
|
||||
default:
|
||||
database: w_blog_test
|
||||
hosts:
|
||||
- localhost:27017
|
||||
options:
|
||||
read:
|
||||
mode: :primary
|
||||
# In the test environment we lower the retries and retry interval to
|
||||
# low amounts for fast failures.
|
||||
max_retries: 1
|
||||
retry_interval: 0
|
|
@ -1,5 +1,4 @@
|
|||
WBlog::Application.routes.draw do
|
||||
root :to => 'blogs#index'
|
||||
|
||||
resources :blogs, :only=>[:index, :show, :edit] do
|
||||
collection do
|
||||
|
@ -24,19 +23,20 @@ WBlog::Application.routes.draw do
|
|||
# photos
|
||||
resources :photos, only: [:create]
|
||||
get '/qrcodes' => 'qrcodes#show'
|
||||
|
||||
|
||||
namespace :admin do
|
||||
resources :posts do
|
||||
resources :posts, except: [:show] do
|
||||
collection do
|
||||
post :preview
|
||||
end
|
||||
resources :comments
|
||||
end
|
||||
resources :sessions, :only=>[:new, :create, :destroy]
|
||||
root to: 'dashboard#index'
|
||||
root 'dashboard#index'
|
||||
end
|
||||
|
||||
get '/about' => 'home#index'
|
||||
get '/mobile' => 'home#mobile'
|
||||
get '/:type' => 'archives#index', constraints: { type: /tech|life|creator/ }
|
||||
|
||||
root 'blogs#index'
|
||||
end
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
class CreatePosts < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :posts do |t|
|
||||
t.string :title
|
||||
t.text :content
|
||||
t.integer :visited_count
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
class CreateComments < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :comments do |t|
|
||||
t.string :name
|
||||
t.string :email
|
||||
t.text :conent
|
||||
t.integer :post_id
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
class CreateLabels < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :labels do |t|
|
||||
t.string :name
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
class CreateLikes < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :likes do |t|
|
||||
t.integer :post_id
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
class CreatePhotos < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :photos do |t|
|
||||
t.string :image
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
class CreateSubscribes < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :subscribes do |t|
|
||||
t.string :email
|
||||
t.boolean :enable
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
class CreateLabelsPosts < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :labels_posts, id: false do |t|
|
||||
t.integer :label_id
|
||||
t.integer :post_id
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class ChangeColumnDefaultVisitedCountToPosts < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
change_column_default :posts, :visited_count, 0
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class RenameColumnContentToComments < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
rename_column :comments, :conent, :content
|
||||
end
|
||||
end
|
|
@ -0,0 +1,66 @@
|
|||
# encoding: UTF-8
|
||||
# This file is auto-generated from the current state of the database. Instead
|
||||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# Note that this schema.rb definition is the authoritative source for your
|
||||
# database schema. If you need to create the application database on another
|
||||
# system, you should be using db:schema:load, not running all the migrations
|
||||
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
||||
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20160421062614) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
create_table "comments", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "email"
|
||||
t.text "content"
|
||||
t.integer "post_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "labels", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "labels_posts", id: false, force: :cascade do |t|
|
||||
t.integer "label_id"
|
||||
t.integer "post_id"
|
||||
end
|
||||
|
||||
create_table "likes", force: :cascade do |t|
|
||||
t.integer "post_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "photos", force: :cascade do |t|
|
||||
t.string "image"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "posts", force: :cascade do |t|
|
||||
t.string "title"
|
||||
t.text "content"
|
||||
t.integer "visited_count", default: 0
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "subscribes", force: :cascade do |t|
|
||||
t.string "email"
|
||||
t.boolean "enable"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Comment, :type => :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Label, :type => :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Photo, :type => :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
Loading…
Reference in New Issue