erbook 9.0.0 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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