Ajax Updates |
- Dynamically Create Charts Using MooTools MilkChart and Google Analytics
- Flashy FAQs Using MooTools Sliders
- Jquery Draggable Ajax Tree Sitemap
- Twit – Display Twitter Tweets on a Blog
- Build an Elastic Textarea with Ext JS
Dynamically Create Charts Using MooTools MilkChart and Google Analytics Posted: 23 Oct 2009 11:39 AM PDT The prospect of creating graphics charts with javascript is exciting. It's also the perfect use of javascript — creating non-essential features with unobtrusive scripting. I've created a mix of PHP (the Analytics class), HTML, and MooTools javascript that will connect to Google Analytics, create an HTML table with the statistics for a given month, and use MooTools MilkChart to colorfully chart them out. /* defaults */ $month = date('n'); $year = date('Y'); $type = 'Column'; /* submission? */ if($_GET['month'] || $_GET['year']): /* cleanse lookups */ $month = (int) $_GET['month']; if(!$month) { $month = 1; } $year = (int) $_GET['year']; if(!$year) { $year = date('Y'); } /* retrieve information from google analytics */ require 'ga/analytics.class.php'; $analytics = new analytics('youraccount@gmail.com', 'yourP@ss'); $analytics->setProfileByName('yourdomain.com'); $analytics->setMonth($month,$year); $visits = $analytics->getVisitors(); $views = $analytics->getPageviews(); /* build tables */ if(count($visits)) { //visits - php $visits_table_data = '<table id="data-table-visits">'; /* $visits_table_data.= '<thead><tr><th>Unique Visits</th><th>PageViews</th></tr><tbody>'; */ $visits_table_data.= '<thead><tr><th>Unique Visits</th></tr><tbody>'; foreach($visits as $day=>$visit) { /* $visits_table_data.= '<tr><td>'.$visit.'</td><td>'.$views[$day].'</td></tr>'."\n"; $visits_table_foot.= '<td>'.$day.'</td><td>'.$day.'</td>'."\n"; */ $visits_table_data.= '<tr><td>'.$visit.'</td></tr>'."\n"; $visits_table_foot.= '<td>'.$day.'</td>'."\n"; } $visits_table_data.= '</tbody>'; $visits_table_data.= '<tfoot><tr>'.$visits_table_foot.'</tr></tfoot>'; $visits_table_data.= '</thead></tbody></thead></table>'; } endif; It all kicks off with grabbing the information from Google Analytics. Simply provide the time frame you would like statistics for. I usually choose to retrieve statistics by the month. The Generated HTML & MooTools Javascript <h2>Select Your Month/Year</h2> <form method="get"> <select name="month" id="month"> <option value="">-- Select Month --</option> < ?php for($x = 1; $x <= 12; $x++): echo '<option value="',$x,'"',($month == $x ? ' selected="selected"' : ''),'>',date('F',mktime(0,0,0,$x,1,2009)),''; endfor; ?> </select> <select name="year" id="year"> <option value="">-- Select Year --</option> < ?php for($x = 2008; $x <= date('Y'); $x++): echo '<option value="',$x,'"',($year == $x ? ' selected="selected"' : ''),'>',$x,''; endfor; ?> </select> <select name="type" id="type"> <option value="">-- Select Chart Type --</option> < ?php $chart_types = array('Column','Bar','Line','Scatter','Pie'); foreach($chart_types as $chart_type): echo '<option value="',$chart_type,'"',($type == $chart_type ? ' selected="selected"' : ''),'>',$chart_type,''; endforeach; ?> </select> <input type="submit" name="submit" id="submit" value="Get Statistics!" /> </form> < ?php //php time - echo tables if($visits_table_data) { echo '<h3>Visits', $visits_table_data,'<br />'; } ?> < ?php if(count($visits)): ?> <script type="text/javascript"> var visits = new MilkChart.< ?php echo $_GET['type']; ?>('data-table-visits',{ width: 960, height: 550, font: 'tahoma', showValues: false, useFooter: true }); </script> < ?php endif; ?> Using the THEAD, TBODY, and TFOOT elements is extremely important in the ensuring the correct labels are placed within the generated chart. The data table itself is very simple. MilkChart will take the above table and create a CANVAS element which will contain the chart. There are five different chart types you may choose from: Column, Bar, Pie, Line, Scatter. MilkChart takes full advantage of MooTools' inheritance model as each type of chart's class extends the base MilkChart class. I love the way the MilkChart developer(s) utilized MooTools' OOP/inheritance model to perfection. I also love that MilkChart requires the bare minimum of data for the HTML table. MilkChart isn't without its flaws though. A few of the table types had a fit about including multiple dimensions (using both page views and visits within the same chart, for example) and value label placement has yet to be perfected. Source: http://davidwalsh.name/milkchart Related Listings:
| |||||
Flashy FAQs Using MooTools Sliders Posted: 23 Oct 2009 11:28 AM PDT I often qualify a great website by one that pay attention to detail and makes all of the "little things" seem as though much time was spent on them. Let's face it — FAQs are as boring as they come. That is, until you go the extra mile and use MooTools sliders. <div class="question" rel="a1-1">Question 1</div> <div class="answer" id="a1-1">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nulla nunc justo, lacinia eu, elementum nec, faucibus blandit, massa. Pellentesque nec leo in urna accumsan sodales. Proin nec ligula. Vivamus vestibulum vestibulum neque. Mauris pede. Vivamus ac tortor id mauris hendrerit tincidunt.</div> <div class="question" rel="a1-2">Question 2</div> <div class="answer" id="a1-2">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nulla nunc justo, lacinia eu, elementum nec, faucibus blandit, massa. Pellentesque nec leo in urna accumsan sodales. Proin nec ligula. Vivamus vestibulum vestibulum neque. Mauris pede. Vivamus ac tortor id mauris hendrerit tincidunt.</div> <div class="question" rel="a1-3">Question 3</div> <div class="answer" id="a1-3">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nulla nunc justo, lacinia eu, elementum nec, faucibus blandit, massa. Pellentesque nec leo in urna accumsan sodales. Proin nec ligula. Vivamus vestibulum vestibulum neque. Mauris pede. Vivamus ac tortor id mauris hendrerit tincidunt.</div> Predictably, I add a question class to every question, and an answer class to every answer DIV. Note, however, the rel attribute. The question's rel attribute matches the answer's ID element. Step 2: The CSS h2 { margin:0 0 8px 0; } .answer { line-height:18px; padding:0 0 20px 30px; } .question { font-weight:bold; cursor:pointer; line-height:25px; padding:4px 30px; background:url(http://davidwalsh.name/dw-content/help.gif) 2px 7px no-repeat; } .question:hover { background-color:lightblue; } Nothing special here. I used a pointer cursor for the question's container though. Step 3: The MooTools Javascript //once the dom is ready window.addEvent('domready', function() { //hide all answers $$('.answer').each(function(el) { el.set('display','none'); }); //for every question div $$('.question').each(function(el) { //create a slider var slyder = new Fx.Slide(el.get('rel')).hide(); //click event el.addEvent('click', function(e) { //toggle! e = new Event(e); slyder.toggle(); e.stop(); }); }); //"show" all answers $$('.answer').each(function(el) { el.set('display','block'); }); }); Once the DOM is ready I hide all answer DIVs. Why didn't I just do this in the CSS? Because if Moo didn't load correctly or the user didn't have javascript enabled, I don't want the answers hidden on the page. Now that the answers are hidden, I create a slider for each question. This is where it's important that the question's rel matches the answer's id. We then add a click event to the question to toggle (open or close) the answer DIV. Lastly, we "show" (in CSS) each answer DIV. Related Listings:
| |||||
Jquery Draggable Ajax Tree Sitemap Posted: 23 Oct 2009 10:27 AM PDT There are a handful of javascript libraries and plugins available that attempt this task, but none of them worked flawlessly with our HTML. The real issue here is that javascript alone cannot produce a slick solution, the HTML and CSS need to be carefully constructed to ensure that the experience is seamless and pleasant. Our HTML consists of nested unordered lists, with each list item containing a definition list for the title, page type, publish status, and action links for editing or deleting the page. The feature for expanding and collapsing child pages already existed, making things extra fun. <ul id="sitemap"> <li> <dl> <dt><a href="#">expand/collapse</a> <a href="#">Page Title</a></dt> <dd>Text Page</dd> <dd>Published</dd> <dd><a href="#">delete</a></dd> </dl> <ul>< !–child pages–></ul> </li> </ul> The requirements. The behaviour had to intuitive for the user, they need to be able to reorder pages and move entire sections to new parents. It had to be clear to the user where a page would end up when they dropped it (ie. between pages or as a child page). When one page is dropped over another page, there are three possible outcomes. The page can end up before, after or as a child. This gets particularly tricky at the boundary point between the last child of a sub list and the following sibling. If the resulting location of where a page ends up is the difference of a couple of pixels, the user could become frustrated. We decided to simplfy the problem so that a page could be dropped only before items or as children of items. The only limitation here is that you couldn't easily drop an item as the last child of a list, but this is only a minor issue as moving the last child up would achieve the same result. You can also drop an item on the parent to cause it to become the last child, but this isn't so obvious really. This means for each item on our list we now need to identify two areas where the user can drop the page, on the page to be a child, and above the page to be a sibling. The great thing about jQuery / jQuery UI is how it lets me write the code I want to write, and takes care of cross-browser behaviours and gaps in DOM manipulation. Anyone who has attempted at creating drag and drop functionality for a website will be well aware of the headaches involved in getting everything to work smoothly across browsers. jQuery UI seems to handle this brilliantly. The first thing I want to do is create a div inside the list item to act as a dropzone for placing items as siblings. $('#sitemap li').prepend('<div class="dropzone"></div>'); Piece of cake. To allow an item to be dragged, we simply call the draggable() function on the items that can be dragged. $('#sitemap li').draggable({ handle: ' > dl', opacity: .8, addClasses: false, helper: 'clone', zIndex: 100 }); As we are dealing with nested lists, it is important that only the definition list inside our list item acts as a handle, otherwise our old friend Internet Explorer can get a little confused over who's meant to be moving and who should be staying where they are. By specifying 'clone' we create a duplicate list item that follows the mouse, while the original item waits patiently for us to decide where it should belong. An opacity of 0.8 and a high zIndex keeps the clone on top of everyone else and slightly opaque. It's the little touches that really count. $('#sitemap dl, #sitemap .dropzone').droppable({ accept: '#sitemap li', tolerance: 'pointer', drop: function(e, ui) { var li = $(this).parent(); var child = !$(this).hasClass('dropzone'); //If this is our first child, we'll need a ul to drop into. if (child && li.children('ul').length == 0) { li.append('<ul />'); } //ui.draggable is our reference to the item that's been dragged. if (child) { li.children('ul').append(ui.draggable); } else { li.before(ui.draggable); } //reset our background colours. li.find('dl,.dropzone').css({ backgroundColor: '', borderColor: '' }); }, over: function() { $(this).filter('dl').css({ backgroundColor: '#ccc' }); $(this).filter('.dropzone').css({ borderColor: '#aaa' }); }, out: function() { $(this).filter('dl').css({ backgroundColor: '' }); $(this).filter('.dropzone').css({ borderColor: '' }); } }); We only want to accept sitemap list items, we don't care about other items they care to drop here. At this point we can also fire off our update in an ajax post to the server, in order to commit the change. The CSS. The secret to the interface working really well is CSS. By making sure we have the right paddings and heights in the right places we give the user enough space to comfortably drop items. If we keep the space around the definition list tight, and apply a 4px border plus 6px height to the 'dropzone' div, we give the user 10 pixels of droppable area. This is plenty to guarantee the user will be comfortable. The 4px border gives us a strong, clear indication that the item will be dropped as a sibling. In the demo you'll notice the addition of an undo stack. This is a great fall back for when a user moves a page to the wrong place but forgets where it came from. This will be covered in a separate tutorial. Related Listings:
| |||||
Twit – Display Twitter Tweets on a Blog Posted: 23 Oct 2009 10:13 AM PDT Starting with twit is really easy! Include the script and stylesheets in your document (you will need to make sure the css and js file are on your server, and adjust the paths in the script and link tag) <link href="jquery.twit.css" type="text/css" rel="stylesheet" /> <script type="text/javascript" src="jquery.twit.js"></script> Javascript: Only username is required. Username means the screen name. http://twitter.com/screen name $('#id_of_container').twit(username); $('#id_of_container').twit(username, { limit: 5, label: 'Twitter', title: 'My tweets' }); HTML: <div id="id_of_container"></div> Related Listings:
| |||||
Build an Elastic Textarea with Ext JS Posted: 23 Oct 2009 09:44 AM PDT Since it was first featured on Facebook, elastic textareas – < textarea > elements that automatically expand or shrink depending on how much text the user inputs – has become one of the coolest functional UI effects on the web. In this article, I will guide you through the re-creation of this astonishing effect using Ext JS, and I bet you that you will be surprised to see how easy it is to do it. For this tutorial, we will use the Ext JS JavaScript framework – my favorite framework for cross-browser web application development. I will explain the mechanics step by step so that if you prefer, you can implement the same programming logic using another JavaScript framework/library or with just JavaScript. Only the Ext Core will be needed in this example. Ext JS describes itself as being a “cross-browser JavaScript library for building rich internet applications”. Although it's true, this description is too succinct to describe this excellent JavaScript framework's power and capabilities. It's the perfect tool for creating Rich Internet Applications (RIA): it has a commanding effects library and an awesome GUI toolkit, providing you with tons of components that mimic desktop applications' fluidity and complexity on the web. Ext JS is available in two flavors: Ext Core and Ext JS. Ext Core is the “lite version” of Ext JS, offering the same kind of functionalities you can find in other popular JS frameworks (like jQuery or MooTools). It's licensed under the very permissive MIT license. Some functions that are available in Ext JS are not available in Ext Core though – but in our instance, it's quite alright. Ext JS is packed with a lot of extra features and lots of GUI gadgets. You can get it under one of the two licenses: under a GPL or a commercial license that waives the GPL restrictions. It's extremely well documented with tons of demos and an easy to follow manual. It also has great community support, although they can be a bit harsh to beginners who don't first search if their question has been answered already before asking questions. If you're interested in learning about Ext JS more fully, check out this great tutorial that is available here. The Issue Unfortunately, there is no textarea.contentHeight or similar method, so forget about a direct way to get the text height. “So how do I make the textarea grow and shrink?” A possible approach to find a textarea's height is to get the font size and textarea width and count the number of characters typed. But then when you press the Enter key your calculations are messed up. “Ok, that's not a problem… I can put the Enter key into the equation” you might think, but then you have to think about CSS formatting (i.e. padding, line height, or font size). The Trick To make the textarea grow or shrink, you need to get its content's height and take into account the CSS styles that affect text formatting like font-size, line-height, etc. The trick to get text height is to mimic the textarea contents in a hidden div. To get a decent effect, we will also limit the textarea minimum and maximum sizes, there is no beauty in a 0-px height textarea. Alright, it's time to get our hands dirty. First step is to create a function and set up some control variables; we shall name this function elasticTextArea. We also declare two extra functions that allow us to get and set all CSS styles at once. function elasticTextArea (elementId){ /* * This are two helper functions, they are declared here for convenience * so we can get and set all styles at once and because they are not * available in ext-core only in Ext JS */ //available in Ext JS (not ext-core) as element.getStyles function getStyles(el, arguments){ var ret = {}; total = arguments.length; for (var n=0; n< len;) { el.setStyle(styles[i++], styles[i++]); } } else if (Ext.isObject(styles)) { el.setStyle(styles); } } } //minimum and maximum textarea size var minHeight = 10; var maxHeight = 300; //increment value when resizing the textarea var growBy = 20 ; var el = Ext.get(elementId); Step 2: Get the textarea CSS styles To get an accurate measurement, we need to get the textarea CSS styles that affect text formatting, and they are: * padding //get textarea width var width = el.getWidth(); //current textarea styles var styles = el.getStyles('padding-top', 'padding-bottom', 'padding-left', 'padding-right', 'line-height', 'font-size', 'font-family', 'font-weight', 'font-style'); //store textarea width into styles object to later apply them to the div styles.width = width +'px'; //hide the textarea scrool to avoid flickering el.setStyle('overflow', 'hidden'); Step 3: Create the hidden div And here's where the magic begins. We start by creating a hidden container for the textarea contents. We set its position to absolute — this way, the div is removed from the layout's flow and positioned outside the visible area of the browser. Note: setting its visibility CSS attribute to hidden or its display to none causes some browsers not to recalculate its height, that's why we opted for this method. We also instruct the textarea to recalculate its height by re-running this function on every key stoke; another method is to run it at a specific interval, but I find it to be more resource-intensive and less elegant that way. //create the hidden div only if does not exists if(!this.div){ //create the hidden div outside the viewport area this.div = Ext.DomHelper.append(Ext.getBody() || document.body, { 'id':elementId + '-preview-div', 'tag' : 'div', 'style' : 'position: absolute; top: -100000px; left: -100000px;' }, true); //apply the textarea styles to the hidden div Ext.DomHelper.applyStyles(this.div, styles); //recalculate the div height on each key stroke el.on('keyup', function(){ elasticTextArea(elementId); }, this); } Step 4: Copy textarea contents to the hidden div and get its height To ensure a correct measurement, we replace some special characters with their HTML character entities and also append a space (’ ‘) string to the new line to force its representation. /* clean up textarea contents, so that no special chars are processed * replace \n with so that the enter key can trigger a height increase * but first remove all previous entries, so that the height measurement * can be as accurate as possible */ this.div.update( el.dom.value.replace(//, '') .replace(/< |>/g, ' ') .replace(/&/g,"&") .replace(/\n/g, '') ); //finally get the div height var textHeight = this.div.getHeight(); Step 5: Resize the textarea In the last step, we give the textarea its new height. //enforce textarea maximum and minimum size if ( (textHeight > maxHeight ) && (maxHeight > 0) ){ textHeight = maxHeight; el.setStyle('overflow', 'auto'); } if ( (textHeight < minHeight ) && (minHeight > 0) ){ textHeight = minHeight ; } //resize the textarea el.setHeight(textHeight + growBy , true); } Try it out Wasn't that simple? Save the JavaScript code we wrote as elasticTextarea.js or download the source, include Ext Core and the JavaScript library, and have fun. To include the JS libraries: <script type="text/JavaScript" src="ext-core/ext-core.js"></script> <script type="text/JavaScript" src="elastic.js"></script> The HTML for the text area: <textarea id="ta"></textarea> To call the function ('ta' being the ID of the textarea): <script type="text/JavaScript"> elasticTextArea("ta"); </script> Conclusion The purpose of this article is to introduce you to Ext JS. If you know your JavaScript well, you might find that this code will only work for one textarea. If you'd like a more robust and flexible solution, get the Ext JS plugin that can be found over at my site. Stay tuned for more Ext JS tutorials here on Six Revisions, written by me. Future tutorials will cover Ext JS plugins, and talk about more cool and easy-to-create UI effects using Ext JS RIA framework. Related Listings:
|
You are subscribed to email updates from Ajax Updates To stop receiving these emails, you may unsubscribe now. | Email delivery powered by Google |
Google Inc., 20 West Kinzie, Chicago IL USA 60610 |
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.