asset_host_core 2.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.markdown +138 -0
  3. data/Rakefile +11 -0
  4. data/app/assets/images/asset_host_core/alert-overlay.png +0 -0
  5. data/app/assets/images/asset_host_core/arrow-left.gif +0 -0
  6. data/app/assets/images/asset_host_core/arrow-right.gif +0 -0
  7. data/app/assets/images/asset_host_core/fallback-img-rect.png +0 -0
  8. data/app/assets/images/asset_host_core/videoplayer-play.png +0 -0
  9. data/app/assets/images/asset_host_core/x.png +0 -0
  10. data/app/assets/javascripts/asset_host_core/admin/assets.js.coffee +221 -0
  11. data/app/assets/javascripts/asset_host_core/application.js +20 -0
  12. data/app/assets/javascripts/asset_host_core/assetadmin.js.coffee +56 -0
  13. data/app/assets/javascripts/asset_host_core/assethost.js.coffee.erb +17 -0
  14. data/app/assets/javascripts/asset_host_core/browserui.js.coffee +139 -0
  15. data/app/assets/javascripts/asset_host_core/chooserui.js.coffee +381 -0
  16. data/app/assets/javascripts/asset_host_core/client.js.coffee +29 -0
  17. data/app/assets/javascripts/asset_host_core/clients/BrightcoveVideo.js.coffee +64 -0
  18. data/app/assets/javascripts/asset_host_core/clients/templates/brightcove_embed.jst.eco +18 -0
  19. data/app/assets/javascripts/asset_host_core/clients/templates/vimeo_embed.jst.eco +1 -0
  20. data/app/assets/javascripts/asset_host_core/clients/templates/youtube_embed.jst.eco +1 -0
  21. data/app/assets/javascripts/asset_host_core/clients/vimeo_video.js.coffee +21 -0
  22. data/app/assets/javascripts/asset_host_core/clients/youtube_video.js.coffee +21 -0
  23. data/app/assets/javascripts/asset_host_core/cmsplugin.js.coffee +235 -0
  24. data/app/assets/javascripts/asset_host_core/models.js.coffee +586 -0
  25. data/app/assets/javascripts/asset_host_core/railsCMS.js.coffee +141 -0
  26. data/app/assets/javascripts/asset_host_core/slideshow.js.coffee +428 -0
  27. data/app/assets/javascripts/asset_host_core/templates/after_upload_button.jst.eco +3 -0
  28. data/app/assets/javascripts/asset_host_core/templates/asset_drop_asset.jst.eco +4 -0
  29. data/app/assets/javascripts/asset_host_core/templates/asset_modal.jst.eco +13 -0
  30. data/app/assets/javascripts/asset_host_core/templates/asset_preview.jst.eco +35 -0
  31. data/app/assets/javascripts/asset_host_core/templates/asset_search.jst.eco +2 -0
  32. data/app/assets/javascripts/asset_host_core/templates/browser_asset.jst.eco +1 -0
  33. data/app/assets/javascripts/asset_host_core/templates/browser_asset_tip.jst.eco +3 -0
  34. data/app/assets/javascripts/asset_host_core/templates/edit_modal.jst.eco +40 -0
  35. data/app/assets/javascripts/asset_host_core/templates/import_help.jst.eco +59 -0
  36. data/app/assets/javascripts/asset_host_core/templates/pagination_link.jst.eco +1 -0
  37. data/app/assets/javascripts/asset_host_core/templates/pagination_links.jst.eco +13 -0
  38. data/app/assets/javascripts/asset_host_core/templates/queued_file.jst.eco +11 -0
  39. data/app/assets/javascripts/asset_host_core/templates/save_and_close_view.jst.eco +4 -0
  40. data/app/assets/javascripts/asset_host_core/templates/upload_all_button.jst.eco +4 -0
  41. data/app/assets/javascripts/asset_host_core/templates/url_input.jst.eco +8 -0
  42. data/app/assets/stylesheets/asset_host_core/application.css.scss +384 -0
  43. data/app/assets/stylesheets/asset_host_core/jquery-ui.css +105 -0
  44. data/app/assets/stylesheets/asset_host_core/public.css.scss +204 -0
  45. data/app/assets/stylesheets/asset_host_core/slidetest.css.scss +93 -0
  46. data/app/controllers/asset_host_core/admin/api_users_controller.rb +72 -0
  47. data/app/controllers/asset_host_core/admin/assets_controller.rb +140 -0
  48. data/app/controllers/asset_host_core/admin/base_controller.rb +36 -0
  49. data/app/controllers/asset_host_core/admin/home_controller.rb +13 -0
  50. data/app/controllers/asset_host_core/admin/outputs_controller.rb +55 -0
  51. data/app/controllers/asset_host_core/api/assets_controller.rb +110 -0
  52. data/app/controllers/asset_host_core/api/base_controller.rb +43 -0
  53. data/app/controllers/asset_host_core/api/outputs_controller.rb +33 -0
  54. data/app/controllers/asset_host_core/application_controller.rb +43 -0
  55. data/app/controllers/asset_host_core/public_controller.rb +104 -0
  56. data/app/models/asset_host_core/api_user.rb +44 -0
  57. data/app/models/asset_host_core/api_user_permission.rb +6 -0
  58. data/app/models/asset_host_core/asset.rb +265 -0
  59. data/app/models/asset_host_core/asset_output.rb +69 -0
  60. data/app/models/asset_host_core/brightcove_video.rb +20 -0
  61. data/app/models/asset_host_core/output.rb +52 -0
  62. data/app/models/asset_host_core/permission.rb +19 -0
  63. data/app/models/asset_host_core/video.rb +8 -0
  64. data/app/models/asset_host_core/vimeo_video.rb +17 -0
  65. data/app/models/asset_host_core/youtube_video.rb +17 -0
  66. data/app/views/asset_host_core/admin/api_users/_form_fields.html.erb +5 -0
  67. data/app/views/asset_host_core/admin/api_users/edit.html.erb +26 -0
  68. data/app/views/asset_host_core/admin/api_users/index.html.erb +31 -0
  69. data/app/views/asset_host_core/admin/api_users/new.html.erb +17 -0
  70. data/app/views/asset_host_core/admin/api_users/show.html.erb +23 -0
  71. data/app/views/asset_host_core/admin/assets/index.html.erb +19 -0
  72. data/app/views/asset_host_core/admin/assets/metadata.html.erb +24 -0
  73. data/app/views/asset_host_core/admin/assets/show.html.erb +86 -0
  74. data/app/views/asset_host_core/admin/home/chooser.html.erb +49 -0
  75. data/app/views/asset_host_core/admin/outputs/_form_fields.html.erb +5 -0
  76. data/app/views/asset_host_core/admin/outputs/edit.html.erb +26 -0
  77. data/app/views/asset_host_core/admin/outputs/index.html.erb +27 -0
  78. data/app/views/asset_host_core/admin/outputs/new.html.erb +13 -0
  79. data/app/views/asset_host_core/admin/outputs/show.html.erb +17 -0
  80. data/app/views/asset_host_core/shared/_footerjs.html.erb +3 -0
  81. data/app/views/asset_host_core/shared/_navbar.html.erb +28 -0
  82. data/app/views/kaminari/_first_page.html.erb +3 -0
  83. data/app/views/kaminari/_gap.html.erb +3 -0
  84. data/app/views/kaminari/_last_page.html.erb +3 -0
  85. data/app/views/kaminari/_next_page.html.erb +3 -0
  86. data/app/views/kaminari/_page.html.erb +3 -0
  87. data/app/views/kaminari/_paginator.html.erb +17 -0
  88. data/app/views/kaminari/_prev_page.html.erb +3 -0
  89. data/app/views/layouts/asset_host_core/application.html.erb +54 -0
  90. data/app/views/layouts/asset_host_core/full_width.html.erb +32 -0
  91. data/app/views/layouts/asset_host_core/minimal.html.erb +45 -0
  92. data/config/initializers/simple_form.rb +142 -0
  93. data/config/initializers/simple_form_bootstrap.rb +45 -0
  94. data/config/locales/simple_form.en.yml +26 -0
  95. data/config/routes.rb +49 -0
  96. data/lib/asset_host_core.rb +38 -0
  97. data/lib/asset_host_core/config.rb +39 -0
  98. data/lib/asset_host_core/engine.rb +94 -0
  99. data/lib/asset_host_core/loaders.rb +34 -0
  100. data/lib/asset_host_core/loaders/asset_host.rb +30 -0
  101. data/lib/asset_host_core/loaders/base.rb +22 -0
  102. data/lib/asset_host_core/loaders/brightcove.rb +67 -0
  103. data/lib/asset_host_core/loaders/flickr.rb +114 -0
  104. data/lib/asset_host_core/loaders/url.rb +59 -0
  105. data/lib/asset_host_core/loaders/vimeo.rb +76 -0
  106. data/lib/asset_host_core/loaders/youtube.rb +90 -0
  107. data/lib/asset_host_core/model_methods.rb +61 -0
  108. data/lib/asset_host_core/paperclip.rb +4 -0
  109. data/lib/asset_host_core/paperclip/asset_thumbnail.rb +92 -0
  110. data/lib/asset_host_core/paperclip/attachment.rb +206 -0
  111. data/lib/asset_host_core/paperclip/trimmer.rb +33 -0
  112. data/lib/asset_host_core/resque_job.rb +13 -0
  113. data/lib/asset_host_core/version.rb +3 -0
  114. data/lib/tasks/asset_host_core_tasks.rake +4 -0
  115. data/spec/controllers/admin/api_users_controller_spec.rb +21 -0
  116. data/spec/controllers/admin/assets_controller_spec.rb +59 -0
  117. data/spec/controllers/admin/home_controller_spec.rb +4 -0
  118. data/spec/controllers/admin/outputs_controller_spec.rb +4 -0
  119. data/spec/controllers/api/assets_controller_spec.rb +133 -0
  120. data/spec/controllers/api/outputs_controller_spec.rb +51 -0
  121. data/spec/controllers/public_controller_spec.rb +4 -0
  122. data/spec/factories.rb +39 -0
  123. data/spec/features/api_users_spec.rb +78 -0
  124. data/spec/fixtures/api/brightcove/video.json +137 -0
  125. data/spec/fixtures/api/flickr/photos_getInfo.json +78 -0
  126. data/spec/fixtures/api/flickr/photos_getSizes.json +82 -0
  127. data/spec/fixtures/api/flickr/photos_licenses_getInfo.json +52 -0
  128. data/spec/fixtures/api/vimeo/video.json +28 -0
  129. data/spec/fixtures/api/youtube/discovery.json +5190 -0
  130. data/spec/fixtures/api/youtube/video.json +44 -0
  131. data/spec/fixtures/images/chipmunk.jpg +0 -0
  132. data/spec/fixtures/images/dude.jpg +0 -0
  133. data/spec/fixtures/images/ernie.jpg +0 -0
  134. data/spec/fixtures/images/fry.png +0 -0
  135. data/spec/fixtures/images/hat.jpg +0 -0
  136. data/spec/fixtures/images/spongebob.png +0 -0
  137. data/spec/fixtures/images/stars.jpg +0 -0
  138. data/spec/internal/app/controllers/application_controller.rb +16 -0
  139. data/spec/internal/app/controllers/sessions_controller.rb +24 -0
  140. data/spec/internal/app/models/user.rb +10 -0
  141. data/spec/internal/app/views/sessions/new.html.erb +14 -0
  142. data/spec/internal/config/database.yml +3 -0
  143. data/spec/internal/config/initializers/assethost_config.rb +57 -0
  144. data/spec/internal/config/routes.rb +7 -0
  145. data/spec/internal/db/combustion_test.sqlite +0 -0
  146. data/spec/internal/db/schema.rb +106 -0
  147. data/spec/internal/log/test.log +14769 -0
  148. data/spec/internal/public/favicon.ico +0 -0
  149. data/spec/internal/public/images/1_27f7745237849975ca90591c1fba5934_original. +0 -0
  150. data/spec/internal/public/images/1_7d33319deca787d5bb3f62ff06563ad2_original. +0 -0
  151. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original. +0 -0
  152. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original.jpg +0 -0
  153. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original.txt +0 -0
  154. data/spec/internal/public/images/1_e179cbd27e07cb55042d0db36cdac095_original. +0 -0
  155. data/spec/internal/public/images/1_e669edd3dfd74be66fc38416e82e3a37_original. +0 -0
  156. data/spec/lib/asset_host_core/loaders/asset_host_spec.rb +33 -0
  157. data/spec/lib/asset_host_core/loaders/brightcove_spec.rb +51 -0
  158. data/spec/lib/asset_host_core/loaders/flickr_spec.rb +72 -0
  159. data/spec/lib/asset_host_core/loaders/url_spec.rb +42 -0
  160. data/spec/lib/asset_host_core/loaders/vimeo_spec.rb +51 -0
  161. data/spec/lib/asset_host_core/loaders/youtube_spec.rb +73 -0
  162. data/spec/lib/asset_host_core/loaders_spec.rb +4 -0
  163. data/spec/lib/asset_host_core/model_methods_spec.rb +4 -0
  164. data/spec/lib/asset_host_core/paperclip/asset_thumbnail_spec.rb +4 -0
  165. data/spec/lib/asset_host_core/paperclip/attachment_spec.rb +4 -0
  166. data/spec/lib/asset_host_core/resque_job_spec.rb +4 -0
  167. data/spec/lib/asset_host_core_spec.rb +4 -0
  168. data/spec/models/api_user_spec.rb +58 -0
  169. data/spec/models/asset_output_spec.rb +4 -0
  170. data/spec/models/asset_spec.rb +4 -0
  171. data/spec/models/output_spec.rb +4 -0
  172. data/spec/models/permission_spec.rb +4 -0
  173. data/spec/spec_helper.rb +30 -0
  174. data/spec/support/fixture_loader.rb +9 -0
  175. data/spec/support/param_helper.rb +14 -0
  176. data/spec/support/permission_matcher.rb +17 -0
  177. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  178. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  179. data/vendor/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
  180. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  181. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  182. data/vendor/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
  183. data/vendor/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  184. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  185. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  186. data/vendor/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
  187. data/vendor/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
  188. data/vendor/assets/images/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
  189. data/vendor/assets/images/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
  190. data/vendor/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
  191. data/vendor/assets/javascripts/backbone.js +1158 -0
  192. data/vendor/assets/javascripts/backbone.modelbinding.js +475 -0
  193. data/vendor/assets/javascripts/exif.js +695 -0
  194. data/vendor/assets/javascripts/jquery-ui.js +5614 -0
  195. data/vendor/assets/javascripts/simplemodal.js +698 -0
  196. data/vendor/assets/javascripts/spin.jquery.js +81 -0
  197. data/vendor/assets/javascripts/spin.min.js +1 -0
  198. data/vendor/assets/javascripts/underscore.min.js +1 -0
  199. metadata +658 -0
@@ -0,0 +1,141 @@
1
+ #= require asset_host_core/assethost
2
+ #= require asset_host_core/models
3
+
4
+ class AssetHost.railsCMS
5
+ DefaultOptions:
6
+ el: ""
7
+ preview: true
8
+
9
+ #----------
10
+
11
+ constructor: (assetdata, options={}) ->
12
+ @options = _.defaults options, @DefaultOptions
13
+
14
+ # add in events
15
+ _.extend @, Backbone.Events
16
+
17
+ # -- load assets -- #
18
+
19
+ @assets = new AssetHost.Models.Assets assetdata
20
+
21
+ # -- initialize our views -- #
22
+
23
+ @assetsView = new railsCMS.CMSAssets collection:@assets
24
+ $(@options.el).html @assetsView.el
25
+
26
+ window.addEventListener "message", (evt) =>
27
+ if evt.data != "LOADED"
28
+ found = {}
29
+
30
+ # reconcile our asset list to the returned list
31
+ _(evt.data).each (a,i) =>
32
+ # do we have this asset?
33
+ if asset = @assets.get(a.id)
34
+ # yes... check for changed caption
35
+ asset.set caption:a.caption, ORDER:i
36
+ else
37
+ # no, needs to be added
38
+ asset = new AssetHost.Models.Asset(a)
39
+ asset.fetch(success: (aobj)=>aobj.set({caption:a.caption,ORDER:i});@assets.add(aobj))
40
+
41
+ found[ a.id ] = true
42
+
43
+ # now check for removed assets
44
+ remove = []
45
+ @assets.each (a,i) =>
46
+ if !found[a.get('id')]
47
+ # not in our return list... delete
48
+ remove.push(a)
49
+
50
+ for a in remove
51
+ @assets.remove(a)
52
+
53
+ @assets.sort()
54
+ @assetsView.render()
55
+
56
+ @trigger("assets",evt.data)
57
+ , false
58
+
59
+ #----------
60
+
61
+ @CMSAsset:
62
+ Backbone.View.extend
63
+ tagName: "li"
64
+
65
+ template:
66
+ '''
67
+ <%= asset.tags[ AssetHost.SIZES.thumb ] %>
68
+ <b><%= asset.title %> (<%= asset.size %>)</b>
69
+ <p><%= asset.caption %></p>
70
+ '''
71
+
72
+ #----------
73
+
74
+ initialize: ->
75
+ @render()
76
+ $(@el).attr("data-asset-url",@model.get('api_url'))
77
+ @model.bind "change", => @render()
78
+
79
+ #----------
80
+
81
+ render: ->
82
+ if @model.get('tags')
83
+ $( @el ).html _.template @template,asset:@model.toJSON()
84
+
85
+ return this
86
+
87
+ #----------
88
+
89
+ @CMSAssets:
90
+ Backbone.View.extend
91
+ tagName: "ul"
92
+ events: { "click button": "_popup" }
93
+
94
+ initialize: ->
95
+ @_views = {}
96
+ @collection.bind "reset", =>
97
+ _(@_views).each (a) => $(a.el).detach(); @_views = {}
98
+
99
+ @collection.bind 'add', (f) =>
100
+ console.log "add event from ", f
101
+ @_views[f.cid] = new railsCMS.CMSAsset({model:f,args:@options.args,rows:@options.rows})
102
+ @render()
103
+
104
+ @collection.bind 'remove', (f) =>
105
+ console.log "remove event from ", f
106
+ $(@_views[f.cid].el).detach()
107
+ delete @_views[f.cid]
108
+ @render()
109
+
110
+
111
+ @render()
112
+
113
+ #----------
114
+
115
+ _popup: (evt) ->
116
+ console.log("evt is ",evt)
117
+ evt.originalEvent.stopPropagation()
118
+ evt.originalEvent.preventDefault()
119
+ newwindow = window.open("http://#{AssetHost.SERVER}#{AssetHost.PATH_PREFIX}/a/chooser", 'chooser', 'height=620,width=1000,scrollbars=1')
120
+
121
+ # attach a listener to wait for the LOADED message
122
+ window.addEventListener "message", (evt) =>
123
+ if evt.data == "LOADED"
124
+ # dispatch our event with the asset data
125
+ newwindow.postMessage @collection.toJSON(), "http://#{AssetHost.SERVER}"
126
+ , false
127
+
128
+ return false
129
+
130
+ #----------
131
+
132
+ render: ->
133
+ @collection.each (a) =>
134
+ @_views[a.cid] ?= new railsCMS.CMSAsset({model:a,args:@options.args,rows:@options.rows})
135
+
136
+ views = _(@_views).sortBy (a) => a.model.get("ORDER")
137
+ $(@el).html( _(views).map (v) -> v.el )
138
+
139
+ $(@el).append( $("<li/>").html( $('<button/>',{text:"Pop Up Asset Chooser"})))
140
+
141
+ @
@@ -0,0 +1,428 @@
1
+ #= require ./assethost
2
+ #= require backbone
3
+ #= require ./models
4
+
5
+ class AssetHost.Slideshow
6
+ DefaultOptions:
7
+ el: "#photo"
8
+ initial: 4
9
+ start: 0
10
+ imgwidth: null
11
+ imgheight: null
12
+ margin: 12
13
+
14
+ constructor: (options) ->
15
+ @options = _(_({}).extend(@DefaultOptions)).extend options||{}
16
+
17
+ # add in events
18
+ _.extend(this, Backbone.Events)
19
+
20
+ $ =>
21
+ # -- create hidden element for dimensioning -- #
22
+ @hidden = $ "<div/>", style:"position:absolute; top:-10000px; width:0px; height:0px;"
23
+ $('body').append @hidden
24
+
25
+ # -- get our parent element -- #
26
+
27
+ @el = $ @options.el
28
+
29
+ # -- create asset collection -- #
30
+
31
+ @assets = new Slideshow.Assets @options.assets
32
+
33
+ # -- create our nav buttons -- #
34
+
35
+ @nav = new Slideshow.NavigationLinks current:@options.start,total:@assets.length
36
+
37
+ # -- set up our slides -- #
38
+
39
+ @slides = new Slideshow.Slides
40
+ collection: @assets
41
+ hidden: @hidden
42
+ initial: @options.initial
43
+ imgwidth: @options.imgwidth
44
+ imgheight: @options.imgheight
45
+ nav: @nav
46
+ margin: @options.margin
47
+
48
+ @el.html @slides.el
49
+ @slides.render()
50
+
51
+ # -- bind slides and nav together -- #
52
+ @nav.bind "slide", (idx) => @slides.slideTo(idx)
53
+ @slides.bind "slide", (idx) =>
54
+ @nav.setCurrent idx
55
+ @trigger "slide", idx
56
+
57
+ #----------
58
+
59
+ @Asset:
60
+ Backbone.Model.extend
61
+ initialize: ->
62
+ # do something
63
+
64
+ @Assets:
65
+ Backbone.Collection.extend
66
+ url: "/"
67
+ model: @Asset
68
+
69
+ #----------
70
+
71
+ @Slide:
72
+ Backbone.View.extend
73
+ tagName: 'li'
74
+ className: "slide"
75
+
76
+ template:
77
+ '''
78
+ <div class="text" style="width: <%= width %>px;margin: 0 auto">
79
+ <div class="credit"><%= credit %></div>
80
+ <p><%= caption %></p>
81
+ </div>
82
+ '''
83
+
84
+ fullTemplate:
85
+ '''
86
+
87
+ '''
88
+
89
+ #----------
90
+
91
+ initialize: ->
92
+ @slides = @options.slides
93
+ @hidden = @options.hidden
94
+ @index = @options.index
95
+
96
+ #----------
97
+
98
+ render: ->
99
+ # -- choose image size -- #
100
+
101
+ # sort of sizes hash
102
+ sizes = @model.get("sizes")
103
+ _(sizes).each (v, k) => v.key = k
104
+ sizes = _(sizes).sortBy (v) -> -v.width
105
+
106
+ # now take the first size that fits
107
+ @imgSize = _(sizes).find (v,i) =>
108
+ if v.width <= $(@el).width()
109
+ # take it
110
+ return true
111
+ else
112
+ return false
113
+
114
+ # -- render text elements -- #
115
+
116
+ # we have to render twice... once to hidden and once to @el.
117
+ # this allows us to get dimensions
118
+
119
+ # create temp element and render
120
+ tmp = $ "<div/>", width:@imgSize.width
121
+
122
+ $(tmp).html _.template @template,
123
+ credit: @model.get("credit")
124
+ caption: @model.get("caption")
125
+ url: @model.get("url")
126
+ width: @imgSize.width
127
+
128
+ @hidden.append tmp
129
+
130
+ # get dimensions
131
+ @textHeight = $(tmp).height()
132
+ @imgHeight = if $(@el).height() then $(@el).height() - @textHeight else @imgSize.height
133
+
134
+ # and remove...
135
+ $(tmp).detach()
136
+
137
+ # now render caption and credit for real
138
+ $(@el).html _.template @template,
139
+ credit: @model.get("credit")
140
+ caption: @model.get("caption")
141
+ url: @model.get("url")
142
+ width: @imgSize.width
143
+
144
+ # -- determine final image size -- #
145
+
146
+ # because we're choosing our image based on horizontal space,
147
+ # we should only have to do our scaling off the vertical size
148
+
149
+ imgh = @imgSize.height
150
+ @scale = 1
151
+
152
+ if imgh > @imgHeight
153
+ vs = @imgHeight / imgh
154
+
155
+ if vs < 1
156
+ @scale = vs
157
+
158
+ # -- create img div with final dimensions -- #
159
+
160
+ @imgDiv = $ "<div/>",
161
+ class:"ah_imgholder"
162
+ style:"width:#{@imgSize.width * @scale}px;height:#{@imgSize.height * @scale}px"
163
+
164
+ $(@el).prepend @imgDiv
165
+
166
+ @
167
+
168
+ #----------
169
+
170
+ loadImage: ->
171
+ if @slides.current == @index then $(@el).fadeOut() else $(@el).hide()
172
+
173
+ @img = $ "<img/>",
174
+ src: @model.get("urls")[@imgSize.key]
175
+ width: @imgSize.width * @scale
176
+ height: @imgSize.height * @scale
177
+
178
+ @hidden.append @img
179
+ @img.load (evt) =>
180
+
181
+ # -- center -- #
182
+
183
+ @imgDiv.css "margin-left", ($(@el).width() - @img.width())/2
184
+ @imgDiv.css "margin-top", (@imgHeight - @img.height())/2
185
+
186
+ # -- add to our element -- #
187
+
188
+ @img.detach()
189
+ @imgDiv.html @img
190
+
191
+ if @slides.current == @index then $(@el).fadeIn('slow') else $(@el).show()
192
+
193
+ # -- tell the loader that we're done -- #
194
+
195
+ @trigger "imgload"
196
+
197
+ #----------
198
+
199
+ @Slides:
200
+ Backbone.View.extend
201
+ className: "slideview"
202
+
203
+ events:
204
+ 'mouseover': '_mouseover'
205
+ 'mouseout': '_mouseout'
206
+
207
+ initialize: ->
208
+ @hidden = @options.hidden
209
+ @slides = []
210
+
211
+ @collection.each (a,idx) =>
212
+ s = new Slideshow.Slide model:a, slides:@, hidden:@hidden, index:idx
213
+ @slides[idx] = s
214
+
215
+ # we need to know the text height of our first slide to
216
+ # dimension space for the rest of the slides
217
+ s = @slides[0]
218
+ $(s.el).css "width", @options.imgwidth+"px"
219
+ s.render()
220
+ txth = s.textHeight
221
+
222
+ @swidth = @options.imgwidth
223
+ @sheight = @options.imgheight + txth
224
+
225
+ console.log "slide height should be ", @sheight
226
+
227
+ @queued = []
228
+ @loaded = []
229
+ @active = false
230
+
231
+ @current = null
232
+
233
+ @hasmouse = false
234
+
235
+ $(window).bind "keydown", (evt) => @_keyhandler(evt)
236
+
237
+ #----------
238
+
239
+ render: () ->
240
+ #$(@el).css "position", "absolute"
241
+ $(@el).attr "tabindex", -1
242
+
243
+ $(@el).css "width", @swidth+"px"
244
+
245
+ totalw = @collection.length * @swidth
246
+
247
+ # check if slide0 has a right margin, and adjust width accordingly
248
+ if @options.margin
249
+ totalw = totalw + @collection.length * @options.margin
250
+
251
+ # height defaults to slide height
252
+ svheight = @sheight
253
+
254
+ if @options.nav
255
+ $(@el).html @options.nav.el
256
+ @options.nav.render()
257
+
258
+ navh = $(@options.nav.el).outerHeight()
259
+
260
+ # add nav height to slideview height
261
+ svheight = svheight + navh
262
+
263
+ # now set height...
264
+ $(@el).css "height", svheight+"px"
265
+
266
+ # create view tray
267
+ @view = $ '<ul/>', style:"position:relative;width:#{totalw}px;height:#{@sheight}px"
268
+
269
+ # drop view into element
270
+ $(@el).prepend @view
271
+
272
+ # add our slides
273
+ _(@slides).each (s,idx) =>
274
+ s.bind "imgload", => @_loaded s, idx
275
+ $(s.el).css "width", @swidth+"px"
276
+ $(s.el).css "height", @sheight+"px"
277
+ $(s.el).css "left", @swidth*idx + (@options.margin||0)*idx + "px"
278
+
279
+ $(@view).append s.render().el
280
+
281
+ # create our load queue
282
+ @queueSlides _.range 0,4
283
+
284
+ #----------
285
+
286
+ _mouseover: (e) ->
287
+ @hasmouse = true
288
+
289
+ _mouseout: (e) ->
290
+ @hasmouse = false
291
+
292
+ _keyhandler: (e) ->
293
+ if @hasmouse
294
+ # is this a keypress we care about?
295
+ if e.which == 37
296
+ @slideBy(-1)
297
+ else if e.which == 39
298
+ @slideBy(1)
299
+
300
+ #----------
301
+
302
+ slideTo: (idx) ->
303
+ # figure out where slide[idx] is at
304
+ @view.stop().animate {left: -$(@slides[idx].el).position().left}, "slow"
305
+ @current = idx
306
+
307
+ @trigger "slide", idx
308
+
309
+ @_updateLoadQueue()
310
+
311
+ #----------
312
+
313
+ slideBy: (idx) ->
314
+ t = @current + idx
315
+
316
+ if @slides[t]
317
+ @slideTo(t)
318
+
319
+ #----------
320
+
321
+ queueSlides: (indexes...) ->
322
+ _(_(indexes).flatten()).each (i) =>
323
+ if !@loaded[i] || @loaded[i] == 0 && !_(@queued).contains(i)
324
+ console.log "queuing #{i}"
325
+ @queued.push i
326
+
327
+ if !@active
328
+ @_fireUpQueue()
329
+
330
+ #----------
331
+
332
+ _updateLoadQueue: ->
333
+ if !@loaded[@current] || @loaded[@current] == 0
334
+ @queued.unshift @current
335
+
336
+ toQueue = []
337
+ _(_.range(@current+1,@current+4)).each (i) => toQueue.push(i) if @slides[i]
338
+ _(_.range(@current-2,@current)).each (i) => toQueue.push(i) if @slides[i]
339
+
340
+ @queueSlides toQueue
341
+
342
+ #----------
343
+
344
+ _fireUpQueue: ->
345
+ return false if !@queued || @queued.length == 0
346
+
347
+ console.log "_fireUpQueue with queue of #{@queued}"
348
+
349
+ i = @queued.shift()
350
+ s = @slides[i]
351
+
352
+ if !@loaded[i] || @loaded[i] == 0
353
+ console.log "triggering load on #{i}"
354
+ @loaded[i] = 1
355
+ @active = i
356
+ s.loadImage()
357
+ else
358
+ @_fireUpQueue()
359
+
360
+ #----------
361
+
362
+ _loaded: (s,idx) ->
363
+ console.log "got _loaded for #{idx}"
364
+ @loaded[idx] = 2
365
+
366
+ if @active == idx
367
+ @active = null
368
+ @_fireUpQueue()
369
+
370
+ #----------
371
+
372
+ @NavigationLinks:
373
+ Backbone.View.extend
374
+ className: "nav"
375
+
376
+ events:
377
+ 'click button': '_buttonClick'
378
+
379
+ template:
380
+ '''
381
+ <div style="width: 15%;">
382
+ <button <% print(prev ? "data-idx='"+prev+"' class='prev-arrow'" : "class='disabled prev-arrow'"); %> >Prev</button>
383
+ </div>
384
+ <div class="buttons" style="width:70%;"></div>
385
+ <div style="width: 15%">
386
+ <button <% print(next ? "data-idx='"+next+"' class='next-arrow'" : "class='disabled next-arrow'"); %> >Next</button>
387
+ </div>
388
+ <br style="clear:both;line-height:0;height:0"/>
389
+ '''
390
+
391
+ #----------
392
+
393
+ initialize: ->
394
+ @total = @options.total
395
+ @current = Number(@options.current) + 1
396
+
397
+ @render()
398
+
399
+ #----------
400
+
401
+ _buttonClick: (evt) ->
402
+ idx = $(evt.currentTarget).attr "data-idx"
403
+
404
+ if idx
405
+ idx = Number(idx) - 1
406
+ console.log "nav trigger slide to #{idx}"
407
+ @trigger "slide", idx
408
+
409
+ #----------
410
+
411
+ setCurrent: (idx) ->
412
+ @current = Number(idx) + 1
413
+ console.log "nav set current to #{@current}"
414
+ @render()
415
+
416
+ #----------
417
+
418
+ render: ->
419
+ buttons = _([1..@total]).map (i) =>
420
+ $("<button/>", {"data-idx":i, text:i, class:if @current == i then "current" else ""})[0]
421
+
422
+ $(@el).html _.template @template,
423
+ current: @current,
424
+ total: @total,
425
+ prev: if @current - 1 > 0 then @current - 1 else null
426
+ next: if @current + 1 <= @total then @current + 1 else null
427
+
428
+ @$(".buttons").html buttons