Revision 35584d80

/dev/null
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
                try {
256
                    this.movie.setText( this.clipText );
257
                } catch (err) {};
258

  
259
                try {
260
                    this.movie.setHandCursor( this.handCursorEnabled );
261
                } catch(err) {};
262

  
263
				break;
264
			
265
			case 'mouseover':
266
				if (this.domElement && this.cssEffects) {
267
					this.domElement.addClass('hover');
268
					if (this.recoverActive) this.domElement.addClass('active');
269
				}
270
				break;
271
			
272
			case 'mouseout':
273
				if (this.domElement && this.cssEffects) {
274
					this.recoverActive = false;
275
					if (this.domElement.hasClass('active')) {
276
						this.domElement.removeClass('active');
277
						this.recoverActive = true;
278
					}
279
					this.domElement.removeClass('hover');
280
				}
281
				break;
282
			
283
			case 'mousedown':
284
				if (this.domElement && this.cssEffects) {
285
					this.domElement.addClass('active');
286
				}
287
				break;
288
			
289
			case 'mouseup':
290
				if (this.domElement && this.cssEffects) {
291
					this.domElement.removeClass('active');
292
					this.recoverActive = false;
293
				}
294
				break;
295
		} // switch eventName
296
		
297
		if (this.handlers[eventName]) {
298
			for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {
299
				var func = this.handlers[eventName][idx];
300
			
301
				if (typeof(func) == 'function') {
302
					// actual function reference
303
					func(this, args);
304
				}
305
				else if ((typeof(func) == 'object') && (func.length == 2)) {
306
					// PHP style object + method, i.e. [myObject, 'myMethod']
307
					func[0][ func[1] ](this, args);
308
				}
309
				else if (typeof(func) == 'string') {
310
					// name of function
311
					window[func](this, args);
312
				}
313
			} // foreach event handler defined
314
		} // user defined handler for event
315
	}
316
	
317
};
b/ui/static/snf/js/lib/jquery.zclip.js
1
/*
2
 * zClip :: jQuery ZeroClipboard v1.1.1
3
 * http://steamdev.com/zclip
4
 *
5
 * Copyright 2011, SteamDev
6
 * Released under the MIT license.
7
 * http://www.opensource.org/licenses/mit-license.php
8
 *
9
 * Date: Wed Jun 01, 2011
10
 */
11

  
12

  
13
(function ($) {
14

  
15
    $.fn.zclip = function (params) {
16

  
17
        if (typeof params == "object" && !params.length) {
18

  
19
            var settings = $.extend({
20

  
21
                path: 'ZeroClipboard.swf',
22
                copy: null,
23
                beforeCopy: null,
24
                afterCopy: null,
25
                clickAfter: true,
26
                setHandCursor: true,
27
                setCSSEffects: true
28

  
29
            }, params);
30
			
31

  
32
            return this.each(function () {
33

  
34
                var o = $(this);
35

  
36
                if (o.is(':visible') && (typeof settings.copy == 'string' || $.isFunction(settings.copy))) {
37
                    ZeroClipboard.setMoviePath(settings.path);
38
                    var clip = new ZeroClipboard.Client();
39
                    
40
                    if($.isFunction(settings.copy)){
41
                    	o.bind('zClip_copy',settings.copy);
42
                    }
43
                    if($.isFunction(settings.beforeCopy)){
44
                    	o.bind('zClip_beforeCopy',settings.beforeCopy);
45
                    }
46
                    if($.isFunction(settings.afterCopy)){
47
                    	o.bind('zClip_afterCopy',settings.afterCopy);
48
                    }                    
49

  
50
                    clip.setHandCursor(settings.setHandCursor);
51
                    clip.setCSSEffects(settings.setCSSEffects);
52
                    clip.addEventListener('mouseOver', function (client) {
53
                        o.trigger('mouseenter');
54
                    });
55
                    clip.addEventListener('mouseOut', function (client) {
56
                        o.trigger('mouseleave');
57
                    });
58
                    clip.addEventListener('mouseDown', function (client) {
59

  
60
                        o.trigger('mousedown');
61
                        
62
			if(!$.isFunction(settings.copy)){
63
			   clip.setText(settings.copy);
64
			} else {
65
			   clip.setText(o.triggerHandler('zClip_copy'));
66
			}                        
67
                        
68
                        if ($.isFunction(settings.beforeCopy)) {
69
                            o.trigger('zClip_beforeCopy');                            
70
                        }
71

  
72
                    });
73

  
74
                    clip.addEventListener('complete', function (client, text) {
75

  
76
                        if ($.isFunction(settings.afterCopy)) {
77
                            
78
                            o.trigger('zClip_afterCopy');
79

  
80
                        } else {
81
                            if (text.length > 500) {
82
                                text = text.substr(0, 500) + "...\n\n(" + (text.length - 500) + " characters not shown)";
83
                            }
84
							
85
			    o.removeClass('hover');
86
                        }
87

  
88
                        if (settings.clickAfter) {
89
                            o.trigger('click');
90
                        }
91

  
92
                    });
93

  
94
					
95
                    clip.glue(o[0], o.parent()[0]);
96
					
97
		    $(window).bind('load resize',function(){clip.reposition();});
98
					
99

  
100
                }
101

  
102
            });
103

  
104
        } else if (typeof params == "string") {
105

  
106
            return this.each(function () {
107

  
108
                var o = $(this);
109

  
110
                params = params.toLowerCase();
111
                var zclipId = o.data('zclipId');
112
                var clipElm = $('#' + zclipId + '.zclip');
113

  
114
                if (params == "remove") {
115

  
116
                    clipElm.remove();
117
                    o.removeClass('active hover');
118

  
119
                } else if (params == "hide") {
120

  
121
                    clipElm.hide();
122
                    o.removeClass('active hover');
123

  
124
                } else if (params == "show") {
125

  
126
                    clipElm.show();
127

  
128
                }
129

  
130
            });
131

  
132
        }
133

  
134
    }	
135
	
136
	
137

  
138
})(jQuery);
139

  
140

  
141

  
142

  
143

  
144

  
145

  
146
// ZeroClipboard
147
// Simple Set Clipboard System
148
// Author: Joseph Huckaby
149
var ZeroClipboard = {
150

  
151
    version: "1.0.7",
152
    clients: {},
153
    // registered upload clients on page, indexed by id
154
    moviePath: 'ZeroClipboard.swf',
155
    // URL to movie
156
    nextId: 1,
157
    // ID of next movie
158
    $: function (thingy) {
159
        // simple DOM lookup utility function
160
        if (typeof(thingy) == 'string') thingy = document.getElementById(thingy);
161
        if (!thingy.addClass) {
162
            // extend element with a few useful methods
163
            thingy.hide = function () {
164
                this.style.display = 'none';
165
            };
166
            thingy.show = function () {
167
                this.style.display = '';
168
            };
169
            thingy.addClass = function (name) {
170
                this.removeClass(name);
171
                this.className += ' ' + name;
172
            };
173
            thingy.removeClass = function (name) {
174
                var classes = this.className.split(/\s+/);
175
                var idx = -1;
176
                for (var k = 0; k < classes.length; k++) {
177
                    if (classes[k] == name) {
178
                        idx = k;
179
                        k = classes.length;
180
                    }
181
                }
182
                if (idx > -1) {
183
                    classes.splice(idx, 1);
184
                    this.className = classes.join(' ');
185
                }
186
                return this;
187
            };
188
            thingy.hasClass = function (name) {
189
                return !!this.className.match(new RegExp("\\s*" + name + "\\s*"));
190
            };
191
        }
192
        return thingy;
193
    },
194

  
195
    setMoviePath: function (path) {
196
        // set path to ZeroClipboard.swf
197
        this.moviePath = path;
198
    },
199

  
200
    dispatch: function (id, eventName, args) {
201
        // receive event from flash movie, send to client		
202
        var client = this.clients[id];
203
        if (client) {
204
            client.receiveEvent(eventName, args);
205
        }
206
    },
207

  
208
    register: function (id, client) {
209
        // register new client to receive events
210
        this.clients[id] = client;
211
    },
212

  
213
    getDOMObjectPosition: function (obj, stopObj) {
214
        // get absolute coordinates for dom element
215
        var info = {
216
            left: 0,
217
            top: 0,
218
            width: obj.width ? obj.width : obj.offsetWidth,
219
            height: obj.height ? obj.height : obj.offsetHeight
220
        };
221

  
222
        if (obj && (obj != stopObj)) {
223
			info.left += obj.offsetLeft;
224
            info.top += obj.offsetTop;
225
        }
226

  
227
        return info;
228
    },
229

  
230
    Client: function (elem) {
231
        // constructor for new simple upload client
232
        this.handlers = {};
233

  
234
        // unique ID
235
        this.id = ZeroClipboard.nextId++;
236
        this.movieId = 'ZeroClipboardMovie_' + this.id;
237

  
238
        // register client with singleton to receive flash events
239
        ZeroClipboard.register(this.id, this);
240

  
241
        // create movie
242
        if (elem) this.glue(elem);
243
    }
244
};
245

  
246
ZeroClipboard.Client.prototype = {
247

  
248
    id: 0,
249
    // unique ID for us
250
    ready: false,
251
    // whether movie is ready to receive events or not
252
    movie: null,
253
    // reference to movie object
254
    clipText: '',
255
    // text to copy to clipboard
256
    handCursorEnabled: true,
257
    // whether to show hand cursor, or default pointer cursor
258
    cssEffects: true,
259
    // enable CSS mouse effects on dom container
260
    handlers: null,
261
    // user event handlers
262
    glue: function (elem, appendElem, stylesToAdd) {
263
        // glue to DOM element
264
        // elem can be ID or actual DOM element object
265
        this.domElement = ZeroClipboard.$(elem);
266

  
267
        // float just above object, or zIndex 99 if dom element isn't set
268
        var zIndex = 99;
269
        if (this.domElement.style.zIndex) {
270
            zIndex = parseInt(this.domElement.style.zIndex, 10) + 1;
271
        }
272

  
273
        if (typeof(appendElem) == 'string') {
274
            appendElem = ZeroClipboard.$(appendElem);
275
        } else if (typeof(appendElem) == 'undefined') {
276
            appendElem = document.getElementsByTagName('body')[0];
277
        }
278

  
279
        // find X/Y position of domElement
280
        var box = ZeroClipboard.getDOMObjectPosition(this.domElement, appendElem);
281

  
282
        // create floating DIV above element
283
        this.div = document.createElement('div');
284
        this.div.className = "zclip";
285
        this.div.id = "zclip-" + this.movieId;
286
        $(this.domElement).data('zclipId', 'zclip-' + this.movieId);
287
        var style = this.div.style;
288
        style.position = 'absolute';
289
        style.left = '' + box.left + 'px';
290
        style.top = '' + box.top + 'px';
291
        style.width = '' + box.width + 'px';
292
        style.height = '' + box.height + 'px';
293
        style.zIndex = zIndex;
294

  
295
        if (typeof(stylesToAdd) == 'object') {
296
            for (addedStyle in stylesToAdd) {
297
                style[addedStyle] = stylesToAdd[addedStyle];
298
            }
299
        }
300

  
301
        // style.backgroundColor = '#f00'; // debug
302
        appendElem.appendChild(this.div);
303

  
304
        this.div.innerHTML = this.getHTML(box.width, box.height);
305
    },
306

  
307
    getHTML: function (width, height) {
308
        // return HTML for movie
309
        var html = '';
310
        var flashvars = 'id=' + this.id + '&width=' + width + '&height=' + height;
311

  
312
        if (navigator.userAgent.match(/MSIE/)) {
313
            // IE gets an OBJECT tag
314
            var protocol = location.href.match(/^https/i) ? 'https://' : 'http://';
315
            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>';
316
        } else {
317
            // all other browsers get an EMBED tag
318
            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" />';
319
        }
320
        return html;
321
    },
322

  
323
    hide: function () {
324
        // temporarily hide floater offscreen
325
        if (this.div) {
326
            this.div.style.left = '-2000px';
327
        }
328
    },
329

  
330
    show: function () {
331
        // show ourselves after a call to hide()
332
        this.reposition();
333
    },
334

  
335
    destroy: function () {
336
        // destroy control and floater
337
        if (this.domElement && this.div) {
338
            this.hide();
339
            this.div.innerHTML = '';
340

  
341
            var body = document.getElementsByTagName('body')[0];
342
            try {
343
                body.removeChild(this.div);
344
            } catch (e) {;
345
            }
346

  
347
            this.domElement = null;
348
            this.div = null;
349
        }
350
    },
351

  
352
    reposition: function (elem) {
353
        // reposition our floating div, optionally to new container
354
        // warning: container CANNOT change size, only position
355
        if (elem) {
356
            this.domElement = ZeroClipboard.$(elem);
357
            if (!this.domElement) this.hide();
358
        }
359

  
360
        if (this.domElement && this.div) {
361
            var box = ZeroClipboard.getDOMObjectPosition(this.domElement);
362
            var style = this.div.style;
363
            style.left = '' + box.left + 'px';
364
            style.top = '' + box.top + 'px';
365
        }
366
    },
367

  
368
    setText: function (newText) {
369
        // set text to be copied to clipboard
370
        this.clipText = newText;
371
        if (this.ready) {
372
            this.movie.setText(newText);
373
        }
374
    },
375

  
376
    addEventListener: function (eventName, func) {
377
        // add user event listener for event
378
        // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel
379
        eventName = eventName.toString().toLowerCase().replace(/^on/, '');
380
        if (!this.handlers[eventName]) {
381
            this.handlers[eventName] = [];
382
        }
383
        this.handlers[eventName].push(func);
384
    },
385

  
386
    setHandCursor: function (enabled) {
387
        // enable hand cursor (true), or default arrow cursor (false)
388
        this.handCursorEnabled = enabled;
389
        if (this.ready) {
390
            this.movie.setHandCursor(enabled);
391
        }
392
    },
393

  
394
    setCSSEffects: function (enabled) {
395
        // enable or disable CSS effects on DOM container
396
        this.cssEffects = !! enabled;
397
    },
398

  
399
    receiveEvent: function (eventName, args) {
400
        // receive event from flash
401
        eventName = eventName.toString().toLowerCase().replace(/^on/, '');
402

  
403
        // special behavior for certain events
404
        switch (eventName) {
405
        case 'load':
406
            // movie claims it is ready, but in IE this isn't always the case...
407
            // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function
408
            this.movie = document.getElementById(this.movieId);
409
            if (!this.movie) {
410
                var self = this;
411
                setTimeout(function () {
412
                    self.receiveEvent('load', null);
413
                }, 1);
414
                return;
415
            }
416

  
417
            // firefox on pc needs a "kick" in order to set these in certain cases
418
            if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {
419
                var self = this;
420
                setTimeout(function () {
421
                    self.receiveEvent('load', null);
422
                }, 100);
423
                this.ready = true;
424
                return;
425
            }
426

  
427
            this.ready = true;
428
            try {
429
                this.movie.setText(this.clipText);
430
            } catch (e) {}
431
            try {
432
                this.movie.setHandCursor(this.handCursorEnabled);
433
            } catch (e) {}
434
            break;
435

  
436
        case 'mouseover':
437
            if (this.domElement && this.cssEffects) {
438
                this.domElement.addClass('hover');
439
                if (this.recoverActive) {
440
                    this.domElement.addClass('active');
441
                }
442

  
443

  
444
            }
445

  
446

  
447
            break;
448

  
449
        case 'mouseout':
450
            if (this.domElement && this.cssEffects) {
451
                this.recoverActive = false;
452
                if (this.domElement.hasClass('active')) {
453
                    this.domElement.removeClass('active');
454
                    this.recoverActive = true;
455
                }
456
                this.domElement.removeClass('hover');
457

  
458
            }
459
            break;
460

  
461
        case 'mousedown':
462
            if (this.domElement && this.cssEffects) {
463
                this.domElement.addClass('active');
464
            }
465
            break;
466

  
467
        case 'mouseup':
468
            if (this.domElement && this.cssEffects) {
469
                this.domElement.removeClass('active');
470
                this.recoverActive = false;
471
            }
472
            break;
473
        } // switch eventName
474
        if (this.handlers[eventName]) {
475
            for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {
476
                var func = this.handlers[eventName][idx];
477

  
478
                if (typeof(func) == 'function') {
479
                    // actual function reference
480
                    func(this, args);
481
                } else if ((typeof(func) == 'object') && (func.length == 2)) {
482
                    // PHP style object + method, i.e. [myObject, 'myMethod']
483
                    func[0][func[1]](this, args);
484
                } else if (typeof(func) == 'string') {
485
                    // name of function
486
                    window[func](this, args);
487
                }
488
            } // foreach event handler defined
489
        } // user defined handler for event
490
    }
491

  
492
};	
493

  
b/ui/static/snf/js/ui/web/ui_connect_view.js
38 38
        },
39 39

  
40 40
        beforeOpen: function() {
41
            this.clip = new snf.util.ClipHelper();
42
            this.connect.parent().append(this.clip.cont);
41
            this.$(".clipboard").empty();
42
        },
43

  
44
        beforeClose: function() {
45
            this.$(".clipboard").empty();
46
            try { delete this.clip; } catch (err) {};
43 47
        },
44 48

  
45 49
        handle_success: function(data) {
......
56 60
            if (!data.subinfo) { this.subinfo.hide() };
57 61
            
58 62
            if (data.ssh) {
59
                this.clip.cont.show();
60
                this.clip.setText(data.link.title);
63
                var ssh_msg = data.link.title;
64
                this.clip = new snf.util.ClipHelper(this.$(".clipboard"), ssh_msg);
61 65
            } else {
62
                this.clip.cont.hide();
63 66
            }
64 67
        },
65 68

  
b/ui/static/snf/js/ui/web/ui_create_view.js
30 30
            _.bindAll(this, 'show_password');
31 31

  
32 32
            this.password = this.$("#new-machine-password");
33
            this.copy = this.$(".clip-copy");
33
            this.copy = this.$(".clipboard");
34 34

  
35 35
            this.$(".show-machine").click(_.bind(function(){
36 36
                if (this.$(".show-machine").hasClass("in-progress")) {
......
42 42

  
43 43
            _.bindAll(this, "handle_vm_added");
44 44
            storage.vms.bind("add", this.handle_vm_added);
45
            this.password.text("");
45 46
        },
46 47

  
47 48
        handle_vm_added: function() {
......
54 55
            if (storage.vms.get(this.vm_id)) {
55 56
                this.$(".show-machine").removeClass("in-progress");
56 57
            }
58
            
59
            this.clip = new snf.util.ClipHelper(this.copy, this.pass);
57 60
        },
58 61

  
59 62
        onClose: function() {
60 63
            this.password.text("");
61 64
            this.vm_id = undefined;
65
            try { delete this.clip; } catch (err) {};
62 66
        },
63 67
        
64 68
        beforeOpen: function() {
65
            try { delete this.clipboard } catch (err) { console.log(err) };
66
            this.clipboard = new util.ClipHelper(this.copy, true);
69
            this.copy.empty();
67 70
        },
68 71
        
69 72
        onOpen: function() {
70
            this.copy.show();
71
            try {
72
                this.clipboard.setText(this.pass);
73
                this.copy.show();
74
            } catch (err) {
75
                this.copy.hide();
76
            }
73
            this.show_password();
77 74
        },
78 75

  
79 76
        show: function(pass, vm_id) {
......
81 78
            this.vm_id = vm_id;
82 79
            
83 80
            views.VMCreationPasswordView.__super__.show.apply(this, arguments);
84
            this.show_password();
85 81
        }
86 82
    })
87 83

  
b/ui/static/snf/js/ui/web/ui_icon_view.js
314 314

  
315 315
                case "mouseup":
316 316
                    logo.addClass('single-image-state4');
317
                    this.view.connect_overlay.show(this.vm);
317
                    //this.view.connect_overlay.show(this.vm);
318 318
                    break;
319 319

  
320 320
                case "mousedown":
b/ui/static/snf/js/utils.js
141 141
        // TODO: implement me
142 142
    }
143 143

  
144
    synnefo.util.ClipHelper = function(cont, clear) {
145
        this.force_empty = clear || false;
146
        this.cont = cont || $('<div class="clip-copy"></div>');
147
        this.clip = new ZeroClipboard.Client();
148
        this.clip.setHandCursor(true);
149

  
150
        this.el = this.cont;
151
        if (this.force_empty) {
152
            this.cont.empty();
153
        }
154
        this.el.append(this.clip.getHTML(20,20));
155

  
156
        this.setText = function(t) {
157
            this.clip.setText(t);
158
        }
159

  
160
        var copy_prompt = "Click to copy to clipboard";
161
        this.el.attr({title: copy_prompt});
162
        this.el.tooltip();
163
        var el = this.el;
164

  
165
        this.clip.addEventListener('complete', _.bind(function(client, text) {
166
            var tip = el.data("tooltip")
167
            tip.hide().getTip().text("Copied");
168
            
169
            window.setTimeout(function() {
170
                tip.show();
171
            }, 70)
172

  
173
            window.setTimeout(function() {
174
                tip.hide().getTip().text(copy_prompt);
175
            }, 3000)
176
        }, this));
144
    synnefo.util.ClipHelper = function(wrapper, text, settings) {
145
        settings = settings || {};
146
        this.el = $('<div class="clip-copy"></div>');
147
        wrapper.append(this.el);
148
        this.clip = $(this.el).zclip(_.extend({
149
            path: synnefo.config.js_url + "lib/ZeroClipboard.swf",
150
            copy: text
151
        }, settings));
177 152
    }
178 153

  
179 154
    synnefo.util.truncate = function(string, size, append, words) {
b/ui/templates/home.html
28 28
    <script src="{{ SYNNEFO_JS_LIB_URL}}jquery.tools.min.js"></script>
29 29
    <script src="{{ SYNNEFO_JS_LIB_URL}}jquery.dataTables.min.js"></script>
30 30
    <script src="{{ SYNNEFO_JS_LIB_URL}}jquery.pagination.js"></script>
31
    <script src="{{ SYNNEFO_JS_LIB_URL}}ZeroClipboard.js"></script>
31
    <script src="{{ SYNNEFO_JS_LIB_URL}}jquery.zclip.js"></script>
32 32

  
33 33

  
34 34
    <script src="{{ SYNNEFO_JS_LIB_URL}}underscore.js"></script>
......
74 74
        if (!window.console) {window.console = {}; window.console.log = window.console.info = window.console.debug =
75 75
            window.console.error = function() {}};
76 76
        
77
        // initialize zero clipboard
78
        ZeroClipboard.setMoviePath( '{{ SYNNEFO_JS_LIB_URL}}ZeroClipboard.swf' );
79

  
80 77
        //populate available image icons array
81 78
        var os_icons = {{image_icons|safe}};
82 79
        
......
556 553
            synnefo.ui.init();
557 554

  
558 555
            synnefo.ui.main.bind("initial", function(){
556

  
557
                $(".header-logo").click(function(e){
558
                    e.preventDefault();
559
                    synnefo.ui.main.create_vm_view.password_view.show("pass",
560
                    synnefo.storage.vms.at(0).id);
561
                })
559 562
            })
560 563

  
561 564
        })
b/ui/templates/partials/create_vm.html
251 251
    <div class="password-cont clearfix">
252 252
        <div class="password-label">{% blocktrans %}Write down your password now:{% endblocktrans %}</div>
253 253
        <div class="password" id="new-machine-password">password</div>
254
        <div class="clip-copy new-vm-password-copy"></div>
254
        <div class="clipboard new-vm-password-copy"></div>
255 255
    </div>
256 256
    <div class="description subinfo">
257 257
        <p>{% blocktrans %}You will need this later to connect to your machine.{% endblocktrans %}</p>
b/ui/templates/partials/vm_connect.html
9 9
        </div>
10 10
        <div class="connect copy-content">
11 11
            <p></p>
12
            <div class="clipboard"></div>
12 13
        </div>
13 14
        <div class="subinfo description">
14 15
            <p></p>

Also available in: Unified diff