update graphs of a pc top page.
@@ -0,0 +1,66 @@ | ||
1 | +availableLanguages = | |
2 | + en: "English" | |
3 | + ja: "日本語" | |
4 | + | |
5 | + | |
6 | +main = -> | |
7 | + @menu = new LangMenu() | |
8 | + @currentLabel = new CurrentLangLabel(@menu) | |
9 | + @menu.buildItems @currentLabel.text() | |
10 | + @currentLabel.$el.attr "data-key": @menu.currentLangSymbol | |
11 | + | |
12 | +class CurrentLangLabel | |
13 | + constructor: (menu)-> | |
14 | + @el = "#current-lang" | |
15 | + @$el = $(@el) | |
16 | + @menu = menu | |
17 | + | |
18 | + @$el.click (event) => | |
19 | + event.stopPropagation() | |
20 | + $(@menu.$el).css( | |
21 | + "z-index": 99 | |
22 | + ).toggle() | |
23 | + | |
24 | + text: -> | |
25 | + @$el.text().replace /\s/g, '' | |
26 | + | |
27 | +class LangMenuItem | |
28 | + constructor: (langSymbol, langText)-> | |
29 | + @$el = $(document.createElement "div") | |
30 | + | |
31 | + @$el.attr( | |
32 | + "data-key": langSymbol | |
33 | + lang: langSymbol | |
34 | + ).addClass("item").css( | |
35 | + clear: "both" | |
36 | + ).text langText | |
37 | + | |
38 | +class LangMenu | |
39 | + constructor: -> | |
40 | + @el = "#lang-menu-container" | |
41 | + @$el = $(@el) | |
42 | + | |
43 | + buildItems: (currentLangText)-> | |
44 | + for k, v of availableLanguages | |
45 | + if v is currentLangText | |
46 | + @currentLangSymbol = k | |
47 | + else | |
48 | + @$el.append new LangMenuItem(k, v).$el | |
49 | + | |
50 | + $('.item', @$el).click @onclickItem | |
51 | + $('body').click => @$el.hide() | |
52 | + return | |
53 | + | |
54 | + onclickItem: (event)-> | |
55 | + console.log(@) | |
56 | + | |
57 | + return if $(@).attr("id") == "current-lang" | |
58 | + key = $(@).attr("data-key") + '/' | |
59 | + key = '' if key is 'ja/' | |
60 | + root = '../' | |
61 | + root = './' if $("div#current-lang").attr("data-key") is "ja" | |
62 | + window.location = root + key | |
63 | + return | |
64 | + | |
65 | +$ -> | |
66 | + main() |
@@ -0,0 +1,10 @@ | ||
1 | +@dictionary = | |
2 | + title: '漢字収録率' | |
3 | + fonts: | |
4 | + gothic: '(さわらびゴシック)' | |
5 | + mincho: '(さわらび明朝)' | |
6 | + kyoikuKanji: '教育漢字' | |
7 | + level1st: '第一水準漢字' | |
8 | + level2nd: '第二水準漢字' | |
9 | + level3rd: '第三水準漢字' | |
10 | + level4th: '第四水準漢字' |
@@ -0,0 +1,10 @@ | ||
1 | +@dictionary = | |
2 | + title: 'Kanji Coverage' | |
3 | + fonts: | |
4 | + gothic: ' (Sawarabi Gothic)' | |
5 | + mincho: ' (Sawarabi Mincho)' | |
6 | + kyoikuKanji: 'Kyoiku Kanji' | |
7 | + level1st: 'JIS 1st Level' | |
8 | + level2nd: 'JIS 2nd Level' | |
9 | + level3rd: 'JIS 3rd Level' | |
10 | + level4th: 'JIS 4th Level' |
@@ -0,0 +1,7 @@ | ||
1 | +browserNameIs = (deviceName...)-> | |
2 | + deviceName.map( (name) -> | |
3 | + if navigator.userAgent.indexOf(name) > 0 then 1 else 9 | |
4 | + ).sort()[0] is 1 | |
5 | + | |
6 | +if browserNameIs 'iPhone', 'iPod', 'Android' | |
7 | + location.href = "/mobile#{location.pathname}" |
@@ -0,0 +1,309 @@ | ||
1 | +Canvas = | |
2 | + el: "canvas#header-canvas" | |
3 | + generateContext: -> | |
4 | + @$el = $(@el) | |
5 | + cvs = @$el.get(0) | |
6 | + @context = if cvs and cvs.getContext then cvs.getContext('2d') else null | |
7 | + @ctx = @context | |
8 | + @ctx.save() if @ctx | |
9 | + | |
10 | +class Screen | |
11 | + constructor: (attr={}) -> | |
12 | + @width = attr.width | |
13 | + @height = attr.height | |
14 | + @objects = [] | |
15 | + @locking = false | |
16 | + | |
17 | + clear: -> | |
18 | + Canvas.ctx.clearRect(0, 0, @width, @height) | |
19 | + Canvas.ctx.restore() | |
20 | + Canvas.ctx.save() | |
21 | + @objects = [] | |
22 | + | |
23 | + add: (obj) -> | |
24 | + @objects.push(obj) | |
25 | + | |
26 | + draw: (obj) -> | |
27 | + if obj | |
28 | + obj.draw() | |
29 | + else | |
30 | + x.draw() for x in @objects | |
31 | + @ | |
32 | + | |
33 | + animate: -> | |
34 | + @locking = true | |
35 | + setTimeout => | |
36 | + animating = false | |
37 | + for x in @objects when x.isAnimating? and x.isAnimating() | |
38 | + x.draw() | |
39 | + animating = true | |
40 | + if animating then @animate() else @afterAnimation() | |
41 | + , 25 | |
42 | + afterAnimation: -> | |
43 | + @locking = false | |
44 | + x.afterAnimation(@) for x in @objects when x.afterAnimation? | |
45 | + | |
46 | +class Label | |
47 | + constructor: (text, attr={}) -> | |
48 | + @text = text | |
49 | + merge(@, attr) | |
50 | + @font ?= '10px sans' | |
51 | + @color ?= 'white' | |
52 | + @x ?= 0 | |
53 | + @y ?= 0 | |
54 | + | |
55 | + getWidth: -> | |
56 | + Canvas.ctx.font = @font | |
57 | + Canvas.ctx.measureText(@text).width | |
58 | + | |
59 | + draw: (offsetX=0, offsetY=0) -> | |
60 | + pos = screenPosition @, offsetX, offsetY | |
61 | + Canvas.ctx.font = @font | |
62 | + Canvas.ctx.fillStyle = @color | |
63 | + Canvas.ctx.fillText @text, pos.x, pos.y | |
64 | + | |
65 | +class Line | |
66 | + constructor: (attr={}) -> | |
67 | + @x0 = attr.x0 or attr.x or 0 | |
68 | + @y0 = attr.y0 or attr.y or 0 | |
69 | + @x1 = attr.x1 or attr.x or 0 | |
70 | + @y1 = attr.y1 or attr.y or 0 | |
71 | + @color = attr.color or '#fff' | |
72 | + | |
73 | + draw: (offsetX=0, offsetY=0) -> | |
74 | + pos = screenPosition @, offsetX, offsetY | |
75 | + c = Canvas.ctx | |
76 | + c.beginPath() | |
77 | + c.strokeStyle = @color | |
78 | + c.moveTo pos.x0, pos.y0 | |
79 | + c.lineTo pos.x1, pos.y1 | |
80 | + c.stroke() | |
81 | + c.closePath() | |
82 | + | |
83 | +class AbstractRectangle | |
84 | + constructor: (attr={}) -> | |
85 | + merge(@, attr) | |
86 | + @x0 ?= 0 | |
87 | + @y0 ?= 0 | |
88 | + @x1 ?= 0 | |
89 | + @y1 ?= 0 | |
90 | + | |
91 | + draw: (offsetX=0, offsetY=0) -> | |
92 | + pos = screenPosition @, offsetX, offsetY | |
93 | + Canvas.ctx.beginPath() | |
94 | + Canvas.ctx.rect(pos.x0, pos.y0, pos.x1 - pos.x0, pos.y1 - pos.y0) | |
95 | + | |
96 | +class GradientRectangle extends AbstractRectangle | |
97 | + constructor: (attr={}) -> | |
98 | + super(attr) | |
99 | + @colors ?= ['#fff', '#fff'] | |
100 | + @direction ?= 'horizontal' | |
101 | + | |
102 | + draw: (offsetX=0, offsetY=0) -> | |
103 | + c = Canvas.ctx | |
104 | + p = screenPosition(@, offsetX, offsetY) | |
105 | + g = null | |
106 | + if @direction is 'vertical' | |
107 | + g = c.createLinearGradient(p.x0, p.y0, p.x0, p.y1) | |
108 | + else if @direction is 'horizontal' | |
109 | + g = c.createLinearGradient(p.x0, p.y0, p.x1, p.y0) | |
110 | + d = 0.0 | |
111 | + for v in @colors | |
112 | + g.addColorStop(d, v) | |
113 | + d += 1 / (@colors.length - 1) | |
114 | + c.fillStyle = g | |
115 | + super(offsetX, offsetY) | |
116 | + c.fill() | |
117 | + | |
118 | +class GraphBar | |
119 | + constructor: (attr={}) -> | |
120 | + merge @, attr | |
121 | + @x ?= 0 | |
122 | + @y ?= 0 | |
123 | + @width ?= 1 | |
124 | + @height ?= 24 | |
125 | + @performance = attr.performance or 0 | |
126 | + @max = attr.max or 1 | |
127 | + @frame = 0.0 | |
128 | + @frames = 10.0 | |
129 | + | |
130 | + draw: (offsetX=0, offsetY=0) -> | |
131 | + width = (@width * 1.0) / @max * @performance * @frame / @frames | |
132 | + c = Canvas.ctx | |
133 | + c.beginPath() | |
134 | + if @frame is @frames | |
135 | + c.shadowBlur = 4 | |
136 | + c.shadowOffsetY = 2 | |
137 | + c.shadowColor = "rgba(0, 0, 0, 0.4)" | |
138 | + pos = screenPosition @, offsetX, offsetY | |
139 | + g = c.createLinearGradient(pos.x, pos.y, pos.x, pos.y + @height) | |
140 | + g.addColorStop 0.0, "#fc8a27" | |
141 | + g.addColorStop 0.1, "#fcb229" | |
142 | + g.addColorStop 0.4, "#fc8a29" | |
143 | + g.addColorStop 1.0, "#e97122" | |
144 | + c.fillStyle = g | |
145 | + c.rect(pos.x, pos.y, width, @height) | |
146 | + c.fill() | |
147 | + | |
148 | + isAnimating: -> | |
149 | + @frame += 1 | |
150 | + @frame <= @frames | |
151 | + | |
152 | + afterAnimation: (screen) -> | |
153 | + rate = 100.0 * @performance / @max | |
154 | + val = rate.toFixed(2) | |
155 | + val = parseInt(val) if parseInt(val) * 1.0 is Number(val) | |
156 | + label = new Label "#{val}%", | |
157 | + font: '12px sans' | |
158 | + width = 1.0 * @width / @max * @performance | |
159 | + x = (width - label.getWidth()) / 2 | |
160 | + x = width + 10 if x < 5 | |
161 | + label.x = x + @x | |
162 | + label.y = @height / 2 + 4 + @y | |
163 | + screen.draw label | |
164 | + | |
165 | +merge = (dist, src) -> | |
166 | + dist[k] = v for k, v of src when src.hasOwnProperty(k) | |
167 | + | |
168 | +screenPosition = (obj, offsetX, offsetY) -> | |
169 | + pos = {} | |
170 | + offset = | |
171 | + x: offsetX | |
172 | + y: offsetY | |
173 | + for m in screenPosition.fields when obj.hasOwnProperty(m) | |
174 | + pos[m] = obj[m] + offset[m[0]] | |
175 | + pos | |
176 | +screenPosition.fields = ['x', 'y', 'x0', 'y0', 'x1', 'y1'] | |
177 | + | |
178 | +KanjiInfo = | |
179 | + max: | |
180 | + kyoikuKanji: 1006 | |
181 | + level1st: 2965 | |
182 | + level2nd: 3390 | |
183 | + level3rd: 1259 | |
184 | + level4th: 2436 | |
185 | + update: (callback) -> | |
186 | + exec = (type, func) -> | |
187 | + $.ajax | |
188 | + type: 'GET' | |
189 | + url: '/cgi-bin/num-of-kanjis.cgi' | |
190 | + data: "type=#{type}" | |
191 | + dataType: 'json' | |
192 | + success: (data, dataType) -> | |
193 | + KanjiInfo[type] = data | |
194 | + func() | |
195 | + error: (request, textStatus, errorThrown) -> | |
196 | + alert(textStatus) | |
197 | + | |
198 | + exec 'gothic', -> | |
199 | + exec 'mincho', callback | |
200 | + | |
201 | +makeGraphPage = (screen, pageName) -> | |
202 | + # title | |
203 | + do -> | |
204 | + titleLabel = new Label window.dictionary.title, | |
205 | + x: 30 | |
206 | + y: 36 | |
207 | + font: '21px sans' | |
208 | + fontLabel = new Label window.dictionary.fonts[pageName], | |
209 | + x: 30 + titleLabel.getWidth() | |
210 | + y: 36 | |
211 | + font: '14px sans' | |
212 | + bottomLine = new Line y: 53, x0: 0, x1: 680 | |
213 | + | |
214 | + screen.add titleLabel | |
215 | + screen.add fontLabel | |
216 | + screen.add bottomLine | |
217 | + | |
218 | + # Graph Area | |
219 | + do -> | |
220 | + graphArea = new GradientRectangle | |
221 | + x0: 146 | |
222 | + y0: 75 | |
223 | + x1: 650 | |
224 | + y1: 268 | |
225 | + colors: [ | |
226 | + 'rgba(0, 0, 0, 0.25)' | |
227 | + 'rgba(0, 0, 0, 0.1)' | |
228 | + ] | |
229 | + | |
230 | + screen.add graphArea | |
231 | + | |
232 | + d = [650 - 146] / 4 | |
233 | + for _, x in new Array(5) | |
234 | + screen.add new Line | |
235 | + x: 146 + d * (x + 1) | |
236 | + y0: 75 | |
237 | + y1: 268 | |
238 | + color: "rgb(178, 255, 178)" | |
239 | + | |
240 | + # Graph bars | |
241 | + do -> | |
242 | + fields = [ | |
243 | + 'kyoikuKanji' | |
244 | + 'level1st' | |
245 | + 'level2nd' | |
246 | + 'level3rd' | |
247 | + 'level4th' | |
248 | + ] | |
249 | + | |
250 | + for field, n in fields | |
251 | + screen.add new Label window.dictionary[field], | |
252 | + x: 30 | |
253 | + y: 103 + (37 * n) | |
254 | + font: '14px sans' | |
255 | + | |
256 | + screen.add new GraphBar | |
257 | + x: 146 | |
258 | + y: 87 + (37 * n) | |
259 | + width: 504 | |
260 | + max: KanjiInfo.max[field] | |
261 | + performance: KanjiInfo[pageName][field] | |
262 | + | |
263 | + # Graph base line | |
264 | + screen.add new Line | |
265 | + x: 146, | |
266 | + y0: 75 | |
267 | + y1: 268 | |
268 | + color: "rgb(255, 255, 255)" | |
269 | + | |
270 | + screen | |
271 | + | |
272 | +$ -> | |
273 | + Canvas.generateContext() | |
274 | + return unless Canvas.ctx | |
275 | + | |
276 | + screenScale = (-> | |
277 | + scale = {} | |
278 | + scale[m] = parseInt(Canvas.$el.css(m)) for m in ['width', 'height'] | |
279 | + scale | |
280 | + )() | |
281 | + | |
282 | + screen = new Screen screenScale | |
283 | + | |
284 | + KanjiInfo.update -> | |
285 | + drawPage = (pageIndex) -> | |
286 | + pageName = drawPage.mapping[pageIndex] | |
287 | + makeGraphPage(screen, pageName).draw().animate() if pageName | |
288 | + drawPage.mapping = [ | |
289 | + 'gothic' | |
290 | + 'mincho' | |
291 | + ] | |
292 | + | |
293 | + $container = $('#docs-header .buttons-container .inner-container') | |
294 | + buttons = [] | |
295 | + for name, n in drawPage.mapping | |
296 | + b = document.createElement('div') | |
297 | + $(b).addClass('button').text(n + 1).click -> | |
298 | + return if screen.locking or $(@).hasClass('pressed') | |
299 | + screen.clear() | |
300 | + index = parseInt($(@).text() - 1) | |
301 | + name = drawPage.mapping[parseInt($(@).text() - 1)] | |
302 | + makeGraphPage(screen, name).draw().animate() if name | |
303 | + buttons.forEach (x) -> $(x).removeClass('pressed') | |
304 | + $(@).addClass('pressed') | |
305 | + $container.append(b) | |
306 | + buttons.push(b) | |
307 | + | |
308 | + drawPage(0) | |
309 | + $(buttons[0]).addClass('pressed') |
@@ -54,15 +54,16 @@ | ||
54 | 54 | div#docs-header .container .buttons-container .inner-container { |
55 | 55 | position: relative; |
56 | 56 | left: 600px; |
57 | - top: 260px; | |
57 | + top: 15px; | |
58 | 58 | } |
59 | 59 | div#docs-header .container .buttons-container .button { |
60 | - padding: .25em .5em; | |
60 | + padding: .25em .55em; | |
61 | 61 | background-color: #fff; |
62 | + border-radius: 0.55em; | |
62 | 63 | float: left; |
63 | 64 | font-family: Arial; |
64 | 65 | font-size: 10pt; |
65 | - margin: 1px 1px; | |
66 | + margin: 1px 2px; | |
66 | 67 | cursor: pointer; |
67 | 68 | } |
68 | 69 | div#docs-header .container .buttons-container .pressed { |
@@ -7,6 +7,7 @@ | ||
7 | 7 | <script src="js/mobile.js" type="text/javascript"></script> |
8 | 8 | <script src="js/jquery-2.1.0.min.js" type="text/javascript"></script> |
9 | 9 | <script src="js/lang.js" type="text/javascript"></script> |
10 | +<script src="js/doc-header/ja.js" type="text/javascript"></script> | |
10 | 11 | <script src="js/doc-header.js" type="text/javascript"></script> |
11 | 12 | </head> |
12 | 13 | <body> |
@@ -27,7 +28,7 @@ | ||
27 | 28 | <div id="docs-header"> |
28 | 29 | <div class="container"> |
29 | 30 | <div class="buttons-container"><div class="inner-container"></div></div> |
30 | -<canvas id="header-canvas" width="680" height="300"></canvas> | |
31 | +<canvas id="header-canvas" width="680" height="300"><!-- <img src="resources/sawarabi-header-a.png" /> --></canvas> | |
31 | 32 | </div> |
32 | 33 | </div> |
33 | 34 |
@@ -60,7 +61,7 @@ | ||
60 | 61 | </p> |
61 | 62 | <img src="img/sample-gothic.png" alt="書体見本(ゴシック)" /><br /> |
62 | 63 | <p> |
63 | - さわらび明朝(ver.20140415)の書体見本です。 | |
64 | + さわらび明朝(ver.20140815)の書体見本です。 | |
64 | 65 | </p> |
65 | 66 | <img src="img/sample-mincho.png" alt="書体見本(明朝)" /><br /> |
66 | 67 | </article> |
@@ -108,7 +109,9 @@ | ||
108 | 109 | |
109 | 110 | <footer> |
110 | 111 | <div class="container"> |
112 | +<!-- | |
111 | 113 | <a href="http://sourceforge.jp/"><img src="http://sourceforge.jp/sflogo.php?group_id=3896&type=1" width="96" height="31" alt="SourceForge.JP" /></a> |
114 | +--> | |
112 | 115 | </div> |
113 | 116 | </footer> |
114 | 117 | </body> |
@@ -1,7 +1,22 @@ | ||
1 | +// Generated by CoffeeScript 1.4.0 | |
1 | 2 | (function() { |
2 | - var o = function(d) { return navigator.userAgent.indexOf(d) > 0; }; | |
3 | - if (o('iPhone') || o('iPod') || o('Android')) { | |
4 | - path = location.pathname; | |
5 | - location.href = '/mobile' + path; | |
6 | - } | |
7 | -})(); | |
3 | + var browserNameIs, | |
4 | + __slice = [].slice; | |
5 | + | |
6 | + browserNameIs = function() { | |
7 | + var deviceName; | |
8 | + deviceName = 1 <= arguments.length ? __slice.call(arguments, 0) : []; | |
9 | + return deviceName.map(function(name) { | |
10 | + if (navigator.userAgent.indexOf(name) > 0) { | |
11 | + return 1; | |
12 | + } else { | |
13 | + return 9; | |
14 | + } | |
15 | + }).sort()[0] === 1; | |
16 | + }; | |
17 | + | |
18 | + if (browserNameIs('iPhone', 'iPod', 'Android')) { | |
19 | + location.href = "/mobile" + location.pathname; | |
20 | + } | |
21 | + | |
22 | +}).call(this); |
@@ -1,295 +1,546 @@ | ||
1 | -$(document).ready(function() { | |
2 | - function DocHeaderScreen(canvasElement, langKey, kanjiCounts) { | |
3 | - var TEXTS = { | |
4 | - ja: { | |
5 | - title: ['漢字収録進捗状況(さわらびゴシック)', | |
6 | - '漢字収録進捗状況(さわらび明朝)', | |
7 | - ], | |
8 | - kyoikuKanji: '教育漢字', | |
9 | - level1st: '第一水準漢字', | |
10 | - level2nd: '第二水準漢字', | |
11 | - level3rd: '第三水準漢字', | |
12 | - level4th: '第四水準漢字', | |
13 | - }, | |
14 | - en: { | |
15 | - title: ['Kanji Coverage (Sawarabi Gothic)', | |
16 | - 'Kanji Coverage (Sawarabi Mincho)', | |
17 | - ], | |
18 | - kyoikuKanji: 'Kyoiku Kanji', | |
19 | - level1st: 'JIS 1st Level', | |
20 | - level2nd: 'JIS 2nd Level', | |
21 | - level3rd: 'JIS 3rd Level', | |
22 | - level4th: 'JIS 4th Level', | |
23 | - }, | |
24 | - de: { | |
25 | - title: ['Kanji Coverage (Sawarabi Gothic)', | |
26 | - 'Kanji Coverage (Sawarabi Mincho)', | |
27 | - ], | |
28 | - kyoikuKanji: 'Kyoiku Kanji', | |
29 | - level1st: 'Niveau 1.', | |
30 | - level2nd: 'Niveau 2.', | |
31 | - level3rd: 'Niveau 3.', | |
32 | - level4th: 'Niveau 4.', | |
33 | - }, | |
34 | - }; | |
35 | - var texts = TEXTS[langKey]; | |
1 | +// Generated by CoffeeScript 1.4.0 | |
2 | +(function() { | |
3 | + var AbstractRectangle, Canvas, GradientRectangle, GraphBar, KanjiInfo, Label, Line, Screen, makeGraphPage, merge, screenPosition, | |
4 | + __hasProp = {}.hasOwnProperty, | |
5 | + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; | |
36 | 6 | |
37 | - function Label(text) { | |
38 | - this.text = text; | |
39 | - this.font = '10px sans'; | |
40 | - this.color = 'white'; | |
41 | - this.x = 0; | |
42 | - this.y = 0; | |
43 | - } | |
44 | - Label.prototype = { | |
45 | - setPosition: function(x, y) { | |
46 | - this.x = x; | |
47 | - this.y = y; | |
48 | - }, | |
49 | - getWidth: function() { | |
50 | - ctx.font = this.font; | |
51 | - var measure = ctx.measureText(this.text); | |
52 | - return measure.width; | |
53 | - }, | |
54 | - draw: function() { | |
55 | - var x = this.getX(); | |
56 | - var y = this.getY(); | |
57 | - ctx.font = this.font; | |
58 | - ctx.fillStyle = this.color; | |
59 | - ctx.fillText(this.text, x, y); | |
60 | - }, | |
61 | - getX: function() { | |
62 | - return screen.content.left + this.x; | |
63 | - }, | |
64 | - getY: function() { | |
65 | - return screen.content.top + this.y; | |
66 | - }, | |
67 | - }; | |
7 | + Canvas = { | |
8 | + el: "canvas#header-canvas", | |
9 | + generateContext: function() { | |
10 | + var cvs; | |
11 | + this.$el = $(this.el); | |
12 | + cvs = this.$el.get(0); | |
13 | + this.context = cvs && cvs.getContext ? cvs.getContext('2d') : null; | |
14 | + this.ctx = this.context; | |
15 | + if (this.ctx) { | |
16 | + return this.ctx.save(); | |
17 | + } | |
18 | + } | |
19 | + }; | |
68 | 20 | |
69 | - function GraphBar(height, max, performance) { | |
70 | - this.x = 0; | |
71 | - this.y = 0; | |
72 | - this.height = height; | |
73 | - this.max = max; | |
74 | - this.performance = performance; | |
75 | - this.frameColor = 'white'; | |
76 | - this.fillColor = '#088a29'; | |
77 | - } | |
78 | - GraphBar.prototype = { | |
79 | - draw: function(frame, frames) { | |
80 | - if (this.performance == 0) return; | |
81 | - var rate = (frame || 1) / (frames || 1); | |
82 | - var value = this.performance * rate; | |
83 | - var width = this.__calcWidth(value); | |
84 | - if (width <= 1) return; | |
85 | - ctx.fillStyle = this.fillColor; | |
86 | - ctx.fillRect(this.getX() + 1, this.getY(), width - 1, this.height); | |
87 | - }, | |
88 | - drawFrame: function() { | |
89 | - var width = screen.content.width - this.x; | |
90 | - ctx.strokeStyle = this.frameColor; | |
91 | - ctx.beginPath() | |
92 | - var x1 = this.getX() + 1; | |
93 | - var y1 = this.getY() - 1; | |
94 | - var x2 = this.getX() + width + 1; | |
95 | - var y2 = this.getY() + this.height + 2; | |
96 | - ctx.moveTo(x1, y1); | |
97 | - ctx.lineTo(x2, y1); | |
98 | - ctx.lineTo(x2, y2); | |
99 | - ctx.lineTo(x1, y2); | |
100 | - ctx.stroke(); | |
101 | - }, | |
102 | - drawRate: function() { | |
103 | - var rate = this.performance * 1.0 / this.max; | |
104 | - var caption = Math.round(rate * 10000) / 100 + '%'; | |
105 | - var label = new Label(caption); | |
106 | - label.font = '10pt Arial'; | |
107 | - var width = this.__calcWidth(); | |
108 | - var x = this.x + | |
109 | - (width > label.getWidth() ? | |
110 | - (width - label.getWidth()) / 2 : (width + 10)); | |
111 | - label.setPosition(x, this.y + 14); | |
112 | - label.draw(); | |
113 | - }, | |
114 | - setPosition: function(x, y) { | |
115 | - this.x = x; | |
116 | - this.y = y; | |
117 | - }, | |
118 | - getX: function() { | |
119 | - return screen.content.left + this.x; | |
120 | - }, | |
121 | - getY: function() { | |
122 | - return screen.content.top + this.y; | |
123 | - }, | |
124 | - __calcWidth: function(performance) { | |
125 | - var width = screen.content.width - this.x; | |
126 | - var value = performance || this.performance; | |
127 | - var rate = (value * 1.0) / this.max; | |
128 | - return parseInt(width * 1.0 * rate); | |
129 | - }, | |
130 | - }; | |
21 | + Screen = (function() { | |
131 | 22 | |
132 | - function KanjiCoverageGraphPage(title, data) { | |
133 | - this.title = this.createTitle(title); | |
134 | - this.data = data; | |
135 | - this.captions = []; | |
136 | - this.graphs = []; | |
137 | - this.__setupGraphs(); | |
138 | - this.pageLock = false; | |
139 | - } | |
140 | - KanjiCoverageGraphPage.prototype = { | |
141 | - draw: function() { | |
142 | - screen.clear(); | |
143 | - this.title.draw(); | |
144 | - for (var n in this.captions) { | |
145 | - this.captions[n].draw(); | |
146 | - this.graphs[n].drawFrame(); | |
147 | - } | |
148 | - var x = screen.content.left + this.graphs[0].x; | |
149 | - var y = screen.content.top + this.graphs[0].y; | |
150 | - ctx.strokeStyle = 'white'; | |
151 | - ctx.moveTo(x, y - 10); | |
152 | - var lastGraph = this.graphs[this.graphs.length - 1]; | |
153 | - y = screen.content.top + lastGraph.y + lastGraph.height; | |
154 | - ctx.lineTo(x, y + 10); | |
155 | - ctx.stroke(); | |
156 | - this.__drawAnimation(); | |
157 | - }, | |
158 | - createTitle: function(caption) { | |
159 | - var title = new Label(caption); | |
160 | - title.font = '21px Sans'; | |
161 | - return title; | |
162 | - }, | |
163 | - __addGraph: function(caption, graphBar) { | |
164 | - this.captions.push(caption); | |
165 | - this.graphs.push(graphBar); | |
166 | - }, | |
167 | - __setupGraphs: function() { | |
168 | - var kanjis = { | |
169 | - kyoikuKanji: 1006, | |
170 | - level1st: 2965, | |
171 | - level2nd: 3390, | |
172 | - level3rd: 1259, | |
173 | - level4th: 2436, | |
174 | - } | |
175 | - var y = 45; | |
176 | - for (var key in kanjis) { | |
177 | - var label = new Label(texts[key]); | |
178 | - label.font = "16px Sans"; | |
179 | - label.setPosition(0, y + 15); | |
180 | - var graph = new GraphBar(18, kanjis[key], this.data[key]); | |
181 | - graph.setPosition(130, y); | |
182 | - this.__addGraph(label, graph); | |
183 | - y += 30; | |
184 | - } | |
185 | - }, | |
186 | - __beforeAnimation: function() { | |
187 | - this.pageLock = true; | |
188 | - }, | |
189 | - __afterAnimation: function() { | |
190 | - this.pageLock = false; | |
191 | - }, | |
192 | - __drawAnimation: function() { | |
193 | - var frame = 1; | |
194 | - var frames = 16; | |
195 | - var that = this; | |
196 | - var scenario = function() { | |
197 | - for (var n in that.graphs) | |
198 | - that.graphs[n].draw(frame, frames); | |
199 | - if (frame++ < frames) { | |
200 | - setTimeout(scenario, 25); | |
201 | - } else { | |
202 | - for (var n in that.graphs) | |
203 | - that.graphs[n].drawRate(); | |
204 | - that.__afterAnimation(); | |
205 | - } | |
206 | - }; | |
207 | - this.__beforeAnimation(); | |
208 | - setTimeout(scenario, 100); | |
209 | - }, | |
210 | - }; | |
23 | + function Screen(attr) { | |
24 | + if (attr == null) { | |
25 | + attr = {}; | |
26 | + } | |
27 | + this.width = attr.width; | |
28 | + this.height = attr.height; | |
29 | + this.objects = []; | |
30 | + this.locking = false; | |
31 | + } | |
211 | 32 | |
212 | - function Screen() { | |
213 | - this.width = parseInt($(canvasElement).css('width')); | |
214 | - this.height = parseInt($(canvasElement).css('height')); | |
215 | - this.margin = { | |
216 | - top: 55, | |
217 | - left: 30, | |
218 | - bottom: 65, | |
219 | - right: 30, | |
220 | - }; | |
221 | - this.content = { | |
222 | - top: this.margin.top, | |
223 | - left: this.margin.left, | |
224 | - bottom: this.height - this.margin.bottom, | |
225 | - right: this.width - this.margin.right, | |
226 | - }; | |
227 | - this.content.width = this.content.right - this.content.left; | |
228 | - this.content.height = this.content.bottom - this.content.top; | |
229 | - } | |
230 | - Screen.prototype.clear = function() { | |
231 | - ctx.clearRect(0, 0, this.width, this.height); | |
232 | - }; | |
33 | + Screen.prototype.clear = function() { | |
34 | + Canvas.ctx.clearRect(0, 0, this.width, this.height); | |
35 | + Canvas.ctx.restore(); | |
36 | + Canvas.ctx.save(); | |
37 | + return this.objects = []; | |
38 | + }; | |
233 | 39 | |
234 | - var ctx = canvasElement.getContext('2d'); | |
235 | - var screen = new Screen(); | |
236 | - this.pages = [ | |
237 | - new KanjiCoverageGraphPage(texts.title[0], kanjiCounts['gothic']), | |
238 | - new KanjiCoverageGraphPage(texts.title[1], kanjiCounts['mincho']), | |
239 | - ]; | |
40 | + Screen.prototype.add = function(obj) { | |
41 | + return this.objects.push(obj); | |
42 | + }; | |
43 | + | |
44 | + Screen.prototype.draw = function(obj) { | |
45 | + var x, _i, _len, _ref; | |
46 | + if (obj) { | |
47 | + obj.draw(); | |
48 | + } else { | |
49 | + _ref = this.objects; | |
50 | + for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
51 | + x = _ref[_i]; | |
52 | + x.draw(); | |
53 | + } | |
54 | + } | |
55 | + return this; | |
56 | + }; | |
57 | + | |
58 | + Screen.prototype.animate = function() { | |
59 | + var _this = this; | |
60 | + this.locking = true; | |
61 | + return setTimeout(function() { | |
62 | + var animating, x, _i, _len, _ref; | |
63 | + animating = false; | |
64 | + _ref = _this.objects; | |
65 | + for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
66 | + x = _ref[_i]; | |
67 | + if (!((x.isAnimating != null) && x.isAnimating())) { | |
68 | + continue; | |
69 | + } | |
70 | + x.draw(); | |
71 | + animating = true; | |
72 | + } | |
73 | + if (animating) { | |
74 | + return _this.animate(); | |
75 | + } else { | |
76 | + return _this.afterAnimation(); | |
77 | + } | |
78 | + }, 25); | |
79 | + }; | |
80 | + | |
81 | + Screen.prototype.afterAnimation = function() { | |
82 | + var x, _i, _len, _ref, _results; | |
83 | + this.locking = false; | |
84 | + _ref = this.objects; | |
85 | + _results = []; | |
86 | + for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
87 | + x = _ref[_i]; | |
88 | + if (x.afterAnimation != null) { | |
89 | + _results.push(x.afterAnimation(this)); | |
90 | + } | |
91 | + } | |
92 | + return _results; | |
93 | + }; | |
94 | + | |
95 | + return Screen; | |
96 | + | |
97 | + })(); | |
98 | + | |
99 | + Label = (function() { | |
100 | + | |
101 | + function Label(text, attr) { | |
102 | + var _ref, _ref1, _ref2, _ref3; | |
103 | + if (attr == null) { | |
104 | + attr = {}; | |
105 | + } | |
106 | + this.text = text; | |
107 | + merge(this, attr); | |
108 | + if ((_ref = this.font) == null) { | |
109 | + this.font = '10px sans'; | |
110 | + } | |
111 | + if ((_ref1 = this.color) == null) { | |
112 | + this.color = 'white'; | |
113 | + } | |
114 | + if ((_ref2 = this.x) == null) { | |
115 | + this.x = 0; | |
116 | + } | |
117 | + if ((_ref3 = this.y) == null) { | |
118 | + this.y = 0; | |
119 | + } | |
240 | 120 | } |
241 | 121 | |
242 | - function getNumOfKanjis() { | |
243 | - var url = '/cgi-bin/num-of-kanjis.cgi'; | |
244 | - var fontTypes = ['gothic', 'mincho']; | |
245 | - var result = {}; | |
246 | - for (var n in fontTypes) { | |
247 | - $.ajax({ | |
122 | + Label.prototype.getWidth = function() { | |
123 | + Canvas.ctx.font = this.font; | |
124 | + return Canvas.ctx.measureText(this.text).width; | |
125 | + }; | |
126 | + | |
127 | + Label.prototype.draw = function(offsetX, offsetY) { | |
128 | + var pos; | |
129 | + if (offsetX == null) { | |
130 | + offsetX = 0; | |
131 | + } | |
132 | + if (offsetY == null) { | |
133 | + offsetY = 0; | |
134 | + } | |
135 | + pos = screenPosition(this, offsetX, offsetY); | |
136 | + Canvas.ctx.font = this.font; | |
137 | + Canvas.ctx.fillStyle = this.color; | |
138 | + return Canvas.ctx.fillText(this.text, pos.x, pos.y); | |
139 | + }; | |
140 | + | |
141 | + return Label; | |
142 | + | |
143 | + })(); | |
144 | + | |
145 | + Line = (function() { | |
146 | + | |
147 | + function Line(attr) { | |
148 | + if (attr == null) { | |
149 | + attr = {}; | |
150 | + } | |
151 | + this.x0 = attr.x0 || attr.x || 0; | |
152 | + this.y0 = attr.y0 || attr.y || 0; | |
153 | + this.x1 = attr.x1 || attr.x || 0; | |
154 | + this.y1 = attr.y1 || attr.y || 0; | |
155 | + this.color = attr.color || '#fff'; | |
156 | + } | |
157 | + | |
158 | + Line.prototype.draw = function(offsetX, offsetY) { | |
159 | + var c, pos; | |
160 | + if (offsetX == null) { | |
161 | + offsetX = 0; | |
162 | + } | |
163 | + if (offsetY == null) { | |
164 | + offsetY = 0; | |
165 | + } | |
166 | + pos = screenPosition(this, offsetX, offsetY); | |
167 | + c = Canvas.ctx; | |
168 | + c.beginPath(); | |
169 | + c.strokeStyle = this.color; | |
170 | + c.moveTo(pos.x0, pos.y0); | |
171 | + c.lineTo(pos.x1, pos.y1); | |
172 | + c.stroke(); | |
173 | + return c.closePath(); | |
174 | + }; | |
175 | + | |
176 | + return Line; | |
177 | + | |
178 | + })(); | |
179 | + | |
180 | + AbstractRectangle = (function() { | |
181 | + | |
182 | + function AbstractRectangle(attr) { | |
183 | + var _ref, _ref1, _ref2, _ref3; | |
184 | + if (attr == null) { | |
185 | + attr = {}; | |
186 | + } | |
187 | + merge(this, attr); | |
188 | + if ((_ref = this.x0) == null) { | |
189 | + this.x0 = 0; | |
190 | + } | |
191 | + if ((_ref1 = this.y0) == null) { | |
192 | + this.y0 = 0; | |
193 | + } | |
194 | + if ((_ref2 = this.x1) == null) { | |
195 | + this.x1 = 0; | |
196 | + } | |
197 | + if ((_ref3 = this.y1) == null) { | |
198 | + this.y1 = 0; | |
199 | + } | |
200 | + } | |
201 | + | |
202 | + AbstractRectangle.prototype.draw = function(offsetX, offsetY) { | |
203 | + var pos; | |
204 | + if (offsetX == null) { | |
205 | + offsetX = 0; | |
206 | + } | |
207 | + if (offsetY == null) { | |
208 | + offsetY = 0; | |
209 | + } | |
210 | + pos = screenPosition(this, offsetX, offsetY); | |
211 | + Canvas.ctx.beginPath(); | |
212 | + return Canvas.ctx.rect(pos.x0, pos.y0, pos.x1 - pos.x0, pos.y1 - pos.y0); | |
213 | + }; | |
214 | + | |
215 | + return AbstractRectangle; | |
216 | + | |
217 | + })(); | |
218 | + | |
219 | + GradientRectangle = (function(_super) { | |
220 | + | |
221 | + __extends(GradientRectangle, _super); | |
222 | + | |
223 | + function GradientRectangle(attr) { | |
224 | + var _ref, _ref1; | |
225 | + if (attr == null) { | |
226 | + attr = {}; | |
227 | + } | |
228 | + GradientRectangle.__super__.constructor.call(this, attr); | |
229 | + if ((_ref = this.colors) == null) { | |
230 | + this.colors = ['#fff', '#fff']; | |
231 | + } | |
232 | + if ((_ref1 = this.direction) == null) { | |
233 | + this.direction = 'horizontal'; | |
234 | + } | |
235 | + } | |
236 | + | |
237 | + GradientRectangle.prototype.draw = function(offsetX, offsetY) { | |
238 | + var c, d, g, p, v, _i, _len, _ref; | |
239 | + if (offsetX == null) { | |
240 | + offsetX = 0; | |
241 | + } | |
242 | + if (offsetY == null) { | |
243 | + offsetY = 0; | |
244 | + } | |
245 | + c = Canvas.ctx; | |
246 | + p = screenPosition(this, offsetX, offsetY); | |
247 | + g = null; | |
248 | + if (this.direction === 'vertical') { | |
249 | + g = c.createLinearGradient(p.x0, p.y0, p.x0, p.y1); | |
250 | + } else if (this.direction === 'horizontal') { | |
251 | + g = c.createLinearGradient(p.x0, p.y0, p.x1, p.y0); | |
252 | + } | |
253 | + d = 0.0; | |
254 | + _ref = this.colors; | |
255 | + for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
256 | + v = _ref[_i]; | |
257 | + g.addColorStop(d, v); | |
258 | + d += 1 / (this.colors.length - 1); | |
259 | + } | |
260 | + c.fillStyle = g; | |
261 | + GradientRectangle.__super__.draw.call(this, offsetX, offsetY); | |
262 | + return c.fill(); | |
263 | + }; | |
264 | + | |
265 | + return GradientRectangle; | |
266 | + | |
267 | + })(AbstractRectangle); | |
268 | + | |
269 | + GraphBar = (function() { | |
270 | + | |
271 | + function GraphBar(attr) { | |
272 | + var _ref, _ref1, _ref2, _ref3; | |
273 | + if (attr == null) { | |
274 | + attr = {}; | |
275 | + } | |
276 | + merge(this, attr); | |
277 | + if ((_ref = this.x) == null) { | |
278 | + this.x = 0; | |
279 | + } | |
280 | + if ((_ref1 = this.y) == null) { | |
281 | + this.y = 0; | |
282 | + } | |
283 | + if ((_ref2 = this.width) == null) { | |
284 | + this.width = 1; | |
285 | + } | |
286 | + if ((_ref3 = this.height) == null) { | |
287 | + this.height = 24; | |
288 | + } | |
289 | + this.performance = attr.performance || 0; | |
290 | + this.max = attr.max || 1; | |
291 | + this.frame = 0.0; | |
292 | + this.frames = 10.0; | |
293 | + } | |
294 | + | |
295 | + GraphBar.prototype.draw = function(offsetX, offsetY) { | |
296 | + var c, g, pos, width; | |
297 | + if (offsetX == null) { | |
298 | + offsetX = 0; | |
299 | + } | |
300 | + if (offsetY == null) { | |
301 | + offsetY = 0; | |
302 | + } | |
303 | + width = (this.width * 1.0) / this.max * this.performance * this.frame / this.frames; | |
304 | + c = Canvas.ctx; | |
305 | + c.beginPath(); | |
306 | + if (this.frame === this.frames) { | |
307 | + c.shadowBlur = 4; | |
308 | + c.shadowOffsetY = 2; | |
309 | + c.shadowColor = "rgba(0, 0, 0, 0.4)"; | |
310 | + } | |
311 | + pos = screenPosition(this, offsetX, offsetY); | |
312 | + g = c.createLinearGradient(pos.x, pos.y, pos.x, pos.y + this.height); | |
313 | + g.addColorStop(0.0, "#fc8a27"); | |
314 | + g.addColorStop(0.1, "#fcb229"); | |
315 | + g.addColorStop(0.4, "#fc8a29"); | |
316 | + g.addColorStop(1.0, "#e97122"); | |
317 | + c.fillStyle = g; | |
318 | + c.rect(pos.x, pos.y, width, this.height); | |
319 | + return c.fill(); | |
320 | + }; | |
321 | + | |
322 | + GraphBar.prototype.isAnimating = function() { | |
323 | + this.frame += 1; | |
324 | + return this.frame <= this.frames; | |
325 | + }; | |
326 | + | |
327 | + GraphBar.prototype.afterAnimation = function(screen) { | |
328 | + var label, rate, val, width, x; | |
329 | + rate = 100.0 * this.performance / this.max; | |
330 | + val = rate.toFixed(2); | |
331 | + if (parseInt(val) * 1.0 === Number(val)) { | |
332 | + val = parseInt(val); | |
333 | + } | |
334 | + label = new Label("" + val + "%", { | |
335 | + font: '12px sans' | |
336 | + }); | |
337 | + width = 1.0 * this.width / this.max * this.performance; | |
338 | + x = (width - label.getWidth()) / 2; | |
339 | + if (x < 5) { | |
340 | + x = width + 10; | |
341 | + } | |
342 | + label.x = x + this.x; | |
343 | + label.y = this.height / 2 + 4 + this.y; | |
344 | + return screen.draw(label); | |
345 | + }; | |
346 | + | |
347 | + return GraphBar; | |
348 | + | |
349 | + })(); | |
350 | + | |
351 | + merge = function(dist, src) { | |
352 | + var k, v, _results; | |
353 | + _results = []; | |
354 | + for (k in src) { | |
355 | + v = src[k]; | |
356 | + if (src.hasOwnProperty(k)) { | |
357 | + _results.push(dist[k] = v); | |
358 | + } | |
359 | + } | |
360 | + return _results; | |
361 | + }; | |
362 | + | |
363 | + screenPosition = function(obj, offsetX, offsetY) { | |
364 | + var m, offset, pos, _i, _len, _ref; | |
365 | + pos = {}; | |
366 | + offset = { | |
367 | + x: offsetX, | |
368 | + y: offsetY | |
369 | + }; | |
370 | + _ref = screenPosition.fields; | |
371 | + for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
372 | + m = _ref[_i]; | |
373 | + if (obj.hasOwnProperty(m)) { | |
374 | + pos[m] = obj[m] + offset[m[0]]; | |
375 | + } | |
376 | + } | |
377 | + return pos; | |
378 | + }; | |
379 | + | |
380 | + screenPosition.fields = ['x', 'y', 'x0', 'y0', 'x1', 'y1']; | |
381 | + | |
382 | + KanjiInfo = { | |
383 | + max: { | |
384 | + kyoikuKanji: 1006, | |
385 | + level1st: 2965, | |
386 | + level2nd: 3390, | |
387 | + level3rd: 1259, | |
388 | + level4th: 2436 | |
389 | + }, | |
390 | + update: function(callback) { | |
391 | + var exec; | |
392 | + exec = function(type, func) { | |
393 | + return $.ajax({ | |
248 | 394 | type: 'GET', |
249 | - url: url, | |
250 | - data: "type=" + fontTypes[n], | |
395 | + url: '/cgi-bin/num-of-kanjis.cgi', | |
396 | + data: "type=" + type, | |
251 | 397 | dataType: 'json', |
252 | 398 | success: function(data, dataType) { |
253 | - result[fontTypes[n]] = data; | |
399 | + KanjiInfo[type] = data; | |
400 | + return func(); | |
254 | 401 | }, |
255 | 402 | error: function(request, textStatus, errorThrown) { |
256 | - alert(textStatus); | |
257 | - }, | |
258 | - async: false, | |
403 | + return alert(textStatus); | |
404 | + } | |
259 | 405 | }); |
260 | - } | |
261 | - return result; | |
406 | + }; | |
407 | + return exec('gothic', function() { | |
408 | + return exec('mincho', callback); | |
409 | + }); | |
262 | 410 | } |
411 | + }; | |
263 | 412 | |
264 | - | |
413 | + makeGraphPage = function(screen, pageName) { | |
265 | 414 | (function() { |
266 | - var canvas = $("canvas#header-canvas").get(0); | |
267 | - if (! canvas || ! canvas.getContext) return false; | |
415 | + var bottomLine, fontLabel, titleLabel; | |
416 | + titleLabel = new Label(window.dictionary.title, { | |
417 | + x: 30, | |
418 | + y: 36, | |
419 | + font: '21px sans' | |
420 | + }); | |
421 | + fontLabel = new Label(window.dictionary.fonts[pageName], { | |
422 | + x: 30 + titleLabel.getWidth(), | |
423 | + y: 36, | |
424 | + font: '14px sans' | |
425 | + }); | |
426 | + bottomLine = new Line({ | |
427 | + y: 53, | |
428 | + x0: 0, | |
429 | + x1: 680 | |
430 | + }); | |
431 | + screen.add(titleLabel); | |
432 | + screen.add(fontLabel); | |
433 | + return screen.add(bottomLine); | |
434 | + })(); | |
435 | + (function() { | |
436 | + var d, graphArea, x, _, _i, _len, _ref, _results; | |
437 | + graphArea = new GradientRectangle({ | |
438 | + x0: 146, | |
439 | + y0: 75, | |
440 | + x1: 650, | |
441 | + y1: 268, | |
442 | + colors: ['rgba(0, 0, 0, 0.25)', 'rgba(0, 0, 0, 0.1)'] | |
443 | + }); | |
444 | + screen.add(graphArea); | |
445 | + d = [650 - 146] / 4; | |
446 | + _ref = new Array(5); | |
447 | + _results = []; | |
448 | + for (x = _i = 0, _len = _ref.length; _i < _len; x = ++_i) { | |
449 | + _ = _ref[x]; | |
450 | + _results.push(screen.add(new Line({ | |
451 | + x: 146 + d * (x + 1), | |
452 | + y0: 75, | |
453 | + y1: 268, | |
454 | + color: "rgb(178, 255, 178)" | |
455 | + }))); | |
456 | + } | |
457 | + return _results; | |
458 | + })(); | |
459 | + (function() { | |
460 | + var field, fields, n, _i, _len, _results; | |
461 | + fields = ['kyoikuKanji', 'level1st', 'level2nd', 'level3rd', 'level4th']; | |
462 | + _results = []; | |
463 | + for (n = _i = 0, _len = fields.length; _i < _len; n = ++_i) { | |
464 | + field = fields[n]; | |
465 | + screen.add(new Label(window.dictionary[field], { | |
466 | + x: 30, | |
467 | + y: 103 + (37 * n), | |
468 | + font: '14px sans' | |
469 | + })); | |
470 | + _results.push(screen.add(new GraphBar({ | |
471 | + x: 146, | |
472 | + y: 87 + (37 * n), | |
473 | + width: 504, | |
474 | + max: KanjiInfo.max[field], | |
475 | + performance: KanjiInfo[pageName][field] | |
476 | + }))); | |
477 | + } | |
478 | + return _results; | |
479 | + })(); | |
480 | + screen.add(new Line({ | |
481 | + x: 146, | |
482 | + y0: 75, | |
483 | + y1: 268, | |
484 | + color: "rgb(255, 255, 255)" | |
485 | + })); | |
486 | + return screen; | |
487 | + }; | |
268 | 488 | |
269 | - var kanjiCounts = getNumOfKanjis(); | |
270 | - var key = $('#current-lang').attr('data-key'); | |
271 | - var headerScreen = new DocHeaderScreen(canvas, key, kanjiCounts); | |
272 | - var container = $("#docs-header .buttons-container .inner-container"); | |
273 | - var buttons = []; | |
274 | - for (var n in headerScreen.pages) { | |
275 | - var button = document.createElement("div"); | |
276 | - $(button).addClass("button").text(parseInt(n) + 1); | |
277 | - container.append(button); | |
278 | - buttons.push(button); | |
279 | - } | |
280 | - headerScreen.pages[0].draw(); | |
281 | - var pageIndex = 0; | |
282 | - $(buttons[0]).addClass('pressed'); | |
283 | - for (var n in buttons) { | |
284 | - $(buttons[n]).click(function() { | |
285 | - var index = parseInt($(this).text()) - 1; | |
286 | - if (index != pageIndex) { | |
287 | - headerScreen.pages[index].draw(); | |
288 | - for (var i in buttons) $(buttons[i]).removeClass('pressed'); | |
289 | - $(this).addClass('pressed'); | |
290 | - pageIndex = index; | |
291 | - } | |
292 | - }); | |
293 | - } | |
489 | + $(function() { | |
490 | + var screen, screenScale; | |
491 | + Canvas.generateContext(); | |
492 | + if (!Canvas.ctx) { | |
493 | + return; | |
494 | + } | |
495 | + screenScale = (function() { | |
496 | + var m, scale, _i, _len, _ref; | |
497 | + scale = {}; | |
498 | + _ref = ['width', 'height']; | |
499 | + for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
500 | + m = _ref[_i]; | |
501 | + scale[m] = parseInt(Canvas.$el.css(m)); | |
502 | + } | |
503 | + return scale; | |
294 | 504 | })(); |
295 | -}); | |
505 | + screen = new Screen(screenScale); | |
506 | + return KanjiInfo.update(function() { | |
507 | + var $container, b, buttons, drawPage, n, name, _i, _len, _ref; | |
508 | + drawPage = function(pageIndex) { | |
509 | + var pageName; | |
510 | + pageName = drawPage.mapping[pageIndex]; | |
511 | + if (pageName) { | |
512 | + return makeGraphPage(screen, pageName).draw().animate(); | |
513 | + } | |
514 | + }; | |
515 | + drawPage.mapping = ['gothic', 'mincho']; | |
516 | + $container = $('#docs-header .buttons-container .inner-container'); | |
517 | + buttons = []; | |
518 | + _ref = drawPage.mapping; | |
519 | + for (n = _i = 0, _len = _ref.length; _i < _len; n = ++_i) { | |
520 | + name = _ref[n]; | |
521 | + b = document.createElement('div'); | |
522 | + $(b).addClass('button').text(n + 1).click(function() { | |
523 | + var index; | |
524 | + if (screen.locking || $(this).hasClass('pressed')) { | |
525 | + return; | |
526 | + } | |
527 | + screen.clear(); | |
528 | + index = parseInt($(this).text() - 1); | |
529 | + name = drawPage.mapping[parseInt($(this).text() - 1)]; | |
530 | + if (name) { | |
531 | + makeGraphPage(screen, name).draw().animate(); | |
532 | + } | |
533 | + buttons.forEach(function(x) { | |
534 | + return $(x).removeClass('pressed'); | |
535 | + }); | |
536 | + return $(this).addClass('pressed'); | |
537 | + }); | |
538 | + $container.append(b); | |
539 | + buttons.push(b); | |
540 | + } | |
541 | + drawPage(0); | |
542 | + return $(buttons[0]).addClass('pressed'); | |
543 | + }); | |
544 | + }); | |
545 | + | |
546 | +}).call(this); |
@@ -0,0 +1,17 @@ | ||
1 | +// Generated by CoffeeScript 1.4.0 | |
2 | +(function() { | |
3 | + | |
4 | + this.dictionary = { | |
5 | + title: 'Kanji Coverage', | |
6 | + fonts: { | |
7 | + gothic: ' (Sawarabi Gothic)', | |
8 | + mincho: ' (Sawarabi Mincho)' | |
9 | + }, | |
10 | + kyoikuKanji: 'Kyoiku Kanji', | |
11 | + level1st: 'JIS 1st Level', | |
12 | + level2nd: 'JIS 2nd Level', | |
13 | + level3rd: 'JIS 3rd Level', | |
14 | + level4th: 'JIS 4th Level' | |
15 | + }; | |
16 | + | |
17 | +}).call(this); |
@@ -0,0 +1,17 @@ | ||
1 | +// Generated by CoffeeScript 1.4.0 | |
2 | +(function() { | |
3 | + | |
4 | + this.dictionary = { | |
5 | + title: '漢字収録率', | |
6 | + fonts: { | |
7 | + gothic: '(さわらびゴシック)', | |
8 | + mincho: '(さわらび明朝)' | |
9 | + }, | |
10 | + kyoikuKanji: '教育漢字', | |
11 | + level1st: '第一水準漢字', | |
12 | + level2nd: '第二水準漢字', | |
13 | + level3rd: '第三水準漢字', | |
14 | + level4th: '第四水準漢字' | |
15 | + }; | |
16 | + | |
17 | +}).call(this); |
@@ -1,39 +1,107 @@ | ||
1 | -var availableLanguages = { | |
2 | - de: "Deutsch", | |
1 | +// Generated by CoffeeScript 1.4.0 | |
2 | +(function() { | |
3 | + var CurrentLangLabel, LangMenu, LangMenuItem, availableLanguages, main; | |
4 | + | |
5 | + availableLanguages = { | |
3 | 6 | en: "English", |
4 | - ja: "日本語", | |
5 | -}; | |
7 | + ja: "日本語" | |
8 | + }; | |
6 | 9 | |
7 | -$(document).ready(function() { | |
8 | - var menu = $("#lang-menu-container"); | |
9 | - var currentText = $("div#navbar").text().replace(/\s/g, ''); | |
10 | - for (var key in availableLanguages) { | |
11 | - var c = availableLanguages[key]; | |
12 | - if (c == currentText) { | |
13 | - $("div#current-lang").attr({"data-key": key}); | |
14 | - } else { | |
15 | - var item = document.createElement("div"); | |
16 | - $(item).attr({"data-key": key}); | |
17 | - $(item).addClass("item").css({clear: "both"}).attr({lang: key}).text(c); | |
18 | - menu.append(item); | |
10 | + main = function() { | |
11 | + this.menu = new LangMenu(); | |
12 | + this.currentLabel = new CurrentLangLabel(this.menu); | |
13 | + this.menu.buildItems(this.currentLabel.text()); | |
14 | + return this.currentLabel.$el.attr({ | |
15 | + "data-key": this.menu.currentLangSymbol | |
16 | + }); | |
17 | + }; | |
18 | + | |
19 | + CurrentLangLabel = (function() { | |
20 | + | |
21 | + function CurrentLangLabel(menu) { | |
22 | + var _this = this; | |
23 | + this.el = "#current-lang"; | |
24 | + this.$el = $(this.el); | |
25 | + this.menu = menu; | |
26 | + this.$el.click(function(event) { | |
27 | + event.stopPropagation(); | |
28 | + return $(_this.menu.$el).css({ | |
29 | + "z-index": 99 | |
30 | + }).toggle(); | |
31 | + }); | |
19 | 32 | } |
20 | - } | |
21 | - $('div#lang').append(menu); | |
22 | 33 | |
23 | - $('body').click(function() { | |
24 | - $(menu).hide(); | |
34 | + CurrentLangLabel.prototype.text = function() { | |
35 | + return this.$el.text().replace(/\s/g, ''); | |
36 | + }; | |
37 | + | |
38 | + return CurrentLangLabel; | |
39 | + | |
40 | + })(); | |
41 | + | |
42 | + LangMenuItem = (function() { | |
43 | + | |
44 | + function LangMenuItem(langSymbol, langText) { | |
45 | + this.$el = $(document.createElement("div")); | |
46 | + this.$el.attr({ | |
47 | + "data-key": langSymbol, | |
48 | + lang: langSymbol | |
49 | + }).addClass("item").css({ | |
50 | + clear: "both" | |
51 | + }).text(langText); | |
52 | + } | |
53 | + | |
54 | + return LangMenuItem; | |
55 | + | |
56 | + })(); | |
57 | + | |
58 | + LangMenu = (function() { | |
59 | + | |
60 | + function LangMenu() { | |
61 | + this.el = "#lang-menu-container"; | |
62 | + this.$el = $(this.el); | |
63 | + } | |
64 | + | |
65 | + LangMenu.prototype.buildItems = function(currentLangText) { | |
66 | + var k, v, | |
67 | + _this = this; | |
68 | + for (k in availableLanguages) { | |
69 | + v = availableLanguages[k]; | |
70 | + if (v === currentLangText) { | |
71 | + this.currentLangSymbol = k; | |
72 | + } else { | |
73 | + this.$el.append(new LangMenuItem(k, v).$el); | |
74 | + } | |
75 | + } | |
76 | + $('.item', this.$el).click(this.onclickItem); | |
77 | + $('body').click(function() { | |
78 | + return _this.$el.hide(); | |
79 | + }); | |
80 | + }; | |
81 | + | |
82 | + LangMenu.prototype.onclickItem = function(event) { | |
83 | + var key, root; | |
84 | + console.log(this); | |
85 | + if ($(this).attr("id") === "current-lang") { | |
86 | + return; | |
87 | + } | |
88 | + key = $(this).attr("data-key") + '/'; | |
89 | + if (key === 'ja/') { | |
90 | + key = ''; | |
91 | + } | |
92 | + root = '../'; | |
93 | + if ($("div#current-lang").attr("data-key") === "ja") { | |
94 | + root = './'; | |
95 | + } | |
96 | + window.location = root + key; | |
97 | + }; | |
98 | + | |
99 | + return LangMenu; | |
100 | + | |
101 | + })(); | |
102 | + | |
103 | + $(function() { | |
104 | + return main(); | |
25 | 105 | }); |
26 | - $('div#lang .item').click(function(event) { | |
27 | - if ($(this).attr("id") == "current-lang") return; | |
28 | - var key = $(this).attr("data-key") + '/'; | |
29 | - if (key == 'ja/') key = ''; | |
30 | - var root = "../" | |
31 | - if ($("div#current-lang").attr("data-key") == "ja") root = "./" | |
32 | - window.location = root + key; | |
33 | - }); | |
34 | - $('div#current-lang').click(function(event) { | |
35 | - event.stopPropagation(); | |
36 | - $(menu).css({'z-index': 99}); | |
37 | - $(menu).toggle(); | |
38 | - }); | |
39 | -}); | |
106 | + | |
107 | +}).call(this); |
@@ -7,6 +7,7 @@ | ||
7 | 7 | <script src="../js/mobile.js" type="text/javascript"></script> |
8 | 8 | <script src="../js/jquery-2.1.0.min.js" type="text/javascript"></script> |
9 | 9 | <script src="../js/lang.js" type="text/javascript"></script> |
10 | +<script src="../js/doc-header/en.js" type="text/javascript"></script> | |
10 | 11 | <script src="../js/doc-header.js" type="text/javascript"></script> |
11 | 12 | </head> |
12 | 13 | <body> |
@@ -63,7 +64,7 @@ | ||
63 | 64 | </p> |
64 | 65 | <img src="../img/sample-gothic.png" alt="Sample (Gothic)" /><br /> |
65 | 66 | <p> |
66 | -Sawarabi Mincho (ver.20140415). | |
67 | +Sawarabi Mincho (ver.20140815). | |
67 | 68 | </p> |
68 | 69 | <img src="../img/sample-mincho.png" alt="Sample (Mincho)" /><br /> |
69 | 70 | </article> |
@@ -0,0 +1,117 @@ | ||
1 | +<!DOCTYPE html> | |
2 | +<html> | |
3 | +<head> | |
4 | +<meta http-equiv="content-type" content="text/html; charset=utf-8"> | |
5 | +<title>試し書きコーナー | さわらびフォント</title> | |
6 | +<link rel="stylesheet" href="../css/style.css" type="text/css" /> | |
7 | +<script src="js/mobile.js" type="text/javascript"></script> | |
8 | +<script src="../js/jquery-2.1.0.min.js" type="text/javascript"></script> | |
9 | +<script src="../js/lang.js" type="text/javascript"></script> | |
10 | +<script src="js/doc-header.js" type="text/javascript"></script> | |
11 | +</head> | |
12 | +<body> | |
13 | +<header> | |
14 | +<div class="container"> | |
15 | +<div id="navbar"> | |
16 | +<div class="logo"> | |
17 | +<a href="/"><img src="../img/logo-ja.png" alt="さわらびフォント" /></a> | |
18 | +</div> | |
19 | +<div id="lang"> | |
20 | +<div id="current-lang" class="item" title="Select your language">日本語</div> | |
21 | +<div id="lang-menu-container" class="container"> | |
22 | +</div> | |
23 | +</div> | |
24 | +</div> | |
25 | +<div style="clear: both;"></div> | |
26 | +</div> | |
27 | +</header> | |
28 | + | |
29 | +<div id="docs-header"> | |
30 | +<div class="container"> | |
31 | +<div class="buttons-container"><div class="inner-container"></div></div> | |
32 | +<canvas id="header-canvas" width="680" height="300"></canvas> | |
33 | +</div> | |
34 | +</div> | |
35 | + | |
36 | +<div id="docs"> | |
37 | +<div class="container"> | |
38 | +<article> | |
39 | +<h2>概要</h2> | |
40 | +<p> | |
41 | + さわらびフォントは、フリーなライセンスで提供している日本語フォントです。現在、ゴシック体のさわらびゴシックと明朝体のさわらび明朝の 2 種類のフォントを公開しています。 | |
42 | +</p> | |
43 | +<p> | |
44 | + なお、公開しているとはいえ、現在のところどちらのフォントも開発中という段階です。残念ながら、現状では通常用途に必要な漢字なども十分には揃っていません(ない文字は、ご利用の OS によっては自動補完が働き、別フォントで表示されるかと思います)。ご利用の際はあらかじめご了承ください。 | |
45 | +</p> | |
46 | +</article> | |
47 | + | |
48 | +<article> | |
49 | +<h2>ライセンス</h2> | |
50 | +<p> | |
51 | + さわらびフォントのライセンスは、Creative Commons Attribution 3.0 です。このライセンスの内容は、以下のリンクからご覧いただけます。 | |
52 | +</p> | |
53 | +<ul> | |
54 | +<li><a href="http://creativecommons.org/licenses/by/3.0/deed.ja" target="_blank">Creative Commons Attribution 3.0</a></li> | |
55 | +</ul> | |
56 | +</article> | |
57 | + | |
58 | +<article> | |
59 | +<h2>書体見本</h2> | |
60 | +<p> | |
61 | + さわらびゴシック(ver.20140215)の書体見本です。 | |
62 | +</p> | |
63 | +<img src="img/sample-gothic-20140215.png" alt="書体見本(ゴシック)" /><br /> | |
64 | +<p> | |
65 | + さわらび明朝(ver.20140315)の書体見本です。 | |
66 | +</p> | |
67 | +<img src="img/sample-mincho-20140315.png" alt="書体見本(明朝)" /><br /> | |
68 | +</article> | |
69 | + | |
70 | +<article> | |
71 | +<h2>ダウンロード</h2> | |
72 | +<p> | |
73 | + 下のリンクから各フォントをダウンロードすることができます。なお、さわらびゴシックが sawarabi-gothic、さわらび明朝が sawarabi-mincho に対応しています。 | |
74 | +</p> | |
75 | +<div id="download-box"> | |
76 | +<script charset="utf-8" type="text/javascript" src="http://sourceforge.jp/projects/sawarabi-fonts/files/compact.js"></script> | |
77 | +<noscript> | |
78 | +<p style="border: 1px solid black"> (JavaScript が有効になっていない場合は、ここにリンクは現れません。ダウンロードは <a href="http://sourceforge.jp/projects/sawarabi-fonts/">SourceForge.JP のプロジェクトページ</a>から行ってください。)</p> | |
79 | +</noscript> | |
80 | +</div> | |
81 | +</article> | |
82 | + | |
83 | +<article> | |
84 | +<h2>ゴシック体の試し書き</h2> | |
85 | +<p> | |
86 | + 以下のページで、さわらびゴシックの“試し書き”ができます。 | |
87 | +</p> | |
88 | +<ul> | |
89 | +<li><a href="http://sawarabi-fonts.sourceforge.jp/sampler/sawarabi-sampler.html">さわらびゴシック試し書きコーナー</a></li> | |
90 | +</ul> | |
91 | +<p> | |
92 | + 試し書きができる、と書きましたが、つまりは、自由に入力した任意の文字列をさわらびゴシックで表示できるようにした、簡単なウェブアプリケーションが用意してあるということです。さわらびゴシックのデザインがどうなっているのか、もっといろんな文字で見てみたいとき、気になる文字がさわらびゴシックに入っているのかどうか確認してみたいときなど、ご利用いただければと思います。 | |
93 | +</p> | |
94 | +<p> | |
95 | + なお、こちらのページでは JavaScript が動かせるようになっている必要があります。また、Internet Explorer ではキレイな表示結果が得られません。お試しには、Mozilla Firefox や Safari、Google Chrome などをお勧めいたします。 | |
96 | +</p> | |
97 | +</article> | |
98 | + | |
99 | +<article> | |
100 | +<h2>リンク</h2> | |
101 | +<dl> | |
102 | +<dt><a href="http://sourceforge.jp/projects/sawarabi-fonts/">さわらびフォントのプロジェクトページ</a></dt> | |
103 | +<dd> | |
104 | +SourceForge.JP 内に設置させていただいているプロジェクトページです。こちらの Wiki 文書などに、さわらびフォントに関する、その他の情報が若干掲載されています。また、フォーラムもございますので、何かございましたらお寄せください。 | |
105 | +</dd> | |
106 | +</dl> | |
107 | +</article> | |
108 | +</div> | |
109 | +</div> | |
110 | + | |
111 | +<footer> | |
112 | +<div class="container"> | |
113 | +<a href="http://sourceforge.jp/"><img src="http://sourceforge.jp/sflogo.php?group_id=3896&type=1" width="96" height="31" alt="SourceForge.JP" /></a> | |
114 | +</div> | |
115 | +</footer> | |
116 | +</body> | |
117 | +</html> |
@@ -0,0 +1,315 @@ | ||
1 | +var CGI_URI = '../../cgi-bin/sawarabi-sampler.cgi'; | |
2 | +var CANNOT_MAKE_HTTP_OBJECT = | |
3 | + 'Cannot make an object for communication with the server.'; | |
4 | +var SESSION_TIMEOUT = | |
5 | + 'Timed out. Could not receive any response from the server in %d seconds'; | |
6 | + | |
7 | +function Session() { | |
8 | + this.request = null; | |
9 | + this.timeout = 10; | |
10 | +} | |
11 | +Session.prototype = { | |
12 | + get_request_object: function() { | |
13 | + var ret = null; | |
14 | + if (XMLHttpRequest) { | |
15 | + try { ret = new XMLHttpRequest(); } catch (err) { } | |
16 | + } else if (ActiveXObject) { | |
17 | + try { ret = new ActiveXObject('Msxml2.XMLHTTP'); } catch (err) { } | |
18 | + } | |
19 | + return ret; | |
20 | + }, | |
21 | + send_request: function(data, size) { | |
22 | + var that = this; | |
23 | + this.request = this.get_request_object(); | |
24 | + if (this.request == null) { | |
25 | + alert(CANNOT_MAKE_HTTP_OBJECT); | |
26 | + return; | |
27 | + } | |
28 | + this.request.onreadystatechange = function() { | |
29 | + var req = that.request; | |
30 | + if (req.readyState == 4 && req.status == 200) { | |
31 | + if (that.timeout_keeper) { that.timeout_keeper.abort(); } | |
32 | + that.get_response(req.responseText); | |
33 | + } | |
34 | + }; | |
35 | + var uri = CGI_URI + '?data=' + escape(data) + '&size=' + escape(size); | |
36 | + this.request.open('GET', uri, true); | |
37 | + this.request.send(null); | |
38 | + this.timeout_keeper = new Timer(this, 'on_timed_out', this.timeout * 1000); | |
39 | + }, | |
40 | + get_response: function(response_text) { | |
41 | + var is_IE = /*@ ! @*/false; // ! | |
42 | + var v = elem('canvas'); | |
43 | + var ret = JSON.parse(response_text); | |
44 | + if (ret.glyphs != 0) { | |
45 | + this.make_svg_elements(v, ret.html, is_IE); | |
46 | + } else { | |
47 | + v.innerHTML = '<br>'; | |
48 | + } | |
49 | + if (ret.glyphs == 0 || is_IE) { enable_update_button(); } | |
50 | + if (svg_is_loaded) { svg_is_loaded.clear_timeout(); } | |
51 | + svg_is_loaded = new SvgLoadedChecker(ret.glyphs); | |
52 | + }, | |
53 | + make_svg_elements: function(canvas, data, is_IE) { | |
54 | + canvas.innerHTML = ''; | |
55 | + for (var i in data) { | |
56 | + var item = data[i]; | |
57 | + var o; | |
58 | + if (item.data) { | |
59 | + o = document.createElement('object'); | |
60 | + o.setAttribute('data', item.data); | |
61 | + o.setAttribute('type', 'image/svg+xml'); | |
62 | + o.setAttribute('width', item.width); | |
63 | + o.setAttribute('height', item.height); | |
64 | + o.setAttribute('onload', item.onload); | |
65 | + } else { | |
66 | + o = document.createTextNode('?'); | |
67 | + } | |
68 | + canvas.appendChild(o); | |
69 | + } | |
70 | + if (is_IE) { | |
71 | + elem('for_sie').innerHTML = 'loading...<script defer="defer" type="text/javascript">svgtovml();</script>'; | |
72 | + } | |
73 | + }, | |
74 | + on_timed_out: function() { | |
75 | + alert(SESSION_TIMEOUT.replace(/%d/, this.timeout)); | |
76 | + if (this.request) { this.request.abort(); } | |
77 | + enable_update_button(); | |
78 | + } | |
79 | +} | |
80 | + | |
81 | +function SvgLoadedChecker(length) { | |
82 | + this.array = []; | |
83 | + this.length = length; | |
84 | + this.timeout = new Timer(this, 'on_timed_out', 10 * 1000); | |
85 | +} | |
86 | +SvgLoadedChecker.prototype = { | |
87 | + check: function(id) { | |
88 | + this.array[id] = true; | |
89 | + var b = true; | |
90 | + for (var i = 0; i < this.length; i++) { | |
91 | + if (! (b = this.array[i])) { break; } | |
92 | + } | |
93 | + if (b) { | |
94 | + var timer = setTimeout(enable_update_button, 100); | |
95 | + svg_is_loaded = null; | |
96 | + } | |
97 | + }, | |
98 | + clear_timeout: function() { | |
99 | + if (this.timeout) { this.timeout.abort(); } | |
100 | + }, | |
101 | + on_timed_out: function() { | |
102 | + enable_update_button(); | |
103 | + } | |
104 | +} | |
105 | + | |
106 | +var svg_is_loaded; | |
107 | + | |
108 | +function on_svg_loaded(id) { | |
109 | + if (svg_is_loaded) { svg_is_loaded.check(id); } | |
110 | +} | |
111 | + | |
112 | +function enable_update_button() { | |
113 | + var button = elem('update'); | |
114 | + button.disabled = false; | |
115 | + document.body.style.cursor = 'auto'; | |
116 | +} | |
117 | + | |
118 | +function draw_svg() { | |
119 | + var text = elem('input').value; | |
120 | + var us = 0; | |
121 | + for (var i = 0, data = ''; i < text.length; i++) { | |
122 | + var a = text.charCodeAt(i); | |
123 | + if (us == 0) { | |
124 | + if (a >= 0xd800 && a <= 0xdbff) us = a; | |
125 | + else c = '0000' + a.toString(16); | |
126 | + } else { | |
127 | + c = ((us - 0xd800) * 0x400 + a - 0xdc00 + 0x10000).toString(16); | |
128 | + us = 0; | |
129 | + } | |
130 | + if (us == 0) { | |
131 | + c = c.substr(c.length - 5); | |
132 | + data += c; | |
133 | + } | |
134 | + } | |
135 | + var size = elem('size').value; | |
136 | + var button = elem('update'); | |
137 | + document.body.style.cursor = 'wait'; | |
138 | + button.disabled = true; | |
139 | + new Session().send_request(data, size); | |
140 | +} | |
141 | + | |
142 | +function clear_field() { | |
143 | + var t = elem('input'); | |
144 | + t.value = ''; | |
145 | + t.focus(); | |
146 | +} | |
147 | + | |
148 | +function init(help_length) { | |
149 | + elem('script-enabled').style.display = 'block'; | |
150 | + HelpSwitch.instance = new HelpSwitch(help_length); | |
151 | + var m = MessageAnimation; | |
152 | + m.instance = new m(elem('help'), elem('next')); | |
153 | +} | |
154 | + | |
155 | +function elem(id) { | |
156 | + return document.getElementById(id); | |
157 | +} | |
158 | + | |
159 | +function HelpSwitch(help_length) { | |
160 | + this.ON_IMAGE = 'img/dolphin.png'; | |
161 | + this.OFF_IMAGE = 'img/dolphin-help.png'; | |
162 | + this.showing = false; | |
163 | + this.assistant = elem('assistant'); | |
164 | + this.balloon = elem('assistant-balloon'); | |
165 | + this.canvas = elem('help'); | |
166 | + this.button = elem('next'); | |
167 | + this.message_no = 0; | |
168 | + this.help_length = help_length; | |
169 | +} | |
170 | +HelpSwitch.instance; | |
171 | +HelpSwitch.prototype = { | |
172 | + execute: function() { | |
173 | + var b = (this.showing = ! this.showing); | |
174 | + this[b ? 'show' : 'hide'](); | |
175 | + }, | |
176 | + | |
177 | + show: function() { | |
178 | + this.assistant.src = this.ON_IMAGE; | |
179 | + var cs = this.canvas.style; | |
180 | + cs.right = '10px'; | |
181 | + cs.border = '1px solid black'; | |
182 | + cs.display = 'block'; | |
183 | + this.balloon.style.display = 'block'; | |
184 | + // TODO: write some codes for animation of the help frame here? | |
185 | + this.message_no = 0; | |
186 | + this.show_next_message(); | |
187 | + }, | |
188 | + hide: function() { | |
189 | + this.assistant.src = this.OFF_IMAGE; | |
190 | + MessageAnimation.instance.abort(); | |
191 | + this.canvas.innerHTML = ''; | |
192 | + this.canvas.style.display = 'none'; | |
193 | + this.button.style.display = 'none'; | |
194 | + this.balloon.style.display = 'none'; | |
195 | + this.message_no = 0; | |
196 | + }, | |
197 | + show_next_message: function() { | |
198 | + this.message_no++; | |
199 | + if (this.message_no == this.help_length + 1) { this.message_no = 1; } | |
200 | + id = 'help-msg-' + this.message_no; | |
201 | + MessageAnimation.instance.show_message(elem(id).innerHTML); | |
202 | + } | |
203 | +} | |
204 | + | |
205 | +function switch_help() { | |
206 | + HelpSwitch.instance.execute(); | |
207 | +} | |
208 | + | |
209 | +function change_message_next() { | |
210 | + HelpSwitch.instance.show_next_message(); | |
211 | +} | |
212 | + | |
213 | +function MessageAnimation(canvas, next_button) { | |
214 | + this.canvas = canvas; | |
215 | + this.next_button = next_button; | |
216 | + this.buffer = ''; | |
217 | + this.html = ''; | |
218 | + this.tag_stack = new TagStack(); | |
219 | + this.interval = 50; | |
220 | +} | |
221 | +MessageAnimation.instance; | |
222 | +MessageAnimation.prototype = { | |
223 | + abort: function() { | |
224 | + if (this.timer) { this.timer.abort(); } | |
225 | + var m = MessageAnimation; | |
226 | + m.instance = new m(this.canvas, this.next_button); | |
227 | + }, | |
228 | + show_message: function(html) { | |
229 | + this.html = html; | |
230 | + this.next_button.style.display = 'none'; | |
231 | + this.timer = this.timer || new Timer(this, 'show_next_char', this.interval); | |
232 | + }, | |
233 | + show_next_char: function() { | |
234 | + var index = this.buffer.length; | |
235 | + if (index == this.html.length) { | |
236 | + this.abort(); | |
237 | + this.next_button.style.display = 'block'; | |
238 | + } else { | |
239 | + var ch = this.html.substring(index, index + 1); | |
240 | + if (ch == '<') { | |
241 | + var end = this.html.indexOf('>', index); | |
242 | + var tag = this.html.substring(index, end + 1); | |
243 | + this.buffer = this.buffer + tag; | |
244 | + if (tag[1] == '/') { | |
245 | + this.tag_stack.pop(); | |
246 | + } else { | |
247 | + this.tag_stack.push_tag(tag); | |
248 | + } | |
249 | + } else if (ch == '&') { | |
250 | + var end = this.html.indexOf(';', index); | |
251 | + if (end != -1) { | |
252 | + ch = this.html.substring(index, end + 1); | |
253 | + } | |
254 | + this.buffer = this.buffer + ch; | |
255 | + } else { | |
256 | + this.buffer = this.buffer + ch; | |
257 | + } | |
258 | + var buf = this.buffer; | |
259 | + if (this.tag_stack.has_tags()) { | |
260 | + buf += this.tag_stack.get_close_tags(); | |
261 | + } | |
262 | + this.canvas.innerHTML = buf; | |
263 | + var interval = this.interval; | |
264 | + if (ch == '。') { interval *= 10; } | |
265 | + this.timer.restart(interval); | |
266 | + } | |
267 | + } | |
268 | +} | |
269 | + | |
270 | +function TagStack() { | |
271 | + this.stack = []; | |
272 | +} | |
273 | +TagStack.prototype = { | |
274 | + has_tags: function() { | |
275 | + return this.stack.length != 0; | |
276 | + }, | |
277 | + pop: function() { | |
278 | + var len = this.stack.length - 1; | |
279 | + return (len < 0) ? null : this.stack.splice(len, 1); | |
280 | + }, | |
281 | + push: function(item) { | |
282 | + this.stack.push(item); | |
283 | + }, | |
284 | + push_tag: function(tag) { | |
285 | + var idx = tag.indexOf(' '); | |
286 | + if (idx < 0) { idx = tag.length - 1; } | |
287 | + var name = tag.substring(1, idx); | |
288 | + this.push(name); | |
289 | + }, | |
290 | + get_close_tags: function() { | |
291 | + var buf = ''; | |
292 | + for (var i = this.stack.length - 1; i >= 0; i--) { | |
293 | + buf += ('</' + this.stack[i] + '>'); | |
294 | + } | |
295 | + return buf; | |
296 | + } | |
297 | +} | |
298 | + | |
299 | +function Timer(target, method, timeout) { | |
300 | + this.target = target; | |
301 | + this.method = method; | |
302 | + this.id = this.set_timer(timeout); | |
303 | +} | |
304 | +Timer.prototype = { | |
305 | + abort: function() { | |
306 | + if (this.id) { clearTimeout(this.id); } | |
307 | + }, | |
308 | + restart: function(timeout) { | |
309 | + this.id = this.set_timer(timeout); | |
310 | + }, | |
311 | + set_timer: function(timeout) { | |
312 | + var t = this.target, m = this.method; | |
313 | + return setTimeout(function() { if (t[m]) { t[m](); } }, timeout); | |
314 | + } | |
315 | +} |
@@ -0,0 +1,88 @@ | ||
1 | +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Traditional//EN"> | |
2 | +<html> | |
3 | +<head> | |
4 | +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | |
5 | +<title>さわらびフォントの試し書き</title> | |
6 | +<script defer="defer" type="text/javascript" src="./sie.js"></script> | |
7 | +<script type="text/javascript" src="./json2.js"></script> | |
8 | +<script type="text/javascript" src="./sawarabi-sampler.js"></script> | |
9 | +<link rel="stylesheet" href="./sawarabi-sampler.css" type="text/css"></link> | |
10 | +</head> | |
11 | +<body onload="init(6)"> | |
12 | +<div style="max-width: 600px; margin: auto"> | |
13 | +<div id="path"> | |
14 | +<a href="../index.html">トップページ</a> > さわらびゴシック試し書きコーナー | |
15 | +</div> | |
16 | +<h1>さわらびゴシック試し書きコーナー</h1> | |
17 | +<p>自由に<strong>さわらびゴシック</strong>の試し書きをしてみよう!</p> | |
18 | +<div id="script-enabled"> | |
19 | +<div><img src="img/dolphin-help.png" alt="assistant" id="assistant" | |
20 | + onmouseup="switch_help()"></div> | |
21 | +<div id="help"></div> | |
22 | +<div> | |
23 | +<img src="img/balloon.png" alt="" id="assistant-balloon"> | |
24 | +<img src="img/next-0.png" id="next" alt="次へ" | |
25 | + onmouseup="change_message_next()"> | |
26 | +</div> | |
27 | +<div id="canvas"><br></div> | |
28 | +<div><br></div> | |
29 | +<div> | |
30 | +<tt>テキスト:</tt><input id="input" type="text" maxlength="40"><br> | |
31 | +<tt>サ イ ズ:</tt><select id="size"> | |
32 | +<option value="min">小</option> | |
33 | +<option value="mid" selected>中</option> | |
34 | +<option value="max">大</option> | |
35 | +</select><br> | |
36 | +<div id="for_sie"></div> | |
37 | +<input type="button" value="更新" id="update" onclick="draw_svg()"> | |
38 | +<input type="button" value="クリア" onclick="clear_field()"> | |
39 | +</div> | |
40 | +</div> | |
41 | +<noscript> | |
42 | +<p> | |
43 | +……というコーナーなのですが、これは JavaScript が有効になっていないと動きません。 | |
44 | +</p> | |
45 | +<p> | |
46 | +<a href="../index.html">トップページに戻る</a> | |
47 | +</p> | |
48 | +</noscript> | |
49 | +<div><br></div> | |
50 | +<div id="hidden" style="display: none"> | |
51 | +<div id="help-msg-1"> | |
52 | +上のテキスト欄に文字を入力して「更新」ボタンを押すと、 | |
53 | +入力した文字が<strong>さわらびゴシック</strong>で表示されます。 | |
54 | +</div> | |
55 | +<div id="help-msg-2"> | |
56 | +「サイズ」コンボボックスの値を変更すると、文字のサイズを変えることもできます。 | |
57 | +</div> | |
58 | +<div id="help-msg-3"> | |
59 | +なお、<strong>さわらびゴシック</strong>にまだ収録されていない文字は、 | |
60 | +<a href="http://mplus-fonts.sourceforge.jp" target="_blank">M+ FONTS</a> でグレー表示されるようになっています。 | |
61 | +M+ FONTS にもない文字は「?」と表示されます。 | |
62 | +</div> | |
63 | +<div id="help-msg-4"> | |
64 | +また、文字の表示はフォントそのものを利用して行っているわけではありません。 | |
65 | +各文字を <a href="http://ja.wikipedia.org/wiki/SVG" target="_blank">SVG</a> に変換して表示しています。 | |
66 | +文字間隔や細かい見え方など、実際と少し違っていることがあります。 | |
67 | +</div> | |
68 | +<div id="help-msg-5"> | |
69 | +Internet Explorer はまだ未対応の扱いですが、一応動作不能ということもないかもしれません。 | |
70 | +とはいえ、表示結果は仮のものだと思ってください。 | |
71 | +<a href="http://mozilla.jp/firefox/" target="_blank">Mozilla Firefox</a> や | |
72 | +<a href="http://www.google.com/chrome/?hl=ja" target="_blank">Google | |
73 | +Chrome</a> などでご覧いただいたほうが綺麗です。 | |
74 | +</div> | |
75 | +<div id="help-msg-6"> | |
76 | +ちなみに、このアプリケーションで利用させていただいている | |
77 | +<a href="http://mplus-fonts.sourceforge.jp" target="_blank">M+ FONTS</a> | |
78 | +は、mplus-TESTFLIGHT-025 の mplus-1p-medium.ttf です。 | |
79 | +それを <a href="http://ja.wikipedia.org/wiki/SVG" target="_blank">SVG</a> | |
80 | +に変換したものを表示しています。 | |
81 | +</div> | |
82 | +</div> | |
83 | +<p> | |
84 | +<a href="http://sourceforge.jp/"><img src="http://sourceforge.jp/sflogo.php?group_id=3896&type=1" width="96" height="31" border="0" alt="SourceForge.JP"></a> | |
85 | +</p> | |
86 | +</div> | |
87 | +</body> | |
88 | +</html> |