shutterbug 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +37 -1
- data/config.ru +18 -0
- data/demo/iframe.html +30 -0
- data/demo/index.html +35 -0
- data/demo/main.css +9 -0
- data/demo/withIframe.html +31 -0
- data/lib/shutterbug/shutterbug.js +91 -24
- data/lib/shutterbug.rb +1 -1
- data/shutterbug.gemspec +1 -0
- metadata +25 -4
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[![Build Status](https://travis-ci.org/concord-consortium/shutterbug.png?branch=master)](https://travis-ci.org/concord-consortium/shutterbug)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/concord-consortium/shutterbug.png)](https://codeclimate.com/github/concord-consortium/shutterbug)
|
5
5
|
|
6
|
-
A rack utility that will create and save images (pngs) from parts of your html's documents current dom. These images become available as public png resources in the rack application. Currently shutterbug supports HTML, SVG and Canvas elements.
|
6
|
+
A rack utility that will create and save images (pngs) from parts of your html's documents current dom. These images become available as public png resources in the rack application. Currently shutterbug supports HTML, SVG and Canvas elements. Here is a sampel config.ru file:
|
7
7
|
|
8
8
|
|
9
9
|
use Shutterbug::Rackapp do |config|
|
@@ -45,6 +45,42 @@ After adding `use Shutterbug::Rackapp` to your config.ru file, you can convert p
|
|
45
45
|
1. include the following javascript in your pages: `<script src='http://<yourhost:port>/shutterbug/shutterbug.js' type='text/javascript'></script>`
|
46
46
|
1. Elsewhere in your javascript call `getDomSnapshot($("#sourceDomID"),$("#imageOutputDomId"));` This will replace the contents of `$("#imageOutputDomId")` with an `<img src="http://<yourhost:port>/gete_png/sha1hash>` tag which will magically spring into existance.
|
47
47
|
|
48
|
+
|
49
|
+
## Deploying on Heroku ##
|
50
|
+
|
51
|
+
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).
|
52
|
+
|
53
|
+
Your app should have a config.ru that looks something like this:
|
54
|
+
|
55
|
+
|
56
|
+
require 'shutterbug'
|
57
|
+
require 'rack/cors'
|
58
|
+
|
59
|
+
use Rack::Cors do
|
60
|
+
allow do
|
61
|
+
origins '*'
|
62
|
+
resource '/shutterbug/*', :headers => :any, :methods => :any
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
use Shutterbug::Rackapp do |config|
|
67
|
+
config.uri_prefix = "http://<your app name>.herokuapp.com/"
|
68
|
+
config.path_prefix = "/shutterbug"
|
69
|
+
config.phantom_bin_path = "/app/vendor/phantomjs/bin/phantomjs"
|
70
|
+
end
|
71
|
+
|
72
|
+
app = proc do |env|
|
73
|
+
[200, { 'Content-Type' => 'text/html' }, ['move along']]
|
74
|
+
end
|
75
|
+
|
76
|
+
run app
|
77
|
+
|
78
|
+
And a Procfile which looks like this:
|
79
|
+
|
80
|
+
web: bundle exec rackup config.ru -p $PORT
|
81
|
+
|
82
|
+
|
83
|
+
|
48
84
|
## TODO: ##
|
49
85
|
|
50
86
|
* Configuration of the rack paths.
|
data/config.ru
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
require 'shutterbug'
|
3
|
+
require 'rack/cors'
|
4
|
+
use Rack::Cors do
|
5
|
+
allow do
|
6
|
+
origins '*'
|
7
|
+
resource '/shutterbug/*', :headers => :any, :methods => :any
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
use Shutterbug::Rackapp do |config|
|
12
|
+
config.uri_prefix = "http://localhost:9292"
|
13
|
+
config.path_prefix = "/shutterbug"
|
14
|
+
end
|
15
|
+
|
16
|
+
app = Rack::Directory.new "demo"
|
17
|
+
|
18
|
+
run app
|
data/demo/iframe.html
ADDED
@@ -0,0 +1,30 @@
|
|
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/index.html
ADDED
@@ -0,0 +1,35 @@
|
|
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: red;
|
11
|
+
}
|
12
|
+
</style>
|
13
|
+
</head>
|
14
|
+
|
15
|
+
<body>
|
16
|
+
<div id="src">
|
17
|
+
testing..
|
18
|
+
</div>
|
19
|
+
<button class="shutterbug" data-src="#src" data-dst="#dst">Snapshot</button>
|
20
|
+
<div id="dst">
|
21
|
+
</div>
|
22
|
+
|
23
|
+
</body>
|
24
|
+
<script type="text/javascript">
|
25
|
+
$(document).ready(function(e) {
|
26
|
+
$("button.shutterbug").click(function(e) {
|
27
|
+
var target = $(e.target);
|
28
|
+
var src = target.attr('data-src');
|
29
|
+
var dst = target.attr('data-dst');
|
30
|
+
var bug = new Shutterbug(src,dst);
|
31
|
+
bug.getDomSnapshot();
|
32
|
+
});
|
33
|
+
});
|
34
|
+
</script>
|
35
|
+
</html>
|
data/demo/main.css
ADDED
@@ -0,0 +1,31 @@
|
|
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
|
+
<style type="text/css">
|
9
|
+
#src {
|
10
|
+
color: red;
|
11
|
+
}
|
12
|
+
</style>
|
13
|
+
</head>
|
14
|
+
|
15
|
+
<body>
|
16
|
+
<iframe src="iframe.html" width="300" height="300"></iframe>
|
17
|
+
<button class="shutterbug" data-dst="#dst">Snapshot</button>
|
18
|
+
<div id="dst">
|
19
|
+
</div>
|
20
|
+
|
21
|
+
</body>
|
22
|
+
<script type="text/javascript">
|
23
|
+
var bug = null;
|
24
|
+
$(document).ready(function(e) {
|
25
|
+
bug = new Shutterbug("iframe","#dst");
|
26
|
+
$("button.shutterbug").click(function(e) {
|
27
|
+
bug.getDomSnapshot();
|
28
|
+
});
|
29
|
+
});
|
30
|
+
</script>
|
31
|
+
</html>
|
@@ -1,9 +1,12 @@
|
|
1
1
|
/*global $ */
|
2
2
|
(function(){
|
3
|
+
|
3
4
|
var getBaseUrl = function() {
|
4
|
-
var base = window.location.protocol + "//" + window.location.host + "/";
|
5
|
-
var root_path = window.location.pathname.split("/").slice(1,-1).join("/");
|
6
|
-
return base + root_path;
|
5
|
+
// var base = window.location.protocol + "//" + window.location.host + "/";
|
6
|
+
// var root_path = window.location.pathname.split("/").slice(1,-1).join("/");
|
7
|
+
// return base + root_path;
|
8
|
+
var base = window.location.href;
|
9
|
+
return base;
|
7
10
|
};
|
8
11
|
|
9
12
|
var cloneDomItem =function(elem, elemTag) {
|
@@ -19,24 +22,26 @@
|
|
19
22
|
return returnElm;
|
20
23
|
};
|
21
24
|
|
22
|
-
var
|
23
|
-
var
|
24
|
-
|
25
|
-
var
|
25
|
+
var getHtmlFragment = function() {
|
26
|
+
var $element = $(this.element);
|
27
|
+
|
28
|
+
var css = $('<div>').append($('link[rel="stylesheet"]').clone()).append($('style').clone()).html();
|
29
|
+
var width = $element.width();
|
30
|
+
var height = $element.height();
|
31
|
+
var element = null;
|
26
32
|
var html_content;
|
27
33
|
|
28
|
-
var replacementImgs = element.find('canvas').map( function(count,elem) {
|
34
|
+
var replacementImgs = $element.find('canvas').map( function(count,elem) {
|
29
35
|
var dataUrl = elem.toDataURL('image/png');
|
30
36
|
var img = cloneDomItem($(elem),"<img>");
|
31
37
|
img.attr('src', dataUrl);
|
32
38
|
return img;
|
33
39
|
});
|
34
40
|
|
35
|
-
element = element.clone();
|
41
|
+
element = $element.clone();
|
36
42
|
element.find('canvas').each(function(i,elm) {
|
37
43
|
var backgroundDiv = cloneDomItem($(elm),"<div>");
|
38
|
-
//
|
39
|
-
// $('canvas.overlay').css('background')
|
44
|
+
// Add a backing (background) dom element for BG canvas property
|
40
45
|
$(elm).replaceWith(replacementImgs[i]);
|
41
46
|
backgroundDiv.insertBefore($(elm));
|
42
47
|
});
|
@@ -49,26 +54,88 @@
|
|
49
54
|
'height':height
|
50
55
|
});
|
51
56
|
|
52
|
-
html_content =
|
57
|
+
html_content = {
|
58
|
+
content: $('<div>').append(element).html(),
|
59
|
+
css: css,
|
60
|
+
width: width,
|
61
|
+
height: height,
|
62
|
+
base_url: getBaseUrl()
|
63
|
+
};
|
64
|
+
return html_content;
|
65
|
+
};
|
53
66
|
|
67
|
+
var getPng = function(html) {
|
68
|
+
if(typeof html === 'undefined') {
|
69
|
+
if($(this.element)[0] && $(this.element)[0].contentWindow) {
|
70
|
+
this.requestHtmlFrag();
|
71
|
+
return;
|
72
|
+
}
|
73
|
+
else {
|
74
|
+
html = this.getHtmlFragment();
|
75
|
+
}
|
76
|
+
}
|
77
|
+
var self = this;
|
54
78
|
$.ajax({
|
55
79
|
url: "CONVERT_PATH",
|
56
80
|
type: "POST",
|
57
|
-
data:
|
58
|
-
'content': html_content,
|
59
|
-
'css': css,
|
60
|
-
'width': width,
|
61
|
-
'height': height,
|
62
|
-
'base_url': getBaseUrl()
|
63
|
-
}
|
81
|
+
data: html
|
64
82
|
}).done(function(msg) {
|
65
|
-
if(imgDst) {
|
66
|
-
imgDst.html(msg);
|
83
|
+
if(self.imgDst) {
|
84
|
+
$(self.imgDst).html(msg);
|
67
85
|
}
|
68
|
-
if (callback) {
|
69
|
-
callback(msg);
|
86
|
+
if (self.callback) {
|
87
|
+
self.callback(msg);
|
70
88
|
}
|
71
89
|
});
|
72
90
|
};
|
73
|
-
|
91
|
+
|
92
|
+
var requestHtmlFrag = function() {
|
93
|
+
var destination = $(this.element)[0].contentWindow;
|
94
|
+
var message = {
|
95
|
+
type: 'htmlFragRequest'
|
96
|
+
};
|
97
|
+
destination.postMessage(JSON.stringify(message),"*");
|
98
|
+
};
|
99
|
+
|
100
|
+
window.Shutterbug = function(selector,imgDst,callback) {
|
101
|
+
var shutterbugInstance = {
|
102
|
+
element: selector,
|
103
|
+
imgDst: imgDst,
|
104
|
+
callback: callback,
|
105
|
+
getDomSnapshot: getPng,
|
106
|
+
getPng: getPng,
|
107
|
+
getHtmlFragment: getHtmlFragment,
|
108
|
+
requestHtmlFrag: requestHtmlFrag
|
109
|
+
};
|
110
|
+
|
111
|
+
var htmlFragRequestListen = function(message) {
|
112
|
+
var data = message.data;
|
113
|
+
if (typeof data === 'string') {
|
114
|
+
data = JSON.parse(data);
|
115
|
+
}
|
116
|
+
if(data.type === 'htmlFragRequest') {
|
117
|
+
var response = {
|
118
|
+
type: 'htmlFragResponse',
|
119
|
+
value: shutterbugInstance.getHtmlFragment()
|
120
|
+
};
|
121
|
+
message.source.postMessage(JSON.stringify(response),"*");
|
122
|
+
}
|
123
|
+
};
|
124
|
+
|
125
|
+
var htmlFragResponseListen = function(message) {
|
126
|
+
var data = message.data;
|
127
|
+
if (typeof data === 'string') {
|
128
|
+
data = JSON.parse(data);
|
129
|
+
}
|
130
|
+
var html = null;
|
131
|
+
if(data.type === 'htmlFragResponse') {
|
132
|
+
html = data.value;
|
133
|
+
shutterbugInstance.getPng(html);
|
134
|
+
}
|
135
|
+
};
|
136
|
+
window.addEventListener('message', htmlFragRequestListen, false);
|
137
|
+
window.addEventListener('message', htmlFragResponseListen, false);
|
138
|
+
return shutterbugInstance;
|
139
|
+
};
|
140
|
+
|
74
141
|
})();
|
data/lib/shutterbug.rb
CHANGED
data/shutterbug.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shutterbug
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -75,6 +75,22 @@ dependencies:
|
|
75
75
|
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rack-cors
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
78
94
|
- !ruby/object:Gem::Dependency
|
79
95
|
name: rack
|
80
96
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,6 +127,11 @@ files:
|
|
111
127
|
- LICENSE.md
|
112
128
|
- README.md
|
113
129
|
- Rakefile
|
130
|
+
- config.ru
|
131
|
+
- demo/iframe.html
|
132
|
+
- demo/index.html
|
133
|
+
- demo/main.css
|
134
|
+
- demo/withIframe.html
|
114
135
|
- lib/shutterbug.rb
|
115
136
|
- lib/shutterbug/bug_file.rb
|
116
137
|
- lib/shutterbug/configuration.rb
|
@@ -140,7 +161,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
140
161
|
version: '0'
|
141
162
|
segments:
|
142
163
|
- 0
|
143
|
-
hash: -
|
164
|
+
hash: -375693095855382946
|
144
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
166
|
none: false
|
146
167
|
requirements:
|
@@ -149,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
170
|
version: '0'
|
150
171
|
segments:
|
151
172
|
- 0
|
152
|
-
hash: -
|
173
|
+
hash: -375693095855382946
|
153
174
|
requirements: []
|
154
175
|
rubyforge_project:
|
155
176
|
rubygems_version: 1.8.23
|