ajax-cat 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -0,0 +1,72 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "ajax-cat"
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ondrej Odchazel"]
12
+ s.date = "2012-04-26"
13
+ s.description = "computer-aided translation backed by machine translation"
14
+ s.email = "odchazel@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "ajax-cat.gemspec",
28
+ "lib/.DS_Store",
29
+ "lib/ajax-cat.rb",
30
+ "lib/public/AjaxCatList.coffee",
31
+ "lib/public/AjaxCatTranslation.coffee",
32
+ "lib/public/Suggestions.coffee",
33
+ "lib/public/TranslationTable.coffee",
34
+ "lib/public/Utils.coffee",
35
+ "lib/public/ajax-cat.coffee",
36
+ "lib/public/ajax-cat.js",
37
+ "lib/public/bootstrap.css",
38
+ "lib/public/bootstrap.js",
39
+ "lib/public/index.html",
40
+ "lib/public/index.js",
41
+ "lib/public/jquery.js",
42
+ "lib/public/style.css",
43
+ "lib/public/translation.html",
44
+ "lib/public/translation.js",
45
+ "test/helper.rb",
46
+ "test/test_ajax-cat.rb"
47
+ ]
48
+ s.homepage = "http://github.com/hypertornado/ajax-cat"
49
+ s.licenses = ["MIT"]
50
+ s.require_paths = ["lib"]
51
+ s.rubygems_version = "1.8.17"
52
+ s.summary = "computer-aided translation backed by machine translation"
53
+
54
+ if s.respond_to? :specification_version then
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
59
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
60
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
61
+ else
62
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
63
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
64
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
65
+ end
66
+ else
67
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
68
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
69
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
70
+ end
71
+ end
72
+
Binary file
@@ -0,0 +1,5 @@
1
+ require 'sinatra.rb'
2
+
3
+ get '/' do
4
+ redirect '/index.html'
5
+ end
@@ -0,0 +1,63 @@
1
+ class AjaxCatList
2
+
3
+ constructor: ->
4
+ $('#new-translation-modal').hide()
5
+ $('#new-translation').on('click',@new_translation)
6
+ $('#create-new-translation').on('click',@create_new_translation)
7
+ @show_translations()
8
+ $(".example").click(
9
+ (event) =>
10
+ text = $(event.currentTarget).data("text")
11
+ $('#new-translation-text').val(text)
12
+ return false
13
+ )
14
+
15
+ new_translation: =>
16
+ $('#new-translation-name').val('Name')
17
+ $('#new-translation-text').val('')
18
+ $('#new-translation-modal').modal('show')
19
+ $('#new-translation-text').focus()
20
+
21
+ show_translations: =>
22
+ $("#translation-list").html('')
23
+ return unless localStorage['ac-data']
24
+ ids = JSON.parse(localStorage['ac-data'])
25
+ for i in ids
26
+ doc = JSON.parse(localStorage[i])
27
+ $("#translation-list").append("<tr><td width='100%'><a href='/translation.html##{doc.id}'>#{doc.name}</a></td><td><button data-id='#{doc.id}' class='btn btn-danger btn-mini delete-button'>delete</button></td></tr>")
28
+ $(".delete-button").click(
29
+ (event) =>
30
+ id = $(event.currentTarget).data("id")
31
+ if confirm("Delete this translation?")
32
+ @delete_document(id)
33
+ @show_translations()
34
+ )
35
+
36
+ delete_document: (id) =>
37
+ return unless localStorage['ac-data']
38
+ ids = JSON.parse(localStorage['ac-data'])
39
+ new_ids = []
40
+ for i in ids
41
+ new_ids.push(i) unless i == id
42
+ localStorage.removeItem(id)
43
+ localStorage.setItem('ac-data', JSON.stringify(new_ids))
44
+
45
+
46
+ create_new_translation: =>
47
+ text = $('#new-translation-text').val()
48
+ if localStorage['ac-data']
49
+ docs = JSON.parse(localStorage['ac-data'])
50
+ else
51
+ docs = []
52
+ doc = {}
53
+ doc.id = Utils.random_string()
54
+ doc['name'] = $('#new-translation-name').val()
55
+ doc['pair'] = $('#new-translation-pair').val()
56
+ doc.source = Utils.split_source(text)
57
+ doc.target = new Array(doc.source.length)
58
+ docs.push(doc.id)
59
+ localStorage.setItem('ac-data', JSON.stringify(docs))
60
+ localStorage.setItem(doc.id, JSON.stringify(doc))
61
+ $('#new-translation-modal').modal('hide')
62
+ @show_translations()
63
+
@@ -0,0 +1,147 @@
1
+ class AjaxCatTranslation
2
+
3
+ cur_position: false
4
+ pair: "en-cs"
5
+ #host: "10.10.24.118"
6
+ host: "localhost"
7
+
8
+ constructor: ->
9
+ @host = window.location.hostname
10
+ @suggestions = new Suggestions(@)
11
+ $('#translation-preview-modal').hide()
12
+ $('#myTab').tab('show')
13
+ hash = window.location.hash.substr(1)
14
+ data = localStorage.getItem(hash)
15
+ unless data
16
+ alert "No such document."
17
+ return
18
+ @doc = JSON.parse(data)
19
+ @pair = @doc.pair
20
+ $('h1').html("#{@doc.name} <small>#{@pair}</small>")
21
+ $("title").html("#{@doc.name} - AJAX-CAT")
22
+ i = 0
23
+ for s in @doc.source
24
+ $("#source-top").append("<span class='ac-element ac-source' data-position='#{i}'>#{s}</span>")
25
+ $("#source-bottom").append("<span class='ac-element ac-source' data-position='#{i}'>#{s}</span>")
26
+ i += 1
27
+ i = 0
28
+ for t in @doc.target
29
+ t = "" unless t
30
+ $("#target-top").append("<span class='ac-element ac-target' data-position='#{i}'>#{t}</span>")
31
+ $("#target-bottom").append("<span class='ac-element ac-target' data-position='#{i}'>#{t}</span>")
32
+ i += 1
33
+ $('.ac-element').click(
34
+ (event) =>
35
+ position = $(event.target).data('position')
36
+ @change_position(position)
37
+ )
38
+ @length = $("#source-top").children().length
39
+ @change_position(0)
40
+ @bind_events()
41
+ @resize()
42
+
43
+ resize: =>
44
+ width = $(window).width()
45
+ $("#translation-table-container").width(width - 60)
46
+
47
+ bind_events: =>
48
+ $("#target-sentence").on('keydown'
49
+ (event) =>
50
+ switch event.which
51
+ when 13 #enter
52
+ @suggestions.take_suggestion()
53
+ when 32 #space
54
+ text = $("#target-sentence").val()
55
+ text = Utils.trim text
56
+ if text.length > 0
57
+ ar = text.split(/[ ]+/)
58
+ word = ar[(ar.length - 1)]
59
+ @table.mark_words(word)
60
+ when 33 #pgup
61
+ @change_position(@cur_position - 1) if @cur_position > 0
62
+ return false
63
+ when 34 #pgdown
64
+ @change_position(@cur_position + 1) if (@cur_position + 1) < @length
65
+ return false
66
+ when 38 #up
67
+ @suggestions.up()
68
+ when 40 #down
69
+ @suggestions.down()
70
+ else
71
+ $(window).trigger('loadSuggestions')
72
+
73
+ )
74
+
75
+ $("#preview").click(
76
+ =>
77
+ @save_target()
78
+ @show_preview()
79
+ return false
80
+ )
81
+
82
+ $("#save").click(
83
+ =>
84
+ @save_target()
85
+ alert "Translation was saved into your browser."
86
+ )
87
+
88
+ show_preview: =>
89
+ $("#source").text(@doc.source.join(''))
90
+ $("#target").text(@doc.target.join(''))
91
+ $('#translation-preview-modal').modal('show')
92
+
93
+ save_target: =>
94
+ $("#target-top .ac-target[data-position=#{@cur_position}]").text($("#target-sentence").val())
95
+ $("#target-bottom .ac-target[data-position=#{@cur_position}]").text($("#target-sentence").val())
96
+
97
+ tar = []
98
+ for el in $("#target-top .ac-target")
99
+ tar.push($(el).text())
100
+ @doc.target = tar
101
+ localStorage.setItem(@doc.id, JSON.stringify(@doc))
102
+
103
+
104
+ load_translation_table: (sentence) =>
105
+ sentence = Utils.tokenize(sentence)
106
+ if sentence.match(/^[\ \t]*$/)
107
+ $("#translation-table-container").html("")
108
+ @suggestions.clear()
109
+ return
110
+ $("#translation-table-container").text("")
111
+ $.ajax "http://"+@host+":8888/table"
112
+ data:
113
+ pair: @pair
114
+ q: sentence
115
+ success: (data) =>
116
+ @table = new TranslationTable(@, data)
117
+ $("#translation-table-container").html(@table.get_table())
118
+ $(window).trigger('loadSuggestions')
119
+ error: =>
120
+ #alert "failed to load translation table"
121
+
122
+ change_position: (position) =>
123
+ @save_target() if @cur_position != false
124
+ $("#source-top").children().slice(0,position).show()
125
+ $("#source-top").children().slice(position,@length).hide()
126
+ $("#source-bottom").children().slice(0,position + 1).hide()
127
+ $("#source-bottom").children().slice(position + 1,@length).show()
128
+
129
+ $("#target-top").children().slice(0,position).show()
130
+ $("#target-top").children().slice(position,@length).hide()
131
+ $("#target-bottom").children().slice(0,position + 1).hide()
132
+ $("#target-bottom").children().slice(position + 1,@length).show()
133
+
134
+ $("#source-sentence").text($("#source-top .ac-source[data-position=#{position}]").text())
135
+ $("#target-sentence").val($("#target-top .ac-target[data-position=#{position}]").text())
136
+ @cur_position = position
137
+ $("#target-sentence").focus()
138
+ @load_translation_table($("#source-top .ac-source[data-position=#{position}]").text())
139
+
140
+ add_words: (words, change_covered = false) =>
141
+ text = $("#target-sentence").val()
142
+ text = Utils.trim(text)
143
+ words = Utils.trim(words)
144
+ text = Utils.trim(text)
145
+ text += " #{words} "
146
+ $("#target-sentence").val(text)
147
+ $("#target-sentence").click()
@@ -0,0 +1,87 @@
1
+ class Suggestions
2
+
3
+ constructor: (@translation, limit = 5) ->
4
+ i = 0
5
+ while i < limit
6
+ sug = $("<div>"
7
+ class: 'ac-suggestion'
8
+ 'data-suggestion-position': i
9
+ click: =>
10
+ @take_suggestion()
11
+ mouseover: (event) =>
12
+ target = $(event.currentTarget)
13
+ if target.hasClass('suggestion-enabled')
14
+ @set_position(target.data('suggestion-position'))
15
+ )
16
+ $("#suggestions-container").append(sug)
17
+ i += 1
18
+
19
+ $(window).bind('loadSuggestions'
20
+ =>
21
+ @load_suggestions()
22
+ $("#target-sentence").focus()
23
+ )
24
+
25
+ clear: =>
26
+ $(".ac-suggestion").text("")
27
+ $(".ac-suggestion").removeClass('suggestion-enabled')
28
+ $(".ac-suggestion").removeClass('suggestion-active')
29
+
30
+ load_suggestions: =>
31
+ @clear()
32
+ sentence = $("#source-sentence").text()
33
+ sentence = Utils.tokenize(sentence)
34
+ translated = Utils.tokenize($("#source-target").text())
35
+ covered = @translation.table.covered_vector()
36
+ $.ajax "http://"+@translation.host+":8888/suggestion"
37
+ data:
38
+ pair: @translation.pair
39
+ q: Utils.tokenize(sentence)
40
+ covered: covered
41
+ translated: translated
42
+ success: (data) =>
43
+ data = JSON.parse(data)
44
+ @process_suggestions(data)
45
+ error: =>
46
+ #alert "failed to load suggestions"
47
+
48
+ take_suggestion: =>
49
+ return if (@get_position() == false)
50
+ text = $(".suggestion-active span").text()
51
+ @translation.add_words(text)
52
+ @translation.table.mark_words(text)
53
+
54
+
55
+ process_suggestions: (data) =>
56
+ i = 0
57
+ for suggestion in data.suggestions
58
+ translation = $("#target-sentence").val()
59
+ el = $(".ac-suggestion").slice(i, (i + 1))
60
+ el.html("#{translation} <span>#{suggestion}</span>")
61
+ el.addClass('suggestion-enabled')
62
+ i += 1
63
+
64
+ positions: =>
65
+ return $(".suggestion-enabled").length
66
+
67
+ get_position: =>
68
+ el = $(".suggestion-active")
69
+ return false unless el.length
70
+ return el.data('suggestion-position')
71
+
72
+ set_position: (position) =>
73
+ $(".suggestion-active").removeClass('suggestion-active')
74
+ $(".suggestion-enabled[data-suggestion-position=#{position}]").addClass('suggestion-active')
75
+
76
+ up: =>
77
+ position = @get_position()
78
+ return if position == false
79
+ @set_position(position - 1)
80
+
81
+ down: =>
82
+ position = @get_position()
83
+ if position == false
84
+ @set_position(0)
85
+ return
86
+ if (position + 1) < @positions()
87
+ @set_position(position + 1)
@@ -0,0 +1,98 @@
1
+ class TranslationTable
2
+
3
+ constructor: (@translation, data) ->
4
+ @data = JSON.parse(data)
5
+
6
+ get_table: =>
7
+ ret = $("<table>"
8
+ class: 'translation-table'
9
+ )
10
+ ret.append(@get_header())
11
+ for row in @data.target
12
+ ret.append(@get_row(row))
13
+ return ret
14
+
15
+ get_header: =>
16
+ ret = $("<tr>")
17
+ i = 0
18
+ for word in @data.source
19
+ src = $("<th>"
20
+ class: 'ac-source'
21
+ html: word
22
+ "data-position": i
23
+ click: (event) =>
24
+ position = parseInt($(event.currentTarget).data('position'))
25
+ if @position_marked(position)
26
+ @unmark_position(position)
27
+ else
28
+ @mark_position(position)
29
+ $(window).trigger('loadSuggestions')
30
+ )
31
+ ret.append(src)
32
+ i += 1
33
+ return ret
34
+
35
+ get_row: (row) =>
36
+ ret = $("<tr>")
37
+ i = 0
38
+ for word in row
39
+ len = parseInt(word.s)
40
+ if word.empty
41
+ ret.append("<td colspan='#{word.s}' class='ac-empty'></td>")
42
+ else
43
+ cell = $("<td colspan='#{word.s}' class='ac-word'></td>")
44
+ content = $("<div>"
45
+ 'data-position-from': i
46
+ 'data-position-to': (i + len - 1)
47
+ html: word.t
48
+ click: (event) =>
49
+ i = parseInt($(event.currentTarget).data('position-from'))
50
+ while i <= parseInt($(event.currentTarget).data('position-to'))
51
+ @mark_position(i)
52
+ i += 1
53
+ @translation.add_words($(event.currentTarget).text())
54
+ $(window).trigger('loadSuggestions')
55
+ )
56
+ cell.append(content)
57
+ ret.append(cell)
58
+ i += len
59
+ return ret
60
+
61
+ position_marked: (position) =>
62
+ return true if $("th.ac-source").slice(position, (position + 1)).hasClass('ac-selected')
63
+ return false
64
+
65
+ mark_words: (words) =>
66
+ words = "#{words} "
67
+ for el in $(".ac-word div")
68
+ el_text = Utils.trim $(el).text()
69
+ el_text = "#{el_text} "
70
+ if ((words.indexOf(el_text) == 0) and (words.length >= el_text.length))
71
+ #console.log "#{words}, #{el_text}, #{words.length} , #{el_text.length}"
72
+ @mark_interval($(el).data('position-from'), $(el).data('position-to'))
73
+ $(window).trigger('loadSuggestions')
74
+ words = words.substr(el_text.length)
75
+ words = Utils.trim(words)
76
+ words = "#{words} "
77
+ return unless words.length > 0
78
+
79
+ mark_interval: (from, to) =>
80
+ i = from
81
+ while i <= to
82
+ @mark_position(i)
83
+ i += 1
84
+
85
+ mark_position: (position) =>
86
+ $("th.ac-source").slice(position, (position + 1)).addClass('ac-selected')
87
+
88
+ unmark_position: (position) =>
89
+ $("th.ac-source").slice(position, (position + 1)).removeClass('ac-selected')
90
+
91
+ covered_vector: =>
92
+ ret = ""
93
+ for el in $("th.ac-source")
94
+ if $(el).hasClass('ac-selected')
95
+ ret += "1"
96
+ else
97
+ ret += "0"
98
+ return ret