Note: If you enjoy this article, you might also check out the Geeky Stuff section.
I'm a member of the Quilting Bee and I use a very simple PHP script I wrote for displaying my quilt. I figure someone else might get some use out of it, so here it is for your coding pleasure:
<?php
// The relative URL to the directory containing my patches
$img_dir =
'/wp-images/qbee/';
// The patches in my quilt, arranged in an array of arrays
// such that each inner array contains the link URL, the
// patch file name, and the title of the patch (e.g. a
// member's name).
$patches = array(
array( 'http://www.theqbee.net', 'qbee.gif', 'Qbee home' ),
array( '/', 'mine.gif', 'My patch' ),
array( 'http://www.theqbee.net', '164.gif', 'My number' )
);
// The total patches in my quilt
$num_patches = count( $patches );
// Decide how many patches to show in a row. The idea
// is to show the patches arranged in a square; that is,
// each side should have the same number of patches.
$num_per_side = ceil( sqrt( $num_patches ) );
// Since each patch is 40 pixels wide and 40 pixels tall,
// we can decide how wide to make the quilt container,
// based on that and how many patches we want per side.
$quilt_width = 40 * $num_per_side;
// Contain the quilt within a paragraph of the determined
// container width. Also give it a position of 'relative' and
// an auto margin on either side so that it centers itself
// within the page. Embedded CSS, run away!!1
echo '<p style="width: ' . $quilt_width . 'px; margin: 10px auto; position: relative;">';
// Go through the patches and stick them in the paragraph.
foreach ( $patches as $count => $patch ) {
// Give more verbose variable names to each part of the
// current patch.
$url = $patch[0];
$image_name = $patch[1];
$title = $patch[2];
// Define the whole path to the patch image.
$image_url = $img_dir . $image_name;
// Display each patch
echo "<a href=\"$url\" title=\"$title\"><img src=\"$image_url\" alt=\"$title - $image_name\" width=\"40\" height=\"40\" /></a>";
// Stick in a line break if we've now got the right number
// of patches on this line.
if ( ($count + 1) % $num_per_side == 0 )
echo '<br />';
}
// Close our containing paragraph.
echo '</p>';
// Display the stats of how many patches are in the quilt.
echo "<p><em>$num_patches patches in my quilt</em></p>";
?>
I just embed the above code in my Qbee page. Since I use WordPress, I have to enable PHP for that page using the runPHP plugin.
- Time:
- 12:06 AM
- Categories:
- PHP
- Tags:
- PHP, programming
- Comments:
-
2 comments / Add a comment »
- Music:
- Frontier Psychiatrist by The Avalanches
Note: If you enjoy this article, you might also check out the Geeky Stuff section.
Recently for work, I’ve had cause to write functionality so that a certain chunk of a form can be inserted again, over and over, by the user. The form involves data about course equivalencies between schools, and the user might need to submit data for multiple courses a student has taken. Hence, the user needs to be able to add extra course sections on the fly, as they’re necessary. Here’s a screenshot to better illustrate what I mean:
I decided to do this with Javascript, but the question was:
- Should I dynamically generate the extra form fields with Javascript before stuffing them into the DOM,
or
- Should I have a separate page, containing the form fields written in plain HTML, that I dynamically insert into the form page via an AJAX call?
Contemplating the idea, I decided the best route would be to use AJAX. Here are some guidelines for making such a choice, based on the logic I used:
- Are you generating a lot of code?
- If you’re going to be generating a lot of code each time, like in my example, the AJAX route makes more sense because you can have a separate page (PHP for me, but you could use a straight HTML page) to write that content in HTML, then use an AJAX call to include that page in your main page. See, if you were to use Javascript for dynamically creating elements (
document.createElement() and element.appendChild() are your friends here), you’re going to write a lot more code in Javascript than the straight HTML it takes to create various elements and their attributes. In my case, with Javascript I would be generating li’s, span’s, fieldset’s, input’s, and legend’s, then several of those had the attributes rel and class, not to mention the normal attributes associated with input. It’s simpler to write out the HTML for this in a separate page, rather than have lots of Javascript functions for creating those elements, applying attributes to them, assembling them together, then stuffing the result somewhere in the existing page.
- Does the dynamically added code replicate content already in the main page?
- In my example, the main form page started out with one course section already showing up. If I were to use straight Javascript DOM manipulation to allow the user to insert extra course sections, I would be replicating the same content in two ways: in the main HTML page, and in the Javascript necessary to generate a new course section. Being a Ruby girl at heart and a big supporter of the DRY principle (Don’t Repeat Yourself), it hurts something deep inside of me to duplicate that much functionality in my application. Well, maybe I’m exaggerating a bit, but I gotta stress this, because such replication leads to harder-to-maintain code. Any time you want to change the teensiest thing, you have two places in which you need to change it: the original HTML, and the Javascript that creates the same chunk of HTML before inserting it into your page. Going the AJAX way here would be best.
- Are you adding only a small piece of HTML?
- If you want the user to be able to dynamically add a single link or something equally trivial to your existing page, the AJAX route might be overkill. The Javascript necessary to generate one or a couple HTML elements isn’t overly complex or lengthy, and so it makes sense to use Javascript element generation followed by DOM manipulation to add your new content. I think it would be more trouble than it’s worth to have a separate page containing just a link or two, and then use AJAX calls to stuff that snippet page into your main page.
- If your dynamic content isn’t complex now, do you foresee it becoming so in the future?
- Maybe for the time being, the user only needs to insert a couple of elements into the page at his or her whim, but in the future, you think your application will expand such that large chunks of HTML will need to be added at a time. In this case, you might start off with the AJAX route just for your future convenience (or the convenience of another developer—be considerate of the next guy, right?). It’ll make your page easier to expand in the future, since you won’t have to remove all the Javascript content generation code, create a separate page to hold the content to be dynamically added, then write the AJAX calls to include that content as the user desires.
- Are you using a PHP (or similar server-side language) back end?
- The site I was creating my example form for uses PHP, so the AJAX route especially makes sense here, since I can make the dynamic addition of content be available for the user even if they have Javascript disabled. I’ll just use PHP to parse a POST request and decide how many course sections to include (using a loop and PHP’s
include on the separate snippet page of content), based on how many they currently have and how many extra they want to add. With the Javascript content generation route, this sort of thing is impossible, because Javascript is entirely client-side, and if the user doesn’t have it enabled or their browser doesn’t support it at all, they’re up a creek. Oh sure, you could have the non-AJAX version for those with Javascript, then write functionality in a server-side language to allow the user the same functionality without Javascript enabled, but there you go again with the replication of functionality—bad programmer! If you’re stuck with just HTML, though—which I have to guess is unlikely in this day and age, what with every Tom, Dick, and Harry of hosts supporting PHP, Perl, JSP, and Ruby—you’ll need to determine whether to go AJAX or Javascript-content-generation based on the other questions raised above.
- Time:
- 6:41 PM
- Categories:
- Javascript, Web development
- Tags:
- ajax, Javascript, list, programming
- Comments:
-
0 comments / Add a comment »
- Music:
- 11h30 by Danger
Note: If you enjoy this article, you might also check out the Geeky Stuff section.
I'm so tickled I can't stand it. All right, so Speech Recognition stuff on a Mac is pretty darn cool by itself, but now I've got a nice Apple Script that opens up Safari with various tabs of my favorite sites, and it does this when I tell my Macbook "Get on it." Here's how I did it:
- Under System Preferences > Speech > Speech Recognition, make sure "Speakable Items" is set to "On." By default, to issue a voice command, you'll have to hold down the Esc key while you talk. I changed mine to the back tick because I use Esc in other applications to do other things; it's whatever works for you. If you want to change this, change the "Listening Key".
- Open Applications > AppleScript > Script Editor and enter the following code:
property links :
{"http://mail.google.com/mail/",
"http://www.3till7.net/wp-admin/",
"http://dubious.nu/forum/index.php?action=unread",
"http://icanhascheezburger.com/"}
tell application "Safari"
activate
set currWindow to front window
repeat with link in links
make new tab at the end of tabs in currWindow with properties {URL:link}
end repeat
end tell
Thanks to Takashi Yoshida for the basis of this script. Feel free to change the links shown to whatever you want Safari to open up with. I imagine this script could also be customized for Firefox, Opera, or whatever other browser you use, but that might take some fiddling around.
- Hit the Compile button in Script Editor and make sure the code gets syntax highlighted nicely, with no warnings displayed. Go ahead and save this script wherever you would like, but give it a name like "Get on it" or something like that. Not "get_on_it", but using spaces and everything.
- Copy your snazzy new script to Library > Speech > Speakable Items. If you're copying the script with Finder, that is your local Library, so the one inside your home folder.
- Hold down Esc (or whatever you set your Listening Key to be) and say, clearly, "Get on it". If all goes well, Safari should pop open with your links opened in separate tabs, with a blank tab showing. If you already have Safari open, this will just open up those links in new tabs, leaving your current tabs alone.
Pronunciation Issues
Being a southern girl by the grace of God and all that jazz, I have a bit of an accent. For me, my Apple Script works better if I name it "Getawnit", which looks more akin to how I sound so that the voice recognizer does a better job of understanding me. You want how the Mac says it to match how you're saying it. One way to test this is to have the Mac say the written version of what you want to say as your command:
- Under System Preferences > Speech > Text to Speech, check "Speak selected text when the key is pressed". Then choose "Set Key..." to choose which key combination you want to hit to make the Mac read selected text. Just hit the desired combination while the little window is open. I have Option+S set for mine.
- Open Applications > TextEdit. Type in how you think you sound when you're saying the desired command. For example, I made a script that will activate when I say "I'm bored," but for me, my words run together and I speak quickly, so "Mbord" is the name I chose for my script.
- Select the text you just typed and hit the key combination you entered in System Preferences (like Option+S). Does the Mac's voice match how you plan to speak the command? If so, then you have a good file name for your script.
Technical note: you'll need a microphone for this to work, obviously. I'm using a Macbook with a built-in microphone and I'm running OS X Leopard.
- Time:
- 7:21 PM
- Categories:
- OS X
- Tags:
- OS X, programming
- Comments:
-
3 comments / Add a comment »
Note: If you enjoy this article, you might also check out the Geeky Stuff section.
I installed Delicious Library earlier and have spent all afternoon and evening scanning in barcodes from my CD’s, DVD’s, books, and games. Wow, that sounds like the dorkiest thing ever: while everyone else in this country is watching the Superbowl, I’m sitting alone in my apartment, waving barcodes at my computer. I feel I have to redeem myself now… Um, I have lots of dates! I go to movies with my friends! I take a yoga class! Yeah…
Anyway, it’s really neat because it uses my Macbook’s iSight camera to scan in barcodes, then it grabs information about the product from Amazon. Now I can browse through all my media without leaving my laptop, and what’s nice is that I can sort things by Amazon users’ rating, genre, number of pages, etc. See this snazzy screenshot of my library:
This totally sounds like a paid post, but I promise it’s not, heh. The scanner worked reasonably well, but sometimes I had to search by title, author, or UPC. I think Amazon is a bit crazy with the ISBN’s, too, probably because of the ISBN number change that happened a while back: sometimes I would scan one thing and get something completely different in my library. I especially had trouble with Orson Scott Card and Stephen King novels, which sucked because I have so much of their stuff.
- Time:
- 8:29 PM
- Categories:
- Techy
- Tags:
- OS X
- Comments:
-
1 comment / Add a comment »
- Music:
- New and Approved (remix) by No Doubt
Note: If you enjoy this article, you might also check out the Geeky Stuff section.
Recently, I switched from a Powerbook to a Macbook, and to copy my files from one to the other, I used a pen drive. Since my pen drive has a FAT file system, it treats everything as being executable. This, however, is not the case on a UNIX-like file system like OS X. In order to save myself the hassle of manually chmodding thousands of files, I wrote this Ruby script:
#!/usr/bin/env ruby
require 'find'
require 'fileutils'
# Append to/remove from this list as necessary
Plain = ['php', 'txt', 'jpg', 'jpeg', 'gif', 'png', 'html', 'pdf', 'css', 'mp3', 'zip', 'tar.gz', 'tar', 'htm', 'psd', 'ai', 'ptg', 'cgi.pl', 'sphp', 'svn-base', 'default'].collect do |ext|
".#{ext}"
end.freeze
# Append to/remove from this list as necessary
Executable = ['pl', 'rb', 'cgi', 'sh'].collect do |ext|
".#{ext}"
end.freeze
$num_chmodded = 0
def chmod_and_puts( cmd )
puts cmd
system cmd
$num_chmodded += 1
end
def chmodder( start_dir )
num_skipped = 0
num_plain = 0
num_executable = 0
Find.find( start_dir ) do |path|
unless File.symlink?( path )
if FileTest.file? path
if is_plain? path
chmod_and_puts "chmod 644 \"#{path}\""
num_plain += 1
elsif is_executable? path
chmod_and_puts "chmod 755 \"#{path}\""
num_executable += 1
else
num_skipped += 1
end
elsif File.directory? path
chmod_and_puts "chmod 755 \"#{path}\""
num_executable += 1
else
num_skipped += 1
end
else
num_skipped += 1
end
end
puts "----------------------------------------------"
puts "Chmodded #{$num_chmodded} total:"
puts "\tExecutable: #{num_executable}"
puts "\tPlain: #{num_plain}"
puts "Skipped #{num_skipped} files/directories/symlinks"
end
def get_extension( path )
File.extname( path ).downcase
end
def is_executable?( path )
extension = get_extension( path )
if Executable.include? extension
true
else
false
end
end
def is_plain?( path )
extension = get_extension( path )
if Plain.include? extension
true
else
false
end
end
chmodder( '.' )
This goes through all the files and directories within the directory from which you run the script and chmods non-executable files to 644 (read+write on User, read on Group and Other) and executable files to 755 (read+write+execute on User, read+execute on Group and Other). If you're unfamiliar with the chmod command, you might want to read my beginning Linux guide.
- Time:
- 4:52 PM
- Categories:
- Linux, OS X, Ruby
- Tags:
- Linux, OS X, programming
- Comments:
-
0 comments / Add a comment »
Note: If you enjoy this article, you might also check out the Geeky Stuff section.
I downloaded the free starter version of ArtRage 2 the other day and I’m just now getting around to playing with it. I have no talent with drawing people or objects, but I was able to whip this up in a few minutes, and Todd was able to discern that it’s a human face, so bully for me:
I think I’m going to shell out the $25 it takes to purchase the full version of ArtRage, because I could see myself making pretty neat layout images with it. Now to go back to playing…
- Time:
- 9:35 PM
- Categories:
- Techy
- Comments:
-
1 comment / Add a comment »
Note: If you enjoy this article, you might also check out the Geeky Stuff section.
I’m finally upgrading my iPod Shuffle to something with a screen! Yesterday, due to the free shipping and free engraving offered, I ordered from Apple online a Product Red iPod Nano. I’m now incredibly excited about it getting here, even though it’ll surely take a week or more for it to get shipped and arrive. Todd today at lunch told me that Apple will be revealing new updates on Tuesday, so I’m wondering if any iPod updates will be made. If so, since I ordered my Nano so shortly before updates are being announced, I’m thinking Apple would go ahead and exchange my Nano for free, so Todd tells me. I’ll be able to use it at the university’s gym, too, because the new treadmills they put in this semester have a feature where you can plug in your iPod and use the treadmill’s touch screen to change tracks, etc.
My PC enjoys messing with me. I have both Ubuntu and Windows XP installed on it, and they both work fine, though Windows dislikes working for me all the time. A lot of the time when I boot my computer and choose Windows, I get the error “Selected disk does not exist.” At this point I always want to smacka’ bitch, because the disk certainly existed a day before when I last booted Windows! So I’ll boot Ubuntu, and often when I reboot it’ll let me boot Windows. Or sometimes I Ctrl-Alt-Delete and open the BIOS setup screen, exit out without changing anything, and then Windows will boot. Does Windows just hate me? Another lovely problem is that occasionally I won’t even get to the Grub boot screen to choose Windows or Ubuntu, because my computer will just say something about the keyboard being missing or disabled. Riiight… Resetting or turning the computer off and back on often fixes that.
- Time:
- 2:28 PM
- Categories:
- Techy
- Tags:
- shopping
- Comments:
-
4 comments / Add a comment »
Note: If you enjoy this article, you might also check out the Geeky Stuff section.
Recently at work, the web admin for the computer science department came into our lab and told us that my employer's site was broken. The admin had need to make all .php files not act as PHP scripts, and instead, all files with the extension .sphp would now run as PHP scripts. Since my employer's site was built using PHP, that meant all of its pages were showing the source code instead of actually executing. I had to whip up a quick Ruby script in order to:
- Rename all .php files to have .sphp as their extension;
- Replace all instances of ".php" within those files with ".sphp", to take care of
include statements, links, etc.
Here's what I came up with:
#!/usr/bin/env ruby
require 'find'
require 'fileutils'
# Used to go through, starting at the directory start_dir and working
# recursively, and rename all files that end in .php to end in .sphp
# because the CS admin got a wild hair. Also goes through all .php
# and .sphp files and replaces all instances of ".php" in them with
# ".sphp".
def finder( start_dir )
Find.find( start_dir ) do |path|
if FileTest.file?( path )
if path =~ /\.php$/i
old_name = File.basename( path )
new_name = old_name.gsub( /\.php$/, '.sphp' )
dir = path.gsub( /#{old_name}$/, '' )
if File.exists?( dir + old_name )
puts "#{dir + old_name} to #{dir + new_name}\n"
# Since the code is part of a Subversion repository, we use
# the 'svn' command to let Subversion rename the file
system( "svn mv #{dir + old_name} #{dir + new_name}" )
end
elsif path =~ /\.sphp$/i || path =~ /\.php$/i
puts "Replacing instances of '.php' in #{path}\n"
system( %Q{ruby -pe 'gsub(/\\.php/, ".sphp")' -i #{path} } )
end
end
end
end
finder( '.' )
- Time:
- 11:22 PM
- Categories:
- Ruby
- Tags:
- programming, Ruby, work
- Comments:
-
6 comments / Add a comment »
Note: If you enjoy this article, you might also check out the Geeky Stuff section.
Sometimes it would be useful to tell users of your Ruby on Rails application if there is a problem in the database, such as some foreign keys are invalid. As an example, let's assume you have two models, Book and Author, such that each Book has an author_id which connects with Author via its primary key, id. That is, the tables are: books(id, author_id) and authors(id). Each table probably has fields other than that, but those are the only fields we need to worry about. Below is a method that generates an unordered HTML list for display to the users:
class Book < ActiveRecord::Base
# Returns HTML about which rows have invalid foreign keys
def self.
find_bad_foreigners
msg = ''
find( :all ).each do |book|
unless Author.exists?( book.author_id )
author_id = ( book.author_id || 'NULL' ).to_s
msg << '<li>Book with ID ' << book.id.to_s + ' has a non-existent
author ID: ' << author_id + '</li>'
end
end
if msg.blank?
nil
else
'<ul class="error">' << msg + '</ul>'
end
end
end
You could have similar methods in your Rails models. Maybe on the main page of your application, the above method could be displayed. If there are no invalid foreign keys, nothing will show up. Otherwise, the user will see a list of the invalid keys that need fixing.
- Time:
- 2:59 PM
- Categories:
- Ruby
- Tags:
- programming, rails, Ruby, tutorials
- Comments:
-
0 comments / Add a comment »
Note: If you enjoy this article, you might also check out the Geeky Stuff section.
I take class notes on my Powerbook, and often I take mathematical notes that involve superscripts and subscripts. To make it more convenient for me to take clean notes, as opposed to notes filled with “x^2″ and “y_j”, I looked into changing the key bindings in OS X. You need to create a file at ~/Library/KeyBindings/DefaultKeyBinding.dict, and if the directory KeyBindings doesn’t exist, you should create it (mkdir ~/Library/KeyBindings). In this file, you can specify different key combinations and the resulting action that should occur. Here’s my DefaultKeyBinding.dict:
I used this tutorial, which has lots of good examples, to create mine.
- Time:
- 12:11 PM
- Categories:
- Config files, OS X
- Tags:
- OS X
- Comments:
-
1 comment / Add a comment »