Tuesday, December 14, 2010
CakePHP Component Re-Directs Revisited
http://j-query.blogspot.com/2010/11/component-based-re-directs-in-cakephp.html
We discussed what was needed to get redirects working from a component.
In this post I will mention a simple bug that can come into a component that will really mess with all your re-directs. The problem is if your component extends Component instead of Object and you don't explicitly extend beforeRedirect(), for whatever reason all redirects on your site will result in infinite loops.
So the moral of the story:
Components extend Object not Component!
Saturday, November 20, 2010
Unfinished Projects
2) Make a PhoneGap app with Sencha Toucha and get it in the iPhone and Android app-stores
3) Learn ExpressJS and how to run Node stably
4) Do a video podcast of how to get up and running with Node.js
5) Learn and write some good tutorials / examples for progressive enhancement at Rain
6) Prepare presentations on Javascript Best Practices, Node, and HTML5/CSS/Progressive Enhancement for Designers
7) etc..
Saturday, November 6, 2010
Real-Time Collaborative Painting With Node.JS and Socket.IO
Introduction
I <3 Node.js!. This post will show you how to put together an amazing collaborative painting web app using Node.jS and web sockets in about 130 lines of code. The whole source code can be found here. I'll mention it's modeled loosely after the chat example found in the Socket.io-node source code.This is more of a simple demo at the moment, but it proves a few points.
1) Node is seriously awesome (and easy to get up and running)
2) Socket.io is equally awesome
3) It's easy to support the iPhone and other touch devices
4) Canvas is cool too :)
Unfortunately I do not currently have a live demo. I'm still hitting https://api.no.de/coupons hoping for a free trial to one of Joyent's Smart Machine's, but so far no luck :)
A Picture
*The red is what you drew, the blue is what someone else drew.
Overview
There are pretty much only 3 files of consequence and you can view them all here:
1) collabpaint.htmlHTML file that just gives you a canvas and contains some simple CSS content. Used to display the page.
2) collabpaint.js
This file is responsible for drawing to your canvas. It contains all of the event listeners and code for listening for messages from the node server.
3) server.js
Tells node to start an http server and socket.io instance to handle messaging between clients.
Getting started with Node
There are a handful of great tutorials for getting started with Node.
In general if you just want to get started with node, it's very easy. There are several tutorials linked from the node wiki page here:
https://github.com/ry/node/wiki
I think I read all of them for doing this example. The biggest things for me was basically figuring out how to install modules. Other than, I noticed that node crashes pretty easily if you're doing something wrong and it doesn't always give you a useful error messages.
Another big thing. Stick with the current stable version of node! The docs mention 0.3.0 on the website, but the current stable version is actually 2.4. That means, if you're checking out the source code with git, you'll need to switch away from the master branch to the 0.2.x branch like so, before configuring and installing Node:
git clone https://github.com/ry/node.git cd node git checkout -b v0.2 origin/v0.2 ./configure make sudo make install
Also, the docs for version 0.2.4 can be found here.
Adding support for web sockets with Socket.IO
Coming soon...
Canvas Quirks
The biggest problem I ran into with the canvas stuff was figuring out where on the screen to draw. I noticed that the coordinates I retrieved initially were only working on Google Chrome (e.offsetX and e.offsetY). Later I changed to a way that seemed not to work if the page had been scrolled down at all. My current solution of relying on the clientX and clientY, subtracting the target offsetX and offsetY and then adding the window scrollX and scrollY seems to work okay Chrome, Safari and Firefox. See the code:
coords = { x:e.clientX - e.target.offsetLeft + window.scrollX, y:e.clientY - e.target.offsetTop + window.scrollY };
Adding iOS Support
There were two things I needed to change to allow this to work really well on an iPhone (and presumably other mobile devices). First, I used a media query to take away all of the extraneous content on the page. The mobile version is just a big canvas. No silly border and no header.
@media screen and (max-width: 320px) { h1 { display: none; } canvas { border: none; border-radius: none; -webkit-box-shadow: none; } }
Next I had to listen for special events in order to tell when we were drawing on the iPhone:
// iOS alternative to mouse move canvas.ontouchmove = function(e) { move(e, true); };
Lastly, we needed to handle multi-touch. This was the trickiest thing I guess, but a few Google searches found me some great docs from Apple website about how to capture those events.
for (var i=0; i<e.targetTouches.length; i++) { coords = { x: e.targetTouches[i].clientX, y: e.targetTouches[i].clientY }; drawCircle("red", coords); send(coords); }
This may not be the fanciest way to detect touch events. I'm not doing any real feature detection, but the browsers don't seem to mind too much about having these extra event handlers in there, so I'm pretty happy with the solution.
The Future
Well, I'm working on a lot of variations to this simple app.1) Different "sessions" where people can only draw with people they invite
2) Different colors / Brush types
3) An eraser
4) Doing fun things with sound.
Some of these are already available in the code itself under different branches.
Android / HTML5 Canvas Mashup
Recently I had a vision in my mind about something I wanted to build. It started with an Android app that I was working on for a presentation. It was a simple game. Simple games are boring. I wanted to bring in web services. Some more interesting games offer a feature where you can watch your game later, so I decided to do a version of this that works on the web. Because this was a simple game (at this point all you could do was roll around a ball using the accelerometer) and because I used the Android 2D Drawing API to do the entire thing. I decided that it wouldn't be very hard to do the replay on the web with canvas.
See some of the completed games here:
http://www.touchenabledweb.com/games/
There were a few important things we needed to make this work. On the Android side, first we need to tell the device that we will be accessing the Internet. The we will needed to asynchronously connect to the web and then we need to parse some JSON. Later we'll figure out how to store and this data on the server side and how to display it using the HTML5 <canvas>l tag
Android Stuff
Obtaining Permission
We need to make sure we add this permissions requests to our AndroidManifest.xml file:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
Asynchronous-ness
There were two different types of requests. One to create a new game and two to update the latest scores. For both of them we started with the AsyncTask class found in the android.os package. It's really weird actually and I can't fully explain how it works, but I can explain how I got it to work. First you declare your class like this (in this case in a file called PostDataTask.java:
public class PostDataTask extends AsyncTask{
GameFrame is just a class that I created to store information about the game. The Integer and Long classes are needed for some of the callback functions that the AsyncTask makes available, however I don't use them in my example. Once you declare what type of arguments you need, you need to over-ride a method on the AsyncTask class called doInBackground:
@Override protected Long doInBackground(GameFrame...frame) { boolean succcess = this.postData(frame[0]); return null; }
The do in background wants you to give it as an argument a fancy kind of array, which you can specify with the three dots between the class and variable names. I know that I only will ever be sending one GameFrame object in at a time, so I just directly grab frame[0] and send that to the postData method I created, which also expects a GameFrame, but only one.
private boolean postData(GameFrame myFrame) {
When you're ready to call off the task to post the data in your main game class all you need to do is create and execute and new post data task with the appropriate arguments. In this case:
new PostDataTask().execute(new GameFrame(this.gameID, (ArrayList) coordinates.clone()));
Using the AsyncTask I'm able to successfully make updates to the web server in the background. If you want to know by the way GameFrame contains a very simple array of coordinates and the ID of the game that the ball has moved around to and is defined in its own GameFrame.java file:
package org.example.dirtsweeper; import java.util.ArrayList; import android.graphics.PointF; public class GameFrame { public int gameID; public ArrayListcoords; public GameFrame(int gameID, ArrayList coords) { this.coords = coords; this.gameID = gameID; } }
JSON-ification
The AsyncTask stuff was super easy to get going, but I was a little bit worried that the web services would be a lot harder than the PHP stuff I typically a usually use. It was. It was really hard and a small typo meant that it took me hours to get it working properly. The first tip is to use the org.apache.http.client class. This seriously made things a lot easier than some of the other solutions out there! Next you have use things like the JSONTokener to parse the JSON data. It kind of sucks, but you just have to do it. Here is an example of my newGame function in my NewGameTask class:
private int newGame(Sweeper sweeper) { int gameID = 0; // Create a new HttpClient and Post Header HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(NEW_GAME_URL); try { // Add your data ListnameValuePairs = new ArrayList (); nameValuePairs.add(new BasicNameValuePair("data[Game][width]", String.valueOf(sweeper.floor.getWidth()))); nameValuePairs.add(new BasicNameValuePair("data[Game][height]", String.valueOf(sweeper.floor.getHeight()))); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); // Execute HTTP Post Request HttpResponse response = httpclient.execute(httppost); BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8")); String json = reader.readLine(); JSONTokener tokener = new JSONTokener(json); try { JSONObject finalResult = new JSONObject(tokener); gameID = finalResult.getInt("game_id"); } catch (JSONException e) { Log.d(TAG, TAG + "ERROR JSON EXCEPTION: " + e.getMessage()); // TODO Auto-generated catch block e.printStackTrace(); } } catch (ClientProtocolException e) { Log.d(TAG, TAG + "This is your error ClientProtocol " + e.getLocalizedMessage()); } catch (IOException e) { e.printStackTrace(); Log.d(TAG, TAG + "This is your IOException error " + e.getLocalizedMessage()); } return gameID; }
If you want to know what my JSON response actually looked like follow along to the next section....
Server-side
I use the CakePHP framework for doing most of my websites. I find it's super easy to get create fully functional data-driven websites with a ton of web services up and running in no time.
Database Schema
The DB here is very simple. The schema is also available in the repo, but here it is:
CREATE TABLE IF NOT EXISTS `games` ( `id` int(11) NOT NULL AUTO_INCREMENT, `width` int(10) unsigned NOT NULL DEFAULT '320', `height` int(10) unsigned NOT NULL DEFAULT '430', `created` datetime NOT NULL, `modified` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- -------------------------------------------------------- -- -- Table structure for table `game_times` -- CREATE TABLE IF NOT EXISTS `game_times` ( `id` int(11) NOT NULL AUTO_INCREMENT, `game_id` int(11) NOT NULL, `x` float(10,6) unsigned NOT NULL, `y` float(10,6) unsigned NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Web Services
We only created two web services.
/games/addGame
and
/games/addTime
Both the views look exactly the same. They just indicate success and return the gameID.
<?php echo json_encode(array('success' => $success, 'game_id' => $gameID)); ?>
PHP
Animating the movements of a ball on a canvas is pretty easy. I'm not going to explain how to draw on a canvas. There are some great tutorials over at the Mozilla Developer's Center. I will show you what I'm doing though to prepare us to print (and of course you can use all the source code). Here is the contents of the watch game view.
<canvas id="floorSweeper" width="<?php echo $game['Game']['width']; ?>" height="<?php echo $game['Game']['height']; ?>"></canvas> <script type='text/javascript'> var FLRSWPR = { id:'floorSweeper', name:'Floor Sweeper', width:<?php echo $game['Game']['width']; ?>, height:<?php echo $game['Game']['height']; ?>, fps:10, background:'black', times:<?php echo json_encode($times); ?> }; </script> <script type="text/javascript" src="http://www.touchenabledweb.com/js/floorsweeper.js"></script>
In case your wondering the times array is very simple and populated that section might look something like this:
times:[{"x":"25.000000","y":"267.500000"},{"x":"22.000000","y":"265.000000"},{"x":"19.000000","y":"262.500000"}, /* ... */ {"x":"22.000000","y":"265.000000"}]
JavaScript
Okay, so finally the real magic. We have the balls coordinates. How do move the ball around on the screen? I'm not going to go over the entire Javascript file. (You can see it here: http://www.touchenabledweb.com/js/floorsweeper.js) Instead I just want to show you a few of the interesting parts.
Here is the Ball prototype:
Ball.prototype = { moveMe: function () { if (this.currentFrame < this.frames.length) { this.x = this.frames[this.currentFrame].x; this.y = this.frames[this.currentFrame].y; this.currentFrame++; } }, drawMe: function(ctx) { ctx.fillStyle = this.color; ctx.moveTo(this.x,this.y); ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI+(Math.PI*360)/2, false); ctx.fill(); } };
There are two very simple methods on the Ball prototype: drawMe() and moveMe(). They do what they say. The moveMe() function checks if we're not at the end of the frames that the object was instantiated with and then just moves the coordinates to the next frames and updates its count of which frame it's displaying. The drawme() function draws a really basic ball.
There is also a Game prototype. When we start the game prototype it is given an arbitrary frames per second and it sets an interval to go through call the moveMe() and drawMe() methods on all of its registered "actors". Simple no?
Phew!
That was a lot to cover. A little bit of Java, a bit of PHP and even some JavaScript. In the future I'd love to use Node.js and Socket.IO so that we can watch the games in real-time. (It might also be nice to finish the Java part, so that there's actually an interesting game).
Please leave a comment or a suggestion if you can see a place where I could have done something better. I'm much more of a web programmer than a Java programmer!
All of the source code (Android and PHP) can be found here: https://github.com/xjamundx/DirtSweeper
Wednesday, November 3, 2010
Component-based Re-directs in CakePHP
See: http://www.dom111.co.uk/blog/coding/cakephp-components-redirect-fail-on-my-part/171
Then see: http://book.cakephp.org/view/65/MVC-Class-Access-Within-Components
The answer:
For reasons which are explained in the above two articles, components that wish to use redirect need to include the following callback function in their component:
function beforeRedirect(&$controller, $url, $status=null, $exit=true) { }
Wednesday, October 6, 2010
Android Development Thoughts
I love Android development. I just want to tell you how easy it is to install on App on your Android phone:
tools/adb -d install ~/Desktop/Android/DirtSweeper/bin/DirtSweeper.apk
Source code is here:
http://github.com/xjamundx/DirtSweeper
More thoughts coming soon!
Saturday, August 21, 2010
Canvas Loading Image Replacement Plugin
http://jamund.com/canvas-loader/no.jquery.html
Here's how it works:
window.onload = function() { var img = document.getElementById("imgLoader"); var span = document.getElementById("spanLoader"); canvasLoaderReplace(img, {color:'red'}); canvasLoaderReplace(span, {backgroundColor:'red', radius:'40'}); };
- Before
X - After
X
NodeJS Based IM server
Simple and fast messaging over web sockets.
Approach
I recently developed an AJAX-based messaging client for a large social networking type website I am developing for a client at Rain. It works fine, but using AJAX to constantly poll the server is slow and creates a fair amount of overhead for the browser. Using web-sockets with a flash back-up for older browsers combined with NodeJS on the server side should create fast and simple solution for my messaging problem. It would also make it easier to separate the messaging server from the web application server to increase scalability.
Results
After getting lost in a la-la land of non-supported NodeJS 1.x based web socket and chat clients, I stumbled on Socket.IO, a library that contains both front-end and back-end code for delivering high speed chat over web sockets using NodeJS 2.x.
Getting Started
Following these simple steps in terminal got me a working chat server up and running in about 5 minutes.
# install node
cd ~/dev;
git clone git://github.com/ry/node.git;
# copy the javascript over to the example directory
cp Socket.IO/socket.io.js Socket.IO-node/example/client/;
Moving forward
I love how easy it is to get started with NodeJS and Socket.IO. I intend to put it to use to build my messaging client. One key feature that might provide a problem is logging the messages. Currently Ithey are being stored in MySQL on a separate database server. Because the storage doesn't need to be real time, only the messaging, I could continue using AJAX to log messages. I might also be able to hook into MySQL directly from the socket.io-node server in a way that does not slow down communication. More research will be needed to determine how practical an approach this will be and how it competes with AJAX/PHP on resources, scalability, and browser support. At the moment I'm excited about the potential and hope to write more about it if I get it up and running!
Resources
http://thechangelog.com/post/456659159/socket-io-multi-transport-socket-server-for-node-js - A good tutorial on how to get started with Socket IO for NodeJS.
Monday, August 16, 2010
psd2html.com form element mis-hap
Monday, August 2, 2010
Saturday, July 31, 2010
Semantically awesome ordered lists
So if you were ever trying to style an ordered list <ol> and get rid of those pesky periods after the numbers you may have wanted to give up.
Do not give up!
Much better than manually adding the numbers and styling them in a very un-semantic way. Now of course this works in Firefox and Webkit and not much else, but that's okay. I need it for an iPhone app, so we're good!
<style>
nav {
margin-left: 20px;
margin-right: 30px;
color: #666;
}
ol { counter-reset: item }
li {
display: block;
margin-top: 10px;
}
nav ol li span {
font-family: 'GothamBook', Arial;
font-size: 1.6em;
}
ol li::before {
content: counter(item) " | ";
counter-increment: item;
font-family: 'GothamLight', Arial;
font-size: 2.2em;
}
</style>
<nav>
<ol>
<li><a href="#">Why mobile?</a> <span>Quotes and figures to astound your clients.</span></li>
<li><a href="#">Focus.</a> <span>Using constraints to improve design across the board.</span></li>
<li><a href="#">Capabilities.</a> <span>What can mobile phones do now-a-days?</span></li>
<li><a href="#">Native vs. Web App.</a> <span>Which is a better fit for your needs?</span></li>
<li><a href="#">Workflow.</a> <span>What happens to your app when it comes through our door.</span></li>
<li><a href="#">Cost.</a> <span>An arm and a ...</span></li>
<li><a href="#">Know before you start.</a> <span>10 essentials that can save your app.</span></li>
<li><a href="#">What's on the horizon?</a> <span>Mobile trends to keep in mind.</span></li>
<li><a href="#">Help me.</a> <span>We’re here to help you with all your Mobile needs..</span></li>
</ol>
</nav>
Thank you:
http://efreedom.com/Question/1-3153019/Remove-decimal-from-ordered-ol-list-via-CSShttp://www.w3.org/TR/CSS2/generate.html
Tuesday, July 27, 2010
Mobile Web Design Resources
- Mobile Web Examples at the bottom
http://paradoxdgn.com/post/notes-on-mobile-design
- A Few cool tips
http://www.sencha.com/products/touch/design.php
- Mobile Web Framework Design Stuff
http://www.noupe.com/how-tos/mobile-web-design-tips-and-best-practices.html
- Best Practices (with pictures)
http://www.slideshare.net/fling/designing-mobile-experiences
- Really interesting (and long) slideshow
Saturday, July 24, 2010
jQuery Canvas Loader Plugin
I want to tell you about a new jQuery plugin I just released yesterday. It's called Canvas Loader and it provides a canvas replacement to the standard Ajax Loading images we're all used to seeing around the web. This is helpful for the mobile space because Android for example does not support animated gifs, but it does support the canvas tag. It's also neat because by default it's transparent and is easily customizable. The actual un-minified size is likely bigger than the a small loader image, but not by much and if included with the main javascript of the site it should actually download faster.
While the plug-in takes a lot of options. The main functionality can be triggered by calling this simple method. It tires to match the width and height of an existing image. Currently, you must have an actual image that is being replaced!
$("img.ajaxLoader").canvasLoader();
Check it out for an example and the code:
http://jamund.com/canvas-loader/
Tuesday, July 20, 2010
Mobile Web Best Practices
http://www.w3.org/TR/mwabp/
The article provides a good overview of some of the things to consider when developing a mobile web application, especially across multiple platforms. Highly recommended read for mobile web developers.
Check it out!
Here is the table of contents from the article:
- Use Cookies Sparingly
- Use Appropriate Client-Side Storage Technologies for Local Data
- Replicate Local Data
- Do not Execute Unescaped or Untrusted JSON data
- Ensure the User is Informed About Use of Personal and Device Information
- Enable Automatic Sign-in
- Use Transfer Compression
- Minimize Application and Data Size
- Avoid Redirects
- Optimize Network Requests
- Minimize External Resources
- Aggregate Static Images into a Single Composite Resource (Sprites)
- Include Background Images Inline in CSS Style Sheets
- Cache Resources By Fingerprinting Resource References
- Cache AJAX Data
- Do not Send Cookie Information Unnecessarily
- Keep DOM Size Reasonable
- Optimize For Application Start-up Time
- Minimize Perceived Latency
- Design for Multiple Interaction Methods
- Preserve Focus on Dynamic Page Updates
- Use Fragment IDs to Drive Application View
- Make Telephone Numbers "Click-to-Call
- Ensure Paragraph Text Flows
- Ensure Consistency Of State Between Devices
- Consider Mobile Specific Technologies for Initiating Web Applications
- Use Meta Viewport Element To Identify Desired Screen Size
- Prefer Server-side Detection Where Possible
- Use Client-side Detection When Necessary
- Use Device Classification to Simplify Content Adaptation
- Support a non-JavaScript Variant if Appropriate
- Offer Users a Choice of Interfaces
Friday, July 2, 2010
Apple's Useful Offline Storage Article
The localStorage and sessionStorage JavaScript objects are functionally identical except in their persistence and scope rules:http://developer.apple.com/safari/library/documentation/iphone/conceptual/safarijsdatabaseguide/Name-ValueStorage/Name-ValueStorage.html
localStorage—used for long-term storage. This data persists after the window is closed and is shared across all browser windows.
sessionStorage—used for ephemeral data related to a single browser window. Data stored in the sessionStorage object does not persist after the window is closed and is not shared with other windows.
A note on storing objects using local storage:
http://stackoverflow.com/questions/2010892/storing-objects-in-html5-localstorage
Great info about creating Mobile Web Applications
Wednesday, June 30, 2010
Mobile Safari CSS3 / JS
Just wanted to point something that I tried out with some good success.
Mobile Safari supports multiple background images.
I kind of wondered when I would get around to actually wanting them, but then it came up in this project I was doing that involved creating a sortable table. I have an up arrow and a down arrow and want them to both appear on an unsorted table and then for only one to appear once the table has been sorted. I am using JQuery tablesorter for my sorting by the way, which works great on mobile. This is a mobile web app that supports the "web clip" option for saving to the mobile desktop, which means everything is loaded through ajax. Anyway, here is some code showing how this works and why it's userful.
#list table thead th { background-color: #777; background-image: url('images/up.png'), url('images/down.png'); background-repeat: no-repeat, no-repeat; background-position: 98% 33%, 98% 66%; width: 50%; text-align: left; padding: 8px 20px 8px 8px; color: #ccc; font-size: 11px; } #list table thead th.headerSortDown { background: #777 url('images/down.png') no-repeat 98% 50%; } #list table thead th.headerSortUp { background: #777 url('images/up.png') no-repeat 98% 50%; }
Links:
JQuery Tablesorter Plugin
CSS3 Multiple Background images
Tuesday, June 29, 2010
Mobile iPhone Web App Cheatsheet
http://www.google.com/support/mobile/bin/answer.py?answer=31238
Full screen mode JS detection:
http://maisonbisson.com/blog/post/13148/mobile-safari-advanced-features/
Monday, June 21, 2010
Command-line Coda
http://wefoundland.com/project/command-line_coda
Tuesday, June 15, 2010
Wordpress Custom Shortcodes
SHORTCODES are only parsed when using the_content() to display the page data.
This was a problem as I was pulling the page data into a variable and then echoing $page->post_content. No worries. Once I added the loop code around the page
if (have_posts()) : while (have_posts()) : the_post();and
endwhile; endif;the_content() AND my short codes worked fine!
Hurray! Wordpress can be a pain, but this was easy!
Links:
http://www.smashingmagazine.com/2009/02/02/mastering-wordpress-shortcodes/
http://codex.wordpress.org/Shortcode_API
http://themocracy.com/2010/03/a-flickr-badge-using-wordpress-shortcodes/
Wednesday, June 9, 2010
Conditional Wordpress Navigation
<?php if ($prevPostsLink = get_next_posts_link("Previous")):?> <li class='active'><?php echo $prevPostsLink;?></li> <?php else:?> <li class=''><a href="#" onclick="return false;" class="prev">Previous</a></li> <?php endif?> <?php if ($nextPostsLink = get_previous_posts_link("Next")): ?> <li class='active'><?php echo $nextPostsLink;?></li> <?php else:?> <li class=''><a href="#" onclick="return false;" class="next">Next</a></li> <?php endif?>
None of the following worked for me:
Friday, May 28, 2010
2 Great Mobile Interfaces
http://gmailblog.blogspot.com/2009/04/new-mobile-gmail-experience-for-iphone.html
http://gmailblog.blogspot.com/2010/04/gmail-on-ipad.html
Thursday, May 27, 2010
Developing Mobile Websites
1) Use CakePhp's isMobile()
I usually use the CakePHP framework for doing programming and I check in the App Controller beforeFilter() function using $this->isMobile() is that's true I'll set a variable $this->mobile to true which I can check all over the place when trying to figure out which version of a page to return. Not to mention it's easy to forward them on to the correct domain name. It's lovely. Once they're in the correct domain name I will tell CakePHP to look in the m/ folder for files. This makes them easy to organize and find just what I need and makes for some wonderful MVC goodness. Something like this works well:
$this->layoutPath .= "/m";
$this->viewPath .= "/m";
$this->mobile = true;
} elseif ($this->RequestHandler->isMobile()) {
$this->redirect("http://m.mysite.com");
}
2) Don't re-use your huge CSS/JS files.
I always write a separate javascript and css file for mobile. Mobile will need it's own version of these files, usually I'll just call them mobile.css and mobile.js or something like that. They will be optimized for the mobile user experience and will likely be much smaller than the normal web javascript files.
3) Test! Test! Test!
Check using emulators and on real devices. You know, this has been difficult. webOS has an easy to use emulator. If you're on a mac you can quickly access the iPhone emulator by creating a new XCode project and running it in the simulator, then just click the home button and you can access and test in mobile safari. The Android emulator can be downloaded for free as well. Opera Mini can be downloaded easily on the Mac. That's 4 platforms right there. I'm still trying to figure out how to test on Blackberry devices. This site will also let you test your phone in some sweet old mobile web browsers:
http://mobiready.com/launch.jsp?locale=en_EN
4) Degrade graecfully.
If your site is built with simple tags like <img /> and <i> you shouldn't have much of a problem with older phones that can't handle images or css. Make sure to use the alt tag on the images and to be thoughtful about how content might appear in a texts based interface. Try to make sure your site will work fairly well without javascript as well. Though this can be a hard one if you want to do anything cool!
5) Keep it simple.
You know just because the iPhone and webOS can support "flashy" CSS3 animations doesn't mean that your site should. Those animations will likely be a little choppy and will ultimately make your site more difficult to use. Not to mention that they won't be supported by every phone. Just leave them out or keep them for your desktop/iPad-ready website.
6) Avoid Phone Specific Code
Avoid phone specific code. This is so hard to maintain. I caught myself throwing in a little if (ua.match(/webos/)) { the other day and quickly stopped myself. There are usually ways around doing phone specific code and whenever possible avoid doing it!
7) Pick your platforms.
It's impossible to support every platform perfectly. Decide right now which phones you want to support fully and then do all you can to ensure that those do work perfectly. You need to choose where to spend your time. If you know that all of your customers use the iPhone, then just optimize for that, it's not worth the resources it takes to optimize for everything else.
8) Don't use WAP.
WAP is difficult to use. It requires special headers. It's barely supported by anything anymore. It doesn't really support normal images and it's pretty much completely useless. Instead stick to basic HTML5 tags that will be supported in most phones. No, I do not have a complete list, but the simpler the better.
9) Avoid tables.
Tables are a clunky way to design sites and really won't help you very much when targeting smaller phones. You should avoid them anyway for normal web development. You are best to stick with lists, which are much more flexible.
10) Avoid Javascript
At least make sure your site works without javascript. Javascript is such a helpful tool, but it will not be supported on a lot of older phones. If you want to create a universal mobile experience see what you can without javascript first. If you can get the core functionality in there without it then you can add additional features for those phones that do support it later.
Those are my tips and tricks. Hope they have been helpful. Here are some other great resources I have found for mobile web development and design:
Tutorials
http://articles.sitepoint.com/article/designing-for-mobile-web - Decent article on building a mobile website for sort of the previous generation of mobile phones (2008)
http://www.smashingmagazine.com/2009/01/13/mobile-web-design-trends-2009/ - Discusses the trends coming along in early 2009 about designing for the mobile web. Again, this mostly is about support previous generation phones.
http://www.elementfusion.com/tutorial-optimizing-your-website-for-mobile-devices - Excellent tutorial for creating a beautiful website that displays on some of the newer phones.
http://mobiforge.com/designing/story/effective-design-multiple-screen-sizes - In depth research about mobile design and development from mobiforge!
Wednesday, May 26, 2010
Palm WebOS and jQuery headaches
Right now my favorite of the bunch is generally webOS. I really want a Palm Pre after developer on there for a little while. It's amazing platform based on HTML5 and Javascript. The emulator generally works really well too, but today I ran into two problems.
1) jQuery stopped working? I'm not sure what happened here, but I have a picture of a demo on jQuery.com and the browser just grayed out the whole thing. After hanging out in #jquery and #webos in irc.freednode.net I found out that the problem doesn't exist (for anyone else at least). I restarted my emulator and then it started working again. Annoying, huh?
2) This one might not be an emulator issue. I'm using jQuery.load to pull in some new webpages and of all of the platforms above this appears to the only one that cannot handle scripts being added to the dom dynamically, which is how .load() pulls in scripts. Instead of having the javascript source file linked from the ajax-loaded page, I re-wrote the script to use jQuery.live and watch for the events throughout the entire app's existence. A bit of a pain, but not too hard. I still don't know if this is a "feature" of webOS or if I just did something wrong. Any thoughts?
jQuery.load() reference:
http://api.jquery.com/load/
Monday, May 24, 2010
Palm WebOS
http://www.slideshare.net/fpatton/marinacci-josh-intro-to-web-os-palm-dev-day - Great overview of the features and capabilities of WebOS
http://developer.palm.com/index.php?option=com_content&view=article&id=1574 - Basic Web Programming Guide for WebOS by Palm
http://developer.palm.com/index.php?option=com_content&view=article&id=1788&Itemid=55 - Download the SDK!
http://developer.palm.com/index.php?option=com_content&view=article&id=1603&Itemid=43 - webOS application programming basics
http://developer.palm.com/index.php?option=com_content&view=article&id=1744&Itemid=58#Emulator-KeyboardShortcutsEmulator - Keyboard Shortcuts are critical because the emulator doesn't have any buttons!
Good luck to all of you future webOS developers out there!
Mobile App Store Lessons
http://gigaom.com/2010/05/19/never-charge-for-a-mobile-app-and-other-freemium-lessons-from-vcs/
To sum it up, basically they said that you should give your apps away for free and then sell upgrades. Make sure your audience is big enough to make money off a 2-3% upgrade margin. Worth reading though for many other tidbits of info.
Saturday, May 22, 2010
Fishes iPhone App
I have made a lot of improvements to my app including levels, colorful fish and a counter. You can also pause and restart gameplay.
The source code is below:
http://www.jamund.com/fishes-iphone/fishes.zip
CSS3 Scaling vs. Changing the width and height of
$("img").css({webkitTransform: 'scale(2)'}); // this actually makes thing bigger
Combined with the transition above it actually looked pretty, however.......When trying to pan the image around I kept having problems. The problems weren't while moving the image. That was fine it was when I stopped and started again it would jerk pretty far in the opposite direction. I still don't know this would happen, so I went back to a non CSS3 zoom and it seems fine. More investigation is needed to understand why working with a scaled image was so much more difficult than working with a resized image. Final solution (it even uses the CSS3 transition above):
$("img").each(function() {
$(this).css({height: "auto",width: $(this).width()*2});
});
This may have just been a bug with the jQuery Touch plugin I was using, but I couldn't get it working in the time it needed to work, so I had to just move on. Sadness.
iPad I know you can do better!
HTML5 Fish Game
https://code.google.com/p/html5fish/
Normal version:
http://www.jamund.com/fishes/
setTimeout() vs setInterval() reprise
http://www.jamund.com/timers/
Code is also here:
http://pastium.org/view/5b5904aad004858f5a4c0a2604096850
Rotating Images on A Canvas
I was having some humongous trouble getting the canvas to rotate properly in the following example. I wanted actors to move around the stage in a meaningful way. I've learned that to get the actors to move you can draw the images in different places or you can save the canvas, translate the canvas, draw the image to the screen and then reset the canvas. This will effectively move around the image. I don't know which way is faster. The following code snippet uses the latter method. In order to get the actors to rotate you have to save the canvas, rotate the canvas, draw the image and then reset the canvas. Well this will do some funny things because you are not rotating the canvas where the actor is, you are rotating (by default) from the center. So what you have to do is something like this:
Actor.prototype.draw = function() { if (this.image.isReady) { context.save(); context.translate(this.dx, this.dy); context.scale(this.scaleVal,this.scaleVal); var rotateX = this.x+this.width/2; var rotateY = this.y+this.height/2; context.translate(rotateX, rotateY); context.rotate(this.angle); context.translate(-rotateX, -rotateY); context.drawImage(this.image, this.x, this.y, this.width, this.height); context.restore(); } }
I will be posting a demo soon!
HTML: http://pastium.org/view/fcc862b3fa944ee07c42917bfccb1ab1
JS: http://pastium.org/view/554ce8888f33b03eb307d11562922ccd
CSS: http://pastium.org/view/c7e2f8eae3c30ef0178d5825be350956
The real key to make this happen though was this simple code posted by caleb_h at irc.freenode.net!:
http://erxz.com/pb/25522
Friday, May 21, 2010
HTML4 vs. Canvas vs. SVG vs. Flash Benchmark
Looks like if you're going for HTML5 animations canvas is the way go. Interesting! Might comment more on this later or post my own benchmarks. Thanks to themaininblue.com for this cool write-up.
Click here for demos and more information about the methods used:
http://www.themaninblue.com/writing/perspective/2010/03/22/
setTimeout vs setInterval
In Firefox I'm getting a limit of 14 FPS using setInterval(), but with setTimeout() my frame rate is 88 FPS!
Code example here:
var fps; var startTime; var diffTime; var rate = 10; var frames = 0; function countTimeRecursive() { time = new Date().getTime(); diffTime = (time - startTime); frames++; if (diffTime >= 1000) { fps.textContent = "FPS: " + frames; frames = 0; diffTime = 0; startTime = time; } setTimeout('countTimeRecursive()', rate); } function countTime() { time = new Date().getTime(); diffTime += (time - startTime); frames++; if (diffTime >= 1000) { fps.textContent = "FPS: " + frames; frames = 0; diffTime = 0; startTime = time; } } function countInterval() { setInterval('countTime()', rate); } window.onload = function() { // print and move them around // countTimeRecursive() countTimeRecursive(); fps = document.getElementById('fps'); startTime = new Date().getTime(); diffTime = 0; }
Thursday, May 20, 2010
Tracking the FPS of a Canvas Animation
// at the top somewhere var diffTime=0; var frames=0; var startTime = new Date().getTime(); setInterval('doAnimation', 100); function doAnimation() { // get the timestamp time = new Date().getTime(); diffTime += (time - startTime); frames++; if (diffTime >= 1000) { $("#fps").text("FPS: " + frames); frames = 0; diffTime = 0; startTime = time; } // animation code }
P.s. don't try this at home
while (true) { countTime(); }
And the final result:
http://jamund.com/fishes.html
Wednesday, May 19, 2010
Ad-Hoc iPad Deployment in Xcode 3.2.2 using PhoneGap
http://developer.apple.com/iphone/manage/distribution/index.action
The problem I had was that in project properties there was no option to set an Entitlements file. This is usually found in Project Settings under the Code Signing heading with the title "Code Signing Entitlements". This is not under project settings when creating a new PhoneGap project in XCode, but does exist when creating a new iPad XCode project.
In order to get Ad-Hoc provisioning to work you will need to go to the project settings menu. In the bottom left hand corner click on the icon and select "Add User-Defined Setting". For the title you will need to use "CODE_SIGN_ENTITLEMENTS" and for the value "Entitlements.plist".
Once you have done this you can follow the instructions from Apple just fine.
http://www.phonegap.com
http://developer.apple.com
Monday, May 17, 2010
Projects I'd love to work on
2)HTML5 2D game framework
3)JQuery CSS3 Effects Plugin
4)Touch-sceeen interactive displays using objective-C??
5)Top Secret iPhone game
iPad Icon Size
Icon.png 57x57 pixels (this is the standard for the Iphone)
More information can be found here:
'http://developer.apple.com/iphone/library/documentation/userexperience/conceptual/mobilehig/IconsImages/IconsImages.html
http://developer.apple.com/iphone/library/documentation/General/Conceptual/iPadHIG/DesignGuidelines/DesignGuidelines.html
http://developer.apple.com/iphone/library/qa/qa2010/qa1686.html
Friday, May 14, 2010
PhoneGap iPad Large Image Problems
I'm loading between 6-10 1-2 MB images in a page on PhoneGap. The view is essentially an image slider that you zoom into. It works fine in a browser, so I figured there would be no problem in an app. Boy was I wrong. (Also, I later checked and even in the ipad web browser it seems pretty bad).
Usually the first few images work fine and then after that they randomly work or don't work. It's very intermittent and no memory errors appear. These are images that I am loading locally. I found this very troubling at first, and it took me a while to figure out what to do.
My first thought:
Pre-loading
If I pre-loaded the images they would be ready to render at a moments notice. I tried some various pre-loading techniques people have suggested with jQuery and none seemed to work. Obviously putting more things in memory isn't going to help if it's a memory problem.
The second attempt:
Lazy-Loading
I start with all of the images unloaded (set to a low res placeholder).
<img src="grey.gif" alt="real_image.jpg" />
As they image come is approaching the screen I load it up:
var el = $("img.next");
el.attr("src", el.attr("alt")+"");
This seems to work better but with the side effect that sometimes the next image isn't loaded before it starts coming into view. And then as I carry on it still has the problem of not all of the information working properly. #fail
The third and final solution:
Lazy-loading and Pre-loading and Post-unloading
I have to lazy load the images and then UNLOAD the unused images by setting their src to a place holder image.
In order to make this work smoothly I'm using opacity and CSS3 transitions:
The CSS:
img {
-webkit-transition: all 1.5s ease-in;
}
The JS:
$("#img2").css({zIndex:1,left:0,top:0}); // put the second picture in place
$("#img1").css({zIndex:2,opacity:0}); // first image will slowly fade out
Thanks for listening.
Jamund
smooth scroll to using css3
Thursday, May 13, 2010
Cross-Domain AJAX with Jquery and JSONP
Eventually we realized that we would need to use JSONP. JSONP requires you to do things on the client side as well as the server side. We use CakePHP here at rain, so you will see that in the server code.
On the client side, as far as I can tell, POST is not an option, so use .getJSON instead
This is the client side code:
var data = $("form").serialize();
$.getJSON("http://mytest.url.com/services/server?callback=?", data, function(data) {
alert(data);
});
Here is the server side:
echo $this->params['url']['callback'] . '(' . json_encode($data) . ');';
Two helpful articles on the subject:
http://remysharp.com/2007/10/08/what-is-jsonp/
http://www.markhneedham.com/blog/2009/08/27/jquery-post-jsonp-and-cross-domain-requests/
Wednesday, May 12, 2010
Using jQuery for iPhone/iPad pinch zoom gestures
http://scriptnode.com/article/javascript-print_r-or-var_dump-equivalent/
See the Apple tutorial here:
http://developer.apple.com/safari/library/documentation/InternetWeb/Conceptual/SafariVisualEffectsProgGuide/InteractiveVisualEffects/InteractiveVisualEffects.html
Tuesday, May 4, 2010
iPhone Touch Events
This is one area that is fairly poorly documented.
In javascript with mobile safari I want to capture the mousemove event on a canvas object. It works fine in normal browsers and I'm using the technique on top here to do it in Firefox, but mobile safari won't let you use mousemove in the same way.
Mobile safari actually provides and even better event for you to use. It's called touchmove. Touch move already knows if your finger is on the screen so you don't have to check for that in your callback function. The code below replaces the code above when developing for mobile safari, however leaving them all in works well and provides mobile safari + desktop browser support for the application
The old way:
$("#canvas").mousedown(function(e) { e.preventDefault(); click = true; }); $("#canvas").mousemove(function(e) { e.preventDefault(); if (click) { sharky.y = e.clientY; } }); $("#canvas").mouseup(function(e) { e.preventDefault(); click = false; sharky.y = e.layerY; return false; });
The new way:
$("#canvas").bind("touchmove", {}, function(e) { e.preventDefault(); touch = window.event.targetTouches[ 0 ]; sharky.y = touch.clientY; });
Thanks to:
Touching and Gesturing on the iPhone
Apple Developer Reference
Drawing On The iPhone Canvas With jQuery And ColdFusion
Wednesday, April 28, 2010
Mobile Web Reserach and Twitter Info
I looked at two different reports, which both basically said the same thing.
In North America, when people use the mobile web they are pretty much on iPhone, Android or Blackberry.
iPhone: 50%-60%
Android: 10%-30%
Blackberry: 5%-10%
The rest: < 5% each
http://metrics.admob.com/2010/01/mobile-browsing-trends-from-quantcast/
http://metrics.admob.com/2010/01/december-2009-mobile-metrics-report/
Just wanted to think about twitter for a minute. Twitter gets huge percentage of its hits from mobile and processing almost a billion SMS messages a month.
http://blog.twitter.com/2010/04/cloudhopping.html
They've also said that their blackberry app gets 8% of their new sign-ups:
http://www.readwriteweb.com/archives/just_the_facts_statistics_from_twitter_chirp.php
And a WAP vs Mobile Web discussion:
http://www.balanceinteractive.com/blog/10/01/mobile-websites-101-wap-vs-css
iPhone animated moving image tutorial
http://www.permadi.com/blog/2009/05/iphone-sdk-bouncing-and-rotating-ball-example/
Here is one that lets you move an image with touch:
http://www.roseindia.net/tutorial/iphone/examples/iphone-DoubleImageMoveasd.html
Wednesday, April 21, 2010
.closest does not mean closest!
http://api.jquery.com/closest/
Monday, April 19, 2010
Functionally Equivalent
// not sure if we need $(this).dequeue(), but it works alright $(this).before( $(""+msg+"").delay(1000).fadeOut("slow").queue(function() { $(this).remove(); $(this).dequeue(); }) ); // use the built-in callback $(this).before( $(""+msg+"").delay(1000).fadeOut("slow", function() { $(this).remove()}) );
Friday, April 16, 2010
2 Great HTML5 Sites
http://html5gallery.com/ - A gallery of sites that use HTMl5. Will be posting here soon!
Tuesday, April 13, 2010
CSS3 / HTML5 Browser Support
http://www.modernizr.com/ - JavaScript Library to Detect Browsers' support. I will be using this to determine if its safe to display the new techniques on my projects.
http://www.standardista.com/hack-for-css3-supporting-browsers - Here's a hack for supporting CSS3 without compromising older browsers.
http://html5test.com/ - Some sort of weird test to see how well your browser support HTML5 and CSS3 rules. I scored 101/160 in Firefox 3.6. Source code is available!
http://net.tutsplus.com/tutorials/html-css-techniques/5-techniques-to-acquaint-you-with-css-3/ - A cool CSS3 tutorial.
http://www.zachstronaut.com/projects/rotate3di/ - Super cool 3d rotate plugin (much better than jQuery Flip if you have the CSS3 support)
Monday, April 12, 2010
jQuery Queue Re-Visited: Why doesn't clearQueue Work?
Primarily I have been using it to create pauses and delays for non-animation functions, which traditionally won't respect the .delay() function in jQuery 1.4.
I created a simple plugin that generates tooltips and want it to delay 1.5 seconds before displaying the tooltip. There are many items that can trigger these tooltips, so I tried something like this inside of the plugin:
$(this).clearQueue.delay(1500).queue(function() { // here is the hovered over element // $(this). $.get("/tooltip/data", {}, function(data) { $(data).appendTo("body").fadeIn('slow'); }); });
This wasn't working however and I was seeing dozens of $.get requests being executed to my intense frustration.
Finally I figured out the problem. The queue is not universal, it's only applied to the selector. Therefore, if I want to make essentially a universal queue I need to a apply it to an element that only exists once on the page.
I changed my function.
el = $(this); $("body").clearQueue().delay(1500).queue(function() { // here's the hovered over element // el. $.get("/tooltip/data", {}, function(data) { $(data).appendTo("body").fadeIn('slow'); }); });
Hurray No more overlapping get requests and ugly tooltip flicker nonsense!
Jamund
Thursday, April 8, 2010
Wednesday, April 7, 2010
Write Panels & Widgets With Wordpress
I think a Write Panel is like a Write Post or Write Page type page. A Write Panel is the ability to essentially create a "page" using a special screen that only requires certain input fields.
So instead of a normal title and content you could create a new "Client" page where it requires only specific fields of "Client Name", "Business Address", and "Logo".
I guess that kind of makes sense, but it's very much not what I want. I think I am looking for Text Widgets instead!!!
http://www.quickonlinetips.com/archives/2007/11/how-to-create-multiple-dynamic-sidebars-for-wordpress-widgets/
http://wordpress.org/extend/plugins/rich-text-widget/ - BREAKS WORD PRESS
http://wordpress.org/extend/plugins/rich-widget/ - Haven't been able to try it yet
http://yoast.com/conditional-wordpress-widgets-with-rich-editable-text/ - custom fix, looks hard.
http://www.findableblogs.com/plugins/wysiwyg-text-widget/ - Does not work in new versions
After that I gave up on using widgets and found my solution. Custom fields and Front End Editor
http://wordpress.org/extend/plugins/custom-field-template/ - This is the one that worked for me!! Allows WYSIWIG editing of custom fields.
http://wordpress.org/extend/plugins/front-end-editor/- Allows In-place WYSIWIG editing. This also worked for me after making the modifications listed here :
http://wordpress.org/extend/plugins/front-end-editor/faq/ - Modification for custom fields
Tuesday, April 6, 2010
[Tue Apr 06 09:11:30 2010] [crit] [client ::1] (13)Permission denied: /Users/jamundf/Sites/website/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable
[Tue Apr 06 09:11:30 2010] [crit] [client ::1] (13)Permission denied: /Users/jamundf/Sites/website/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable
I scoured the Internet for a solution and found nothing. I tried chmod 777 on .htaccess and used xattr to remove other flags on the file.
Turns out it was even simpler than that. The parent directory had bad permissions and as such I couldn't read it.
The solution:
chmod 755 website/
Simple!
Jamund!
Friday, April 2, 2010
Awesome reference to remotely hosted content
http://cdncatalog.com/
While I'm at it I've read some useful jQuery "most important functions" article lately. They're handy at least for an overview of some useful features. You might even discover something new. Here are a few:
http://net.tutsplus.com/tutorials/javascript-ajax/20-helpful-jquery-methods-you-should-be-using/
http://www.tvidesign.co.uk/blog/improve-your-jquery-25-excellent-tips.aspx
http://haineault.com/blog/84/
Wednesday, March 31, 2010
PHP Random Color
<?php $hexColor=dechex(rand(0,255)).dechex(rand(0,255)).dechex(rand(0,255)); ?> <div style="height: 100px; width: 100px; background: #<?php echo $hexColor; ?>"> </div> // thius one works a little better <?php $hexColor=str_pad(dechex(rand(0,255)), 2, "0", STR_PAD_LEFT).str_pad(dechex(rand(0,255)), 2, "0", STR_PAD_LEFT).str_pad(dechex(rand(0,255)), 2, "0", STR_PAD_LEFT); ?>
Monday, March 29, 2010
ajax load a jquery ui dialog box
$(function() { // ajax load a jquery dialog box $.fn.ajaxDialog = function(options) { var defaults = { autoOpen:false, modal:true, resizable:false, }; var options = $.extend(defaults, options); var id = "dialog_"+Math.floor(Math.random()*11); var el = $(" ").attr("id", id); $(this).after(el); el.dialog(options); $(this).click(function () { url = $(this).attr("href"); $("#"+id).load(url,{}, function() { $(this).dialog('open'); }); return false; }) }; $("a.dialog_link").ajaxDialog({width: '890px', height: '800px'}); });
Thursday, March 25, 2010
jQuery Flip Plugins
http://www.zachstronaut.com/projects/rotate3di/#demos
This is the perfect flip, exactly what i was looking for. It requires a few includes and does not support older browsers at all (it requires css3 support, which is rare amongst browsers). While it's what I want, I can't use it because it's not compatible enough with anyhting.
jQuery Flip Plugin:
http://lab.smashup.it/flip/
It's a good looking flip, except that it doesn't really do images properly. It only does the flipping motions with a gray background (or color of your choice), does a pretty smooth flip and then returns whatever content you had to the box. It might be okay with a black background, but not exactly what i was looking for. However, it does have full browser support, so you can't really complain
jQuery Image Flip
http://webmuch.com/image-flip-using-jquery/
This kind of works, it's not really flipping. It's squashing and expanding, but it could do possibly. Hmm.
Wednesday, March 24, 2010
jQuery .queue() and .dequeue()
There are the following functions:
.queue()
.stop()
.dequeue()
.clearQueue()
The normal queue() is the "fx" queue, which you can use for chaining effects (and it is used by default in the background). Hopefully with this command I can add things to the "fx" queue that can take advantage of some of the other chained functions like .delay() without having to use the animations hack. Hurray. Also stop() is cool, because it's a essentially a "pause" button, though I don't know how to resume() =)
Hopefully, I will post more on this soon!
Once I get it figured out!
- Jamund
Fun with offset and position
.offset() - returns the position relative to the page
.position() - returns the position relative to the container div
The following works assuming that both #head and #neck are located within the same container div.
// grab the offset relative to the page pos = $("div#head").position(); // make some changes pos.top += ("div#head").height(); // attach the neck on the head $("div#neck").css(pos);
The following works no matter where the divs are located.
// grab the offset relative to the page off = $("div#head").offset(); // make some changes off.top += ("div#head").height(); // attach the neck on the head $("div#neck").css(off);
Both have their merits. Occasionally using position you might find your tooltip clipped by the container div, so attach your tooltip to the body of the page and then absolutely position it on top of the container div but still in the correct location.
Hurray for the nerdery.
jQuery Random Filter
This is awesome by the way. I've made one small change that apparently makes it more browser compatible.
$(function() { $.jQueryRandom = 0; $.extend($.expr[":"], { random: function(a, i, m, r) { if (i == 0) { jQuery.jQueryRandom = Math.floor(Math.random() * $(r).size()); }; return i == jQuery.jQueryRandom; } }); // hide a random div on your page $("div:random").hide(); });
Monday, March 15, 2010
Single Page Web Design
- http://www.instantshift.com/2009/06/10/88-single-page-website-designs-for-design-inspiration/
- http://www.instantshift.com/2009/09/15/65-new-examples-of-beautiful-single-page-website-designs/
- http://www.instantshift.com/2009/06/27/74-fresh-examples-of-beautiful-single-page-website-designs/ - (Check-out #7, 17, maybe 18, 41 )
- http://www.instantshift.com/2009/08/21/beautiful-single-page-website-designs-65-new-examples/
- http://www.instantshift.com/2009/07/24/70-inspirational-single-page-website-designs/
Saturday, March 13, 2010
Utah Web Design Companies
Ugly Fruit Media -Brand new start-up out of Provo, Utah. These guys have a lot of experience with front-end development and they do great work
BP3 - Based out of Springville, these guys do some pretty cool sites using Joomla. They are experts at that and can also do Facebook applications and help with advertising and social networking.
Media Rain - My current employer. This place makes the best websites, FLEX, and iPhone apps in the industry. I love them!
Friday, March 12, 2010
Environmental IT
Here are some of the main areas where green IT can come into play:
Virtualization - This technique uses software from XEN, VMWare or others to have several virtual server platforms running on the same system simultaneously. The argument is that the biggest environmental impact of computing is not just energy, but also the equipment. Being able to squeeze 2-20 servers onto one physical machine saves a lot energy and precious resources.
Less-intensive cooling - A big thing right now is trying to figure out how cool we need to keep servers. A big factor in data center energy use is in cooling the servers. A popular school of thought is to have hot rows and cold rows in the data center. The differences in air temperature creates drafts that keep the servers relatively cool in addition to what the cooling system already does. It's a good idea, but the question remains if they even need to be that cool. How hot can you keep the data center. Can you avoid not including all of that air conditioning. Can you use natural sources such as water to do the cooling that might not require as much energy to pump through? A lot of good work is being done here.
Fancy Websites
http://www.chromeexperiments.com/ - These are some of the finest examples of what's capable in a modern browser around. Making extensive use of the HTML5 Canvas and many other techniques. Some of my favorite examples are jsCanvasBike, 100 Tweets, Canvas 3D Engine, Colors Cube.
They're all very cool and fun examples of what can be possible in a modern browser using Javascript and HTML5 Canvas.
Wednesday, March 10, 2010
SQL Date Queries
SELECT FLOOR(PERIOD_DIFF(Test.taken, NOW())/12)) AS "Years Ago" FROM tests TestHow many people took the test per "years ago"
SELECT COUNT(*),FLOOR(PERIOD_DIFF(Test.taken, NOW())/12)) AS "Years Ago" FROM tests Test GROUP BY FLOOR(PERIOD_DIFF(Test.taken, NOW())/12))
How many people took the test between now and 2 years ago?
SELECT COUNT(*) FROM tests Test WHERE Test.taken >= DATE_SUB(NOW(), 'INTERVAL 2 YEAR')
How many people took the test between 2 and 3 years ago?
SELECT COUNT(*) FROM tests Test INNER JOIN users User ON User.id = Test.user_id WHERE Test.taken <= DATE_SUB(NOW(), 'INTERVAL 2 YEAR') AND Test.taken >= DATE_SUB(NOW(), 'INTERVAL 3 YEAR') GROUP BY User.id
What if a user could take the test multiple times in one year
SELECT COUNT(*),FLOOR(PERIOD_DIFF(Test.taken, NOW())/12)) AS "Years Ago" FROM tests Test INNER JOIN users User ON User.id = Test.user_id GROUP BY FLOOR(PERIOD_DIFF(Test.taken, NOW())/12)), User.id
How many times each user took a test each year
SELECT User.id, User.name, COUNT(*), FLOOR(PERIOD_DIFF(Test.taken, NOW())/12)) AS "Years Ago" FROM tests Test INNER JOIN users User ON User.id = Test.user_id GROUP BY FLOOR(PERIOD_DIFF(Test.taken, NOW())/12)), User.id
Explanation:
FLOOR - Essentially takes off the extra digits after the division
PERIOD_DIFF - The number of months between dates
Saturday, March 6, 2010
Coda Plug-ins
Thanks,
J
1. Coda PHP Toolkit
This plugin helps you validate your PHP code inline, allowing you to spot errors before going to your web browser for testing. Very helpful. It also allows you to Tidy your code and strip white spaces. It's great.
2. Apache Configuration Module
When I first setup a new box and get Coda installed on there the first thing I do is setup a "Site" for editing my local XAMPP configuration and adding new vhosts. Obviously, a minor annoyance is that there is no built-in module for viewing apache configuration files. I love this plugin.
3. Lorum Ipsum Plugin
This really simple plugin just generates gibberish text useful for creating mockups that have content that looks slightly more realistic than "123. 123. 123. 123. 123. 123. 123" copy and pasted a million times.
4. MD5 Hash Plugin
This simple plugin helps when you're debugging things that need MD5 content like passwords and gravatar URLs. It's really basic, but I've used it a lot, actually. It's highly recommended.
5. PHP Docblock Generator
I know, comments, really, but they're actually really important and this will automatically add a comment to your function that includes the parameters and some basic information. Quite nice. And helps your comments maintain a bit of posh formality.
6. Pastie Plugin
Pastie is a simple site that lets you post snippets of code for yourself or sharing with others. This plugin makes it super easy to share your code with the world!