ballonizer 0.2.4 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/ballonizer_app/config.ru +4 -2
- data/examples/ballonizer_app/index.html +105 -157
- data/examples/ballonizer_app/test.db +0 -0
- data/examples/ballonizer_js_module/index.html +4 -4
- data/lib/assets/javascripts/ballonizer.js +119 -17
- data/lib/assets/stylesheets/ballonizer.css +17 -12
- data/lib/ballonizer.rb +81 -25
- data/spec/ballonizer_spec.rb +108 -45
- data/spec/javascripts/ballonizer_spec.js +186 -129
- data/spec/javascripts/fixtures/ballonized-xkcd-with-anchor-in-image.html +2 -2
- data/spec/javascripts/fixtures/ballonized-xkcd-with-ballons.html +2 -2
- data/spec/javascripts/fixtures/ballonized-xkcd-without-ballons.html +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bf4f7c8da8c6850ded2132c67beebc4bb5306ff
|
4
|
+
data.tar.gz: 8238aea52c3812bdb5ef6113744d2c2f01d0e488
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7b614154da4bf1e78483c9266e067d33a425f57dd4d10f662732163316a5852b76aac86e59aba5e591ac9531d45d1829b1990b9e3b6d349d2f6ee2693b8d527
|
7
|
+
data.tar.gz: 4ebfcf50deafb861e2cce5f5e20120399e133748ece9865dec01c1def8cf936ff81b926d6e4f1fbca8aca39c8ff6754507a9743c2d1074813a7ef5e1150d31b8
|
@@ -13,6 +13,7 @@ html_name = 'index.html'
|
|
13
13
|
html = File.read("#{path_rake_to_app}#{html_name}")
|
14
14
|
|
15
15
|
ballonizer = Ballonizer.new(db_uri, {
|
16
|
+
img_to_ballonize_css_selector: '#comic img',
|
16
17
|
create_tables_if_none: true,
|
17
18
|
form_handler_url: '/request_handler',
|
18
19
|
add_required_css: true,
|
@@ -26,9 +27,10 @@ app = Rack::Builder.new do
|
|
26
27
|
run(lambda do | env |
|
27
28
|
# the url is needed to make relative paths to images absolute
|
28
29
|
request = Rack::Request.new(env)
|
29
|
-
|
30
|
+
mime_type = 'application/xhtml+xml'
|
31
|
+
ballonized_page = ballonizer.ballonize_page(html, request.url, mime_type)
|
30
32
|
|
31
|
-
[200, {}, [ballonized_page]]
|
33
|
+
[200, { 'content-type' => mime_type }, [ballonized_page]]
|
32
34
|
end)
|
33
35
|
end
|
34
36
|
|
@@ -1,159 +1,107 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
<a href="http://
|
86
|
-
|
87
|
-
|
88
|
-
<a
|
89
|
-
|
90
|
-
|
91
|
-
<a href="http://
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
<img src="http://imgs.xkcd.com/s/a899e84.jpg" width="520"
|
107
|
-
height="100" alt="Selected Comics" usemap="#comicmap" />
|
108
|
-
<map id="comicmap">
|
109
|
-
<!-- http://code.google.com/p/chromium/issues/detail?id=108489 Might be MIME dependant. -->
|
110
|
-
<area shape="rect" coords="0,0,100,100" href="http://xkcd.com/150/"
|
111
|
-
alt="Grownups" />
|
112
|
-
<area shape="rect" coords="104,0,204,100" href="http://xkcd.com/730/"
|
113
|
-
alt="Circuit Diagram" />
|
114
|
-
<area shape="rect" coords="208,0,308,100" href="http://xkcd.com/162/"
|
115
|
-
alt="Angular Momentum" />
|
116
|
-
<area shape="rect" coords="312,0,412,100" href="http://xkcd.com/688/"
|
117
|
-
alt="Self-Description" />
|
118
|
-
<area shape="rect" coords="416,0,520,100" href="http://xkcd.com/556/"
|
119
|
-
alt="Alternative Energy Revolution" />
|
120
|
-
</map>
|
121
|
-
<a href="http://xkcd.com/rss.xml">RSS Feed</a>-
|
122
|
-
<a href="http://xkcd.com/atom.xml">Atom Feed</a></div>
|
123
|
-
<br />
|
124
|
-
<div id="comicLinks">Comics I enjoy:
|
125
|
-
<br />
|
126
|
-
<a href="http://threewordphrase.com/">Three Word Phrase</a>,
|
127
|
-
<a href="http://oglaf.com/">Oglaf</a>(nsfw),
|
128
|
-
<a href="http://www.smbc-comics.com/">SMBC</a>,
|
129
|
-
<a href="http://www.qwantz.com">Dinosaur Comics</a>,
|
130
|
-
<a href="http://www.asofterworld.com">A Softer World</a>,
|
131
|
-
<a href="http://buttersafe.com/">Buttersafe</a>,
|
132
|
-
<a href="http://pbfcomics.com/">Perry Bible Fellowship</a>,
|
133
|
-
<a href="http://questionablecontent.net/">Questionable
|
134
|
-
Content</a>,
|
135
|
-
<a href="http://www.buttercupfestival.com/">Buttercup
|
136
|
-
Festival</a></div>
|
137
|
-
<p>Warning: this comic occasionally contains strong language
|
138
|
-
(which may be unsuitable for children), unusual humor (which
|
139
|
-
may be unsuitable for adults), and advanced mathematics
|
140
|
-
(which may be unsuitable for liberal-arts majors).</p>
|
141
|
-
<div id="footnote">BTC 1NEPgrUmed3VyXpqbYZom7YVJ8MozYrNWx
|
142
|
-
<br />We did not invent the algorithm. The algorithm
|
143
|
-
consistently finds Jesus. The algorithm killed Jeeves.
|
144
|
-
<br />The algorithm is banned in China. The algorithm is from
|
145
|
-
Jersey. The algorithm constantly finds Jesus.
|
146
|
-
<br />This is not the algorithm. This is close.</div>
|
147
|
-
<div id="licenseText">
|
148
|
-
<p>This work is licensed under a
|
149
|
-
<a href="http://creativecommons.org/licenses/by-nc/2.5/">
|
150
|
-
Creative Commons Attribution-NonCommercial 2.5
|
151
|
-
License</a>.</p>
|
152
|
-
<p>This means you're free to copy and share these comics
|
153
|
-
(but not to sell them).
|
154
|
-
<a rel="license" href="http://xkcd.com/license.html">More details</a>.</p>
|
155
|
-
</div>
|
156
|
-
</div>
|
157
|
-
</body>
|
1
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
3
|
+
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
4
|
+
<html version="-//W3C//DTD XHTML 1.1//EN" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
5
|
+
<head>
|
6
|
+
<link rel="stylesheet" type="text/css" href="http://xkcd.com/s/d16ebb.css" title="Default"/>
|
7
|
+
<title>xkcd: Cells</title>
|
8
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
9
|
+
<link rel="shortcut icon" href="http://xkcd.com/s/919f27.ico" type="image/x-icon"/>
|
10
|
+
<link rel="icon" href="http://xkcd.com/s/919f27.ico" type="image/x-icon"/>
|
11
|
+
<link rel="alternate" type="application/atom+xml" title="Atom 1.0" href="http://xkcd.com/atom.xml"/>
|
12
|
+
<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://xkcd.com/rss.xml"/>
|
13
|
+
<link rel="apple-touch-icon-precomposed" href="http://xkcd.com/s/d9522a.png" />
|
14
|
+
</head>
|
15
|
+
<body>
|
16
|
+
<div id="topContainer">
|
17
|
+
<div id="topLeft">
|
18
|
+
<ul>
|
19
|
+
<li><a href="http://xkcd.com/archive">Archive</a></li>
|
20
|
+
<li><a href="http://what-if.xkcd.com">What If?</a></li>
|
21
|
+
<li><a href="http://blag.xkcd.com">Blag</a></li>
|
22
|
+
<li><a href="http://store.xkcd.com/">Store</a></li>
|
23
|
+
<li><a rel="author" href="http://xkcd.com/about">About</a></li>
|
24
|
+
</ul>
|
25
|
+
</div>
|
26
|
+
<div id="topRight">
|
27
|
+
<div id="masthead">
|
28
|
+
<span><a href="/"><img src="http://imgs.xkcd.com/static/terrible_small_logo.png" alt="xkcd.com logo" height="83" width="185"/></a></span>
|
29
|
+
<span id="slogan">A webcomic of romance,<br/> sarcasm, math, and language.</span>
|
30
|
+
</div>
|
31
|
+
<div id="news">
|
32
|
+
You can get the Subways comic as a <a href="http://store-xkcd-com.myshopify.com/products/subways">poster</a>!
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
<div id="bgLeft" class="bg box"></div>
|
36
|
+
<div id="bgRight" class="bg box"></div>
|
37
|
+
</div>
|
38
|
+
<div id="middleContainer" class="box">
|
39
|
+
|
40
|
+
<div id="ctitle">Cells</div>
|
41
|
+
<ul class="comicNav">
|
42
|
+
<li><a href="http://xkcd.com/1/">|<</a></li>
|
43
|
+
<li><a rel="prev" href="http://xkcd.com/1216/" accesskey="p">< Prev</a></li>
|
44
|
+
<li><a href="http://dynamic.xkcd.com/random/comic/">Random</a></li>
|
45
|
+
<li><a rel="next" href="http://xkcd.com/1218/" accesskey="n">Next ></a></li>
|
46
|
+
<li><a href="/">>|</a></li>
|
47
|
+
</ul>
|
48
|
+
<div id="comic">
|
49
|
+
<img src="http://imgs.xkcd.com/comics/cells.png" title="Now, if it selectively kills cancer cells in a petri dish, you can be sure it's at least a great breakthrough for everyone suffering from petri dish cancer." alt="Cells" />
|
50
|
+
</div>
|
51
|
+
<ul class="comicNav">
|
52
|
+
<li><a href="http://xkcd.com/1/">|<</a></li>
|
53
|
+
<li><a rel="prev" href="http://xkcd.com/1216/" accesskey="p">< Prev</a></li>
|
54
|
+
<li><a href="http://dynamic.xkcd.com/random/comic/">Random</a></li>
|
55
|
+
<li><a rel="next" href="http://xkcd.com/1218/" accesskey="n">Next ></a></li>
|
56
|
+
<li><a href="http://xkcd.com/">>|</a></li>
|
57
|
+
</ul>
|
58
|
+
<br />
|
59
|
+
Permanent link to this comic: http://xkcd.com/1217/<br />
|
60
|
+
Image URL (for hotlinking/embedding): http://imgs.xkcd.com/comics/cells.png
|
61
|
+
<div id="transcript" style="display: none">When you see a claim that a common drug or vitamin "kills cancer cells in a petri dish," keep in mind:
|
62
|
+
[[A scientist stands on a chair next to a desk, pointing a gun at a petri dish. There is a microscope on the desk.]]
|
63
|
+
So does a handgun.
|
64
|
+
|
65
|
+
{{Title text: Now, if it selectively kills cancer cells in a petri dish, you can be sure it's at least a great breakthrough for everyone suffering from petri dish cancer.}}</div>
|
66
|
+
</div>
|
67
|
+
<div id="bottom" class="box">
|
68
|
+
<img src="http://imgs.xkcd.com/s/a899e84.jpg" width="520" height="100" alt="Selected Comics" usemap="#comicmap"/>
|
69
|
+
<map id="comicmap">
|
70
|
+
<!-- http://code.google.com/p/chromium/issues/detail?id=108489 Might be MIME dependent. -->
|
71
|
+
<area shape="rect" coords="0,0,100,100" href="http://xkcd.com/150/" alt="Grownups"/>
|
72
|
+
<area shape="rect" coords="104,0,204,100" href="http://xkcd.com/730/" alt="Circuit Diagram"/>
|
73
|
+
<area shape="rect" coords="208,0,308,100" href="http://xkcd.com/162/" alt="Angular Momentum"/>
|
74
|
+
<area shape="rect" coords="312,0,412,100" href="http://xkcd.com/688/" alt="Self-Description"/>
|
75
|
+
<area shape="rect" coords="416,0,520,100" href="http://xkcd.com/556/" alt="Alternative Energy Revolution"/>
|
76
|
+
</map>
|
77
|
+
<div>
|
78
|
+
Search comic titles and transcripts:
|
79
|
+
<a href="http://xkcd.com/rss.xml">RSS Feed</a> - <a href="/atom.xml">Atom Feed</a>
|
80
|
+
</div>
|
81
|
+
<br />
|
82
|
+
<div id="comicLinks">
|
83
|
+
Comics I enjoy:<br/>
|
84
|
+
<a href="http://threewordphrase.com/">Three Word Phrase</a>,
|
85
|
+
<a href="http://oglaf.com/">Oglaf</a> (nsfw),
|
86
|
+
<a href="http://www.smbc-comics.com/">SMBC</a>,
|
87
|
+
<a href="http://www.qwantz.com">Dinosaur Comics</a>,
|
88
|
+
<a href="http://www.asofterworld.com">A Softer World</a>,
|
89
|
+
<a href="http://buttersafe.com/">Buttersafe</a>,
|
90
|
+
<a href="http://pbfcomics.com/">Perry Bible Fellowship</a>,
|
91
|
+
<a href="http://questionablecontent.net/">Questionable Content</a>,
|
92
|
+
<a href="http://www.buttercupfestival.com/">Buttercup Festival</a>
|
93
|
+
</div>
|
94
|
+
<p>Warning: this comic occasionally contains strong language (which may be unsuitable for children), unusual humor (which may be unsuitable for adults), and advanced mathematics (which may be unsuitable for liberal-arts majors).</p>
|
95
|
+
<div id="footnote">BTC 1NfBXWqseXc9rCBc3Cbbu6HjxYssFUgkH6<br />We did not invent the algorithm. The algorithm consistently finds Jesus. The algorithm killed Jeeves. <br/>The algorithm is banned in China. The algorithm is from Jersey. The algorithm constantly finds Jesus.<br/>This is not the algorithm. This is close.</div>
|
96
|
+
<div id="licenseText">
|
97
|
+
<p>
|
98
|
+
This work is licensed under a
|
99
|
+
<a href="http://creativecommons.org/licenses/by-nc/2.5/">Creative Commons Attribution-NonCommercial 2.5 License</a>.
|
100
|
+
</p><p>
|
101
|
+
This means you're free to copy and share these comics (but not to sell them). <a rel="license" href="http://xkcd.com/license.html">More details</a>.</p>
|
102
|
+
</div>
|
103
|
+
</div>
|
104
|
+
</body>
|
105
|
+
<!-- Layout by Ian Clasbey, davean, and chromakode -->
|
158
106
|
</html>
|
159
107
|
|
Binary file
|
@@ -9,9 +9,9 @@
|
|
9
9
|
href="http://imgs.xkcd.com/static/styles_short_beta.css"
|
10
10
|
title="Default" />
|
11
11
|
<link rel="stylesheet" type="text/css"
|
12
|
-
href="../../
|
12
|
+
href="../../vendor/assets/stylesheets/ui-lightness/jquery-ui-1.10.3.custom.min.css" />
|
13
13
|
<link rel="stylesheet" type="text/css"
|
14
|
-
href="../../lib/
|
14
|
+
href="../../lib/assets/stylesheets/ballonizer.css" />
|
15
15
|
<script type="text/javascript"
|
16
16
|
src="../../vendor/assets/javascripts/jquery-2.0.1.js"></script>
|
17
17
|
<script type="text/javascript"
|
@@ -19,7 +19,7 @@
|
|
19
19
|
<script type="text/javascript"
|
20
20
|
src="../../vendor/assets/javascripts/jquery-ui-1.10.3.custom.min.js"></script>
|
21
21
|
<script type="text/javascript"
|
22
|
-
src="../../lib/
|
22
|
+
src="../../lib/assets/javascripts/ballonizer.js"></script>
|
23
23
|
<script type="text/javascript">
|
24
24
|
$(document).ready(function() {
|
25
25
|
Ballonizer('/path/to/form/submit',
|
@@ -87,7 +87,7 @@
|
|
87
87
|
</li>
|
88
88
|
</ul>
|
89
89
|
<div id="comic">
|
90
|
-
<div class="ballonizer_image_container"><p style="left: 0px; top: 0px; width: 218px; height: 82px;" class="ballonizer_ballon" >When you see a claim that a common drug or vitamin "kills cancer cells in a petri dish", keep in mind:</p><p style="top: 319px; left: 21px; width: 170px; height: 19px;" class="ballonizer_ballon">So does a handgun.</p><img src="http://imgs.xkcd.com/comics/cells.png"
|
90
|
+
<div class="ballonizer_image_container"><p style="left: 0px; top: 0px; width: 218px; height: 82px; font-size: 15px;" class="ballonizer_ballon" >When you see a claim that a common drug or vitamin "kills cancer cells in a petri dish", keep in mind:</p><p style="top: 319px; left: 21px; width: 170px; height: 19px; font-size: 14px;" class="ballonizer_ballon">So does a handgun.</p><img src="http://imgs.xkcd.com/comics/cells.png"
|
91
91
|
title="Now, if it selectively kills cancer cells in a petri dish, you can be sure it's at least a great breakthrough for everyone suffering from petri dish cancer."
|
92
92
|
width="218px"
|
93
93
|
height="339px"
|
@@ -117,10 +117,11 @@
|
|
117
117
|
|
118
118
|
Ballonizer.prototype.generateBallonizerFormNode = function () {
|
119
119
|
var form = $("<form class='ballonizer_page_form' method='post' >" +
|
120
|
-
"<input name='ballonizer_data' type='hidden'
|
121
|
-
"
|
122
|
-
"value='" +
|
123
|
-
|
120
|
+
"<div><input name='ballonizer_data' type='hidden'>" +
|
121
|
+
"</input><input name='ballonizer_submit'" +
|
122
|
+
" type='submit' value='" +
|
123
|
+
this.config.submitButtonValue +
|
124
|
+
"'></input></div></form>");
|
124
125
|
|
125
126
|
form.attr("action", this.actionFormURL);
|
126
127
|
|
@@ -161,17 +162,29 @@
|
|
161
162
|
containerNode);
|
162
163
|
}
|
163
164
|
|
165
|
+
// See notifyBallonChange for this flag explanation
|
166
|
+
this.userAlreadyInteracted = false;
|
167
|
+
|
164
168
|
this.ballonizerInstance = ballonizerInstance;
|
165
169
|
this.containerNode = containerNode;
|
166
170
|
this.ballons = [];
|
167
171
|
|
168
172
|
// Insert the form for the ballons in edit mode
|
169
|
-
|
170
|
-
|
173
|
+
this.form = $(
|
174
|
+
"<form class='ballonizer_image_form' action='#'></form>"
|
175
|
+
);
|
176
|
+
this.formInnerContainer = $(
|
177
|
+
"<div></div>"
|
171
178
|
);
|
179
|
+
this.form.prepend(this.formInnerContainer);
|
180
|
+
// The form is prepended in the beggining of the ballonizer
|
181
|
+
// context and not inside the ballonizer_image_container
|
182
|
+
// because not every element that can wrap a image (as an
|
183
|
+
// anchor for example) can wrap a form (or a block element).
|
184
|
+
// See more in: http://www.w3.org/TR/REC-html40/struct/global.html#block-inline, http://skypoetsworld.blogspot.com.br/2008/10/dont-ever-put-block-inside-inline.html, http://stackoverflow.com/questions/1091739/html-div-in-link-problem, stackoverflow.com/questions/1827965/is-putting-a-div-inside-an-anchor-ever-correcta
|
185
|
+
this.ballonizerInstance.getContext().prepend(this.form);
|
172
186
|
|
173
|
-
var ballons = $(".ballonizer_ballon",
|
174
|
-
this.ballonizerInstance.getContext());
|
187
|
+
var ballons = $(".ballonizer_ballon", this.containerNode);
|
175
188
|
|
176
189
|
ballons.each($.proxy(function (ix, element) {
|
177
190
|
this.ballons.push(new InterfaceBallon(this, $(element)));
|
@@ -186,6 +199,10 @@
|
|
186
199
|
}, this));
|
187
200
|
};
|
188
201
|
|
202
|
+
BallonizedImageContainer.prototype.getFormInnerContainer = function () {
|
203
|
+
return this.formInnerContainer;
|
204
|
+
};
|
205
|
+
|
189
206
|
BallonizedImageContainer.prototype.getContainerNode = function () {
|
190
207
|
return this.containerNode;
|
191
208
|
};
|
@@ -194,7 +211,33 @@
|
|
194
211
|
return this.ballonizerInstance;
|
195
212
|
};
|
196
213
|
|
214
|
+
// Avoid to call this method in methods that update the ballons
|
215
|
+
// data, call this method only in callbacks of events, after calling
|
216
|
+
// the methods that update the ballons data. This is intended to
|
217
|
+
// preserve the semantics of the ballon change be always from a user
|
218
|
+
// interaction.
|
197
219
|
BallonizedImageContainer.prototype.notifyBallonChange = function () {
|
220
|
+
// This flag is necessary to work around the load of the image.
|
221
|
+
// The ready callback don't wait for images to load and the
|
222
|
+
// load callback has several caveats with using images (see
|
223
|
+
// http://api.jquery.com/ready/ and http://api.jquery.com/load-event/).
|
224
|
+
// All the ballons are defined in percentages and probably won't
|
225
|
+
// be visible until the image is loaded (or will be over the alt
|
226
|
+
// text but is hard to think of an user edit a ballon in this
|
227
|
+
// case). So when the user interact with a ballon it will
|
228
|
+
// calculate and update the sizes in pixels of all ballons
|
229
|
+
// (the attributes used for the serialize), assuming that the
|
230
|
+
// user is already editing because the image is loaded.
|
231
|
+
// This fix a bug where all the ballons except the modified
|
232
|
+
// (who the bounds are recalculated) are serialized and
|
233
|
+
// submitted with the incorrect values (but are displayed
|
234
|
+
// corretly to the user before the submission).
|
235
|
+
if (!this.userAlreadyInteracted) {
|
236
|
+
jQuery.each(this.ballons, function (ix, ballon) {
|
237
|
+
ballon.updatePositionAndSize();
|
238
|
+
});
|
239
|
+
this.userAlreadyInteracted = true;
|
240
|
+
}
|
198
241
|
return this.ballonizerInstance.notifyBallonChange();
|
199
242
|
};
|
200
243
|
|
@@ -274,6 +317,7 @@
|
|
274
317
|
if (2 === arguments.length) {
|
275
318
|
this.node = xOrNode;
|
276
319
|
this.updatePositionAndSize();
|
320
|
+
this.fontSize = parseInt(this.node.css('font-size'), 10);
|
277
321
|
this.text = this.node.text();
|
278
322
|
} else {
|
279
323
|
this.left = xOrNode;
|
@@ -304,9 +348,8 @@
|
|
304
348
|
|
305
349
|
this.text = initialText;
|
306
350
|
this.node = this.generateBallonNode();
|
307
|
-
this.
|
308
|
-
|
309
|
-
);
|
351
|
+
this.imgContainer.getContainerNode().prepend(this.node);
|
352
|
+
this.changeFontSizeToBestFitBallon();
|
310
353
|
}
|
311
354
|
|
312
355
|
this.node.draggable({
|
@@ -316,6 +359,7 @@
|
|
316
359
|
stop: $.proxy(function (event, ui) {
|
317
360
|
/* jshint unused: false */
|
318
361
|
this.updatePositionAndSize();
|
362
|
+
this.imgContainer.notifyBallonChange();
|
319
363
|
}, this)
|
320
364
|
});
|
321
365
|
this.node.resizable({
|
@@ -327,13 +371,17 @@
|
|
327
371
|
stop: $.proxy(function (event, ui) {
|
328
372
|
/* jshint unused: false */
|
329
373
|
this.updatePositionAndSize();
|
374
|
+
this.changeFontSizeToBestFitBallon();
|
375
|
+
this.imgContainer.notifyBallonChange();
|
330
376
|
}, this)
|
331
377
|
});
|
332
378
|
|
333
|
-
var imageForm =
|
334
|
-
this.imgContainer.getContainerNode());
|
379
|
+
var imageForm = this.imgContainer.getFormInnerContainer();
|
335
380
|
var editionBallon = $(
|
336
|
-
|
381
|
+
// cols and rows are obrigatory attributes, the choosen
|
382
|
+
// values are magic numbers without a good reason
|
383
|
+
"<textarea cols='100' rows='40' " +
|
384
|
+
"class='ballonizer_edition_ballon'></textarea>"
|
337
385
|
).val(this.text);
|
338
386
|
|
339
387
|
this.editionNode = editionBallon;
|
@@ -358,7 +406,7 @@
|
|
358
406
|
var nodeStyle = ["left: ", this.left, "px; ", "top: ",
|
359
407
|
this.top, "px; ", "width: ", this.width, "px; ",
|
360
408
|
"height: ", this.height, "px;"].join("");
|
361
|
-
var node = $("<
|
409
|
+
var node = $("<span class='ballonizer_ballon' ></span>");
|
362
410
|
|
363
411
|
// The use of ".text" will escape '<', '>', and others
|
364
412
|
node.text(this.text).attr("style", nodeStyle);
|
@@ -377,6 +425,19 @@
|
|
377
425
|
height: this.height
|
378
426
|
};
|
379
427
|
};
|
428
|
+
InterfaceBallon.prototype.changeFontSizeToBestFitBallon = function () {
|
429
|
+
var old_height = this.node.css('height');
|
430
|
+
var desired_calc_height = this.node.height();
|
431
|
+
this.node.css('height', 'auto');
|
432
|
+
var actual_font_size = 1;
|
433
|
+
this.node.css('font-size', actual_font_size);
|
434
|
+
while (this.node.height() < desired_calc_height) {
|
435
|
+
this.node.css('font-size', ++actual_font_size + 'px');
|
436
|
+
}
|
437
|
+
this.node.css('font-size', --actual_font_size + 'px');
|
438
|
+
this.node.css('height', old_height);
|
439
|
+
this.fontSize = actual_font_size;
|
440
|
+
};
|
380
441
|
InterfaceBallon.prototype.updatePositionAndSize = function () {
|
381
442
|
var newX = this.node.position().left;
|
382
443
|
var newY = this.node.position().top;
|
@@ -390,7 +451,6 @@
|
|
390
451
|
this.top = newY;
|
391
452
|
this.width = newWidth;
|
392
453
|
this.height = newHeight;
|
393
|
-
this.imgContainer.notifyBallonChange();
|
394
454
|
}
|
395
455
|
};
|
396
456
|
InterfaceBallon.prototype.getState = function () {
|
@@ -445,6 +505,7 @@
|
|
445
505
|
this.node.removeClass("ballonizer_ballon_hidden_for_edition");
|
446
506
|
this.editionNode.removeClass("ballonizer_ballon_in_edition");
|
447
507
|
if (this.text !== oldText) {
|
508
|
+
this.changeFontSizeToBestFitBallon();
|
448
509
|
this.imgContainer.notifyBallonChange();
|
449
510
|
}
|
450
511
|
}
|
@@ -452,8 +513,48 @@
|
|
452
513
|
|
453
514
|
InterfaceBallon.prototype.dblclick = function () {
|
454
515
|
this.state = this.state.replace("initial", "edit");
|
516
|
+
|
517
|
+
var context = this.imgContainer.getBallonizerInstance().getContext();
|
518
|
+
|
519
|
+
// The add not only add this node to the set but sort the set
|
520
|
+
// (that is a array, not a set) in the order that the elements
|
521
|
+
// appears in the document. This way the most outer parent is
|
522
|
+
// the first element.
|
523
|
+
// This behaviour is documented in: http://api.jquery.com/add/
|
524
|
+
var els = this.node.parentsUntil(context).add(this.node);
|
525
|
+
var zIndexes = [];
|
526
|
+
els.each(function (ix, el) {
|
527
|
+
var zIndexCSS = $(el).css('z-index');
|
528
|
+
// the inherit is made numeric by the jQuery, we are
|
529
|
+
// filtering here only the "auto" string value
|
530
|
+
if (jQuery.isNumeric(zIndexCSS)) {
|
531
|
+
zIndexes.push(parseInt(zIndexCSS));
|
532
|
+
}
|
533
|
+
});
|
534
|
+
var zIndex = null;
|
535
|
+
if (zIndexes.length > 0) {
|
536
|
+
// The zIndex only need to be one greater than the
|
537
|
+
// zIndex of the most outer parent with a defined zIndex.
|
538
|
+
zIndex = zIndexes[0] + 1;
|
539
|
+
} else {
|
540
|
+
zIndex = 1;
|
541
|
+
}
|
542
|
+
|
543
|
+
// we subtract the offset of the imageform from the offset
|
544
|
+
// of the normal ballon because the left and top of the edition
|
545
|
+
// ballon is relative to this form (its the closest parent with
|
546
|
+
// position: relative defined)
|
547
|
+
var offset = this.node.offset();
|
548
|
+
var imageFormOffset = this.imgContainer.getFormInnerContainer().offset();
|
549
|
+
|
550
|
+
this.editionNode.css('top', offset.top - imageFormOffset.top);
|
551
|
+
this.editionNode.css('left', offset.left - imageFormOffset.left);
|
552
|
+
this.editionNode.css('width', this.node.css('width'));
|
553
|
+
this.editionNode.css('height', this.node.css('height'));
|
554
|
+
this.editionNode.css('z-index', zIndex);
|
555
|
+
|
556
|
+
// only make the ballon hidden after getting the offset
|
455
557
|
this.node.addClass("ballonizer_ballon_hidden_for_edition");
|
456
|
-
this.editionNode.attr("style", this.node.attr("style"));
|
457
558
|
this.editionNode.addClass("ballonizer_ballon_in_edition");
|
458
559
|
// focus after is visible, otherwise will crash in IE
|
459
560
|
// http://api.jquery.com/focus/#focus
|
@@ -474,6 +575,7 @@
|
|
474
575
|
top: this.top / containerHeight,
|
475
576
|
width: this.width / containerWidth,
|
476
577
|
height: this.height / containerHeight,
|
578
|
+
font_size: this.fontSize,
|
477
579
|
text: this.text
|
478
580
|
};
|
479
581
|
};
|