I created a WordPress site for a client who needed to support both English and Español versions of their content, which involved using a plugin called MultilingualPress that creates relationships between sites for each language.

I developed the site locally on my server, and then after they created some content, migrated it to their hosting service.

Continue reading

I love Firebug, and I’m getting so I understand jQuery pretty well.

I often drop into the console and type in jQuery commands to figure out how to get things to happen on a page. For example, I was looking at a really long page of search results from Taleo that lists out all of my submissions for jobs at CACI. The problem is, that it shows the fully active submissions with the inactive ones, so it’s not very useful for figuring out what I need to follow up on.

 

So it occurred to me that if I could just write a couple lines of jQuery to look for the items that include “Active” in them, I could reduce this list in a way that would be meaningful for me.

So the first thing I did was go look at the page HTML to figure out whether there was something on the page I could use to separate out each row on the search page.

 

 

 

I fired up Firebug by right clicking on one of the items and choosing “Inspect in Firebug”.

 

 

 

 

 

 

 

 

 

 

This starts up Firebug (if it isn’t already showing) and took me to the part of the HTML that I was looking for:

 

 

 

 

 

 

So now I knew I needed to look for something that had a class of “iconcontentpanel” that contained the text “Active”.  I decided to outline it with a green dashed line, so my jQuery looked like:

So I flipped over to the Console in Firebug and tried running that:

 

 

 

 

 

But that gave me an error since there is no jQuery on the original page. But there’s this nifty little thing in the console that says “jQuerify”, and clicking that injects jQuery into the page:

 

 

 

 

 

 

So now that jQuery is available, running the script again gives me what I was looking for:

 

 

 

 

 

 

 

And of course I can add even more jQuery to strip out unwanted parts of the page, change format, etc, leaving me something that is more  actionable:

Enhanced by Zemanta

Since last week, I’ve been immersed in coding and development education about various cloud applications.
Google Wave

First there were a couple of meetups about the Google Wave product that gave me a overview of some of the capabilities and requirements for developing applications around the Wave product. Google Wave is an interesting piece of social media that is a bit like chat and MediaWiki combined with WebEx.

The first talk on Monday, was about the federation server, which is the open source implementation of Google Wave. The idea is that you could have a Wave server inside your firewall that could protect your data, while also allowing for communication and interaction with other federated servers. The code is so new, that it is actually using a different protocol than the Google Wave servers are using.

This is a very early prototype, but the idea is that it will use standard XMPP servers to communicate between domains, and use typical certificate based trust mechanisms to authenticate between domains. The internal server could be implemented with rules to (for example) prevent patient data from being sent outside of the firewall in a conversation between a medical team and a provider at another institution.

The next talk on Wednesday was about writing extensions for Google Wave. These extensions are UI widgets (called Gadgets), and Robots, which add capability to Google Wave.

A Gadget is basically an HTML and JavaScript snippet that does something useful when added to a Wave. A Robot is a bit of code that interacts with the Wave as if it were one of the collaborators in the wave. The Robot can add participants, Gadgets and edit the contents of the Wave.

As an example, you could have a voting Gadget, that allows the collaborators to vote. A Robot could add the Gadget to the Wave,  tally the results, and write them out to a database.

A Robot can also do interesting things like watch the wave for keywords and make changes or respond. Some of the examples are a grammar checker that corrects grammar as you type, a code formatting and highlighting robot, and the classic Eliza conversational robot.

Next was the weekend long GTUG Campout at the Googleplex. This was a heads down coding adventure where the idea was to get a workable Google application up and running in 48 hours. I signed up for the campout a while back, with the intent of learning how to work with Google Wave.

I had signed up for a Wave sandbox account when it was first announced at the Google I/O conference, so I was able to play with it a bit, but hadn’t really had time to get started with developing anything. After the talk on Wednesday, I had a pretty good overview of how to get set up, so at least I had all the bits installed to parcipate.

So Friday came and I returned to Google once again. The idea was that we form teams to develop applications using the Wave extensions, so the first task was to come up with ideas and pitch them. After the 50+ people got through with their 5 minute pitches, we networked for another hour forming teams. There were many ideas that were very similar, and for the most part these groups joined up into a combined team.

After the teams were formed, the Google team gave another talk about developing Wave extensions, which was a great review and contained some things that aren’t really documented elsewhere (since the API is still changing). The slides from that talk became my guide to building my first robot, an experience that I’ll talk about in another post about the GTUG Campout 2009.

I’m on a quest to make my application provide RESTful web services. After much digging, I found a post by Chris Hartjes at http://www.littlehart.net/atthekeyboard/2007/03/13/how-easy-are-web-services-in-cakephp-12-really-easy/ that helped a lot.

Turns out that Cake has some really nifty built in support that can be turned on really easily. For basic XML support, all you need to do is to add a couple of lines to your routes.php file to allow Cake to handle XML. This is pretty well described in the Cookbook at http://book.cakephp.org/view/477/The-Simple-Setup

So for my VolunteerCake project I added the following lines to my routes.php:

The mapResources() does the magic that maps the REST requests to the actions in the controllers, and the parseExtensions() sets up Cake to do some other routing magic when the request has a “.xml” extension.

So now if I call any of my actions and append “.xml”, Cake changes the response type and view to return XML. Next we need to add the view for the XML, which goes in the xml directory under the view we are REST enabling (e.g.- for jobs, we have a views/jobs/xml directory where the view CTP files need to be placed).

First I created the xml directory under the views/jobs folder, and next I created an index.ctp. This is a very simple file, which Cake’s XML helper to spit out the data with the following code:

Now to get the XML to display, all I have to do is create the appropriate views for my REST actions.

So for example if I go to the app/jobs action, I would normally see the XHTML representation of the page like:

VolunteerCake Jobs

Then if I append “.xml” to that same URL, I get the XML back as shown in the following screen shot:

Screen Shot 2013-06-16 at 10.51.23 AM

Next we need to do the view.ctp to provide support for sending back the data for a specific job by ID. This is practically identical to the index.ctp, except we’ve modified the code to use the variable $job instead of $jobs (since that’s what Cake returns):

This allows us to get the behavior of being able to get the XHTML for a specific job by using a url like /jobs/view/1 as shown:

Screen Shot 2013-06-16 at 10.53.03 AM

 

Then by appending “.xml” to that same URL, we get the XML for the job with ID of 1:

Screen Shot 2013-06-16 at 10.55.35 AM

You may notice that the XML for this Job has a lot more data than we saw when we got the list for the specific Job. The XML from /jobs.xml is only one level deep, while the data from /jobs/view/1.xml has a hierarchy of a job having slots, which in turn has a job, user_slot and user.

That happened because the index action was set up to only get the data from the Jobs, while the view action had recursion set in order to gather all the related data. By setting the recursive var to 0 (zero) in the index action, we get no children, while in the view action we set the value to 2 (two) which tells cake to fetch all the HABTM data (see: http://book.cakephp.org/view/439/recursive for more on this). Alternatively we could do a specific find and modify which bits of data we populate in the controller to determine what data gets spit out in the XML (this would alleviate the one potential downside to this approach which is that ALL of the data fields and tables are currently being placed out in the XML stream).

The basic point here is that we now have a working RESTful service (at least as far as fetching data) that doesn’t require a great deal of specific view code.

Next: completing the RESTful CRUD

Enhanced by Zemanta

I have a new open source project at VolunteerCake that is using their recently released web hosting service. This service includes the typical LAMP stack with MySQL, Apache and PHP, so I thought it would be a great place to keep a demo of the site running.

It was working fine, and then one day I noticed that the pages were being over aggressively cached. For instance, if I clicked the login button on the front page, and logged in successfully, I expected to see a “logout” button and my user name, but instead was seeing the original page. By hitting “shift-refresh”, I was able to get the right page to display, but obviously that wasn’t a good way to demonstrate the software.

 

During my work on figuring out my Plaxo problem, I found a really cool tool called Fiddler2 that acts as a web proxy and lets you do nifty things like see the headers on web requests. Using this tool, I was able to look at the cache headers being sent by the server which looked like:

HTTP/1.1 200 OK
Server: nginx/0.6.31
Date: Tue, 18 Nov 2008 22:02:49 GMT
Content-Type: text/html
Connection: keep-alive
X-Powered-By: PHP/5.2.6
Set-Cookie: CAKEPHP=b7pvoorvj11tb45micnfqhc4b2; path
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Cache-Control: max-age=172800
Expires: Thu, 20 Nov 2008 22:02:46 GMT

Content-Length: 444

The part marked in red was the problem, the Cache-Control and Expires headers were being set to 48 hours in the future for my pages, so the browser was displaying the cached version of the page instead of asking the server for a new copy.

Knowing this, I opened a case with the SF.net support team to see if they could help figure out why the server was setting these headers for the PHP pages. I had a suspicion it had to do with the fact that Cake uses a new file extension of “.ctp” for the view files, but I really had no proof of this.

The SourceForge.net guys told me that their service had just been moved to some new servers, so it was possible this was related to that. They suggested that my application was responsible for setting the cache headers. While Cake does do some caching, it didn’t fit with what I knew. This exact same setup was working on my hosting service at http://volunteer.lctd.org/, which didn’t send those same headers.

I did some research on the Apache settings for cache, and while it is generally something you do at the server level, I found that it is possible to override these settings in the .htaccess file for a particular directory. Having had to tweak this file before to get Cake to work properly, my .htaccess file looked something like:

So what I needed to do was to tell the server not to set the Cache-control or Expires headers. After some experiments, I ended up with a new .htaccess file that looked like:

Which basically turned off the whole caching on the http://volunteercake.sourceforge.net site. Since this is just a demo application, I figured that was good enough, so I didn’t spend any more time on figuring out how to restrict the change to a specific type of file (which would be important if this were a large application).

Enhanced by Zemanta
Posted in Web.

I spent some time yesterday figuring out CSS problems for Job Connections.

The Job Connections site was built using a CSS for printing that wasn’t including all of the parts of the page that should be printed. They use a stylesheet called print.css, and when somebody would try to print a page, they weren’t getting anything but the text in the middle of the page.

I took a look and found that the stylesheet was setting all of the region styles to “display: none”, which tells CSS not to display them. Editing the stylesheet to remove these bits was all that was needed, so I set it up to print everything but the menu bar at the top and down the side.

In the same file, there was a reference that looked like an attempt to make the links display as bolded when the page was printed. The code that was trying to do this looked like:

 

That wasn’t working, mostly because the style was being applied to all anchors. I updated it to look like:

This change applied the style to both links and visited links. I then went one step further and added some magic to get the actual link to print (works in CSS2 compliant browsers):

The magic is in the “:after” bit, which basically says “after you display the link, display something else”. With this applied, the links all get bolded, underlined, and are followed by the actual URL in parentheses afterward.

I got access to the web site (thanks to Walt Feigenson), so this is partially fixed now. It looks pretty good except the content still has quite a large area of whitespace to the left due to the way the style sheets are interacting. I’m playing with updating this now to make the print CSS work the way it should and not inherit the styles that cause this from the “screen” CSS.

Enhanced by Zemanta