erbook 9.0.0 → 9.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,14 +22,14 @@ code: |
22
22
 
23
23
  ##
24
24
  # Transforms this string into a valid URI fragment.
25
- # See http://www.nmt.edu/tcc/help/pubs/xhtml/id-type.html
25
+ # See http://www.w3.org/TR/REC-html40/types.html#type-name
26
26
  #
27
27
  def to_uri_fragment
28
28
  # remove XML tags from the input
29
29
  buf = gsub(/<.*?>/, '')
30
30
 
31
- # The first or only character must be a letter.
32
- buf.insert(0, 'a') unless buf[0,1] =~ /[[:alpha:]]/
31
+ # The first or only character must be a letter or an underscore (_).
32
+ buf.insert(0, 'a') unless buf[0,1] =~ /[[:alpha:]_]/
33
33
 
34
34
  # The remaining characters must be letters, digits, hyphens (-),
35
35
  # underscores (_), colons (:), or periods (.) or Unicode characters
@@ -350,15 +350,15 @@ code: |
350
350
  children.select {|c| c.index_toc? }
351
351
  end
352
352
 
353
- HERE_TEXT = ERBook::PHRASES['Focus this segment']
354
- PREV_TEXT = ERBook::PHRASES['Focus previous segment']
355
- NEXT_TEXT = ERBook::PHRASES['Focus next segment']
356
- LIST_TEXT = ERBook::PHRASES['Return to listing']
353
+ HERE_TEXT = ERBook::PHRASES['Here']
354
+ PREV_TEXT = ERBook::PHRASES['Previous']
355
+ NEXT_TEXT = ERBook::PHRASES['Next']
356
+ LIST_TEXT = ERBook::PHRASES['Contents']
357
357
 
358
- HERE_SIGN = ICON_BY_NAME['nav_here'].to_xhtml(:alt => HERE_TEXT)
359
- PREV_SIGN = ICON_BY_NAME['nav_prev'].to_xhtml(:alt => PREV_TEXT)
360
- NEXT_SIGN = ICON_BY_NAME['nav_next'].to_xhtml(:alt => NEXT_TEXT)
361
- LIST_SIGN = ICON_BY_NAME['nav_list'].to_xhtml(:alt => LIST_TEXT)
358
+ HERE_SIGN = ICON_BY_NAME['nav_here'].to_xhtml(:alt => "[#{HERE_TEXT}]")
359
+ PREV_SIGN = ICON_BY_NAME['nav_prev'].to_xhtml(:alt => "[#{PREV_TEXT}]")
360
+ NEXT_SIGN = ICON_BY_NAME['nav_next'].to_xhtml(:alt => "[#{NEXT_TEXT}]")
361
+ LIST_SIGN = ICON_BY_NAME['nav_list'].to_xhtml(:alt => "[#{LIST_TEXT}]")
362
362
 
363
363
  ##
364
364
  # Calculates a local navigation menu containing links
@@ -428,7 +428,7 @@ code: |
428
428
  # of contents / list of figures that points this node.
429
429
  #
430
430
  def list_frag #:nodoc:
431
- @list_frag ||= "__toc__#{here_frag}".to_uri_fragment
431
+ @list_frag ||= "_contents:#{here_frag}".to_uri_fragment
432
432
  end
433
433
  end
434
434
  end
@@ -526,6 +526,7 @@ nodes:
526
526
 
527
527
  paragraph:
528
528
  <<: *latex
529
+ index: false
529
530
  number: false
530
531
  output: |
531
532
  <%= @node.parent_tabs_begin %>
@@ -777,20 +778,12 @@ output: |
777
778
  }.strip
778
779
  %>
779
780
 
780
- <div id="__loading__">
781
- <%= ERBook::PHRASES['Loading...'] %> <noscript><%=
782
- "<ins>%s</ins> <p>%s</p> %s" % [
783
- ERBook::PHRASES['Failed!'],
784
- ERBook::PHRASES['Please enable JavaScript in your Web browser.'],
785
- text_only_browser_divider
786
- ]
787
- %></noscript>
788
- </div>
781
+ <div id="_loading"></div>
789
782
 
790
- <div id="__body__">
783
+ <div id="_body">
791
784
  %= node.output if node = @nodes_by_type['header_outside_above'].first
792
785
 
793
- <div id="__header__">
786
+ <div id="_header">
794
787
  %= node.output if node = @nodes_by_type['header_inside_above'].first
795
788
 
796
789
  % if header = @nodes_by_type['header'].first
@@ -831,31 +824,31 @@ output: |
831
824
  <div class="tabs">
832
825
  <ul>
833
826
  % if abstract
834
- <li><a href="#__abstract__"><%= ERBook::PHRASES['Abstract'] %></a></li>
827
+ <li><a href="#_abstract"><%= ERBook::PHRASES['Abstract'] %></a></li>
835
828
 
836
- <li><a href="#__doc__"><%= ERBook::PHRASES['Document'] %></a></li>
829
+ <li><a href="#_document"><%= ERBook::PHRASES['Document'] %></a></li>
837
830
 
838
831
  % unless toc.empty?
839
- <li><a href="#__toc__"><%= ERBook::PHRASES['Contents'] %></a></li>
832
+ <li><a href="#_contents"><%= ERBook::PHRASES['Contents'] %></a></li>
840
833
 
841
834
  % if references
842
- <li><a href="#__bib__"><%= ERBook::PHRASES['References'] %></a></li>
835
+ <li><a href="#_references"><%= ERBook::PHRASES['References'] %></a></li>
843
836
 
844
- <li><a href="#__nfo__"><%= ERBook::PHRASES['About'] %></a></li>
837
+ <li><a href="#_about"><%= ERBook::PHRASES['About'] %></a></li>
845
838
  </ul>
846
839
 
847
840
  %= abstract.output if abstract
848
841
 
849
842
  % unless toc.empty?
850
- <div id="__toc__">
843
+ <div id="_contents">
851
844
  <h1 class="title"><%= ERBook::PHRASES['Contents'] %></h1>
852
845
  <ul><%= toc %></ul>
853
846
 
854
847
  % unless lof.empty?
855
- <div id="__lof__"><%= lof %></div>
848
+ <div id="_floats"><%= lof %></div>
856
849
  </div>
857
850
 
858
- <div id="__doc__" class="tabs">
851
+ <div id="_document" class="tabs">
859
852
  <h1 style="display: none"><%= ERBook::PHRASES['Document'] %></h1>
860
853
  <ul>
861
854
  % @roots.select {|n| n.index_toc? }.each do |n|
@@ -866,7 +859,7 @@ output: |
866
859
  </div>
867
860
 
868
861
  % if references
869
- <div id="__bib__">
862
+ <div id="_references">
870
863
  <h1 class="title"><%= ERBook::PHRASES['References'] %></h1>
871
864
  <ol>
872
865
  % references.each do |n|
@@ -876,7 +869,7 @@ output: |
876
869
 
877
870
  %= text_only_browser_divider
878
871
 
879
- <div id="__nfo__">
872
+ <div id="_about">
880
873
  <p><%=
881
874
  ERBook::PHRASES[
882
875
  'This document was generated by %s on %s using the following resources.',
@@ -941,7 +934,7 @@ output: |
941
934
 
942
935
  %= node.output if node = @nodes_by_type['footer_outside_above'].first
943
936
 
944
- <div id="__footer__">
937
+ <div id="_footer">
945
938
  %= node.output if node = @nodes_by_type['footer_inside_above'].first
946
939
 
947
940
  % if footer = @nodes_by_type['footer'].first
@@ -958,26 +951,33 @@ output: |
958
951
 
959
952
  javascript: |
960
953
  $(function() {
961
- /*
962
- %< File.join(ERBook::INSTALL, 'LICENSE')
963
- */
954
+ /*<%= File.read File.join(ERBook::INSTALL, 'LICENSE') %>*/
955
+ "use strict";
956
+
957
+ //--------------------------------------------------------------------------
958
+ // utility logic
959
+ //--------------------------------------------------------------------------
964
960
 
965
961
  //
966
- // respond to changes in window location
962
+ // Returns the tab corresponding to the
963
+ // given panel in the given tabs widget.
967
964
  //
968
- var $last_hash = null;
969
-
970
- function on_hash_change() {
971
- var curr_hash = window.location.hash;
972
-
973
- if (curr_hash && curr_hash != $last_hash) {
974
- $last_hash = curr_hash;
975
- reveal_hash(curr_hash);
965
+ function tab_by_panel(panel, tabs_widget) {
966
+ if (!tabs_widget) {
967
+ tabs_widget = panel.parent('.ui-tabs');
976
968
  }
977
969
 
978
- setTimeout(on_hash_change, 300);
970
+ return tabs_widget.find(
971
+ '.ui-tabs-nav > li > a[href=#'+ panel.attr('id') +']'
972
+ ).parent('li');
979
973
  }
980
974
 
975
+ //--------------------------------------------------------------------------
976
+ // document location
977
+ //--------------------------------------------------------------------------
978
+
979
+ var $last_hash;
980
+
981
981
  //
982
982
  // Sets the location bar hash to the given value.
983
983
  //
@@ -986,14 +986,12 @@ javascript: |
986
986
  // the element corresponding to the given hash.
987
987
  //
988
988
  function set_hash(hash, prevent_jump) {
989
- if ($last_hash == hash) {
989
+ if (hash === $last_hash) {
990
990
  return;
991
991
  }
992
992
 
993
- var set_the_hash = function() {
994
- //
993
+ function set_the_hash() {
995
994
  // XXX: bypass on_hash_change() by setting $last_hash
996
- //
997
995
  window.location.hash = $last_hash = hash;
998
996
  }
999
997
 
@@ -1026,7 +1024,7 @@ javascript: |
1026
1024
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1027
1025
  // THE SOFTWARE.
1028
1026
  //
1029
- // This plugin is documented at:
1027
+ // The jQuery.LocalScroll plugin is documented at:
1030
1028
  //
1031
1029
  // http://flesler.blogspot.com/2007/10/jquerylocalscroll-10.html
1032
1030
  //
@@ -1034,12 +1032,11 @@ javascript: |
1034
1032
  //
1035
1033
  // http://flesler-plugins.googlecode.com/svn/trunk/jquery.localScroll/jquery.localScroll.js
1036
1034
  //
1035
+
1037
1036
  var target_id = target.attr('id');
1038
1037
 
1039
- //
1040
1038
  // temporarily place a dummy element at the current
1041
1039
  // screen position and give it the ID of the target
1042
- //
1043
1040
  var original_screen_position = $(window).scrollTop();
1044
1041
 
1045
1042
  var dummy = $('<span/>').attr('id', target_id).css({
@@ -1049,23 +1046,17 @@ javascript: |
1049
1046
 
1050
1047
  target.removeAttr('id').before(dummy);
1051
1048
 
1052
- //
1053
1049
  // when we set the hash, the browser will jump to the
1054
1050
  // dummy, which is where the browser screen currently
1055
1051
  // is, and therefore the jump will not be visualized!
1056
- //
1057
1052
  set_the_hash();
1058
1053
 
1059
- //
1060
1054
  // undo the temporary changes
1061
- //
1062
1055
  dummy.remove();
1063
1056
  target.attr('id', target_id);
1064
1057
 
1065
- //
1066
1058
  // the above approach does not work for Opera and IE.
1067
1059
  // they ignore the dummy and jump to the actual target
1068
- //
1069
1060
  $(window).scrollTop(original_screen_position);
1070
1061
 
1071
1062
  return;
@@ -1075,35 +1066,19 @@ javascript: |
1075
1066
  set_the_hash();
1076
1067
  }
1077
1068
 
1078
- //
1079
- // Returns the tab corresponding to the
1080
- // given panel in the given tabs widget.
1081
- //
1082
- function tab_by_panel(panel, tabs_widget) {
1083
- if (!tabs_widget) {
1084
- tabs_widget = panel.parent('.ui-tabs');
1085
- }
1086
-
1087
- return tabs_widget.find(
1088
- '.ui-tabs-nav > li > a[href=#'+ panel.attr('id') +']'
1089
- ).parent('li');
1090
- }
1091
-
1092
1069
  //
1093
1070
  // Reveals the element at the given hash by (1) activating all
1094
1071
  // tabs that contain it, (2) smoothly scrolling to it, and (3)
1095
1072
  // updating the hash in the browser's location bar accordingly.
1096
1073
  //
1097
- function reveal_hash(hash) {
1098
- var target = $(hash);
1074
+ function reveal(hash_or_elem, callback) {
1075
+ var target = $(hash_or_elem);
1099
1076
 
1100
1077
  if (target.length) {
1101
1078
  var target_is_panel = target.is('div') &&
1102
1079
  target.parent('.ui-tabs').length;
1103
1080
 
1104
- //
1105
1081
  // reveal all tabs which contain the target
1106
- //
1107
1082
  if (target.is(':hidden')) {
1108
1083
  var panels = target.parents('.ui-tabs > div:hidden').get().reverse();
1109
1084
 
@@ -1111,28 +1086,30 @@ javascript: |
1111
1086
  panels.push(target);
1112
1087
  }
1113
1088
 
1114
- for (var i in panels) {
1115
- var panel = $(panels[i]);
1089
+ $(panels).each(function() {
1090
+ var panel = $(this);
1116
1091
  var tabs_widget = panel.parent('.ui-tabs');
1117
1092
  var selected_index = tabs_widget.tabs('option', 'selected');
1118
1093
 
1119
- //
1120
1094
  // map the panel to its tab because tabs do not
1121
1095
  // have to be in the same order as their panels
1122
- //
1123
1096
  var tab = tab_by_panel(panel, tabs_widget);
1124
1097
  var wanted_index = tab.prevAll('li').length;
1125
1098
 
1126
- if (wanted_index != selected_index) {
1099
+ if (wanted_index !== selected_index) {
1127
1100
  tabs_widget.tabs('select', wanted_index);
1128
1101
  }
1129
- }
1102
+ });
1103
+ }
1104
+
1105
+ // scroll to nearest visible element if the target
1106
+ // is naturally hidden (e.g. because of a CSS rule)
1107
+ if (target.is(':hidden')) {
1108
+ target = target.closest(':not(:hidden)');
1130
1109
  }
1131
1110
 
1132
- //
1133
1111
  // scroll to the tab bar instead of the target
1134
1112
  // because it contains the title for the target
1135
- //
1136
1113
  var scroll_target = target;
1137
1114
 
1138
1115
  if (target_is_panel) {
@@ -1143,73 +1120,251 @@ javascript: |
1143
1120
  }
1144
1121
  }
1145
1122
 
1146
- var scroll_offset = scroll_target.offset().top;
1123
+ var scroll_offset = Math.floor(scroll_target.offset().top);
1147
1124
 
1148
- //
1149
1125
  // set body height so that any element can be
1150
1126
  // brought to the top of the screen via scrolling
1151
- //
1152
1127
  var document_height = $(document).height();
1153
1128
  var window_height = $(window).height();
1154
1129
  if (document_height - scroll_offset <= window_height) {
1155
1130
  $('body').css('min-height', document_height + window_height);
1156
1131
  }
1157
1132
 
1133
+ var pending = true;
1158
1134
  $('html, body').animate(
1159
1135
  { scrollTop: scroll_offset }, 'slow', 'swing', function() {
1160
- set_hash(hash, target_is_panel);
1136
+ // prevent the body of this function from being
1137
+ // executed twice -- because there are 2 target
1138
+ // elements in the animation list and only one
1139
+ // of them actually works in different browsers!
1140
+ if (pending && scroll_offset === $(window).scrollTop()) {
1141
+ pending = false;
1142
+
1143
+ var target_id = target.attr('id');
1144
+ set_hash('#' + (target_id || '_reveal' + Math.random()),
1145
+ target_is_panel || !target_id);
1146
+
1147
+ if (callback && typeof(callback) === 'function') {
1148
+ callback();
1149
+ }
1150
+ }
1161
1151
  }
1162
1152
  );
1163
1153
  }
1164
1154
  }
1165
1155
 
1166
- //
1167
- // create jQuery UI tabs
1168
- //
1169
- $('.tabs').tabs();
1156
+ //--------------------------------------------------------------------------
1157
+ // search engine
1158
+ //--------------------------------------------------------------------------
1159
+
1160
+ // Adapted from the source code of the ":contains" selector from
1161
+ // the "Search on this Page" plugin by Waldek Mastykarz
1162
+ // <http://blog.mastykarz.nl>, which was (1) published online on
1163
+ // 17 November 2008 at <http://www.endusersharepoint.com/?p=951>
1164
+ // and <http://blog.mastykarz.nl/search-page-jquery/>, and was
1165
+ // (2) updated to work with jQuery 1.3 by "anonymous" here:
1166
+ // <http://stackoverflow.com/questions/187537>.
1167
+ jQuery.expr[':'].matches = function(a, i, m) {
1168
+ // compile the regexp during the first call to this
1169
+ // function only, so that subsequent calls are fast
1170
+ if (typeof(m[3]) === 'string') {
1171
+ m[3] = new RegExp(m[3], 'i');
1172
+ }
1173
+ return jQuery(a).text().match(m[3]);
1174
+ };
1175
+
1176
+ $('.tabs:first > ul').append(
1177
+ $('<li/>').append(
1178
+ $('<a/>').attr('href', '#_search').
1179
+ text(<%= ERBook::PHRASES['Search'].inspect %>)
1180
+ )
1181
+ ).after(
1182
+ $('<div/>').attr('id', '_search').append(
1183
+ $('<form/>').append(
1184
+ $('<input/>').attr('type', 'text').attr('name', 'q')
1185
+ ).append(
1186
+ $('<input/>').attr('type', 'submit').
1187
+ val(<%= ERBook::PHRASES['Search'].inspect %>).
1188
+ css({'margin-left': '0.125em', 'margin-right': '1em'})
1189
+ ).append(
1190
+ $('<a/>').attr('href',
1191
+ 'https://developer.mozilla.org/En/Core_JavaScript_1.5_Guide:Regular_Expressions#Using_Special_Characters'
1192
+ ).text(<%= ERBook::PHRASES['Help'].inspect %>)
1193
+ ).append(
1194
+ $('<p/>').addClass('status')
1195
+ ).submit(function(event) {
1196
+ event.preventDefault();
1197
+
1198
+ var form = $(this);
1199
+ var query = form.find(':text').val().replace(/^\s+|\s+$/g, '');
1200
+ var status = form.find('.status');
1201
+ var results = form.next();
1202
+
1203
+ if (/\S/.test(query)) {
1204
+ results.text(''); // clear previous results
1205
+ status.text(<%= ERBook::PHRASES['Searching...'].inspect %>);
1206
+
1207
+ // timeout allows the status.text() to appear
1208
+ setTimeout(function() {
1209
+ var num_results = 0;
1210
+
1211
+ function emit_result(match) {
1212
+ // exclude matches from previous search results,
1213
+ // the table of contents, and jQuery UI tab bars
1214
+ if (match.closest('#_search, #_contents, .ui-tabs-nav').length) {
1215
+ return;
1216
+ }
1217
+
1218
+ var excerpt;
1219
+
1220
+ // resolve tab panels into their section title
1221
+ // because additional matches, which lie within
1222
+ // the content of these tab panels, will come
1223
+ if (match.is('.ui-tabs-panel')) {
1224
+ excerpt = match.find('.title:first').clone().show();
1225
+ }
1226
+ else {
1227
+ excerpt = match.clone();
1228
+ }
1229
+
1230
+ // highlight the query inside the match excerpt
1231
+ excerpt.html(excerpt.html().replace(
1232
+ new RegExp('(<[^>]*)?(' + query + ')', 'ig'),
1233
+ function($0, $1, $2) {
1234
+ // only highlight if not inside an XML tag literal
1235
+ return $1 ? $0 :
1236
+ '<span class="ui-state-error">' + $2 + '</span>';
1237
+ }
1238
+ ));
1239
+
1240
+ num_results += 1;
1241
+ var result = $('<li/>').addClass('result').append(
1242
+ $('<blockquote/>').addClass('excerpt').append(excerpt)
1243
+ ).attr('id', '_search' + num_results).click(
1244
+ function(event) {
1245
+ event.stopPropagation();
1246
+
1247
+ // save this search result's hash in browser history
1248
+ // before revealing the matching element so that
1249
+ // the user can press the back button to return to
1250
+ // this exact spot in the search results listing
1251
+ reveal(this, function() {
1252
+ if (!$(event.target).is('a')) {
1253
+ reveal(match);
1254
+ }
1255
+ });
1256
+ }
1257
+ );
1258
+
1259
+ // show bread-crumb trail for the match
1260
+ var first = true;
1261
+ match.parents('.ui-tabs-panel').each(function() {
1262
+ var panel = $(this);
1263
+ var tab = tab_by_panel(panel);
1264
+
1265
+ if (tab.length) {
1266
+ if (!first) {
1267
+ result.prepend(' &rang; ');
1268
+ }
1269
+ first = false;
1270
+
1271
+ result.prepend(tab.find('a').clone());
1272
+ }
1273
+ });
1170
1274
 
1171
- //
1172
- // make internal hyperlinks reveal their targets when clicked
1173
- //
1174
- $('a[href^=#]').click(function() {
1175
- var link = $(this);
1176
- var hash = link.attr('href');
1275
+ results.append(result);
1276
+
1277
+ // unhide any hidden elements in the search result
1278
+ result.find(':hidden').removeClass('ui-tabs-hide').show();
1279
+
1280
+ // remove tab bars (used for titles) and mini navigation menus
1281
+ result.find('.ui-tabs-nav, .ui-tabs-panel > .nav').remove();
1282
+ };
1283
+
1284
+ var matching_elems = $('#_body').
1285
+ find(':matches("'+ query.replace(/"/, '\\"') +'")');
1286
+
1287
+ var prev_match;
1288
+ var prev_elem;
1289
+
1290
+ function process_match(i, n) {
1291
+ status.text(status.text().
1292
+ replace(/( \d+%)?$/, ' ' + Math.round(i / n * 100) + '%'));
1293
+
1294
+ var elem = matching_elems.eq(i);
1295
+
1296
+ // ascend to a larger container for more context
1297
+ var match = elem.closest('pre,ul,ol,dl,table,p,div');
1298
+ if (!match.length) {
1299
+ match = elem;
1300
+ }
1301
+
1302
+ if (
1303
+ prev_match && prev_match.length &&
1304
+ match.get(0) !== prev_match.get(0) && // unique matches only
1305
+ elem.parent().get(0) !== prev_elem.get(0) // leaf nodes only
1306
+ ) {
1307
+ emit_result(prev_match);
1308
+ }
1309
+
1310
+ prev_elem = elem;
1311
+ prev_match = match;
1312
+
1313
+ if (i < n) {
1314
+ setTimeout(function() {
1315
+ process_match(i + 1, n);
1316
+ }, 0);
1317
+ }
1318
+ else {
1319
+ // handle the last item in this two-stage prev/curr loop
1320
+ if (prev_match && prev_match.length) {
1321
+ emit_result(prev_match);
1322
+ }
1323
+
1324
+ if (num_results > 0) {
1325
+ status.text(<%= ERBook::PHRASES['%d matches', 0].inspect %>.replace('0', num_results));
1326
+ }
1327
+ else {
1328
+ status.html(<%= ERBook::PHRASES['Not found'].inspect %>);
1329
+ }
1330
+ }
1331
+ }
1177
1332
 
1178
- if (link.parent('li').parent('.ui-tabs-nav').length) {
1179
- // tab clicks should not cause the screen to scroll
1180
- set_hash(hash, true);
1181
- }
1182
- else {
1183
- reveal_hash(hash);
1184
- }
1333
+ process_match(0, matching_elems.length);
1185
1334
 
1186
- return false;
1187
- });
1335
+ }, 0);
1336
+ }
1188
1337
 
1189
- //
1190
- // checkbox for printer friendly stylesheet
1191
- //
1192
- $('#__header__ > .authors_and_date').append(
1338
+ return false;
1339
+ })
1340
+ ).append(
1341
+ $('<ol/>').addClass('results')
1342
+ )
1343
+ );
1344
+
1345
+ //--------------------------------------------------------------------------
1346
+ // create print preview toggle
1347
+ //--------------------------------------------------------------------------
1348
+
1349
+ $('#_header > .authors_and_date').append(
1193
1350
  $('<span/>').addClass('printer_friendly_toggle').append(
1194
- $('<input/>').attr('type', 'checkbox').click(function() {
1351
+ $('<input/>').attr('type', 'checkbox').
1352
+ attr('id', 'printer_friendly_toggle').click(function() {
1195
1353
  var checkbox = $(this);
1196
1354
 
1197
1355
  function change_media(src, dst) {
1198
1356
  var styles = $('style[media="'+ src +'"]');
1199
1357
  if (styles.length) {
1200
- //
1201
1358
  // try changing the media in-place
1202
- //
1203
1359
  var before = checkbox.offset();
1204
1360
  styles.attr('media', dst);
1205
1361
  var after = checkbox.offset();
1206
1362
 
1207
- if (after.top == before.top && after.left == before.left) {
1208
- //
1363
+ // but if that did not work
1364
+ if (after.top === before.top && after.left === before.left) {
1209
1365
  // try reinserting the <style> into document.
1210
1366
  // this works in Webkit browsers, which ignore
1211
1367
  // the in-place changing approach tried above.
1212
- //
1213
1368
  styles.each(function() {
1214
1369
  var style = $(this);
1215
1370
  var parent = style.parent();
@@ -1232,12 +1387,16 @@ javascript: |
1232
1387
 
1233
1388
  return true;
1234
1389
  })
1235
- ).append(" <%= ERBook::PHRASES['Printer friendly'] %>")
1390
+ ).append(
1391
+ $('<label/>').attr('for', 'printer_friendly_toggle').
1392
+ text(<%= ERBook::PHRASES['Printer friendly'].inspect %>)
1393
+ )
1236
1394
  );
1237
1395
 
1238
- //
1239
- // activate embedded data URIs
1240
- //
1396
+ //--------------------------------------------------------------------------
1397
+ // activate base64 data URIs
1398
+ //--------------------------------------------------------------------------
1399
+
1241
1400
  var data_uri_by_embed_uri = <%=
1242
1401
  result = {}
1243
1402
  ICONS.each do |icon|
@@ -1250,10 +1409,10 @@ javascript: |
1250
1409
 
1251
1410
  $('img[src]').each(function() {
1252
1411
  var image = $(this);
1253
- var data_uri = data_uri_by_embed_uri[image.attr('src')];
1412
+ var embed_uri = image.attr('src');
1254
1413
 
1255
- if (data_uri) {
1256
- image.attr('src', data_uri);
1414
+ if (data_uri_by_embed_uri.hasOwnProperty(embed_uri)) {
1415
+ image.attr('src', data_uri_by_embed_uri[embed_uri]);
1257
1416
  }
1258
1417
  });
1259
1418
 
@@ -1263,23 +1422,65 @@ javascript: |
1263
1422
 
1264
1423
  if (css) {
1265
1424
  for (var embed_uri in data_uri_by_embed_uri) {
1266
- var src = new RegExp('\\burl\\(' + embed_uri + '\\)', 'g');
1267
- var dst = 'url("' + data_uri_by_embed_uri[embed_uri] + '")';
1425
+ if (data_uri_by_embed_uri.hasOwnProperty(embed_uri)) {
1426
+ var src = new RegExp('\\burl\\(' + embed_uri + '\\)', 'g');
1427
+ var dst = 'url("' + data_uri_by_embed_uri[embed_uri] + '")';
1268
1428
 
1269
- css = css.replace(src, dst);
1429
+ css = css.replace(src, dst);
1430
+ }
1270
1431
  }
1271
1432
 
1272
1433
  style.text(css);
1273
1434
  }
1274
1435
  });
1275
1436
 
1276
- //
1277
- // ready for action!
1278
- //
1279
- $('#__loading__').append("<%= ERBook::PHRASES['Ready!'] %>").
1437
+ //--------------------------------------------------------------------------
1438
+ // create jQuery UI tabs
1439
+ //--------------------------------------------------------------------------
1440
+
1441
+ $('.tabs').tabs();
1442
+
1443
+ // make internal hyperlinks reveal their targets (which may be
1444
+ // nested within many levels of jQuery UI tabs) when clicked
1445
+ $('a[href^=#]').click(function() {
1446
+ var link = $(this);
1447
+ var hash = link.attr('href');
1448
+
1449
+ if (link.parent('li').parent('.ui-tabs-nav').length) {
1450
+ // tab clicks should not cause the screen to scroll
1451
+ set_hash(hash, true);
1452
+ }
1453
+ else {
1454
+ reveal(hash);
1455
+ }
1456
+
1457
+ return false;
1458
+ });
1459
+
1460
+ // make external hyperlinks open in a separate window
1461
+ $('a[href]').not('[href^=#]').attr('target', '_blank');
1462
+
1463
+ //--------------------------------------------------------------------------
1464
+ // unveil the document
1465
+ //--------------------------------------------------------------------------
1466
+
1467
+ $('#_loading').append(<%= ERBook::PHRASES['Ready!'].inspect %>).
1280
1468
  fadeOut('slow', function() {
1281
- $('#__body__').show();
1282
- on_hash_change();
1469
+ $(this).remove();
1470
+
1471
+ $('#_body').show();
1472
+
1473
+ // respond to changes in window location
1474
+ (function on_hash_change() {
1475
+ var current_hash = window.location.hash;
1476
+
1477
+ if (current_hash && current_hash !== $last_hash) {
1478
+ $last_hash = current_hash;
1479
+ reveal(current_hash);
1480
+ }
1481
+
1482
+ setTimeout(on_hash_change, 300);
1483
+ })();
1283
1484
  });
1284
1485
  });
1285
1486
 
@@ -1349,12 +1550,12 @@ styles: # these are SASS templates
1349
1550
  font-family: <%= @format['fonts']['serif'] %>
1350
1551
 
1351
1552
 
1352
- #__lof__
1553
+ #_floats
1353
1554
  h1, h2, h3, h4, h5, h6
1354
1555
  margin-top: 1.25em
1355
1556
 
1356
1557
 
1357
- #__doc__
1558
+ #_document
1358
1559
  h1, h2, h3, h4, h5, h6
1359
1560
  margin-top: 2.5em
1360
1561
  line-height: 1.25em
@@ -1398,25 +1599,28 @@ styles: # these are SASS templates
1398
1599
  background-color: #F5F5F5
1399
1600
 
1400
1601
 
1401
- #__header__ > .title
1602
+ #_header > .title
1402
1603
  font-size: 2.25em
1403
1604
 
1404
1605
 
1405
1606
  @media print
1406
- #__header__ .printer_friendly_toggle
1607
+ #_header .printer_friendly_toggle
1407
1608
  display: none
1408
1609
 
1409
1610
 
1410
1611
  @media screen
1411
- #__header__ .printer_friendly_toggle
1612
+ #_header .printer_friendly_toggle
1412
1613
  display: inline
1413
1614
 
1615
+ label:hover
1616
+ cursor: pointer
1617
+
1414
1618
 
1415
- #__abstract__
1619
+ #_abstract
1416
1620
  margin-bottom: 5em
1417
1621
 
1418
1622
 
1419
- #__toc__
1623
+ #_contents
1420
1624
  ul > li
1421
1625
  list-style-type: none
1422
1626
 
@@ -1427,7 +1631,7 @@ styles: # these are SASS templates
1427
1631
  padding-left: 1em
1428
1632
 
1429
1633
 
1430
- #__footer__
1634
+ #_footer
1431
1635
  padding-top: 1em
1432
1636
  text-align: center
1433
1637
  margin: auto
@@ -1447,6 +1651,10 @@ styles: # these are SASS templates
1447
1651
  margin-top: 2em
1448
1652
 
1449
1653
 
1654
+ .paragraph > .content
1655
+ margin: 1em
1656
+
1657
+
1450
1658
  .tip, .note, .caution, .warning, .important, .figure, .table, .example, .equation, .procedure
1451
1659
  margin: 3em
1452
1660
 
@@ -1485,7 +1693,10 @@ styles: # these are SASS templates
1485
1693
  background-color: #FFFFFF
1486
1694
 
1487
1695
 
1488
- #__body__, #__abstract__ > .title, #__toc__ > .title, .part > .title, .chapter > .title, .section > .title, .paragraph > .title, #__bib__ > .title
1696
+ #_loading:before
1697
+ content: <%= ERBook::PHRASES['Loading...'].inspect %>
1698
+
1699
+ #_body, #_abstract > .title, #_contents > .title, .part > .title, .chapter > .title, .section > .title, #_references > .title
1489
1700
  display: none
1490
1701
 
1491
1702
 
@@ -1560,7 +1771,7 @@ styles: # these are SASS templates
1560
1771
  padding-right: 13px
1561
1772
 
1562
1773
 
1563
- #__header__ >
1774
+ #_header >
1564
1775
  .logo
1565
1776
  text-align: center
1566
1777
 
@@ -1584,7 +1795,7 @@ styles: # these are SASS templates
1584
1795
 
1585
1796
  // visually indicate the current location in
1586
1797
  // the hierarchy as the cursor hovers about
1587
- #__toc__
1798
+ #_contents
1588
1799
  li ul
1589
1800
  border-left: thick solid #F5F5F5
1590
1801
 
@@ -1592,7 +1803,7 @@ styles: # these are SASS templates
1592
1803
  border-color: #DCDCDC
1593
1804
 
1594
1805
 
1595
- #__toc__ a:target, #__lof__ a:target
1806
+ #_contents a:target, #_floats a:target
1596
1807
  background: <%= ICON_BY_NAME['here_frag'].data_css %>
1597
1808
  background-position: center right
1598
1809
  background-repeat: no-repeat
@@ -1619,10 +1830,23 @@ styles: # these are SASS templates
1619
1830
  margin-right: 9em
1620
1831
 
1621
1832
 
1622
- #__nfo__ > table td:first-child, #__nfo__ > .validations
1833
+ #_about > table td:first-child, #_about > .validations
1623
1834
  text-align: center
1624
1835
 
1625
1836
 
1837
+ #_search
1838
+ > form
1839
+ text-align: center
1840
+
1841
+ > .results > .result > .excerpt:hover
1842
+ background-color: #FFFFE0
1843
+ cursor: pointer
1844
+
1845
+ // show same cursor on contained elements
1846
+ *
1847
+ cursor: pointer
1848
+
1849
+
1626
1850
  - print: |
1627
1851
  body
1628
1852
  font-family: <%= @format['fonts']['serif'] %>
@@ -1681,36 +1905,36 @@ styles: # these are SASS templates
1681
1905
  font-size: smaller
1682
1906
 
1683
1907
 
1684
- .tabs > ul, .nav, #__lof__, #__nfo__
1908
+ .tabs > ul, .nav, #_floats, #_about, #_search
1685
1909
  display: none
1686
1910
 
1687
1911
 
1688
- #__toc__, .part, .chapter, #__bib__
1912
+ #_contents, .part, .chapter, #_references
1689
1913
  page-break-before: always
1690
1914
 
1691
1915
 
1692
- #__header__, #__footer__
1916
+ #_header, #_footer
1693
1917
  text-align: center
1694
1918
 
1695
1919
 
1696
- #__header__ > .authors_and_date > .authors
1920
+ #_header > .authors_and_date > .authors
1697
1921
  margin-top: 1.625em
1698
1922
  margin-bottom: -0.25em
1699
1923
 
1700
1924
 
1701
- .header_outside_above, #__header__, .header_outside_below, .logo
1925
+ .header_outside_above, #_header, .header_outside_below, .logo
1702
1926
  margin-bottom: 5em
1703
1927
 
1704
1928
 
1705
- .footer_outside_above, #__footer__, .footer_outside_below, #__bib__, #__nfo__
1929
+ .footer_outside_above, #_footer, .footer_outside_below, #_references, #_about
1706
1930
  margin-top: 5em
1707
1931
 
1708
1932
 
1709
- #__header__ .header_inside_above, #__footer__ .footer_inside_above
1933
+ #_header .header_inside_above, #_footer .footer_inside_above
1710
1934
  margin-bottom: 4em
1711
1935
 
1712
1936
 
1713
- #__header__ .header_inside_below, #__footer__ .footer_inside_below
1937
+ #_header .header_inside_below, #_footer .footer_inside_below
1714
1938
  margin-top: 4em
1715
1939
 
1716
1940