Table of Contents Plus - Version 1111

Version Description

  • Released: 11 November 2011
  • New: option to adjust the font size. Thanks to DJ for the suggestion. The default remains at 95%.
  • New: advanced option to select the heading levels (1 to 6) to be included. Thanks to those that hinted about wanting to achieve this.
  • New: you can now have the TOC appear in the sidebar via the TOC+ widget. Thanks to Nick Daugherty and DJ for the suggestion.
  • The TOC shortcode now supports the heading_levels attribute to allow you to limit the headings you want to appear in the table of contents on a per instance basis. Separate multiple headings with a comma. For example: include headings 3, 4 and 5 but exclude the others with [toc heading_levels="3,4,5"]
  • The TOC shortcode also supports the wrapping attribute with possible values: "left" or "right". This lets you wrap text next to the table of contents on a per instance basis. Thanks to Phil for the suggestion.
  • Better internal numbering system to avoid repeated headings. This means that for non-repeated headings, there is no trailing number in the anchor.
  • Consolidated information about shortcodes and their attributes into the help tab.
  • Fixed: repeated headings on the same level are no longer broken. For users with international character sets, please report any strange garbage characters in your headings (eg a character ends up being a question mark, square symbol, or diamond). Thanks to Juozas for the assistance.
  • Fixed: removed PHP notices on a verbosely configured PHP setup.
  • Fixed: suppress TOC frame output when heading count was less than the minimum required.
  • Note: when removing the last TOC+ widget, please make sure you disable the "Show the table of contents only in the sidebar" option otherwise your table of contents won't appear where you'd expect. I will look to address this in the future.
Download this release

Release Info

Developer conjur3r
Plugin Icon 128x128 Table of Contents Plus
Version 1111
Comparing to
See all releases

Code changes from version 1109 to 1111

Files changed (5) hide show
  1. admin.css +14 -1
  2. admin.js +3 -3
  3. readme.txt +39 -13
  4. screen.css +2 -1
  5. toc.php +445 -80
admin.css CHANGED
@@ -14,6 +14,9 @@ div.tab_content ul li {
14
  margin-left: 2em;
15
  list-style-type: disc;
16
  }
 
 
 
17
  ul#tabbed-nav {
18
  margin-top: 1em;
19
  }
@@ -93,7 +96,8 @@ div.toc_theme_option {
93
  #wpcontent select optgroup option {
94
  padding-left: 15px;
95
  }
96
- input#width_custom {
 
97
  width: 50px;
98
  text-align: center;
99
  }
@@ -116,4 +120,13 @@ table#theme_custom img:hover {
116
  }
117
  div#farbtastic_colour_wheel {
118
  margin-left: 20px;
 
 
 
 
 
 
 
 
 
119
  }
14
  margin-left: 2em;
15
  list-style-type: disc;
16
  }
17
+ div.tab_content ol li {
18
+ list-style: inherit;
19
+ }
20
  ul#tabbed-nav {
21
  margin-top: 1em;
22
  }
96
  #wpcontent select optgroup option {
97
  padding-left: 15px;
98
  }
99
+ input#width_custom,
100
+ input#font_size {
101
  width: 50px;
102
  text-align: center;
103
  }
120
  }
121
  div#farbtastic_colour_wheel {
122
  margin-left: 20px;
123
+ }
124
+ #shortcode_table th {
125
+ background: #f5f5f5;
126
+ padding: 0.5em;
127
+ }
128
+ #shortcode_table td {
129
+ vertical-align: top;
130
+ border-bottom: #f5f5f5 1px solid;
131
+ padding: 1em 0 1em 0;
132
  }
admin.js CHANGED
@@ -44,9 +44,9 @@ jQuery(document).ready(function($) {
44
  else
45
  $(this).siblings('div.more_toc_options').hide('fast');
46
  });
47
- $('input#width_custom').keyup(function() {
48
- var width = $(this).val();
49
- $(this).val( width.replace(/[^0-9]/, '') );
50
  });
51
  $('input#fragment_prefix').keyup(function() {
52
  var fragment = $(this).val();
44
  else
45
  $(this).siblings('div.more_toc_options').hide('fast');
46
  });
47
+ $('input#width_custom, input#font_size').keyup(function() {
48
+ var value = $(this).val();
49
+ $(this).val( value.replace(/[^0-9\.]/, '') );
50
  });
51
  $('input#fragment_prefix').keyup(function() {
52
  var fragment = $(this).val();
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link:
4
  Tags: table of contents, indexes, toc, sitemap, cms, options, list, page listing, category listing
5
  Requires at least: 3.0
6
  Tested up to: 3.3
7
- Stable tag: 1109
8
 
9
  A powerful yet user friendly plugin that automatically creates a table of contents. Can also output a sitemap listing all pages and categories.
10
 
@@ -47,22 +47,48 @@ This plugin requires PHP 5.
47
 
48
  == Shortcodes ==
49
 
50
- * `[toc]` lets you generate the table of contents at the preferred position. Useful for sites that only require a TOC on a small handful of pages. Supports the following parameters:
51
- ** "label": text, title of the table of contents
52
- ** "no_label": true/false, shows or hides the title
53
- * `[no_toc]` allows you to disable the table of contents for the current post, page, or custom post type.
54
- * `[sitemap]` produces a listing of all pages and categories for your site. You can use this on any post, page or even in a text widget.
55
- * `[sitemap_pages]` lets you print out a listing of only pages. The following parameters are accepted:
56
- ** "heading": number between 1 and 6, defines which html heading to use
57
- ** "label": text, title of the list
58
- ** "no_label": true/false, shows or hides the list heading
59
- ** "exclude": IDs of the pages or categories you wish to exclude
60
- When parameters are left out, they will fallback to the default settings.
61
- * `[sitemap_categories]` as above but for categories.
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
 
64
  == Changelog ==
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  = 1109 =
67
  * Released: 12 September 2011
68
  * Adjusted hide action for a smoother transition.
4
  Tags: table of contents, indexes, toc, sitemap, cms, options, list, page listing, category listing
5
  Requires at least: 3.0
6
  Tested up to: 3.3
7
+ Stable tag: 1111
8
 
9
  A powerful yet user friendly plugin that automatically creates a table of contents. Can also output a sitemap listing all pages and categories.
10
 
47
 
48
  == Shortcodes ==
49
 
50
+ When attributes are left out for the shortcodes below, they will fallback to the settings you defined under Settings > TOC+.
51
+
52
+ = `[toc]` =
53
+ Lets you generate the table of contents at the preferred position. Useful for sites that only require a TOC on a small handful of pages. Supports the following attributes:
54
+ * "label": text, title of the table of contents
55
+ * "no_label": true/false, shows or hides the title
56
+ * "wrapping": text, either "left" or "right"
57
+ * "heading_levels": numbers, this lets you select the heading levels you want included in the table of contents. Separate multiple levels with a comma. Example: include headings 3, 4 and 5 but exclude the others with `heading_levels="3,4,5"`
58
+
59
+ = `[no_toc]` =
60
+ Allows you to disable the table of contents for the current post, page, or custom post type.
61
+
62
+ = `[sitemap]` =
63
+ Produces a listing of all pages and categories for your site. You can use this on any post, page or even in a text widget.
64
+
65
+ = `[sitemap_pages]` =
66
+ Lets you print out a listing of only pages. The following attributes are accepted:
67
+ * "heading": number between 1 and 6, defines which html heading to use
68
+ * "label": text, title of the list
69
+ * "no_label": true/false, shows or hides the list heading
70
+ * "exclude": IDs of the pages or categories you wish to exclude
71
+
72
+ = `[sitemap_categories]` =
73
+ Same as `[sitemap_pages]` but for categories.
74
 
75
 
76
  == Changelog ==
77
 
78
+ = 1111 =
79
+ * Released: 11 November 2011
80
+ * New: option to adjust the font size. Thanks to [DJ](http://dublue.com/plugins/toc/comment-page-1/#comment-323) for the suggestion. The default remains at 95%.
81
+ * New: advanced option to select the heading levels (1 to 6) to be included. Thanks to those that hinted about wanting to achieve this.
82
+ * New: you can now have the TOC appear in the sidebar via the TOC+ widget. Thanks to [Nick Daugherty](http://dublue.com/plugins/toc/comment-page-1/#comment-172) and [DJ](http://dublue.com/plugins/toc/comment-page-1/#comment-323) for the suggestion.
83
+ * The TOC shortcode now supports the *heading_levels* attribute to allow you to limit the headings you want to appear in the table of contents on a per instance basis. Separate multiple headings with a comma. For example: include headings 3, 4 and 5 but exclude the others with `[toc heading_levels="3,4,5"]`
84
+ * The TOC shortcode also supports the *wrapping* attribute with possible values: "left" or "right". This lets you wrap text next to the table of contents on a per instance basis. Thanks to [Phil](http://dublue.com/plugins/toc/comment-page-1/#comment-331) for the suggestion.
85
+ * Better internal numbering system to avoid repeated headings. This means that for non-repeated headings, there is no trailing number in the anchor.
86
+ * Consolidated information about shortcodes and their attributes into the help tab.
87
+ * Fixed: repeated headings on the same level are no longer broken. For users with international character sets, please report any strange garbage characters in your headings (eg a character ends up being a question mark, square symbol, or diamond). Thanks to [Juozas](http://dublue.com/plugins/toc/comment-page-2/#comment-441) for the assistance.
88
+ * Fixed: removed PHP notices on a verbosely configured PHP setup.
89
+ * Fixed: suppress TOC frame output when heading count was less than the minimum required.
90
+ * Note: when removing the last TOC+ widget, please make sure you disable the "Show the table of contents only in the sidebar" option otherwise your table of contents won't appear where you'd expect. I will look to address this in the future.
91
+
92
  = 1109 =
93
  * Released: 12 September 2011
94
  * Adjusted hide action for a smoother transition.
screen.css CHANGED
@@ -2,7 +2,8 @@
2
  margin: 0;
3
  padding: 0;
4
  }
5
- #toc_container.no_bullets ul, #toc_container.no_bullets li {
 
6
  background: none;
7
  list-style-type: none;
8
  }
2
  margin: 0;
3
  padding: 0;
4
  }
5
+ #toc_container.no_bullets ul, #toc_container.no_bullets li,
6
+ .toc_widget_list, .toc_widget_list li {
7
  background: none;
8
  list-style-type: none;
9
  }
toc.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI: http://dublue.com/plugins/toc/
5
  Description: A powerful yet user friendly plugin that automatically creates a table of contents. Can also output a sitemap listing all pages and categories.
6
  Author: Michael Tran
7
  Author URI: http://dublue.com/
8
- Version: 1109
9
  License: GPL2
10
  */
11
 
@@ -69,12 +69,14 @@ if ( !class_exists( 'toc' ) ) :
69
  private $options;
70
  private $show_toc; // allows to override the display (eg through [no_toc] shortcode)
71
  private $exclude_post_types;
 
72
 
73
  function __construct()
74
  {
75
  $this->path = dirname( WP_PLUGIN_URL . '/' . plugin_basename( __FILE__ ) );
76
  $this->show_toc = true;
77
  $this->exclude_post_types = array( 'attachment', 'revision', 'nav_menu_item', 'safecss' );
 
78
 
79
  // get options
80
  $defaults = array( // default options
@@ -94,6 +96,8 @@ if ( !class_exists( 'toc' ) ) :
94
  'width_custom' => '275',
95
  'width_custom_units' => 'px',
96
  'wrapping' => TOC_WRAPPING_NONE,
 
 
97
  'theme' => TOC_THEME_GREY,
98
  'custom_background_colour' => TOC_DEFAULT_BACKGROUND_COLOUR,
99
  'custom_border_colour' => TOC_DEFAULT_BORDER_COLOUR,
@@ -103,11 +107,13 @@ if ( !class_exists( 'toc' ) ) :
103
  'custom_links_visited_colour' => TOC_DEFAULT_LINKS_VISITED_COLOUR,
104
  'bullet_spacing' => false,
105
  'include_homepage' => false,
 
106
  'sitemap_show_page_listing' => true,
107
  'sitemap_show_category_listing' => true,
108
  'sitemap_heading_type' => 3,
109
  'sitemap_pages' => 'Pages',
110
- 'sitemap_categories' => 'Categories'
 
111
  );
112
  $options = get_option( 'toc-options', $defaults );
113
  $this->options = wp_parse_args( $options, $defaults );
@@ -118,6 +124,7 @@ if ( !class_exists( 'toc' ) ) :
118
  add_action( 'wp_head', array(&$this, 'wp_head') );
119
  add_action( 'admin_init', array(&$this, 'admin_init') );
120
  add_action( 'admin_menu', array(&$this, 'admin_menu') );
 
121
 
122
  add_filter( 'the_content', array(&$this, 'the_content'), 11 ); // run after shortcodes are interpretted (level 10)
123
  add_filter( 'plugin_action_links', array(&$this, 'plugin_action_links'), 10, 2 );
@@ -136,6 +143,23 @@ if ( !class_exists( 'toc' ) ) :
136
  }
137
 
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  function plugin_action_links( $links, $file )
140
  {
141
  if ( $file == 'table-of-contents-plus/' . basename(__FILE__) ) {
@@ -150,12 +174,48 @@ if ( !class_exists( 'toc' ) ) :
150
  {
151
  extract( shortcode_atts( array(
152
  'label' => $this->options['heading_text'],
153
- 'no_label' => false
 
 
154
  ), $atts )
155
  );
156
 
157
  if ( $no_label ) $this->options['show_heading_text'] = false;
158
  if ( $label ) $this->options['heading_text'] = html_entity_decode( $label );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
  if ( !is_search() && !is_archive() )
161
  return '<!--TOC-->';
@@ -283,6 +343,12 @@ if ( !class_exists( 'toc' ) ) :
283
  }
284
 
285
 
 
 
 
 
 
 
286
  /**
287
  * Load needed scripts and styles only on the toc administration interface.
288
  */
@@ -330,8 +396,10 @@ if ( !class_exists( 'toc' ) ) :
330
 
331
  private function save_admin_options()
332
  {
 
 
333
  // security check
334
- if ( !wp_verify_nonce( $_POST['toc-admin-options'], plugin_basename(__FILE__) ) )
335
  return false;
336
 
337
  // require an administrator level to save
@@ -347,35 +415,38 @@ if ( !class_exists( 'toc' ) ) :
347
  $custom_title_colour = $this->hex_value( trim($_POST['custom_title_colour']), TOC_DEFAULT_TITLE_COLOUR );
348
  $custom_links_colour = $this->hex_value( trim($_POST['custom_links_colour']), TOC_DEFAULT_LINKS_COLOUR );
349
  $custom_links_hover_colour = $this->hex_value( trim($_POST['custom_links_hover_colour']), TOC_DEFAULT_LINKS_HOVER_COLOUR );
350
- $custom_links_visited_colour = $this->hex_value( trim($_POST['custom_links_visited_colour']), TOC_DEFAULT_LINKS_VISITED_COLOUR );
351
 
352
  $this->options = array(
353
  'fragment_prefix' => trim($_POST['fragment_prefix']),
354
  'position' => intval($_POST['position']),
355
  'start' => intval($_POST['start']),
356
- 'show_heading_text' => ($_POST['show_heading_text']) ? true : false,
357
  'heading_text' => stripslashes( trim($_POST['heading_text']) ),
358
- 'auto_insert_post_types' => (array)$_POST['auto_insert_post_types'],
359
- 'show_heirarchy' => ($_POST['show_heirarchy']) ? true : false,
360
- 'ordered_list' => ($_POST['ordered_list']) ? true : false,
361
- 'smooth_scroll' => ($_POST['smooth_scroll']) ? true : false,
362
- 'visibility' => ($_POST['visibility']) ? true : false,
363
  'visibility_show' => stripslashes( trim($_POST['visibility_show']) ),
364
  'visibility_hide' => stripslashes( trim($_POST['visibility_hide']) ),
365
  'width' => trim($_POST['width']),
366
- 'width_custom' => intval($_POST['width_custom']),
367
  'width_custom_units' => trim($_POST['width_custom_units']),
368
  'wrapping' => intval($_POST['wrapping']),
 
 
369
  'theme' => intval($_POST['theme']),
370
  'custom_background_colour' => $custom_background_colour,
371
  'custom_border_colour' => $custom_border_colour,
372
  'custom_title_colour' => $custom_title_colour,
373
  'custom_links_colour' => $custom_links_colour,
374
  'custom_links_hover_colour' => $custom_links_hover_colour,
375
- 'bullet_spacing' => ($_POST['bullet_spacing']) ? true : false,
376
- 'include_homepage' => ($_POST['include_homepage']) ? true : false,
377
- 'sitemap_show_page_listing' => ($_POST['sitemap_show_page_listing']) ? true : false,
378
- 'sitemap_show_category_listing' => ($_POST['sitemap_show_category_listing']) ? true : false,
 
379
  'sitemap_heading_type' => intval($_POST['sitemap_heading_type']),
380
  'sitemap_pages' => stripslashes( trim($_POST['sitemap_pages']) ),
381
  'sitemap_categories' => stripslashes( trim($_POST['sitemap_categories']) )
@@ -529,7 +600,7 @@ if ( !class_exists( 'toc' ) ) :
529
  </select>
530
  <div class="more_toc_options<?php if ( 'User defined' != $this->options['width'] ) echo ' disabled'; ?>">
531
  <label for="width_custom"><?php _e('Please enter a number and', 'toc+'); ?></label><label for="width_custom_units"> <?php _e('select its units, eg: 100px, 10em', 'toc+'); ?></label><br />
532
- <input type="text" class="regular-text" value="<?php echo intval($this->options['width_custom']); ?>" id="width_custom" name="width_custom" />
533
  <select name="width_custom_units" id="width_custom_units">
534
  <option value="px"<?php if ( 'px' == $this->options['width_custom_units'] ) echo ' selected="selected"'; ?>>px</option>
535
  <option value="%"<?php if ( '%' == $this->options['width_custom_units'] ) echo ' selected="selected"'; ?>>%</option>
@@ -548,6 +619,17 @@ if ( !class_exists( 'toc' ) ) :
548
  </select>
549
  </td>
550
  </tr>
 
 
 
 
 
 
 
 
 
 
 
551
  <tr>
552
  <th><?php _e('Presentation', 'toc+'); ?></th>
553
  <td>
@@ -638,6 +720,20 @@ if ( !class_exists( 'toc' ) ) :
638
  <th><label for="include_homepage"><?php _e('Include homepage', 'toc+'); ?></label></th>
639
  <td><input type="checkbox" value="1" id="include_homepage" name="include_homepage"<?php if ( $this->options['include_homepage'] ) echo ' checked="checked"'; ?> /><label for="include_homepage"> <?php _e( 'Show the table of contents for qualifying items on the homepage', 'toc+'); ?></label></td>
640
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
641
  <tr>
642
  <th><label for="fragment_prefix"><?php _e('Default anchor prefix', 'toc+'); ?></label></th>
643
  <td>
@@ -651,11 +747,7 @@ if ( !class_exists( 'toc' ) ) :
651
  </table>
652
 
653
  <h4><?php _e('Usage', 'toc+'); ?></h4>
654
- <p>If you would like to fully customise the position of the table of contents, you can use the <code>[toc]</code> shortcode by placing it at the desired position of your post, page or custom post type. This method allows you to generate the table of contents despite having auto insertion disabled for its content type. Supports the following parameters:</p>
655
- <ul>
656
- <li><strong>label</strong> text, title of the table of contents</li>
657
- <li><strong>no_label</strong> true/false, shows or hides the title</li>
658
- </ul>
659
  </div>
660
 
661
 
@@ -705,14 +797,7 @@ if ( !class_exists( 'toc' ) ) :
705
 
706
  <h3>Advanced usage <span class="show_hide">(<a href="#sitemap_advanced_usage">show</a>)</span></h3>
707
  <div id="sitemap_advanced_usage">
708
- <p><code>[sitemap_pages]</code> lets you print out a listing of only pages. Similarly, <code>[sitemap_categories]</code> can be used to print out a category listing. They both can accept the following parameters for further customisation:</p>
709
- <ul>
710
- <li><strong>heading</strong>: number between 1 and 6, defines which html heading to use</li>
711
- <li><strong>label</strong>: text, title of the list</li>
712
- <li><strong>no_label</strong>: true/false, shows or hides the list heading</li>
713
- <li><strong>exclude</strong>: IDs of the pages or categories you wish to exclude</li>
714
- </ul>
715
- <p>When parameters are left out, they will fallback to the default settings.</p>
716
  <p>Examples</p>
717
  <ol>
718
  <li><code>[sitemap_categories no_label="true"]</code> hides the heading from a category listing</li>
@@ -730,6 +815,7 @@ if ( !class_exists( 'toc' ) ) :
730
  <li>In most cases, the post, page or custom post type has less than the minimum number of headings. By default, this is set to four so make sure you have at least four headings within your content. If you want to change this value, you can find it under 'Main Options' &gt; 'Show when'.</li>
731
  <li>Is auto insertion enabled for your content type? By default, only pages are enabled.</li>
732
  <li>Have you got <code>[no_toc]</code> somewhere within the content? This will disable the index for the current post, page or custom post type.</li>
 
733
  </ol>
734
 
735
  <h3>How do I stop the table of contents from appearing on a single page?</h3>
@@ -743,8 +829,58 @@ if ( !class_exists( 'toc' ) ) :
743
  <p>No extra styles are created for the sitemap, instead it inherits any styles you used when adding the shortcode. If you copy and pasted, you probably also copied the 'code' tags surrounding it so remove them if this is the case.</p>
744
  <p>In most cases, try to have the shortcode on its own line with nothing before or after the square brackets.</p>
745
 
746
- <h3>What's with the version numbers?</h3>
747
- <p>I like Ubuntu, especially the server product and highly recommend it for Linux deployments. I also like their versioning scheme and have adopted it. All versions are in a YYMM format (year month) of when the release was made.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
748
 
749
  <h3>I have another question...</h3>
750
  <p>Visit the <a href="http://dublue.com/plugins/toc/">plugin homepage</a> to ask your question - who knows, maybe your question has already been answered. I'd really like to hear your suggestions if you have any.</p>
@@ -768,7 +904,11 @@ if ( !class_exists( 'toc' ) ) :
768
 
769
  function wp_head()
770
  {
771
- if ( $this->options['theme'] == TOC_THEME_CUSTOM || $this->options['width'] != '275px' ) :
 
 
 
 
772
  ?>
773
  <style type="text/css">
774
  div#toc_container {
@@ -786,6 +926,10 @@ div#toc_container {
786
  echo $this->options['width_custom'] . $this->options['width_custom_units'];
787
  echo ";\n";
788
  }
 
 
 
 
789
  ?>
790
  }
791
  <?php if ( $this->options['custom_title_colour'] != TOC_DEFAULT_TITLE_COLOUR ) : ?>
@@ -870,16 +1014,21 @@ div#toc_container ul.toc_list a:visited {
870
  '_',
871
  $return
872
  );
873
-
874
- // remove leading _- if any
875
- $return = ltrim( $return, '_-' );
876
 
877
- // if only a number, then prepend with the prefix to avoid any collisions with IDs
878
- if ( is_numeric($return) ) {
879
- $return = ( $this->options['fragment_prefix'] ) ? $this->options['fragment_prefix'] . '-' . $return : '_' . $return;
 
880
  }
881
  }
882
 
 
 
 
 
 
 
 
883
  return $return;
884
  }
885
 
@@ -891,6 +1040,9 @@ div#toc_container ul.toc_list a:visited {
891
  $numbered_items = array();
892
  $numbered_items_min = null;
893
 
 
 
 
894
  // find the minimum heading to establish our baseline
895
  for ($i = 0; $i < count($matches); $i++) {
896
  if ( $current_depth > $matches[$i][2] )
@@ -908,23 +1060,26 @@ div#toc_container ul.toc_list a:visited {
908
  // start lists
909
  if ( $current_depth != (int)$matches[$i][2] ) {
910
  for ($current_depth; $current_depth < (int)$matches[$i][2]; $current_depth++) {
 
911
  $html .= '<ul><li>';
912
  }
913
  }
914
 
915
  // list item
916
- $html .= '<a href="#' . $this->url_anchor_target( $matches[$i][0] . '-' . ($i + 1) ) . '">';
917
- if ( $this->options['ordered_list'] ) {
918
- // attach leading numbers when lower in hierarchy
919
- for ($j = $numbered_items_min; $j < $current_depth; $j++) {
920
- $number = ($numbered_items[$j]) ? $numbered_items[$j] : 0;
921
- $html .= $number . '.';
 
 
 
 
 
922
  }
923
-
924
- $html .= (@$numbered_items[$current_depth] + 1) . ' ';
925
- @$numbered_items[$current_depth]++;
926
  }
927
- $html .= strip_tags($matches[$i][0]) . '</a>';
928
 
929
 
930
  // end lists
@@ -952,24 +1107,78 @@ div#toc_container ul.toc_list a:visited {
952
  }
953
 
954
 
955
- function the_content( $content )
 
 
 
 
 
 
 
 
 
 
956
  {
957
- global $post;
958
- $items = $css_classes = '';
959
- $custom_toc_position = strpos($content, '<!--TOC-->');
960
- $matches = $find = $replace = array();
961
-
962
- if (
963
- ( in_array(get_post_type($post), $this->options['auto_insert_post_types']) && $this->show_toc && !is_search() && !is_archive() && !is_front_page() ) ||
964
- ( $this->options['include_homepage'] && is_front_page() ) ||
965
- ( $custom_toc_position !== false )
966
- ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
967
  // get all headings
968
  // the html spec allows for a maximum of 6 heading depths
969
  if ( preg_match_all('/(<h([1-6]{1})[^>]*>).*<\/h\2>/', $content, $matches, PREG_SET_ORDER) >= $this->options['start'] ) {
 
 
 
 
 
 
 
 
 
 
 
970
  for ($i = 0; $i < count($matches); $i++) {
971
-
972
- // create find and replace arrays
973
  $find[] = $matches[$i][0];
974
  $replace[] = str_replace(
975
  array(
@@ -977,7 +1186,7 @@ div#toc_container ul.toc_list a:visited {
977
  '</h' . $matches[$i][2] . '>' // end of heading
978
  ),
979
  array(
980
- $matches[$i][1] . '<span id="' . $this->url_anchor_target( $matches[$i][0] . '-' . ($i + 1) ) . '">',
981
  '</span></h' . $matches[$i][2] . '>'
982
  ),
983
  $matches[$i][0]
@@ -985,16 +1194,57 @@ div#toc_container ul.toc_list a:visited {
985
 
986
  // assemble flat list
987
  if ( !$this->options['show_heirarchy'] ) {
988
- $items .= '<li><a href="#' . $this->url_anchor_target( $matches[$i][0] . '-' . ($i + 1) ) . '">';
989
- if ( $this->options['ordered_list'] ) $items .= ($i + 1) . ' ';
990
  $items .= strip_tags($matches[$i][0]) . '</a></li>';
991
  }
992
  }
993
-
994
  // build a hierarchical toc?
995
  // we could have tested for $items but that var can be quite large in some cases
996
  if ( $this->options['show_heirarchy'] ) $items = $this->build_hierarchy( &$matches );
997
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
998
  // wrapping css classes
999
  switch( $this->options['wrapping'] ) {
1000
  case TOC_WRAPPING_LEFT:
@@ -1052,22 +1302,24 @@ div#toc_container ul.toc_list a:visited {
1052
  if ( $custom_toc_position !== false ) {
1053
  $find[] = '<!--TOC-->';
1054
  $replace[] = $html;
1055
- $content = str_replace($find, $replace, $content);
1056
  }
1057
  else {
1058
- switch ( $this->options['position'] ) {
1059
- case TOC_POSITION_TOP:
1060
- $content = $html . str_replace($find, $replace, $content);
1061
- break;
 
 
 
 
 
1062
 
1063
- case TOC_POSITION_BOTTOM:
1064
- $content = str_replace($find, $replace, $content) . $html;
1065
- break;
1066
-
1067
- case TOC_POSITION_BEFORE_FIRST_HEADING:
1068
- default:
1069
- $replace[0] = $html . $replace[0];
1070
- $content = str_replace($find, $replace, $content);
1071
  }
1072
  }
1073
  }
@@ -1076,11 +1328,124 @@ div#toc_container ul.toc_list a:visited {
1076
  return $content;
1077
  }
1078
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1079
 
1080
  } // end class
1081
  endif;
1082
 
1083
 
 
1084
  // do the magic
1085
  $tic = new toc();
1086
 
5
  Description: A powerful yet user friendly plugin that automatically creates a table of contents. Can also output a sitemap listing all pages and categories.
6
  Author: Michael Tran
7
  Author URI: http://dublue.com/
8
+ Version: 1111
9
  License: GPL2
10
  */
11
 
69
  private $options;
70
  private $show_toc; // allows to override the display (eg through [no_toc] shortcode)
71
  private $exclude_post_types;
72
+ private $collision_collector; // keeps a track of used anchors for collision detecting
73
 
74
  function __construct()
75
  {
76
  $this->path = dirname( WP_PLUGIN_URL . '/' . plugin_basename( __FILE__ ) );
77
  $this->show_toc = true;
78
  $this->exclude_post_types = array( 'attachment', 'revision', 'nav_menu_item', 'safecss' );
79
+ $this->collection_collector = array();
80
 
81
  // get options
82
  $defaults = array( // default options
96
  'width_custom' => '275',
97
  'width_custom_units' => 'px',
98
  'wrapping' => TOC_WRAPPING_NONE,
99
+ 'font_size' => '95',
100
+ 'font_size_units' => '%',
101
  'theme' => TOC_THEME_GREY,
102
  'custom_background_colour' => TOC_DEFAULT_BACKGROUND_COLOUR,
103
  'custom_border_colour' => TOC_DEFAULT_BORDER_COLOUR,
107
  'custom_links_visited_colour' => TOC_DEFAULT_LINKS_VISITED_COLOUR,
108
  'bullet_spacing' => false,
109
  'include_homepage' => false,
110
+ 'heading_levels' => array('1', '2', '3', '4', '5', '6'),
111
  'sitemap_show_page_listing' => true,
112
  'sitemap_show_category_listing' => true,
113
  'sitemap_heading_type' => 3,
114
  'sitemap_pages' => 'Pages',
115
+ 'sitemap_categories' => 'Categories',
116
+ 'show_toc_in_widget_only' => false
117
  );
118
  $options = get_option( 'toc-options', $defaults );
119
  $this->options = wp_parse_args( $options, $defaults );
124
  add_action( 'wp_head', array(&$this, 'wp_head') );
125
  add_action( 'admin_init', array(&$this, 'admin_init') );
126
  add_action( 'admin_menu', array(&$this, 'admin_menu') );
127
+ add_action( 'widgets_init', array(&$this, 'widgets_init') );
128
 
129
  add_filter( 'the_content', array(&$this, 'the_content'), 11 ); // run after shortcodes are interpretted (level 10)
130
  add_filter( 'plugin_action_links', array(&$this, 'plugin_action_links'), 10, 2 );
143
  }
144
 
145
 
146
+ public function get_options()
147
+ {
148
+ return $this->options;
149
+ }
150
+
151
+
152
+ public function set_show_toc_in_widget_only( $value = false )
153
+ {
154
+ if ( $value )
155
+ $this->options['show_toc_in_widget_only'] = true;
156
+ else
157
+ $this->options['show_toc_in_widget_only'] = false;
158
+
159
+ update_option( 'toc-options', $this->options );
160
+ }
161
+
162
+
163
  function plugin_action_links( $links, $file )
164
  {
165
  if ( $file == 'table-of-contents-plus/' . basename(__FILE__) ) {
174
  {
175
  extract( shortcode_atts( array(
176
  'label' => $this->options['heading_text'],
177
+ 'no_label' => false,
178
+ 'wrapping' => $this->options['wrapping'],
179
+ 'heading_levels' => $this->options['heading_levels']
180
  ), $atts )
181
  );
182
 
183
  if ( $no_label ) $this->options['show_heading_text'] = false;
184
  if ( $label ) $this->options['heading_text'] = html_entity_decode( $label );
185
+ if ( $wrapping ) {
186
+ switch ( strtolower(trim($wrapping)) ) {
187
+ case 'left':
188
+ $this->options['wrapping'] = TOC_WRAPPING_LEFT;
189
+ break;
190
+
191
+ case 'right':
192
+ $this->options['wrapping'] = TOC_WRAPPING_RIGHT;
193
+ break;
194
+
195
+ default:
196
+ // do nothing
197
+ }
198
+ }
199
+
200
+ // if $heading_levels is an array, then it came from the global options
201
+ // and wasn't provided by per instance
202
+ if ( $heading_levels && !is_array($heading_levels) ) {
203
+ // make sure they are numbers between 1 and 6 and put into
204
+ // the $clean_heading_levels array if not already
205
+ $clean_heading_levels = array();
206
+ foreach (explode(',', $heading_levels) as $heading_level) {
207
+ if ( is_numeric($heading_level) ) {
208
+ if ( 1 <= $heading_level && $heading_level <= 6 ) {
209
+ if ( !in_array($heading_level, $clean_heading_levels) ) {
210
+ $clean_heading_levels[] = $heading_level;
211
+ }
212
+ }
213
+ }
214
+ }
215
+
216
+ if ( count($clean_heading_levels) > 0 )
217
+ $this->options['heading_levels'] = $clean_heading_levels;
218
+ }
219
 
220
  if ( !is_search() && !is_archive() )
221
  return '<!--TOC-->';
343
  }
344
 
345
 
346
+ function widgets_init()
347
+ {
348
+ register_widget('toc_widget');
349
+ }
350
+
351
+
352
  /**
353
  * Load needed scripts and styles only on the toc administration interface.
354
  */
396
 
397
  private function save_admin_options()
398
  {
399
+ global $post_id;
400
+
401
  // security check
402
+ if ( !wp_verify_nonce( @$_POST['toc-admin-options'], plugin_basename(__FILE__) ) )
403
  return false;
404
 
405
  // require an administrator level to save
415
  $custom_title_colour = $this->hex_value( trim($_POST['custom_title_colour']), TOC_DEFAULT_TITLE_COLOUR );
416
  $custom_links_colour = $this->hex_value( trim($_POST['custom_links_colour']), TOC_DEFAULT_LINKS_COLOUR );
417
  $custom_links_hover_colour = $this->hex_value( trim($_POST['custom_links_hover_colour']), TOC_DEFAULT_LINKS_HOVER_COLOUR );
418
+ //$custom_links_visited_colour = $this->hex_value( trim($_POST['custom_links_visited_colour']), TOC_DEFAULT_LINKS_VISITED_COLOUR );
419
 
420
  $this->options = array(
421
  'fragment_prefix' => trim($_POST['fragment_prefix']),
422
  'position' => intval($_POST['position']),
423
  'start' => intval($_POST['start']),
424
+ 'show_heading_text' => (isset($_POST['show_heading_text']) && $_POST['show_heading_text']) ? true : false,
425
  'heading_text' => stripslashes( trim($_POST['heading_text']) ),
426
+ 'auto_insert_post_types' => @(array)$_POST['auto_insert_post_types'],
427
+ 'show_heirarchy' => (isset($_POST['show_heirarchy']) && $_POST['show_heirarchy']) ? true : false,
428
+ 'ordered_list' => (isset($_POST['ordered_list']) && $_POST['ordered_list']) ? true : false,
429
+ 'smooth_scroll' => (isset($_POST['smooth_scroll']) && $_POST['smooth_scroll']) ? true : false,
430
+ 'visibility' => (isset($_POST['visibility']) && $_POST['visibility']) ? true : false,
431
  'visibility_show' => stripslashes( trim($_POST['visibility_show']) ),
432
  'visibility_hide' => stripslashes( trim($_POST['visibility_hide']) ),
433
  'width' => trim($_POST['width']),
434
+ 'width_custom' => floatval($_POST['width_custom']),
435
  'width_custom_units' => trim($_POST['width_custom_units']),
436
  'wrapping' => intval($_POST['wrapping']),
437
+ 'font_size' => floatval($_POST['font_size']),
438
+ 'font_size_units' => trim($_POST['font_size_units']),
439
  'theme' => intval($_POST['theme']),
440
  'custom_background_colour' => $custom_background_colour,
441
  'custom_border_colour' => $custom_border_colour,
442
  'custom_title_colour' => $custom_title_colour,
443
  'custom_links_colour' => $custom_links_colour,
444
  'custom_links_hover_colour' => $custom_links_hover_colour,
445
+ 'bullet_spacing' => (isset($_POST['bullet_spacing']) && $_POST['bullet_spacing']) ? true : false,
446
+ 'include_homepage' => (isset($_POST['include_homepage']) && $_POST['include_homepage']) ? true : false,
447
+ 'heading_levels' => @(array)$_POST['heading_levels'],
448
+ 'sitemap_show_page_listing' => (isset($_POST['sitemap_show_page_listing']) && $_POST['sitemap_show_page_listing']) ? true : false,
449
+ 'sitemap_show_category_listing' => (isset($_POST['sitemap_show_category_listing']) && $_POST['sitemap_show_category_listing']) ? true : false,
450
  'sitemap_heading_type' => intval($_POST['sitemap_heading_type']),
451
  'sitemap_pages' => stripslashes( trim($_POST['sitemap_pages']) ),
452
  'sitemap_categories' => stripslashes( trim($_POST['sitemap_categories']) )
600
  </select>
601
  <div class="more_toc_options<?php if ( 'User defined' != $this->options['width'] ) echo ' disabled'; ?>">
602
  <label for="width_custom"><?php _e('Please enter a number and', 'toc+'); ?></label><label for="width_custom_units"> <?php _e('select its units, eg: 100px, 10em', 'toc+'); ?></label><br />
603
+ <input type="text" class="regular-text" value="<?php echo floatval($this->options['width_custom']); ?>" id="width_custom" name="width_custom" />
604
  <select name="width_custom_units" id="width_custom_units">
605
  <option value="px"<?php if ( 'px' == $this->options['width_custom_units'] ) echo ' selected="selected"'; ?>>px</option>
606
  <option value="%"<?php if ( '%' == $this->options['width_custom_units'] ) echo ' selected="selected"'; ?>>%</option>
619
  </select>
620
  </td>
621
  </tr>
622
+ <tr>
623
+ <th><label for="font_size"><?php _e('Font size', 'toc+'); ?></label></th>
624
+ <td>
625
+ <input type="text" class="regular-text" value="<?php echo floatval($this->options['font_size']); ?>" id="font_size" name="font_size" />
626
+ <select name="font_size_units" id="font_size_units">
627
+ <option value="px"<?php if ( 'pt' == $this->options['font_size_units'] ) echo ' selected="selected"'; ?>>pt</option>
628
+ <option value="%"<?php if ( '%' == $this->options['font_size_units'] ) echo ' selected="selected"'; ?>>%</option>
629
+ <option value="em"<?php if ( 'em' == $this->options['font_size_units'] ) echo ' selected="selected"'; ?>>em</option>
630
+ </select>
631
+ </td>
632
+ </tr>
633
  <tr>
634
  <th><?php _e('Presentation', 'toc+'); ?></th>
635
  <td>
720
  <th><label for="include_homepage"><?php _e('Include homepage', 'toc+'); ?></label></th>
721
  <td><input type="checkbox" value="1" id="include_homepage" name="include_homepage"<?php if ( $this->options['include_homepage'] ) echo ' checked="checked"'; ?> /><label for="include_homepage"> <?php _e( 'Show the table of contents for qualifying items on the homepage', 'toc+'); ?></label></td>
722
  </tr>
723
+ <tr>
724
+ <th><?php _e('Heading levels', 'toc+'); ?></th>
725
+ <td>
726
+ <p><?php _e('Include (or exclude) the following heading levels', 'toc+'); ?></p>
727
+ <?php
728
+ // show heading 1 to 6 options
729
+ for ($i = 1; $i <= 6; $i++) {
730
+ echo '<input type="checkbox" value="' . $i . '" id="heading_levels' . $i .'" name="heading_levels[]"';
731
+ if ( in_array($i, $this->options['heading_levels']) ) echo ' checked="checked"';
732
+ echo ' /><label for="heading_levels' . $i .'"> ' . __('heading ') . $i . ' - h' . $i . '</label><br />';
733
+ }
734
+ ?>
735
+ </td>
736
+ </tr>
737
  <tr>
738
  <th><label for="fragment_prefix"><?php _e('Default anchor prefix', 'toc+'); ?></label></th>
739
  <td>
747
  </table>
748
 
749
  <h4><?php _e('Usage', 'toc+'); ?></h4>
750
+ <p>If you would like to fully customise the position of the table of contents, you can use the <code>[toc]</code> shortcode by placing it at the desired position of your post, page or custom post type. This method allows you to generate the table of contents despite having auto insertion disabled for its content type. Please visit the help tab for further information about this shortcode.</p>
 
 
 
 
751
  </div>
752
 
753
 
797
 
798
  <h3>Advanced usage <span class="show_hide">(<a href="#sitemap_advanced_usage">show</a>)</span></h3>
799
  <div id="sitemap_advanced_usage">
800
+ <p><code>[sitemap_pages]</code> lets you print out a listing of only pages. Similarly, <code>[sitemap_categories]</code> can be used to print out a category listing. They both can accept a number of attributes so visit the help tab for more information.</p>
 
 
 
 
 
 
 
801
  <p>Examples</p>
802
  <ol>
803
  <li><code>[sitemap_categories no_label="true"]</code> hides the heading from a category listing</li>
815
  <li>In most cases, the post, page or custom post type has less than the minimum number of headings. By default, this is set to four so make sure you have at least four headings within your content. If you want to change this value, you can find it under 'Main Options' &gt; 'Show when'.</li>
816
  <li>Is auto insertion enabled for your content type? By default, only pages are enabled.</li>
817
  <li>Have you got <code>[no_toc]</code> somewhere within the content? This will disable the index for the current post, page or custom post type.</li>
818
+ <li>If you are using the TOC+ widget, check if you have the <em>"Show the table of contents only in the sidebar"</em> enabled as this will limit its display to only the sidebar. You can check by going into Appearance &gt; Widgets.</li>
819
  </ol>
820
 
821
  <h3>How do I stop the table of contents from appearing on a single page?</h3>
829
  <p>No extra styles are created for the sitemap, instead it inherits any styles you used when adding the shortcode. If you copy and pasted, you probably also copied the 'code' tags surrounding it so remove them if this is the case.</p>
830
  <p>In most cases, try to have the shortcode on its own line with nothing before or after the square brackets.</p>
831
 
832
+ <h3>What were those shortcodes and attributes again?</h3>
833
+ <p>When attributes are left out for the shortcodes below, they will fallback to the settings you defined under Settings &gt; TOC+.</p>
834
+ <table id="shortcode_table">
835
+ <thead>
836
+ <tr>
837
+ <th>Shortcode</th>
838
+ <th>Description</th>
839
+ <th>Attributes</th>
840
+ </tr>
841
+ </thead>
842
+ <tbody>
843
+ <tr>
844
+ <td>[toc]</td>
845
+ <td>Lets you generate the table of contents at the preferred position. Also useful for sites that only require a TOC on a small handful of pages.</td>
846
+ <td>
847
+ <ul>
848
+ <li><strong>label</strong>: text, title of the table of contents</li>
849
+ <li><strong>no_label</strong>: true/false, shows or hides the title</li>
850
+ <li><strong>wrapping</strong>: text, either "left" or "right"</li>
851
+ <li><strong>heading_levels</strong>: numbers, this lets you select the heading levels you want included in the table of contents. Separate multiple levels with a comma. Example: include headings 3, 4 and 5 but exclude the others with <code>heading_levels="3,4,5"</code></li>
852
+ </ul>
853
+ </td>
854
+ </tr>
855
+ <tr>
856
+ <td>[no_toc]</td>
857
+ <td>Allows you to disable the table of contents for the current post, page, or custom post type.</td>
858
+ <td>&nbsp;</td>
859
+ </tr>
860
+ <tr>
861
+ <td>[sitemap]</td>
862
+ <td>Produces a listing of all pages and categories for your site. You can use this on any post, page or even in a text widget.</td>
863
+ <td>&nbsp;</td>
864
+ </tr>
865
+ <tr>
866
+ <td>[sitemap_pages]</td>
867
+ <td>Lets you print out a listing of only pages.</td>
868
+ <td>
869
+ <ul>
870
+ <li><strong>heading</strong>: number between 1 and 6, defines which html heading to use</li>
871
+ <li><strong>label</strong>: text, title of the list</li>
872
+ <li><strong>no_label</strong>: true/false, shows or hides the list heading</li>
873
+ <li><strong>exclude</strong>: IDs of the pages or categories you wish to exclude</li>
874
+ </ul>
875
+ </td>
876
+ </tr>
877
+ <tr>
878
+ <td>[sitemap_categories]</td>
879
+ <td>Similar to [sitemap_pages] but for categories.</td>
880
+ <td>&nbsp;</td>
881
+ </tr>
882
+ </tbody>
883
+ </table>
884
 
885
  <h3>I have another question...</h3>
886
  <p>Visit the <a href="http://dublue.com/plugins/toc/">plugin homepage</a> to ask your question - who knows, maybe your question has already been answered. I'd really like to hear your suggestions if you have any.</p>
904
 
905
  function wp_head()
906
  {
907
+ if (
908
+ $this->options['theme'] == TOC_THEME_CUSTOM ||
909
+ $this->options['width'] != '275px' ||
910
+ ( '95%' != $this->options['font_size'] . $this->options['font_size_units'] )
911
+ ) :
912
  ?>
913
  <style type="text/css">
914
  div#toc_container {
926
  echo $this->options['width_custom'] . $this->options['width_custom_units'];
927
  echo ";\n";
928
  }
929
+
930
+ if ( '95%' != $this->options['font_size'] . $this->options['font_size_units'] ) {
931
+ echo ' font-size: ' . $this->options['font_size'] . $this->options['font_size_units'] . ";\n";
932
+ }
933
  ?>
934
  }
935
  <?php if ( $this->options['custom_title_colour'] != TOC_DEFAULT_TITLE_COLOUR ) : ?>
1014
  '_',
1015
  $return
1016
  );
 
 
 
1017
 
1018
+ // if blank, then prepend with the fragment prefix
1019
+ // blank anchors normally appear on sites that don't use the latin charset
1020
+ if ( !$return ) {
1021
+ $return = ( $this->options['fragment_prefix'] ) ? $this->options['fragment_prefix'] : '_';
1022
  }
1023
  }
1024
 
1025
+ if ( array_key_exists($return, $this->collection_collector) ) {
1026
+ $this->collection_collector[$return]++;
1027
+ $return .= '-' . $this->collection_collector[$return];
1028
+ }
1029
+ else
1030
+ $this->collection_collector[$return] = 1;
1031
+
1032
  return $return;
1033
  }
1034
 
1040
  $numbered_items = array();
1041
  $numbered_items_min = null;
1042
 
1043
+ // reset the internal collision collection
1044
+ $this->collection_collector = array();
1045
+
1046
  // find the minimum heading to establish our baseline
1047
  for ($i = 0; $i < count($matches); $i++) {
1048
  if ( $current_depth > $matches[$i][2] )
1060
  // start lists
1061
  if ( $current_depth != (int)$matches[$i][2] ) {
1062
  for ($current_depth; $current_depth < (int)$matches[$i][2]; $current_depth++) {
1063
+ $numbered_items[$current_depth + 1] = 0;
1064
  $html .= '<ul><li>';
1065
  }
1066
  }
1067
 
1068
  // list item
1069
+ if ( in_array($matches[$i][2], $this->options['heading_levels']) ) {
1070
+ $html .= '<a href="#' . $this->url_anchor_target( $matches[$i][0] ) . '">';
1071
+ if ( $this->options['ordered_list'] ) {
1072
+ // attach leading numbers when lower in hierarchy
1073
+ for ($j = $numbered_items_min; $j < $current_depth; $j++) {
1074
+ $number = ($numbered_items[$j]) ? $numbered_items[$j] : 0;
1075
+ $html .= $number . '.';
1076
+ }
1077
+
1078
+ $html .= ($numbered_items[$current_depth] + 1) . ' ';
1079
+ $numbered_items[$current_depth]++;
1080
  }
1081
+ $html .= strip_tags($matches[$i][0]) . '</a>';
 
 
1082
  }
 
1083
 
1084
 
1085
  // end lists
1107
  }
1108
 
1109
 
1110
+ /**
1111
+ * Returns a string with all items from the $find array replaced with their matching
1112
+ * items in the $replace array. This does a one to one replacement (rather than
1113
+ * globally).
1114
+ *
1115
+ * This function is multibyte safe.
1116
+ *
1117
+ * $find and $replace are arrays, $string is the haystack. All variables are
1118
+ * passed by reference.
1119
+ */
1120
+ private function mb_find_replace( &$find = false, &$replace = false, &$string = '' )
1121
  {
1122
+ if ( is_array($find) && is_array($replace) && $string ) {
1123
+ // check if multibyte strings are supported
1124
+ if ( function_exists( 'mb_substr' ) ) {
1125
+ for ($i = 0; $i < count($find); $i++) {
1126
+ $string =
1127
+ mb_substr( $string, 0, mb_strpos($string, $find[$i]) ) . // everything befor $find
1128
+ $replace[$i] . // its replacement
1129
+ mb_substr( $string, mb_strpos($string, $find[$i]) + mb_strlen($find[$i]) ) // everything after $find
1130
+ ;
1131
+ }
1132
+ }
1133
+ else {
1134
+ for ($i = 0; $i < count($find); $i++) {
1135
+ $string = substr_replace(
1136
+ $string,
1137
+ $replace[$i],
1138
+ strpos($string, $find[$i]),
1139
+ strlen($find[$i])
1140
+ );
1141
+ }
1142
+ }
1143
+ }
1144
+
1145
+ return $string;
1146
+ }
1147
+
1148
+
1149
+ /**
1150
+ * This function extracts headings from the html formatted $content. It will pull out
1151
+ * only the require headings as specified in the options. For all qualifying headings,
1152
+ * this function populates the $find and $replace arrays (both passed by reference)
1153
+ * with what to search and replace with.
1154
+ *
1155
+ * Returns a html formatted string of list items for each qualifying heading. This
1156
+ * is everything between and not including <ul> and </ul>
1157
+ */
1158
+ public function extract_headings( &$find, &$replace, $content = '' )
1159
+ {
1160
+ $matches = array();
1161
+ $anchor = '';
1162
+ $items = false;
1163
+
1164
+ if ( is_array($find) && is_array($replace) && $content ) {
1165
  // get all headings
1166
  // the html spec allows for a maximum of 6 heading depths
1167
  if ( preg_match_all('/(<h([1-6]{1})[^>]*>).*<\/h\2>/', $content, $matches, PREG_SET_ORDER) >= $this->options['start'] ) {
1168
+
1169
+ // remove disqualified headings (if any) as defined by heading_levels
1170
+ if ( count($this->options['heading_levels']) != 6 ) {
1171
+ $new_matches = array();
1172
+ for ($i = 0; $i < count($matches); $i++) {
1173
+ if ( in_array($matches[$i][2], $this->options['heading_levels']) )
1174
+ $new_matches[] = $matches[$i];
1175
+ }
1176
+ $matches = $new_matches;
1177
+ }
1178
+
1179
  for ($i = 0; $i < count($matches); $i++) {
1180
+ // get anchor and add to find and replace arrays
1181
+ $anchor = $this->url_anchor_target( $matches[$i][0] );
1182
  $find[] = $matches[$i][0];
1183
  $replace[] = str_replace(
1184
  array(
1186
  '</h' . $matches[$i][2] . '>' // end of heading
1187
  ),
1188
  array(
1189
+ $matches[$i][1] . '<span id="' . $anchor . '">',
1190
  '</span></h' . $matches[$i][2] . '>'
1191
  ),
1192
  $matches[$i][0]
1194
 
1195
  // assemble flat list
1196
  if ( !$this->options['show_heirarchy'] ) {
1197
+ $items .= '<li><a href="#' . $anchor . '">';
1198
+ if ( $this->options['ordered_list'] ) $items .= count($replace) . ' ';
1199
  $items .= strip_tags($matches[$i][0]) . '</a></li>';
1200
  }
1201
  }
1202
+
1203
  // build a hierarchical toc?
1204
  // we could have tested for $items but that var can be quite large in some cases
1205
  if ( $this->options['show_heirarchy'] ) $items = $this->build_hierarchy( &$matches );
1206
+ }
1207
+ }
1208
+
1209
+ return $items;
1210
+ }
1211
+
1212
+
1213
+ /**
1214
+ * Returns true if the table of contents is eligible to be printed, false otherwise.
1215
+ */
1216
+ public function is_eligible()
1217
+ {
1218
+ global $post;
1219
+
1220
+ return (
1221
+ ( in_array(get_post_type($post), $this->options['auto_insert_post_types']) && $this->show_toc && !is_search() && !is_archive() && !is_front_page() ) ||
1222
+ ( $this->options['include_homepage'] && is_front_page() )
1223
+ );
1224
+ }
1225
+
1226
+
1227
+ function the_content( $content )
1228
+ {
1229
+ global $post;
1230
+ $items = $css_classes = $anchor = '';
1231
+ $custom_toc_position = strpos($content, '<!--TOC-->');
1232
+ $find = $replace = array();
1233
+
1234
+ if (
1235
+ $this->is_eligible() ||
1236
+ ( $custom_toc_position !== false ) // user specified toc to appear at a custom position
1237
+ ) {
1238
+ $items = $this->extract_headings( &$find, &$replace, $content );
1239
+
1240
+ // do we display the toc within the content or has the user opted
1241
+ // to only show it in the widget? if so, then we still need to
1242
+ // make the find/replace call to insert the anchors
1243
+ if ( $this->options['show_toc_in_widget_only'] ) {
1244
+ $content = $this->mb_find_replace($find, $replace, $content);
1245
+ }
1246
+ else {
1247
+
1248
  // wrapping css classes
1249
  switch( $this->options['wrapping'] ) {
1250
  case TOC_WRAPPING_LEFT:
1302
  if ( $custom_toc_position !== false ) {
1303
  $find[] = '<!--TOC-->';
1304
  $replace[] = $html;
1305
+ $content = $this->mb_find_replace($find, $replace, $content);
1306
  }
1307
  else {
1308
+ if ( count($find) > 0 ) {
1309
+ switch ( $this->options['position'] ) {
1310
+ case TOC_POSITION_TOP:
1311
+ $content = $html . $this->mb_find_replace($find, $replace, $content);
1312
+ break;
1313
+
1314
+ case TOC_POSITION_BOTTOM:
1315
+ $content = $this->mb_find_replace($find, $replace, $content) . $html;
1316
+ break;
1317
 
1318
+ case TOC_POSITION_BEFORE_FIRST_HEADING:
1319
+ default:
1320
+ $replace[0] = $html . $replace[0];
1321
+ $content = $this->mb_find_replace($find, $replace, $content);
1322
+ }
 
 
 
1323
  }
1324
  }
1325
  }
1328
  return $content;
1329
  }
1330
 
1331
+ } // end class
1332
+ endif;
1333
+
1334
+
1335
+
1336
+ if ( !class_exists( 'toc_widget' ) ) :
1337
+ class toc_widget extends WP_Widget {
1338
+
1339
+ function __construct()
1340
+ {
1341
+ $widget_options = array(
1342
+ 'classname' => 'toc_widget',
1343
+ 'description' => 'Display the table of contents in the sidebar with this widget'
1344
+ );
1345
+ $control_options = array(
1346
+ 'width' => 250,
1347
+ 'height' => 350,
1348
+ 'id_base' => 'toc-widget'
1349
+ );
1350
+ $this->WP_Widget( 'toc-widget', 'TOC+', $widget_options, $control_options );
1351
+ }
1352
+
1353
+
1354
+ /**
1355
+ * Widget output to the public
1356
+ */
1357
+ function widget( $args, $instance )
1358
+ {
1359
+ global $tic, $wp_query;
1360
+ $items = $custom_toc_position = '';
1361
+ $find = $replace = array();
1362
+
1363
+ $post = get_post( $wp_query->post->ID );
1364
+ $custom_toc_position = strpos( $post->post_content, '[toc]' ); // at this point, shortcodes haven't run yet so we can't search for <!--TOC-->
1365
+
1366
+ if (
1367
+ $tic->is_eligible() ||
1368
+ $custom_toc_position !== false
1369
+ ) {
1370
+
1371
+ $toc_options = $tic->get_options();
1372
+
1373
+ extract( $args );
1374
+
1375
+ $items = $tic->extract_headings( &$find, &$replace, $post->post_content );
1376
+ $title = apply_filters('widget_title', $instance['title'] );
1377
+ $hide_inline = $toc_options['show_toc_in_widget_only'];
1378
+
1379
+ if ( $items ) {
1380
+ // before widget (defined by themes)
1381
+ echo $before_widget;
1382
+
1383
+ // display the widget title if one was input (before and after defined by themes)
1384
+ if ( !$title ) $title = $toc_options['heading_text'];
1385
+ echo
1386
+ $before_title . $title . $after_title .
1387
+ '<ul class="toc_widget_list">' . $items . '</ul>'
1388
+ ;
1389
+
1390
+ // after widget (defined by themes)
1391
+ echo $after_widget;
1392
+ }
1393
+ }
1394
+ }
1395
+
1396
+
1397
+ /**
1398
+ * Update the widget settings
1399
+ */
1400
+ function update( $new_instance, $old_instance )
1401
+ {
1402
+ global $tic;
1403
+
1404
+ $instance = $old_instance;
1405
+
1406
+ // strip tags for title to remove HTML (important for text inputs)
1407
+ $instance['title'] = strip_tags( $new_instance['title'] );
1408
+
1409
+ // no need to strip tags for the following
1410
+ //$instance['hide_inline'] = $new_instance['hide_inline'];
1411
+ $tic->set_show_toc_in_widget_only( $new_instance['hide_inline'] );
1412
+
1413
+ return $instance;
1414
+ }
1415
+
1416
+
1417
+ /**
1418
+ * Displays the widget settings on the widget panel.
1419
+ */
1420
+ function form( $instance )
1421
+ {
1422
+ global $tic;
1423
+ $toc_options = $tic->get_options();
1424
+
1425
+ $defaults = array(
1426
+ 'title' => ''
1427
+ //'hide_inline' => $toc_options['show_toc_in_widget_only']
1428
+ );
1429
+ $instance = wp_parse_args( (array)$instance, $defaults );
1430
+
1431
+ ?>
1432
+ <p>
1433
+ <label for="<?php echo $this->get_field_id( 'title' ); ?>">Title:</label>
1434
+ <input type="text" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" style="width:100%;" />
1435
+ </p>
1436
+
1437
+ <p>
1438
+ <input class="checkbox" type="checkbox" <?php checked( $toc_options['show_toc_in_widget_only'], 1 ); ?> id="<?php echo $this->get_field_id( 'hide_inline' ); ?>" name="<?php echo $this->get_field_name( 'hide_inline' ); ?>" value="1" />
1439
+ <label for="<?php echo $this->get_field_id( 'hide_inline' ); ?>"> <?php _e('Show the table of contents only in the sidebar'); ?></label>
1440
+ </p>
1441
+ <?php
1442
+ }
1443
 
1444
  } // end class
1445
  endif;
1446
 
1447
 
1448
+
1449
  // do the magic
1450
  $tic = new toc();
1451