ela 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile.lock +3 -1
- data/app/css/screen.styl +22 -11
- data/app/js/lib/views/1_viewport_view.coffee +4 -0
- data/app/js/lib/views/axis_handler.coffee +62 -0
- data/app/js/lib/views/base_app.coffee +23 -100
- data/app/js/lib/views/canvas.coffee +8 -1
- data/app/js/lib/views/graph_view.coffee +102 -0
- data/app/js/lib/views/interpolated_graph.coffee +75 -62
- data/app/js/lib/views/legend.coffee +13 -2
- data/app/js/lib/views/viewport.coffee +26 -0
- data/app/views/general/app.jst.hamlc +2 -12
- data/ela.gemspec +1 -1
- data/lib/ela/version.rb +1 -1
- metadata +15 -7
- data/app/js/lib/views/legend_handler.coffee +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 17010b55c4244377534fb008bb8b00701b2ec1f3a03b8c08e57ca9ffb8321860
|
4
|
+
data.tar.gz: 9ea5fbd11fb13b0ed539ffb903a8f4d543a3a2e7ab92054dcb2afd2d31f9a22f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 226cd20184cdde3a1f651d205995e4de2c0527357a789ff3a49aa6d268da1eea5431a16298e422d6be5fa75220c10af07577929d7675f361f8b8146e8f9c5b5b
|
7
|
+
data.tar.gz: 0b6e09af8f8b0cd19557e2030c139cbbd84ff84d14c53996c3ae88f8decb33e38fc71728608a7673f5d905b8c6c87814e954533536eacd57ac546d7a0c5a2fa1
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ela (1.0
|
4
|
+
ela (1.1.0)
|
5
|
+
andand (~> 1.3, >= 1.3.3)
|
5
6
|
bundler (~> 1.13)
|
6
7
|
coffee-script (~> 2.4, >= 2.4.1)
|
7
8
|
guard (~> 2.10)
|
@@ -23,6 +24,7 @@ PATH
|
|
23
24
|
GEM
|
24
25
|
remote: https://rubygems.org/
|
25
26
|
specs:
|
27
|
+
andand (1.3.3)
|
26
28
|
coderay (1.1.2)
|
27
29
|
coffee-script (2.4.1)
|
28
30
|
coffee-script-source
|
data/app/css/screen.styl
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
// ELA specific
|
2
|
-
$
|
2
|
+
$axis-handler-size = 59px
|
3
3
|
|
4
4
|
// Remember that this color should be set in CurveGraph aswell
|
5
5
|
// to resemble the fillColor of the range indicator triangles:
|
@@ -112,9 +112,22 @@ li.share-form
|
|
112
112
|
&.failure:before
|
113
113
|
content "\f00d"
|
114
114
|
|
115
|
-
article.
|
115
|
+
article.viewport
|
116
116
|
display flex
|
117
|
-
|
117
|
+
|
118
|
+
.view
|
119
|
+
flex 1
|
120
|
+
display flex
|
121
|
+
flex-direction column
|
122
|
+
border-right 1px solid #bbb
|
123
|
+
overflow hidden
|
124
|
+
|
125
|
+
&:last-child
|
126
|
+
border-right: none
|
127
|
+
|
128
|
+
.horizontal-wrapper
|
129
|
+
display flex
|
130
|
+
flex 1
|
118
131
|
|
119
132
|
div.legend
|
120
133
|
z-layer 'section', 'legend'
|
@@ -180,8 +193,6 @@ article.graph
|
|
180
193
|
|
181
194
|
&.legend-simple
|
182
195
|
border-bottom 1px solid #ccc
|
183
|
-
absolute 0
|
184
|
-
width 100%
|
185
196
|
|
186
197
|
.curve
|
187
198
|
display inline-block
|
@@ -217,15 +228,15 @@ article.graph
|
|
217
228
|
padding 10px
|
218
229
|
background-color rgba(255, 255, 255, 0.8)
|
219
230
|
|
220
|
-
div.
|
231
|
+
div.axis-handler
|
221
232
|
text-align center
|
222
233
|
cursor pointer
|
223
234
|
background $legend-background
|
224
235
|
padding 14px 5px
|
225
236
|
|
226
|
-
&.
|
227
|
-
|
228
|
-
|
237
|
+
&.axis-handler-left
|
238
|
+
width $axis-handler-size
|
239
|
+
position relative
|
229
240
|
|
230
241
|
span.hint
|
231
242
|
absolute 50% none none 50%
|
@@ -234,7 +245,7 @@ article.graph
|
|
234
245
|
|
235
246
|
// vertical range slider and large, non-transparent legend with values
|
236
247
|
#international-standard-atmosphere article.graph div.graph
|
237
|
-
margin-left $
|
248
|
+
margin-left $axis-handler-size
|
238
249
|
|
239
250
|
// Some space for the delete button
|
240
251
|
#composites
|
@@ -349,7 +360,7 @@ aside.curves
|
|
349
360
|
|
350
361
|
img.logo
|
351
362
|
absolute none 0 0 none
|
352
|
-
height $
|
363
|
+
height $axis-handler-size
|
353
364
|
z-layer 'section', 'graph'
|
354
365
|
|
355
366
|
@media $media-lt-phone
|
@@ -0,0 +1,62 @@
|
|
1
|
+
ELA.Views ?= {}
|
2
|
+
class ELA.Views.AxisHandler extends Backbone.Poised.View
|
3
|
+
className: 'axis-handler'
|
4
|
+
|
5
|
+
events:
|
6
|
+
'pan': 'updateValue'
|
7
|
+
'tap': 'updateValue'
|
8
|
+
|
9
|
+
hammerjs:
|
10
|
+
recognizers: [
|
11
|
+
[Hammer.Rotate, { enable: false }],
|
12
|
+
[Hammer.Pinch, { enable: false }, ['rotate']],
|
13
|
+
[Hammer.Swipe, { enable: false }],
|
14
|
+
[Hammer.Pan, { direction: Hammer.DIRECTION_ALL, threshold: 1 }, ['swipe']],
|
15
|
+
[Hammer.Tap, { threshold: 5 }],
|
16
|
+
[Hammer.Press, { enable: false }]
|
17
|
+
]
|
18
|
+
|
19
|
+
initialize: (options) ->
|
20
|
+
@displayParams = options.displayParams
|
21
|
+
@position = options.position or 'bottom'
|
22
|
+
@orientation = switch @position
|
23
|
+
when 'bottom' then 'x'
|
24
|
+
when 'left' then 'y'
|
25
|
+
@attribute = options.attribute
|
26
|
+
@precision = @model.get("#{@attribute}Precision")
|
27
|
+
@precision ?= options.precision
|
28
|
+
@precision ?= 2
|
29
|
+
|
30
|
+
@listenTo @model, "change:#{@attribute}", @renderText
|
31
|
+
|
32
|
+
updateValue: (e) =>
|
33
|
+
origin = @displayParams.get("#{@orientation}Origin")
|
34
|
+
range = @displayParams.get("#{@orientation}Range")
|
35
|
+
graphOffset = @parentView.subviews.graph.$el.offset()
|
36
|
+
if @orientation is 'x'
|
37
|
+
width = @displayParams.get('width')
|
38
|
+
point = (range / width) *
|
39
|
+
(e.gesture.pointers[0].clientX - graphOffset.left - origin)
|
40
|
+
else # @orientation is 'y'
|
41
|
+
height = @displayParams.get('height')
|
42
|
+
y = e.gesture.pointers[0].clientY - graphOffset.top
|
43
|
+
y = Math.min(Math.max(y, 0), height)
|
44
|
+
point = (range / height) * (origin - y)
|
45
|
+
|
46
|
+
pow = Math.pow(10, @precision)
|
47
|
+
point = Math.round(point * pow) / pow
|
48
|
+
@model.set(@attribute, point)
|
49
|
+
|
50
|
+
renderText: =>
|
51
|
+
@$el.find('span').text(t(
|
52
|
+
"#{@model.name}.axisHandler.#{@attribute}.label"
|
53
|
+
"#{@model.name}.axisHandler.label"
|
54
|
+
'axisHandler.label'
|
55
|
+
value: @model.get(@attribute).toFixed(@precision)
|
56
|
+
))
|
57
|
+
|
58
|
+
render: =>
|
59
|
+
@$el.html('<span class="hint"></span>')
|
60
|
+
@$el.addClass("axis-handler-#{@position}")
|
61
|
+
@renderText()
|
62
|
+
this
|
@@ -9,28 +9,10 @@ class ELA.Views.BaseApp extends Backbone.Poised.View
|
|
9
9
|
# Typically in a subclass we override the list of asides. This may
|
10
10
|
# be a list of classes inheriting from ELA.Views.BaseAside or an
|
11
11
|
# object with `name` and `klass` attributes.
|
12
|
-
|
12
|
+
asides: []
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
graphView: null
|
17
|
-
graphOverlayView: null
|
18
|
-
graphDefaults: {}
|
19
|
-
|
20
|
-
rangeHandlerView: null
|
21
|
-
|
22
|
-
# TODO: Rename valueAtRange name pattern to something like selectValue
|
23
|
-
# TODO: use correct attribute in every app instead of generic valueAtRange
|
24
|
-
valueAtRange: null
|
25
|
-
valueAtRangeAxis: 'x'
|
26
|
-
valueAtRangeAttribute: 'valueAtRange'
|
27
|
-
valueAtRangePrecision: null
|
28
|
-
|
29
|
-
legendValueAtRange: null
|
30
|
-
legendValueAtRangeAxis: null
|
31
|
-
legendValueAtRangeAttribute: null
|
32
|
-
|
33
|
-
useHeadup: false
|
14
|
+
# Typically in a subclass we override the list of views.
|
15
|
+
views: []
|
34
16
|
|
35
17
|
events:
|
36
18
|
'tap header .overview.icon': 'backToOverview'
|
@@ -55,16 +37,13 @@ class ELA.Views.BaseApp extends Backbone.Poised.View
|
|
55
37
|
initialize: ->
|
56
38
|
@listenTo @model, 'change:currentAside', @toggleAside
|
57
39
|
@listenTo @model, 'change:showHelp', @renderHelp
|
58
|
-
|
59
|
-
|
60
|
-
@on 'controlLiveChangeEnd', @liveChangeEnd
|
40
|
+
@on 'controlLiveChangeStart', @liveChangeStart
|
41
|
+
@on 'controlLiveChangeEnd', @liveChangeEnd
|
61
42
|
|
62
|
-
for
|
63
|
-
|
43
|
+
for aside in @asides
|
44
|
+
aside.link ?= 'icon'
|
64
45
|
|
65
|
-
|
66
|
-
GraphParams = @graphView.toFunction()['Params']
|
67
|
-
@model.displayParams = new GraphParams if GraphParams?
|
46
|
+
@model.displayParams ?= {}
|
68
47
|
|
69
48
|
viewSubappOptions: =>
|
70
49
|
@$('.subapps.select').toggleClass('view')
|
@@ -117,16 +96,16 @@ class ELA.Views.BaseApp extends Backbone.Poised.View
|
|
117
96
|
|
118
97
|
iconAsideNames: ->
|
119
98
|
@_iconAsideNames ?= do =>
|
120
|
-
_.compact(_.map(@
|
121
|
-
|
99
|
+
_.compact(_.map(@asides, (aside) ->
|
100
|
+
aside.name if aside.link is 'icon'
|
122
101
|
))
|
123
102
|
|
124
103
|
contextAsides: ->
|
125
104
|
@_contextAsideNames ?= do =>
|
126
|
-
_.compact(_.map(@
|
127
|
-
if
|
128
|
-
name:
|
129
|
-
label: @loadLocale("contextMenu.#{
|
105
|
+
_.compact(_.map(@asides, (aside) =>
|
106
|
+
if aside.link is 'contextMenu'
|
107
|
+
name: aside.name
|
108
|
+
label: @loadLocale("contextMenu.#{aside.name}")
|
130
109
|
))
|
131
110
|
|
132
111
|
backToOverview: =>
|
@@ -181,11 +160,6 @@ class ELA.Views.BaseApp extends Backbone.Poised.View
|
|
181
160
|
hasHelpText: @model.hasHelpText
|
182
161
|
iconAsideNames: @iconAsideNames()
|
183
162
|
contextAsides: @contextAsides()
|
184
|
-
legendView: @legendView?
|
185
|
-
graphOverlayView: @graphOverlayView?
|
186
|
-
graphView: @graphView?
|
187
|
-
rangeHandlerView: @rangeHandlerView?
|
188
|
-
useHeadup: @useHeadup
|
189
163
|
relatedApps: @relatedApps()
|
190
164
|
currentPath: @model.path
|
191
165
|
@$shareLink = @$('li.share-link')
|
@@ -194,7 +168,7 @@ class ELA.Views.BaseApp extends Backbone.Poised.View
|
|
194
168
|
@$shareCopyButton = @$shareForm.find('button')
|
195
169
|
|
196
170
|
@$app = @$('section.app')
|
197
|
-
for aside in @
|
171
|
+
for aside in @asides
|
198
172
|
AsideView = aside.view.toFunction()
|
199
173
|
view = @subviews[aside.name] = new AsideView
|
200
174
|
model: @model
|
@@ -203,70 +177,19 @@ class ELA.Views.BaseApp extends Backbone.Poised.View
|
|
203
177
|
localePrefix: @localePrefix
|
204
178
|
@$app.append(view.render().el)
|
205
179
|
|
206
|
-
|
207
|
-
@$legend = @$('article .legend')
|
208
|
-
LegendView = @legendView.toFunction()
|
209
|
-
@subviews.legend = view = new LegendView
|
210
|
-
model: @model
|
211
|
-
parentView: this
|
212
|
-
el: @$legend
|
213
|
-
useValueAtRange: @legendValueAtRange or @valueAtRange or @rangeHandlerView?
|
214
|
-
valueAtRangeAxis: @legendValueAtRangeAxis or @valueAtRangeAxis
|
215
|
-
valueAtRangeAttribute: @legendValueAtRangeAttribute or @valueAtRangeAttribute
|
216
|
-
localePrefix: @localePrefix
|
217
|
-
view.render()
|
218
|
-
|
219
|
-
if @graphOverlayView? and not @subviews.graphOverlayView
|
220
|
-
@$graphOverlay = @$('article .graph-overlay')
|
221
|
-
GraphOverlayView = @graphOverlayView.toFunction()
|
222
|
-
@subviews.graphOverlayView = view = new GraphOverlayView
|
223
|
-
model: @model
|
224
|
-
parentView: this
|
225
|
-
el: @$graphOverlay
|
226
|
-
localPrefix: @localePrefix
|
227
|
-
view.render()
|
228
|
-
|
229
|
-
if @rangeHandlerView? and not @subviews.rangeHandler?
|
230
|
-
@$rangeHandler = @$('article .range-handler')
|
231
|
-
RangeHandlerView = @rangeHandlerView.toFunction()
|
232
|
-
@subviews.rangeHandler = view = new RangeHandlerView
|
233
|
-
model: @model
|
234
|
-
parentView: this
|
235
|
-
el: @$rangeHandler
|
236
|
-
axis: @valueAtRangeAxis
|
237
|
-
attribute: @valueAtRangeAttribute
|
238
|
-
precision: @valueAtRangePrecision
|
239
|
-
localePrefix: @localePrefix
|
240
|
-
view.render()
|
241
|
-
|
242
|
-
if @useHeadup and not @subviews.headup?
|
180
|
+
unless @subviews.headup?
|
243
181
|
@$headup = @$('aside.headup')
|
244
182
|
@subviews.headup = new ELA.Views.Headup
|
245
183
|
el: @$headup
|
246
184
|
localePrefix: @localePrefix
|
247
185
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
@
|
253
|
-
|
254
|
-
|
255
|
-
params: @model.displayParams
|
256
|
-
defaults: _.defaults
|
257
|
-
# Taken from ELA.Views.Canvas::readCanvasResolution
|
258
|
-
width: @$graph[0].clientWidth
|
259
|
-
height: @$graph[0].clientHeight
|
260
|
-
valueAtRangeAxis: @valueAtRangeAxis
|
261
|
-
valueAtRangeAttribute: @valueAtRangeAttribute
|
262
|
-
, @graphDefaults
|
263
|
-
localePrefix: @localePrefix
|
264
|
-
@$graph.html(view.render().el)
|
265
|
-
|
266
|
-
# If the legend uses the value at range feature, it's height
|
267
|
-
# may change with updated calculators
|
268
|
-
if @subviews.legend?.useValueAtRange
|
269
|
-
@listenTo(@model, 'change:calculators', view.readCanvasResolution)
|
186
|
+
unless @subviews.viewport
|
187
|
+
view = @subviews.viewport = new ELA.Views.Viewport
|
188
|
+
model: @model
|
189
|
+
parentView: this
|
190
|
+
views: @views
|
191
|
+
localePrefix: @localePrefix
|
192
|
+
@$('.viewport').replaceWith(view.render().el)
|
270
193
|
|
271
194
|
@renderHelp()
|
272
195
|
@toggleAside(@model, @model.get('currentAside'))
|
@@ -21,11 +21,18 @@ class ELA.Views.Canvas extends Backbone.Poised.View
|
|
21
21
|
@params = options.params
|
22
22
|
@params.set(@defaults)
|
23
23
|
else
|
24
|
+
@model.displayParams ?= {}
|
24
25
|
@params = new @constructor.Params(@defaults)
|
26
|
+
@model.displayParams[options.name] = @params
|
25
27
|
|
26
28
|
@setCanvasResolution()
|
27
29
|
|
28
|
-
$(window).resize
|
30
|
+
$(window).on('resize', @readCanvasResolution)
|
31
|
+
|
32
|
+
# If the legend uses the value at range feature, it's height
|
33
|
+
# may change with updated calculators
|
34
|
+
@listenTo(@model, 'change:calculators', @readCanvasResolution)
|
35
|
+
|
29
36
|
@listenTo(@params, 'change:width change:height', @setCanvasResolution)
|
30
37
|
|
31
38
|
remove: ->
|
@@ -0,0 +1,102 @@
|
|
1
|
+
ELA.Views ?= {}
|
2
|
+
|
3
|
+
class ELA.Views.GraphView extends ELA.Views.ViewportView
|
4
|
+
initialize: (options = {}) ->
|
5
|
+
unless options.name?
|
6
|
+
throw 'ELA.Views.GraphView: option `name` is required'
|
7
|
+
|
8
|
+
if options.graph?.view
|
9
|
+
@GraphView = options.graph.view.toFunction()
|
10
|
+
else
|
11
|
+
@GraphView = ELA.Views.InterpolatedGraph
|
12
|
+
@displayParams = @model.displayParams[options.name] = new @GraphView.Params
|
13
|
+
|
14
|
+
unless options.legend is false
|
15
|
+
if _.isObject(options.legend) and options.legend.view?
|
16
|
+
@LegendView = options.legend.view.toFunction()
|
17
|
+
else
|
18
|
+
@LegendView = ELA.Views.Legend
|
19
|
+
|
20
|
+
if options.graphOverlay?.view?
|
21
|
+
@GraphOverlayView = options.graphOverlay.view.toFunction()
|
22
|
+
|
23
|
+
for axis, props of options.graph?.axes
|
24
|
+
if props.handler
|
25
|
+
attribute: props.attribute
|
26
|
+
position: switch axis
|
27
|
+
when 'x' then @bottomAxisHandler = attribute: props.attribute
|
28
|
+
when 'y' then @leftAxisHandler = attribute: props.attribute
|
29
|
+
|
30
|
+
@curves = options.graph?.curves?.slice()
|
31
|
+
|
32
|
+
@subviews = {}
|
33
|
+
|
34
|
+
render: =>
|
35
|
+
@$el.empty()
|
36
|
+
|
37
|
+
if @LegendView?
|
38
|
+
view = @subviews.legend ?= new @LegendView
|
39
|
+
model: @model
|
40
|
+
parentView: this
|
41
|
+
localePrefix: @localePrefix
|
42
|
+
curves: @curves
|
43
|
+
@$el.append(view.render().el)
|
44
|
+
|
45
|
+
if @GraphOverlayView?
|
46
|
+
view = @subviews.graphOverlay ?= new @GraphOverlayView
|
47
|
+
model: @model
|
48
|
+
parentView: this
|
49
|
+
localePrefix: @localePrefix
|
50
|
+
@$el.append(view.render().el)
|
51
|
+
|
52
|
+
$horizontalWrapper = $('<div>', class: 'horizontal-wrapper')
|
53
|
+
|
54
|
+
if @leftAxisHandler?
|
55
|
+
view = @subviews.leftAxisHandler ?= new ELA.Views.AxisHandler
|
56
|
+
model: @model
|
57
|
+
displayParams: @displayParams
|
58
|
+
attribute: @leftAxisHandler.attribute
|
59
|
+
position: 'left'
|
60
|
+
parentView: this
|
61
|
+
localePrefix: @localePrefix
|
62
|
+
$horizontalWrapper.append(view.render().el)
|
63
|
+
|
64
|
+
$horizontalWrapper.append($('<div>', class: 'graph'))
|
65
|
+
@$el.append($horizontalWrapper)
|
66
|
+
|
67
|
+
if @bottomAxisHandler?
|
68
|
+
view = @subviews.bottomAxisHandler ?= new ELA.Views.AxisHandler
|
69
|
+
model: @model
|
70
|
+
displayParams: @displayParams
|
71
|
+
attribute: @bottomAxisHandler.attribute
|
72
|
+
position: 'bottom'
|
73
|
+
parentView: this
|
74
|
+
localePrefix: @localePrefix
|
75
|
+
@$el.append(view.render().el)
|
76
|
+
|
77
|
+
delay =>
|
78
|
+
$graph = @$('.graph')
|
79
|
+
guides = []
|
80
|
+
if @bottomAxisHandler?
|
81
|
+
guides.push
|
82
|
+
orientation: 'vertical'
|
83
|
+
attribute: @bottomAxisHandler.attribute
|
84
|
+
if @leftAxisHandler?
|
85
|
+
guides.push
|
86
|
+
orientation: 'horizontal'
|
87
|
+
attribute: @leftAxisHandler.attribute
|
88
|
+
view = @subviews.graph ?= new @GraphView
|
89
|
+
model: @model
|
90
|
+
parentView: this
|
91
|
+
params: @displayParams
|
92
|
+
defaults: _.defaults
|
93
|
+
# Taken from ELA.Views.Canvas::readCanvasResolution
|
94
|
+
width: $graph[0].clientWidth
|
95
|
+
height: $graph[0].clientHeight
|
96
|
+
guides: guides
|
97
|
+
curves: @curves
|
98
|
+
, @graphDefaults
|
99
|
+
localePrefix: @localePrefix
|
100
|
+
$graph.html(view.render().el)
|
101
|
+
|
102
|
+
this
|
@@ -14,8 +14,9 @@ class ELA.Views.InterpolatedGraph extends ELA.Views.BaseGraph
|
|
14
14
|
@bindCalculatorEvents()
|
15
15
|
@requestRepaint()
|
16
16
|
|
17
|
-
|
18
|
-
@model
|
17
|
+
for guide in @params.get('guides')
|
18
|
+
@listenTo(@model, "change:#{guide.attribute}", @requestRepaint)
|
19
|
+
|
19
20
|
@model.on 'change:axisLabelingForCurve', @requestRepaint
|
20
21
|
|
21
22
|
bindCalculatorEvents: ->
|
@@ -23,14 +24,15 @@ class ELA.Views.InterpolatedGraph extends ELA.Views.BaseGraph
|
|
23
24
|
@stopListening(@model.previous('calculators'))
|
24
25
|
|
25
26
|
for calc in @model.get('calculators')
|
26
|
-
|
27
|
+
filteredCurves = @_filteredCurves()
|
28
|
+
for curve in filteredCurves
|
27
29
|
@listenTo calc, "change:#{curve.get('function')}", @requestRepaint
|
28
30
|
|
29
31
|
@listenTo calc, 'change:maxX change:xRange', @calculateRangeX
|
30
32
|
@listenTo calc, 'change:maxY change:yRange', @calculateRangeY
|
31
33
|
# TODO: Add dynamic dependencies to calculator, so that we can
|
32
34
|
# actually only listen to maxY changes and recalculate ranges.
|
33
|
-
oldestCurve =
|
35
|
+
oldestCurve = filteredCurves[0]
|
34
36
|
if oldestCurve?
|
35
37
|
@listenTo calc, "change:#{oldestCurve.get('function')}", @calculateRanges
|
36
38
|
|
@@ -124,9 +126,18 @@ class ELA.Views.InterpolatedGraph extends ELA.Views.BaseGraph
|
|
124
126
|
else
|
125
127
|
@drawSpline(points, tension, closed, xPos, yPos)
|
126
128
|
|
129
|
+
_filteredCurves: ->
|
130
|
+
curves = @model.curves.history
|
131
|
+
if graphCurves = @params.get('curves')
|
132
|
+
_.filter curves, (curve) ->
|
133
|
+
graphCurves.indexOf(curve.get('function')) >= 0
|
134
|
+
else
|
135
|
+
curves
|
136
|
+
|
127
137
|
_sortedCurves: ->
|
128
|
-
_.sortBy @
|
129
|
-
|
138
|
+
_.sortBy @_filteredCurves(), (curve) ->
|
139
|
+
curve.get('zIndex')
|
140
|
+
|
130
141
|
|
131
142
|
beforeRenderCurves: (resultCurves) ->
|
132
143
|
afterRenderCurves: (resultCurves) ->
|
@@ -135,7 +146,6 @@ class ELA.Views.InterpolatedGraph extends ELA.Views.BaseGraph
|
|
135
146
|
resultCurves = []
|
136
147
|
for calc, i in @model.get('calculators')
|
137
148
|
for curve, j in @_sortedCurves()
|
138
|
-
|
139
149
|
func = curve.get('function')
|
140
150
|
resultCurves.push
|
141
151
|
curve: curve
|
@@ -219,63 +229,66 @@ class ELA.Views.InterpolatedGraph extends ELA.Views.BaseGraph
|
|
219
229
|
@context.fill()
|
220
230
|
@context.closePath()
|
221
231
|
|
222
|
-
|
223
|
-
|
224
|
-
@context.beginPath()
|
225
|
-
@context.setLineDash []
|
226
|
-
@context.strokeStyle = '#999999'
|
227
|
-
@context.lineWidth = 2
|
228
|
-
|
229
|
-
# Border below legend
|
230
|
-
@context.moveTo(@width, 0)
|
231
|
-
@context.lineTo(0, 0)
|
232
|
-
|
233
|
-
if (axis = @params.get('valueAtRangeAxis')) is 'x'
|
234
|
-
# Border next to range handler
|
235
|
-
@context.moveTo(0, @height)
|
236
|
-
@context.lineTo(@width, @height)
|
237
|
-
@context.lineTo(@width, @height-10)
|
238
|
-
|
239
|
-
# Range handler line
|
240
|
-
xPos = @xOrigin + valueAtPoint * @width / @xRange
|
241
|
-
@context.moveTo(xPos, 0)
|
242
|
-
@context.lineTo(xPos, @height)
|
243
|
-
else
|
244
|
-
# Border next to range handler
|
245
|
-
@context.lineTo(0, @height)
|
232
|
+
renderGuide: (guide) ->
|
233
|
+
valueAtPoint = @model.get(guide.attribute)
|
246
234
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
@context.
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
235
|
+
@context.beginPath()
|
236
|
+
@context.setLineDash []
|
237
|
+
@context.strokeStyle = '#999999'
|
238
|
+
@context.lineWidth = 2
|
239
|
+
|
240
|
+
# Border below legend
|
241
|
+
@context.moveTo(@width, 0)
|
242
|
+
@context.lineTo(0, 0)
|
243
|
+
|
244
|
+
if guide.orientation is 'vertical'
|
245
|
+
# Border next to range handler
|
246
|
+
@context.moveTo(0, @height)
|
247
|
+
@context.lineTo(@width, @height)
|
248
|
+
@context.lineTo(@width, @height-10)
|
249
|
+
|
250
|
+
# Range handler line
|
251
|
+
xPos = @xOrigin + valueAtPoint * @width / @xRange
|
252
|
+
@context.moveTo(xPos, 0)
|
253
|
+
@context.lineTo(xPos, @height)
|
254
|
+
else
|
255
|
+
# Border next to range handler
|
256
|
+
@context.lineTo(0, @height)
|
257
|
+
|
258
|
+
# Range handler line
|
259
|
+
yPos = - valueAtPoint * @height / @yRange + @yOrigin
|
260
|
+
@context.moveTo(0, yPos)
|
261
|
+
@context.lineTo(@width, yPos)
|
262
|
+
|
263
|
+
@context.stroke()
|
264
|
+
@context.closePath()
|
265
|
+
|
266
|
+
@context.beginPath()
|
267
|
+
# The fillStyle of the triangle should match the color of the
|
268
|
+
# background set for the legend and range handler in screen.styl:
|
269
|
+
@context.fillStyle = "#f2f2f2"
|
270
|
+
@context.lineWidth = 1
|
271
|
+
|
272
|
+
if guide.orientation is 'vertical'
|
273
|
+
@context.moveTo(xPos + 8, 0)
|
274
|
+
@context.lineTo(xPos, 8)
|
275
|
+
@context.lineTo(xPos - 8, 0)
|
276
|
+
@context.moveTo(xPos - 8, @height)
|
277
|
+
@context.lineTo(xPos, @height - 8)
|
278
|
+
@context.lineTo(xPos + 8, @height)
|
279
|
+
else
|
280
|
+
@context.moveTo(0, yPos - 8)
|
281
|
+
@context.lineTo(8, yPos)
|
282
|
+
@context.lineTo(0, yPos + 8)
|
283
|
+
@context.moveTo(@width, yPos - 8)
|
284
|
+
@context.lineTo(@width - 8, yPos)
|
285
|
+
@context.lineTo(@width, yPos + 8)
|
286
|
+
@context.stroke()
|
287
|
+
@context.fill()
|
288
|
+
@context.closePath()
|
277
289
|
|
278
290
|
render: =>
|
279
291
|
super
|
280
|
-
@
|
292
|
+
for guide in @params.get('guides')
|
293
|
+
@renderGuide(guide)
|
281
294
|
this
|
@@ -1,5 +1,7 @@
|
|
1
1
|
ELA.Views ?= {}
|
2
2
|
class ELA.Views.Legend extends Backbone.Poised.View
|
3
|
+
className: 'legend'
|
4
|
+
|
3
5
|
valueCurveColumnTemplate: _.template '
|
4
6
|
<div class="values col<%= activeClass %>"
|
5
7
|
data-index="<%= curveIndex %>"
|
@@ -29,6 +31,7 @@ class ELA.Views.Legend extends Backbone.Poised.View
|
|
29
31
|
@useValueAtRange = options.useValueAtRange
|
30
32
|
@valueAtRangeAxis = options.valueAtRangeAxis or 'x'
|
31
33
|
@valueAtRangeAttribute = options.valueAtRangeAttribute or 'valueAtRange'
|
34
|
+
@_curves = options.curves
|
32
35
|
|
33
36
|
@model.on "change:#{@valueAtRangeAttribute}", @render
|
34
37
|
|
@@ -115,6 +118,14 @@ class ELA.Views.Legend extends Backbone.Poised.View
|
|
115
118
|
calculatorFunction: (curve) ->
|
116
119
|
"#{curve.get('function')}_value"
|
117
120
|
|
121
|
+
curves: =>
|
122
|
+
curves = @model.curves.whereInHistory()
|
123
|
+
if @_curves
|
124
|
+
_.filter curves, (curve) =>
|
125
|
+
@_curves.indexOf(curve.get('function')) >= 0
|
126
|
+
else
|
127
|
+
curves
|
128
|
+
|
118
129
|
render: =>
|
119
130
|
if @useValueAtRange
|
120
131
|
@range = @model.get(@valueAtRangeAttribute)
|
@@ -125,7 +136,7 @@ class ELA.Views.Legend extends Backbone.Poised.View
|
|
125
136
|
|
126
137
|
@renderValueHeaderColumn()
|
127
138
|
|
128
|
-
_.each
|
139
|
+
_.each(@curves(), @renderValueCurveColumn)
|
129
140
|
|
130
141
|
# Replace keeping horizontal scroll position
|
131
142
|
scrollLeft = @$el.find('.scroll-x').scrollLeft()
|
@@ -134,5 +145,5 @@ class ELA.Views.Legend extends Backbone.Poised.View
|
|
134
145
|
this
|
135
146
|
else
|
136
147
|
@$el.empty().addClass('legend-simple')
|
137
|
-
_.each
|
148
|
+
_.each(@curves(), @renderSimpleCurveColumn)
|
138
149
|
this
|
@@ -0,0 +1,26 @@
|
|
1
|
+
ELA.Views ?= {}
|
2
|
+
|
3
|
+
class ELA.Views.Viewport extends Backbone.Poised.View
|
4
|
+
tagName: 'article'
|
5
|
+
className: 'viewport'
|
6
|
+
|
7
|
+
initialize: (options = {}) ->
|
8
|
+
@views = for view in options.views
|
9
|
+
view.options = _.omit(view, 'view')
|
10
|
+
view.options.name = view.name or Math.random().toString(36).slice(-8)
|
11
|
+
view.View = view.view?.toFunction() or ELA.Views.GraphView
|
12
|
+
view
|
13
|
+
|
14
|
+
@subviews = {}
|
15
|
+
|
16
|
+
render: ->
|
17
|
+
@$el.empty()
|
18
|
+
for view in @views
|
19
|
+
options = _.extend
|
20
|
+
model: @model
|
21
|
+
parentView: this
|
22
|
+
localePrefix: @localePrefix
|
23
|
+
, view.options
|
24
|
+
view = @subviews[view.options.name] ?= new view.View(options)
|
25
|
+
@$el.append(view.render().el)
|
26
|
+
this
|
@@ -26,17 +26,7 @@
|
|
26
26
|
%button.button.poised.copy
|
27
27
|
- if @hasHelpText
|
28
28
|
%li.help= t('contextMenu.help')
|
29
|
-
|
30
|
-
- if @legendView
|
31
|
-
.legend
|
32
|
-
- if @graphOverlayView
|
33
|
-
.graph-overlay-wrapper
|
34
|
-
.graph-overlay
|
35
|
-
- if @graphView
|
36
|
-
.graph
|
37
|
-
- if @rangeHandlerView
|
38
|
-
.range-handler
|
29
|
+
.viewport
|
39
30
|
%a{ href: ELA.settings.upstream.url, target: '_blank' }
|
40
31
|
%img.logo{ src: 'images/logo.png' }
|
41
|
-
|
42
|
-
%aside.right.headup
|
32
|
+
%aside.right.headup
|
data/ela.gemspec
CHANGED
@@ -46,5 +46,5 @@ Gem::Specification.new do |spec|
|
|
46
46
|
spec.add_dependency "jasmine", "~> 2.9", ">= 2.9.0"
|
47
47
|
spec.add_dependency "rake", "~> 10.5", ">= 10.5.0"
|
48
48
|
spec.add_dependency "uglifier", "~> 4.1", ">= 4.1.5"
|
49
|
-
spec.add_dependency "andand"
|
49
|
+
spec.add_dependency "andand", "~> 1.3", ">= 1.3.3"
|
50
50
|
end
|
data/lib/ela/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ela
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Franz Kißig
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
11
|
+
date: 2018-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -342,16 +342,22 @@ dependencies:
|
|
342
342
|
name: andand
|
343
343
|
requirement: !ruby/object:Gem::Requirement
|
344
344
|
requirements:
|
345
|
+
- - "~>"
|
346
|
+
- !ruby/object:Gem::Version
|
347
|
+
version: '1.3'
|
345
348
|
- - ">="
|
346
349
|
- !ruby/object:Gem::Version
|
347
|
-
version:
|
350
|
+
version: 1.3.3
|
348
351
|
type: :runtime
|
349
352
|
prerelease: false
|
350
353
|
version_requirements: !ruby/object:Gem::Requirement
|
351
354
|
requirements:
|
355
|
+
- - "~>"
|
356
|
+
- !ruby/object:Gem::Version
|
357
|
+
version: '1.3'
|
352
358
|
- - ">="
|
353
359
|
- !ruby/object:Gem::Version
|
354
|
-
version:
|
360
|
+
version: 1.3.3
|
355
361
|
description:
|
356
362
|
email:
|
357
363
|
- fkissig@velalu.qa
|
@@ -422,7 +428,9 @@ files:
|
|
422
428
|
- app/js/lib/models/base_subapp_container.coffee
|
423
429
|
- app/js/lib/models/curve.coffee
|
424
430
|
- app/js/lib/router.coffee
|
431
|
+
- app/js/lib/views/1_viewport_view.coffee
|
425
432
|
- app/js/lib/views/app.coffee
|
433
|
+
- app/js/lib/views/axis_handler.coffee
|
426
434
|
- app/js/lib/views/base_app.coffee
|
427
435
|
- app/js/lib/views/base_aside.coffee
|
428
436
|
- app/js/lib/views/base_graph.coffee
|
@@ -431,16 +439,17 @@ files:
|
|
431
439
|
- app/js/lib/views/curve_graph.coffee
|
432
440
|
- app/js/lib/views/curves_aside.coffee
|
433
441
|
- app/js/lib/views/curves_list_item.coffee
|
442
|
+
- app/js/lib/views/graph_view.coffee
|
434
443
|
- app/js/lib/views/grouped_parameters_aside.coffee
|
435
444
|
- app/js/lib/views/headup.coffee
|
436
445
|
- app/js/lib/views/help.coffee
|
437
446
|
- app/js/lib/views/interpolated_graph.coffee
|
438
447
|
- app/js/lib/views/legend.coffee
|
439
|
-
- app/js/lib/views/legend_handler.coffee
|
440
448
|
- app/js/lib/views/overview.coffee
|
441
449
|
- app/js/lib/views/overview_tile.coffee
|
442
450
|
- app/js/lib/views/parameters_aside.coffee
|
443
451
|
- app/js/lib/views/three_graph.coffee
|
452
|
+
- app/js/lib/views/viewport.coffee
|
444
453
|
- app/js/vendor/Markdown.Converter.js
|
445
454
|
- app/js/vendor/Markdown.Extra.js
|
446
455
|
- app/js/vendor/Markdown.Toc.coffee
|
@@ -674,7 +683,6 @@ files:
|
|
674
683
|
- dist/app_js/lib/views/help.js
|
675
684
|
- dist/app_js/lib/views/interpolated_graph.js
|
676
685
|
- dist/app_js/lib/views/legend.js
|
677
|
-
- dist/app_js/lib/views/legend_handler.js
|
678
686
|
- dist/app_js/lib/views/overview.js
|
679
687
|
- dist/app_js/lib/views/overview_tile.js
|
680
688
|
- dist/app_js/lib/views/parameters_aside.js
|
@@ -4358,7 +4366,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
4358
4366
|
version: '0'
|
4359
4367
|
requirements: []
|
4360
4368
|
rubyforge_project:
|
4361
|
-
rubygems_version: 2.
|
4369
|
+
rubygems_version: 2.7.3
|
4362
4370
|
signing_key:
|
4363
4371
|
specification_version: 4
|
4364
4372
|
summary: HTML5 E-Learning Framework
|
@@ -1,51 +0,0 @@
|
|
1
|
-
ELA.Views ?= {}
|
2
|
-
class ELA.Views.LegendHandler extends Backbone.Poised.View
|
3
|
-
events:
|
4
|
-
'pan': 'updateRange'
|
5
|
-
'tap': 'updateRange'
|
6
|
-
|
7
|
-
hammerjs:
|
8
|
-
recognizers: [
|
9
|
-
[Hammer.Rotate, { enable: false }],
|
10
|
-
[Hammer.Pinch, { enable: false }, ['rotate']],
|
11
|
-
[Hammer.Swipe, { enable: false }],
|
12
|
-
[Hammer.Pan, { direction: Hammer.DIRECTION_ALL, threshold: 1 }, ['swipe']],
|
13
|
-
[Hammer.Tap, { threshold: 5 }],
|
14
|
-
[Hammer.Press, { enable: false }]
|
15
|
-
]
|
16
|
-
|
17
|
-
initialize: (options) ->
|
18
|
-
super
|
19
|
-
@axis = options.axis or 'x'
|
20
|
-
@attribute = options.attribute or @axis
|
21
|
-
@precision = @model.get('valueAtRangePrecision') # TODO: Make this obsolete
|
22
|
-
@precision ?= options.precision
|
23
|
-
@precision ?= 2
|
24
|
-
|
25
|
-
@listenTo @model, "change:#{@attribute}", @renderText
|
26
|
-
|
27
|
-
updateRange: (e) =>
|
28
|
-
origin = @model.displayParams.get("#{@axis}Origin")
|
29
|
-
range = @model.displayParams.get("#{@axis}Range")
|
30
|
-
if @axis is 'x'
|
31
|
-
width = @model.displayParams.get('width')
|
32
|
-
point = (range / width) * (e.gesture.pointers[0].clientX - origin)
|
33
|
-
else
|
34
|
-
height = @model.displayParams.get('height')
|
35
|
-
y = e.gesture.pointers[0].clientY - @$el.offset().top
|
36
|
-
y = Math.min(Math.max(y, 0), height)
|
37
|
-
point = (range / height) * (origin - y)
|
38
|
-
|
39
|
-
pow = Math.pow(10, @precision)
|
40
|
-
point = Math.round(point * pow) / pow
|
41
|
-
@model.set(@attribute, point)
|
42
|
-
|
43
|
-
renderText: =>
|
44
|
-
@$el.find('span').text(t(@model.name + '.legendHandler.label', 'legendHandler.label', value: @model.get(@attribute).toFixed(@precision)))
|
45
|
-
|
46
|
-
render: =>
|
47
|
-
@$el.html('<span class="hint"></span>')
|
48
|
-
@$el.toggleClass('orientation-x', @axis is 'x')
|
49
|
-
@$el.toggleClass('orientation-y', @axis is 'y')
|
50
|
-
@renderText()
|
51
|
-
this
|