ajax_canvas_field 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b6473159e106c84c7d22f88082f09673881e75ba
4
+ data.tar.gz: 19c2ded0fa28248bad6827bd640ad08d3d1b45ba
5
+ SHA512:
6
+ metadata.gz: 7a1804d70527ba1bab761106cbcf05b240d70909bba0b8a181b40c64ec39d30e4f131c86039ea899e019facac4fac3460f476c64cc51636d0ac06f722f250f78
7
+ data.tar.gz: 8a1b0af731180d5698822a7ed7321a8ed92fefa640ecafffd8abf1508dde7b3115355e5592f6a64dadcc2c64f0c36b357cc2af016fa0580b4a8f10f409688b30
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ajax_canvas_field.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # AjaxCanvasField
2
+
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ ```ruby
9
+ gem 'ajax_canvas_field'
10
+ ```
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install ajax_canvas_field
19
+
20
+ ## Usage
21
+ There are three tasks you can execute.
22
+
23
+ ### ATTENTION: Use at your own risk! Back your shit up, before using this!
24
+ Each will ask you for the file
25
+ If this gem is installed inside a Rails-Application you just have to written
26
+ e.g.:
27
+ ```
28
+ 'en' -> for en.yml
29
+ 'de' -> for de.yml
30
+ ...
31
+ ```
32
+ One will be the master-file (this one will not be changed)
33
+ and
34
+ One will be the slave-file (this one will be changed)
35
+
36
+ #### Script 1: Interactive
37
+ ```bash
38
+ rake lit:interactive
39
+ ```
40
+ This script will ask you for the missing value.
41
+ It will find every difference and will ask you to fill every hole... yeah.
42
+ After everything is filled out it will merge the data back into your File.
43
+
44
+ #### Script 2: Recent
45
+ ```bash
46
+ rake lit:recent
47
+ ```
48
+ REQUIRED: Connection to Git
49
+ This script will ask you for the missing value.
50
+ It will find everything you changed in your master-file since you last pushed commit.
51
+ After everything is filled out it will merge the data back into your File.
52
+
53
+ #### Script 3: Cleanup (Deletes something!)
54
+ ```bash
55
+ rake lit:cleanup
56
+ ```
57
+ This script will find every key/value inside your slave-file that isn´t present in your master-file.
58
+ And it will be deleted!!!!
59
+
60
+ #### Sometimes the Rake tasks aren't working
61
+ In this case you can use the Rails-Console and the Class -LostInTranslation-.
62
+
63
+ ```bash
64
+ rails c
65
+ ```
66
+ ```
67
+ LostInTranslation.interactive
68
+ or
69
+ LostInTranslation.recent
70
+ or
71
+ LostInTranslation.cleanup
72
+ ```
73
+
74
+ #### Yet to come
75
+ I am planning on an integration of Translation APIs.
76
+
77
+ ## Contributing
78
+
79
+ Bug reports and pull requests are welcome on GitHub at https://github.com/datyv/lost_in_translation. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
80
+
81
+
82
+ ## License
83
+
84
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'ajax_canvas_field/rails/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'ajax_canvas_field'
9
+ spec.version = AjaxCanvasField::Rails::VERSION
10
+ spec.authors = ['datyv']
11
+ spec.email = ['yvesgoizet@gmail.com']
12
+
13
+ spec.summary = 'HTML5 CanvasField Support'
14
+ spec.description = 'Add a CanvasField to point out errors in three different colors'
15
+ spec.homepage = 'https://github.com/Datyv/ajax_canvas_field'
16
+ spec.license = 'MIT'
17
+
18
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
20
+ if spec.respond_to?(:metadata)
21
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
22
+ else
23
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
24
+ end
25
+
26
+ spec.files = `git ls-files -z`.split("\x0")
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = %w[app lib]
29
+
30
+ spec.add_development_dependency 'bundler', '~> 1.15'
31
+ spec.add_development_dependency 'rake', '~> 10.0'
32
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,192 @@
1
+ document.addEventListener('DOMContentLoaded', function(){
2
+ var canvas = document.getElementById('canvas_field');
3
+ var data_fields = document.getElementsByClassName('canvas_data_field');
4
+ if (canvas) {
5
+ if (data_fields.length == 0) {
6
+ console.log('No Data Field found. Please add canvas_data_field in your code!');
7
+ document.getElementsByClassName('canvas_table')[0].style.display = 'none';
8
+ canvas.style.display = 'none';
9
+ } else {
10
+ canvas.width = canvas.dataset.width;
11
+ canvas.height = canvas.dataset.height;
12
+ var context = canvas.getContext('2d'),
13
+ url = canvas.dataset.url,
14
+ param = canvas.dataset.strongParam,
15
+ token = canvas.dataset.token,
16
+ points = [];
17
+
18
+ function refreshAll(e) {
19
+ points = [];
20
+ initCircles();
21
+ }
22
+
23
+ function initCircles() {
24
+ var data_field = document.getElementsByClassName('active canvas_data_field')[0].dataset;
25
+ var initialData = JSON.parse(data_field.initialData);
26
+ for (i = 0; i < initialData.length; i++) {
27
+ var point = buildCircle(initialData[i][1], initialData[i][2], initialData[i][3]);
28
+ point.database_id = initialData[i][0];
29
+ points.push(point);
30
+ }
31
+ redrawAllCircles();
32
+ }
33
+
34
+ function isPixelCollision(e) {
35
+ e.preventDefault();
36
+
37
+ if (e.type == "contextmenu") return;
38
+
39
+ var r = canvas.getBoundingClientRect(),
40
+ x = e.clientX - r.left,
41
+ y = e.clientY - r.top,
42
+ removed = false,
43
+ i;
44
+
45
+ for (i = points.length - 1; i >= 0; --i) {
46
+ if (context.isPointInPath(points[i], x, y, 'nonzero')) {
47
+ deleteAjax(i);
48
+ removed = true;
49
+ }
50
+ }
51
+
52
+ if (removed == false) {
53
+ createAjax(x, y, e);
54
+ }
55
+ }
56
+
57
+ function buildCircle(x, y, e) {
58
+ var c = new Path2D(),
59
+ offset = 3.5;
60
+
61
+ c.arc(x - offset, y - offset, 7, 0, Math.PI * 2);
62
+ c.color = (typeof e === 'string') ? e : chooseColor(e)
63
+ c.x = x;
64
+ c.y = y;
65
+ return c;
66
+ }
67
+
68
+ function chooseColor(e) {
69
+ if (e === null) return '#ff0000';
70
+ switch (e.which) {
71
+ case 1:
72
+ return canvas.dataset.leftColor;
73
+ case 2:
74
+ return canvas.dataset.middleColor;
75
+ case 3:
76
+ return canvas.dataset.rightColor;
77
+ }
78
+ }
79
+
80
+ function chooseButton(e) {
81
+ if (e === null) return null;
82
+ switch (e.which) {
83
+ case 1:
84
+ return 'left';
85
+ case 2:
86
+ return 'middle';
87
+ case 3:
88
+ return 'right';
89
+ }
90
+ }
91
+
92
+ function deleteAjax(i) {
93
+ var id = points[i].database_id;
94
+ $.ajax({
95
+ type: 'DELETE',
96
+ url: url + '/' + id,
97
+ headers: {
98
+ 'Authorization': 'Token token=' + token
99
+ },
100
+ dataType: "json",
101
+ success: function(data) {
102
+ removeCircle(i, data);
103
+ },
104
+ error: function(data) {
105
+ alert('No connection to Server');
106
+ }
107
+ });
108
+ }
109
+
110
+ function removeCircle(i, data) {
111
+ points.splice(i, 1);
112
+ redrawAllCircles();
113
+ }
114
+
115
+ function createAjax(x, y, e) {
116
+ post_data = collectPostData(x, y, e);
117
+ $.ajax({
118
+ type: 'POST',
119
+ url: url,
120
+ headers: {
121
+ 'Authorization': 'Token token=' + token
122
+ },
123
+ data: post_data,
124
+ dataType: "json",
125
+ success: function(data) {
126
+ addCircle(x, y, data, e);
127
+ },
128
+ error: function(data) {
129
+ alert('No connection to Server');
130
+ }
131
+ });
132
+ }
133
+
134
+ function collectPostData(x, y, e) {
135
+ var params = {};
136
+ var data_field = document.getElementsByClassName('active canvas_data_field')[0].dataset;
137
+ var additionalData = JSON.parse(data_field.additionalData);
138
+ params[param] = {
139
+ x_value: x,
140
+ y_value: y,
141
+ button: chooseButton(e)
142
+ };
143
+ for (var attrname in additionalData) {
144
+ params[param][attrname] = additionalData[attrname];
145
+ }
146
+ return params;
147
+ }
148
+
149
+ function addCircle(x, y, data, e) {
150
+ new_point = buildCircle(x, y, e);
151
+ new_point['database_id'] = data.id;
152
+ points.push(new_point);
153
+ redrawAllCircles();
154
+ }
155
+
156
+ function redrawAllCircles() {
157
+ var tmpData = [];
158
+ context.clearRect(0, 0, canvas.width, canvas.height);
159
+ for (i = 0; i < points.length; i++) {
160
+ context.fillStyle = points[i].color;
161
+ context.fill(points[i], 'nonzero');
162
+ context.stroke(points[i], 'nonzero');
163
+
164
+ tmpData.push([points[i].database_id, points[i].x, points[i].y, points[i].color]);
165
+ }
166
+ document.getElementsByClassName('active canvas_data_field')[0].dataset.initialData = JSON.stringify(tmpData);
167
+ }
168
+
169
+ canvas.addEventListener('click', isPixelCollision, false);
170
+ canvas.addEventListener('auxclick', isPixelCollision, false);
171
+ canvas.addEventListener('contextmenu', isPixelCollision, false);
172
+ initCircles();
173
+
174
+ var tableRows = document.getElementsByClassName('request_row');
175
+ var markRequestRow = function() {
176
+ for (var i = 0; i < tableRows.length; i++) {
177
+ tableRows[i].classList.remove('active');
178
+ }
179
+ for (var i = 0; i < data_fields.length; i++) {
180
+ data_fields[i].classList.remove('active');
181
+ }
182
+ this.classList.add('active');
183
+ this.getElementsByClassName('canvas_data_field')[0].classList.add('active');
184
+ refreshAll();
185
+ };
186
+
187
+ for (var i = 0; i < tableRows.length; i++) {
188
+ tableRows[i].addEventListener('click', markRequestRow, false);
189
+ }
190
+ }
191
+ }
192
+ }, false);
@@ -0,0 +1,42 @@
1
+ var canvases = document.getElementsByClassName('canvas_field');
2
+ if (canvases) {
3
+ for (o = 0; o < canvases.length; o++) {
4
+ var canvas = canvases[o];
5
+ canvas.width = canvas.dataset.width;
6
+ canvas.height = canvas.dataset.height;
7
+ var context = canvas.getContext('2d');
8
+ var points = [];
9
+
10
+ function initCircles() {
11
+ var initialData = JSON.parse(canvas.dataset.initialData);
12
+ for (i = 0; i < initialData.length; i++) {
13
+ var point = buildCircle(initialData[i][1], initialData[i][2], initialData[i][3]);
14
+ point.database_id = initialData[i][0];
15
+ points.push(point);
16
+ }
17
+ redrawAllCircles();
18
+ }
19
+
20
+ function buildCircle(x, y, e) {
21
+ var c = new Path2D(),
22
+ offset = 3.5;
23
+
24
+ c.arc(x - offset, y - offset, 7, 0, Math.PI * 2);
25
+ c.color = (typeof e === 'string') ? e : '#ff0000'
26
+ c.x = x;
27
+ c.y = y;
28
+ return c;
29
+ }
30
+
31
+ function redrawAllCircles() {
32
+ context.clearRect(0, 0, canvas.width, canvas.height);
33
+ for (i = 0; i < points.length; i++) {
34
+ context.fillStyle = points[i].color;
35
+ context.fill(points[i], 'nonzero');
36
+ context.stroke(points[i], 'nonzero');
37
+ }
38
+ }
39
+
40
+ initCircles();
41
+ }
42
+ }
@@ -0,0 +1,24 @@
1
+ #canvas_field {
2
+ border: 1px groove lightgrey;
3
+ }
4
+
5
+ .canvas_field {
6
+ border: 1px groove lightgrey;
7
+ }
8
+
9
+ .canvas_data_field {
10
+ display: none;
11
+ }
12
+
13
+ .canvas_legend_sub {
14
+ height: 30px;
15
+ font-weight: 600;
16
+ padding-top: 9px;
17
+ text-align: center;
18
+ }
19
+
20
+ tr.active {
21
+ -webkit-box-shadow: 0px 0px 25px -2px #967474 inset;
22
+ -moz-box-shadow: 0px 0px 25px -2px #967474 inset;
23
+ box-shadow: 0px 0px 25px -2px #967474 inset;
24
+ }
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CanvasFieldHelper
4
+ def canvas_field(options = {})
5
+ url = '/'
6
+ url += options[:namespace].to_s + '/' if options[:namespace]
7
+ url += options[:controller] || 'canvas_fields'
8
+
9
+ background_url = options[:background_url].blank? ? '' : "url(#{options[:background_url]})"
10
+ background = "background: #fff #{background_url} no-repeat center top"
11
+ failure_message = 'Your browser does not support the canvas element.'
12
+
13
+ content_tag :canvas, failure_message, id: :canvas_field, data: collect_data(url, options), style: background
14
+ end
15
+
16
+ def canvas_data_field(active = false, options = {})
17
+ klass = active ? 'active' : ''
18
+ data = { additional_data: options[:additional_data].to_json,
19
+ initial_data: options[:initial_data].to_json,
20
+ content: options[:content] || '' }
21
+ content_tag(:span, '', class: "#{klass} canvas_data_field", data: data)
22
+ end
23
+
24
+ def canvas_legend_field(options = {})
25
+ locals = {
26
+ left_text: options[:left_text] || '',
27
+ middle_text: options[:middle_text] || '',
28
+ right_text: options[:right_text] || '',
29
+ left_color: options[:left_color] || '#ff0000',
30
+ middle_color: options[:middle_color] || '#00ff00',
31
+ right_color: options[:right_color] || '#0000ff',
32
+ no_icon: options[:no_icon] || false,
33
+ no_header: options[:no_header] || false
34
+ }
35
+ render partial: 'ajax_canvas_field/canvas_legend', locals: locals
36
+ end
37
+
38
+ def ro_canvas_field(options = {})
39
+ background_url = options[:background_url].blank? ? '' : "url(#{options[:background_url]})"
40
+ background = "background: #fff #{background_url} no-repeat center top"
41
+ failure_message = 'Your browser does not support the canvas element.'
42
+
43
+ content_tag :canvas, failure_message, data: collect_ro_data(options), style: background, class: 'canvas_field'
44
+ end
45
+
46
+ private
47
+
48
+ def collect_data(url, options)
49
+ { url: url,
50
+ strong_param: options[:param] || options[:controller]&.singularize || 'canvas_field',
51
+ token: options[:token],
52
+ width: options[:width] || AjaxCanvasField.config[:default_width],
53
+ height: options[:height] || AjaxCanvasField.config[:default_height],
54
+ left_color: options[:left_color] || '#ff0000',
55
+ middle_color: options[:middle_color] || '#00ff00',
56
+ right_color: options[:right_color] || '#0000ff' }
57
+ end
58
+
59
+ def collect_ro_data(options)
60
+ { width: options[:width] || AjaxCanvasField.config[:default_width],
61
+ height: options[:height] || AjaxCanvasField.config[:default_height],
62
+ left_color: options[:left_color] || '#ff0000',
63
+ middle_color: options[:middle_color] || '#00ff00',
64
+ right_color: options[:right_color] || '#0000ff',
65
+ initial_data: options[:initial_data].to_json }
66
+ end
67
+ end
@@ -0,0 +1,21 @@
1
+ %table
2
+ - unless no_header
3
+ %thead
4
+ %tr
5
+ %th.canvas_legend_sub Linke Maustaste
6
+ %th.canvas_legend_sub Mittlere Maustaste
7
+ %th.canvas_legend_sub Rechte Maustaste
8
+ %tbody
9
+ - unless no_icon
10
+ %tr
11
+ %td.canvas_legend_sub= image_tag('mouse_left.png', size: '50x50')
12
+ %td.canvas_legend_sub= image_tag('mouse_middle.png', size: '50x50')
13
+ %td.canvas_legend_sub= image_tag('mouse_right.png', size: '50x50')
14
+ %tr
15
+ %td.canvas_legend_sub= left_text
16
+ %td.canvas_legend_sub= middle_text
17
+ %td.canvas_legend_sub= right_text
18
+ %tr
19
+ %td.canvas_legend_sub{ style: "background-color: #{left_color}" }
20
+ %td.canvas_legend_sub{ style: "background-color: #{middle_color}" }
21
+ %td.canvas_legend_sub{ style: "background-color: #{right_color}" }
Binary file
Binary file
Binary file
@@ -0,0 +1,192 @@
1
+ document.addEventListener('DOMContentLoaded', function(){
2
+ var canvas = document.getElementById('canvas_field');
3
+ var data_fields = document.getElementsByClassName('canvas_data_field');
4
+ if (canvas) {
5
+ if (data_fields.length == 0) {
6
+ console.log('No Data Field found. Please add canvas_data_field in your code!');
7
+ document.getElementsByClassName('canvas_table')[0].style.display = 'none';
8
+ canvas.style.display = 'none';
9
+ } else {
10
+ canvas.width = canvas.dataset.width;
11
+ canvas.height = canvas.dataset.height;
12
+ var context = canvas.getContext('2d'),
13
+ url = canvas.dataset.url,
14
+ param = canvas.dataset.strongParam,
15
+ token = canvas.dataset.token,
16
+ points = [];
17
+
18
+ function refreshAll(e) {
19
+ points = [];
20
+ initCircles();
21
+ }
22
+
23
+ function initCircles() {
24
+ var data_field = document.getElementsByClassName('active canvas_data_field')[0].dataset;
25
+ var initialData = JSON.parse(data_field.initialData);
26
+ for (i = 0; i < initialData.length; i++) {
27
+ var point = buildCircle(initialData[i][1], initialData[i][2], initialData[i][3]);
28
+ point.database_id = initialData[i][0];
29
+ points.push(point);
30
+ }
31
+ redrawAllCircles();
32
+ }
33
+
34
+ function isPixelCollision(e) {
35
+ e.preventDefault();
36
+
37
+ if (e.type == "contextmenu") return;
38
+
39
+ var r = canvas.getBoundingClientRect(),
40
+ x = e.clientX - r.left,
41
+ y = e.clientY - r.top,
42
+ removed = false,
43
+ i;
44
+
45
+ for (i = points.length - 1; i >= 0; --i) {
46
+ if (context.isPointInPath(points[i], x, y, 'nonzero')) {
47
+ deleteAjax(i);
48
+ removed = true;
49
+ }
50
+ }
51
+
52
+ if (removed == false) {
53
+ createAjax(x, y, e);
54
+ }
55
+ }
56
+
57
+ function buildCircle(x, y, e) {
58
+ var c = new Path2D(),
59
+ offset = 3.5;
60
+
61
+ c.arc(x - offset, y - offset, 7, 0, Math.PI * 2);
62
+ c.color = (typeof e === 'string') ? e : chooseColor(e)
63
+ c.x = x;
64
+ c.y = y;
65
+ return c;
66
+ }
67
+
68
+ function chooseColor(e) {
69
+ if (e === null) return '#ff0000';
70
+ switch (e.which) {
71
+ case 1:
72
+ return canvas.dataset.leftColor;
73
+ case 2:
74
+ return canvas.dataset.middleColor;
75
+ case 3:
76
+ return canvas.dataset.rightColor;
77
+ }
78
+ }
79
+
80
+ function chooseButton(e) {
81
+ if (e === null) return null;
82
+ switch (e.which) {
83
+ case 1:
84
+ return 'left';
85
+ case 2:
86
+ return 'middle';
87
+ case 3:
88
+ return 'right';
89
+ }
90
+ }
91
+
92
+ function deleteAjax(i) {
93
+ var id = points[i].database_id;
94
+ $.ajax({
95
+ type: 'DELETE',
96
+ url: url + '/' + id,
97
+ headers: {
98
+ 'Authorization': 'Token token=' + token
99
+ },
100
+ dataType: "json",
101
+ success: function(data) {
102
+ removeCircle(i, data);
103
+ },
104
+ error: function(data) {
105
+ alert('No connection to Server');
106
+ }
107
+ });
108
+ }
109
+
110
+ function removeCircle(i, data) {
111
+ points.splice(i, 1);
112
+ redrawAllCircles();
113
+ }
114
+
115
+ function createAjax(x, y, e) {
116
+ post_data = collectPostData(x, y, e);
117
+ $.ajax({
118
+ type: 'POST',
119
+ url: url,
120
+ headers: {
121
+ 'Authorization': 'Token token=' + token
122
+ },
123
+ data: post_data,
124
+ dataType: "json",
125
+ success: function(data) {
126
+ addCircle(x, y, data, e);
127
+ },
128
+ error: function(data) {
129
+ alert('No connection to Server');
130
+ }
131
+ });
132
+ }
133
+
134
+ function collectPostData(x, y, e) {
135
+ var params = {};
136
+ var data_field = document.getElementsByClassName('active canvas_data_field')[0].dataset;
137
+ var additionalData = JSON.parse(data_field.additionalData);
138
+ params[param] = {
139
+ x_value: x,
140
+ y_value: y,
141
+ button: chooseButton(e)
142
+ };
143
+ for (var attrname in additionalData) {
144
+ params[param][attrname] = additionalData[attrname];
145
+ }
146
+ return params;
147
+ }
148
+
149
+ function addCircle(x, y, data, e) {
150
+ new_point = buildCircle(x, y, e);
151
+ new_point['database_id'] = data.id;
152
+ points.push(new_point);
153
+ redrawAllCircles();
154
+ }
155
+
156
+ function redrawAllCircles() {
157
+ var tmpData = [];
158
+ context.clearRect(0, 0, canvas.width, canvas.height);
159
+ for (i = 0; i < points.length; i++) {
160
+ context.fillStyle = points[i].color;
161
+ context.fill(points[i], 'nonzero');
162
+ context.stroke(points[i], 'nonzero');
163
+
164
+ tmpData.push([points[i].database_id, points[i].x, points[i].y, points[i].color]);
165
+ }
166
+ document.getElementsByClassName('active canvas_data_field')[0].dataset.initialData = JSON.stringify(tmpData);
167
+ }
168
+
169
+ canvas.addEventListener('click', isPixelCollision, false);
170
+ canvas.addEventListener('auxclick', isPixelCollision, false);
171
+ canvas.addEventListener('contextmenu', isPixelCollision, false);
172
+ initCircles();
173
+
174
+ var tableRows = document.getElementsByClassName('request_row');
175
+ var markRequestRow = function() {
176
+ for (var i = 0; i < tableRows.length; i++) {
177
+ tableRows[i].classList.remove('active');
178
+ }
179
+ for (var i = 0; i < data_fields.length; i++) {
180
+ data_fields[i].classList.remove('active');
181
+ }
182
+ this.classList.add('active');
183
+ this.getElementsByClassName('canvas_data_field')[0].classList.add('active');
184
+ refreshAll();
185
+ };
186
+
187
+ for (var i = 0; i < tableRows.length; i++) {
188
+ tableRows[i].addEventListener('click', markRequestRow, false);
189
+ }
190
+ }
191
+ }
192
+ }, false);
@@ -0,0 +1,42 @@
1
+ var canvases = document.getElementsByClassName('canvas_field');
2
+ if (canvases) {
3
+ for (o = 0; o < canvases.length; o++) {
4
+ var canvas = canvases[o];
5
+ canvas.width = canvas.dataset.width;
6
+ canvas.height = canvas.dataset.height;
7
+ var context = canvas.getContext('2d');
8
+ var points = [];
9
+
10
+ function initCircles() {
11
+ var initialData = JSON.parse(canvas.dataset.initialData);
12
+ for (i = 0; i < initialData.length; i++) {
13
+ var point = buildCircle(initialData[i][1], initialData[i][2], initialData[i][3]);
14
+ point.database_id = initialData[i][0];
15
+ points.push(point);
16
+ }
17
+ redrawAllCircles();
18
+ }
19
+
20
+ function buildCircle(x, y, e) {
21
+ var c = new Path2D(),
22
+ offset = 3.5;
23
+
24
+ c.arc(x - offset, y - offset, 7, 0, Math.PI * 2);
25
+ c.color = (typeof e === 'string') ? e : '#ff0000'
26
+ c.x = x;
27
+ c.y = y;
28
+ return c;
29
+ }
30
+
31
+ function redrawAllCircles() {
32
+ context.clearRect(0, 0, canvas.width, canvas.height);
33
+ for (i = 0; i < points.length; i++) {
34
+ context.fillStyle = points[i].color;
35
+ context.fill(points[i], 'nonzero');
36
+ context.stroke(points[i], 'nonzero');
37
+ }
38
+ }
39
+
40
+ initCircles();
41
+ }
42
+ }
@@ -0,0 +1,24 @@
1
+ #canvas_field {
2
+ border: 1px groove lightgrey;
3
+ }
4
+
5
+ .canvas_field {
6
+ border: 1px groove lightgrey;
7
+ }
8
+
9
+ .canvas_data_field {
10
+ display: none;
11
+ }
12
+
13
+ .canvas_legend_sub {
14
+ height: 30px;
15
+ font-weight: 600;
16
+ padding-top: 9px;
17
+ text-align: center;
18
+ }
19
+
20
+ tr.active {
21
+ -webkit-box-shadow: 0px 0px 25px -2px #967474 inset;
22
+ -moz-box-shadow: 0px 0px 25px -2px #967474 inset;
23
+ box-shadow: 0px 0px 25px -2px #967474 inset;
24
+ }
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CanvasFieldHelper
4
+ def canvas_field(options = {})
5
+ url = '/'
6
+ url += options[:namespace].to_s + '/' if options[:namespace]
7
+ url += options[:controller] || 'canvas_fields'
8
+
9
+ background_url = options[:background_url].blank? ? '' : "url(#{options[:background_url]})"
10
+ background = "background: #fff #{background_url} no-repeat center top"
11
+ failure_message = 'Your browser does not support the canvas element.'
12
+
13
+ content_tag :canvas, failure_message, id: :canvas_field, data: collect_data(url, options), style: background
14
+ end
15
+
16
+ def canvas_data_field(active = false, options = {})
17
+ klass = active ? 'active' : ''
18
+ data = { additional_data: options[:additional_data].to_json,
19
+ initial_data: options[:initial_data].to_json,
20
+ content: options[:content] || '' }
21
+ content_tag(:span, '', class: "#{klass} canvas_data_field", data: data)
22
+ end
23
+
24
+ def canvas_legend_field(options = {})
25
+ locals = {
26
+ left_text: options[:left_text] || '',
27
+ middle_text: options[:middle_text] || '',
28
+ right_text: options[:right_text] || '',
29
+ left_color: options[:left_color] || '#ff0000',
30
+ middle_color: options[:middle_color] || '#00ff00',
31
+ right_color: options[:right_color] || '#0000ff',
32
+ no_icon: options[:no_icon] || false,
33
+ no_header: options[:no_header] || false
34
+ }
35
+ render partial: 'ajax_canvas_field/canvas_legend', locals: locals
36
+ end
37
+
38
+ def ro_canvas_field(options = {})
39
+ background_url = options[:background_url].blank? ? '' : "url(#{options[:background_url]})"
40
+ background = "background: #fff #{background_url} no-repeat center top"
41
+ failure_message = 'Your browser does not support the canvas element.'
42
+
43
+ content_tag :canvas, failure_message, data: collect_ro_data(options), style: background, class: 'canvas_field'
44
+ end
45
+
46
+ private
47
+
48
+ def collect_data(url, options)
49
+ { url: url,
50
+ strong_param: options[:param] || options[:controller]&.singularize || 'canvas_field',
51
+ token: options[:token],
52
+ width: options[:width] || AjaxCanvasField.config[:default_width],
53
+ height: options[:height] || AjaxCanvasField.config[:default_height],
54
+ left_color: options[:left_color] || '#ff0000',
55
+ middle_color: options[:middle_color] || '#00ff00',
56
+ right_color: options[:right_color] || '#0000ff' }
57
+ end
58
+
59
+ def collect_ro_data(options)
60
+ { width: options[:width] || AjaxCanvasField.config[:default_width],
61
+ height: options[:height] || AjaxCanvasField.config[:default_height],
62
+ left_color: options[:left_color] || '#ff0000',
63
+ middle_color: options[:middle_color] || '#00ff00',
64
+ right_color: options[:right_color] || '#0000ff',
65
+ initial_data: options[:initial_data].to_json }
66
+ end
67
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ module AjaxCanvasField
6
+ # Configuration defaults
7
+ @config = {
8
+ default_height: 470,
9
+ default_width: 470,
10
+ default_left_color: '#ff0000',
11
+ default_middle_color: '#00ff00',
12
+ default_right_color: '#0000ff'
13
+ }
14
+
15
+ @valid_config_keys = @config.keys
16
+
17
+ # Configure through hash
18
+ def self.configure(opts = {})
19
+ opts.each { |k, v| @config[k.to_sym] = v if @valid_config_keys.include? k.to_sym }
20
+ end
21
+
22
+ # Configure through yaml file
23
+ def self.configure_with(path_to_yaml_file)
24
+ begin
25
+ config = YAML.safe_load(IO.read(path_to_yaml_file))
26
+ rescue Errno::ENOENT
27
+ log(:warning, "YAML configuration file couldn't be found. Using defaults."); return
28
+ rescue Psych::SyntaxError
29
+ log(:warning, 'YAML configuration file contains invalid syntax. Using defaults.'); return
30
+ end
31
+
32
+ configure(config)
33
+ end
34
+
35
+ def self.config
36
+ @config
37
+ end
38
+ end
@@ -0,0 +1,12 @@
1
+ module AjaxCanvasField #:nodoc:
2
+ module Rails #:nodoc:
3
+ class Engine < ::Rails::Engine
4
+ initializer 'ajax_canvas_field.assets.precompile' do |app|
5
+ %w(stylesheets javascripts images).each do |sub|
6
+ app.config.assets.paths << root.join('app/assets', sub).to_s
7
+ end
8
+ app.config.assets.precompile += %w( mouse_left.png mouse_right.png mouse_middle.png )
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ module AjaxCanvasField #:nodoc:
2
+ module Rails #:nodoc:
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ require 'ajax_canvas_field/rails/engine' if ::Rails.version >= '3.1'
2
+ require 'ajax_canvas_field/rails/version'
3
+
4
+ module AjaxCanvasField #:nodoc:
5
+ module Rails #:nodoc:
6
+ end
7
+ end
@@ -0,0 +1,2 @@
1
+ require 'ajax_canvas_field/rails'
2
+ require 'ajax_canvas_field/config'
@@ -0,0 +1,15 @@
1
+ require 'rails/generators/base'
2
+
3
+ class AjaxCanvasFieldGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+
6
+ desc "Copy the initializer for AjaxCanvasField"
7
+ def copy_initializer_file
8
+ copy_file "initializer.rb", "config/initializers/ajax_canvas_field.rb"
9
+
10
+ inject_into_file 'app/assets/javascripts/application.js', "//= require ajax_canvas_field\n", before: "//= require_tree ." rescue nil
11
+ inject_into_file 'app/assets/stylesheets/application.scss', " *= require ajax_canvas_field\n", before: " *= require_tree ." rescue nil
12
+ inject_into_file 'app/assets/stylesheets/application.scss.erb', " *= require ajax_canvas_field\n", before: " *= require_tree ." rescue nil
13
+ inject_into_file 'app/assets/stylesheets/application.css.scss', " *= require ajax_canvas_field\n", before: " *= require_tree ." rescue nil
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ AjaxCanvasField.configure(default_height: 400,
4
+ default_width: 400,
5
+ default_left_color: '#ff0000',
6
+ default_middle_color: '#00ff00',
7
+ default_right_color: '#0000ff')
@@ -0,0 +1,21 @@
1
+ %table
2
+ - unless no_header
3
+ %thead
4
+ %tr
5
+ %th.canvas_legend_sub Linke Maustaste
6
+ %th.canvas_legend_sub Mittlere Maustaste
7
+ %th.canvas_legend_sub Rechte Maustaste
8
+ %tbody
9
+ - unless no_icon
10
+ %tr
11
+ %td.canvas_legend_sub= image_tag('mouse_left.png', size: '50x50')
12
+ %td.canvas_legend_sub= image_tag('mouse_middle.png', size: '50x50')
13
+ %td.canvas_legend_sub= image_tag('mouse_right.png', size: '50x50')
14
+ %tr
15
+ %td.canvas_legend_sub= left_text
16
+ %td.canvas_legend_sub= middle_text
17
+ %td.canvas_legend_sub= right_text
18
+ %tr
19
+ %td.canvas_legend_sub{ style: "background-color: #{left_color}" }
20
+ %td.canvas_legend_sub{ style: "background-color: #{middle_color}" }
21
+ %td.canvas_legend_sub{ style: "background-color: #{right_color}" }
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ajax_canvas_field
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - datyv
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-10-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.15'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.15'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Add a CanvasField to point out errors in three different colors
42
+ email:
43
+ - yvesgoizet@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - Gemfile
49
+ - README.md
50
+ - Rakefile
51
+ - ajax_canvas_field.gemspec
52
+ - app/assets/images/mouse_left.png
53
+ - app/assets/images/mouse_middle.png
54
+ - app/assets/images/mouse_right.png
55
+ - app/assets/javascripts/ajax_canvas_field.js
56
+ - app/assets/javascripts/ro_canvas_field.js
57
+ - app/assets/stylesheets/ajax_canvas_field.css
58
+ - app/helpers/canvas_field_helper.rb
59
+ - app/views/ajax_canvas_field/_canvas_legend.html.haml
60
+ - assets/images/mouse_left.png
61
+ - assets/images/mouse_middle.png
62
+ - assets/images/mouse_right.png
63
+ - assets/javascripts/ajax_canvas_field.js
64
+ - assets/javascripts/ro_canvas_field.js
65
+ - assets/stylesheets/ajax_canvas_field.css
66
+ - helpers/canvas_field_helper.rb
67
+ - lib/ajax_canvas_field.rb
68
+ - lib/ajax_canvas_field/config.rb
69
+ - lib/ajax_canvas_field/rails.rb
70
+ - lib/ajax_canvas_field/rails/engine.rb
71
+ - lib/ajax_canvas_field/rails/version.rb
72
+ - lib/generators/ajax_canvas_field/ajax_canvas_field_generator.rb
73
+ - lib/generators/ajax_canvas_field/templates/initializer.rb
74
+ - views/ajax_canvas_field/_canvas_legend.html.haml
75
+ homepage: https://github.com/Datyv/ajax_canvas_field
76
+ licenses:
77
+ - MIT
78
+ metadata:
79
+ allowed_push_host: https://rubygems.org
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - app
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.5.2
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: HTML5 CanvasField Support
101
+ test_files: []