[S5-discuss] Some S5 patches

Stefan Rank stefan.rank at ofai.at
Tue Oct 3 07:52:14 CDT 2006


Hi there sleepy list,

I recently did a docutils-rst --> S5 presentation,
and wanted to use the most recent version from s5project.org (silly me :)

So attached are some of the changes I made / had to make.
The file uses a darcs changes format.
I tried to separate the changes into meaningful patches, see the 
descriptions below. If applying them is difficult, I can resend a simple 
diff-patch (all mixed in one).

Patches:

   * moving MochiKit into the default skin

     I thought this makes more sense than having a top-level ./lib/ dir.
     (I also think that, for sharing stuff between skins, the shared
      files, such as MochiKit.js should be in default, or at least in
      ./ui/ )

   * missing bg-shade.png

   * small function for opening in a new window

     useful for example in Firefox. put something like:
     <a class="reference" href="javascript:openInUnadornedWindow()">████</a>
     on your first slide, and you can open a new window without toolbar
     or statusbar with a click.

   * always use var

   * missing clear:left's and handout class in notes.css

     this keeps handout material from the slides in the notes window.
     mixed with fixing some layout problems.

   * notes window can be a little bit more compact

     (that's a matter of taste;, but I wanted to see more of the notes)

   * make the times in the notes window line up

   * another useful debugging aid

   * missing thises

     a lot of 'this.' were missing in slides.js.

   * bugs in keys method

     update the onkeyup handler to really use mochikit, et al..

   * slight change to delayed note loading

     busy-waiting forever is not funny, so i simplified the delaying.

   * commenting log message

   * hide currentslide indicator AND footer on first slide

     I think hiding the footer on the first slide was in the original s5

   * update leftclick handling

     ... to use MochiKt events

   * some comment updates

   * arbitrary slideIDs (docutils), special case last slide on notes, 
hide footer on slide0

     this is the biggest patch. it allows arbitrary ids on the
     class="slide" tags, not just the generated "slide1"..."slideN".
     the docutils rst2s5.py generator needs that, because it uses the
     slide title as id. The patch also simplifies some things.
     also: special case bug for the last slide in the notes window.



cheers,
stefan
-------------- next part --------------

New patches:

[moving MochiKit into the default skin
stefan.rank at ofai.at**20061002154230] 
<
> {
move ./lib/MochiKit.js ./ui/default/MochiKit.js
hunk ./index.html 32
   img#me05 {top: 43px;left: 36px;}
 </style>
 <!-- S5 JS -->
-<script src="lib/MochiKit.js" type="text/javascript"></script>
+<script src="ui/default/MochiKit.js" type="text/javascript"></script>
 <script src="ui/default/slides.js" type="text/javascript"></script>
 </head>
 <body>
hunk ./ui/s5-notes.html 8
 <head>
 <title>Notes</title>
 <link rel="stylesheet" href="default/notes.css" type="text/css" />
-<script src="../lib/MochiKit.js" type="text/javascript"></script>
+<script src="default/MochiKit.js" type="text/javascript"></script>
 <script type="text/javascript">
 // <![CDATA[
   connect(document, 'onkeyup', opener.s, 'keys');
}
[missing bg-shade.png
stefan.rank at ofai.at**20061002175704] 
<
> {
addfile ./pix/bg-shade.png
hunk ./index.html 134
 <h1>PNG Alpha Tests</h1>
 <div style="width: 400px; height: 150px; text-align: center; background: url(pix/bg-shade.png)">
 <p>DIV with PNG background followed by foreground PNG</p>
-<img src="ui/bg-shade.png" alt="" title="A translucent image" />
+<img src="pix/bg-shade.png" alt="" title="A translucent image" />
 </div>
 <div style="width: 100%; height: 150px; text-align: center; background: url(pix/bg-shade.png)">
 <p>DIV with PNG background followed by foreground PNG</p>
hunk ./index.html 138
-<img src="ui/bg-shade.png" alt="" title="A translucent image" />
+<img src="pix/bg-shade.png" alt="" title="A translucent image" />
 </div>
 </li>
 
binary ./pix/bg-shade.png
oldhex
*
newhex
*89504e470d0a1a0a0000000d49484452000000c8000000c80806000000ad58ae9e000002194944
*4154789cedd3b111802000c04064171a7be7737516e0d26af13f419a5ceb7ede011ccdaf03e0cf
*0c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120
*100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c1
*20100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02
*c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c
*02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c12010
*0c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120
*100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c1
*20100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02
*c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c
*02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c12010
*0c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120
*100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c120100c02c1
*20100c02c120100c02c120100c02c120100c02c120100c02c1201036b2280293a8679474000000
*0049454e44ae426082
}
[small function for opening in a new window
stefan.rank at ofai.at**20061002182704] 
<
> {
hunk ./ui/default/slides.js 5
 //
 // Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information
 // about all the wonderful and talented contributors to this code!
+
+// StefanRank: a simple function for opening in a new nearly empty window:
+function openInUnadornedWindow() {
+  window.open(window.location, "newPresentationWindow", 'toolbar=no,menubar=no');
+  return void(0);
+}
+
 var undef;
 
 var S5 = function() {
}
[always use var
stefan.rank at ofai.at**20061002184042] 
<
> {
hunk ./ui/default/slides.js 14
 
 var undef;
 
-var S5 = function() {
+S5 = function() {
   this.slides;
   this.slideCSS = '';
   this.snum = 0;
}
[missing clear:left's and handout class in notes.css
stefan.rank at ofai.at**20061003082701] 
<
> {
hunk ./ui/default/notes.css 23
 }
 
 #current-slide {
+  clear:left;
 }
 
 #next-slide {
hunk ./ui/default/notes.css 69
   color:red;
 }
 
-.slide .notes {
+.slide .notes, .slide .handout {
  display:none;
  float:none;
 }
hunk ./ui/default/notes.css 167
 }
 
 div#elapsed {
+  clear: left;
   width: 12.1em;
 }
 
}
[notes window can be a little bit more compact
stefan.rank at ofai.at**20061003082750] 
<
> {
hunk ./ui/default/notes.css 5
 
 body {
   margin: 0;
-  padding: 1.0em;
+  padding: 0.5em;
   background: #333; 
   color: #FFF;
   font: 2em/1.4em 'Lucida Grande', Verdana, sans-serif;
hunk ./ui/default/notes.css 14
 /*slide preview styles*/
 
 .slide {
- font-size:50%;
+ font-size:40%;
  border:1px solid black;
  padding-left:1em;
  float:left;
hunk ./ui/default/notes.css 22
  height:40%;
 }
 
+.slide ul, .slide ol, .slide pre, .slide p, .slide, .slide dl, .slide dt, .slide dd {
+  margin: 0; line-height: 1.9em;
+}
+
 #current-slide {
   clear:left;
 }
hunk ./ui/default/notes.css 44
 #current-notes,
 #next-notes {
   font-size: 0.75em;
-  line-height: 1.4em;
+  line-height: 1.3em;
   text-shadow: 0.1em 0.1em 0.1em #111;
 }
 
hunk ./ui/default/notes.css 90
 
 div.timer h1 {
   text-align: left;
-  font-size: 0.6em;
-  line-height: 1.4em;
+  font-size: 0.4em;
+  line-height: 1.2em;
   background-color: #FF9;
   border: 1px solid #EE8;
 }
hunk ./ui/default/notes.css 97
 
 div.timer div.controls {
-  line-height: 1em;
+  line-height: 0.9em;
 }
 
 div.timer h1 a {
hunk ./ui/default/notes.css 106
 }
 
 div.timer div.controls a {
-  font-size: 0.5em;
+  font-size: 0.4em;
   padding: 0;
   color: #330;
 }
hunk ./ui/default/notes.css 135
 }
 
 div.timer h2 {
-  font-size: 0.6em;
-  line-height: 1.0em;
+  font-size: 0.4em;
+  line-height: 0.8em;
   font-weight: normal;
   margin: 0 0 -0.25em;
hunk ./ui/default/notes.css 139
-  padding-top: 0.5em;
+  padding-top: 0.3em;
   color: #666;
 }
 
}
[make the times in the notes window line up
stefan.rank at ofai.at**20061003083017] 
<
> {
hunk ./ui/s5-notes.html 65
     <h1>
       <a href="#minimize-remaining" id="minimize-remaining" title="Minimize this box">Remaining Time</a>
     </h1>
+    <h2>&nbsp;</h2>
     <p>
       <a href="#subtract-remaining" class="control" id="minus" title="Subtract 5 Minutes">-</a>
       <span class="clock" id="timeLeft">00:00:00</span>
}
[another useful debugging aid
stefan.rank at ofai.at**20061003083105] 
<
> {
hunk ./ui/default/pretty.css 263
 /* diagnostics
 
 li:after {content: " [" attr(class) "]"; color: #F88;}
+div:before {content: "[" attr(class) "]"; color: #F88;}
  */
hunk ./ui/default/pretty.css 265
+
}
[missing thises
stefan.rank at ofai.at**20061003090315] 
<
> {
hunk ./ui/default/slides.js 64
   if (node.nodeType == 1) { //TODO: lookup these node types, eliminate the magic numbers
     var children = node.childNodes;
     for (var i = 0, l = children.length; i < l; i++) {
-      result += nodeValue(children[i]);
+      result += this.nodeValue(children[i]);
     }
   } else if (node.nodeType == 3) {
     result = node.nodeValue;
hunk ./ui/default/slides.js 604
   }
   this.resetElapsedSlide(); // TODO: odd place for these, probably need to be refactored out
   this.resetRemainingTime();
-  window.setInterval('S5.prototype.updateElaspedTime()', 1000);
+  window.setInterval('window.s.updateElaspedTime()', 1000);
 }
 
 S5.prototype.createNotesWindow = function() { 
hunk ./ui/default/slides.js 665
 
 S5.prototype.resetElapsedTime = function() {
   this.presentationStart = new Date();
-  slideStart = new Date();
-  updateElaspedTime();
+  this.slideStart = new Date();
+  this.updateElapsedTime();
 }
 
 S5.prototype.resetElapsedSlide = function() {
hunk ./ui/default/slides.js 689
 S5.prototype.resetRemainingTime = function() {
   if (!this.s5NotesWindowLoaded || !this.s5NotesWindow || this.s5NotesWindow.closed) return;
   var startField = this.s5NotesWindow.document.getElementById('startFrom');
-  var startFrom = readTime(startField.value);
+  var startFrom = this.readTime(startField.value);
   this.countdown.remaining = startFrom * 60000;  // convert to msecs
   this.countdown.start = new Date().valueOf();
   this.countdown.end = this.countdown.start + this.countdown.remaining;
hunk ./ui/default/slides.js 694
   var tl = this.s5NotesWindow.document.getElementById('timeLeft');
-  var timeLeft = this.formatTime(countdown.remaining);
+  var timeLeft = this.formatTime(this.countdown.remaining);
   tl.innerHTML = timeLeft;
 }
 
hunk ./ui/default/slides.js 702
   if (!this.s5NotesWindowLoaded || !this.s5NotesWindow || this.s5NotesWindow.closed) return;
   var tl = this.s5NotesWindow.document.getElementById('timeLeft');
   var now = new Date();
-  if (countdown.state == 'run') {
-    countdown.remaining = countdown.end - now;
+  if (this.countdown.state == 'run') {
+    this.countdown.remaining = this.countdown.end - now;
   }
   tl.style.color = '';
   tl.style.backgroundColor = '';
hunk ./ui/default/slides.js 707
-  if (countdown.remaining >= 0) {
-    var timeLeft = this.formatTime(countdown.remaining);
+  if (this.countdown.remaining >= 0) {
+    var timeLeft = this.formatTime(this.countdown.remaining);
     removeElementClass(tl,'overtime');
hunk ./ui/default/slides.js 710
-    if (countdown.remaining < 300000) {
-      tl.style.color = 'rgb(' + (255-Math.round(countdown.remaining/2000)) + ',0,0)';
-      tl.style.backgroundColor = 'rgb(255,255,' + (Math.round(countdown.remaining/2000)) + ')';
+    if (this.countdown.remaining < 300000) {
+      tl.style.color = 'rgb(' + (255-Math.round(this.countdown.remaining/2000)) + ',0,0)';
+      tl.style.backgroundColor = 'rgb(255,255,' + (Math.round(this.countdown.remaining/2000)) + ')';
     }
   } else {
hunk ./ui/default/slides.js 715
-    var timeLeft = '-' + this.formatTime(-countdown.remaining);
+    var timeLeft = '-' + this.formatTime(-this.countdown.remaining);
     addElementClass(tl,'overtime');
   }
   tl.innerHTML = timeLeft;
hunk ./ui/default/slides.js 722
 }
 
 S5.prototype.toggleRemainingTime = function() {
-  if (countdown.state == 'pause') countdown.state = 'run'; else countdown.state = 'pause';
-  if (countdown.state == 'pause') {
-    window.clearInterval(countdown.timer);
-  }
-  if (countdown.state == 'run') {
-    countdown.start = new Date().valueOf();
-    countdown.end = countdown.start + countdown.remaining;
-    countdown.timer = window.setInterval('updateRemainingTime()', 1000);
+  if (this.countdown.state == 'pause') {
+    this.countdown.state = 'run';
+    this.countdown.start = new Date().valueOf();
+    this.countdown.end = this.countdown.start + this.countdown.remaining;
+    this.countdown.timer = window.setInterval('window.s.updateRemainingTime()', 1000);
+  } else {
+    this.countdown.state = 'pause';
+    window.clearInterval(this.countdown.timer);
   }
 }
 
hunk ./ui/default/slides.js 736
 S5.prototype.alterRemainingTime = function(amt) {
   //takes an integer, `amt` and then updates the remaining time in the other window
   var change = amt * 60000;  // convert to msecs
-  countdown.end += change;
-  countdown.remaining += change;
-  updateRemainingTime();
+  this.countdown.end += change;
+  this.countdown.remaining += change;
+  this.updateRemainingTime();
 }
 
 S5.prototype.formatTime = function(msecs) {
hunk ./ui/default/slides.js 799
   if (!this.isOp) this.notOperaFix();
   this.slideJump();
   if (this.defaultView == 'outline') {
-    toggle();
+    this.toggle();
   }
   connect(document, 'onkeyup', this, 'keys');
   connect(document, 'onkeypress', this, 'trap');
}
[bugs in keys method
stefan.rank at ofai.at**20061003104010] 
<
> {
hunk ./ui/default/slides.js 248
 //TODO: reseach mozpoint
 S5.prototype.keys = function(e) {
   //handles keypresses
-  //TODO: could this be cleaned up?
-  key = e.key()
-  if (!key) {
-    key = event;
-    key.which = key.keyCode;
-  }
-  if (key.which == 84) {
+  var key = e.key(); // MochiKit key event: {code, string}
+  if (key.code == 84) { // 't'
     this.toggle();
     return;
   }
hunk ./ui/default/slides.js 253
-  if(!key.which){
-    key.which = key.code;
-  }
   if (this.s5mode) {
hunk ./ui/default/slides.js 254
-    switch (key.which) {
+    var underControls = false;
+    if ((e.src() && this.isParentOrSelf(e.src(), 'controls')) ||
+        (e.target() && this.isParentOrSelf(e.target(), 'controls'))) {
+        // don't react to certain keys if focus in controls area (jumplist)
+        underControls = true;
+    }
+    switch (key.code) {
       case 10: // return
       case 13: // enter
hunk ./ui/default/slides.js 263
-        if (window.event && this.isParentOrSelf(window.event.srcElement, 'controls')) return;
-        if (key.target && this.isParentOrSelf(key.target, 'controls')) return;
+        if (underControls) return;
         if(this.number != undef) {
           this.goTo(this.number);
           break;
hunk ./ui/default/slides.js 272
       case 34: // page down
       case 39: // rightkey
       case 40: // downkey
+        if (underControls) return;
         if(this.number != undef) {
           this.go(this.number);
         } else if (!this.incrementals[this.snum] || this.incpos >= this.incrementals[this.snum].length) {
hunk ./ui/default/slides.js 284
       case 33: // page up
       case 37: // leftkey
       case 38: // upkey
+        if (underControls) return;
         if(this.number != undef) {
           this.go(-1 * this.number);
         } else if (!this.incrementals[this.snum] || this.incpos <= 0) {
hunk ./ui/default/slides.js 294
         }
         break;
       case 36: // home
+        if (underControls) return;
         this.goTo(0);
         break;
       case 35: // end
hunk ./ui/default/slides.js 298
+        if (underControls) return;
         this.goTo(this.smax - 1);
         break;
       case 67: // c
hunk ./ui/default/slides.js 302
+        if (underControls) return;
         this.showHide('k');
         break;
       case 78: // n
hunk ./ui/default/slides.js 309
         this.createNotesWindow();
         break;
     }
-    if (key.which < 48 || key.which > 57) {
+    if (key.code < 48 || key.code > 57) {
       this.number = undef;
     } else {
hunk ./ui/default/slides.js 312
-      if (window.event && this.isParentOrSelf(window.event.srcElement, 'controls')) return;
-      if (key.target && this.isParentOrSelf(key.target, 'controls')) return;
-      this.number = (((this.number != undef) ? this.number : 0) * 10) + (key.which - 48);
+      if (underControls) return;
+      this.number = (((this.number != undef) ? this.number : 0) * 10) + (key.code - 48);
     }
   }
   return false;
}
[slight change to delayed note loading
stefan.rank at ofai.at**20061003112619] 
<
> {
hunk ./ui/default/slides.js 615
     // Note: Safari has a tendency to ignore window options preferring to default to the settings of the parent window, grr.
     this.s5NotesWindow = window.open('ui/s5-notes.html', 'this.s5NotesWindow', 'top=0,left=0');
   }
-  while(!this.s5NotesWindow || !this.s5NotesWindow.document) {
-    wait(1000);
+  if (this.s5NotesWindowLoaded) { // Load the current note if the Note HTML has loaded
+    this.loadNotes();
+  } else { // DONT Keep trying... (because its annoying, for example, with popup blockers)
+    // just try loading a little bit later. if it fails, it fails.
+    window.setTimeout('window.s.loadNotes()', 500);
   }
hunk ./ui/default/slides.js 621
-  this.loadNotes();
 }
 
 S5.prototype.loadNotes = function() {
}
[commenting log message
stefan.rank at ofai.at**20061003112802] 
<
> {
hunk ./ui/default/slides.js 624
 }
 
 S5.prototype.loadNotes = function() {
-  log(this.snum);
+  //log(this.snum);
   // Loads a note into the note window
   var notes = nextNotes = '<em class="disclaimer">There are no notes for this slide.</em>';
   if ($('note' + this.snum.toString())) {
}
[hide currentslide indicator AND footer on first slide
stefan.rank at ofai.at**20061003113106] 
<
> {
hunk ./ui/default/slides.js 104
 
 S5.prototype.currentSlide = function() {
   //builds the HTML shown on the slide to indicate the current slide
-  var cs = $('currentSlide');
-  cs.innerHTML = '<a id="plink" href="">' + 
-    '<span id="csHere">' + this.snum + '<\/span> ' + 
-    '<span id="csSep">\/<\/span> ' + 
-    '<span id="csTotal">' + (this.smax - 1) + '<\/span>' +
-    '<\/a>'
-    ;
+  var current_slide = $('currentSlide');
+  var footer_nodes = $('footer').childNodes;
+  replaceChildNodes(current_slide,
+    A(
+      {'id':'plink', 'href':''},
+      SPAN({'id':'csHere'}, this.snum)
+      /* don't want a slide total? comment the following 3 lines:
+         TODO: make this a (meta) parameter */
+      ,
+      SPAN({'id':'csSep'},'/'),
+      SPAN({'id':'csTotal'}, this.smax - 1)
+    ));
+  var vis = 'visible';
   if (this.snum == 0) {
hunk ./ui/default/slides.js 118
-    cs.style.visibility = 'hidden';
-  } else {
-    cs.style.visibility = 'visible';
+    vis = 'hidden';
+  }
+  current_slide.style.visibility = vis;
+  for (var i = 0; i < footer_nodes.length; i++) {
+    if (footer_nodes[i].nodeType == 1) {
+      footer_nodes[i].style.visibility = vis;
+    }
   }
 }
 
}
[update leftclick handling
stefan.rank at ofai.at**20061003120153] 
<
> {
hunk ./ui/default/slides.js 332
 S5.prototype.clicker = function(e) {
   //handles mouse clicks
   this.number = undef;
-  var target;
-  //not sure what the point was in the following
-/*  if (window.event) {
-    target = window.event.srcElement;
-    e = window.event;
-  } else {
-    target = e.target;
-  }*/
-  if (e.target().href != null ||
-      this.hasValue(e.target().rel, 'external') ||
-      this.isParentOrSelf(e.target(), 'controls') ||
-      this.isParentOrSelf(e.target(),'embed') ||
-      this.isParentOrSelf(e.target(),'object'))
+  // don't want a mouse click to advance, only to unset a slide number jump?
+  // then uncomment this: (TODO: make this a meta-parameter)
+  //return true;
+  var target = e.target(); // MochiKit event object
+  if (target.href != null ||
+      this.hasValue(target.rel, 'external') ||
+      this.isParentOrSelf(target, 'controls') ||
+      this.isParentOrSelf(target, 'embed') ||
+      this.isParentOrSelf(target, 'object')) {
     return true;
hunk ./ui/default/slides.js 342
-  if (!e.which || e.which == 1) {
+  }
+  if (e.mouse().button.left) {
     if (!this.incrementals[this.snum] || this.incpos >= this.incrementals[this.snum].length) {
       this.go(1);
     } else {
}
[some comment updates
stefan.rank at ofai.at**20061003120653] 
<
> {
hunk ./ui/default/slides.js 239
 }
 
 S5.prototype.showHide = function(action) {
-  //not sure what this is used for, isn't demonstrated in the default slideshow
+  //Shows or hides the controls (bound to pressing 'c').
   var obj = getElementsByTagAndClassName('*','hideme')[0];
   switch (action) {
     case 's': obj.style.visibility = 'visible'; break;
hunk ./ui/default/slides.js 452
   '<a accesskey="x" id="next" href="javascript:s.go(1);">&raquo;<\/a>' +
   '<div id="navList"' + hideList + '><select id="jumplist" onchange="s.go(\'j\');"><\/select><\/div>' +
   '<\/div><\/form>';
+  /* with the following mochikit version the hide events do not work:
+  replaceChildNodes(controlsDiv,
+    FORM({'action':'#', 'id':'controlForm'},
+      DIV({'id':'navLinks'},
+        A({'accesskey':'n', 'id':'show-notes', 'href':'javascript:s.createNotesWindow();', 'title':'Show Notes'}, '\u2261'),
+        A({'accesskey':'t', 'id':'toggle', 'href':'javascript:s.toggle();'}, '\u00d8'),
+        A({'accesskey':'z', 'id':'prev', 'href':'javascript:s.go(-1);'}, '\u00ab'),
+        A({'accesskey':'x', 'id':'next', 'href':'javascript:s.go(1);'}, '\u00bb'),
+        DIV({'id':'navList'},
+          SELECT({'id':'jumplist', 'onchange':'s.go(\'j\');'})
+        )
+      )
+    )
+  );
+  */
+  
   if (this.controlVis == 'hidden') {
     var hidden = $('navLinks');
   } else {
hunk ./ui/default/slides.js 618
   return modifierKey || e.which == 0;
 }
 
+// note that this labelling is currently very very brittle,
+// it allows only one notes child element per slide! --StefanRank
 S5.prototype.noteLabel = function() { 
   // Gives notes id's to match parent slides
   var notes = getElementsByTagAndClassName('div','notes');
}
[arbitrary slideIDs (docutils), special case last slide on notes, hide footer on slide0
stefan.rank at ofai.at**20061003121152] 
<
> {
hunk ./ui/default/slides.js 19
   this.slideCSS = '';
   this.snum = 0;
   this.smax = 1;
+  this.slideIDs = new Array(); /* needed for rst, allows different ids than slideX on slides */
   this.incpos = 0;
   this.number = undef;
   this.s5mode = true;
hunk ./ui/default/slides.js 83
     var obj = slideColl[i];
 
     var did = 'slide' + i.toString();
-    obj.setAttribute('id', did);
+    if (obj.getAttribute('id')) {
+      this.slideIDs[i] = obj.getAttribute('id');
+    } else {
+      obj.setAttribute('id', did);
+      this.slideIDs[i] = did;
+    }
 
     //if (isOp) continue;   // Opera fix (hallvord)
 
hunk ./ui/default/slides.js 139
   //TODO: cleanup and split up
   if ($('slideProj').disabled || step == 0) return;
   var jl = $('jumplist');
-  var cid = 'slide' + this.snum;
-  var ce = $(cid);
+  var current_id = this.slideIDs[this.snum];
+  var current_element = $(current_id);
   if (this.incrementals[this.snum].length > 0) {
     for (var i = 0, l = this.incrementals[this.snum].length; i < l; i++) {
       removeElementClass(this.incrementals[this.snum][i], 'current');
hunk ./ui/default/slides.js 156
     //apparently, 'j' means to look for the value in the jump list.
     this.snum = parseInt(jl.value);
   }
-  var nid = 'slide' + this.snum;
-  var ne = $(nid);
-  if (!ne) {
-    ne = $('slide0');
+  var next_id = this.slideIDs[this.snum];
+  var next_element = $(next_id);
+  if (!next_element) {
+    next_element = $(this.slideIDs[0]);
     this.snum = 0;
   }
   if (step < 0) {
hunk ./ui/default/slides.js 180
     addElementClass(this.incrementals[this.snum][this.incpos - 1], 'current');
   }
   if (this.isOp) { //hallvord
-    location.hash = nid;
+    location.hash = next_id; // why? --StefanRank
   } else {
hunk ./ui/default/slides.js 182
-    ce.style.visibility = 'hidden'; 
-    ne.style.visibility = 'visible';
-    location.hash = nid;
+    current_element.style.visibility = 'hidden'; 
+    next_element.style.visibility = 'visible';
   } // /hallvord
   jl.selectedIndex = this.snum;
   this.currentSlide();
hunk ./ui/default/slides.js 359
 
 S5.prototype.findSlide = function(hash) {
   //finds a slide based on `hash` - not sure of the constrains on `hash`
-  var target = null;
-  for (var i = 0, l = this.slides.length; i < l; i++) {
-    var targetSlide = this.slides[i];
-    //TODO: should we support @name? why?
-    if ((targetSlide.name && targetSlide.name == hash)
-     || (targetSlide.id && targetSlide.id == hash)) {
-      target = targetSlide;
-      break;
-    }
-  }
-  while(target != null && target.nodeName != 'BODY') {
-    if (hasElementClass(target, 'slide')) {
-      return parseInt(target.id.slice(5));
+  var target = $(hash);
+  if (target) {
+    for (var i = 0; i < this.slideIDs.length; i++) {
+      if (target.id == this.slideIDs[i]) return i;
     }
hunk ./ui/default/slides.js 364
-    target = target.parentNode;
   }
   return null;
 }
hunk ./ui/default/slides.js 370
 
 S5.prototype.slideJump = function() {
   //jumps to the slide specified by the fragment identifier in the URL
-  if (window.location.hash == null) return;
+  if (window.location.hash == null || window.location.hash == '') {
+    this.currentSlide(); // hides footer on slide0
+    return;
+  }
   var sregex = /^#slide(\d+)$/;
   var matches = sregex.exec(window.location.hash);
   var dest = null;
hunk ./ui/default/slides.js 394
   var aelements = getElementsByTagAndClassName('a');
   for (var i = 0, l = aelements.length; i < l; i++) {
     var a = aelements[i].href;
-    var slideID = a.match('\#slide[0-9]{1,2}');
+    var slideID = a.match('\#.+');
     if ((slideID) && (slideID[0].slice(0,1) == '#')) { //TODO: put this second part in the regex
       var dest = this.findSlide(slideID[0].slice(1));
       if (dest != null) {
hunk ./ui/default/slides.js 428
 
 S5.prototype.permaLink = function() {
   //sets the permalink for the current slide
-  $('plink').href = window.location.pathname + '#slide' + this.snum.toString();
+  $('plink').href = window.location.pathname + '#' + this.slideIDs[this.snum];
 }
 
 S5.prototype.createControls = function() {
hunk ./ui/default/slides.js 582
 S5.prototype.createIncrementals = function() {
   var incrementals = new Array();
   for (var i = 0; i < this.smax; i++) {
-    incrementals[i] = this.getIncrementals($('slide' + i));
+    incrementals[i] = this.getIncrementals($(this.slideIDs[i]));
   }
   return incrementals;
 }
hunk ./ui/default/slides.js 623
   var notes = getElementsByTagAndClassName('div','notes');
   for (var i = 0; i < notes.length; i++) {
     var note = notes[i];
-    var id = 'note' + note.parentNode.id.substring(5); //assumes that there's no levels between the slide and the notes
-    note.setAttribute('id', id);
+    // assumes that there's no levels between the slide and the notes:
+    var index = findIdentical(this.slideIDs, note.parentNode.id);
+    if (index != -1) {
+      var id = 'note' + index;
+      note.setAttribute('id', id);
+    }
   }
   this.resetElapsedSlide(); // TODO: odd place for these, probably need to be refactored out
   this.resetRemainingTime();
hunk ./ui/default/slides.js 660
   if ($('note' + (this.snum + 1))) {
     nextNotes = $('note' + (this.snum + 1)).innerHTML;
   }
+  var finalfinalSlide = '<em class="disclaimer">There are no more slides beyond this point. Move along, nothing to see here.</em>'
 
   //I've removed the slide titles from the notes (since we now have the entire slides, w/ titles) --ryan
 //  var jl = $('jumplist');
hunk ./ui/default/slides.js 677
   if (this.s5NotesWindow && !this.s5NotesWindow.closed && this.s5NotesWindow.document) {
     this.s5NotesWindow.document.getElementById('current-notes').innerHTML = notes;
     this.s5NotesWindow.document.getElementById('next-notes').innerHTML = nextNotes;
-    this.s5NotesWindow.document.getElementById('current-slide').innerHTML = $('slide' + this.snum).innerHTML
-    this.s5NotesWindow.document.getElementById('next-slide').innerHTML = $('slide' + (this.snum + 1)).innerHTML
+    this.s5NotesWindow.document.getElementById('current-slide').innerHTML = $(this.slideIDs[this.snum]).innerHTML;
+    this.s5NotesWindow.document.getElementById('next-slide').innerHTML = ((this.snum + 1 < this.smax) ? $(this.slideIDs[this.snum + 1]).innerHTML : finalfinalSlide);
   }
   this.resetElapsedSlide();
 }
}

Context:

[initial
stefan.rank at ofai.at**20061002153818] 
Patch bundle hash:
863e09d1b9de67dccac988ddbb6bf531826a9875


More information about the S5-discuss mailing list