• R/O
  • SSH
  • HTTPS

sawarabi-fonts: コミット


コミットメタ情報

リビジョン155 (tree)
日時2015-01-25 21:27:11
作者mshio

ログメッセージ

update graphs of a pc top page.

変更サマリ

差分

--- trunk/html/coffee/lang.coffee (nonexistent)
+++ trunk/html/coffee/lang.coffee (revision 155)
@@ -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()
--- trunk/html/coffee/doc-header/ja.coffee (nonexistent)
+++ trunk/html/coffee/doc-header/ja.coffee (revision 155)
@@ -0,0 +1,10 @@
1+@dictionary =
2+ title: '漢字収録率'
3+ fonts:
4+ gothic: '(さわらびゴシック)'
5+ mincho: '(さわらび明朝)'
6+ kyoikuKanji: '教育漢字'
7+ level1st: '第一水準漢字'
8+ level2nd: '第二水準漢字'
9+ level3rd: '第三水準漢字'
10+ level4th: '第四水準漢字'
--- trunk/html/coffee/doc-header/en.coffee (nonexistent)
+++ trunk/html/coffee/doc-header/en.coffee (revision 155)
@@ -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'
--- trunk/html/coffee/mobile.coffee (nonexistent)
+++ trunk/html/coffee/mobile.coffee (revision 155)
@@ -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}"
--- trunk/html/coffee/doc-header.coffee (nonexistent)
+++ trunk/html/coffee/doc-header.coffee (revision 155)
@@ -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')
--- trunk/html/css/style.css (revision 154)
+++ trunk/html/css/style.css (revision 155)
@@ -54,15 +54,16 @@
5454 div#docs-header .container .buttons-container .inner-container {
5555 position: relative;
5656 left: 600px;
57- top: 260px;
57+ top: 15px;
5858 }
5959 div#docs-header .container .buttons-container .button {
60- padding: .25em .5em;
60+ padding: .25em .55em;
6161 background-color: #fff;
62+ border-radius: 0.55em;
6263 float: left;
6364 font-family: Arial;
6465 font-size: 10pt;
65- margin: 1px 1px;
66+ margin: 1px 2px;
6667 cursor: pointer;
6768 }
6869 div#docs-header .container .buttons-container .pressed {
--- trunk/html/index.html (revision 154)
+++ trunk/html/index.html (revision 155)
@@ -7,6 +7,7 @@
77 <script src="js/mobile.js" type="text/javascript"></script>
88 <script src="js/jquery-2.1.0.min.js" type="text/javascript"></script>
99 <script src="js/lang.js" type="text/javascript"></script>
10+<script src="js/doc-header/ja.js" type="text/javascript"></script>
1011 <script src="js/doc-header.js" type="text/javascript"></script>
1112 </head>
1213 <body>
@@ -27,7 +28,7 @@
2728 <div id="docs-header">
2829 <div class="container">
2930 <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>
3132 </div>
3233 </div>
3334
@@ -60,7 +61,7 @@
6061 </p>
6162 <img src="img/sample-gothic.png" alt="書体見本(ゴシック)" /><br />
6263 <p>
63- さわらび明朝(ver.20140415)の書体見本です。
64+ さわらび明朝(ver.20140815)の書体見本です。
6465 </p>
6566 <img src="img/sample-mincho.png" alt="書体見本(明朝)" /><br />
6667 </article>
@@ -108,7 +109,9 @@
108109
109110 <footer>
110111 <div class="container">
112+<!--
111113 <a href="http://sourceforge.jp/"><img src="http://sourceforge.jp/sflogo.php?group_id=3896&amp;type=1" width="96" height="31" alt="SourceForge.JP" /></a>
114+-->
112115 </div>
113116 </footer>
114117 </body>
--- trunk/html/js/mobile.js (revision 154)
+++ trunk/html/js/mobile.js (revision 155)
@@ -1,7 +1,22 @@
1+// Generated by CoffeeScript 1.4.0
12 (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);
--- trunk/html/js/doc-header.js (revision 154)
+++ trunk/html/js/doc-header.js (revision 155)
@@ -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; };
366
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+ };
6820
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() {
13122
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+ }
21132
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+ };
23339
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+ }
240120 }
241121
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({
248394 type: 'GET',
249- url: url,
250- data: "type=" + fontTypes[n],
395+ url: '/cgi-bin/num-of-kanjis.cgi',
396+ data: "type=" + type,
251397 dataType: 'json',
252398 success: function(data, dataType) {
253- result[fontTypes[n]] = data;
399+ KanjiInfo[type] = data;
400+ return func();
254401 },
255402 error: function(request, textStatus, errorThrown) {
256- alert(textStatus);
257- },
258- async: false,
403+ return alert(textStatus);
404+ }
259405 });
260- }
261- return result;
406+ };
407+ return exec('gothic', function() {
408+ return exec('mincho', callback);
409+ });
262410 }
411+ };
263412
264-
413+ makeGraphPage = function(screen, pageName) {
265414 (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+ };
268488
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;
294504 })();
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);
--- trunk/html/js/doc-header/en.js (nonexistent)
+++ trunk/html/js/doc-header/en.js (revision 155)
@@ -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);
--- trunk/html/js/doc-header/ja.js (nonexistent)
+++ trunk/html/js/doc-header/ja.js (revision 155)
@@ -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);
--- trunk/html/js/lang.js (revision 154)
+++ trunk/html/js/lang.js (revision 155)
@@ -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 = {
36 en: "English",
4- ja: "日本語",
5-};
7+ ja: "日本語"
8+ };
69
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+ });
1932 }
20- }
21- $('div#lang').append(menu);
2233
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();
25105 });
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);
--- trunk/html/en/index.html (revision 154)
+++ trunk/html/en/index.html (revision 155)
@@ -7,6 +7,7 @@
77 <script src="../js/mobile.js" type="text/javascript"></script>
88 <script src="../js/jquery-2.1.0.min.js" type="text/javascript"></script>
99 <script src="../js/lang.js" type="text/javascript"></script>
10+<script src="../js/doc-header/en.js" type="text/javascript"></script>
1011 <script src="../js/doc-header.js" type="text/javascript"></script>
1112 </head>
1213 <body>
@@ -63,7 +64,7 @@
6364 </p>
6465 <img src="../img/sample-gothic.png" alt="Sample (Gothic)" /><br />
6566 <p>
66-Sawarabi Mincho (ver.20140415).
67+Sawarabi Mincho (ver.20140815).
6768 </p>
6869 <img src="../img/sample-mincho.png" alt="Sample (Mincho)" /><br />
6970 </article>
--- trunk/html/sampler/index.html (nonexistent)
+++ trunk/html/sampler/index.html (revision 155)
@@ -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&amp;type=1" width="96" height="31" alt="SourceForge.JP" /></a>
114+</div>
115+</footer>
116+</body>
117+</html>
--- trunk/html/sampler/js/sawarabi-sampler.js (nonexistent)
+++ trunk/html/sampler/js/sawarabi-sampler.js (revision 155)
@@ -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+}
--- trunk/html/sampler/sawarabi-sampler.html (nonexistent)
+++ trunk/html/sampler/sawarabi-sampler.html (revision 155)
@@ -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> &gt; さわらびゴシック試し書きコーナー
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>
旧リポジトリブラウザで表示