ample_assets 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.textile +68 -0
- data/Rakefile +38 -0
- data/app/assets/images/ample_assets/bg-noise.png +0 -0
- data/app/assets/images/ample_assets/btn-next.png +0 -0
- data/app/assets/images/ample_assets/btn-prev.png +0 -0
- data/app/assets/images/ample_assets/btn-select-files.png +0 -0
- data/app/assets/images/ample_assets/cancel.png +0 -0
- data/app/assets/images/ample_assets/closelabel.png +0 -0
- data/app/assets/images/ample_assets/collapse.png +0 -0
- data/app/assets/images/ample_assets/gravity.png +0 -0
- data/app/assets/images/ample_assets/icon_other.gif +0 -0
- data/app/assets/images/ample_assets/icon_pdf.gif +0 -0
- data/app/assets/images/ample_assets/icon_swf.gif +0 -0
- data/app/assets/images/ample_assets/loading.gif +0 -0
- data/app/assets/images/ample_assets/play.png +0 -0
- data/app/assets/images/ample_assets/prev-next.png +0 -0
- data/app/assets/images/ample_assets/reload.png +0 -0
- data/app/assets/images/ample_assets/remove.png +0 -0
- data/app/assets/javascripts/ample_assets.js +1 -0
- data/app/assets/javascripts/ample_assets/application.js +18 -0
- data/app/assets/javascripts/ample_assets/classes/ample_assets_gravity.js.coffee +86 -0
- data/app/assets/javascripts/ample_assets/classes/ample_assets_toolbar.js.coffee +769 -0
- data/app/assets/javascripts/ample_assets/classes/ample_assets_uploadify.js.coffee +30 -0
- data/app/assets/javascripts/ample_assets/files.js.coffee +5 -0
- data/app/assets/stylesheets/ample_assets.css +3 -0
- data/app/assets/stylesheets/ample_assets/application.css +8 -0
- data/app/assets/stylesheets/ample_assets/bourbon/css3/_border-radius.scss +59 -0
- data/app/assets/stylesheets/ample_assets/bourbon/css3/_box-shadow.scss +11 -0
- data/app/assets/stylesheets/ample_assets/custom_mixins.scss +47 -0
- data/app/assets/stylesheets/ample_assets/facebox.css +79 -0
- data/app/assets/stylesheets/ample_assets/files.css.scss +750 -0
- data/app/assets/swf/ample_assets/expressInstall.swf +0 -0
- data/app/assets/swf/ample_assets/uploadify.swf +0 -0
- data/app/controllers/ample_assets/application_controller.rb +4 -0
- data/app/controllers/ample_assets/files_controller.rb +109 -0
- data/app/helpers/ample_assets/application_helper.rb +4 -0
- data/app/models/ample_assets/file.rb +79 -0
- data/app/views/ample_assets/files/_drop.html.erb +12 -0
- data/app/views/ample_assets/files/_file.html.erb +1 -0
- data/app/views/ample_assets/files/_file.js.erb +3 -0
- data/app/views/ample_assets/files/index.html.erb +6 -0
- data/app/views/ample_assets/files/new.html.erb +21 -0
- data/app/views/ample_assets/files/recent.html.erb +1 -0
- data/app/views/ample_assets/files/show.html.erb +1 -0
- data/app/views/layouts/ample_assets/application.html.erb +14 -0
- data/config/routes.rb +27 -0
- data/lib/ample_assets.rb +26 -0
- data/lib/ample_assets/configuration.rb +73 -0
- data/lib/ample_assets/custom_processor.rb +29 -0
- data/lib/ample_assets/devise_constraint.rb +9 -0
- data/lib/ample_assets/engine.rb +36 -0
- data/lib/ample_assets/form_builder.rb +19 -0
- data/lib/ample_assets/form_helper.rb +14 -0
- data/lib/ample_assets/plugin_methods.rb +11 -0
- data/lib/ample_assets/version.rb +3 -0
- data/lib/ample_assets/view_helper.rb +80 -0
- data/lib/generators/ample_assets/install_generator.rb +25 -0
- data/lib/generators/ample_assets/templates/migration.rb +16 -0
- data/lib/generators/ample_assets/utils.rb +15 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/images/rails.png +0 -0
- data/test/dummy/app/assets/javascripts/application.js +11 -0
- data/test/dummy/app/assets/sample.pdf +0 -0
- data/test/dummy/app/assets/stylesheets/application.css +8 -0
- data/test/dummy/app/controllers/application_controller.rb +7 -0
- data/test/dummy/app/controllers/public/pages_controller.rb +32 -0
- data/test/dummy/app/controllers/public_controller.rb +6 -0
- data/test/dummy/app/helpers/application_helper.rb +11 -0
- data/test/dummy/app/models/page.rb +7 -0
- data/test/dummy/app/views/layouts/application.html.erb +17 -0
- data/test/dummy/app/views/public/index.html.erb +0 -0
- data/test/dummy/app/views/public/pages/_form.html.erb +18 -0
- data/test/dummy/app/views/public/pages/edit.html.erb +1 -0
- data/test/dummy/app/views/public/pages/index.html.erb +8 -0
- data/test/dummy/app/views/public/pages/new.html.erb +1 -0
- data/test/dummy/app/views/public/pages/show.html.erb +3 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +45 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +30 -0
- data/test/dummy/config/environments/production.rb +60 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/ample_assets.rb +4 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +10 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +8 -0
- data/test/dummy/db/migrate/20120105034123_create_pages.rb +9 -0
- data/test/dummy/db/migrate/20120106192233_create_ample_assets_tables.rb +16 -0
- data/test/dummy/db/schema.rb +37 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/functional/ample_assets/files_controller_test.rb +49 -0
- data/test/integration/ample_assets/admin_test.rb +96 -0
- data/test/integration/ample_assets/public_test.rb +7 -0
- data/test/integration_test_helper.rb +24 -0
- data/test/test_helper.rb +25 -0
- data/test/unit/ample_assets/configuration_test.rb +35 -0
- data/test/unit/ample_assets/file_test.rb +14 -0
- data/test/unit/ample_assets/plugin_methods_test.rb +30 -0
- data/test/unit/helpers/ample_assets/form_builder_test.rb +11 -0
- data/test/unit/helpers/ample_assets/form_helper_test.rb +23 -0
- data/test/unit/helpers/ample_assets/view_helper_test.rb +128 -0
- metadata +395 -0
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2011 YOURNAME
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
h1. Ample Assets
|
|
2
|
+
|
|
3
|
+
AmpleAssets is a mountable engine that provides drag & drop file-management for Rails 3.2 applications.
|
|
4
|
+
|
|
5
|
+
!http://ample.github.com/ample_assets/images/assets.png!
|
|
6
|
+
|
|
7
|
+
h3. Example Usage
|
|
8
|
+
|
|
9
|
+
Add the following to your Gemfile and bundle...
|
|
10
|
+
|
|
11
|
+
<code>
|
|
12
|
+
gem 'ample_assets', :git => 'https://github.com/ample/ample_assets.git'
|
|
13
|
+
</code>
|
|
14
|
+
|
|
15
|
+
Run the generator to copy over the necessary migrations...
|
|
16
|
+
|
|
17
|
+
<code>
|
|
18
|
+
rails g ample_assets:install
|
|
19
|
+
</code>
|
|
20
|
+
|
|
21
|
+
You'll need to create a foreign_key on the model with which you plan to integrate AmpleAssets. For the purposes of this example, let's assume your model is named @Post@...
|
|
22
|
+
|
|
23
|
+
<code>rails g migration add_file_id_to_posts file_id:integer</code>
|
|
24
|
+
|
|
25
|
+
Now you're ready to migrate...
|
|
26
|
+
|
|
27
|
+
<code>rake db:migrate</code>
|
|
28
|
+
|
|
29
|
+
Add the following plugin to your model...
|
|
30
|
+
|
|
31
|
+
<pre><code>class Post < ActiveRecord::Base
|
|
32
|
+
...
|
|
33
|
+
has_asset
|
|
34
|
+
...
|
|
35
|
+
end</code></pre>
|
|
36
|
+
|
|
37
|
+
In both of your manifest files (stylesheets & javascripts) require ample_assets, for example...
|
|
38
|
+
|
|
39
|
+
<pre><code>/**
|
|
40
|
+
*= require ample_assets
|
|
41
|
+
*/
|
|
42
|
+
</code></pre>
|
|
43
|
+
|
|
44
|
+
Add the engine to your app's routes.rb file...
|
|
45
|
+
|
|
46
|
+
<code>
|
|
47
|
+
mount AmpleAssets::Engine => "/ample_assets", :as => "ample_assets"
|
|
48
|
+
</code>
|
|
49
|
+
|
|
50
|
+
To invoke the asset toolbar, include the following in any view...
|
|
51
|
+
|
|
52
|
+
<code>
|
|
53
|
+
<%= assets_toolbar %>
|
|
54
|
+
</code>
|
|
55
|
+
|
|
56
|
+
To invoke a new drop_target, include the following within a form attached to your model...
|
|
57
|
+
|
|
58
|
+
<pre><code><%= form_for current_page do |f| %>
|
|
59
|
+
<%= f.asset_drop(:file_id) %>
|
|
60
|
+
<% end %>
|
|
61
|
+
</code></pre>
|
|
62
|
+
|
|
63
|
+
h3. Configuration
|
|
64
|
+
|
|
65
|
+
<pre><code>AmpleAssets.configure do |config|
|
|
66
|
+
config.mount_at = YOUR PATH PREFIX
|
|
67
|
+
end
|
|
68
|
+
</code></pre>
|
data/Rakefile
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
begin
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
rescue LoadError
|
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
6
|
+
end
|
|
7
|
+
begin
|
|
8
|
+
require 'rdoc/task'
|
|
9
|
+
rescue LoadError
|
|
10
|
+
require 'rdoc/rdoc'
|
|
11
|
+
require 'rake/rdoctask'
|
|
12
|
+
RDoc::Task = Rake::RDocTask
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
17
|
+
rdoc.title = 'AmpleAssets'
|
|
18
|
+
rdoc.options << '--line-numbers'
|
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
|
24
|
+
load 'rails/tasks/engine.rake'
|
|
25
|
+
|
|
26
|
+
Bundler::GemHelper.install_tasks
|
|
27
|
+
|
|
28
|
+
require 'rake/testtask'
|
|
29
|
+
|
|
30
|
+
Rake::TestTask.new(:test) do |t|
|
|
31
|
+
t.libs << 'lib'
|
|
32
|
+
t.libs << 'test'
|
|
33
|
+
t.pattern = 'test/**/*_test.rb'
|
|
34
|
+
t.verbose = true
|
|
35
|
+
t.ruby_opts << '-rturn'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
task :default => :test
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//= require ./ample_assets/application
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into including all the files listed below.
|
|
2
|
+
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
|
|
3
|
+
// be included in the compiled file accessible from http://example.com/assets/application.js
|
|
4
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
5
|
+
// the compiled file.
|
|
6
|
+
//
|
|
7
|
+
//= require jquery
|
|
8
|
+
//= require jquery-ui
|
|
9
|
+
//= require jquery_ujs
|
|
10
|
+
//= require jquery.ample_panels
|
|
11
|
+
//= require jquery.facebox
|
|
12
|
+
//= require jquery.uploadify
|
|
13
|
+
//= require moustache
|
|
14
|
+
//= require pdfobject
|
|
15
|
+
//= require swfobject
|
|
16
|
+
//= require coffee_cup
|
|
17
|
+
//= require_tree ./classes
|
|
18
|
+
//= require ./files
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# **AmpleAssets** is drag and drop file management for Rails applications.
|
|
2
|
+
#
|
|
3
|
+
class window.AmpleAssetsGravity extends CoffeeCup
|
|
4
|
+
|
|
5
|
+
default_options:
|
|
6
|
+
debug: false
|
|
7
|
+
uid: false
|
|
8
|
+
url: "/ample_assets/files/{{ id }}/gravity"
|
|
9
|
+
min_width: 100
|
|
10
|
+
min_height: 100
|
|
11
|
+
max_width: 480
|
|
12
|
+
max_height: 300
|
|
13
|
+
|
|
14
|
+
init: ->
|
|
15
|
+
@log "init()"
|
|
16
|
+
@handle = $("#asset-gravity-handle")
|
|
17
|
+
@image = $(".asset-media img")
|
|
18
|
+
@test()
|
|
19
|
+
|
|
20
|
+
test: ->
|
|
21
|
+
if @image.width() > 0
|
|
22
|
+
@html()
|
|
23
|
+
else
|
|
24
|
+
@log "@image not loaded"
|
|
25
|
+
setTimeout (=> @test()), 500
|
|
26
|
+
|
|
27
|
+
html: ->
|
|
28
|
+
@log "html()"
|
|
29
|
+
# Don't show this for tiny images
|
|
30
|
+
return false unless @image.height() > @options.min_width && @image.height() > @options.min_height
|
|
31
|
+
@gravity = $("#file_attachment_gravity").val() || "c"
|
|
32
|
+
@gravity_grid =
|
|
33
|
+
top: @image.height() / 3
|
|
34
|
+
left: @image.width() / 3
|
|
35
|
+
@image_pos = @image.position()
|
|
36
|
+
@image_center =
|
|
37
|
+
top: (@image_pos.top + (@image.height() / 2) - (@handle.height() / 2))
|
|
38
|
+
left: (@image_pos.left + (@image.width() / 2) - (@handle.width() / 2))
|
|
39
|
+
@handle.css
|
|
40
|
+
position: "absolute"
|
|
41
|
+
left: (@image_center.left - @gravity_grid.left) + (@gravity_grid.left * @gravities()[@gravity][0])
|
|
42
|
+
top: (@image_center.top - @gravity_grid.top) + (@gravity_grid.top * @gravities()[@gravity][1])
|
|
43
|
+
@handle.draggable
|
|
44
|
+
containment: @image
|
|
45
|
+
grid: [@gravity_grid.left, @gravity_grid.top]
|
|
46
|
+
scroll: false,
|
|
47
|
+
start: (event, ui) =>
|
|
48
|
+
$('div.ui-droppable, textarea.ui-droppable').addClass('asset-inactive-target')
|
|
49
|
+
stop: (event, ui) =>
|
|
50
|
+
$('div.ui-droppable, textarea.ui-droppable').removeClass('asset-inactive-target')
|
|
51
|
+
|
|
52
|
+
left = ui.position.left
|
|
53
|
+
top = ui.position.top
|
|
54
|
+
|
|
55
|
+
# Account for images smaller than max width and/or height.
|
|
56
|
+
left = Math.abs(((@options.max_width - @image.width()) / 2) - left) if @image.width() < @options.max_width
|
|
57
|
+
top = Math.abs(((@options.max_height - @image.height()) / 2) - top) if @image.height() < @options.max_height
|
|
58
|
+
|
|
59
|
+
gravity_pos = [ Math.floor(left / @gravity_grid.left), Math.floor(top / @gravity_grid.top) ]
|
|
60
|
+
|
|
61
|
+
for key, value of @gravities()
|
|
62
|
+
if value[0] is gravity_pos[0] and value[1] is gravity_pos[1]
|
|
63
|
+
gravity = key
|
|
64
|
+
break
|
|
65
|
+
$("#file_attachment_gravity").val(gravity);
|
|
66
|
+
@submit(gravity)
|
|
67
|
+
@log gravity
|
|
68
|
+
@handle.fadeIn()
|
|
69
|
+
|
|
70
|
+
submit: (gravity) ->
|
|
71
|
+
@log "submit(#{gravity})"
|
|
72
|
+
$.post @options.url, { gravity: gravity }, (e) =>
|
|
73
|
+
$("a[data-uid='#{@options.uid}']").attr('data-gravity',gravity)
|
|
74
|
+
$('#asset-gravity-notification').show().delay(2500).fadeOut()
|
|
75
|
+
|
|
76
|
+
gravities: ->
|
|
77
|
+
nw: [ 0, 0 ]
|
|
78
|
+
n: [ 1, 0 ]
|
|
79
|
+
ne: [ 2, 0 ]
|
|
80
|
+
w: [ 0, 1 ]
|
|
81
|
+
c: [ 1, 1 ]
|
|
82
|
+
e: [ 2, 1 ]
|
|
83
|
+
sw: [ 0, 2 ]
|
|
84
|
+
s: [ 1, 2 ]
|
|
85
|
+
se: [ 2, 2 ]
|
|
86
|
+
|
|
@@ -0,0 +1,769 @@
|
|
|
1
|
+
# **AmpleAssets** is drag and drop file management for Rails applications.
|
|
2
|
+
#
|
|
3
|
+
class window.AmpleAssetsToolbar extends CoffeeCup
|
|
4
|
+
|
|
5
|
+
default_options:
|
|
6
|
+
debug: false
|
|
7
|
+
expanded: false
|
|
8
|
+
id: "ample-assets"
|
|
9
|
+
handle_text: 'Assets'
|
|
10
|
+
expanded_height: 180
|
|
11
|
+
collapsed_height: 0
|
|
12
|
+
base_url: '/ample_assets'
|
|
13
|
+
search_url: '/files/search'
|
|
14
|
+
thumb_url: '/files/thumbs'
|
|
15
|
+
show_url: '/files/{{ id }}'
|
|
16
|
+
touch_url: '/files/{{ id }}/touch'
|
|
17
|
+
gravity_url: '/files/{{ id }}/gravity'
|
|
18
|
+
onInit: ->
|
|
19
|
+
onExpand: ->
|
|
20
|
+
onCollapse: ->
|
|
21
|
+
panels_options:
|
|
22
|
+
debug: false
|
|
23
|
+
width: 950
|
|
24
|
+
height: 100
|
|
25
|
+
orientation: 'vertical'
|
|
26
|
+
key_orientation: 'vertical'
|
|
27
|
+
keyboard_nav: true
|
|
28
|
+
auto: false
|
|
29
|
+
parent: 'div'
|
|
30
|
+
children: 'div.page'
|
|
31
|
+
pages_options:
|
|
32
|
+
interval: 5000
|
|
33
|
+
width: 81
|
|
34
|
+
height: 81
|
|
35
|
+
enabled: true
|
|
36
|
+
distance: 10
|
|
37
|
+
auto: false
|
|
38
|
+
orientation: 'horizontal'
|
|
39
|
+
key_orientation: 'horizontal'
|
|
40
|
+
per_page: 10
|
|
41
|
+
pages: [
|
|
42
|
+
{
|
|
43
|
+
id: 'recent-assets',
|
|
44
|
+
title: 'Recently Viewed',
|
|
45
|
+
url: '',
|
|
46
|
+
panels: false
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
# Initialize product toolbar and drop targets.
|
|
51
|
+
init: ->
|
|
52
|
+
@options.onInit()
|
|
53
|
+
super
|
|
54
|
+
@setup()
|
|
55
|
+
@events()
|
|
56
|
+
|
|
57
|
+
# Setup global parameters & class options.
|
|
58
|
+
set_options: (opts) ->
|
|
59
|
+
@current = 0
|
|
60
|
+
@keys_enabled = true
|
|
61
|
+
@reloading = false
|
|
62
|
+
@searching = false
|
|
63
|
+
@loaded = false
|
|
64
|
+
super
|
|
65
|
+
|
|
66
|
+
# Build structure and stylize layout of toolbar, setup drag, drop and search logic.
|
|
67
|
+
# Opens first tab if toolbar is expanded on init.
|
|
68
|
+
setup: ->
|
|
69
|
+
id = @options.id
|
|
70
|
+
layout = Mustache.to_html(@tpl('layout'),{ id: id, pages: @get_pages(), tabs: @get_pages('tab') })
|
|
71
|
+
@handle = Mustache.to_html(@tpl('handle'),{ id: id, title: @options.handle_text })
|
|
72
|
+
html = $(layout)
|
|
73
|
+
$('body').append(html).append(@handle)
|
|
74
|
+
@style()
|
|
75
|
+
@drag_drop()
|
|
76
|
+
@search()
|
|
77
|
+
@goto(0) if @options.expanded
|
|
78
|
+
|
|
79
|
+
# Set initial styles on toolbar elements.
|
|
80
|
+
style: ->
|
|
81
|
+
handle_opts =
|
|
82
|
+
position: 'absolute'
|
|
83
|
+
bottom: 0
|
|
84
|
+
right: 0
|
|
85
|
+
$("##{@options.id}-handle").css(handle_opts)
|
|
86
|
+
|
|
87
|
+
@loading = $("##{@options.id}-tabs span.asset-loading")
|
|
88
|
+
$("##{@options.id} .container").css('height',200)
|
|
89
|
+
if @options.expanded
|
|
90
|
+
$("##{@options.id}").css({height:@options.expanded_height});
|
|
91
|
+
|
|
92
|
+
# Reloads tab identified by `i`
|
|
93
|
+
reload: (i) ->
|
|
94
|
+
@log "reload(#{i})"
|
|
95
|
+
@reloading = true
|
|
96
|
+
if i < @options.pages.length - 1
|
|
97
|
+
@empty(i)
|
|
98
|
+
@options.pages[i]['loaded'] = false
|
|
99
|
+
@options.pages[i]['pages_loaded'] = false
|
|
100
|
+
@options.pages[i]['last_request_empty'] = false
|
|
101
|
+
$(@options.pages[i]['panel_selector']).amplePanels('goto', 0)
|
|
102
|
+
@goto(i)
|
|
103
|
+
@enable_panel(i)
|
|
104
|
+
|
|
105
|
+
# Empties the contents of the page identified by `i`
|
|
106
|
+
empty: (i) ->
|
|
107
|
+
@log "empty(#{i})"
|
|
108
|
+
selector = "##{@options.id} .pages .page:nth-child(#{(i+1)})"
|
|
109
|
+
selector += " ul" if @options.pages[i]['panels']
|
|
110
|
+
$(selector).empty()
|
|
111
|
+
|
|
112
|
+
# Hide and deactivate current page, load next page identified by `i`
|
|
113
|
+
goto: (i) ->
|
|
114
|
+
@log "goto(#{i})"
|
|
115
|
+
@show(i)
|
|
116
|
+
@disable_panels()
|
|
117
|
+
@activate(i)
|
|
118
|
+
@load(i) unless @already_loaded(i)
|
|
119
|
+
@enable_panel(i) if @already_loaded(i)
|
|
120
|
+
|
|
121
|
+
# Hide all pages, show page identified by `i`
|
|
122
|
+
show: (i) ->
|
|
123
|
+
$("##{@options.id} .pages .page").hide()
|
|
124
|
+
$("##{@options.id} .pages .page:nth-child(#{i+1}), ##{@options.id} .pages .page:nth-child(#{i+1}) ul").show()
|
|
125
|
+
|
|
126
|
+
# Implement drag & droppable instances, with appropriate callbacks.
|
|
127
|
+
drag_drop: ->
|
|
128
|
+
base_url = @options.base_url
|
|
129
|
+
thumb_url = @options.thumb_url
|
|
130
|
+
ref = this
|
|
131
|
+
|
|
132
|
+
# Note the use of liveDraggable here. See extended plugin at the bottom of this file.
|
|
133
|
+
$(".draggable").liveDraggable
|
|
134
|
+
appendTo: "body"
|
|
135
|
+
helper: "clone"
|
|
136
|
+
start: ->
|
|
137
|
+
$('div.ui-droppable, textarea.ui-droppable').addClass('asset-drop-target')
|
|
138
|
+
stop: ->
|
|
139
|
+
$('div.ui-droppable, textarea.ui-droppable').removeClass('asset-drop-target')
|
|
140
|
+
|
|
141
|
+
$("textarea").droppable
|
|
142
|
+
activeClass: "asset-notice"
|
|
143
|
+
hoverClass: "asset-success"
|
|
144
|
+
drop: (event, ui) ->
|
|
145
|
+
unless $(ui.helper).data('role') == 'gravity'
|
|
146
|
+
ref.target_textarea = this
|
|
147
|
+
ref.resize_modal(ui.draggable)
|
|
148
|
+
|
|
149
|
+
$(".droppable").droppable
|
|
150
|
+
activeClass: "asset-notice"
|
|
151
|
+
hoverClass: "asset-success"
|
|
152
|
+
drop: (event, ui) ->
|
|
153
|
+
unless $(ui.helper).data('role') == 'gravity'
|
|
154
|
+
$(this).html ui.draggable.clone()
|
|
155
|
+
asset_id = $(ui.draggable).attr("id").split("-")[1]
|
|
156
|
+
$(this).parent().children().first().val asset_id
|
|
157
|
+
$(this).parent().find('a.asset-remove').removeClass('hide').show()
|
|
158
|
+
|
|
159
|
+
# Build html for modal windows wherein users can resize the asset's dimensions & geometry.
|
|
160
|
+
# Executes when dropping a file into a textarea. The first argument is the response
|
|
161
|
+
# from the droppable callbacks defined above.
|
|
162
|
+
resize_modal: (el) ->
|
|
163
|
+
uid = $(el).attr("data-uid")
|
|
164
|
+
size = $(el).attr("data-size")
|
|
165
|
+
orientation = $(el).attr("data-orientation")
|
|
166
|
+
base_url = @options.base_url
|
|
167
|
+
thumb_url = @options.thumb_url
|
|
168
|
+
geometry = '100x>'
|
|
169
|
+
opts =
|
|
170
|
+
src: "#{base_url}#{thumb_url}/#{geometry}?uid=#{uid}"
|
|
171
|
+
orientation: orientation
|
|
172
|
+
dimensions: size
|
|
173
|
+
uid: uid
|
|
174
|
+
html = Mustache.to_html(@tpl('drop'), opts)
|
|
175
|
+
$.facebox("<div class=\"asset-detail\">#{html}</div>")
|
|
176
|
+
|
|
177
|
+
# Removes active state from all tabs, adds it back for tab identified by `i`
|
|
178
|
+
activate: (i) ->
|
|
179
|
+
@log "activate(#{i})"
|
|
180
|
+
@current = i
|
|
181
|
+
tabs = $("##{@options.id} a.tab")
|
|
182
|
+
tabs.removeClass('on')
|
|
183
|
+
tabs.eq(i).addClass('on')
|
|
184
|
+
|
|
185
|
+
# Highlight & load next tab (right) by incrementing `@current`
|
|
186
|
+
next: ->
|
|
187
|
+
if @current < @options.pages.length - 1
|
|
188
|
+
@log "next()"
|
|
189
|
+
@current += 1
|
|
190
|
+
@goto(@current)
|
|
191
|
+
|
|
192
|
+
# Highlight & load previous tab (left) by decrementing `@current`
|
|
193
|
+
previous: ->
|
|
194
|
+
unless @current == 0
|
|
195
|
+
@log "previous()"
|
|
196
|
+
@current -= 1
|
|
197
|
+
@goto(@current)
|
|
198
|
+
|
|
199
|
+
# Loops through all pages, generates HTML and returns concatenated string of everything.
|
|
200
|
+
get_pages: (tpl = 'page') ->
|
|
201
|
+
html = ''
|
|
202
|
+
$.each @options.pages, (idx,el) =>
|
|
203
|
+
el['classes'] = 'first-child' if idx == 0
|
|
204
|
+
html += Mustache.to_html @tpl(tpl), el
|
|
205
|
+
html
|
|
206
|
+
|
|
207
|
+
# Expands and collapses asset toolbar.
|
|
208
|
+
toggle: ->
|
|
209
|
+
el = $("##{@options.id}")
|
|
210
|
+
if @options.expanded
|
|
211
|
+
@options.expanded = false
|
|
212
|
+
$('body').animate {'padding-bottom': 0}, "fast"
|
|
213
|
+
el.animate {height: @options.collapsed_height}, "fast", =>
|
|
214
|
+
@collapse()
|
|
215
|
+
@options.onCollapse()
|
|
216
|
+
el.trigger('collapse')
|
|
217
|
+
else
|
|
218
|
+
$("##{@options.id}-handle").hide()
|
|
219
|
+
@options.expanded = true
|
|
220
|
+
$('body').animate {'padding-bottom': @options.expanded_height}, "fast"
|
|
221
|
+
el.animate {height: @options.expanded_height}, "fast", =>
|
|
222
|
+
@expand()
|
|
223
|
+
@options.onExpand()
|
|
224
|
+
el.trigger('expand')
|
|
225
|
+
|
|
226
|
+
# Loads contents of page identified by `i`
|
|
227
|
+
load: (i) ->
|
|
228
|
+
@log "load(#{i})"
|
|
229
|
+
ref = this
|
|
230
|
+
load_next_page = true
|
|
231
|
+
load_next_page = false if @options.pages[i]['last_request_empty']
|
|
232
|
+
load_next_page = true if @reloading
|
|
233
|
+
|
|
234
|
+
if @options.pages[i]['url'] && load_next_page
|
|
235
|
+
@loading.show()
|
|
236
|
+
url = @next_page_url(i)
|
|
237
|
+
data_type = @options.pages[i]['data_type'] if @options.pages[i]['data_type']
|
|
238
|
+
$.get url, (response, xhr) ->
|
|
239
|
+
ref.loading.hide()
|
|
240
|
+
ref.options.pages[i]['loaded'] = true
|
|
241
|
+
# If response is empty, let users know by loading an empty notification.
|
|
242
|
+
if $.trim(response) == '' || response.length == 0
|
|
243
|
+
ref.options.pages[i]['last_request_empty'] = true
|
|
244
|
+
ref.load_empty(i) if ref.reloading || !ref.options.pages[i]['panel_selector']
|
|
245
|
+
else
|
|
246
|
+
switch data_type
|
|
247
|
+
when "json"
|
|
248
|
+
# Parse json for requests of that type.
|
|
249
|
+
ref.load_json i, response
|
|
250
|
+
when "html"
|
|
251
|
+
else
|
|
252
|
+
# Parse html by default or for requests of that specific type.
|
|
253
|
+
ref.load_html i, response
|
|
254
|
+
, data_type
|
|
255
|
+
else
|
|
256
|
+
# Notify console if we couldn't load a page due to a missing URL.
|
|
257
|
+
@log "ERROR --> Couldn't load page because there was no url" unless @options.pages[i]['last_request_empty']
|
|
258
|
+
|
|
259
|
+
# For empty requests, insert notification text into page identified by `i`
|
|
260
|
+
load_empty: (i) ->
|
|
261
|
+
@log "load_empty(#{i})"
|
|
262
|
+
empty = Mustache.to_html(@tpl('empty'))
|
|
263
|
+
@load_html(i, empty)
|
|
264
|
+
@loading.hide()
|
|
265
|
+
$('li.empty').css('width',$('.ampn').first().width())
|
|
266
|
+
$('li.empty a').click =>
|
|
267
|
+
@goto(@options.pages.length-2)
|
|
268
|
+
|
|
269
|
+
# Load html content returned as `response` by XHR request into page identified by `i`
|
|
270
|
+
load_html: (i, response) ->
|
|
271
|
+
@log "load(#{i}) html"
|
|
272
|
+
selector = "##{@options.id} .pages .page:nth-child(#{(i+1)})"
|
|
273
|
+
selector += " ul" if @options.pages[i]['panels'] || @searching
|
|
274
|
+
$(selector).html(response).show()
|
|
275
|
+
@panels(i)
|
|
276
|
+
|
|
277
|
+
# Parse `response` as json data and build list-items for each element contained therein.
|
|
278
|
+
# This method assumes page identified by `i` contains an ample_panels instance.
|
|
279
|
+
load_json: (i, response) ->
|
|
280
|
+
@log "load(#{i}) json"
|
|
281
|
+
panels_loaded = if @options.pages[i]['panel_selector'] then true else false
|
|
282
|
+
ref = this
|
|
283
|
+
selector = "##{@options.id} .pages .page:nth-child(#{(i+1)}) ul"
|
|
284
|
+
$.each response, (j,el) ->
|
|
285
|
+
link = ref.build(el)
|
|
286
|
+
li = $('<li class="file"></li>').append(link)
|
|
287
|
+
if panels_loaded
|
|
288
|
+
$(selector).amplePanels('append', li)
|
|
289
|
+
else
|
|
290
|
+
$(selector).append(li)
|
|
291
|
+
ref.load_img(li.find('a'), el.sizes.tn)
|
|
292
|
+
$(selector).show()
|
|
293
|
+
@panels(i) unless panels_loaded
|
|
294
|
+
if @reloading
|
|
295
|
+
@reloading = false
|
|
296
|
+
@controls()
|
|
297
|
+
|
|
298
|
+
# Parse `response` from search results as json data.
|
|
299
|
+
load_results: (response) ->
|
|
300
|
+
@log "load_results()"
|
|
301
|
+
i = @options.pages.length - 1
|
|
302
|
+
|
|
303
|
+
if response.length > 0
|
|
304
|
+
# Build list-item for each item returned from search query.
|
|
305
|
+
$.each response, (j,el) =>
|
|
306
|
+
link = @build(el)
|
|
307
|
+
li = $('<li class="file"></li>').append(link)
|
|
308
|
+
$("#asset-results ul").amplePanels('append', li)
|
|
309
|
+
@load_img(link, el.sizes.tn)
|
|
310
|
+
else
|
|
311
|
+
# No results were returned, inject no-results verbiage.
|
|
312
|
+
no_results = Mustache.to_html(@tpl('no_results'))
|
|
313
|
+
@load_html(i, no_results)
|
|
314
|
+
@loading.hide()
|
|
315
|
+
$('li.empty').css('width',$('.ampn').first().width())
|
|
316
|
+
|
|
317
|
+
@options.pages[i]['panel_selector'] = "#asset-results ul"
|
|
318
|
+
@active_panel = $(@options.pages[i]['panel_selector'])
|
|
319
|
+
@searching = false
|
|
320
|
+
@loading.hide()
|
|
321
|
+
@controls()
|
|
322
|
+
|
|
323
|
+
# Builds each asset instance with proper attributes.
|
|
324
|
+
build: (el) ->
|
|
325
|
+
ref = this
|
|
326
|
+
show_url = Mustache.to_html @options.show_url, { id: el.id }
|
|
327
|
+
link = $("<a href=\"#{@options.base_url}#{show_url}\" draggable=\"true\"></a>")
|
|
328
|
+
.attr('id',"file-#{el.id}")
|
|
329
|
+
.attr('data-uid',"#{el.uid}")
|
|
330
|
+
.attr('data-filename',"#{el.filename}")
|
|
331
|
+
.attr('data-gravity', el.gravity)
|
|
332
|
+
.addClass('draggable')
|
|
333
|
+
if el.document == 'true'
|
|
334
|
+
link.addClass('document')
|
|
335
|
+
else
|
|
336
|
+
link.attr('data-orientation',el.orientation)
|
|
337
|
+
link.attr('data-size',el.size)
|
|
338
|
+
link.click ->
|
|
339
|
+
# Open a modal window on any asset instance's click event.
|
|
340
|
+
ref.modal_open(el)
|
|
341
|
+
false
|
|
342
|
+
link
|
|
343
|
+
|
|
344
|
+
# Opens modal window instance for asset detail.
|
|
345
|
+
modal_open: (data) ->
|
|
346
|
+
@modal_active = true
|
|
347
|
+
if data.document == 'true'
|
|
348
|
+
# Asset is a document, so lets instantiate PDFObject for viewing inline.
|
|
349
|
+
html = Mustache.to_html @tpl('pdf'),
|
|
350
|
+
filename: data.uid,
|
|
351
|
+
id: data.id,
|
|
352
|
+
mime_type: data.mime_type
|
|
353
|
+
$.facebox("<div class=\"asset-detail\">#{html}</div>")
|
|
354
|
+
myPDF = new PDFObject(
|
|
355
|
+
url: data.url
|
|
356
|
+
pdfOpenParams:
|
|
357
|
+
view: "Fit"
|
|
358
|
+
).embed("pdf")
|
|
359
|
+
else
|
|
360
|
+
# Asset is an image, lets display it inline, according to its orientation.
|
|
361
|
+
geometry = if data.orientation == 'portrait' then 'x300>' else '480x>'
|
|
362
|
+
url = "#{@options.base_url}#{@options.thumb_url}/#{geometry}?uid=#{data.uid}"
|
|
363
|
+
delete_url = Mustache.to_html @options.show_url, { id: data.id }
|
|
364
|
+
gravity_url = Mustache.to_html @options.gravity_url, { id: data.id }
|
|
365
|
+
gravity = $("a[data-uid='#{data.uid}']").first().attr('data-gravity')
|
|
366
|
+
keywords = ""
|
|
367
|
+
html = Mustache.to_html @tpl('show'),
|
|
368
|
+
filename: data.filename,
|
|
369
|
+
size: data.size,
|
|
370
|
+
mime_type: data.mime_type,
|
|
371
|
+
keywords: keywords,
|
|
372
|
+
src: url,
|
|
373
|
+
orientation: data.orientation,
|
|
374
|
+
id: data.id,
|
|
375
|
+
uid: data.uid,
|
|
376
|
+
gravity: gravity,
|
|
377
|
+
delete_url: "#{@options.base_url}#{delete_url}",
|
|
378
|
+
gravity_url: "#{@options.base_url}#{gravity_url}"
|
|
379
|
+
$.facebox("<div class=\"asset-detail\">#{html}</div>")
|
|
380
|
+
# Update the asset timestamp.
|
|
381
|
+
@touch(data)
|
|
382
|
+
|
|
383
|
+
# Create new image element from `src`, insert into `el` and fadeIn opacity.
|
|
384
|
+
load_img: (el,src) ->
|
|
385
|
+
img = new Image()
|
|
386
|
+
$(img).load(->
|
|
387
|
+
$(this).hide()
|
|
388
|
+
$(el).html this
|
|
389
|
+
$(this).fadeIn()
|
|
390
|
+
).attr src: src
|
|
391
|
+
|
|
392
|
+
# Generates the next URL for paginated record sets.
|
|
393
|
+
next_page_url: (i) ->
|
|
394
|
+
@options.pages[i]['pages_loaded'] = 0 unless @options.pages[i]['pages_loaded']
|
|
395
|
+
@options.pages[i]['pages_loaded'] += 1
|
|
396
|
+
"#{@options.pages[i]['url']}?page=#{@options.pages[i]['pages_loaded']}"
|
|
397
|
+
|
|
398
|
+
# By touching asset records, we update the timestamp value which ensures our recently
|
|
399
|
+
# viewed tab contains accurate results. Called from `modal_open()`
|
|
400
|
+
touch: (el) ->
|
|
401
|
+
@log "touch()"
|
|
402
|
+
touch_url = Mustache.to_html @options.touch_url, { id: el.id }
|
|
403
|
+
$.post "#{@options.base_url}#{touch_url}"
|
|
404
|
+
|
|
405
|
+
# Instantiate an amplePanels instance within page `i` if `@options.pages[i]['panels']` is true.
|
|
406
|
+
panels: (i) ->
|
|
407
|
+
ref = this
|
|
408
|
+
if @options.pages[i]['panels']
|
|
409
|
+
@log "panels(#{i})"
|
|
410
|
+
el = "##{@options.id} .pages .page:nth-child(#{(i+1)}) ul"
|
|
411
|
+
@options.pages[i]['panel_selector'] = el
|
|
412
|
+
@active_panel = el
|
|
413
|
+
@options.pages[i][''] = $(el).attr('id',"#{@options.pages[i]['id']}-panel")
|
|
414
|
+
$(el).parent().addClass('panels')
|
|
415
|
+
@controls()
|
|
416
|
+
$(el).amplePanels(@options.pages_options)
|
|
417
|
+
.bind 'slide_horizontal', (e,d,dir) ->
|
|
418
|
+
ref.load(i) if dir == 'next'
|
|
419
|
+
|
|
420
|
+
# Disable all panels, preventing any loading or key-driven actions from taking place within any amplePanels instance.
|
|
421
|
+
disable_panels: ->
|
|
422
|
+
@log "disable_panels()"
|
|
423
|
+
ref = this
|
|
424
|
+
@controls(false)
|
|
425
|
+
$.each @options.pages, (i,el) ->
|
|
426
|
+
$(ref.options.pages[i]['panel_selector']).amplePanels('disable') if ref.options.pages[i]['panel_selector']
|
|
427
|
+
|
|
428
|
+
# Enable panels instance contained with page identified by `i`.
|
|
429
|
+
# This allows key-events and previous/next actions to be executed.
|
|
430
|
+
enable_panel: (i) ->
|
|
431
|
+
@log "enable_panel(#{i})"
|
|
432
|
+
if @options.pages[i]['panel_selector']
|
|
433
|
+
@active_panel = @options.pages[i]['panel_selector']
|
|
434
|
+
$(@options.pages[i]['panel_selector']).amplePanels('enable')
|
|
435
|
+
@controls()
|
|
436
|
+
|
|
437
|
+
# Toggles display of left/right arrows which control amplePanels paging event, determined by `display`.
|
|
438
|
+
controls: (display=true) ->
|
|
439
|
+
@log "controls(#{display})"
|
|
440
|
+
display = false if $(@active_panel).find('li').length < @options.pages_options.per_page
|
|
441
|
+
switch display
|
|
442
|
+
when true
|
|
443
|
+
$('nav.controls').show()
|
|
444
|
+
when false
|
|
445
|
+
$('nav.controls').hide()
|
|
446
|
+
|
|
447
|
+
# Evaluates whether URL attached to page `i` has been loaded yet. Returns `boolean`.
|
|
448
|
+
already_loaded: (i) ->
|
|
449
|
+
typeof @options.pages[i]['loaded'] == 'boolean' && @options.pages[i]['loaded']
|
|
450
|
+
|
|
451
|
+
# Removes the asset from drop-target identified by `el`.
|
|
452
|
+
remove: (el) ->
|
|
453
|
+
parent = $(el).parent()
|
|
454
|
+
parent.find('.droppable').empty().html('<span>Drag Asset Here</span>')
|
|
455
|
+
parent.find('input').val('')
|
|
456
|
+
$(el).hide()
|
|
457
|
+
|
|
458
|
+
# Called upon successful DELETE request for a specific asset. Removes any instances of
|
|
459
|
+
# asset identified by `id`, closes the modal window and reloads the first tab.
|
|
460
|
+
delete: (id) ->
|
|
461
|
+
@log "delete(#{id})"
|
|
462
|
+
$("a#file-#{id}").parent().remove()
|
|
463
|
+
$(document).trigger('close.facebox')
|
|
464
|
+
@reload(0)
|
|
465
|
+
false
|
|
466
|
+
|
|
467
|
+
# Upon collapse, we disable panels.
|
|
468
|
+
collapse: ->
|
|
469
|
+
$("##{@options.id}-handle").css('bottom',-35).show().animate({'bottom': 0},'fast')
|
|
470
|
+
@disable_panels()
|
|
471
|
+
|
|
472
|
+
# Expands the asset toolbar and reenables the currently loaded tab.
|
|
473
|
+
expand: ->
|
|
474
|
+
@goto(@current)
|
|
475
|
+
|
|
476
|
+
# Setup all associated events.
|
|
477
|
+
events: ->
|
|
478
|
+
@modal_events()
|
|
479
|
+
@global_events()
|
|
480
|
+
@field_events()
|
|
481
|
+
@drop_events()
|
|
482
|
+
@drag_events()
|
|
483
|
+
@reload_events()
|
|
484
|
+
@resize_events()
|
|
485
|
+
@key_events()
|
|
486
|
+
@tab_events()
|
|
487
|
+
ref = this
|
|
488
|
+
# Collapse toolbar
|
|
489
|
+
$("##{@options.id} a.collapse").live 'click', =>
|
|
490
|
+
@toggle()
|
|
491
|
+
# Reload the first tab following a successful upload.
|
|
492
|
+
$('body').bind 'ample_uploadify.complete', =>
|
|
493
|
+
@reload(0)
|
|
494
|
+
# Bind event to succesful deletion of an asset.
|
|
495
|
+
$("a.asset-delete").live 'ajax:success', ->
|
|
496
|
+
id = parseInt $(this).attr('data-id')
|
|
497
|
+
ref.delete(id)
|
|
498
|
+
# Bind live event to any asset-remove element.
|
|
499
|
+
$("a.asset-remove").live 'click', ->
|
|
500
|
+
ref.remove(this)
|
|
501
|
+
false
|
|
502
|
+
# Bind `toggle()` method to toolbar handle.
|
|
503
|
+
$("##{@options.id}-handle").live 'click', =>
|
|
504
|
+
@toggle()
|
|
505
|
+
false
|
|
506
|
+
|
|
507
|
+
# Bind events for global left/right arrows to currently active panel's `previous()` and `next()` methods.
|
|
508
|
+
global_events: ->
|
|
509
|
+
$('a.global.next').click =>
|
|
510
|
+
$(@active_panel).amplePanels('next')
|
|
511
|
+
$('a.global.previous').click =>
|
|
512
|
+
$(@active_panel).amplePanels('previous')
|
|
513
|
+
|
|
514
|
+
# TODO: kill key events during drag?
|
|
515
|
+
drag_events: ->
|
|
516
|
+
@log "drag_events()"
|
|
517
|
+
|
|
518
|
+
# Open modal window when clicking an asset contained with a drop-target.
|
|
519
|
+
drop_events: ->
|
|
520
|
+
ref = this
|
|
521
|
+
$('.asset-drop .droppable a').live 'click', ->
|
|
522
|
+
id = $(this).attr("href")
|
|
523
|
+
$.get $(this).attr("href"), (response) ->
|
|
524
|
+
ref.modal_open(response)
|
|
525
|
+
, 'json'
|
|
526
|
+
false
|
|
527
|
+
|
|
528
|
+
# Toggle the active state of key_events when user focuses / blurs on textareas or input fields.
|
|
529
|
+
field_events: ->
|
|
530
|
+
@log "field_events()"
|
|
531
|
+
$('textarea, input').live 'blur', =>
|
|
532
|
+
@keys_enabled = true
|
|
533
|
+
$('textarea, input').live 'focus', =>
|
|
534
|
+
@keys_enabled = false
|
|
535
|
+
|
|
536
|
+
# Bind `reload()` method to assets-reload button.
|
|
537
|
+
reload_events: ->
|
|
538
|
+
@log "reload_events()"
|
|
539
|
+
reload = $('<a href="#" class="assets-reload"><span></span></a>')
|
|
540
|
+
reload.appendTo('.asset-refresh').click (e) =>
|
|
541
|
+
@reload(@current)
|
|
542
|
+
|
|
543
|
+
# Builds the markup for an asset dropped into a textarea.
|
|
544
|
+
resize_events: ->
|
|
545
|
+
$('.asset-resize').live 'click', =>
|
|
546
|
+
constraints = $('#asset-constraints').val()
|
|
547
|
+
uid = $('#asset-uid').val()
|
|
548
|
+
width = $('#asset-width').val()
|
|
549
|
+
height = $('#asset-height').val()
|
|
550
|
+
alt = $('#asset-alt').val()
|
|
551
|
+
geometry = "#{width}x#{height}#{constraints}"
|
|
552
|
+
if constraints == '#' && (width == '' || height == '')
|
|
553
|
+
alert 'Can\'t resize image using this geometry. Please select another option or supply a value for both width and height.'
|
|
554
|
+
else
|
|
555
|
+
url = encodeURI "#{@options.base_url}#{@options.thumb_url}/#{geometry}?uid=#{uid}"
|
|
556
|
+
url = url.replace('#','%23')
|
|
557
|
+
textile = "!#{url}(#{alt})!"
|
|
558
|
+
html = "<img src=\"#{url}\" alt=\"#{alt}\" />"
|
|
559
|
+
$(@target_textarea).insertAtCaret (if $(@target_textarea).hasClass('textile') then textile else html)
|
|
560
|
+
$(document).trigger('close.facebox')
|
|
561
|
+
|
|
562
|
+
# Toggles params when modal window is opened or closed.
|
|
563
|
+
modal_events: ->
|
|
564
|
+
@modal_active = false
|
|
565
|
+
$(document).bind 'afterClose.facebox', =>
|
|
566
|
+
@keys_enabled = true
|
|
567
|
+
@modal_active = false
|
|
568
|
+
$(document).bind 'loading.facebox', =>
|
|
569
|
+
@keys_enabled = false
|
|
570
|
+
@modal_active = true
|
|
571
|
+
|
|
572
|
+
# Setup amplePanels instance for search results and bind search field to methods that
|
|
573
|
+
# execute request and parse response.
|
|
574
|
+
search: ->
|
|
575
|
+
@log 'search()'
|
|
576
|
+
search_url = "#{@options.base_url}#{@options.search_url}"
|
|
577
|
+
i = ($("##{@options.id} .pages .page").length - 1)
|
|
578
|
+
ref = this
|
|
579
|
+
$('#asset-results ul').attr('id','assets-result-list').amplePanels(@options.pages_options)
|
|
580
|
+
@options.pages[i] = { loaded: true }
|
|
581
|
+
$('#asset-search').bind 'change', ->
|
|
582
|
+
$("#asset-results ul").amplePanels('empty')
|
|
583
|
+
ref.loading.show()
|
|
584
|
+
ref.controls(false)
|
|
585
|
+
ref.show(i)
|
|
586
|
+
ref.activate(i)
|
|
587
|
+
ref.searching = true
|
|
588
|
+
$('.asset-results').show()
|
|
589
|
+
$.post search_url, $(this).serialize(), (response) ->
|
|
590
|
+
ref.load_results(response)
|
|
591
|
+
, 'json'
|
|
592
|
+
|
|
593
|
+
# Bind events to tabs.
|
|
594
|
+
tab_events: ->
|
|
595
|
+
tabs = $("##{@options.id} a.tab")
|
|
596
|
+
ref = this
|
|
597
|
+
$.each tabs, (idx, el) ->
|
|
598
|
+
$(this).addClass('on') if idx == 0
|
|
599
|
+
$(el).click ->
|
|
600
|
+
ref.goto(idx)
|
|
601
|
+
false
|
|
602
|
+
|
|
603
|
+
# Controls all user keyboard events. Binds as neccesary and
|
|
604
|
+
# prevents interaction when key functions are disabled.
|
|
605
|
+
key_events: ->
|
|
606
|
+
ref = this
|
|
607
|
+
previous = 37
|
|
608
|
+
next = 39
|
|
609
|
+
up = 38
|
|
610
|
+
down = 40
|
|
611
|
+
escape = 27
|
|
612
|
+
|
|
613
|
+
# Why does this need to be on keyup?
|
|
614
|
+
$(document).keyup (e) =>
|
|
615
|
+
return unless @keys_enabled
|
|
616
|
+
switch e.keyCode
|
|
617
|
+
when escape
|
|
618
|
+
@toggle() unless @modal_active
|
|
619
|
+
e.stopPropagation();
|
|
620
|
+
|
|
621
|
+
# Keydown events.
|
|
622
|
+
$(document).keydown (e) =>
|
|
623
|
+
return unless @keys_enabled
|
|
624
|
+
if @active_panel
|
|
625
|
+
switch e.keyCode
|
|
626
|
+
when previous
|
|
627
|
+
$(@active_panel).amplePanels('previous')
|
|
628
|
+
when next
|
|
629
|
+
$(@active_panel).amplePanels('next')
|
|
630
|
+
when up
|
|
631
|
+
@previous()
|
|
632
|
+
when down
|
|
633
|
+
@next()
|
|
634
|
+
e.stopPropagation();
|
|
635
|
+
|
|
636
|
+
# Returns Mustache template for template defined by `view`
|
|
637
|
+
tpl: (view) ->
|
|
638
|
+
@tpls()[view]
|
|
639
|
+
|
|
640
|
+
# Returns object containing all Mustache templates.
|
|
641
|
+
tpls: ->
|
|
642
|
+
# Layout returns the HTML structure of the main asset toolbar.
|
|
643
|
+
layout: '
|
|
644
|
+
<div id="{{ id }}"><div class="background">
|
|
645
|
+
<a href="#" class="collapse">Close</a>
|
|
646
|
+
<div class="container">
|
|
647
|
+
<div id="{{ id }}-tabs" class="tabs">
|
|
648
|
+
<div class="asset-refresh"></div>
|
|
649
|
+
<div class="asset-search">
|
|
650
|
+
<input type="text" id="asset-search" name="q" placeholder="Enter keywords..." />
|
|
651
|
+
<label for="asset-search">Search</label>
|
|
652
|
+
</div>
|
|
653
|
+
{{{ tabs }}}
|
|
654
|
+
<a href="#" data-role="asset-search-results" class="tab asset-results">Results</a>
|
|
655
|
+
<span class="asset-loading"></span>
|
|
656
|
+
</div>
|
|
657
|
+
<div id="{{ id }}-pages" class="pages">
|
|
658
|
+
{{{ pages }}}
|
|
659
|
+
<div id="asset-results" class="page panels">
|
|
660
|
+
<ul></ul>
|
|
661
|
+
</div>
|
|
662
|
+
</div>
|
|
663
|
+
<nav class="controls">
|
|
664
|
+
<a href="#" class="global previous">Previous</a>
|
|
665
|
+
<a href="#" class="global next">Next</a>
|
|
666
|
+
</nav>
|
|
667
|
+
</div></div>
|
|
668
|
+
</div>'
|
|
669
|
+
# Handle returns HTML for the asset toolbar toggle handle.
|
|
670
|
+
handle: '<a href="#" id="{{ id }}-handle" class="handle">{{ title }}</a>'
|
|
671
|
+
# Tab returns HTML for each tab instance.
|
|
672
|
+
tab: '<a href="#" data-role="{{ id }}" class="tab {{ classes }}">{{ title }}</a>'
|
|
673
|
+
# Page returns generic HTML structure for each page.
|
|
674
|
+
page: '
|
|
675
|
+
<div id="{{ id }}" class="page">
|
|
676
|
+
<ul></ul>
|
|
677
|
+
</div>'
|
|
678
|
+
# Show represents the HTML used within the modal window detail view for non-document assets.
|
|
679
|
+
show: '
|
|
680
|
+
<div class="asset-detail">
|
|
681
|
+
<div class="asset-media {{ orientation }}">
|
|
682
|
+
<img src="{{ src }}" />
|
|
683
|
+
</div>
|
|
684
|
+
<input id="file_attachment_gravity" name="file[attachment_gravity]" type="hidden" value="{{ gravity }}">
|
|
685
|
+
<div id="asset-gravity-handle" style="display:none" data-role="gravity"></div>
|
|
686
|
+
<script type="text/javascript">
|
|
687
|
+
$(document).ready(function() {
|
|
688
|
+
new AmpleAssetsGravity({url: "{{ gravity_url }}", uid: "{{ uid }}"});
|
|
689
|
+
});
|
|
690
|
+
</script>
|
|
691
|
+
<div id="asset-gravity-notification">Asset updated successfully.</div>
|
|
692
|
+
<a href="{{ delete_url }}" class="asset-delete" data-id="{{ id }}" data-method="delete" data-confirm="Are you sure?" data-remote="true">Delete This Asset?</a>
|
|
693
|
+
<h3>{{ filename }}</h3><hr />
|
|
694
|
+
<ul>
|
|
695
|
+
<li>Original Dimensions: <strong>{{ size }}</strong></li>
|
|
696
|
+
<li>MimeType: <strong>{{ mime_type }}</strong></li>
|
|
697
|
+
<li>Orientation: <strong>{{ orientation }}</strong></li>
|
|
698
|
+
</ul>
|
|
699
|
+
<p>{{ keywords }}</p>
|
|
700
|
+
</div>'
|
|
701
|
+
# PDF represents the HTML used within the modal window detail view for document assets.
|
|
702
|
+
pdf: '
|
|
703
|
+
<div class="asset-detail">
|
|
704
|
+
<div id="pdf" class="asset-media"></div>
|
|
705
|
+
<a href="{{ delete_url }}" class="asset-delete" data-id="{{ id }}" data-method="delete" data-confirm="Are you sure?" data-remote="true">Delete This Asset?</a>
|
|
706
|
+
<h3>{{ filename }}</h3><hr />
|
|
707
|
+
<ul>
|
|
708
|
+
<li>MimeType: <strong>{{ mime_type }}</strong></li>
|
|
709
|
+
</ul>
|
|
710
|
+
<p>{{ keywords }}</p>
|
|
711
|
+
</div>'
|
|
712
|
+
# There's no content within this panels instance...
|
|
713
|
+
empty: '<li class="empty">Oops. There\'s nothing here. You should <a href="#">upload something</a>.</li>'
|
|
714
|
+
# Your search query returned an empty result set...
|
|
715
|
+
no_results: '<li class="empty">Sorry. Your search returned zero results.</li>'
|
|
716
|
+
# Drop returns HTML used in the modal window resize view. This is used when dropping an asset onto a textarea.
|
|
717
|
+
drop: '
|
|
718
|
+
<div class="asset-selection">
|
|
719
|
+
<div class="asset-media {{ orientation }}">
|
|
720
|
+
<img src="{{ src }}" />
|
|
721
|
+
</div>
|
|
722
|
+
<div class="asset-dimensions">
|
|
723
|
+
<p><label>Image Dimensions</label> ({{ dimensions }}, {{ orientation }})</p>
|
|
724
|
+
<p><select id="asset-constraints" name="asset-constraints">
|
|
725
|
+
<option value="">Maintain aspect ratio</option>
|
|
726
|
+
<option value="!">Force resize, don\'t maintain aspect ratio</option>
|
|
727
|
+
<option value=">">Resize only if image larger than this</option>
|
|
728
|
+
<option value="<">Resize only if image smaller than this</option>
|
|
729
|
+
<option value="^">Resize to minimum x,y, maintain aspect ratio</option>
|
|
730
|
+
<option value="#">Resize, crop if necessary to maintain aspect ratio</option>
|
|
731
|
+
</select></p>
|
|
732
|
+
<p><input type="hidden" id="asset-dimensions-target" name="asset-dimensions-target" value="" />
|
|
733
|
+
<input type="hidden" id="asset-uid" name="asset-uid" value="{{ uid }}" />
|
|
734
|
+
<input type="text" id="asset-width" name="asset-width" value="480" /> <span>x</span>
|
|
735
|
+
<input type="text" id="asset-height" name="asset-height" value="" /><br />
|
|
736
|
+
<input type="text" id="asset-alt" name="asset-alt" value="" placeholder="Alt text" />
|
|
737
|
+
<input type="submit" id="asset-resize" name="asset-resize" class="asset-resize" value="Insert" /></p>
|
|
738
|
+
|
|
739
|
+
</div>
|
|
740
|
+
<hr class="space" />
|
|
741
|
+
</div>'
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
# Extend draggable to elements added to the DOM after page load.
|
|
745
|
+
jQuery.fn.liveDraggable = (opts) ->
|
|
746
|
+
@live "mouseover", ->
|
|
747
|
+
$(this).data("init", true).draggable opts unless $(this).data("init")
|
|
748
|
+
|
|
749
|
+
# Insert `value` at the cursor position of the currently focused textarea or input field.
|
|
750
|
+
jQuery.fn.insertAtCaret = (value) ->
|
|
751
|
+
@each (i) ->
|
|
752
|
+
if document.selection
|
|
753
|
+
@focus()
|
|
754
|
+
sel = document.selection.createRange()
|
|
755
|
+
sel.text = value
|
|
756
|
+
@focus()
|
|
757
|
+
else if @selectionStart or @selectionStart is "0"
|
|
758
|
+
startPos = @selectionStart
|
|
759
|
+
endPos = @selectionEnd
|
|
760
|
+
scrollTop = @scrollTop
|
|
761
|
+
@value = @value.substring(0, startPos) + value + @value.substring(endPos, @value.length)
|
|
762
|
+
@focus()
|
|
763
|
+
@selectionStart = startPos + value.length
|
|
764
|
+
@selectionEnd = startPos + value.length
|
|
765
|
+
@scrollTop = scrollTop
|
|
766
|
+
else
|
|
767
|
+
@value += value
|
|
768
|
+
@focus()
|
|
769
|
+
|