<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-262733752711874688</id><updated>2011-11-27T15:28:38.249-08:00</updated><category term='append'/><category term='flash'/><category term='fdviewer'/><category term='fpdf'/><category term='fdview'/><category term='php'/><category term='ajax'/><category term='back button'/><category term='concatinate'/><category term='swf'/><category term='fpdi'/><category term='dsHistory'/><category term='pdf2swf'/><category term='prototype'/><category term='pdf'/><category term='merge'/><title type='text'>Zeb's Tech Blog</title><subtitle type='html'>A blog showing off some of the programming tech that I think is really cool.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://zebulonevans.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/262733752711874688/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://zebulonevans.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Zebulon "Zeb" Evans</name><uri>http://www.blogger.com/profile/15619340177510289955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_JJe9pGJctGg/R-nyLjgTpCI/AAAAAAAAADk/8zE3wdoWLh0/S220/2363541388_d2f80eee98_o.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>2</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-262733752711874688.post-6876431278952571073</id><published>2009-01-12T14:13:00.000-08:00</published><updated>2009-01-12T14:34:35.808-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='swf'/><category scheme='http://www.blogger.com/atom/ns#' term='fpdi'/><category scheme='http://www.blogger.com/atom/ns#' term='merge'/><category scheme='http://www.blogger.com/atom/ns#' term='pdf2swf'/><category scheme='http://www.blogger.com/atom/ns#' term='fdviewer'/><category scheme='http://www.blogger.com/atom/ns#' term='pdf'/><category scheme='http://www.blogger.com/atom/ns#' term='fpdf'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='flash'/><category scheme='http://www.blogger.com/atom/ns#' term='fdview'/><category scheme='http://www.blogger.com/atom/ns#' term='append'/><category scheme='http://www.blogger.com/atom/ns#' term='concatinate'/><title type='text'>View PDF Files in Flash using PHP</title><content type='html'>I'm currently working on how to view PDF files in Flash.  The first problem was that of merging or appending PDF files using PHP.  This problem was solved using FPDF &lt;a href="http://www.fpdf.org/"&gt;http://www.fpdf.org/&lt;/a&gt; with FPDI &lt;a href="http://www.setasign.de/products/pdf-php-solutions/fpdi/"&gt;http://www.setasign.de/products/pdf-php-solutions/fpdi/ &lt;/a&gt;and the following example from FPDI &lt;a href="http://www.setasign.de/products/pdf-php-solutions/fpdi/demos/concatenate-fake/"&gt;http://www.setasign.de/products/pdf-php-solutions/fpdi/demos/concatenate-fake/&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Now that we have the ability to concatenate PDF files using PHP now onto the converting PDF files to SWF Flash files with a viewer similar to the one at &lt;a href="http://www.scribd.com"&gt;Scribd&lt;/a&gt;.  Looking into this has led me to many resources.  I think I'm going to use swftools with the pdf2swf from &lt;a href="http://www.swftools.org/"&gt;http://www.swftools.org/&lt;/a&gt;.  This comes with a viewer and I found the source code for FDVIEW here &lt;a href="http://www.code4net.com/2005/11/05/fdview/"&gt;http://www.code4net.com/2005/11/05/fdview/&lt;/a&gt; in a comment at the bottom with an example here &lt;a href="http://www.code4net.com/archives/000114.html#114"&gt;http://www.code4net.com/archives/000114.html#114&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;With these resources I'm confident that I can use or polish the FDVIEW to achieve the PDF viewing in Flash in a clean way. &lt;br /&gt;&lt;br /&gt;I'll keep you posted.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/262733752711874688-6876431278952571073?l=zebulonevans.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zebulonevans.blogspot.com/feeds/6876431278952571073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=262733752711874688&amp;postID=6876431278952571073' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/262733752711874688/posts/default/6876431278952571073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/262733752711874688/posts/default/6876431278952571073'/><link rel='alternate' type='text/html' href='http://zebulonevans.blogspot.com/2009/01/view-pdf-files-in-flash-using-php.html' title='View PDF Files in Flash using PHP'/><author><name>Zebulon "Zeb" Evans</name><uri>http://www.blogger.com/profile/15619340177510289955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_JJe9pGJctGg/R-nyLjgTpCI/AAAAAAAAADk/8zE3wdoWLh0/S220/2363541388_d2f80eee98_o.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-262733752711874688.post-158647235554774606</id><published>2008-04-28T11:01:00.000-07:00</published><updated>2008-04-28T14:39:33.918-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='back button'/><category scheme='http://www.blogger.com/atom/ns#' term='dsHistory'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='prototype'/><title type='text'>Enable the Back Button with dsHistory and prototype in an AJAX Application</title><content type='html'>&lt;span style="font-size:180%;"&gt;&lt;br /&gt;Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A common problem with AJAX applications is that they break the back button functionality from a user's perspective.  While coding &lt;a href="http://www.givegroup.com/"&gt;GiveGroup&lt;/a&gt; Craig Tran and I ran into this problem.  Our AJAX application uses the Zend Framework and the prototype JavaScript library.  We looked into a few options to enable the back button support, but they did not seem to blend with our implementation well until we looked into the &lt;a href="http://code.google.com/p/dshistory/"&gt;dsHistory&lt;/a&gt; library.&lt;br /&gt;&lt;br /&gt;We decided to use dsHistory because it allows us to push function calls with an argument object onto a history stack that will be popped off when the user hits the back button.  This worked very well in our implementation because we could pass the div to update, the controller and action pair to call, and the options array into a function, push it onto the history stack, and then call the Ajax.Updater method to fetch the new content.  When the user hits the back button those old calls and their arguments are popped off the stack and ran again emulating returning to the previous page.&lt;br /&gt;&lt;br /&gt;In this example I'm going to try to keep the code as simple as possible to illustrate the technique we used with dsHistory and prototype.  Due to this it will feel a little contrived, but will give you a good start into seeing how to put it into your own application.&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Requirements:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;PHP 5 Server ( I would recommend &lt;a href="http://www.apachefriends.org/en/xampp.html"&gt;XAMMP&lt;/a&gt; if you are new )&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The &lt;a href="http://code.google.com/p/dshistory/"&gt;dsHistory&lt;/a&gt; JavaScript library version 1&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The &lt;a href="http://www.prototypejs.org/"&gt;prototype&lt;/a&gt; JavaScript library version 1.6&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A &lt;a href="http://www.mozilla.com/en-US/firefox/"&gt;modern browser&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;First we will look at the server side code, then at the client site code.&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;span style="font-size:130%;"&gt;Server Side - index.php&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The server side index.php will parse the requested action and serve back the base index page if an action or index was requested.  If a specific action was requested it will serve back just an html snippet to load in the mainContent div.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&amp;lt;?php&lt;br /&gt;// array of allowed actions&lt;br /&gt;$actionFilter = array( 'index', 'welcome', 'content1', 'content2' );&lt;br /&gt;&lt;br /&gt;// get the requested action, if none exists serve the index page&lt;br /&gt;$action = isset($_GET['action']) ? $_GET['action'] : 'index';&lt;br /&gt;&lt;br /&gt;// if an unsupported action is requested return an error message&lt;br /&gt;if( !in_array( $action, $actionFilter ) ){&lt;br /&gt;$action = 'error';&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// based on the action return some content&lt;br /&gt;switch( $action ){&lt;br /&gt;case 'welcome':&lt;br /&gt; echo "This is the initial state of the application.";&lt;br /&gt; echo "&amp;lt;br /&amp;gt;&amp;lt;a href=\"javascript:navigate('content1');\"&amp;gt;next page&amp;lt;/a&amp;gt;";&lt;br /&gt; break;&lt;br /&gt;case 'content1':&lt;br /&gt; echo "This is content 1.";&lt;br /&gt; echo "&amp;lt;br /&amp;gt;&amp;lt;a href=\"javascript:navigate('content2');\"&amp;gt;next page&amp;lt;/a&amp;gt;";&lt;br /&gt; break;&lt;br /&gt;case 'content2':&lt;br /&gt; echo "This is content 2.";&lt;br /&gt; break;&lt;br /&gt;case 'index':&lt;br /&gt; echo file_get_contents('content.htm');&lt;br /&gt; break;&lt;br /&gt;default:&lt;br /&gt; echo "An unsupported action was requested.";&lt;br /&gt; break;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;span style="font-size:130%;"&gt;Client Side - content.htm&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;The html coded for our client side is very simple.  In the body it consists of a single div with an id of 'mainContent'.  This div will hold the results returned by our server side PHP script.  You will notice that when the page first loads we call navigate('welcome') this will then call updateContent with everything the Ajax.Updater needs to know.  The dsHistory script will store the function call with the arguments onto the history stack and we have just set our base state.  From this point the back button will not do anything on the browser until the next call since dsHistory sees the first entry as what it needs to do to bring your application back to its initial state.  You can think of this as everything you would have to do to setup the home page.&lt;br /&gt;&lt;br /&gt;As the user clicks the 'next page' links the server will serve the appropriate html snippets and dsHistory will manage the stack.  Notice that the back and forward buttons work like the user would expect.&lt;span style="font-size:130%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;title&amp;gt;Fix the Back Button with AJAX, dsHistory, and prototype&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript" language="javascript" src="prototype-1.6.0.2.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript" language="javascript" src="dshistory.compressed.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;SCRIPT&amp;gt;&lt;br /&gt;&amp;lt;!-- Begin to hide script contents from old browsers.&lt;br /&gt;&lt;br /&gt;function navigate( page ){&lt;br /&gt;var params = "action=" + page;&lt;br /&gt;&lt;br /&gt;// in a real application we would have an action, but for our&lt;br /&gt;// purposes we'll just use a parameter&lt;br /&gt;var args = {&lt;br /&gt; target:'mainContent',&lt;br /&gt; action: '',&lt;br /&gt; options: { method: 'get', parameters: params }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;updateContent( args );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function updateContent( args, historyObject ) {&lt;br /&gt;// store the function that loaded the 'page' onto the stack.&lt;br /&gt;// the history object helps us to know if this was called from&lt;br /&gt;// history because if it was we shouldn't push it on the stack.&lt;br /&gt;if (!historyObject || !historyObject.calledFromHistory) {&lt;br /&gt;   dsHistory.addFunction( updateContent, this, args );&lt;br /&gt; }&lt;br /&gt; // update the page with prototype&lt;br /&gt;new Ajax.Updater(args['target'], args['action'], args['options']);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// End the hiding here. --&amp;gt;&lt;br /&gt;&amp;lt;/SCRIPT&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body onLoad="navigate('welcome');"&amp;gt;&lt;br /&gt;&amp;lt;div id='mainContent'&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-size:130%;"&gt;Extending the Example&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;With GiveGroup we had some "pages" that required multiple AJAX calls to form.  We had a mainContent and subContent divs and we would sometimes change both based on user interaction and we wanted to treat that set of function calls as a "page" for the user.  If you study the example you can see how it would be easy to add multiple function calls to our implementation on the dsHistory stack.  All you would need to do is modify  the args in updateContent to be an array of the current objects that they are now, and loop over them and call Ajax.Updater for each one.  This way when the args are pushed onto the dsHistory stack they represent one or many AJAX updates to update multiple divs at once.&lt;br /&gt;&lt;br /&gt;We could also extend the example to include JSON responses.  We needed this functionality in GiveGroup as well.  To keep "pages" on the stack that are simple JSON responses from the server make another function similar to updateContent called getResponse and call Ajax.Request instead of Ajax.Updater with your params.  Make sure to the callback function to process your JSON response.&lt;br /&gt;&lt;br /&gt;You could also use dsHistory to push the server responses onto the stack instead of the server requests creating a client side cache so that when the user hits the back and forward buttons the server is not called at all.  You would have to see if this is appropriate for your application, and perhaps we will cover it in a future blog post.&lt;br /&gt;&lt;br /&gt;- Zebulon ( Zeb ) Evans&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href="http://www.givegroup.com/"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/262733752711874688-158647235554774606?l=zebulonevans.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zebulonevans.blogspot.com/feeds/158647235554774606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=262733752711874688&amp;postID=158647235554774606' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/262733752711874688/posts/default/158647235554774606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/262733752711874688/posts/default/158647235554774606'/><link rel='alternate' type='text/html' href='http://zebulonevans.blogspot.com/2008/04/enable-back-button-with-dshistory-and.html' title='Enable the Back Button with dsHistory and prototype in an AJAX Application'/><author><name>Zebulon "Zeb" Evans</name><uri>http://www.blogger.com/profile/15619340177510289955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp0.blogger.com/_JJe9pGJctGg/R-nyLjgTpCI/AAAAAAAAADk/8zE3wdoWLh0/S220/2363541388_d2f80eee98_o.jpg'/></author><thr:total>0</thr:total></entry></feed>
