<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;Ck4MR30-eSp7ImA9WhdbEUU.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834</id><updated>2011-10-09T10:23:06.351-07:00</updated><category term="education" /><category term="Web 2.0" /><category term="LMS" /><category term="eLearning" /><title>The Other Brian Whitmer</title><subtitle type="html">Yeah, so there's this like "super chef" guy whose name is Brian Whitmer.  That's not me.  Sorry.  Me?  I'll be talking about improving eLearning and my coding discoveries that happen along the way.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://brianwhitmer.blogspot.com/" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/TheOtherBrianWhitmer" /><feedburner:info uri="theotherbrianwhitmer" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DEMGQ3Y4eSp7ImA9Wx5SGEk.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-8916605584906646071</id><published>2010-08-14T21:17:00.000-07:00</published><updated>2010-08-14T21:27:02.831-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-14T21:27:02.831-07:00</app:edited><title>uninitialized constant Jammit::Routes</title><content type="html">This post is mostly just for me (because I know someday this is going to happen again and I'm going to search for this error string), but maybe somebody else will find it useful too.  I just switched ruby environments and I couldn't run my rails project anymore, it failed with the error "uninitialized constant Jammit::Routes".&lt;br /&gt;&lt;br /&gt;It routes.rb we've included the line "Jammit::Routes.draw(map)" for jammit routes, and that fails for some reason.  Last time it took me forever to figure out why, but eventually I found that (for me, anyway) there was a problem with the closure-compiler-0.3.2 gem.  It checks if you're on Windows and if so, it checks if you have ruby 1.9 installed or not.  If you do it requires 'open3' and if you don't requires 'win32/open3'.  I don't want to deal with all the mess of getting 'win32/open3' into our bundler bundle, and I don't actually need closure-compiler to work since I can't deploy from my box anyway, so I just changed the "lib/closure/popen.rb" file in the gem to not require 'win32/open3' and everything's happy again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-8916605584906646071?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/MwapJV4Q958" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/8916605584906646071/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=8916605584906646071" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8916605584906646071?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8916605584906646071?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/MwapJV4Q958/uninitialized-constant-jammitroutes.html" title="uninitialized constant Jammit::Routes" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2010/08/uninitialized-constant-jammitroutes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUBQ3YyeSp7ImA9WxFXF08.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-5433015090000313815</id><published>2010-05-21T11:29:00.000-07:00</published><updated>2010-05-24T10:47:32.891-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-24T10:47:32.891-07:00</app:edited><title>The Story of Instructure</title><content type="html">For the curious at heart, here's a little color around how I ended up co-founding an educational software company called &lt;a href="http://www.instructure.com"&gt;Instructure&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;In 2008 I was a grad student at Brigham Young University, just finishing up my Master's in Human-Computer Interaction.  One of my last classes was a Software Business class taught through the C.S. department with a visiting professor, and the idea of the class was to pretend like you were doing a startup, do all the market research, put together a plan and "pitch" at the end of the semester.  Devlin Daley and myself ended up in a group (we'd taken usability classes together before) and sort of decided not to pretend.  Devlin had always been the entrepreneurial type, and I'll confess it didn't take much for me to catch the bug, either.  We didn't have to look far for a legitimate opportunity.&lt;br /&gt;&lt;br /&gt;BYU used Blackboard as their LMS, and we were so frustrated with the product both as students and as TA's, that we decided to poke around that market a little more.  We were baffled when we failed to find anybody that we considered pushing the boundaries of education.  Usually in a healthy market you have some one product that's really driving innovation, but in the LMS market we didn't feel like anyone was doing that.  Plus, education was something I could really get excited about.  I realized I already had tons of ideas for how online learning could be improved, and I started itching to implement them.&lt;br /&gt;&lt;br /&gt;So we dug deeper, looked at the size of the market, the way contracts were signed, why innovation seemed to have stagnated, etc. and realized there was a legitimate opportunity for someone to step in and disrupt things.&lt;br /&gt;&lt;br /&gt;So we did.  We started jotting down what we thought was busted, how we thought the system should look -- and then we did the very hard thing that I think a lot more startups should do.  Instead of starting to write code, which both of us loved doing, we took all our ideas and built them into a mocked-up version of the product in PowerPoint.  Then we started calling schools.  We would cold-call the CTO, CIO or the head of Instructional Design and tell them we were a new company who wanted to show our thoughts on the future of the LMS and get their feedback as well.&lt;br /&gt;&lt;br /&gt;We had a very favorable response, and met with eighteen universities over the summer of 2008 including UCLA, Berkeley, UNLV, UVU, Westminster and USC.  Everyone loved what we were doing and gave us great feedback.  After each school we'd write down a ton of notes, re-work the PowerPoint and go at it again.  We learned a TON and ended up with a very compelling product.&lt;br /&gt;&lt;br /&gt;After that we found an angel investor who funded us enough to start development and, well, haven't stopped for a breath since then.  We now have a team of eight, a few contracts under our belt, and a bunch more on the way.  I'm having all sorts of fun integrating with big-name web tools, building new approaches to education problems, and designing simple but effective interactions for teachers and students.  It's been a blast, and I don't see that changing in the near future.&lt;br /&gt;&lt;br /&gt;Good times :-).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-5433015090000313815?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/7qn0071-ZIQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/5433015090000313815/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=5433015090000313815" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/5433015090000313815?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/5433015090000313815?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/7qn0071-ZIQ/story-of-instructure.html" title="The Story of Instructure" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2010/05/story-of-instructure.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUAMSXk4eyp7ImA9WxNbFko.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-8321228337710425960</id><published>2009-11-19T16:30:00.000-08:00</published><updated>2009-11-19T16:43:08.733-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-19T16:43:08.733-08:00</app:edited><title>Google's Crowdsourcing the Training Set</title><content type="html">In all the Google news today, one piece that hasn't gotten much attention is the &lt;a href="http://bit.ly/1afjkq"&gt;YouTube speech recognition tool&lt;/a&gt;.  There's a hidden bit of genius in Google's implementation of this easy captioning tool for YouTube videos (which, by the way, will rock for educational accessibility purposes).  Right now it's only turned on for a few trusted sites, but Google is looking to beef up its speech recognition classifier even more by gathering auto tracks from all its YouTube videos.  This is actually a much richer dataset than the Goog-411 could provide (or even Google Voice voicemails, really).&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/kTvHIDKLFqc&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/kTvHIDKLFqc&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;That's not the genius part, though.  The real genius is Google's "automatic caption timing", where you type in the textual version of your video and YouTube will automatically chunk it up into caption blocks based on what it can decipher from the video.  Adding captions is now a cakewalk, so why wouldn't you do it?&lt;br /&gt;&lt;br /&gt;Let me say that again, another way.  Google has found a way to motivate people to, of their own free will, send in textual versions of their audio tracks.  An accurate textual representation of the audio a machine learning algorithm is going to try to classify as, well, text.  They just won themselves a huge, presumably fairly accurate, training set for speech-to-text translation, donated by some not-insignificant subset of YouTube's giant population who will want captions on their videos.&lt;br /&gt;&lt;br /&gt;Google Voice voicemails may actually spit out something legible in the near future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-8321228337710425960?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/W7lBcR8Jg98" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/8321228337710425960/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=8321228337710425960" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8321228337710425960?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8321228337710425960?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/W7lBcR8Jg98/googles-crowdsourcing-training-set.html" title="Google's Crowdsourcing the Training Set" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2009/11/googles-crowdsourcing-training-set.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMERXo6fyp7ImA9WxJbGE0.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-4903436613506632608</id><published>2009-07-28T11:44:00.000-07:00</published><updated>2009-07-28T12:13:24.417-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-28T12:13:24.417-07:00</app:edited><title>Ruby ERB and output_buffer</title><content type="html">I just ran into this little frustration and thought others might, too.  I have some template files that I need evaluated, and recently I wanted to add in some new functionality similar to the content_for method used in Rails templates, but in my own special way.  I don't want them just rendered like Rails controllers because I don't need all that overhead for what are really some pretty small template files.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The funny thing about Rails is that if you try to go off the beaten path, everyone will ask why you're bothering to wander off, and shouldn't you just stay where it's comfortable?  Probably 95% of the time they're right (and 3% of the rest of the time you realize six months later that they were probably right), but there are cases where it's useful to do something a little different (I think).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, most of the posts I saw on using ERB talked about its scary voodoo magic internals that aren't worth delving into.  So I didn't.  I had what I thought was a pretty basic problem, as follows:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I defined a method &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;my_method &lt;/span&gt;that I wanted to call from within the templates which, for starters, I just wanted to assign to an instance variable.  So I wrote:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="font-family:-webkit-monospace;font-size:100%;"&gt;&lt;span class="Apple-style-span"  style=" white-space: pre;font-size:13px;"&gt;&lt;span class="Apple-style-span"   style="font-family:Georgia;font-size:130%;"&gt;&lt;span class="Apple-style-span"  style=" white-space: normal;font-size:16px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;pre&gt;def my_method(name, &amp;amp;block)&lt;br /&gt; res = yield&lt;br /&gt; self.instance_variable_set("@value_#{name}".to_sym, res.to_s.strip)&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def parse!(template)&lt;br /&gt; b = binding&lt;br /&gt; self.body = ERB.new(template, 0, "%&lt;&gt;").result(b)&lt;br /&gt; self.value_a = @value_a&lt;br /&gt; self.body&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Looked good to me, pretty simple.  But if I passed in the template:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;Start Template&lt;br /&gt; &amp;lt;% my_method :a do %&amp;gt;&lt;br /&gt; value for a&lt;br /&gt; &amp;lt;% end %&amp;gt;&lt;br /&gt;End Template&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;then I'd get:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;== value for self.body ==&lt;br /&gt;Start Template&lt;br /&gt;value for a&lt;br /&gt;End Template&lt;br /&gt;&lt;br /&gt;== value for self.value_a ==&lt;br /&gt;Start Template&lt;br /&gt;value for a&lt;br /&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is what is generally considered bad, and not correct.  I messed around with things for a while and got nowhere.  Then I dug into how Rails was evaluating templates and its &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;content_for&lt;/span&gt; method.  ActionView::Base has an accessor called &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;output_buffer&lt;/span&gt; being used by CaptureHelper (where &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;content_for &lt;/span&gt;is defined) in a way I couldn't understand at first.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When you call &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;content_for&lt;/span&gt;, part of its process is to store the value of &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;output_buffer &lt;/span&gt;as &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;old_output_buffer&lt;/span&gt;, then call its &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;yield &lt;/span&gt;and finally re-set &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;output_buffer &lt;/span&gt;to its original value.  Weird, but at least it was a start.  So I blindly added &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;attr_accessor :output_buffer&lt;/span&gt; to my class and hoped for the best.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;No love.  I dug around a little more and found the rest of the trick.  One of the arguments for ERB.new is the name of the local variable to use to store the string buffer used in the ERB evaluation.  I'd never used that before because I didn't care, but if I set that value to "@output_buffer" then everything works magically.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So the new code is:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;def my_method(name, &amp;amp;block)&lt;br /&gt; old_buffer, @output_buffer = @output_buffer, ''&lt;br /&gt; res = yield&lt;br /&gt; self.instance_variable_set("@value_#{name}".to_sym, res.to_s.strip)&lt;br /&gt; @output_buffer = old_buffer&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def parse!(template)&lt;br /&gt; b = binding&lt;br /&gt; self.body = ERB.new(template, 0, "%&lt;&gt;", "@output_buffer").result(b)&lt;br /&gt; self.value_a = @value_a&lt;br /&gt; self.body&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;And suddenly everything works like a champ.  Happy sigh.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-4903436613506632608?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/dsRsH2YnU_U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/4903436613506632608/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=4903436613506632608" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/4903436613506632608?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/4903436613506632608?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/dsRsH2YnU_U/ruby-erb-and-outputbuffer.html" title="Ruby ERB and output_buffer" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2009/07/ruby-erb-and-outputbuffer.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEDQ3Y5eip7ImA9WxJXEUg.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-8598699294844105291</id><published>2009-06-04T14:36:00.000-07:00</published><updated>2009-06-04T14:57:52.822-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-04T14:57:52.822-07:00</app:edited><title>Google Wave Limitations</title><content type="html">&lt;a href="http://wave.google.com/"&gt;&lt;img style="margin: 0px auto; display: block; text-align: center; cursor: pointer; width: 200px; height: 200px;" src="http://2.bp.blogspot.com/_YFZ-FVkAzBU/SihAy0CISXI/AAAAAAAAHaQ/NeyQX0Dt1yk/s200/wavelogo.png" alt="" id="BLOGGER_PHOTO_ID_5343592199580305778" border="0" /&gt;&lt;/a&gt;Don't get me wrong.  I dig(g?) the Wave.  I think it's got some great potential to really disrupt things in a much-needed way.  But I'm still skeptical.  I've tried to figure out what I can about Wave given that I don't even have a sandbox account yet, and now I want to share my thoughts.  So here's what I think Wave doesn't do:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Wave Will Replace Blogs&lt;/span&gt;&lt;br /&gt;&lt;img style="margin: 0pt 10px 3px 0pt; float: left; cursor: pointer; width: 122px; height: 122px;" src="http://3.bp.blogspot.com/_YFZ-FVkAzBU/Sig-8FRI8fI/AAAAAAAAHZ4/z_GkdYM2XV8/s200/icon_blogger.gif" alt="" id="BLOGGER_PHOTO_ID_5343590159802233330" border="0" /&gt;If you're interested in Wave, you've probably &lt;a href="http://wave.google.com/"&gt;already seen the Wave video&lt;/a&gt;.  One of the examples in the video shows embedding waves as blog posts, so you get real-time comments from visitors.  The thing they gloss over in the demo is that, as Wave stands right now, anyone who joins that wave has permissions to edit anything -- the original blog post, or anyone else's comments.  It's like making your blog a public wiki instead of a set of authored posts.  In the extreme case you've got almighty blog spam potential, but even in the realistic case there's potential for editing other people's comments.&lt;br /&gt;&lt;br /&gt;You could technically write a "read-only-enforcy" robot that keeps reverting segments of the wave if anyone else edits them, but, well, that smells funny.  I expect that someday Wave will add &lt;a href="http://code.google.com/apis/wave/guide.html"&gt;wavelets&lt;/a&gt; with limited editability, but that doesn't solve everything.&lt;br /&gt;&lt;br /&gt;One issue that will be addressed as this all evolves is how much are users expected to monitor the development of waves they're subscribed to?  Is it as important as responding to a new email?  How easy is it to recognize and dismiss minor edits?  If I'm still part of a wave is it assumed I endorse it?  There's some haziness that the system will have to define for itself as it develops.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Wave Will Replace Facebook&lt;/span&gt;&lt;br /&gt;&lt;img style="margin: 0pt 10px 3px 0pt; float: left; cursor: pointer; width: 120px; height: 120px;" src="http://2.bp.blogspot.com/_YFZ-FVkAzBU/Sig_7xhUOKI/AAAAAAAAHaI/_pzQ_cUj3mE/s200/facebook-icon.png" alt="" id="BLOGGER_PHOTO_ID_5343591254012999842" border="0" /&gt;Or Twitter, for that matter.  This isn't going to happen, because of one simple but significant feature in Wave: the "unread" feature.  Facebook's stream and Twitter's feeds are very much about real-time.  You don't comment on old tweets, and Facebook doesn't really make it easy to "catch-up" on old items.  There's no indication of what you might have missed between visits, and that changes the medium.  Things like Email, Feed Readers -- or Wave, for that matter, make sure to highlight any items that have seen activity.  I think that implies a sense of importance to each message, and for me anyway, I feel weird clicking any kind of "clear all" button.  What did I just dismiss?  Whose question did I just unintentionally ignore?  In Wave's case, was the latest edit a change in spelling or an important question that needs addressing?  I don't feel that urgency at all with Twitter of Facebook.  Interesting how taking away that "unread" feature completely changes the nature of the service.&lt;br /&gt;&lt;br /&gt;Anyway, I think that because of the way Wave is organized and its coming from an email background, it won't do well replacing services that are more real-time, if only because they actually mark all those changes and encourage you to review them.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Wave Will Replace the LMS&lt;/span&gt;&lt;br /&gt;&lt;img style="margin: 0pt 10px 3px 0pt; float: left; cursor: pointer; width: 80px; height: 100px;" src="http://4.bp.blogspot.com/_YFZ-FVkAzBU/Sig_ZZZgcmI/AAAAAAAAHaA/qGo3rSxcmZU/s200/logo.png" alt="" id="BLOGGER_PHOTO_ID_5343590663422243426" border="0" /&gt;I won't talk much about this, because I think it's been hit already.  &lt;a href="http://mfeldstein.com/does-google-wave-mean-the-end-of-the-lms/"&gt;Michael Feldstein made some good points&lt;/a&gt; (especially the part about how it's silly to put much stock in the death-tolls of the LMS from people who aren't even using them anymore).  &lt;a href="http://www.dr-chuck.com/csev-blog/000630.html"&gt;Dr. Chuck adds some other points&lt;/a&gt; about authorization and the inherent de-normalization of waves.&lt;br /&gt;&lt;br /&gt;For my part I'll just say I think you &lt;span style="font-style: italic;"&gt;could&lt;/span&gt; write an LMS on top of Wave, but there'd be some serious robottage going on behind the scenes to make everything play nice, and I think the decentralized nature of Waves make it too disjointed on its own.  That said, I think &lt;a href="http://www.instructure.com/"&gt;a future-looking LMS&lt;/a&gt; could seriously benefit from harnessing waves for things like group projects, peer reviews, or maybe even assessment.  That's what I'll be working on -- if Google ever gives me my sandbox account, that is.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-8598699294844105291?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/lIoZDRBVtu4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/8598699294844105291/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=8598699294844105291" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8598699294844105291?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8598699294844105291?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/lIoZDRBVtu4/google-wave-limitations.html" title="Google Wave Limitations" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_YFZ-FVkAzBU/SihAy0CISXI/AAAAAAAAHaQ/NeyQX0Dt1yk/s72-c/wavelogo.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2009/06/google-wave-limitations.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYMR3s5fSp7ImA9WxJREUs.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-2615585089242804450</id><published>2009-05-12T15:09:00.000-07:00</published><updated>2009-05-12T15:26:26.525-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-12T15:26:26.525-07:00</app:edited><title>jQuery UI :tabbable -- what the?</title><content type="html">This week I've been working on adding some basic accessibility tweaks to our site.  Instead of starting from scratch, I've been peeking at the &lt;a href="http://jqueryui.com/"&gt;jQuery UI&lt;/a&gt; code, because I know those guys have been working with the &lt;a href="http://www.w3.org/WAI/intro/aria.php"&gt;ARIA &lt;/a&gt;blokes to "accessibleize" jQuery UI.  I think that's greate for everybody, by the way, for specifically this reason.  Instead of having just the specs alone, I can study the standards and also look at how some real-world coders have implemented those standards.&lt;br /&gt;&lt;br /&gt;Anyway, the trick I wanted to duplicate was the dialog's auto-focus trick.  When a jQuery UI dialog pops up it automatically shifts tab focus to the first element in the dialog that can receive focus, which is nice for accessibility because then even a non-visual user's attention is brought to the dialog.  I could have thrown together a quick selector that checks for the first anchor, input element or whatever, but like I said, I wanted to see what they'd done.&lt;br /&gt;&lt;br /&gt;I snuck into the source, and noticed they're using a selector filter called ":tabbable" to select the elements that, I assumed, was capable of being tabbed to.  A quick Google search and I found nothing -- hence this post.&lt;br /&gt;&lt;br /&gt;Apparently jQuery UI is adding two very useful (for accessibility purposes, anyway) selector filters to the jQuery selector engine, ":focusable" and ":tabbable".  Here's the code:&lt;br /&gt;&lt;br /&gt;&lt;pre style="overflow: auto;"&gt;//Additional selectors&lt;br /&gt;$.extend($.expr[':'], {&lt;br /&gt;  data: function(elem, i, match) {&lt;br /&gt;    return !!$.data(elem, match[3]);&lt;br /&gt;  },&lt;br /&gt;&lt;br /&gt;  focusable: function(element) {&lt;br /&gt;    var nodeName = element.nodeName.toLowerCase(),&lt;br /&gt;      tabIndex = $.attr(element, 'tabindex');&lt;br /&gt;    return (/input|select|textarea|button|object/.test(nodeName)&lt;br /&gt;      ? !element.disabled&lt;br /&gt;      : 'a' == nodeName || 'area' == nodeName&lt;br /&gt;        ? element.href || !isNaN(tabIndex)&lt;br /&gt;        : !isNaN(tabIndex))&lt;br /&gt;      // the element and all of its ancestors must be visible&lt;br /&gt;      // the browser may report that the area is hidden&lt;br /&gt;      &amp;amp;&amp;amp; !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;&lt;br /&gt;  },&lt;br /&gt;&lt;br /&gt;  tabbable: function(element) {&lt;br /&gt;    var tabIndex = $.attr(element, 'tabindex');&lt;br /&gt;    return (isNaN(tabIndex) || tabIndex &gt;= 0) &amp;amp;&amp;amp; $(element).is(':focusable');&lt;br /&gt;  }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;:focusable selects the list of elements that are inherently focusable, i.e. anchor tags, input elements, form elements that aren't disabled, or elements that have a defined "tabindex" attribute.  :tabbable is a subset of this list, only including those :focusable elements that have tabindex &gt;= 0.  You can set an element to have tabindex="-1" and it will be focusable, but won't show up anywhere in the page's tab order, hence it's not tabbable.&lt;br /&gt;&lt;br /&gt;Anyway, cool stuff.  If you use this you'll probably want to check ":visible" as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-2615585089242804450?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/iNWYve07w0E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/2615585089242804450/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=2615585089242804450" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/2615585089242804450?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/2615585089242804450?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/iNWYve07w0E/jquery-ui-tabbable-what.html" title="jQuery UI :tabbable -- what the?" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2009/05/jquery-ui-tabbable-what.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MHRHw6fSp7ImA9WxVbFUw.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-6078451032219683454</id><published>2009-03-31T09:57:00.001-07:00</published><updated>2009-03-31T10:10:35.215-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-31T10:10:35.215-07:00</app:edited><title>How Desire2Learn is avoiding Blackboard's New Patent</title><content type="html">Just found &lt;a href="http://ocolly.com/2009/03/31/desire2learn-modifies-site-to-avoid-lawsuit/"&gt;this article&lt;/a&gt; talking about Desire2Learn's new version.  This is in response to Blackboard's recent suit over their &lt;a href="http://www.freepatentsonline.com/7493396.html"&gt;newly-received patent&lt;/a&gt;.  Blackboard just can't seem to leave it alone, they want some D2L blood.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, the workaround is one that won't affect most users.  Instead of listing all courses in a single list, the new version of D2L's LMS will have multiple tabs, one for each role.  So if you're a TA and a student, you'll have a tab for the classes you're TA'ing and a tab for the classes you're taking.  If you're just a student or just a teacher, you won't notice any difference at all.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is pretty similar to the &lt;a href="http://brianwhitmer.blogspot.com/2009/03/all-right-who-gave-billy-another-marker.html"&gt;workaround I suggested&lt;/a&gt; the other day, but it still lets the interface offer custom links for different roles.  Desire2Learn is very confident in their workaround, having already run it past outside legal counsel, and even I in my patent-meekness can see it's a good fit.  The clincher in Bb's new patent is that it requires that after a user logs in they are presented with a list of courses for which they have access, and that the links for those courses must vary depending on the role the user has for each course.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I guess technically Bb could still get mad, but this version is a much harder sell on infringement.  Here's the actual text:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;wherein the step of providing access in response to the single login by the user includes presenting, with a login manager, the user with a list of courses, wherein the list includes a set of respective hyperlinks for each of the courses for which the user is to have a level of access and further wherein at least one of the sets of respective hyperlinks varies according to the associated respective role, wherein each of the respective hyperlinks points to an associated course web page. &lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What I get from that is that D2L is in the clear as long as the list of hyperlinks presented after login are the same for all the courses presented.  Again, Bb could &lt;i&gt;try&lt;/i&gt; to sue still, and argue that the two lists are just one list on separate pages.  But meh.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-6078451032219683454?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/xlEMZh1cUYI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/6078451032219683454/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=6078451032219683454" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/6078451032219683454?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/6078451032219683454?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/xlEMZh1cUYI/how-desire2learn-is-avoiding.html" title="How Desire2Learn is avoiding Blackboard's New Patent" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2009/03/how-desire2learn-is-avoiding.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0AHR3o5eyp7ImA9WxVbFEk.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-4298095278710987956</id><published>2009-03-29T14:36:00.000-07:00</published><updated>2009-03-30T12:35:36.423-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-30T12:35:36.423-07:00</app:edited><title>Studeous, the Bucket has Kicked</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YFZ-FVkAzBU/SdEdvKwat1I/AAAAAAAAGw0/i76uQh-ZnSY/s1600-h/studeous.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 207px; height: 89px;" src="http://2.bp.blogspot.com/_YFZ-FVkAzBU/SdEdvKwat1I/AAAAAAAAGw0/i76uQh-ZnSY/s320/studeous.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5319065331079755602" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="clear: left;"&gt;&lt;/div&gt;&lt;div&gt;Well, it looks like Studeous is, for all intents and purposes, no more.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's their death message, &lt;a href="http://www.classroom20.com/forum/topics/649749:Topic:183526"&gt;as I found it&lt;/a&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;Dear Studeous Teachers,&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Due to increasing costs and marginal revenue from our teacher-based offering, we have decided to shut down Studeous.com as it is right now. We will still be offering our school-based version, Studeous Campus Suite, to K-12 schools and colleges. If you have purchased a paid account, we will refund you the pro-rated amount.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Please download all the files you would like to keep, as we will be shutting the service down this Wednesday, March 18. We apologize for the inconvenience.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sincerely,&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Studeous Team&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Okay, so it's not actually a death message, and they do technically still exist in some form or another (though you wouldn't think so if you visited &lt;a href="http://studeous.com/"&gt;their web site&lt;/a&gt;).  But it's clear that, even if this isn't the end of Studeous, it's going to be perceived that way.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'll confess that I'm a little sad to see them go, if only because of how it affects things for the rest of us.  Studeous, for those that don't know, was a startup Learning Management System that was trying to be a bit more approachable than the big boys are right now.  They were pricing themselves quite a bit cheaper than everyone else (which I think was part of the problem) and also giving it away free to invidual teachers.  The interface wasn't all that exciting, sort of a Facebook theme on top of a traditional LMS, but they did have some nice new features and they were more open than the other guys.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;More importantly, they had a name and a little bit of traction.  I was catching &lt;a href="http://search.twitter.com/search?q=studeous"&gt;little snippets of comments&lt;/a&gt; from people about Studeous, comparing it to Blackboard or Moodle or whatever.  Some people were excited about the new guy in town, and about healthy competition.  Now they've tanked, and that's going to make progress all that much harder.  If a startup with a name falls on their face, people are going to hesitate before jumping onto the next go-round.  Add to that recent events like Google's &lt;a href="http://www.readwriteweb.com/archives/google_giveth_and_it_taketh_away.php"&gt;dropping of some young services&lt;/a&gt; and I don't really blame them.  Teachers are using this stuff for their classes, for goodness sake, and if they can't trust the service to be around six months from now (Studeous, by the way, served up a double-whammy in that they bailed mid-semester.  Harsh.) then there's not much point in investing the time to learn and leverage it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The other product I keep hearing about, &lt;a href="http://www.edu20.org/home"&gt;edu2.0&lt;/a&gt;, seems to still be alive and kicking.  I'm not terribly excited about their product or their interface (or the fact that they have no plans for a viable business model), but options are always a good thing.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We'll see how this all plays out.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-4298095278710987956?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/dhjceCcWasI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/4298095278710987956/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=4298095278710987956" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/4298095278710987956?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/4298095278710987956?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/dhjceCcWasI/studeous-bucket-has-kicked.html" title="Studeous, the Bucket has Kicked" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_YFZ-FVkAzBU/SdEdvKwat1I/AAAAAAAAGw0/i76uQh-ZnSY/s72-c/studeous.png" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2009/03/studeous-bucket-has-kicked.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YDQHY4fip7ImA9WxVbEUo.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-8957825840224910832</id><published>2009-03-27T08:40:00.000-07:00</published><updated>2009-03-27T10:32:51.836-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-27T10:32:51.836-07:00</app:edited><title>All right, who gave Billy another marker?</title><content type="html">I leave the room for five minutes, and look what happens!  Honestly, don't you remember what happened last time Billy got his hands on a marker?  There were smudges &lt;i&gt;all over&lt;/i&gt; the walls!  Who's the genius that thought we should give him another one?&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Change "Billy" to "&lt;a href="http://www.desire2learn.com/mail/patent/emailClient-Mar19-09.html"&gt;Blackboard&lt;/a&gt;", and "marker" to "&lt;a href="http://www.freepatentsonline.com/7493396.html"&gt;patent&lt;/a&gt;" and you've got yourself some news.  This one (7,493,396) seems to have slipped under the radar as it happened February 17.  But thanks to &lt;a href="http://www.desire2learn.com/mail/patent/emailClient-Mar19-09.html"&gt;Desire2Learn's openness&lt;/a&gt; we at least know about it now.  This is a different patent from the &lt;a href="http://www.google.com/patents?id=RX94AAAAEBAJ&amp;amp;dq=6988138"&gt;infamous '138 patent of yesteryear&lt;/a&gt; (6,988,138)-- although Blackboard is again up to its old antics, and has already slapped Desire2Learn (not just the stateside version this time) with a suit for patent infringement.  Apparently the suit was filed only hours after the judge denied Blackboard's second attempt to stay proceedings of the appeals case for the original suit.  Good times, good times.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, I'm slightly baffled as to how this even happened.  I've read both patents, and while there are some differences, they are actually somewhat similar.  They both cover essentially a course management system in which a single user can have multiple roles amounting to different levels of access.  Reading over the second patent, which was filed five years after the first but still before the first was granted, it seems in a lot of ways a follow-up attempt when the expectation was that the first patent wouldn't fly -- which it shouldn't have.  Rants about software patents aside, it was still a very broad patent and there was clearly (well, not to me, but to those in the know at the time) &lt;a href="http://en.wikipedia.org/wiki/History_of_virtual_learning_environments"&gt;prior art&lt;/a&gt;.  As a result, that patent has been shot down not once, but twice -- once in court, and once by the USPTO (both are still non-official).  Normally you only get one or the other, but that's another story.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So where does that leave us now?  The first patent is for all intents and purposes out of the running for the time being, all tied up in legal proceedings as it is.  The second is very much alive.  All I can guess is that the second patent, since it is a bit more specific, doesn't raise any "prior art" red flags in the patent office.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For those that aren't patent-aware, patents are a list of claims, with a few major claims and a bunch of minor claims based on those major claims.  The new patent has three major claims (1, 18 and 28), which are all pretty similar.  If you can work your way around the major claims, then you don't even have to worry about the minor claims.  The verbage still includes the requirement of users potentially having multiple roles for a single account, but also includes the requirement that after login the user is presented with a list of the courses they have access to, and that the links for those courses vary depending on the user's role for each course.  In short, if the course list after login looks the same for both teachers and students then you're golden.  Keep in mind I'm not a lawyer, and there may be other bigger loopholes as well that I'm just not adept enough to see.  At any rate, even that small one seems to take out a lot of the patent's teeth.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In my opinion, the new patent should also never have been granted.  In 2005 when the patent was filed there was already plenty of prior art.  Moodle and ATutor had been around for four years already and I can't imagine they didn't have multiple roles yet -- especially since TA counts as a different role than student.  I'll have to do some digging, but this just seems silly.  Another patent so Blackboard can go mucking about once again.  Sigh.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-8957825840224910832?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/EhM5QZkgQCQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/8957825840224910832/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=8957825840224910832" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8957825840224910832?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8957825840224910832?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/EhM5QZkgQCQ/all-right-who-gave-billy-another-marker.html" title="All right, who gave Billy another marker?" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2009/03/all-right-who-gave-billy-another-marker.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEBSXY4fSp7ImA9WxVQEU0.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-2306644285274773924</id><published>2009-01-27T17:00:00.001-08:00</published><updated>2009-01-27T17:37:38.835-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-27T17:37:38.835-08:00</app:edited><title>Are rounded corners THAT hard to implement?</title><content type="html">So Microsoft has just announced their first (and probably only) &lt;a href="http://blog.wired.com/business/2009/01/more-details-ab.html"&gt;release candidate of Internet Explorer 8&lt;/a&gt;.  For those in the not-know, release candidates fit somewhere between betas and final releases, most often leaning closer to the final release.  It's a last chance to make sure there's nothing seriously wrong before actually releasing the product.&lt;br /&gt;&lt;br /&gt;IE8's supposed to add a bunch of new features, while not changing the actual interface much at all.  If you look at the list of new features for IE8, it's pretty much a smattering of a bunch of little cool things -- no real direction, just a bunch of little cool things.  They have web snippets, some new accessibility events, a safe JSON parser, etc. etc.  I'm fine with all that, I'd actually really love for every browser to get a JSON parser and improved accessibility.  My beef is what they don't have.&lt;br /&gt;&lt;br /&gt;Rounded corners.&lt;br /&gt;&lt;br /&gt;Most other major browsers (Firefox, Safari, Chrome) have support for those friendly little curves on the edges of your layout boxes.  Microsoft, however, has said they're basically not expanding their CSS support at all, just sticking with the CSS 2.1 that they already complies with.  I guess they did say it's "high on the wish list" and to expect it in the next version, but my complaint is, how hard is it really to implement rounded corners?  I mean, they could seriously have had one intern working on it for a few months and he probably could have managed rounded corners in CSS.&lt;br /&gt;&lt;br /&gt;What's the big deal, you may ask.  Who cares about rounded corners anyway?  Well.  If you were to ask a web designer, what's the most-awkwardly-hacked-on layout feature in today's web pages, they'd almost definitely say it's rounded corners.  There are so many "workarounds" for the rounded corner problem it's not even funny.  Most of them use tables and CSS -- insert cringe here -- to get around the problem, but that's like using toothpaste to fill the holes in your walls.  It technically works, but it's really not the right tool for the job.  Not to mention how much it can bork with accessibility and semantic meaning.&lt;br /&gt;&lt;br /&gt;Anyway, everyone knows that anywhere from 30-90% of a web site's users are on IE, so until Microsoft implements rounded corners we're stuck in nastyland.  I'm a little frustrated with Microsoft over this one, actually.  They had the opportunity to save thousands of web sites from code nastification currently happening in the name of aesthetics, and they just didn't bother.  I seriously doubt it would have taken THAT much effort, and even an unfinished implementation (say, we only do up to 10 pixel rounding, for example) would have been good enough for me.  Honestly, you shouldn't have to make a table or write twenty lines of CSS (or both) just to get some non-square navigation tabs at the top of your page.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-2306644285274773924?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/FFw1i4LW6ro" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/2306644285274773924/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=2306644285274773924" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/2306644285274773924?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/2306644285274773924?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/FFw1i4LW6ro/are-rounded-corners-that-hard-to.html" title="Are rounded corners THAT hard to implement?" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2009/01/are-rounded-corners-that-hard-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0AFRngzfip7ImA9WxVTGU8.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-3213484662060925877</id><published>2009-01-02T10:01:00.000-08:00</published><updated>2009-01-02T11:48:37.686-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-02T11:48:37.686-08:00</app:edited><title>jQuery 1.3 delegation</title><content type="html">This post will most likely be useful only to me, but I'm extremely excited about the new version of jQuery that's coming out, and I wanted to put down some of its new features before I forget, and to make sure I understand them completely.  If you aren't familiar with javascript event delegation, this probably won't mean a lot to you (&lt;a href="http://www.robertnyman.com/2008/05/04/event-delegation-with-javascript/"&gt;here's a quick tutorial&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;I went poking around in &lt;a href="http://dev.jquery.com/changeset/5990"&gt;the jQuery &lt;/a&gt;&lt;a href="http://dev.jquery.com/changeset/5987"&gt;revisions &lt;/a&gt;because I haven't found hardly any details on what exactly is changing with the new version (other than speedups and such, but those don't excited me nearly as much as other people -- probably because I tend to write my code for the speed of "right now" instead of for a future version, so if something is changing from slow to fast, I'm probably not using it anyway).  There's some good stuff going into this new version.&lt;br /&gt;&lt;br /&gt;And more than just &lt;a href="http://github.com/jeresig/sizzle/tree/master"&gt;Sizzle&lt;/a&gt;, which I'm not going to spend any time on.&lt;br /&gt;&lt;br /&gt;So I've been using the &lt;a href="http://code.google.com/p/reglib/"&gt;jQuery event delegation plugin&lt;/a&gt; on my most recent project, and it works nicely, but there are a few problems.  First is that your selectors have to match on the target of the event, not an ancestor.  So if I have a list of "div.child"s inside of a "div.parent", I call:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$("div.parent").delegate('click', 'div.child', function(e) { });&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;to watch for clicks on any of the div.child's.  The problem here is that if I have an image tag inside of the div.child, and the user clicks on the image instead of the whitespace in the div, then the delegation plugin won't trigger the event.  I actually did a quick rewrite of the plugin on my own to check against parents as well, changing:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;return this.bind(type, function(event) {&lt;br /&gt;   var target = $(event.target);&lt;br /&gt;   if (target.is(delegate)) {&lt;br /&gt;       return handler.apply(target, arguments);&lt;br /&gt;   }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;to:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;return this.bind(type, function(event) {&lt;br /&gt;   var target = $(event.target);&lt;br /&gt;   if (target.is(delegate)) {&lt;br /&gt;       return handler.apply(target, arguments);&lt;br /&gt;   }&lt;br /&gt;   var $container = $(this);&lt;br /&gt;   var $parent_target = null;&lt;br /&gt;   target.parents().each(function() {&lt;br /&gt;       if($(this).is(delegate)) {&lt;br /&gt;           $parent_target = $(this);&lt;br /&gt;           return false;&lt;br /&gt;       }&lt;br /&gt;       if($(this)[0] == $container[0]) {&lt;br /&gt;           return false;&lt;br /&gt;       }&lt;br /&gt;   });&lt;br /&gt;   if($parent_target) {&lt;br /&gt;       return handler.apply($parent_target, arguments);&lt;br /&gt;   }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Problem solved -- for me, anyway.  But the better news is that jQuery's new delegation mechanism takes care of this for you!  &lt;a href="http://dev.jquery.com/changeset/5987"&gt;It's got a .closest method&lt;/a&gt; that matches on the element or its closest matching ancestor.  Pretty vital, if you ask me, for any actually usable delegation system.  In that case you could replace my code with:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;return this.bind(type, function(event) {&lt;br /&gt;   var closest = $(event.target).closest(delegate);&lt;br /&gt;   if (closest.length &gt; 0) {&lt;br /&gt;       return handler.apply(closest, arguments);&lt;br /&gt;   }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So that's cool, and it contented me for a while, but then I ran into another problem: bubbling.  Normal user events bubble just fine, but jQuery also lets you trigger artificial events using .click, .submit, or .trigger(type) methods -- these don't bubble.  At least, they didn't used to.  &lt;a href="http://www.ejohn.org/"&gt;Resig &lt;/a&gt;&lt;a href="http://dev.jquery.com/changeset/5988"&gt;fixed that as well&lt;/a&gt; in the new version, for which I am extremely grateful.  Hours of conniving workarounds were wasted, but I can handle that.&lt;br /&gt;&lt;br /&gt;As it turns out, I may still be using the delegation plugin, as enhanced by the new changes in jQuery 1.3.  I wasn't entirely sure how&lt;a href="http://dev.jquery.com/changeset/5990"&gt; jQuery's new .live and .die functions&lt;/a&gt; behaved, so I didn't know how applicable they'd be, but &lt;a href="http://ejohn.org/"&gt;John Resig&lt;/a&gt; himself left a nice comment on &lt;a href="http://ajaxian.com/archives/jquery-13-beta-sizzling-and-feature-testing"&gt;Ajaxian's post&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;We’re not using the name ‘delegate’ because it isn’t normal event delegation (not to mention that there are already a number of delegate plugins using that name). Typically when someone wants to do full delegation they also want to specify the root element - e.g.: $(”#someroot”).delegate(”div”, “click”, someFn); We wanted to provide something that was much simpler than normal delegation but still leave room for people to write their own full delegation code/plugins.&lt;/blockquote&gt;&lt;br /&gt;What he means about it not being "normal event delegation" is that jQuery's .live and .die methods don't let you specify who you're delegating to.  It's always a the document (root) level.  So if I call:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$("div.child").live('click', function(e) { });&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(which, by the way, would be the appropriate way to listen for clicks on any div.child's in the document) then it always bubbles all the way up to the document.  What if you just want to catch clicks on div.child's that are inside a "div.parent"?  Not possible with .live and .die.  That's ok, though, because I'm willing to bet most people won't care, and if nothing else this addition offers a great starting point for those new to event delegation.  This is a great piece of functionality, and the fact that it handles both inner-element events and triggered-event bubbling makes me a very happy programmer.&lt;br /&gt;&lt;br /&gt;As a side note, you can kill all delegated functions of a given type with:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$("div.child").die('click');&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;or just a specific function with:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$(".div.child").die('click', function_to_stop_calling);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Resig is calling this a &lt;a href="http://brandonaaron.net/docs/livequery/"&gt;livequery&lt;/a&gt;/&lt;a href="http://stilbuero.de/jquery/delegate/"&gt;event delegation&lt;/a&gt; hybrid, although it's really more delegation than anything.  I think the reasoning there is that more people know of and use livequery than the delegation plugins, so it's more familiar, and in fact the syntax is more like livequery than delegation -- although honestly there's not that much difference between the two.  Either way, it's a great addition to a great library, and a useful inclusion of a great new feature in web programming.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-3213484662060925877?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/xUqUhE2nvwM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/3213484662060925877/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=3213484662060925877" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/3213484662060925877?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/3213484662060925877?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/xUqUhE2nvwM/jquery-13-delegation.html" title="jQuery 1.3 delegation" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2009/01/jquery-13-delegation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQASX4zfCp7ImA9WxRaE0s.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-6764064335106347834</id><published>2008-12-15T10:26:00.000-08:00</published><updated>2008-12-15T10:55:48.084-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-15T10:55:48.084-08:00</app:edited><title>jQuery events: setting a property that has only a getter</title><content type="html">I ran into a new problem in jQuery the other day, and I couldn't find a good solution for it.  Hence, a new post in the hopes of helping out the next individual.&lt;br /&gt;&lt;br /&gt;In case you didn't know, I'm working on a modern learning management system for Instructure.  Good stuff, but I can't spill too many beans yet.  Sorry. &lt;br /&gt;&lt;br /&gt;Anyway, as part of that I need a good javascript WYSIWYG editor (love to do just &lt;a href="http://en.wikipedia.org/wiki/WYSIWYM"&gt;WYSIWYM&lt;/a&gt;, but I don't think it's general enough for all faculty) and I've settled on &lt;a href="http://tinymce.moxiecode.com/"&gt;TinyMCE &lt;/a&gt;for the time being -- mostly because they've actually got some accessibility functionality baked in.  I've written a jQuery wrapper around it for all the features I need to get at (because let's face it, TinyMCE's API is NOT intuitive, and I'd prefer to touch it as little as possible), but I also need to capture key events so I can treat the "escape" key like a cancel click.  Sadly, TinyMCE uses iframes and eats up javascript events before you can get to them.&lt;br /&gt;&lt;br /&gt;No problem, TinyMCE's API lets you catch key and mouse events and do what you will with them.  To make things simple I'm listening for key events on all form text elements, so I just want to take TinyMCE's key event and pretend like it got called on the textarea that TinyMCE replaced.  jQuery has a .trigger method that lets you call events as if they happened on the selection, so I just pass the event TinyMCE gives me into jQuery.&lt;br /&gt;&lt;br /&gt;Bzzzt!  Firefox throws an error, "setting a property that has only a getter".  Blast.  I futz around with it for a bit, can't solve it, so I finally muster the courage to dive into jQuery code and figure out what the problem is.  The error's being thrown because the jQuery trigger method asks you to specify the event type ("keydown", "mouseup", etc.) and then sets the event.type property to make sure it's the right type.  Problem is, javascript native events don't let you SET the event type, only get it.  Hence the error.&lt;br /&gt;&lt;br /&gt;Double-blast.  Okay, so now what?  I dig a little deeper (like I said before, no good documentation that I could find on this) to see what jQuery's doing with events.  When jQuery catches an event, it wraps it in a jQuery event object to make things happy (and you can set the event.type property on this wrapped object to your heart's content).  So if I just wrap the event, problem solved.  I realized I should probably do this anyway, because while the only error I hit was setting an unsettable property, there's probably other kinks I don't want to deal with.&lt;br /&gt;&lt;br /&gt;So how do you wrap events?  Turns out it's pretty easy.  Instead of:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;if(e.type == 'keydown') {&lt;br /&gt;    $("selection").trigger(e.type, e);&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;You use:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;if(e.type == 'keydown') {&lt;br /&gt;     $("selection").trigger(e.type, $.event.fix(e));&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;That's if you have "$" as an alias for jQuery.  Otherwise you'd call jQuery.event.fix(e) to get the wrapped object.&lt;br /&gt;&lt;br /&gt;Also, I'm actually using triggerHandler instead of trigger.  Trigger just fires the event, while triggerHandler triggers everything except the default behavior (that way I'm not initiating a keydown on the textarea and inadvertently adding text).&lt;br /&gt;&lt;br /&gt;Problem solved!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-6764064335106347834?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/m3SWl4a5mMk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/6764064335106347834/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=6764064335106347834" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/6764064335106347834?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/6764064335106347834?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/m3SWl4a5mMk/jquery-events-setting-property-that-has.html" title="jQuery events: setting a property that has only a getter" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2008/12/jquery-events-setting-property-that-has.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYFQHs5fip7ImA9WxRVF08.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-7537670307009785056</id><published>2008-11-14T18:48:00.000-08:00</published><updated>2008-11-14T20:25:11.526-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-14T20:25:11.526-08:00</app:edited><title>Universities and OpenID</title><content type="html">Today's &lt;a href="http://www.edtechpost.ca/wordpress/2008/11/14/best-password-recovery/"&gt;post by Scott Leslie&lt;/a&gt; got me thinking about universities and their identity systems.  The issue Scott brought up was getting all these web services to play nice with the university's system.  Teachers are getting tired of the lack of functionality that's available from their LMS (I have some &lt;a href="http://brianwhitmer.blogspot.com/2008/08/mashable-one-stop-shop.html"&gt;thoughts on that, too&lt;/a&gt;), so they're turning to services elsewhere that provide better features, better interaction and more flexibility.  I can't say as I blame them.  I heard that at a recent web usability conference the presenter referred to Blackboard as, essentially, the &lt;span style="font-style: italic;"&gt;anti-interface&lt;/span&gt;.  So sure, use the tools that are actually useful, and education actually benefits.&lt;br /&gt;&lt;br /&gt;That's great and all, but it leaves the students in a bit of a lurch.  That smattering of web services aren't integrated.  Like at all.  Suddenly a student needs accounts with Blogger, WordPress, the local wiki, Google Docs, etc. etc. etc.  And then they have to link up with everyone else to make things work.  Day one of class turns into a mass sign-up, sync-up session.  That's not a great place to be.  Scott put it aptly when he said “those nasty web 2.0 tools won’t single sign-on to my campus login system, so what are we to do?”&lt;br /&gt;&lt;br /&gt;Well!  OpenID is a pretty cool idea that just might help out.  I'm not going to go into specifics, because I'd probably embarass myself if I did, but the basic jist of OpenID is having a common means of authenticating users across multiple sites.  In other words, accomplishing a single sign-on, single identity for the whole web.  That way when you go to OpenID-enabled site X, instead of having to create a new username and password, you say "dude, I totally already have an account at this OpenID site.  I'll just use that account."  Then site X says, "oh, my bad.  Lemme just go check and make sure," and then "hey OpenID site, you ever heard of this dude?"  Your OpenID site finishes up with a "heck yeah" and you're signed in.  Once you've signed in once with your OpenID site, you're good to go for that browser session.  You can log in at sites X, Y and Z without registering or even putting in your password.  Cool beans.&lt;br /&gt;&lt;br /&gt;The best news?  Sites are actually starting to accept OpenID.  You can use Scribd, WordPress, Plaxo, Blogger, Disqus, etc. with a single identifier.  Right now.&lt;br /&gt;&lt;br /&gt;So here's my thought:  Why not make your university an OpenID provider?  Schools aren't going to pass their login off to someone else (any time soon, anyway), but I can't think of a reason for them not to share that login at other sites.  Let students clump all their school-related accounts into one  It would be a great thing for &lt;a href="http://en.wikipedia.org/wiki/Edupunk"&gt;&lt;/a&gt;&lt;a href="http://www.chrislott.org/"&gt;these &lt;/a&gt;"edupunk" &lt;a href="http://www.jonmott.com/blog/"&gt;folks&lt;/a&gt;, if nothing else.  Besides, I really like the idea of an OpenID account being tied to something more concrete than just a web site somewhere.  It... feels... very natural to cluster related accounts around a single global id.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-7537670307009785056?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/N8pEoO78YIU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/7537670307009785056/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=7537670307009785056" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/7537670307009785056?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/7537670307009785056?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/N8pEoO78YIU/universities-and-openid.html" title="Universities and OpenID" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2008/11/universities-and-openid.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUACQno6eCp7ImA9WxRWGU4.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-2288762689093750244</id><published>2008-11-05T16:27:00.000-08:00</published><updated>2008-11-05T17:09:23.410-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-05T17:09:23.410-08:00</app:edited><title>How to use django filters in python code</title><content type="html">Okay, so django is pretty nice.  It's a great web framework with a very straightforward templating engine, and I'm sad to be leaving it for Rails-land for the time being.  One of the nice things about django is the &lt;a href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/"&gt;set of included template tags and variable filters&lt;/a&gt;.  You can define blocks of code that can then be overwritten by templates that inherit the given template, and you can very easily format your data in view-specific ways.  The variable filters in particular come in handy.  Very often.&lt;br /&gt;&lt;br /&gt;In fact, there are times when it would be nice to be able to use those filters outside of django template code.  In the true spirit of &lt;a href="http://www.google.com/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FDon%2527t_repeat_yourself&amp;amp;ei=Kj0SSbT_LImMsAOm4q3BAg&amp;amp;usg=AFQjCNHbd1Tlapfbw-ez3fqqI1cnJXhKkA&amp;amp;sig2=TI9D5YcQV8wMlf7hGosA8A"&gt;DRY&lt;/a&gt;, I don't want to recreate django's date filter, file size formatter, &lt;a href="http://www.djangosnippets.org/snippets/43/"&gt;slugify tool&lt;/a&gt;, etc.&lt;br /&gt;&lt;br /&gt;So how do you use django filters in plain old python?  Turns out it's pretty easy:&lt;br /&gt;&lt;pre&gt;&lt;span class="p"&gt;&lt;br /&gt;def process_data():&lt;/span&gt;&lt;br /&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.template&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultfilters&lt;/span&gt;&lt;br /&gt; page_title = "How to use django filters in python code"&lt;br /&gt; page_slug = defaultfilters.slugify(page_title)&lt;br /&gt; # page_slug == "how-to-use-django-filters-in-python-code"&lt;br /&gt;&lt;br /&gt; file_size = 123456789&lt;br /&gt; file_size_display = defaultfilters.filesizeformat(file_size)&lt;br /&gt; # file_size_display == "117.7 MB"&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;And there you have it.  Good stuff.  If you don't want to keep typing "defaultfilters" you can alias it, of course.&lt;br /&gt;&lt;pre&gt;&lt;span class="k"&gt;&lt;br /&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.template&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultfilters as filters&lt;/span&gt;&lt;br /&gt;page_slug = filters.slugify(page_title)&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;You can call any filter from the &lt;a href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/#built-in-filter-reference"&gt;built-in list&lt;/a&gt; this way.  The first argument is the value upon which to perform the filter, the second argument is (optionally) the string argument used as additional information for some formats.  So&lt;br /&gt;&lt;pre&gt;&lt;span class="cp"&gt;&lt;br /&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="s2"&gt;:"D d M Y"&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;becomes&lt;br /&gt;&lt;pre&gt;&lt;span class="cp"&gt;&lt;br /&gt;defaultfilters.date(value, "D d M Y")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; Pretty straightforward stuff.  Obviously this only works for the default filters.  If you've added any more filters, you should know already where they're located and how to call them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-2288762689093750244?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/HKlZoaC92eE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/2288762689093750244/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=2288762689093750244" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/2288762689093750244?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/2288762689093750244?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/HKlZoaC92eE/how-to-use-django-filters-in-python.html" title="How to use django filters in python code" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2008/11/how-to-use-django-filters-in-python.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcNSH85fip7ImA9WxRXE0g.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-491031194129805381</id><published>2008-10-18T10:45:00.000-07:00</published><updated>2008-10-18T11:21:39.126-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-18T11:21:39.126-07:00</app:edited><title>Fickle Finances and Software Startups</title><content type="html">&lt;span style=";font-family:arial;font-size:100%;"  &gt;Too true, too true.  I ran into Paul Graham's post on &lt;a href="http://www.paulgraham.com/badeconomy.html"&gt;startups in a bad economy&lt;/a&gt; via &lt;a href="http://www.windley.com/archives/2008/10/start_your_business_now.shtml"&gt;Phil Windley's blog&lt;/a&gt;, and I very much agree with what was said, there:&lt;br /&gt;&lt;/span&gt;&lt;blockquote  style="font-family:arial;"&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;"&lt;/span&gt;&lt;span style="font-size:100%;"&gt;The economic situation is apparently so grim that some experts fear we may be in for a stretch as bad as the mid seventies.&lt;br /&gt;&lt;br /&gt;"When Microsoft and Apple were founded.&lt;br /&gt;&lt;br /&gt;"Someone who thinks 'I better not start a startup now, because the economy is so bad' is making the same mistake as the people who thought during the Bubble 'all I have to do is start a startup, and I'll be rich.'"&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style=";font-family:arial;font-size:100%;"  &gt;On the nose, I'd say!  We've been batting this idea around as we talk about eLearning technology.  The fact of the matter is, no matter how bad the economy gets, schools are still going to use an LMS because, well, they need it.  They can't ask their faculty to go back to paper grading, and they can't suddenly drop their distance learning programs.  In some ways it makes our product even more viable because it's a better return on investment.  You don't have to keep paying on top for all the plugins and features that make the product actually viable.  But in general, web services aren't going to be the first thing to go in a budget cut.&lt;br /&gt;&lt;br /&gt;The same vein goes for a lot of web technology.  Companies still need software to manage their customers and to mine their data, even with a bad economy.  People aren't going to stop using email.  They're not going to stop using Facebook or watching movies on Hulu or Netflix online or whatever.  They actually might do it more because it's cheaper than going out.  I think it's fair to say that in general it would take quite a financial sucker-punch for people to cancel their Internet service altogether.  They may even be looking for &lt;span style="font-style: italic;"&gt;new &lt;/span&gt;opportunities and experiences online.  Now, people may be reluctant to add &lt;span style="font-style: italic;"&gt;more &lt;/span&gt;monthly fees, so in that sense maybe there's an issue.  But at the same time, if you really are doing a startup &lt;span style="font-style: italic;"&gt;right now&lt;/span&gt; then you're probably offering a free beta for the next little while anyway.  And products for companies, all you need to do is hit a meaningful ROI and you're home free.&lt;br /&gt;&lt;br /&gt;Phil summarized the sentiment quite well, I thought:&lt;br /&gt;&lt;/span&gt;&lt;blockquote  style="font-family:arial;"&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;"Actually, he doesn't necessarily think starting in bad times is better than good times, just that there's nothing special about good times when it comes to starting high-tech businesses"&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style=";font-family:arial;font-size:100%;"  &gt;Phil and Paul both get the idea pretty clearly.  The technology sector is less sensitive to (or maybe just slower at reacting to) financial upheavals.  In the end it still boils down to having a good idea and doing a good job putting it forward.&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:100%;"  &gt;&lt;/span&gt;&lt;blockquote  style="font-family:arial;"&gt;&lt;span style="font-size:100%;"&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;br /&gt;"If we've learned one thing from funding so many startups, it's that they succeed or fail based on the qualities of the founders.  The economy has some effect, certainly, but as a predictor of success it's rounding error compared to the founders.&lt;br /&gt;&lt;br /&gt;"If you're worried about threats to the survival of your company, don't look for them in the news.  Look in the mirror... &lt;/span&gt;&lt;span style="font-size:100%;"&gt;If you're the right sort of person, you'll win even in a bad economy. And if you're not, a good economy won't save you."&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style=";font-family:verdana;font-size:100%;"  &gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-491031194129805381?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/Vl7BcRGtzI8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/491031194129805381/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=491031194129805381" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/491031194129805381?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/491031194129805381?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/Vl7BcRGtzI8/fickle-finances-and-software-startups.html" title="Fickle Finances and Software Startups" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2008/10/fickle-finances-and-software-startups.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cASXo6fyp7ImA9WxRTFEs.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-5541392979069278474</id><published>2008-08-25T13:55:00.000-07:00</published><updated>2008-09-03T11:04:08.417-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-03T11:04:08.417-07:00</app:edited><title>The Mashable One-Stop Shop</title><content type="html">So... interesting meeting yesterday, it really got me thinking.  We've been on the road this week talking to a bunch of schools, and one meeting in particular sparked the pontifical juices.  It was a rough discussion.  Funny how rejection always makes you think harder than success.&lt;br /&gt;&lt;br /&gt;See, there's a lot of talk right now about student-centered learning, about putting the student in the driver's seat of their education.  The LMS, instead of just dispersing static information, needs to be a springboard to new resources and innovative learning techniques.  Great rhetoric, although I find it interesting that we're talking about totally transforming the nature of the LMS when I've yet to see &lt;a href="http://mfeldstein.com/blackboard-inc-analysis-part-2-financial-performance/trackback/"&gt;even the most successful LMS's&lt;/a&gt; take advantage of basic things like AJAX requests and in-page edits.  But that's another story.  As is the issue of &lt;a href="http://www.academiccommons.org/commons/review/moodle-and-social-constructionism"&gt;moderate vs. extreme constructivism&lt;/a&gt;.  Anyway.&lt;br /&gt;&lt;br /&gt;Web 2.0 services keep showing up, and educators are finally starting to take note (well, some of them anyway) of their potential for learning.  There's a natural push from the innovators to leverage these new technologies in education, and that means including them in the LMS somehow.  Maybe even &lt;span style="font-style: italic;"&gt;replacing&lt;/span&gt; an established feature of the LMS.  That's a big change from how things have worked in the past.  Traditional LMS's are a one-stop shop.  They have their version of a standard list of features, and that's about it.  You can add new functionality with plugins, but replacing say, the discussion board, could only happen by throwing a new link somewhere else in the course structure -- confusing faculty and students in the process.  That leaves you stuck with whatever the LMS offers, there's no chance to search for best of breed on your standard feature set.&lt;br /&gt;&lt;br /&gt;Solution?  The impression I got from yesterday's meeting is that you make the LMS into a mash-up.  It becomes a skeleton that doesn't offer the features itself, it links to other services that offer the features.  Let the teachers decide for themselves.   Taken to the extreme, when the teacher first sets up the course they pick from a drop-down list of discussion boards, group messaging systems, gradebooks, file repositories, content management systems, etc.   The LMS just keeps student data secure and brings all the resources into one place.  That's really just one step up from what the innovators are doing right now -- WordPress for their announcements, MediaWiki for their assignments, and Google Groups for their discussions.  All that plus a single point of entry.&lt;br /&gt;&lt;br /&gt;While I do see the utility of heading in that direction (and also the challenge of integrating with all those services), I think there's a bigger jump involved than a lot of instructional techs are acknowledging.   It's funny, really, because I've described the future of the LMS in almost exactly the same words that I heard yesterday, although I had a slightly different image in mind.  I just don't see the LMS becoming quite that... fleshless.  I'm not sure that's the right functionality to offer to or require of the faculty.&lt;br /&gt;&lt;br /&gt;It's totally awesome to say the LMS should let faculty use WordPress or Blogger or whatever for their announcements, MediaWiki or DocuWiki or whatever for course content, Google Groups or Disqus or whatever for communication, MicroGrade Online or Google Spreadsheets or whatever for their gradebook, YouTube or TeacherTube or iTunesU for their video, etc. But most teachers aren't savvy enough to have&lt;span style="font-style: italic;"&gt; &lt;/span&gt;a preference.  I'd even go so far as to say they don't &lt;span style="font-style: italic;"&gt;want&lt;/span&gt; to have to have a preference.  They don't want to (or don't have time to) go set up accounts at different sites and manage student permissions for every course.  They want to have one option for each feature, they want it to be easy and seamless, and they even want it to look the same as everything else so they don't get confused.  And that's actually not a bad thing.  Most people just want a single tool that does its job without much fuss or fiddle.  It's only the rare power user that wants to tinker.  You do have to give the power users freedom to innovate, though, or you'll get left in the dust by the competition.&lt;br /&gt;&lt;br /&gt;That's why I think an LMS needs to play both fields: they need to offer flexible options for the power users, but also either integrate deeply with or include their own version of all the major components.  Then you can throw in some settings that cover most standard alternatives.  For example, students could use the integrated blog, but the LMS could also allow Blogger and WordPress URLs instead.  A teacher could export their course calendar to Google Calendar -- or maybe the teacher could even import their Google Calendar into the LMS instead.  Or the teacher could just use the standard calendar if they like.  Likewise a teacher could use the included wiki and file system to build up a repository of learning objects, or point to some external content management system that housed their objects.  It shouldn't matter to the LMS which approach they take.  By keeping these sort of approaches in mind, I definitely think it's possible to create a one-stop shop that's also mashable.  It lets the evolution happen more gradually (and realistically) while still letting the innovators keep pushing the front edge.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-style: italic;"&gt;real&lt;/span&gt; trick would be in finding a way to integrate with new services &lt;span style="font-style: italic;"&gt;as they appear&lt;/span&gt; instead of having to wait for the LMS vendor to catch up and recognize the service themselves.  Educational software, though important, doesn't have enough of a commanding presence to motivate new services to integrate with it, so the responsibility will probably stay with the LMS to do the integrating.  Again, that's another story.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-5541392979069278474?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/74n5ZEsp0V4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/5541392979069278474/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=5541392979069278474" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/5541392979069278474?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/5541392979069278474?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/74n5ZEsp0V4/mashable-one-stop-shop.html" title="The Mashable One-Stop Shop" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2008/08/mashable-one-stop-shop.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcBR38yfCp7ImA9WxdUF04.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-8384892501008042311</id><published>2008-08-01T09:39:00.000-07:00</published><updated>2008-08-02T19:20:56.194-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-02T19:20:56.194-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="education" /><category scheme="http://www.blogger.com/atom/ns#" term="LMS" /><category scheme="http://www.blogger.com/atom/ns#" term="Web 2.0" /><category scheme="http://www.blogger.com/atom/ns#" term="eLearning" /><title>The LMS Web 2.0 Scramble</title><content type="html">First off, this post would probably be more accurate talking about &lt;span style="font-style: italic;"&gt;course &lt;/span&gt;management systems than &lt;span style="font-style: italic;"&gt;learning&lt;/span&gt; management systems, but I don't like typing that many words and I just can't bring myself to call it a CMS.  To everyone else in the world a CMS is a &lt;span style="font-style: italic;"&gt;content&lt;/span&gt; management system (like WordPress or drupal), and even though IMS-GLC calls these guys CM's to avoid confusion, I can't bring myself to do the same.&lt;br /&gt;&lt;br /&gt;Anyway, in trying to keep my finger somewhere close enough to catch hints of the pulse of eLearning technology, I've noticed (along with a lot of other people) the shift toward more Web 2.0-like solutions in eLearning.  The need for more interactive solutions &lt;a href="http://imsproject.org/ltst/ltstbc.cfm"&gt;has been discussed in the past&lt;/a&gt;, but only recently are we starting to see LMS companies actually include modern web technologies.&lt;br /&gt;&lt;br /&gt;It's no surprise that the evolution is gradual.  Education software is notoriously slow at adopting new tech (one of the reasons I got into this whole startup thing in the first place, actually), and when they do it's often more reactive than anything.  It's a sad state of affairs when a company can say "look!  We do drag and drop using Javascript" and it's actually a big deal, but that's where we're at.&lt;br /&gt;&lt;br /&gt;Which brings me to my point.  The more "Web 2.0" I see in higher ed software, the more frustrated  I am by how companies are missing the point.  It's all more patch-job and superficial than anything, to the point where it seems like certain slate-associated companies just said "hey, everyone's saying we need to be doing Web 2.0!  Let's throw something together so we can say we're doing that!"  Blech.  Other companies are pulling a similar trick, saying their LMS will offer a new social network ("social network", of course, meaning you can add comments to other people's posts) to help students and teachers interact.  Instead of actually embracing the underlying change to the way we interact, they're just patching on a few buzz-wordy features and calling it good.  There's a lot of room for improvement in LMS's, and I would love for &lt;a href="http://www.jonmott.com/blog/?p=15"&gt;some people to actually sit down and think about what that means&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Very few education people seem to be getting the REAL point of this whole web evolution.  Sure, part of it's Javascript interaction, but that's more the the means than the end.  Part of it is social, and other services have already done a smashing job of that part (as a side note, I'm impressed by &lt;a href="http://mfeldstein.com/sis-to-facebook-direct-introducing-schools-on-facebook/"&gt;Oracle's new tactic&lt;/a&gt;.  They're basically saying "we know your LMS doesn't do social, so we'll take care of that part"), but the other big part is in bringing web pieces together.  That means importing YouTube videos and Flickr pictures -- but it also means posting to Blogger or auto-generating Google docs.  You can't just suck everybody else in or you're still stuck in the silo paradigm (a la "Blackboard will also display your Moodle and Sakai courses"), you have to share, too. &lt;br /&gt;&lt;br /&gt;There are definitely some things that can stay in the LMS (I'm undecided at the moment if those "things" include a social network of sorts), but I think we'll start to see more features outsourced and the &lt;a href="http://www.jonmott.com/blog/?p=22"&gt;LMS turn more into a facilitator&lt;/a&gt; of those outside tools.&lt;br /&gt;&lt;br /&gt;Anyway, this is long enough.  I'll post more later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-8384892501008042311?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/Tmf-MoJozCk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/8384892501008042311/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=8384892501008042311" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8384892501008042311?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8384892501008042311?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/Tmf-MoJozCk/lms-web-20-scramble.html" title="The LMS Web 2.0 Scramble" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2008/08/lms-web-20-scramble.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkABRHoyfCp7ImA9WxdQFUU.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-8471470648235049915</id><published>2008-06-15T20:51:00.000-07:00</published><updated>2008-06-15T20:59:15.494-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-06-15T20:59:15.494-07:00</app:edited><title>Not so smart after all</title><content type="html">So it's really funny, but whenever I get on here and vent about something, not long afterwards I learn why my rant isn't so justified after all.  The day after posting about that CSS quirk, I learned the reason behind it.  A friend of mine sat me down and explained the intricacies of CSS (of which I was surprised that I knew about 2/3 after all) and now it makes more sense to me.  It's not really the BEST behavior for the image to spill outside its div in IE like it does once you set a relative position, but it at least makes sense.  See. when you set the position attribute on an object, it defines the positioning based on its innermost parent that has a defined position attribute.  So if you don't define an outer object with a position, then the outermost object (the body?  or document?  I can't remember which...) will be used.  Hence, the image's positioning won't be based on its container div, and I guess in one sense that means ignoring the div is justified.  Weird, but logical.&lt;br /&gt;&lt;br /&gt;As for app engine, I really do enjoy working on it.  One comment that I caught at Google I/O (and which, in my opinion, should be somewhere in the documentation) is that if you want to use back-references, you should explicitly define the "collection_name" parameter:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;image = db.ReferenceProperty(User, collection_name="user_images")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you don't define it, there's a default name that gets set (modelname_set, or in the example it would be image_set), but for whatever reason this isn't necessarily reliable.  I think he said something to the effect of "funky things" could happen.&lt;br /&gt;&lt;br /&gt;And there you have it.  I stand corrected and educated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-8471470648235049915?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/vqMMJEpkiY8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/8471470648235049915/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=8471470648235049915" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8471470648235049915?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/8471470648235049915?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/vqMMJEpkiY8/not-so-smart-after-all.html" title="Not so smart after all" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2008/06/not-so-smart-after-all.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8BRXk7fSp7ImA9WxdQEUg.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-7928741045749781215</id><published>2008-06-10T20:09:00.000-07:00</published><updated>2008-06-10T20:27:34.705-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-06-10T20:27:34.705-07:00</app:edited><title>Because of IE, I'm mad at CSS</title><content type="html">I never know what to capitalize and what not to.  IE or ie?  CSS or css?  Meh, whatever.&lt;br /&gt;&lt;br /&gt;The brief summary is that when you add a DOCTYPE tag to the html, IE7 won't respect relative position inside a hidden overflow div unless the container div also has relative positioning.&lt;br /&gt;&lt;br /&gt;See, I was racking my brain trying to figure out this stupid ie7 compatibility problem with my css.  I had a div with "overflow: hidden" set to an explicit width and height.  However, I needed to be able to move the content of the div around, so I set the inner content to "position: relative" with an exlicit top and left.  Everything worked great in firefox, but IE7/ie7 was spilling the content outside of the div, like so (check it out in ie7):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;div style="overflow: hidden; border: 1px solid #000;&lt;br /&gt;width: 200px; height: 100px;"&gt;&lt;br /&gt;&amp;lt;img src="http://www.google.com/intl/en_ALL/images/logo.gif" &lt;br /&gt;style="position: relative;"/&gt;&lt;br /&gt;&amp;lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow: hidden; border: 1px solid #000; width: 200px; height: 100px;"&gt;&lt;img src="http://www.google.com/intl/en_ALL/images/logo.gif" style="position: relative;"/&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I tried everything I could think of, but couldn't fix it.  So I did the programmer thing, and started eliminating possibilities.  I'd just delete on possibility at a time until the problem went away.  Turns out it's the DOCTYPE definition at the top of the page:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"&lt;br /&gt;        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As far as I can tell, ALL DOCTYPE definitions result in the problem.  Great.  So that doesn't help me, because I actually do want to adhere to a dtd.  Poop.  I Google around for a while, and can't find anything.  Double-poop.  After a bit more fenagling, I finally find a solution:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;div style="overflow: hidden; border: 1px solid #000;&lt;br /&gt;width: 200px; height: 100px; position: relative;"&gt;&lt;br /&gt;&amp;lt;img src="http://www.google.com/intl/en_ALL/images/logo.gif" &lt;br /&gt;style="position: relative;"/&gt;&lt;br /&gt;&amp;lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow: hidden; border: 1px solid #000; width: 200px; height: 100px; position: relative;"&gt;&lt;img src="http://www.google.com/intl/en_ALL/images/logo.gif" style="position: relative;"/&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The trick is that the container div, for whatever reason, must also be "position: relative".  I wish I could say as a master of css that doing this won't break anything, but I'm no CSS master.  It doesn't affect my code at all, if that makes you feel any better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-7928741045749781215?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/XVlhiRc8LjU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/7928741045749781215/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=7928741045749781215" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/7928741045749781215?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/7928741045749781215?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/XVlhiRc8LjU/because-of-ie-i-hate-css.html" title="Because of IE, I'm mad at CSS" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2008/06/because-of-ie-i-hate-css.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEGQn87eip7ImA9WxdTEU4.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-6621986796239174947</id><published>2008-05-06T21:44:00.000-07:00</published><updated>2008-05-06T22:03:43.102-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-06T22:03:43.102-07:00</app:edited><title>AppEngine back-references and timezones bug</title><content type="html">Ok, I've learned two important lessons in fuddling around with AppEngine today.&lt;br /&gt;&lt;br /&gt;First, there's a bug in the SDK that affects DateTimeProperty and DateProperty objects (since they're all stored in bigtable as datetime.datetime objects, they're really one and the same underneath).  Whenever I would type dates in, they were getting returned to me as the day before.  Extremely frustrating.  &lt;br /&gt;&lt;br /&gt;Turns out it's a bug in the SDK.  The datastore stores all times as UTC times, so it will translate from your local time to UTC to store the data.  Then when it retrieves the date, it should add back in the time zone.  This works perfectly in the live build, but the SDK actually subtracts your time zone &lt;i&gt;twice&lt;/i&gt;, thus effectively messing up your dates and datetimes.  The problem is discussed &lt;a href="http://code.google.com/p/googleappengine/issues/detail?id=131"&gt;here&lt;/a&gt; along with a successful fix.  It involves changing some source code in the appengine folder, but you don't have to recompile or anything.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;I tried a patch to module datastore_types.py, which seems to work:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;change line 1033&lt;br /&gt;from&lt;br /&gt;    lambda val: datetime.datetime.fromtimestamp(float(val) / 1000000.0),&lt;br /&gt;to&lt;br /&gt;    lambda val: datetime.datetime.utcfromtimestamp(float(val) / 1000000.0),&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Per the Python doc, fromtimestamp() converts to the local timezone.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Second, I've been freaking out trying to get some back-referencing to work out.  It's been hard for me to let go of normalized data in the datastore, but I'm warming up to it.  One trick is that I'm overriding the save methods for my models so that they update related models as well.  That way even though the data is in multiple places, it gets synced up on any kind of save.  This is fine and dandy, except sometimes I need to use back-references to make this happen.&lt;br /&gt;&lt;br /&gt;Google says to do this using the &lt;pre&gt;modelname_set&lt;/pre&gt; property on the model instance.  However, you'll get the following TypeError: &lt;pre&gt;'_ReverseReferenceProperty' object is not iterable&lt;/pre&gt; if you try to retrieve back-references on an object that hasn't been saved yet.  There are two ways around this.  You can either first save the object, &lt;pre&gt;super(ObjectType, self).save()&lt;/pre&gt; and then iterate over the back-references, or you can recognize that a new instance won't &lt;i&gt;have&lt;/i&gt; and back-references, and check only update back-references if &lt;pre&gt;self.is_saved()&lt;/pre&gt; is true.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-6621986796239174947?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/U7J_QwWDVA4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/6621986796239174947/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=6621986796239174947" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/6621986796239174947?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/6621986796239174947?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/U7J_QwWDVA4/appengine-back-references-and-timezones.html" title="AppEngine back-references and timezones bug" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2008/05/appengine-back-references-and-timezones.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYFQX8_eip7ImA9WxdbFEU.&quot;"><id>tag:blogger.com,1999:blog-5825798647577501834.post-7989581500369225689</id><published>2008-04-21T20:07:00.000-07:00</published><updated>2008-08-11T13:55:10.142-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-11T13:55:10.142-07:00</app:edited><title>Blackboard v. Desire2Learn</title><content type="html">Okay, so I was learning all this grand stuff that I wasn't finding anywhere else on the net, and I thought to myself, "hey, isn't that what blogs are for?"  So I set this one up.  I've been meaning to for a while, and I just never got around to it.&lt;br /&gt;&lt;br /&gt;Anyway.  For various reasons I've been following the Blackboard v. Desire2Learn case very closely, and actually trying to understand what's been going on.  My latest quest has been to figure out what the Desire2Learn workaround is going to be for their recent legal failure -- but I'm getting ahead of myself.  Here's the skinny:&lt;br /&gt;&lt;br /&gt;Blackboard was granted a &lt;a href="http://www.google.com/patents?id=RX94AAAAEBAJ&amp;amp;dq=6,988,138"&gt;pretty crummy paten&lt;/a&gt;t (I'm not the biggest fan of &lt;a href="http://mfeldstein.com/an_open_letter_to_the_ceo_of_ecollege/trackback/"&gt;software patents&lt;/a&gt; in general) in January of 2006 that basically says only they can create course management software in the U.S.  It's a pretty broad patent, covering things like different roles for different users, online quizzes, digital dropboxes, etc.  Since then (and this part is where I've done the least amount of homework) they've been suing or acquiring everybody else in the market.  Their biggest competitor was WebCT, which is now part of the Blackboard family of products.&lt;br /&gt;&lt;br /&gt;Then recently Canada's Desire2Learn branched out into the U.S. and Blackboard slapped them with a lawsuit (July 26, 2006).  The court proceedings have recently wrapped up, with mixed results.  Blackboard's patent had 44 claims.  Claims 1-35 were invalidated by the court.  Claims 2-35 all build on top of claim 1, and the court ruled that claim 1 was too vague.  Claims 36-38 stuck, and Blackboard apparently didn't bother pursuing claims 39-44.&lt;br /&gt;&lt;br /&gt;Claims 36-38, in case you were wondering, are related to the "digital dropbox" idea.  Basically students can submit their assignments by uploading them to the server, the teacher can download these assignments and enter grades based on how well the students did.  Pretty straightforward idea.&lt;br /&gt;&lt;br /&gt;So Blackboard gained an injunction against Desire2Learn since their product infringes on the patent.  Desire2Lean claimed that they had an easy workaround for the patent problem, and I spent a few weeks trying to figure out what exactly that workaround was.  I couldn't find anything, so I finally caved and read the legal mush.  Now that I know the sticking point is only those three claims, 36-38, it's not hard to conceive of a workaround.  What exactly they did is up for debate, of course, but this whole time I was thinking it was a problem with user roles when that had been shot down from the beginning.  Go figure.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5825798647577501834-7989581500369225689?l=brianwhitmer.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheOtherBrianWhitmer/~4/Ka05uHXa9TA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://brianwhitmer.blogspot.com/feeds/7989581500369225689/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=5825798647577501834&amp;postID=7989581500369225689" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/7989581500369225689?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5825798647577501834/posts/default/7989581500369225689?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheOtherBrianWhitmer/~3/Ka05uHXa9TA/blackboard-v-desire2learn.html" title="Blackboard v. Desire2Learn" /><author><name>Brian Whitmer</name><uri>http://www.blogger.com/profile/00009042638644799674</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://brianwhitmer.blogspot.com/2008/04/blackboard-v-desire2learn.html</feedburner:origLink></entry></feed>

