New(ish) CSS Gradient rules imposed for webkit
So, I’m working on the new version of nerd appropriate and am making heavy use of CSS3 for the site. Why? Because drop shadows are a pain in the ass when done graphically and since we are in 100% control of how this site goes out I am making sure it degrades nicely, but isn’t necessarily pixel perfect on all fronts. So if you’re using modern builds of Chrome, Firefox, Opera, IE, or Safari you’ll receive the full featured site, if not you may not get 100% of everything, but I’m doing my best to make sure interaction works the same across all platforms (with fallbacks for things like the history API in HTML5 and using hashbangs for those not blessed with a modern browser).
Getting back to gradients. In webkit you made gradients using the following standard:
-webkit-gradient(linear, left top, left bottom, color-stop(0, #666), color-stop(.5, #333));
This would be the prefixed “gradient” background-image. The first parameter being what kind of gradient, in this case linear, the next two were directions for where you wanted to gradient to go, in this case from the top left to the bottom left (90deg) and then the final two parameters are what are called “stops”. This means that from 0 to 50% of the box I want a gradient that smoothly moves from #666 to #333.
The rendered effect would like the following:
![]()
A nice rounded off look. I won’t even get into how we do it in images because it is a much longer process. So moving forward. While perusing the webkit blog today I noticed that earlier this year they had updated their CSS standard to include a more “mozilla-ey” way of doing gradients. This is good news, it means we are moving towards a standard and while I may have slightly preferred webkits somewhat more verbose take, I must say I am enjoying how it works now.
So this same effect from above would now be written as follows:
-webkit-linear-gradient(top, #666, #333 50%);
You may say “SACRE BLEU, that is so much shorter!” I agree, it is. It is a much more compact way to write it, but for some reason and this is just personal tastes, this feels less readable to me, but I will take less readable for shorter code I guess. It is a fair trade off. To translate this:
We now prefix with both webkit for browsers and the gradient type, in this case linear. We then tell it where we want to start, it can be a direction or degree. If omitted it just assumes left to write. We give it a color and starting point, and then more colors and starting points. So the #666 will smoothly transition into #333 over 50% of the box. We could add as many colors as we want here. The only thing we can’t do (logically) is change direction.
This method works for both mozilla and webkit. Webkit is still allowing the old way, but don’t be surprised if that starts to fade. A move to standards is always a better thing, and this concise short code makes that transition that much easier to swallow. Gradiate away!
Nerd Post: Why I’m moving to closure for some of my projects
I’ve been working on an HTML5 app for the chrome store for a few weeks now, it started to slow down recently because I was getting worried about something. You see, I had been using jQuery as my library of choice. and I still love me some jQ. This is not a bash jQuery post, but more to speak towards the limitations I feel it is beginning to impose on me.
This app is built almost entirely JS and allows users to upload, manipulate and group images. When I first thought about it, I planned it out as a series of jQuery plugins which while sound in jQuery development becomes a nightmare of passing functions and variables around, possible duplicated code, and a spaghetti of a mess. I stopped, took a breath and looked around. After looking for a bit I found Closure and Backbone.
So, why closure? Well, I like the compiler and I’m an unabashed Google Fanboy. Could I probably organize my jQuery better and deal with the pain of passing data around (which granted the .data() makes a lot easier), or do I use this as an excuse to expand my skills. Since my timeline is essentially non-existant I decided to step back choose a new path and move forward. The things I like so far about Closure:
- Built in templating (that looks a lot like mustache) but is its own beast
- The compiler, that magical compiler.
- Built in goog library of ui/event driven libs
- Namespacing - hence the organizing
I’ll keep this blog updated with how it goes, but so far, with only one minor hiccup, I’m having a blast. Onward to JS heaven!
Nerd Post: The plot thickens with the filesystem
So in my earlier post (http://8bitorange.tumblr.com/post/6520843543/nerd-alert-web-workers-and-the-filesystem) I wrote about some issues I hit with web workers and filesystems. I talked to a couple of friends and the web workers may have just been me non-intelligently spawning to many workers at a single time. I will be revisiting that at a later date. But the files with a # in the name intrigued me. So I put a little test together today with the following files:
- a.rtf
- a^.rtf
- a-.rtf
- a,.rtf
- a!.rtf
- a’.rtf
- a().rtf
- a&.rtf
- a%.rtf
- a$.rtf
- a#.rtf
- a|.rtf
- a*.rtf
I then ran them through the following script:
self.addEventListener("message", function(e){
var $this = self;
var file = e.data;
$this.webkitRequestFileSystem($this.TEMPORARY, 5*1024*1024, function(fs) {
fs.root.getFile(file.name, {create: true, exclusive: false}, function(fileEntry) {
fileEntry.file(function(f){
if(f.size !== 0){
var date = new Date();
var newName = date.getMilliseconds() + '_' + file.name;
fileEntry.copyTo(fs.root, newName, function(entry){
entry.file(function(newFile){
$this.postMessage({'success': true, 'msg': 'File Written', 'file': newFile});
});
});
} else {
fileEntry.createWriter(function(fileWriter) {
fileWriter.write(file);
$this.postMessage({'success': true, 'msg': 'File Written', 'file': file});
}, function(error){
$this.postMessage({'success': false, 'msg': 'write', 'error': error});
});
}
});
}, function(error){
$this.postMessage({'success': false, 'msg': 'get', 'error': error, 'file': file});
});
}, function(error){
$this.postMessage({'success': false, 'msg': 'filesystem', 'error': error});
});
}, false);
This is pretty basic stuff, I’m just copying the file with a modified name if it does exist and otherwise writing a new file if it doesn’t. I then return what file uploaded or whether there was an error. I came upon some interesting results that I thought I would share.
All files uploaded fine with exception of 3:
- a*.rtf
- a|.rtf
- a#.rtf (as expected….sort of)
The first two threw an error and died, which is fine, now I know, but the third did something odd and unexpected. It chopped the name at the “#” and just saved “a” as a file, dropping “#.rtf”.
I’m going to keep looking into this, but for now it appears that #,*,| are all characters that are not allowed in the filesystem in Chrome.
Nerd Alert: Web Workers and the Filesystem
So I’m building something right now in pure Javascript. No PHP, it allows you to upload images, briefly edit them (basic things like brightness, size, crop, etc), and then continue on to the web service that I am back ending it with.
I thought that it would be great if on image upload, it backed up the file to the filesystem. This was going well until I uploaded a lot of pictures at the same time, things would get hairy and eventually bomb out. Then a flash bulb went off and I decided to use Web Workers to upload the image, since workers have access to the file system and the image could continue to get processed in the meantime, I thought this would be a great way to do it. I started having problems though, so I’m going to list this stuff out here, if any of the 3 of you who read this and would know this stuff have a solution I’m open to trying anything, but at this time I have moved on without either tech.
- Debugging workers: It’s a pain, at this time there seems to be no real solution around it, you just have to post messages back and hope they make it. There is a lot of finger crossing when it comes to web workers and a lot of try/catch to see if you can log an error before everything dies
- Silently dying workers: It was really weird, if I uploaded 5 at a time everything would go great and they would load as expected. If I uploaded a lot, and I’m talking a 50-100, they would load in anywhere from 7-12 and then hang. Most of the time dying error free without ever finishing their job. I’m assuming the bulk (7-12 at a time) loading was due to available threads, but could not figure out a way to manage this due to the lack of debugging. I tried storing all active workers by reference in an array and then closing off the ones that finished, but that didn’t seem to help ( I am assuming they are doing some trash management of their own ).
- File names…oh file names. You are the bastard process that screws up everything. I noticed that some files were bombing out and others weren’t. There, at first, was seemingly no pattern as to why one image would load and another wouldn’t. Then I realized it was all in the name. The ones that were dying had a “#” in them. I couldn’t find anything about name issues, but it appears that #’s are not allowed. So that’s all fine and dandy, just change the name right? Well I don’t have access to the file object in any meaningful way to change it until its uploaded (then I could do ye ol “moveTo” and change the name). I tried just manually changing it, but that wouldn’t work, which leaves me with the only other solution, which is to load each image into a canvas, output a data/image and save that to the filesystem with an arbitrary name. That is way to much “pre” work for something that was going to be a convenience for me. So I moved on without.
These three issues had me sidetracked for 2 days trying to get them to work, I ultimately decided to forgo it. Now instead, when you click to edit an image I will save a copy to my file system and version it off, that way you can go back to “snapshots” of the photo during editing, otherwise, for now, it is all destructible (don’t hit refresh).
Anyone else tried to tackle these beasts and run into these issues? Have any work arounds?
Nerd Post: A utilities component
We are finding often that we want to have cross plugin functionality and sometimes this involves a lot ( a form builder or a messaging system ), sometimes it does not ( a method to list available elements ). So I decided to make a component titled utilities and include it in our app controller by default, so that we would have a single place to gather and use some functionality regardless of which plugin you are inside.
I am posting the utility here with a method called listElements, that can be passed an array with a plugin name and a directory to search, and will return an array of the available files.
/* SVN FILE: $Id$ */ /** * Utilities component * * A place to collect useful methods within the portal * * PHP versions 4 and 5 * * CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org) * Copyright 2005-2010, Cake Software Foundation, Inc. (http://www.cakefoundation.org) * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * * @filesource * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://www.cakefoundation.org) * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project * @package cake * @subpackage cake.cake.libs.controller.components * @since CakePHP(tm) v 0.10.0.1076 * @version $Revision$ * @modifiedby $LastChangedBy$ * @lastmodified $Date$ * @license http://www.opensource.org/licenses/mit-license.php The MIT License */ class UtilitiesComponent extends Object { /* Function List Elements * Takes an array of options * plugin = plugin the element is in, if it is in one * dir = directory inside of the elements directory to search. * * This will navigate to an elements directory grab all available files and return them * in an array with their name minus the extension (ie: view.ctp = view) */ function listElements($options = array()) { App::Import('Core', 'Folder'); $folder =& new Folder(); //set our option variables and allow plugin to be null. $plugin = (isset($options['plugin']))? 'plugins' . DS . $options['plugin'] . DS : null; $dir = $options['dir']; $path = APP . $plugin . 'views' . DS . 'elements' . DS . $dir; $tree = $folder->tree($path, true, array('file')); $elements = array(); foreach($tree as $item){ $item = substr($item, (strrpos($item, '/') + 1), strlen($item)); $elements[] = substr($item, 0, strrpos($item, '.')); } return $elements; } }
Nerd Post: User tracking in CakePHP
So with this portal we are building one of the things we wanted to do was track users actions in an organized useful way. Why? To see where people are clicking, to be able to see what they are doing when they call and need help, and to help them remember and track their own actions over days. So here is what it does, very minimal, very lightweight and very simple:
if($this->Auth->user('User.id')){
CakeLog::config('custom_path', array(
'engine' => 'FileLog',
'path' => APP . 'logs' . DS . $this->Auth->user('User.email') . DS
));
$what = null;
$url = $this->params['url']['url'];
$what .= $url;
if(isset($this->data)){
$changed = serialize($this->data);
$what .= '.:||:.' . $changed;
}
CakeLog::write('activity', $what);
}
So what’s happening? First we check to see if there is a user logged in, if someone is, we setup our custom pathing to create a folder in the logs folder with the users email, so that we can easily and legibly understand who’s logs are where. Then we set the url of where they are and check if they are submitting any data. If they are, we serialize that array, attach it to the url with a unique symbol that we can seperate the data by and then we write that data to the log. This is fired in the beforeFilter of the app_controller.
What we end up with is something like this:
2010-06-03 10:36:11 Activity: items/edit/1.:||:.a:1:{s:4:”Item”;a:6:{s:2:”id”;s:1:”1”;s:4:”name”;s:6:”Portal”;s:3:”url”;s:6:”Portal”;s:6:”parent”;s:0:”“;s:5:”Group”;s:1:”1”;s:4:”User”;s:1:”6”;}}
Not to bad right? We get a date, a marker, the url and the data that moved through. Now we have an “actions” controller that will let us sift through this data and use it as needed. When I get that finished out I will post it to my github account with the other things we have come up with in this project.
CakePHP 1.3 and DomPDF
After a lot of ridiculous meddling with code, I took a break and came back to trying to get DomPDF working with CakePHP 1.3. There were a few major problems, but most have been fixed now with only a couple of styling issues to make this work.
The goal was to output an already styled HTML page to PDF with as little effort as possible, so that we could then reuse this package across multiple sites without having to relayout the pages or reconfigure the php each time. DomPDF appeared to be a good way to go about this, but the first error I was running into was DomPDF’s autoloader attempting to load cake core classes from its own include directory. I tried to figure out where this was coming from but was hitting a wall over and over again, the fix ended up being pretty simple and its this:
In the dom_configure.inc.php just add an if statement as follows
function DOMPDF_autoload($class) {
$filename = mb_strtolower($class) . ".cls.php";
if(is_file(DOMPDF_INC_DIR . "/$filename")){
require_once(DOMPDF_INC_DIR . "/$filename");
}
}
This prevents from loading anything that is not in the DomPDF includes folder. This was the first major hurtle. Still working out some major kinks on how to display the pdf.
Nerd Post: Planning…planning…planning
I had a friend post on twitter the following:
The problem with so much pre-planning and documentation is that the moment you start actually making, it’s no longer accurate. Time wasted.
Now I agree with him somewhat, but I recently began running projects here at UCF, and my team is small, and somewhat under experienced. The project was a sort of single login system for all of the staff in our college to be able to manage anything from web tickets/new projects, Help Desk tickets, Asset Management and even CMS for their departments sites. This was a big undertaking and when it began I stressed the need for planning, and a lot of it. The first was a debate over technologies. We wanted to push forward into HTML5, and heavy use of javascript, great, the problem was that our users are all using IE7. They will be moving to 8 soon, but none of them will, by default, be using Firefox or Chrome and we know it. So we had to come up with some solutions, we spent a couple of weeks working out demos and getting stats on what we could use and what we couldn’t. We learned a good bit and moved on.
Next part of planning was how we were going to build this. To say that this place was not set up for heavy code work, is an understatement. So I had to then put some standards in place. We moved into a Debian server, wrote up some PHP documentation and some JS documentation on how we would write it, set up a code repository (SVN, which I’m now regretting and thinking of switching to Git due to a couple of headaches we hit within the first two weeks), and got to work…planning.
So how planning really started was this, we (me, two developers, our designer and our work study) sat in the conference room with pencils and paper and literally drew up how we thought the “portal” would work. We all had to demonstrate with a pencil how you would navigate through the site and how it would work. It was interesting and taught us a lot of how we all think. We group voted on the best solutions from each of our versions and mashed them into one site. After that we set out on our needs, heavy use of a strong ACL system, a good quick deployable UI including a useful but extendable js library.
So then we went into what I like to call active planning. One of my developers who is basically our designer, was set to task on creating the HTML/CSS for the entire portal. Allowing us to quickly apply some classes and such and have our UI work, immediately with little to no work on our part. I don’t want to have to redesign a table everytime we put it together. I want to be able to put a table on it and call it “index” and have it look the way it should, and he’s wrapping that part up now, and it looks great and works well. No photoshop was used, he literally did all of his design work in HTML/CSS, which was gratifying to know that we don’t have to now figure out how to cut up a PS file, we have a working version of code that can be applied.
Then I wanted a JS library, that extends jQuery (our favorite framework) that could sit in our UI plugin and quickly be called and used without interfering with our structure. I don’t want to have to be doing custom js to pop up a modal window at any point. I want to say $.modal(‘type’, ‘message’) and move on. We have that now and it is great.
Last we planned how we want our DB structures to work and how we want to move from app development to deployment. We sketched it out on paper and have it in writing now.
We are now about 2 - 3 months into dev with a team of 3 and are getting ready to deploy the user system that backs every application we will be putting on top of it. I think if we hadn’t done the planning we would be trying to reconfigure every app we build, instead with the planning we have a stable UI, a solid user system for each and every app we build, which should make each of our app deployments quicker and less buggy.
I guess time will tell, but I am all for documentation, planning and process building. Without it, especially with a relatively young and tiny team, I think I would be setting myself up for disaster and a horrid rebuild cycle. Now different teams mean different processes, sometimes, scratch that, most of the time I think meetings are entirely unnecessary and hardly improve morale or productivity, but then again, some places work having meetings. To each their own and some may think my level of planning is under done, who knows. At the end of the day I think you assess where you are, assess your teams abilities and move forward with the best set of processes for you.
Nerd Post: Extending the Auth Component in Cakephp
You may have guessed by now, I do a lot of my php (if not all) in CakePHP and I really enjoy it. There are times where the core libs are good, but not quite to my liking of what I need, in this case it was the built in ACL and Auth Components. The ACL has a list of needs that I won’t get into right here and now, I will probably write a post about the custom one I am building when it is finished, but for now just understand that I needed people to be able to be in multiple groups at a time and I wanted to be able to access this information through Cake’s built in Auth component.
Up until recently I would have simply done something in the app_controller to go through and attach that data to the user data once they were logged in, but NO MORE my friends. I decided to jump in to the Core component and start tinkering. After looking at it I realized it was just one function, identify, which was attaching that user data to my Auth’s session and that was where I needed to go to access it. So I extended my Auth component and overwrote that function, really only changed a couple of lines and only added one variable to the Auth and thanks to some help from the excellent cakebaker blog and a little google groups search, this is my newly extended component with all of the trimmings to make it work appropriately without throwing a wrench into your app. Here we go:
First, go to the model you are using for your auth data (mine is User) and add the following line:
var $actsAs = array('Containable')
This attaches the containable behaviour to your model and allows us to easily associate data as needed to that model.
Second copy this code (now on github) and add it as your new component and call it in your app_controller instead of the regular Auth component, so add:
var $components = array('MyAuth');
Then in your app_controller add the following:
public function constructClasses() {
parent::constructClasses();
$this->Auth = $this->MyAuth;
}
Thanks to cakebaker for this tidbit. This allows you to still use $this->Auth uninterrupted and only use MyAuth when setting the one variable below.
After that add this in your beforeFilter():
$this->MyAuth->included = array( 'Group', 'Profile' );
You don’t have to put Group or Profile there, but those are the models I wanted to associate.
Now when you look at $this->Auth->user you will see an array containing all your necessary data. Unfortunately this completely destroys the conveinance of saying $this->Auth->user(‘email’) instead you would say $this->Auth->user(‘User’) for the User array or ‘Group’ for the group array. I will work on fixing this up and adding it as an edit to the github repo when its ready. Hope this helps anyone looking to get a bit more out of the great Auth component in cake.
Nerd Post: Working with paypal or how I learned to deal with the obnoxious
Paypal…oh paypal, in some ways you make my life so much easier, and yet in others you complicate it to no end. So if you are a developer and you’ve ever had to work with paypal you may have come across their “sandbox”. Now before we go any further I’d like to say that I appreciate paypal’s approach to sanitizing a sandbox for you to test your functionality in, and if I were building a full e-commerce site with paypal as my merchant, this would be a dream place to test and build, but I am not. I am adding a single “Pay Now” button to a form that once submitted comes back to our site and confirms that the person paid their dues. I spent no less then 45 min setting up my sandbox account and getting it working, this is not the first time I’ve had to do this, but it is for where I am now and there is some considerable setup to get it working, and a great bit of reading to understand it. There are differences between account types and I had to verify those difference and also change things to make them work as needed. None of this is to big of a deal over all, but when you add that up to test a single, simple, auto-generated button, well it is a bit of a pain. Really all I wanted was a paypal fake credit card that I could use to test whether the transaction worked or not.
Moving on, because that is not what this is about, lets assume you’ve set up your sandbox account, then setup your fake user and your fake seller account, you’ve made your fake button to test with (that duplicates, hopefully, what the real button you have does), and you are signed in and ready to go. You can do something handy, you can use whats called PDT with paypal and get information back about the transaction you just made. I thought, “wow, great, I can get back an xml feed or json object and handle it”. Nope. You get Text. Plain text, it looks something like this.
SUCCESS mc_gross=1.00 protection_eligibility=Ineligible address_status=confirmed payer_id=xxxxxxxxxx tax=0.00 address_street=1+Main+St payment_date=11%3A27%3A08+Apr+09%2C+2010+PDT payment_status=Pending charset=windows-1252 address_zip=95131 first_name=Test mc_fee=0.33 address_country_code=US address_name=Test+User custom= payer_status=unverified business=xxxxxxx%40mail.com address_country=United+States address_city=San+Jose quantity=1 payer_email=xxxxxxxx%40mail.xom txn_id=xxxxxxxx payment_type=instant btn_id=1145116 last_name=User address_state=CA receiver_email=xxxxxx%40mail.com payment_fee=0.33 shipping_discount=0.00 insurance_amount=0.00 receiver_id=xxxxxxxxx pending_reason=paymentreview txn_type=web_accept item_name=testitem discount=0.0 mc_currency=USD item_number= residence_country=US shipping_method=Default handling_amount=0.00 transaction_subject=testitem payment_gross=1.00 shipping=0.00
handy right? well…its just text, and while strings can be parsed in any language, so can xml, and strings are a pain, how am I supposed to get “payment_gross” regex? I guess, it seems pointless. So I broke up the text and made an array out of it, if you use PHP and want to borrow this, break it, steal it, re-write it, you may do whatever you’d like with it, but it has made my life easier.
$send['tx'] = $_GET['tx'];
$send['at'] = $this->paypal_test;
$send['cmd'] = '_notify-synch';
App::import('Core', 'HttpSocket');
$HttpSocket = new HttpSocket();
$url = 'www.paypal.com';
$test_url = 'www.sandbox.paypal.com';
$results = $HttpSocket->post('https://' . $test_url . '/cgi-bin/webscr', $send);\
$results = explode("\n", $results);
$final_results = array();
if($results[0] == 'SUCCESS'){
foreach($results as $result){
if($result != 'SUCCESS'){
$new_val = explode('=', $result);
if(!empty($new_val)){
$final_results[$new_val[0]] = $new_val[1];
}
} else {
$final_results['result'] = $result;
}
}
} else {
$final_results['result'] = 'FAIL';
}
Theres some CakePHP love going on in there (mainly the httpsocket class), but other then that I build the post data array i need to send to paypal, I have my urls setup for prod and test, and then I retrieve my response from paypal. I then break my response into an array by the new line (/n), and begin building my array, luckily I know what format my string is in so there isn’t much need for guessing, but I essentially then break my results array up into arrays from each line and make them a key => value associative array, making it much easier to get at “payment_gross”. Also, if paypal comes back with a fail, set the first result as “fail” and then move on, because paypal does not return much in the way of handy error codes, I felt knowing that it failed would be about all I needed at this point. What I plan to do after this is save a field in the database as “paid” and redirect them to a thank you page.
Hope this helps some paypal devs out there, it may shave a few minutes off your dealing with paypal time.
Nerd Post: the joys of xml
That title is a lie, I actually kind of hate working with XML, or at least I used to. Before I understood objects and the basics of OO programming I would get lost in traversing what could sometimes be a huge tangle of children and attributes. I am working on a new personal project in my off time. It’s partially for the Design for America link I posted yesterday, but basically I am working with Government data and thinking of new ways to simplify how to show it to people (me included).
One of the sites provides an XML sheet that lists out all members of congress and the senate along with varied data. Its a pretty massive list and could be difficult to find the data that I needed. I am building this in CakePHP, mostly due to it being what I am most familiar with, and also because in my admittedly non-technical opinion, I feel it does all the things I want it to do without complication without over including things I don’t need. Now I realize some of that is not true, Cake is a big library and can sometimes add some processing time, but if you are selective and optimize and cache, I’ve found it to be a great framework to write PHP in, but arguing frameworks is yet another post and we all know it kind of grinds my gears, what we are here to talk about today is XML and the newly discovered by me, but long existing xpath. If you know what xpath is and its old hat to you, then please feel free to move on and stop reading this post now, because this is a novice tutorial on reading in an xml file and searching it.
You ready for this big reveal…it’s going to blow your mind, I will find any congress person in the state of california with two lines of code:
$this->xml = simplexml_load_file($this->xml_path, null, true);
$results = $this->xml->xpath('person[@state="CA"]');
That’s it, but I will explain it a little bit. The first thing I am doing (and this is stretched across a few functions in my class, hence the “$this->”) is reading in the xml file I have cached on my server. After that I am returning a list of simpleXML objects that meet my search criteria. Essentially I go to the first set of children “person” and I search the attribute “state” for the term CA. You can traverse as deep as you need, I could say:
$results = $this->xml->xpath('person/role[@district="43"]');
which would return all people who are in the 43rd district. Pretty powerful and amazingly fast. You can read a lot more about what queries you can make and how to form them at the W3Schools Tutorial site as well as the W3 Doc.
I hope this little bit of information can save you a few minutes on how to query and manage XML with PHP, and if you care to share more I am just beginning to learn this as well, but always welcome opinions.
Nerd Post: Things I’m tired of…
For whatever reason, Drupal is all the rage right now. I know people that make their living off of building within drupal, and this post is not aimed at them, although I’m sure you could replace Drupal with Rails, Spring or any number of frameworks and some of this would apply, but mainly I want to address the following.
- Writing code in drupal because that way when you hire someone new, they dont have to learn your custom system is the most backward, ridiculous thought I’ve ever seen. For one, if you do it in Drupal, then you have to hire someone who knows Drupal, and to be honest, even though the community is growing, that still limits your potential talent. Here’s a crazy thought, write well organized, well documented code, use a framework if you feel like, but don’t use one that suffocates you in its own logic, do something with a common organization like MVC if you’d like. Examples on the PHP side would be Zend, Cake and Symfony, any of which, any PHP dev should be able to get in, see and understand relatively quickly without the INSANE learning curve that Drupal, ExpressionEngine, or to a much smaller degree for obvious reasons, Wordpress.
- Blaming PHP for security holes is about the dumbest thing I’ve ever heard. Now I will agree before PHP embraced OO stylings and before the advent of frameworks like I mentioned before, it was easy to write nonsecure code, but you would have to create it, through laziness and sloppiness (both of which every dev has been guilty of at some point). Now PHP has one probably large fault and that is that it is not a compiled coding language, but it really isn’t meant to be, if thats a requirement then PHP probably isn’t where you should look.
- Claiming you use or are “open source” simply because you use open source products. If you really are part of the community, you’ll put back in as much as you take out, THAT is the point of OS.
Thats it, it’s sort of a “what really grinds my gears” kind of post. Anyways, I hope you enjoyed.
Yes…another nerd post
I’m working on a project at work that is trying to mirror a desktop application as much as possible. Enter HTML5, CSS2, and a whole heaping helping of jQuery (a personal fave). I won’t lie, I’m not a hardcore javascript guy, some of this may come off as basic to some, but I extremely enjoy jQuery’s method of object input and tracking because it makes a very CSS familiar guy like me feel comfortable and happy. I’ve read the speed tests and seen that jQuery sometimes may fall behind loading to prototype or others, but for ease of use, I would maintain that it can’t be beat.
Enter current project. We are trying to make something that will be very, very easy for non tech people to log in to and manage their accounts (which include a large amount of varied media). One of my goals was to make it seamless for a user who, for whatever reason, closes the browser they are in or goes to a different page and comes back, I want to be able to take them back where they were without to much hassle. I looked at some built in jQuery solutions, which didn’t seem to match up, as well as handling it on the server-side with cookies or sessions, which honestly was clunky, and just not the right solution. Enter sessionStorage. This handy javascript, browser side, data storage object is supported across all browsers (with the exception of Chrome, who knows why, since webkit and safari seem to support it). This allows you to store session data on the browser end and barring a full browser crash on the mozilla side, allow a user to retain what you store for them in their local file system, incredibly fast, server light and honestly just fantastic. I may be wrong about this, but I believe this was created by microsoft and is one of those things that has been supported by ie for a ridiculously long time, but enter the rush of javascript heavy apps and needs should be met, and well, now you have sessionStorage with multi-browser support. So onto my super simple easy example of how I used it.
$(document).ready(function(){
//For initial load set current item to first item in list
var current_item = $("aside > nav > a.first").attr("href");
//check if there was a previous loaded item and load that item.
if(sessionStorage.current_item){
current_item = sessionStorage.current_item;
} else {
sessionStorage.current_item = current_item;
}
$("#content").load(current_item);
//handle the click event on sidebar nav
$("aside > nav > a").click(function(){
current_item = $(this).attr("href");
sessionStorage.current_item = current_item;
$("#content").load(current_item);
return false;
});
});
So what’s going on here? Not to hard, I have a nav bar that is being tracked by the class “on” as to which item is active.
- Upon first load of page it is setting a variable “current_item” that is equal to the first item in the list (which is on).
- It is then checking the sessionStorage object to see if I previously set, if it is, then set the “current_item” to the object found in the session, if not then set the session object to the first item. (I can safely assume if no session data is sent, that I would just follow the first item in the list, since it should be on the first time the page loaded).
- Then it uses the built in jQuery method of load which will load a page that is called (in this case I am loading the link in the nav)
- Finally, I need to handle the case if someone clicks a link. Essentially when someone clicks a link in the nav, it will set the session item to the clicked links url and then load the page via jQuery’s handy “load” method.
And that’s it. Not to many painful lines and yet I’ve done something very handy. Stored and tracked what a user has clicked on and insured them that if they click away or exit this page in anyway, they can get back to exactly where they were with no effort on their part. Eventually this will be used to store some form data in case of accidental page closure and we will be helping a user to keep from getting frustrated, hope this helped.
HTML5 for the lazy
Are you building in HTML5? Are you lazy? Here let me help you with something:
header, section, aside, footer { display: block; }
Your welcome, it annoyed me for about 15 min today before I realized that none of the new elements are turned on as block level elements in most (if not all, again I’m lazy, didn’t really look) browsers.
Supposedly this will be changed soon, but until it is, just throw that in at the top of your css and you’ll blissfully forget. You could include nav and article in there, but some people may not want to lay those out as block elements.