shutterbug 0.4.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +4 -86
- data/lib/shutterbug.rb +1 -1
- data/lib/shutterbug/handlers.rb +0 -1
- data/lib/shutterbug/handlers/convert_handler.rb +11 -24
- data/lib/shutterbug/phantom_job.rb +25 -7
- data/lib/shutterbug/rackapp.rb +0 -1
- data/spec/shutterbug/rackapp_spec.rb +0 -8
- metadata +2 -23
- data/bower.json +0 -26
- data/demo/The_Scream.jpg +0 -0
- data/demo/canvas_example.html +0 -36
- data/demo/iframe.html +0 -30
- data/demo/iframe2.html +0 -30
- data/demo/iframe3.html +0 -29
- data/demo/iframe4.html +0 -29
- data/demo/iframe_example.html +0 -38
- data/demo/iframe_no_shutterbug.html +0 -20
- data/demo/index.html +0 -20
- data/demo/main.css +0 -9
- data/demo/nested_iframe_example.html +0 -41
- data/demo/oil-and-water/heatbath.svg +0 -20
- data/demo/oil-and-water/ke-gradient.svg +0 -27
- data/demo/oil-and-water/oil-and-water.svg +0 -487
- data/demo/simple_example.html +0 -35
- data/demo/svg_example.html +0 -571
- data/lib/shutterbug/handlers/js_file_handler.rb +0 -30
- data/lib/shutterbug/handlers/shutterbug.js +0 -388
- data/spec/shutterbug/js_file_handler_spec.rb +0 -5
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZDhhMGNiMWQ4MGY0Yzc3N2FkNWEyYWY4OWMyYjhmOTgzYWE3YjBlYg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjM4NDMyODcyYWIxNWJjN2FkN2MzZjRjMjA2NDExODBjNGZmODFlOQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YTk4ZTlhOGYxOTBiMGY2OTE0ZDc2YThlMjE4MDI2NzNhZmY1ZmMwYTVhYjE2
|
10
|
+
ZjhjNTUzMzY4MTMzYWQyMWQ4YmM0ZDM2Yzk2NDhlNjk2MjIyNTM3MDRjOWIx
|
11
|
+
ODU2ZWFhMzU5OGVkNDZiMzdhZDA5MDhjNjBmZGVmZDg5ZjA0OWQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTkwNDc5OTFkNWRiNjMxNzEyMTg2NjRiMTY2MjRiODEwMjcwMmU5NWRlMWJk
|
14
|
+
Zjk0MDE2YTdjN2IyM2Q3M2VhNmIwZTA3YmJmOGYxMjM0ZDUxNmY2ZTM3ODNl
|
15
|
+
ODIyNDAwNjcwNDU3NjdkZWQ4ZTA3MzU2YmU4ZjcyZDJjNDA1NTM=
|
data/README.md
CHANGED
@@ -6,19 +6,7 @@
|
|
6
6
|
|
7
7
|
## Overview ##
|
8
8
|
|
9
|
-
Shutterbug has two parts: a browser javascript library for taking html snapshots, and a server side utility for turning those html snapshots into images.
|
10
|
-
|
11
|
-
### Browser Javascript library
|
12
|
-
|
13
|
-
By itself `shutterbug.js` is useful for authors of iframe'able content. With `shutterbug.js` on the iframe'd page, the parent window can request an html snapshot even if the iframe'd page is on a different domain. To enable this functionality you need to add the following lines to your iframe'able page:
|
14
|
-
|
15
|
-
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
|
16
|
-
<script src="shutterbug.js"></script>
|
17
|
-
<script>new Shutterbug('body');</script>
|
18
|
-
|
19
|
-
The `shutterbug.js` file is located in this repository: `lib/shutterbug/handlers/shutterbug.js`
|
20
|
-
|
21
|
-
`shutterbug.js` also includes the API to talk to the server side utility to generate a image of the html snapshot. See the [Usage section](#usage) below for information.
|
9
|
+
Shutterbug has two parts: a browser javascript library for taking html snapshots, and a server side utility for turning those html snapshots into images. This repository consists of JavaScript library.
|
22
10
|
|
23
11
|
### Server Side Utility
|
24
12
|
|
@@ -40,7 +28,6 @@ Shutterbug is distributed as a Ruby Gem. The rack service delivers a javascript
|
|
40
28
|
|
41
29
|
## Requirements & Dependencies
|
42
30
|
|
43
|
-
* shutterbug.js requires [JQuery](http://jquery.com/), and expects JQuery to be found via window.$ . Note that shutterbug will allow you to pass in JQuery through its constructor too, in the event that its not at window.$
|
44
31
|
* Ruby 1.9x or greater is required to run the Rack application.
|
45
32
|
* [PhantomJS](http://phantomjs.org/) is requird to run the Rack application.
|
46
33
|
|
@@ -66,78 +53,6 @@ Or install it yourself as:
|
|
66
53
|
|
67
54
|
See [LICENSE.md](LICENSE.md) for more information.
|
68
55
|
|
69
|
-
## Usage
|
70
|
-
|
71
|
-
After adding `use Shutterbug::Rackapp` to your config.ru file, you can convert pieces of your web-page into png images. Just follow these steps:
|
72
|
-
|
73
|
-
Include the following javascript in your pages:
|
74
|
-
|
75
|
-
<script src='http://<yourhost:port>/shutterbug/shutterbug.js' type='text/javascript'></script>
|
76
|
-
|
77
|
-
Elsewhere in your javascript, something like this:
|
78
|
-
|
79
|
-
var shutterbug = new Shutterbug('#sourceselector', '#outselector',optCallbackFn, optIdentifier);
|
80
|
-
$('#button').click(function() {
|
81
|
-
shutterbug.getDomSnapshot();
|
82
|
-
});
|
83
|
-
|
84
|
-
This will replace the contents of `$("#outselector")` with an `<img src="http://<yourhost:port>/gete_png/sha1hash>` tag which will magically spring into existance. `optCallbackFn` is an optional callback function which will be invoked with the `<img src=..>` tag. `optIdentifier` is useful when there are multiple snapshot buttons targetting multiple iframes, and you need to verify the destination for various snapshot window message events.
|
85
|
-
|
86
|
-
## Advanced usage
|
87
|
-
|
88
|
-
You can specify a failure callback on your shutterbug object. This callback will be invoked when the server response was not 200:
|
89
|
-
|
90
|
-
var shutterbug = new Shutterbug('#sourceselector', '#outselector',optCallbackFn, optIdentifier);
|
91
|
-
shutterbug.setFailureCallback(function(jqXHR, textStatus, errorThrown) {
|
92
|
-
alert("Something went wrong: " + textStatus);
|
93
|
-
});
|
94
|
-
|
95
|
-
### IFrame support
|
96
|
-
|
97
|
-
If the element being snapshot'd is an iframe then the iframe needs to handle a postMessage API.
|
98
|
-
Shutterbug will run something like the following JS to get the html of the iframe
|
99
|
-
|
100
|
-
iframe.contentWindow.postMessage(JSON.stringify({
|
101
|
-
type: 'htmlFragRequest',
|
102
|
-
id: id
|
103
|
-
}), "*");
|
104
|
-
|
105
|
-
It is passing a JSON message that specifies the 'type' of message and passes an id so the caller can match up the response.
|
106
|
-
Currently the id will be the optIdentifier passed to the Shutterbug constructor in the parent window.
|
107
|
-
The iframe should respond by posting back to the source window a message like:
|
108
|
-
|
109
|
-
message.source.postMessage(JSON.stringfy({
|
110
|
-
type: 'htmlFragResponse',
|
111
|
-
value: {
|
112
|
-
content: 'htmlContent'
|
113
|
-
css: '<div><link rel='stylesheet'..><style>...</style></div>',
|
114
|
-
width: width,
|
115
|
-
height: height,
|
116
|
-
base_url: 'url that resource urls in content and css are relative to'
|
117
|
-
},
|
118
|
-
id: id // id sent in in the 'htmlFragRequest'
|
119
|
-
}), message.origin);
|
120
|
-
|
121
|
-
The `shutterbug.js` script actually adds a handler for this postMessage API when the Shutterbug constructor is called.
|
122
|
-
So if shutterbug is included in the iframe html as described in the Usage section above, then a parent page can snapshot
|
123
|
-
the iframe. The iframe's html doesn't need the button with a click hander because the parent window will trigger things.
|
124
|
-
Additionally the `#outselector` in the iframe is not used.
|
125
|
-
|
126
|
-
You could also reimplement this API in the html of the iframe if you'd like. However the shutterbug implementation includes
|
127
|
-
some useful things like finding and including all the css on the page, and 'serializing' canvas elements into images.
|
128
|
-
|
129
|
-
### Shutterbug JQuery custom events ###
|
130
|
-
|
131
|
-
Shutterbug emits a jQuery custom event called `shutterbug-saycheese` just prior to copying styles, elements, and canvas contents to the document fragment. This allows applications to do any preparation required before they are ready to be snapshotted.
|
132
|
-
|
133
|
-
In your application, you can register your event-handler like this:
|
134
|
-
|
135
|
-
$(window).on('shutterbug-saycheese', function() {
|
136
|
-
api.renderCanvas();
|
137
|
-
});
|
138
|
-
|
139
|
-
After all elements are copied, emits a `shutterbug-asyouwere` event.
|
140
|
-
|
141
56
|
### Deploying on Heroku ###
|
142
57
|
|
143
58
|
To deploy on heroku, you are going to want to modify your stack following [these instructions](http://nerdery.crowdmob.com/post/33143120111/heroku-ruby-on-rails-and-phantomjs).
|
@@ -179,6 +94,9 @@ And a Procfile which looks like this:
|
|
179
94
|
|
180
95
|
## Changes ##
|
181
96
|
|
97
|
+
* December 11, 2014 – v 0.5.0
|
98
|
+
* JS lib, JS handler and demos removed (as they are part of the new [shutterbug.js](https://github.com/concord-consortium/shutterbug.js) repo now).
|
99
|
+
|
182
100
|
* December 4, 2014 – v 0.4.3
|
183
101
|
* Added support of various image formats and quality settings.
|
184
102
|
|
data/lib/shutterbug.rb
CHANGED
data/lib/shutterbug/handlers.rb
CHANGED
@@ -2,7 +2,6 @@ module Shutterbug
|
|
2
2
|
module Handlers
|
3
3
|
autoload :ConvertHandler, "shutterbug/handlers/convert_handler"
|
4
4
|
autoload :DirectUploadHandler, "shutterbug/handlers/direct_upload_handler"
|
5
|
-
autoload :JsFileHandler, "shutterbug/handlers/js_file_handler"
|
6
5
|
autoload :FileHandler, "shutterbug/handlers/file_handler"
|
7
6
|
end
|
8
7
|
end
|
@@ -17,33 +17,20 @@ module Shutterbug
|
|
17
17
|
helper.response(response_text, 'text/plain')
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
val *= 100
|
30
|
-
else
|
31
|
-
val *= 100
|
32
|
-
end
|
33
|
-
# PhantomJS expects integer.
|
34
|
-
val.to_i
|
20
|
+
def get_options(req)
|
21
|
+
opts = {}
|
22
|
+
opts[:html] = req.POST()['content']
|
23
|
+
opts[:width] = req.POST()['width']
|
24
|
+
opts[:height] = req.POST()['height']
|
25
|
+
opts[:css] = req.POST()['css']
|
26
|
+
opts[:format] = req.POST()['format']
|
27
|
+
opts[:quality] = req.POST()['quality']
|
28
|
+
return opts
|
35
29
|
end
|
36
30
|
|
37
31
|
def convert(req)
|
38
|
-
|
39
|
-
|
40
|
-
height = req.POST()['height'] || 700
|
41
|
-
css = req.POST()['css'] || ""
|
42
|
-
format = req.POST()['format'] || "png"
|
43
|
-
quality = req.POST()['quality'] || 1
|
44
|
-
quality = convert_quality(quality, format)
|
45
|
-
config = self.class.config
|
46
|
-
job = PhantomJob.new(config.base_url(req), html, css, width, height, format, quality)
|
32
|
+
config = self.class.config
|
33
|
+
job = PhantomJob.new(config.base_url(req), get_options(req))
|
47
34
|
unless (cache_entry = config.cache_manager.find(job.cache_key))
|
48
35
|
job.rasterize
|
49
36
|
html_entry = Shutterbug::CacheManager::CacheEntry.new(job.html_file)
|
@@ -11,14 +11,32 @@ module Shutterbug
|
|
11
11
|
File.join(File.dirname(__FILE__),'rasterize.js')
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def convert_quality(val, format)
|
15
|
+
# Client sends quality between 0 and 1 (similar to .toDataURL() second argument).
|
16
|
+
# This conversion tries to ensure that the size of the final image is similar to
|
17
|
+
# .toDataURL() output with given quality settings.
|
18
|
+
val = val.to_f
|
19
|
+
case format
|
20
|
+
when "png"
|
21
|
+
val *= 10
|
22
|
+
when "jpeg"
|
23
|
+
val *= 100
|
24
|
+
else
|
25
|
+
val *= 100
|
26
|
+
end
|
27
|
+
# PhantomJS expects integer.
|
28
|
+
val.to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(base_url, options)
|
15
32
|
@base_url = base_url
|
16
|
-
@html = html
|
17
|
-
@css = css
|
18
|
-
@width = width
|
19
|
-
@height = height
|
20
|
-
@format = format
|
21
|
-
@quality = quality
|
33
|
+
@html = options[:html] || ""
|
34
|
+
@css = options[:css] || ""
|
35
|
+
@width = options[:width] || 1000
|
36
|
+
@height = options[:height] || 700
|
37
|
+
@format = options[:format] || "png"
|
38
|
+
@quality = options[:quality] || 1
|
39
|
+
@quality = convert_quality(@quality, @format)
|
22
40
|
@config = Configuration.instance
|
23
41
|
end
|
24
42
|
|
data/lib/shutterbug/rackapp.rb
CHANGED
@@ -68,13 +68,5 @@ describe Shutterbug::Rackapp do
|
|
68
68
|
last_response.headers['Content-Type'].should match 'image/png'
|
69
69
|
end
|
70
70
|
end
|
71
|
-
|
72
|
-
describe "get shutterbug.js javascipt route" do
|
73
|
-
it "should return js file" do
|
74
|
-
get "/shutterbug/shutterbug.js"
|
75
|
-
last_response.should be_ok
|
76
|
-
last_response.headers['Content-Type'].should match 'application/javascript'
|
77
|
-
end
|
78
|
-
end
|
79
71
|
end
|
80
72
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shutterbug
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Paessel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -156,24 +156,7 @@ files:
|
|
156
156
|
- LICENSE.md
|
157
157
|
- README.md
|
158
158
|
- Rakefile
|
159
|
-
- bower.json
|
160
159
|
- config.ru
|
161
|
-
- demo/The_Scream.jpg
|
162
|
-
- demo/canvas_example.html
|
163
|
-
- demo/iframe.html
|
164
|
-
- demo/iframe2.html
|
165
|
-
- demo/iframe3.html
|
166
|
-
- demo/iframe4.html
|
167
|
-
- demo/iframe_example.html
|
168
|
-
- demo/iframe_no_shutterbug.html
|
169
|
-
- demo/index.html
|
170
|
-
- demo/main.css
|
171
|
-
- demo/nested_iframe_example.html
|
172
|
-
- demo/oil-and-water/heatbath.svg
|
173
|
-
- demo/oil-and-water/ke-gradient.svg
|
174
|
-
- demo/oil-and-water/oil-and-water.svg
|
175
|
-
- demo/simple_example.html
|
176
|
-
- demo/svg_example.html
|
177
160
|
- images/shutterbug.jpg
|
178
161
|
- lib/shutterbug.rb
|
179
162
|
- lib/shutterbug/cache_manager.rb
|
@@ -184,8 +167,6 @@ files:
|
|
184
167
|
- lib/shutterbug/handlers/convert_handler.rb
|
185
168
|
- lib/shutterbug/handlers/direct_upload_handler.rb
|
186
169
|
- lib/shutterbug/handlers/file_handler.rb
|
187
|
-
- lib/shutterbug/handlers/js_file_handler.rb
|
188
|
-
- lib/shutterbug/handlers/shutterbug.js
|
189
170
|
- lib/shutterbug/phantom_job.rb
|
190
171
|
- lib/shutterbug/rackapp.rb
|
191
172
|
- lib/shutterbug/rasterize.js
|
@@ -200,7 +181,6 @@ files:
|
|
200
181
|
- spec/shutterbug/direct_upload_handler_spec.rb
|
201
182
|
- spec/shutterbug/file_handler_spec.rb
|
202
183
|
- spec/shutterbug/file_storage_spec.rb
|
203
|
-
- spec/shutterbug/js_file_handler_spec.rb
|
204
184
|
- spec/shutterbug/rackapp_spec.rb
|
205
185
|
- spec/shutterbug/s3_storage_spec.rb
|
206
186
|
- spec/spec_helper.rb
|
@@ -236,7 +216,6 @@ test_files:
|
|
236
216
|
- spec/shutterbug/direct_upload_handler_spec.rb
|
237
217
|
- spec/shutterbug/file_handler_spec.rb
|
238
218
|
- spec/shutterbug/file_storage_spec.rb
|
239
|
-
- spec/shutterbug/js_file_handler_spec.rb
|
240
219
|
- spec/shutterbug/rackapp_spec.rb
|
241
220
|
- spec/shutterbug/s3_storage_spec.rb
|
242
221
|
- spec/spec_helper.rb
|
data/bower.json
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"name": "shutterbug",
|
3
|
-
"version": "0.4.3",
|
4
|
-
"homepage": "https://github.com/concord-consortium/shutterbug",
|
5
|
-
"authors": [
|
6
|
-
"Noah Paessel <npaessel@concord.org>"
|
7
|
-
],
|
8
|
-
"description": "Javascript library for facilitating rendering DOM components in rasterized form.",
|
9
|
-
"main": "./lib/shutterbug/handlers/shutterbug.js",
|
10
|
-
"dependencies": {
|
11
|
-
"jquery": "1.11.0"
|
12
|
-
},
|
13
|
-
"keywords": [
|
14
|
-
"shutterbug"
|
15
|
-
],
|
16
|
-
"license": "MIT",
|
17
|
-
"private": true,
|
18
|
-
"ignore": [
|
19
|
-
"**/.*",
|
20
|
-
"node_modules",
|
21
|
-
"bower_components",
|
22
|
-
"spec",
|
23
|
-
"demo",
|
24
|
-
"images"
|
25
|
-
]
|
26
|
-
}
|
data/demo/The_Scream.jpg
DELETED
Binary file
|
data/demo/canvas_example.html
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
<!doctype html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>demo</title>
|
5
|
-
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
|
6
|
-
<script type="text/javascript" src="/shutterbug/shutterbug.js"></script>
|
7
|
-
<link rel="stylesheet" type="text/css" href="main.css">
|
8
|
-
</head>
|
9
|
-
|
10
|
-
<body>
|
11
|
-
<div>
|
12
|
-
<canvas id="src" width="350" height="350"></canvas>
|
13
|
-
</div>
|
14
|
-
<button class="shutterbug" data-dst="#dst">Snapshot</button>
|
15
|
-
<div id="dst"></div>
|
16
|
-
</body>
|
17
|
-
<script type="text/javascript">
|
18
|
-
$(document).ready(function(e) {
|
19
|
-
var img = new Image();
|
20
|
-
img.onload = function () {
|
21
|
-
var ctx = $("canvas")[0].getContext("2d");
|
22
|
-
ctx.fillStyle = "green";
|
23
|
-
ctx.fillRect(0, 0, 350, 350);
|
24
|
-
ctx.fillStyle = "orange";
|
25
|
-
ctx.fillRect(10, 10, 330, 330);
|
26
|
-
ctx.drawImage(img, 20, 20, 310, 310);
|
27
|
-
};
|
28
|
-
img.src = "The_Scream.jpg";
|
29
|
-
|
30
|
-
var bug = new Shutterbug("#src", "#dst", null, null, null, {format: "jpeg", quality: 0.75});
|
31
|
-
$("button.shutterbug").click(function(e) {
|
32
|
-
bug.getDomSnapshot();
|
33
|
-
});
|
34
|
-
});
|
35
|
-
</script>
|
36
|
-
</html>
|
data/demo/iframe.html
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
<!doctype html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>demo</title>
|
5
|
-
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
|
6
|
-
<script type="text/javascript" src="/shutterbug/shutterbug.js"></script>
|
7
|
-
<link rel="stylesheet" type="text/css" href="main.css"></link>
|
8
|
-
<style type="text/css">
|
9
|
-
#src {
|
10
|
-
color: blue;
|
11
|
-
width: 100px;
|
12
|
-
height: 100px;
|
13
|
-
}
|
14
|
-
</style>
|
15
|
-
</head>
|
16
|
-
|
17
|
-
<body>
|
18
|
-
<div id="src">
|
19
|
-
(iframe)
|
20
|
-
</div>
|
21
|
-
</div>
|
22
|
-
|
23
|
-
</body>
|
24
|
-
<script type="text/javascript">
|
25
|
-
var dd = null;
|
26
|
-
$(document).ready(function(e) {
|
27
|
-
dd = new Shutterbug('#src');
|
28
|
-
});
|
29
|
-
</script>
|
30
|
-
</html>
|
data/demo/iframe2.html
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
<!doctype html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>demo</title>
|
5
|
-
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
|
6
|
-
<script type="text/javascript" src="/shutterbug/shutterbug.js"></script>
|
7
|
-
<link rel="stylesheet" type="text/css" href="main.css"></link>
|
8
|
-
<style type="text/css">
|
9
|
-
#src {
|
10
|
-
color: green;
|
11
|
-
width: 100px;
|
12
|
-
height: 100px;
|
13
|
-
}
|
14
|
-
</style>
|
15
|
-
</head>
|
16
|
-
|
17
|
-
<body>
|
18
|
-
<div id="src">
|
19
|
-
(iframe)
|
20
|
-
</div>
|
21
|
-
</div>
|
22
|
-
|
23
|
-
</body>
|
24
|
-
<script type="text/javascript">
|
25
|
-
var dd = null;
|
26
|
-
$(document).ready(function(e) {
|
27
|
-
dd = new Shutterbug('#src');
|
28
|
-
});
|
29
|
-
</script>
|
30
|
-
</html>
|