/adei/ui

To get this branch, use:
bzr branch http://darksoft.org/webbzr/adei/ui

« back to all changes in this revision

Viewing changes to includes/scriptaculous/extra/resizable.js

  • Committer: Suren A. Chilingaryan
  • Date: 2008-04-02 10:23:22 UTC
  • Revision ID: csa@dside.dyndns.org-20080402102322-okib92sicg2dx3o3
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
// script.aculo.us Resizables.js
 
3
 
 
4
// Copyright(c) 2007 - Orr Siloni, Comet Information Systems http://www.comet.co.il/en/
 
5
//
 
6
// Resizable.js is freely distributable under the terms of an MIT-style license.
 
7
// For details, see the script.aculo.us web site: http://script.aculo.us/
 
8
 
 
9
var Resizables = {
 
10
        instances: [],
 
11
        observers: [],
 
12
        
 
13
        register: function(resizable) {
 
14
                if(this.instances.length == 0) {
 
15
                        this.eventMouseUp   = this.endResize.bindAsEventListener(this);
 
16
                        this.eventMouseMove = this.updateResize.bindAsEventListener(this);
 
17
                        
 
18
                        Event.observe(document, "mouseup", this.eventMouseUp);
 
19
                        Event.observe(document, "mousemove", this.eventMouseMove);
 
20
                }
 
21
                this.instances.push(resizable);
 
22
        },
 
23
        
 
24
        unregister: function(resizable) {
 
25
                this.instances = this.instances.reject(function(d) { return d==resizable });
 
26
                if(this.instances.length == 0) {
 
27
                        Event.stopObserving(document, "mouseup", this.eventMouseUp);
 
28
                        Event.stopObserving(document, "mousemove", this.eventMouseMove);
 
29
                }
 
30
        },
 
31
        
 
32
        activate: function(resizable) {
 
33
                if(resizable.options.delay) { 
 
34
                        this._timeout = setTimeout(function() {
 
35
                                Resizables._timeout = null; 
 
36
                                Resizables.activeResizable = resizable; 
 
37
                        }.bind(this), resizable.options.delay); 
 
38
                } else {
 
39
                        this.activeResizable = resizable;
 
40
                }
 
41
        },
 
42
        
 
43
        deactivate: function() {
 
44
                this.activeResizable = null;
 
45
        },
 
46
        
 
47
        updateResize: function(event) {
 
48
                if(!this.activeResizable) return;
 
49
                var pointer = [Event.pointerX(event), Event.pointerY(event)];
 
50
                // Mozilla-based browsers fire successive mousemove events with
 
51
                // the same coordinates, prevent needless redrawing (moz bug?)
 
52
                if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
 
53
                this._lastPointer = pointer;
 
54
                
 
55
                this.activeResizable.updateResize(event, pointer);
 
56
        },
 
57
        
 
58
        endResize: function(event) {
 
59
                if(this._timeout) { 
 
60
                  clearTimeout(this._timeout); 
 
61
                  this._timeout = null; 
 
62
                }
 
63
                if(!this.activeResizable) return;
 
64
                this._lastPointer = null;
 
65
                this.activeResizable.endResize(event);
 
66
                this.activeResizable = null;
 
67
        },
 
68
        
 
69
        addObserver: function(observer) {
 
70
                this.observers.push(observer);
 
71
                this._cacheObserverCallbacks();
 
72
        },
 
73
  
 
74
        removeObserver: function(element) {  // element instead of observer fixes mem leaks
 
75
                this.observers = this.observers.reject( function(o) { return o.element==element });
 
76
                this._cacheObserverCallbacks();
 
77
        },
 
78
        
 
79
        notify: function(eventName, resizable, event) {  // 'onStart', 'onEnd', 'onResize'
 
80
                if(this[eventName+'Count'] > 0)
 
81
                        this.observers.each( function(o) {
 
82
                                if(o[eventName]) o[eventName](eventName, resizable, event);
 
83
                        });
 
84
                if(resizable.options[eventName]) resizable.options[eventName](resizable, event);
 
85
        },
 
86
        
 
87
        _cacheObserverCallbacks: function() {
 
88
                ['onStart','onEnd','onResize'].each( function(eventName) {
 
89
                        Resizables[eventName+'Count'] = Resizables.observers.select(
 
90
                                function(o) { return o[eventName]; }
 
91
                        ).length;
 
92
                });
 
93
        }
 
94
}
 
95
 
 
96
var Resizable = Class.create();
 
97
Resizable._resizing = {};
 
98
 
 
99
Resizable.prototype = {
 
100
        initialize: function(element){
 
101
                var defaults = {
 
102
                        handle: false,
 
103
                        snap: false,  // false, or xy or [x,y] or function(x,y){ return [x,y] }
 
104
                        delay: 0,
 
105
                        minHeight: false,
 
106
                        minwidth: false,
 
107
                        maxHeight: false,
 
108
                        maxWidth: false
 
109
                }
 
110
                
 
111
                this.element = $(element);
 
112
                
 
113
                var options = Object.extend(defaults, arguments[1] || {});
 
114
                if(options.handle && typeof options.handle == 'string')
 
115
                        this.handle = $(options.handle);
 
116
                if(!this.handle) this.handle = this.element;
 
117
                
 
118
                this.options  = options;
 
119
                this.dragging = false;
 
120
                
 
121
                this.eventMouseDown = this.initResize.bindAsEventListener(this);
 
122
                Event.observe(this.handle, "mousedown", this.eventMouseDown);
 
123
                
 
124
                Resizables.register(this);
 
125
        },
 
126
        
 
127
        destroy: function() {
 
128
                Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
 
129
        },
 
130
        
 
131
        currentDelta: function() {
 
132
                return([
 
133
                        parseInt(Element.getStyle(this.element,'width') || '0'),
 
134
                        parseInt(Element.getStyle(this.element,'height') || '0')]);
 
135
        },
 
136
        
 
137
        initResize: function(event) {
 
138
                if(typeof Resizable._resizing[this.element] != 'undefined' &&
 
139
                        Resizable._resizing[this.element]) return;
 
140
                if(Event.isLeftClick(event)) {
 
141
                        // abort on form elements, fixes a Firefox issue
 
142
                        var src = Event.element(event);
 
143
                        if((tag_name = src.tagName.toUpperCase()) && (
 
144
                                tag_name=='INPUT' || tag_name=='SELECT' || tag_name=='OPTION' ||
 
145
                                tag_name=='BUTTON' || tag_name=='TEXTAREA')) return;
 
146
                        
 
147
                        this.pointer = [Event.pointerX(event), Event.pointerY(event)];
 
148
                        this.size = [parseInt(this.element.getStyle('width')) || 0, parseInt(this.element.getStyle('height')) || 0];
 
149
                        
 
150
                        Resizables.activate(this);
 
151
                        Event.stop(event);
 
152
                }
 
153
        },
 
154
        
 
155
        startResize: function(event) {
 
156
                this.resizing = true;
 
157
                if(this.options.zindex) {
 
158
                        this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
 
159
                        this.element.style.zIndex = this.options.zindex;
 
160
                }
 
161
                Resizables.notify('onStart', this, event);
 
162
                Resizable._resizing[this.element] = true;
 
163
        },
 
164
        
 
165
        updateResize: function(event, pointer) {
 
166
                if(!this.resizing) this.startResize(event);
 
167
                
 
168
                Resizables.notify('onResize', this, event);
 
169
                
 
170
                this.draw(pointer);
 
171
                if(this.options.change) this.options.change(this);
 
172
                
 
173
                // fix AppleWebKit rendering
 
174
                if(Prototype.Browser.WebKit) window.scrollBy(0,0);
 
175
                Event.stop(event);
 
176
        },
 
177
        
 
178
        finishResize: function(event, success) {
 
179
                this.resizing = false;
 
180
                Resizables.notify('onEnd', this, event);
 
181
                if(this.options.zindex) this.element.style.zIndex = this.originalZ;
 
182
                Resizable._resizing[this.element] = false;
 
183
                Resizables.deactivate(this);
 
184
        },
 
185
        
 
186
        endResize: function(event) {
 
187
                if(!this.resizing) return;
 
188
                this.finishResize(event, true);
 
189
                Event.stop(event);
 
190
        },
 
191
        
 
192
        draw: function(point) {
 
193
                var p = [0,1].map(function(i){ 
 
194
                        return (this.size[i] + point[i] - this.pointer[i]);
 
195
                }.bind(this));
 
196
                
 
197
                if(this.options.snap) {
 
198
                        if(typeof this.options.snap == 'function') {
 
199
                                p = this.options.snap(p[0],p[1],this);
 
200
                        } else {
 
201
                                if(this.options.snap instanceof Array) {
 
202
                                p = p.map( function(v, i) {
 
203
                                return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
 
204
                        } else {
 
205
                                p = p.map( function(v) {
 
206
                                return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
 
207
                        }
 
208
                }}
 
209
                
 
210
                if (this.options.minWidth && p[0] <= this.options.minWidth) p[0] = this.options.minWidth;
 
211
                if (this.options.maxWidth && p[0] >= this.options.maxWidth) p[0] = this.options.maxWidth;
 
212
                if (this.options.minHeight && p[1] <= this.options.minHeight) p[1] = this.options.minHeight;
 
213
                if (this.options.maxHeight && p[1] >= this.options.maxHeight) p[1] = this.options.maxHeight;
 
214
                
 
215
                var style = this.element.style;
 
216
                if((!this.options.constraint) || (this.options.constraint=='horizontal')){
 
217
                        style.width = p[0] + "px";
 
218
                }
 
219
                if((!this.options.constraint) || (this.options.constraint=='vertical')){
 
220
                        style.height = p[1] + "px";
 
221
                }
 
222
                
 
223
                if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
 
224
        }
 
225
};