Teaching
Visual Homework Policy
1
Click to download a PDF of this. Feel free to reuse it — just let me know, especially if you make any particularly effective tweaks.
This policy has been gestating for some time, and I started to formulate it in conversation with one of my students who had had a brush with the academic dishonesty fairy. I presented it in class last week, and I realized that it is as good a representation as I have of my homework policy. I’m not really interested in coming up with a suitably punitive formula for docking grades for lateness, and I don’t particularly care about negotiating reasonable extensions. Mostly, like my students, I just don’t want to be bothered. But, by golly, there are things that bother me, and it would be good to steer clear of them. And it’s worth knowing how they rank in my worldview. And this expresses it.
Better not to do your work than to cheat or plagiarize to finish your work. Better to ask for an extension at the last minute than to just not do the work. But noticeably better to ask for the extension in a timely manner.
I’m pretty sure that this both made sense to and stuck with my ninth graders.
Transmogrifying those Google Reader JSON dumps into something useful
9For the last few years (my JSON feed tells me: since 2008), I have been tagging and annotating articles of interest as they passed before my eyes in Google Reader. This served a two-fold purpose:
- I could find them again later, easily, because they were tagged and annotated.
- I could share an RSS feed with those annotations to particular interest groups that I worked with (e.g. anything tagged “for robotics” would show up on my advanced computer science class’ portal page, or anything tagged “for academic computing” would show up on my school home page).
This was a great way to share (and manage) resources. Granted, much of what passed before my eyes in Google Reader was trivial and not of lasting value, but this filtering allowed me to hang on to at least a few gems for future reference.
And then Google Reader got the Google+ treatment and sharing items broke. But you could download a JSON dump of all the items that you had ever shared. It wasn’t entirely clear what you could do with this JSON dump, but… there it was. And then: I realized that all of my other information is stashed on my web server (and that I have become increasingly distrustful of relying on cloud services to maintain my data and workflows — e.g. my weekly backup of all my Google Docs… just in case).
Wouldn’t it be handy to import that JSON feed into a new blog on my server? So I wrote a PHP script that converts (at least my) Google Reader JSON dump into an XML file that WordPress can import as a list of posts. With the tags and annotations converted over. In fact, with all of the data in the JSON dump embedded in the XML file (although WordPress doesn’t read all of it).
This comes with a few caveats:
- For items that came from blogs with a full feed, the result is a republication of the original post — which feels ethically dubious to me. (I have made my new blog of Google Reader shared items private, so that I have the data but I’m not sharing it with the world).
- I’ve made guesses as to how to treat some of Google’s data. Reasoned, educated guesses, but guesses nonetheless. For example, I’m not super-clear on which dates in the file correspond with what events — does a publication date refer to when the item was shared or the original post was posted?
- I’ve added in some arbitrary (and therefore, ideally, eventually, configurable) WordPress tags to make the import go more smoothly. Where I have done that, I mark it in the script as a TODO item. (And, in truth, I didn’t really test to see if all of these items were necessary.)
- The original authors of the posts are transfered to the XML file, which means that when the actual import into WordPress is done, you will have the option to either laboriously create a new user for each distinct author or simply revert authorship to the currently logged-in WordPress user. It doesn’t seem like WordPress has a format for exporting or importing users (or, at least, my cursory search didn’t find it). Clearly an ancillary SQL query could be generated that pre-populated the WordPress database with the users that the XML file refers to. But I haven’t bothered to do that.
- You’ll need your own PHP-compatible webserver to run the script, since I have been quick and dirty and simply imported the JSON file from and exported the XML file to the script’s local directory. And I have no interest in setting up my world-facing webserver to take the traffic hit of processing other people’s multi-megabyte JSON dumps.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | /**********************************************************************
* Google Reader to Wordpress
*
* 2011-11-27
* Seth Battis (seth@battis.net)
*
* This script takes the output of Google Reader's JSON export of
* shared items and converts it into an XML file that can be imported
* into a Wordpress blog as posts. All of the data in the original JSON
* file is preserved in the XML file, either by transfering it to
* an appropriate format (e.g. Google Reader categories are converted
* to WordPress post tags) or simply as an additional XML tag (e.g. the
* Google Reader commentInfo metadata for recent shared items). In
* situations where actual data has to be converted to make it readable
* for WordPress, the original data is included as the JSON attribute
* of that tag (e.g. timestamps and categories).
*
* As currently written, the script looks in its local directory for
* Google Reader "shared-items.json" file and generates a matching
* "shared-items.xml" file, also in its local directory.
*
* There are a number of potentially configurable (i.e. arbitrary)
* values marked as TODO.
*
* Caveat emptor: this has been tested against my ~1000 item Google
* Reader shared items feed and on my WordPress 3.2.1 site. I would
* presume that it should work fairly well for others, but make no
* guarantees!
*********************************************************************/
/* returns a Wordpress slug-version of the given text (only
alphanumeric characters and dashes) */
function sluggify($text)
{
return preg_replace("|[^a-z0-9]+|", "-", strtolower($text));
}
/* SimpleXML doesn't really support namespaces unless you force it */
$xml = '<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"
xmlns:excerpt="http://wordpress.org/export/1.1/excerpt/"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:wp="http://wordpress.org/export/1.1/"
></rss>';
$rss = new SimpleXMLElement($xml);
$namespaces = $rss->getDocNamespaces(true);
/* load the Google Reader JSON file */
$file = file_get_contents("shared-items.json");
$json = json_decode($file, true);
/* Wordpress will choke if our post names aren't unique, so we track
them separately */
$post_names = array();
/* header information describing the file itself */
$channel = $rss->addChild("channel");
$channel->addAttribute("direction", $json["direction"]);
$channel->addAttribute("id", $json["id"]);
$channel->addAttribute("self", $json["self"][0]["href"]);
$channel->addAttribute("author", $json["author"]);
$channel->addChild("title", $json["title"]);
$channel->addChild("link");
$channel->addChild("description");
$pubDate = $channel->addChild("pubDate", gmdate("D, j M Y G:i:s O", $json["updated"]));
$pubDate->addAttribute("json", $json["updated"]);
$channel->addChild("language");
$channel->addChild("wxr_version", "1.1", $namespaces["wp"]);
/* run through the list of items and add them to the XML */
foreach ($json["items"] as $item)
{
$rssItem = $channel->addChild("item");
/* a bunch of Google Reader-specific metadata */
if (isset($item["isReadStateLocked"]))
{
$rssItem->addAttribute("isReadStateLocked", $item["isReadStateLocked"]);
}
$rssItem->addAttribute("crawlTimeMsec", $item["crawlTimeMsec"]);
$rssItem->addAttribute("timestampUsec", $item["timestampUsec"]);
$rssItem->addAttribute("id", $item["id"]);
if (isset($item["commentInfo"]))
{
while (list($commentInfoKey, $commentInfoValue) = each($item["commentInfo"]))
{
$commentInfo = $rssItem->addChild("commentInfo", $commentInfoKey);
$commentInfo->addAttribute("permalinkUrl", $commentInfoValue["permalinkUrl"]);
$commentInfo->addAttribute("commentState", $commentInfoValue["commentState"]);
}
}
/* annoyingly, not every item has its content in the content
element -- sometimes it's in the summary element (and once in a
while, it's just not there). I think this is an artifact of how
the original RSS feeds were constructed. I think. */
if (isset($item["content"]))
{
$content = $item["content"]["content"];
}
else if (isset($item["summary"]["content"]))
{
$content = $item["summary"]["content"];
}
else
{
$content = "";
}
/* sometimes items don't even have titles */
if (isset($item["title"]))
{
$rssItem->addChild("title", $item["title"]);
}
/* most items store the original linkback information in the
alternate element -- Wordpress won't honor this link tag when
it's imported (i.e. it won' treat it like the Daring Fireball
feed), so I have embedded a more descriptive linkback after the
annotations at the start of the content, using some information
from the origin element. The linkback is in the
"google-reader-alternate-href" div (for easy CSS-wrangling!) */
if (isset($item["alternate"]))
{
$rssItem->addChild("link", htmlentities($item["alternate"][0]["href"], ENT_COMPAT, "UTF-8"));
$content = htmlspecialchars("<div class=\"google-reader-alternate-href\"><p>Originally posted at <a href=\"{$item["alternate"][0]["href"]}\">{$item["origin"]["title"]}</a></p></div>", ENT_COMPAT, "UTF-8") . $content;
}
/* I haven't bothered to figure out if the dates are really GMT or
localized -- GMT was an easier assumption to make */
$pubDate = $rssItem->addChild("pubDate", gmdate("D, j M Y G:i:s O", $item["published"]));
$pubDate->addAttribute("json", $item["published"]);
/* not every item has an a author, either -- again, an artifact of
the original RSS feeds */
if (isset($item["author"]))
{
$rssItem->addChild("creator", $item["author"], $namespaces["dc"]);
}
/* annotations were tricky -- I have added them as their own XML
tags _and_ inserted them within a "google-reader-annotation" div
at the top of the post content (to match the original format on-
screen). All of the original data is preserved in the XML tag,
with an ID that matches the embedded div ID. */
foreach($item["annotations"] as $annotation)
{
$annotationHTML = htmlentities("<div id=\"" . md5($annotation["content"] . $annotation["author"]) . "\" class=\"google-reader-annotation\"><blockquote><p>{$annotation["content"]}</p><p class=\"author\">{$annotation["author"]}</p></blockquote></div>", ENT_COMPAT, "UTF-8");
$content = $annotationHTML . $content;
$rssAnnotation = $rssItem->addChild("annotation", $annotation["content"]);
$rssAnnotation->addAttribute("id", md5($annotation["content"] . $annotation["author"]));
$rssAnnotation->addAttribute("author", $annotation["author"]);
$rssAnnotation->addAttribute("userId", $annotation["userId"]);
$rssAnnotation->addAttribute("profileId", $annotation["profileId"]);
$rssAnnotation->addAttribute("profileCardParams", $annotation["profileCardParams"]);
}
/* again, sometimes content is in content, sometimes it's in the
summary element */
$rssContent = $rssItem->addChild("encoded", $content, $namespaces["content"]);
if (isset($item["content"]))
{
$rssContent->addAttribute("direction", $item["content"]["direction"]);
}
if (isset($item["summary"]))
{
$excerpt = $rssItem->addChild("encoded", $item["summary"]["content"], $namespaces["excerpt"]);
$excerpt->addAttribute("direction", $item["summary"]["direction"]);
}
/* more Google reader metadata, this time about the original feed
that the item came from -- which is used above to format the
linkback that is embedded a the start of the content */
$origin = $rssItem->addChild("origin");
$origin->addAttribute("streamId", $item["origin"]["streamId"]);
$origin->addAttribute("title", $item["origin"]["title"]);
$origin->addAttribute("htmlUrl", $item["origin"]["htmlUrl"]);
/* it's not clear to me whether the published or modified date is
when the original post was published or when the item <span class="hiddenGrammarError" pre="item ">was
shared</span> -- I think when published refers to when it was shared. */
$postDate = $rssItem->addChild("post_date", date("Y-m-d G:i:s", $item["published"]), $namespaces["wp"]);
$postDate->addAttribute("json", $item["published"]);
$rssItem->addChild("comment_status", "open", $namespaces["wp"]); // TODO make configurable
$rssItem->addChild("ping_status", "open", $namespaces["wp"]); // TODO make configurable
/* make a Wordpress friendly title slug for the post */
if (isset($item["title"]))
{
$slug = sluggify($item["title"]);
}
else
{
/* if no title, generate the slug from the timestamp */
$slug = date("Y-m-d-G-i-s", $item["published"]);
}
/* make sure that our slug is unique -- add a counter to the end
if it is not, and track those counter values in $post_names[] */
if (isset($post_names[$slug]))
{
$post_names[$slug]++;
$slug .= "-" . $post_names[$slug];
}
else
{
$post_names[$slug] = 0;
}
$rssItem->addChild("post_name", $slug, $namespaces["wp"]);
/* more Wordpress metadata -- all of which could be tweaked */
$rssItem->addChild("status", "publish", $namespaces["wp"]); // TODO make configurable
$rssItem->addchild("post_parent", 0, $namespaces["wp"]); // TODO make configurable
$rssItem->addChild("menu_order", 0, $namespaces["wp"]); // TODO make configurable
$rssItem->addChild("post_type", "post", $namespaces["wp"]); // TODO make configurable
$rssItem->addChild("post_password", "", $namespaces["wp"]); // TODO make configurable
$rssItem->addChild("is_sticky", 0, $namespaces["wp"]); // TODO make configurable
/* convert categories to post tags -- nota bene that Google Reader
has conflated the reader's categories with the original post's
tags, creating a... mish-mash. */
foreach($item["categories"] as $category)
{
if (!preg_match("|.*/com\.google/.*|", $category))
{
$cleanCategory = $category;
$cleanCategory = preg_replace("|user/\d+/label/(.*)|", "$1", $cleanCategory);
$rssCategory = $rssItem->addChild("category", htmlentities($cleanCategory, ENT_COMPAT, "UTF-8"));
$rssCategory->addAttribute("domain", "post_tag");
$rssCategory->addAttribute("nicename", sluggify($cleanCategory));
$rssCategory->addAttribute("json", $category);
}
}
/* add comments -- note that for privacy reasons, while the
commenter's metadata is added as an XML tag, it is not embedded
in the Wordpress-readable wp:comment tags */
foreach($item["comments"] as $comment)
{
$rssComment = $rssItem->addChild("comment", "", $namespaces["wp"]);
$rssComment->addAttribute("id", $comment["id"]);
$commentContent = $rssComment->addChild("comment_content", $comment["htmlContent"], $namespaces["wp"]);
$commentContent->addAttribute("plainContent", $comment["plainContent"]);
$author = $rssComment->addChild("comment_author", $comment["author"], $namespaces["wp"]);
$author->addAttribute("userId", $comment["userId"]);
$author->addAttribute("profileId", $comment["profileId"]);
$author->addAttribute("profileCardParams", $comment["profileCardParams"]);
$author->addAttribute("venueStreamid", $comment["venueStreamId"]);
$commentDate = $rssComment->AddChild("comment_date", $comment["createdTime"], $namespaces["wp"]);
$commentDate->addAttribute("modifiedTime", $comment["modifiedTime"]);
$rssComment->addAttribute("isSpam", $comment["isSpam"]);
}
}
/* dump the converted XML out as a file */
header ("Content-type: text/xml");
echo $rss->asXML();
file_put_contents("shared-items.xml", $rss->asXML()); |
Custom Software
0One of my colleagues, Matt Zipin (in fact, my high school computer science teacher), just sent me a link to an iPhone app that his current student, Ari Weinstein put together. It was one of those rare moments of seeing a piece of software and thinking, “This… this is exactly what I have been looking for! It’s almost like they had me in mind when they wrote it!”
Perhaps unsurprisingly, I had this reaction because, in fact, Ari has written an application that I suggested. Based on my work at St. Grottlesex as a Thirds’ basketball coach. I had been running practices using the timer and counter apps separately on my iPhone. Which was workable. But unwieldy. Enter.. Ari’s Basketball Timer app, which elegantly and cleanly combines these two tools into a single screen.
I think my favorite part of the app is something that you can’t see, that you can only experience: starting the Time out Timer stops the main clock, and starting the main clock stops the Time out Timer. How simple. How elegant. How easy it would have been to skip over.
Thank you Ari and Matt!
Developing for the App Store with High School Students
6I actually really, really want to document some of our projects that we’re working on this year in a great deal more detail. But, for now, I am simply publishing my notes from a conversation that I just had with Apple Education about the legalities of having high school students develop for the app store.
So… I just got off the phone with Apple Education (they were following up on an iOS in Education event a few months ago that I had actually missed). But: I did get the straight dope on Apple Developer accounts and high schools:
- University accounts are just that: for higher education. Non-negotiable.
- There are really three levels of developer that are pertinent to high school:
- Free — they can download Xcode and use the iPhone simulator.
- Individual ($99) — Same as free, plus they can use their iPhones/iPads to debug the software live (with the right certificates — I’ve found that the easiest way to set up the certificates is directly through the Xcode Organizer). My recollection is that they can have up to something like 100 devices for “debugging.” At this level, they can post apps to the App Store.
- Enterprise ($299, IIRC) — Individual, plus the ability to manage a fleet of iOS devices (remote install and remote wipe), as well as distributing their software internally with no restrictions. I actually pressed him pretty hard on this, and he wasn’t 100% (“read the language in the agreement first”), but he thinks that it would be viable for the school to buy an Enterprise license and then say “Come by the computer lab and we’ll install our cool in-house app on your iPhone for free.” (Or for money — I don’t think they care.)
- Apple strongly discourages the school (which would, in reality, be a single individual) signing up for an Individual developer account as the primary distribution channel to the App store for student apps. The rationale being that if a particular app makes it big, the individual who has control of that account well, has control of that account. Apple deals with account holders, not the model that the school constructed. They suggested that if a group of students wanted to band together on an app, that they should sign up as a group for an Individual account through which to distribute that app — and that they should draw up their own contract on their end for how to manage that account.
- Students under 18 need to be signed up for the account by their parents. (Contract law — the kids are underage.)
At the end of the day, it sounded like my approach this year is basically right on the nose: I have an Individual account in my name that I use to install apps on test iPhones (and I have registered all the student iPhones as debugging devices). The students signed up for free accounts at the beginning of the year. I think what we’ll do when we release this app is sign up for a new Individual account that the students will jointly share to post the app to the App Store (something like “[Jewish Day School] App Design ’10′-’11″).
Building a Google Earth Tour in a Spreadsheet
1For the last couple of months, one of my high school classes at Jewish Day School has been working on building an interactive tool about the Six Day War for a middle school curriculum unit. They have put a lot of work into researching their data and laying it out in Google Earth, and now we’re putting together a tour of the data for the middle school students, that will also teach them a little about how to use Google Earth. It’s been enormously fun.
But. But, we now have to do some programming or some very careful recording in Google Earth to create this tour (a là Al Gore’s Climate Change tours). And my students are far more interested in the design end of things than in the coding end of things. They’re great at what they do, but niggling coding details give them head aches.
So I built a Google Docs spreadsheet, into which they can plug various pertinent information and out of which comes valid KML instructions that will define the tour. I’m a little proud of this — I don’t think that there’s anything else quite like it out there. There are three kinds of information that need to be entered:
- SoundCue — any audio that should be played in the background. You can either enter the whole URL to the MP3 file that should be played, or just the file name (and make sure that you enter the path in which all the files can be found on the KML Generator tab). You also need to tell us both when the cue should be played and how long it should last.
- AnimatedUpdate — anything that should be happening in Google Earth in terms of showing photo overlays or placemarks or polygons or what-have-you. Enter what should happen, and when (and, if relevant, for how long).
- FlyTo — any time we change where (or when) we’re looking at Google Earth. Enter when and how long the transition should take, and the date (and time) that we’re meant to be looking at.
The AnimatedUpdate and the FlyTo also expect the user to enter KML code — which can be copy-and-pasted from Google Earth KML exports for each transition. Happily, if something needs to happen more than once, entering the KML for the first instance will automatically populate future instances. In addition, the pauses necessary to synch up all of the action are calculated by the spreadsheet.
Update March 25, 2011: The spreadsheet above is our live work (since I kept updating the spreadsheet after this post).
The end result is both a visual timeline of the tour (helpful for debugging any weird errors) and also KML code that can be copy-and-pasted out of Google Docs and into a KML file. (Caveat emptor: depending on what you’re pasting the KML into — I like Xmplify — you may see that there is a leading and trailing quote that need to be manually deleted.)
Right now the spreadsheet can handle tours up to four minutes and 10 seconds in length (250 seconds, for those of you keeping score at home). This is because I was originally copying the KML out of the KML Orderer worksheet, and Google Docs supports pasting of up to 1000 rows in total. You’ll see that the current KML worksheet is a single cell, getting around this limitation, but I didn’t bother to extend any of the other worksheets. Just make sure you fill down all the formulas if you extend any of the sheets!
Here’s a link to a scratch copy of the spreadsheet. Feel free to copy and use it for your own purposes — let me know how you used it!
Free-style Online Learning
0One of my responsibilities at Jewish Day School is to write a weekly “tech tips” column for the online faculty news. This is one such tip.
Even as the end-of-year to-do lists are approaching critical overload, I find that one of the joys of the spring is the contemplation of what I will be working on next year. Not so much in a “next year I’ll do this all differently” kind of snit, but with more of a “year in review” focus: spring and graduation makes me sentimental and reminiscent.
With that in mind, in the past week I have come across two interesting resources both for teaching in general and for thinking about our work as “knowledge workers” in the 21st century (to infinity and beyond!). First, Merlin Mann discusses how we do (or do not) allocate our time and attention to getting our projects done. Thoughtful, provocative and entertaining stuff. Second, Williams College’s Project for Effective Teaching has gone online with a truly exciting, provocative array of professorial reflections and questions around specific aspects of classrooms and teaching and learning. Enjoy!
How, you might ask, do videos like these fall into my hands? I follow-up on the sources of interesting articles that I see. And then on the sources of those sources: I like to find where the ideas are swimming around raw and unfettered. I do this by following a boat-load of interesting “edu-bloggers”, by following (and engaging with) other teachers on Twitter, and by doing a lot of skimming.
PowerPoint makes us D-U-M-Dumb
0One of my responsibilities at Jewish Day School is to write a weekly “tech tips” column for the online faculty news. This is one such tip.
As we head down the homestretch of May and June, more and more students (and teachers) are experiencing siyyum for their coursework, either as final papers or presentations or projects. Projects and papers are delightfully straight-forward and easy to facilitate and grade… at least, when compared to presentations, which have the added benefit of being a potential exercise in goodwill and patience to sit through.
The first hurdle our students have to get over is the technology itself — bringing together all the disparate elements of their presentation into one place and time. A few years ago, I wrote up a cheat sheet of tips that help to avoid the most common student pitfalls. I have not run into technical problems with student PowerPoints since I started giving them this handout (I kid you not).
In general, a good presentation has to nail not just the content and technology, but also visuals and public speaking. And this is the hardest thing to do right. For adults, even. Experts have started to decry PowerPoint as not just problematic, but actively destructive when it comes to communicating information and especially nuance clearly.
Gen. Stanley A. McChrystal, the leader of American and NATO forces in Afghanistan, was shown a PowerPoint slide in Kabul last summer that was meant to portray the complexity of American military strategy, but looked more like a bowl of spaghetti.
“When we understand that slide, we’ll have won the war,” General McChrystal dryly remarked, one of his advisers recalled, as the room erupted in laughter.
Shifting the focus from a PowerPoint document to the holistic presentation will further the student’s ability to communicate complex ideas — a key skill in today’s (or any day’s) world. Some further reading that is both informative and motivational on that front:
- Merlin Mann talks about “How [he] made his presentations a little better” (know this: he was pretty good to begin with)
- Business Week breaks down how to “Deliver a presentation like Steve Jobs” (the inimitable CEO of Apple)
- Edward Tufte (the master of information presentation — and notorious PowerPoint-hater) examines how to get the absolute most out of PowerPoint (or not)
PowerPoint Tips
1One of my responsibilities at Jewish Day School is to write a weekly “tech tips” column for the online faculty news. This is one such tip.
Making Things Run Smoothly
- Make sure that you always insert pictures into your presentation using the Insert Picture command from the Insert menu. Do not copy and paste pictures into your presentation. For arcane reasons, copy and pasting pictures can make your PowerPoint fail to display your pictures on other computers.
- Keep a folder of all of the pictures and video that you add to your PowerPoint. Just in case you need to re-insert it (for example, if you messed up on following the tip above).
- Video is not embedded in PowerPoint, pictures are – share Zip files. That is, you can insert pictures into a PowerPoint presentation and send the presentation to someone else and they can see the pictures but you cannot insert video, send the presentation to someone else, and expect them to see the video. PowerPoint creates a link to the video instead. To get around this, if you are going to use video, put your presentation and your video files in a folder together, then insert the video. When you are ready to share your presentation, right-click on the folder and Send To > Compress or Zip Archive and send out the Zip file instead. Your recipient can unzip the archive and will have the presentation and the video.
Making Things Look Pretty
- Black text on a white background is not traditional by accident. It’s easy to read. Think carefully before trying a novel color combination.
- One picture per slide lets you show the picture big, in all its glory. Multiple pictures per slide lets you compare pictures. Think about which it is you want to be doing (and remember that postage stamps are hard to see!).
- Don’t stretch your pictures. You can scale your pictures proportionately by holding down the Shift key when you drag the grab boxes on the corners of the picture. This will make sure that the picture doesn’t get distorted.
- Use text judiciously. This one is complicated: you don’t want to have too much text on a slide because it will get small and hard to read. You don’t want to put your script on the slide, because then you’ll be reading from the slide, which is deathly dull (unless, maybe, you’re Morgan Freeman). But you do want to present text that will support your arguments and highlight important ideas. And you do want to present quotations that are illuminating. One rule of thumb is the “six by six” rule: no more than six words per bullet point, no more than six bullet points per slide. This is totally artificial and you should violate it as needed… but remember it and what it is really urging: don’t overwhelm your audience with text!
- Less is more. This is true of almost everything involved in PowerPoint, but particularly when it comes to animation and sound effects. They have a campy appeal, and can sometimes underscore a point you’re trying to make. But you ain’t Spielberg and PowerPoint ain’t ILM, so don’t go trying to put in gratuitous special effects just to make your PowerPoint more appealing. Your research and ideas should be the focus, not your ability to make car crash sound effects.

