zui53 0.0.2

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.
@@ -0,0 +1,257 @@
1
+ #= require ./helper
2
+ #= require ./tools/pan_tool
3
+ #= require ./tools/zoom_tool
4
+ #= require ./surfaces/svg_surface
5
+ #= require ./surfaces/css_surface
6
+
7
+ namespace 'ZUI53', (exports)->
8
+ class exports.Viewport
9
+ constructor: (vp)->
10
+ @min_scale = null
11
+ @max_scale = null
12
+
13
+ @viewport = @styleViewport(vp)
14
+ @surfaces = []
15
+
16
+ # Offset Matrix, this should change in future, if viewport HTML-Element changes position
17
+ @updateOffset()
18
+
19
+ @reset()
20
+ $(vp).scroll (e)=>
21
+ # If the browser automatically scrolls our viewport, we translate the scroll into a pan and
22
+ # reset the scroll. Otherwise MouseFocused Zooming and @clientToSurface is broken.
23
+ # This happens when the user types into a contenteditable element and the carat moves outside
24
+ # of the viewport.
25
+ jVP = $(@viewport)
26
+ @panBy( -jVP.scrollLeft(), -jVP.scrollTop() )
27
+ jVP.scrollTop(0).scrollLeft(0)
28
+
29
+ @toolset = new ZUI53.Tools.Set( new ZUI53.Tools.Zoom(@) )
30
+
31
+ styleViewport: (vp)->
32
+ $(vp).css({
33
+ 'position': 'relative',
34
+ 'overflow': 'hidden',
35
+ 'width': '100%',
36
+ 'height': '100%'
37
+ })
38
+ vp
39
+
40
+ updateOffset: ()=>
41
+ @vpOffset = $(@viewport).offset()
42
+
43
+ @vpOffset.left -= (Number) $(window.document).scrollLeft()
44
+ @vpOffset.top -= (Number) $(window.document).scrollTop()
45
+
46
+ @vpOffM = $M([
47
+ [1, 0, @vpOffset.left],
48
+ [0, 1, @vpOffset.top],
49
+ [0, 0, 1]
50
+ ])
51
+
52
+ return @vpOffM
53
+
54
+ reset: ()=>
55
+ @zoomPos = 0
56
+ @scale = 1.0
57
+ # Base Transformation Matrix for Scale/Pan and Point-Calculation
58
+ @surfaceM = $M([
59
+ [1, 0, 0],
60
+ [0, 1, 0],
61
+ [0, 0, 1]
62
+ ])
63
+ @updateSurface()
64
+
65
+ addSurface: (surface)=>
66
+ @surfaces.push surface
67
+ @addLimits(surface.limits())
68
+
69
+ removeSurface: (surface)=>
70
+ i = @surfaces.indexOf(surface)
71
+ @surfaces.splice(i, 1) if i >= 0
72
+
73
+ addLimits: (limits)=>
74
+ return unless limits
75
+ if @min_scale || @max_scale
76
+ @min_scale = Math.max(limits[0], @min_scale) if limits[0]
77
+ @max_scale = Math.min(limits[1], @max_scale) if limits[1]
78
+ else
79
+ @min_scale = limits[0]
80
+ @max_scale = limits[1]
81
+ # console.log "LIMITS: #{@min_scale}, #{@max_scale}"
82
+
83
+ clientToSurface: (x, y)=>
84
+ v = $V([x, y, 1])
85
+ sV = @surfaceM.inverse().multiply( @updateOffset().inverse().multiply(v) )
86
+
87
+ layerToSurface: (x, y)=>
88
+ v = $V([x, y, 1])
89
+ sV = @surfaceM.inverse().multiply( v )
90
+
91
+ surfaceToClient: (v)=>
92
+ @updateOffset().multiply( @surfaceM.multiply(v) )
93
+
94
+ surfaceToLayer: (v)=>
95
+ @surfaceM.multiply(v)
96
+
97
+ updateSurface: ()=>
98
+ v = @getPanAndScale()
99
+ for node in @surfaces
100
+ node.apply(v[0], v[1], v[2])
101
+
102
+ return true
103
+
104
+ panBy: (x, y)=>
105
+ @translateSurface(x, y)
106
+ @updateSurface()
107
+
108
+ zoomBy: (byF, clientX, clientY)=>
109
+ newScale = @_pos_to_scale(@zoomPos + byF)
110
+ @zoomSet(newScale, clientX, clientY)
111
+
112
+ zoomSet: (newScale, clientX, clientY)=>
113
+ newScale = @fitToLimits(newScale)
114
+ @zoomPos = @_scale_to_pos(newScale)
115
+ if newScale != @scale
116
+ sf = @clientToSurface(clientX, clientY)
117
+ scaleBy = newScale/@scale
118
+
119
+ @surfaceM = @_scaleMatrix(@surfaceM, scaleBy)
120
+ @scale = newScale
121
+
122
+ c = @surfaceToClient(sf)
123
+ dX = clientX - c.e(1)
124
+ dY = clientY - c.e(2)
125
+ @translateSurface(dX, dY)
126
+
127
+ @updateSurface()
128
+
129
+ # zoomByO: (byF, offsetX, offsetY)=>
130
+ # # @zoomPos += byF
131
+ # newScale = @_pos_to_scale(@zoomPos + byF)
132
+ # @zoomSetO(newScale, offsetX, offsetY)
133
+ #
134
+ # zoomSetO: (newScale, offsetX, offsetY)=>
135
+ # newScale = @fitToLimits(newScale)
136
+ # @zoomPos = @_scale_to_pos(newScale)
137
+ # if newScale != @scale
138
+ # sf = @layerToSurface(offsetX, offsetY)
139
+ # scaleBy = newScale/@scale
140
+ #
141
+ # @surfaceM = @_scaleMatrix(@surfaceM, scaleBy)
142
+ # @scale = newScale
143
+ #
144
+ # c = @surfaceToLayer(sf)
145
+ # dX = offsetX - c.e(1)
146
+ # dY = offsetY - c.e(2)
147
+ # @translateSurface(dX, dY)
148
+ #
149
+ # @updateSurface()
150
+
151
+
152
+ fitToLimits: (s)=>
153
+ # console.log "Try Scale: #{s}"
154
+ if @min_scale && s < @min_scale
155
+ s = @min_scale
156
+ else if @max_scale && s > @max_scale
157
+ s = @max_scale
158
+ return s
159
+
160
+ translateSurface: (x, y)=>
161
+ @surfaceM = @_translateMatrix(@surfaceM, x, y)
162
+
163
+ _translateMatrix: (m, x, y)->
164
+ m.add( $M([
165
+ [0, 0, x],
166
+ [0, 0, y],
167
+ [0, 0, 0]
168
+ ]))
169
+
170
+ _scaleMatrix: (m, s)->
171
+ return m.multiply( $M([
172
+ [s, 0, 0],
173
+ [0, s, 0],
174
+ [0, 0, 1]
175
+ ]))
176
+
177
+ _pos_to_scale: (pos)->
178
+ Math.exp(pos)
179
+
180
+ _scale_to_pos: (s)->
181
+ Math.log(s)
182
+
183
+ avp: ()=>
184
+ @updateOffset()
185
+ min = @clientToSurface(@vpOffset.left, @vpOffset.top)
186
+ max = @clientToSurface(@vpOffset.left + $(@viewport).width(), @vpOffset.top + $(@viewport).height())
187
+
188
+ del = max.subtract(min)
189
+
190
+ return {
191
+ x: min.e(1),
192
+ y: min.e(2),
193
+ width: del.e(1),
194
+ height: del.e(2)
195
+ }
196
+
197
+ _boundsCenter: (b)->
198
+ return {
199
+ x: (b.x + b.width/2),
200
+ y: (b.y + b.height/2)
201
+ }
202
+
203
+ showBounds: (evp)=>
204
+ if evp.width == 0 or evp.height == 0
205
+ return
206
+
207
+ avp = @avp()
208
+ s = Math.min(avp.width/evp.width, avp.height/evp.height)
209
+
210
+ # Expand
211
+ exp = 50/s #expand 50px, just a constant at the moment, should be variable
212
+ evp.x -= exp
213
+ evp.y -= exp
214
+ evp.width += 2*exp
215
+ evp.height += 2*exp
216
+ s = Math.min(avp.width/evp.width, avp.height/evp.height)
217
+
218
+ s = @fitToLimits(s)
219
+ eC = @_boundsCenter(evp)
220
+ aC = @_boundsCenter(avp)
221
+
222
+ @setPanAndScale(-eC.x*s, -eC.y*s, s)
223
+ @translateSurface( $(@viewport).width()/2, $(@viewport).height()/2) # Center
224
+
225
+ @updateSurface()
226
+
227
+ getPanAndScale: ()=>
228
+ [@surfaceM.e(1, 3), @surfaceM.e(2, 3), @surfaceM.e(1, 1)]
229
+
230
+ setPanAndScale: (panX, panY, scale)=>
231
+ @surfaceM = $M([
232
+ [1, 0, 0],
233
+ [0, 1, 0],
234
+ [0, 0, 1]
235
+ ])
236
+
237
+ @translateSurface(panX, panY)
238
+ @surfaceM = @_scaleMatrix(@surfaceM, scale)
239
+ @scale = scale
240
+ @zoomPos = @_scale_to_pos(scale)
241
+
242
+ getTransformString: ()=>
243
+ @getPanAndScale().join(',')
244
+
245
+ setTransformString: (str)=>
246
+ return unless str
247
+ v = str.split(',')
248
+ # console.log v.length
249
+ # return unless v.length == 3
250
+ panX = (Number) v[0]
251
+ panY = (Number) v[1]
252
+ scale = (Number) v[2]
253
+ @setPanAndScale(panX, panY, scale)
254
+ @updateSurface()
255
+
256
+
257
+
@@ -0,0 +1,21 @@
1
+ module Zui53
2
+ class InstallGenerator < Rails::Generators::Base
3
+ desc "Copies zui53 assets"
4
+ source_root File.expand_path('../../../../build', __FILE__)
5
+
6
+ def copy_stylesheets_and_images
7
+ copy_file "zui53.js", "app/assets/javascripts/zui53.js"
8
+
9
+ # ["zui53.js.coffee"].each do |f|
10
+ # copy_file "javascripts/zui53/#{f}", "app/assets/javascripts/#{f}"
11
+ # end
12
+ # copy_file "images/css3buttons/css3-github-buttons-icons.png",
13
+ # "public/images/css3buttons/css3-github-buttons-icons.png"
14
+ # copy_file "stylesheets/css3buttons/css3-github-buttons.css",
15
+ # "public/stylesheets/css3buttons/css3-github-buttons.css"
16
+ # copy_file "stylesheets/css3buttons/reset.css",
17
+ # "public/stylesheets/css3buttons/reset.css"
18
+ # gsub_file "public/stylesheets/css3buttons/css3-github-buttons.css", /url\(css3buttons/, "url(/images/css3buttons"
19
+ end
20
+ end
21
+ end
data/lib/zui53.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Zui53
2
+ if ::Rails.version >= "3.1"
3
+ class Engine < ::Rails::Engine
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,78 @@
1
+ /*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
2
+ * Licensed under the MIT License (LICENSE.txt).
3
+ *
4
+ * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
5
+ * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
6
+ * Thanks to: Seamus Leahy for adding deltaX and deltaY
7
+ *
8
+ * Version: 3.0.4
9
+ *
10
+ * Requires: 1.2.2+
11
+ */
12
+
13
+ (function($) {
14
+
15
+ var types = ['DOMMouseScroll', 'mousewheel'];
16
+
17
+ $.event.special.mousewheel = {
18
+ setup: function() {
19
+ if ( this.addEventListener ) {
20
+ for ( var i=types.length; i; ) {
21
+ this.addEventListener( types[--i], handler, false );
22
+ }
23
+ } else {
24
+ this.onmousewheel = handler;
25
+ }
26
+ },
27
+
28
+ teardown: function() {
29
+ if ( this.removeEventListener ) {
30
+ for ( var i=types.length; i; ) {
31
+ this.removeEventListener( types[--i], handler, false );
32
+ }
33
+ } else {
34
+ this.onmousewheel = null;
35
+ }
36
+ }
37
+ };
38
+
39
+ $.fn.extend({
40
+ mousewheel: function(fn) {
41
+ return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
42
+ },
43
+
44
+ unmousewheel: function(fn) {
45
+ return this.unbind("mousewheel", fn);
46
+ }
47
+ });
48
+
49
+
50
+ function handler(event) {
51
+ var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
52
+ event = $.event.fix(orgEvent);
53
+ event.type = "mousewheel";
54
+
55
+ // Old school scrollwheel delta
56
+ if ( event.wheelDelta ) { delta = event.wheelDelta/120; }
57
+ if ( event.detail ) { delta = -event.detail/3; }
58
+
59
+ // New school multidimensional scroll (touchpads) deltas
60
+ deltaY = delta;
61
+
62
+ // Gecko
63
+ if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
64
+ deltaY = 0;
65
+ deltaX = -1*delta;
66
+ }
67
+
68
+ // Webkit
69
+ if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; }
70
+ if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; }
71
+
72
+ // Add event and delta to the front of the arguments
73
+ args.unshift(event, delta, deltaX, deltaY);
74
+
75
+ return $.event.handle.apply(this, args);
76
+ }
77
+
78
+ })(jQuery);