Mercurial > hg > soundsoftware-site
comparison vendor/plugins/redmine_checkout/assets/javascripts/ZeroClipboard.js @ 16:020926a36823 yuya
* Add redmine-checkout plugin (as of svn rev 179 of the plugin)
author | Chris Cannam |
---|---|
date | Wed, 25 Aug 2010 16:39:01 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:9c6c72729d91 | 16:020926a36823 |
---|---|
1 // Simple Set Clipboard System | |
2 // Author: Joseph Huckaby | |
3 | |
4 var ZeroClipboard = { | |
5 | |
6 version: "1.0.7", | |
7 clients: {}, // registered upload clients on page, indexed by id | |
8 moviePath: 'ZeroClipboard.swf', // URL to movie | |
9 nextId: 1, // ID of next movie | |
10 | |
11 $: function(thingy) { | |
12 // simple DOM lookup utility function | |
13 if (typeof(thingy) == 'string') thingy = document.getElementById(thingy); | |
14 if (!thingy.addClass) { | |
15 // extend element with a few useful methods | |
16 thingy.hide = function() { this.style.display = 'none'; }; | |
17 thingy.show = function() { this.style.display = ''; }; | |
18 thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; }; | |
19 thingy.removeClass = function(name) { | |
20 var classes = this.className.split(/\s+/); | |
21 var idx = -1; | |
22 for (var k = 0; k < classes.length; k++) { | |
23 if (classes[k] == name) { idx = k; k = classes.length; } | |
24 } | |
25 if (idx > -1) { | |
26 classes.splice( idx, 1 ); | |
27 this.className = classes.join(' '); | |
28 } | |
29 return this; | |
30 }; | |
31 thingy.hasClass = function(name) { | |
32 return !!this.className.match( new RegExp("\\s*" + name + "\\s*") ); | |
33 }; | |
34 } | |
35 return thingy; | |
36 }, | |
37 | |
38 setMoviePath: function(path) { | |
39 // set path to ZeroClipboard.swf | |
40 this.moviePath = path; | |
41 }, | |
42 | |
43 dispatch: function(id, eventName, args) { | |
44 // receive event from flash movie, send to client | |
45 var client = this.clients[id]; | |
46 if (client) { | |
47 client.receiveEvent(eventName, args); | |
48 } | |
49 }, | |
50 | |
51 register: function(id, client) { | |
52 // register new client to receive events | |
53 this.clients[id] = client; | |
54 }, | |
55 | |
56 getDOMObjectPosition: function(obj, stopObj) { | |
57 // get absolute coordinates for dom element | |
58 var info = { | |
59 left: 0, | |
60 top: 0, | |
61 width: obj.width ? obj.width : obj.offsetWidth, | |
62 height: obj.height ? obj.height : obj.offsetHeight | |
63 }; | |
64 | |
65 while (obj && (obj != stopObj)) { | |
66 info.left += obj.offsetLeft; | |
67 info.top += obj.offsetTop; | |
68 obj = obj.offsetParent; | |
69 } | |
70 | |
71 return info; | |
72 }, | |
73 | |
74 Client: function(elem) { | |
75 // constructor for new simple upload client | |
76 this.handlers = {}; | |
77 | |
78 // unique ID | |
79 this.id = ZeroClipboard.nextId++; | |
80 this.movieId = 'ZeroClipboardMovie_' + this.id; | |
81 | |
82 // register client with singleton to receive flash events | |
83 ZeroClipboard.register(this.id, this); | |
84 | |
85 // create movie | |
86 if (elem) this.glue(elem); | |
87 } | |
88 }; | |
89 | |
90 ZeroClipboard.Client.prototype = { | |
91 | |
92 id: 0, // unique ID for us | |
93 ready: false, // whether movie is ready to receive events or not | |
94 movie: null, // reference to movie object | |
95 clipText: '', // text to copy to clipboard | |
96 handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor | |
97 cssEffects: true, // enable CSS mouse effects on dom container | |
98 handlers: null, // user event handlers | |
99 | |
100 glue: function(elem, appendElem, stylesToAdd) { | |
101 // glue to DOM element | |
102 // elem can be ID or actual DOM element object | |
103 this.domElement = ZeroClipboard.$(elem); | |
104 | |
105 // float just above object, or zIndex 99 if dom element isn't set | |
106 var zIndex = 99; | |
107 if (this.domElement.style.zIndex) { | |
108 zIndex = parseInt(this.domElement.style.zIndex, 10) + 1; | |
109 } | |
110 | |
111 if (typeof(appendElem) == 'string') { | |
112 appendElem = ZeroClipboard.$(appendElem); | |
113 } | |
114 else if (typeof(appendElem) == 'undefined') { | |
115 appendElem = document.getElementsByTagName('body')[0]; | |
116 } | |
117 | |
118 // find X/Y position of domElement | |
119 var box = ZeroClipboard.getDOMObjectPosition(this.domElement, appendElem); | |
120 | |
121 // create floating DIV above element | |
122 this.div = document.createElement('div'); | |
123 var style = this.div.style; | |
124 style.position = 'absolute'; | |
125 style.left = '' + box.left + 'px'; | |
126 style.top = '' + box.top + 'px'; | |
127 style.width = '' + box.width + 'px'; | |
128 style.height = '' + box.height + 'px'; | |
129 style.zIndex = zIndex; | |
130 | |
131 if (typeof(stylesToAdd) == 'object') { | |
132 for (addedStyle in stylesToAdd) { | |
133 style[addedStyle] = stylesToAdd[addedStyle]; | |
134 } | |
135 } | |
136 | |
137 // style.backgroundColor = '#f00'; // debug | |
138 | |
139 appendElem.appendChild(this.div); | |
140 | |
141 this.div.innerHTML = this.getHTML( box.width, box.height ); | |
142 }, | |
143 | |
144 getHTML: function(width, height) { | |
145 // return HTML for movie | |
146 var html = ''; | |
147 var flashvars = 'id=' + this.id + | |
148 '&width=' + width + | |
149 '&height=' + height; | |
150 | |
151 if (navigator.userAgent.match(/MSIE/)) { | |
152 // IE gets an OBJECT tag | |
153 var protocol = location.href.match(/^https/i) ? 'https://' : 'http://'; | |
154 html += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="'+protocol+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="'+width+'" height="'+height+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+flashvars+'"/><param name="wmode" value="transparent"/></object>'; | |
155 } | |
156 else { | |
157 // all other browsers get an EMBED tag | |
158 html += '<embed id="'+this.movieId+'" src="'+ZeroClipboard.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+width+'" height="'+height+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+flashvars+'" wmode="transparent" />'; | |
159 } | |
160 return html; | |
161 }, | |
162 | |
163 hide: function() { | |
164 // temporarily hide floater offscreen | |
165 if (this.div) { | |
166 this.div.style.left = '-2000px'; | |
167 } | |
168 }, | |
169 | |
170 show: function() { | |
171 // show ourselves after a call to hide() | |
172 this.reposition(); | |
173 }, | |
174 | |
175 destroy: function() { | |
176 // destroy control and floater | |
177 if (this.domElement && this.div) { | |
178 this.hide(); | |
179 this.div.innerHTML = ''; | |
180 | |
181 var body = document.getElementsByTagName('body')[0]; | |
182 try { body.removeChild( this.div ); } catch(e) {;} | |
183 | |
184 this.domElement = null; | |
185 this.div = null; | |
186 } | |
187 }, | |
188 | |
189 reposition: function(elem) { | |
190 // reposition our floating div, optionally to new container | |
191 // warning: container CANNOT change size, only position | |
192 if (elem) { | |
193 this.domElement = ZeroClipboard.$(elem); | |
194 if (!this.domElement) this.hide(); | |
195 } | |
196 | |
197 if (this.domElement && this.div) { | |
198 var box = ZeroClipboard.getDOMObjectPosition(this.domElement); | |
199 var style = this.div.style; | |
200 style.left = '' + box.left + 'px'; | |
201 style.top = '' + box.top + 'px'; | |
202 } | |
203 }, | |
204 | |
205 setText: function(newText) { | |
206 // set text to be copied to clipboard | |
207 this.clipText = newText; | |
208 if (this.ready) this.movie.setText(newText); | |
209 }, | |
210 | |
211 addEventListener: function(eventName, func) { | |
212 // add user event listener for event | |
213 // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel | |
214 eventName = eventName.toString().toLowerCase().replace(/^on/, ''); | |
215 if (!this.handlers[eventName]) this.handlers[eventName] = []; | |
216 this.handlers[eventName].push(func); | |
217 }, | |
218 | |
219 setHandCursor: function(enabled) { | |
220 // enable hand cursor (true), or default arrow cursor (false) | |
221 this.handCursorEnabled = enabled; | |
222 if (this.ready) this.movie.setHandCursor(enabled); | |
223 }, | |
224 | |
225 setCSSEffects: function(enabled) { | |
226 // enable or disable CSS effects on DOM container | |
227 this.cssEffects = !!enabled; | |
228 }, | |
229 | |
230 receiveEvent: function(eventName, args) { | |
231 // receive event from flash | |
232 eventName = eventName.toString().toLowerCase().replace(/^on/, ''); | |
233 | |
234 // special behavior for certain events | |
235 switch (eventName) { | |
236 case 'load': | |
237 // movie claims it is ready, but in IE this isn't always the case... | |
238 // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function | |
239 this.movie = document.getElementById(this.movieId); | |
240 if (!this.movie) { | |
241 var self = this; | |
242 setTimeout( function() { self.receiveEvent('load', null); }, 1 ); | |
243 return; | |
244 } | |
245 | |
246 // firefox on pc needs a "kick" in order to set these in certain cases | |
247 if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) { | |
248 var self = this; | |
249 setTimeout( function() { self.receiveEvent('load', null); }, 100 ); | |
250 this.ready = true; | |
251 return; | |
252 } | |
253 | |
254 this.ready = true; | |
255 this.movie.setText( this.clipText ); | |
256 this.movie.setHandCursor( this.handCursorEnabled ); | |
257 break; | |
258 | |
259 case 'mouseover': | |
260 if (this.domElement && this.cssEffects) { | |
261 this.domElement.addClass('hover'); | |
262 if (this.recoverActive) this.domElement.addClass('active'); | |
263 } | |
264 break; | |
265 | |
266 case 'mouseout': | |
267 if (this.domElement && this.cssEffects) { | |
268 this.recoverActive = false; | |
269 if (this.domElement.hasClass('active')) { | |
270 this.domElement.removeClass('active'); | |
271 this.recoverActive = true; | |
272 } | |
273 this.domElement.removeClass('hover'); | |
274 } | |
275 break; | |
276 | |
277 case 'mousedown': | |
278 if (this.domElement && this.cssEffects) { | |
279 this.domElement.addClass('active'); | |
280 } | |
281 break; | |
282 | |
283 case 'mouseup': | |
284 if (this.domElement && this.cssEffects) { | |
285 this.domElement.removeClass('active'); | |
286 this.recoverActive = false; | |
287 } | |
288 break; | |
289 } // switch eventName | |
290 | |
291 if (this.handlers[eventName]) { | |
292 for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) { | |
293 var func = this.handlers[eventName][idx]; | |
294 | |
295 if (typeof(func) == 'function') { | |
296 // actual function reference | |
297 func(this, args); | |
298 } | |
299 else if ((typeof(func) == 'object') && (func.length == 2)) { | |
300 // PHP style object + method, i.e. [myObject, 'myMethod'] | |
301 func[0][ func[1] ](this, args); | |
302 } | |
303 else if (typeof(func) == 'string') { | |
304 // name of function | |
305 window[func](this, args); | |
306 } | |
307 } // foreach event handler defined | |
308 } // user defined handler for event | |
309 } | |
310 | |
311 }; |