javod.com
May
2010
25
zeroclipboard: Get javascript events firing after AJAX request

An interesting problem I came across recently was trying to get Zero Clipboard to work in an AJAX loaded div. Zero Clipboard is pretty much the only way to copy text to the user's clipboard that works across browsers. There is no native way to do this, so it floats an invisible movie on top of a DOM element. Yes, your users need to have Flash installed for this to work.

The issue is as follows:

  1. We need zeroclipboard available on a page that is loaded via ajax inside a div.
  2. Javascript events are not bound in an ajax call unless specifically loaded by an onclick, onload etc...
  3. The scripts themselves need to exist outside of the ajax loaded page to be loaded during page load.

At the time of this writing zeroclipboard is on version 1.0.7

As the documentation notes, the ZeroClipboard.swf file by default is sought for in the same directory as the webpage, and this tutorial assumes that it is.

Let's say we have two pages: index.html and ajaxload.html

The default example for zeroclipboard:

<html>
	<head>
		<style type="text/css">
			#d_clip_button {
				text-align:center; 
				border:1px solid black; 
				background-color:#ccc; 
				margin:10px; padding:10px; 
			}
			#d_clip_button.hover { background-color:#eee; }
			#d_clip_button.active { background-color:#aaa; }
		</style>
	</head>
	<body>
		<script type="text/javascript" src="ZeroClipboard.js"></script>
                
		Copy to Clipboard: <input type="text" id="clip_text" size="40" value="Copy me!"/>
        
		<div id="d_clip_button">Copy To Clipboard</div>
        
		<script language="JavaScript">
			var clip = new ZeroClipboard.Client();
                        
			clip.setText( '' ); // will be set later on mouseDown
			clip.setHandCursor( true );
			clip.setCSSEffects( true );
                        
			clip.addEventListener( 'load', function(client) {
				// alert( "movie is loaded" );
			} );
                        
			clip.addEventListener( 'complete', function(client, text) {
				alert("Copied text to clipboard: " + text );
			} );
                        
			clip.addEventListener( 'mouseOver', function(client) {
				// alert("mouse over"); 
			} );
                        
			clip.addEventListener( 'mouseOut', function(client) { 
				// alert("mouse out"); 
			} );
                        
			clip.addEventListener( 'mouseDown', function(client) { 
				// set text to copy here
				clip.setText( document.getElementById('clip_text').value );
                                
				// alert("mouse down"); 
			} );
                        
			clip.addEventListener( 'mouseUp', function(client) { 
				// alert("mouse up"); 
			} );
                        
			clip.glue( 'd_clip_button' );
		</script>
	</body>
</html>

For our purposes we're going to make a couple of changes.
index.html:

<html>
	<head>
		<style type="text/css">
			#d_clip_button {
				text-align:center; 
				border:1px solid black; 
				background-color:#ccc; 
				margin:10px; padding:10px; 
			}
			#d_clip_button.hover { background-color:#eee; }
			#d_clip_button.active { background-color:#aaa; }
		</style>

       <!-- We're moving the main javascript file to the head section -->
       <script type="text/javascript" src="ZeroClipboard.js"></script>
		<!-- We're also taking the following code and wrapping it in a function to call later -->
		<script language="JavaScript">
		function clipit(){
			var clip = new ZeroClipboard.Client();
                        
			clip.setText( '' ); // will be set later on mouseDown
			clip.setHandCursor( true );
			clip.setCSSEffects( true );
                        
			clip.addEventListener( 'load', function(client) {
				// alert( "movie is loaded" );
			} );
                        
			clip.addEventListener( 'complete', function(client, text) {
				alert("Copied text to clipboard: " + text );
			} );
                        
			clip.addEventListener( 'mouseOver', function(client) {
				// alert("mouse over"); 
			} );
                        
			clip.addEventListener( 'mouseOut', function(client) { 
				// alert("mouse out"); 
			} );
                        
			clip.addEventListener( 'mouseDown', function(client) { 
				// set text to copy here
				clip.setText( document.getElementById('clip_text').value );
                                
				// alert("mouse down"); 
			} );
                        
			clip.addEventListener( 'mouseUp', function(client) { 
				// alert("mouse up"); 
			} );
                        
			clip.glue( 'd_clip_button' );
		}
		</script>

	</head>
	<body>
		<!-- We're adding the div where we will load our ajax file -->
		<div id="loadPageHere"></div>	
	</body>
</html>

ajaxload.html:

Copy to Clipboard: <input type="text" id="clip_text" size="40" value="Copy me!"/>
<div id="d_clip_button">Copy To Clipboard</div>

<!-- Here's the tricky part -->
<!-- We need to load our function after the ajax call, but we can't use a body tag, and divs don't allow the onload attribute -->
<!-- The hack here is to use a 1px x 1px image  and use the onload function available in the img tag to load our function -->
<img src="blank.gif" onload="clipit();" />

So that's the way to use zeroclipboard in an AJAX call. Please note that I did not include the ajax code that actually loads ajaxload.php in the index's div. I assume if you're having this problem you've probably already come that far. If you do need help with that though, just ask!

If you have any questions, problems or suggestions feel free to leave a comment.

thursday, 3rd june

Cameron


I just wanna know when this site officially turned into Nerdfest?!? Gone are the usual quips, ruminations and ramblings... replaced with CODE! :)
tuesday, 3rd august

Gaurab


Thanks a lot for the trick but iam again stuck in the ajax part.
Let me explain a bit
---------------------------
I have a textarea and a button when i click on the button it calls the ajax and a new textarea is loaded and the posted data is modified by some method and load in the new textarea and what iam trying is to automatically make the ajax loaded content in the textarea copied.
tuesday, 3rd august

javod

www.javod.com
@Gaurab: I could be wrong, but I believe the browser itself prevents that as it would be a rather large security hole. (That being said, Flash overrides a lot of these things so it may be a non-issue.)

You could try and use 'load' on the event listener instead of waiting on the click event, but I don't know if that will actually work...


clip.addEventListener( 'load', function(client, text) {
alert("Copied text to clipboard: " + text );
});
wednesday, 4th august

Gaurab


Thanks for your reply javod,I have below code in my ajax loaded content


window.onload=init();
var clip = null;

function $(id) { return document.getElementById(id); }

function init() {
clip = new ZeroClipboard.Client();
clip.setHandCursor( true );
clip.addEventListener(''load'', function (client) {
alert("Flash movie loaded and ready.");
});

clip.addEventListener(''mouseOver'', function (client) {
// update the text on mouse over
clip.setText( $(''ajax_area'').value );
alert($(''ajax_area'').value);
});

clip.addEventListener(''complete'', function (client, text) {
alert("Copied text to clipboard: " + text );
});

clip.glue( ''btn_copy'', ''d_clip_container'' );
document.getElementById(''ajax_area'').select();
}


The movie is loaded fine but the "mouseOver" and "complete" event listener is not working.
 
your name: 
url: 
comment: 
  required: copy the following code to post
test