<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[13086] trunk: Convert Terms page to use WP_Ajax_Response(),
  hierarchical terms will now appear under their parent OR have the parents prefixed
 , Terms will be removed from tag cloud/parent list upon deletion,
  Terms will be added to Parent list in correct order upon ajax creation,
  Errors on term creation flow back to UI, clean up _tag_row()
  alternate class handling,
  Show None text in Category dropdown if empty and show_if_empty = true.</title>
</head>
<body>

<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.wordpress.org/changeset/13086">13086</a></dd>
<dt>Author</dt> <dd>dd32</dd>
<dt>Date</dt> <dd>2010-02-13 05:40:47 +0000 (Sat, 13 Feb 2010)</dd>
</dl>

<h3>Log Message</h3>
<pre>Convert Terms page to use WP_Ajax_Response(), hierarchical terms will now appear under their parent OR have the parents prefixed, Terms will be removed from tag cloud/parent list upon deletion, Terms will be added to Parent list in correct order upon ajax creation, Errors on term creation flow back to UI, clean up _tag_row() alternate class handling, Show None text in Category dropdown if empty and show_if_empty = true. See <a href="http://trac.wordpress.org/ticket/11838">#11838</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpadminadminajaxphp">trunk/wp-admin/admin-ajax.php</a></li>
<li><a href="#trunkwpadminincludestemplatephp">trunk/wp-admin/includes/template.php</a></li>
<li><a href="#trunkwpadminjstagsdevjs">trunk/wp-admin/js/tags.dev.js</a></li>
<li><a href="#trunkwpadminjstagsjs">trunk/wp-admin/js/tags.js</a></li>
<li><a href="#trunkwpincludescategorytemplatephp">trunk/wp-includes/category-template.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpadminadminajaxphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/admin-ajax.php (13085 => 13086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/admin-ajax.php        2010-02-13 05:35:47 UTC (rev 13085)
+++ trunk/wp-admin/admin-ajax.php        2010-02-13 05:40:47 UTC (rev 13086)
</span><span class="lines">@@ -538,30 +538,51 @@
</span><span class="cx">         $taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag';
</span><span class="cx">         $tax = get_taxonomy($taxonomy);
</span><span class="cx"> 
</span><ins>+        $x = new WP_Ajax_Response();
+
</ins><span class="cx">         if ( !current_user_can( $tax-&gt;edit_cap ) )
</span><span class="cx">                 die('-1');
</span><span class="cx"> 
</span><span class="cx">         $tag = wp_insert_term($_POST['tag-name'], $taxonomy, $_POST );
</span><span class="cx"> 
</span><span class="cx">         if ( !$tag || is_wp_error($tag) || (!$tag = get_term( $tag['term_id'], $taxonomy )) ) {
</span><del>-                echo '&lt;div class=&quot;error&quot;&gt;&lt;p&gt;' . __('An error has occured. Please reload the page and try again.') . '&lt;/p&gt;&lt;/div&gt;';
-                exit;
</del><ins>+                $message = __('An error has occured. Please reload the page and try again.');
+                if ( is_wp_error($tag) &amp;&amp; $tag-&gt;get_error_message() )
+                        $message = $tag-&gt;get_error_message();
+
+                $x-&gt;add( array(
+                        'what' =&gt; 'taxonomy',
+                        'data' =&gt; new WP_Error('error', $message )
+                ) );
+                $x-&gt;send();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         $level = 0;
</span><span class="cx">         $tag_full_name = false;
</span><ins>+        $tag_full_name = $tag-&gt;name;
</ins><span class="cx">         if ( is_taxonomy_hierarchical($taxonomy) ) {
</span><del>-                $tag_full_name = $tag-&gt;name;
</del><span class="cx">                 $_tag = $tag;
</span><del>-                while ( $_tag-&gt;parent ) {
</del><ins>+                while ( $_tag-&gt;parent  ) {
</ins><span class="cx">                         $_tag = get_term( $_tag-&gt;parent, $taxonomy );
</span><span class="cx">                         $tag_full_name = $_tag-&gt;name . ' &amp;#8212; ' . $tag_full_name;
</span><span class="cx">                         $level++;
</span><span class="cx">                 }
</span><del>-                $tag_full_name = esc_attr($tag_full_name);
</del><span class="cx">         }
</span><del>-        echo _tag_row( $tag, $level, $tag_full_name, $taxonomy );
-        exit;
</del><ins>+        if ( is_taxonomy_hierarchical($taxonomy) )
+                $noparents = _tag_row( $tag, $level, $taxonomy );
+        $tag-&gt;name = $tag_full_name;
+        $parents = _tag_row( $tag, 0, $taxonomy);
+
+        $x-&gt;add( array(
+                'what' =&gt; 'taxonomy',
+                'supplemental' =&gt; compact('parents', 'noparents')
+                ) );
+        $x-&gt;add( array(
+                'what' =&gt; 'term',
+                'position' =&gt; $level,
+                'supplemental' =&gt; get_term( $tag-&gt;term_id, $taxonomy, ARRAY_A ) //Refetch as $tag has been contaminated by the full name.
+                ) );
+        $x-&gt;send();
</ins><span class="cx">         break;
</span><span class="cx"> case 'get-tagcloud' :
</span><span class="cx">         if ( !current_user_can( 'edit_posts' ) )
</span></span></pre></div>
<a id="trunkwpadminincludestemplatephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/template.php (13085 => 13086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/template.php        2010-02-13 05:35:47 UTC (rev 13085)
+++ trunk/wp-admin/includes/template.php        2010-02-13 05:40:47 UTC (rev 13086)
</span><span class="lines">@@ -482,7 +482,10 @@
</span><span class="cx">  * @param unknown_type $class
</span><span class="cx">  * @return unknown
</span><span class="cx">  */
</span><del>-function _tag_row( $tag, $level, $class = '', $taxonomy = 'post_tag' ) {
</del><ins>+function _tag_row( $tag, $level, $taxonomy = 'post_tag' ) {
+                static $row_class = '';
+                $row_class = ($row_class == '' ? ' class=&quot;alternate&quot;' : '');
+
</ins><span class="cx">                 $count = number_format_i18n( $tag-&gt;count );
</span><span class="cx">                 if ( 'post_tag' == $taxonomy )
</span><span class="cx">                         $tagsel = 'tag';
</span><span class="lines">@@ -496,13 +499,14 @@
</span><span class="cx">                 $count = ( $count &gt; 0 ) ? &quot;&lt;a href='edit.php?$tagsel=$tag-&gt;slug'&gt;$count&lt;/a&gt;&quot; : $count;
</span><span class="cx"> 
</span><span class="cx">                 $pad = str_repeat( '&amp;#8212; ', max(0, $level) );
</span><del>-                $name = apply_filters( 'term_name', $pad . ' ' . $tag-&gt;name );
</del><ins>+                $name = apply_filters( 'term_name', $pad . ' ' . $tag-&gt;name, $tag );
</ins><span class="cx">                 $qe_data = get_term($tag-&gt;term_id, $taxonomy, object, 'edit');
</span><span class="cx">                 $edit_link = &quot;edit-tags.php?action=edit&amp;amp;taxonomy=$taxonomy&amp;amp;tag_ID=$tag-&gt;term_id&quot;;
</span><span class="cx"> 
</span><span class="cx">                 $out = '';
</span><del>-                $out .= '&lt;tr id=&quot;tag-' . $tag-&gt;term_id . '&quot;' . $class . '&gt;';
</del><ins>+                $out .= '&lt;tr id=&quot;tag-' . $tag-&gt;term_id . '&quot;' . $row_class . '&gt;';
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">                 $columns = get_column_headers('edit-tags');
</span><span class="cx">                 $hidden = get_hidden_columns('edit-tags');
</span><span class="cx">                 $default_term = get_option('default_' . $taxonomy);
</span><span class="lines">@@ -607,12 +611,12 @@
</span><span class="cx">                 else
</span><span class="cx">                         $children = _get_term_hierarchy($taxonomy);
</span><span class="cx"> 
</span><del>-                // Some funky recursion to get the job done is contained within, Skip it for non-hierarchical taxonomies for performance sake
</del><ins>+                // Some funky recursion to get the job done(Paging &amp; parents mainly) is contained within, Skip it for non-hierarchical taxonomies for performance sake
</ins><span class="cx">                 $out .= _term_rows($taxonomy, $terms, $children, $page, $pagesize, $count);
</span><span class="cx">         } else {
</span><span class="cx">                 $terms = get_terms( $taxonomy, $args );
</span><span class="cx">                 foreach( $terms as $term )
</span><del>-                        $out .= _tag_row( $term, 0, ++$count % 2 ? ' class=&quot;alternate&quot;' : '', $taxonomy );
</del><ins>+                        $out .= _tag_row( $term, 0, $taxonomy );
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         echo $out;
</span><span class="lines">@@ -648,21 +652,20 @@
</span><span class="cx">                         unset($parent_ids);
</span><span class="cx"> 
</span><span class="cx">                         $num_parents = count($my_parents);
</span><del>-                        $count -= $num_parents; // Do not include parents in the per-page count, This is due to paging issues with unknown numbers of rows.
</del><span class="cx">                         while ( $my_parent = array_pop($my_parents) ) {
</span><del>-                                $output .=  &quot;\t&quot; . _tag_row( $my_parent, $level - $num_parents, ++$count % 2 ? ' class=&quot;alternate&quot;' : '', $taxonomy );
</del><ins>+                                $output .=  &quot;\t&quot; . _tag_row( $my_parent, $level - $num_parents, $taxonomy );
</ins><span class="cx">                                 $num_parents--;
</span><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 if ( $count &gt;= $start )
</span><del>-                        $output .= &quot;\t&quot; . _tag_row( $term, $level, ++$count % 2 ? ' class=&quot;alternate&quot;' : '', $taxonomy );
-                else
-                        ++$count;
</del><ins>+                        $output .= &quot;\t&quot; . _tag_row( $term, $level, $taxonomy );
</ins><span class="cx"> 
</span><ins>+                ++$count;
+
</ins><span class="cx">                 unset($terms[$key]);
</span><span class="cx"> 
</span><del>-                if ( isset($children[$term-&gt;term_id]) )
</del><ins>+                if ( isset($children[$term-&gt;term_id]) &amp;&amp; empty($_GET['s']) )
</ins><span class="cx">                         $output .= _term_rows( $taxonomy, $terms, $children, $page, $per_page, $count, $term-&gt;term_id, $level + 1 );
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkwpadminjstagsdevjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/js/tags.dev.js (13085 => 13086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/js/tags.dev.js        2010-02-13 05:35:47 UTC (rev 13085)
+++ trunk/wp-admin/js/tags.dev.js        2010-02-13 05:40:47 UTC (rev 13086)
</span><span class="lines">@@ -10,6 +10,9 @@
</span><span class="cx">                                 if ( '1' == r ) {
</span><span class="cx">                                         $('#ajax-response').empty();
</span><span class="cx">                                         tr.fadeOut('normal', function(){ tr.remove(); });
</span><ins>+                                        // Remove the term from the parent box and tag cloud
+                                        $('select#parent option[value=' + data.match(/tag_ID=(\d+)/)[1] + ']').remove();
+                                        $('a.tag-link-' + data.match(/tag_ID=(\d+)/)[1]).remove();
</ins><span class="cx">                                 } else if ( '-1' == r ) {
</span><span class="cx">                                         $('#ajax-response').empty().append('&lt;div class=&quot;error&quot;&gt;&lt;p&gt;' + tagsl10n.noPerm + '&lt;/p&gt;&lt;/div&gt;');
</span><span class="cx">                                         tr.children().css('backgroundColor', '');
</span><span class="lines">@@ -30,17 +33,31 @@
</span><span class="cx">                         return false;
</span><span class="cx"> 
</span><span class="cx">                 $.post(ajaxurl, $('#addtag').serialize(), function(r){
</span><del>-                        if ( r.indexOf('&lt;div class=&quot;error&quot;') === 0 ) {
-                                $('#ajax-response').append(r);
-                        } else {
-                                $('#ajax-response').empty();
-                                var parent = form.find('select#parent').val();
-                                if ( parent &gt; 0 &amp;&amp; $('#tag-' + parent ).length &gt; 0 ) // If the parent exists on this page, insert it below. Else insert it at the top of the list.
-                                        $('#the-list #tag-' + parent).after(r);
-                                else
-                                        $('#the-list').prepend(r);
-                                $('input[type=&quot;text&quot;]:visible, textarea:visible', form).val('');
</del><ins>+                   $('#ajax-response').empty();
+                        var res = wpAjax.parseAjaxResponse(r, 'ajax-response');
+                        if ( ! res )
+                                return;
+
+                        var parent = form.find('select#parent').val();        
+
+                        if ( parent &gt; 0 &amp;&amp; $('#tag-' + parent ).length &gt; 0 ) // If the parent exists on this page, insert it below. Else insert it at the top of the list.
+                                $('#the-list #tag-' + parent).after( res.responses[0].supplemental['noparents'] ); // As the parent exists, Insert the version with - - - prefixed
+                        else
+                                $('#the-list').prepend( res.responses[0].supplemental['parents'] ); // As the parent is not visible, Insert the version with Parent - Child - ThisTerm
+
+                        if ( form.find('select#parent') ) {
+                                // Parents field exists, Add new term to the list.
+                                var term = res.responses[1].supplemental;
+
+                                // Create an indent for the Parent field
+                                var indent = '';
+                                for ( var i = 0; i &lt; res.responses[1].position; i++ )
+                                        indent += '&amp;nbsp;&amp;nbsp;&amp;nbsp;';
+
+                                form.find('select#parent option:selected').after('&lt;option value=&quot;' + term['term_id'] + '&quot;&gt;' + indent + term['name'] + '&lt;/option&gt;');
</ins><span class="cx">                         }
</span><ins>+
+                        $('input[type=&quot;text&quot;]:visible, textarea:visible', form).val('');
</ins><span class="cx">                 });
</span><span class="cx"> 
</span><span class="cx">                 return false;
</span></span></pre></div>
<a id="trunkwpadminjstagsjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/js/tags.js (13085 => 13086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/js/tags.js        2010-02-13 05:35:47 UTC (rev 13085)
+++ trunk/wp-admin/js/tags.js        2010-02-13 05:40:47 UTC (rev 13086)
</span><span class="lines">@@ -1 +1 @@
</span><del>-jQuery(document).ready(function($){$(&quot;.delete-tag&quot;).live(&quot;click&quot;,function(e){var t=$(this),tr=t.parents(&quot;tr&quot;),r=true,data;if(&quot;undefined&quot;!=showNotice){r=showNotice.warn()}if(r){data=t.attr(&quot;href&quot;).replace(/[^?]*\?/,&quot;&quot;).replace(/action=delete/,&quot;action=delete-tag&quot;);$.post(ajaxurl,data,function(r){if(&quot;1&quot;==r){$(&quot;#ajax-response&quot;).empty();tr.fadeOut(&quot;normal&quot;,function(){tr.remove()})}else{if(&quot;-1&quot;==r){$(&quot;#ajax-response&quot;).empty().append('&lt;div class=&quot;error&quot;&gt;&lt;p&gt;'+tagsl10n.noPerm+&quot;&lt;/p&gt;&lt;/div&gt;&quot;);tr.children().css(&quot;backgroundColor&quot;,&quot;&quot;)}else{$(&quot;#ajax-response&quot;).empty().append('&lt;div class=&quot;error&quot;&gt;&lt;p&gt;'+tagsl10n.broken+&quot;&lt;/p&gt;&lt;/div&gt;&quot;);tr.children().css(&quot;backgroundColor&quot;,&quot;&quot;)}}});tr.children().css(&quot;backgroundColor&quot;,&quot;#f33&quot;)}return false});$(&quot;#submit&quot;).click(function(){var form=$(this).parents(&quot;form&quot;);if(!validateForm(form)){return false}$.post(ajaxurl,$(&quot;#addtag&quot;).serialize(),function(r){if(r.indexOf('&lt;div class=&quot;error&quot;')===0){$(&quot;#ajax-response&quot;).append(r)}else{$(&quot;#ajax-response&quot;).empty();var parent=form.find(&quot;select#parent&quot;).val();if(parent&gt;0&amp;&amp;$(&quot;#tag-&quot;+parent).length&gt;0){$(&quot;#the-list #tag-&quot;+parent).after(r)}else{$(&quot;#the-list&quot;).prepend(r)}$('input[type=&quot;text&quot;]:visible, textarea:visible',form).val(&quot;&quot;)}});return false})});
</del><span class="cx">\ No newline at end of file
</span><ins>+jQuery(document).ready(function($){$(&quot;.delete-tag&quot;).live(&quot;click&quot;,function(e){var t=$(this),tr=t.parents(&quot;tr&quot;),r=true,data;if(&quot;undefined&quot;!=showNotice){r=showNotice.warn()}if(r){data=t.attr(&quot;href&quot;).replace(/[^?]*\?/,&quot;&quot;).replace(/action=delete/,&quot;action=delete-tag&quot;);$.post(ajaxurl,data,function(r){if(&quot;1&quot;==r){$(&quot;#ajax-response&quot;).empty();tr.fadeOut(&quot;normal&quot;,function(){tr.remove()});$(&quot;select#parent option[value=&quot;+data.match(/tag_ID=(\d+)/)[1]+&quot;]&quot;).remove();$(&quot;a.tag-link-&quot;+data.match(/tag_ID=(\d+)/)[1]).remove()}else{if(&quot;-1&quot;==r){$(&quot;#ajax-response&quot;).empty().append('&lt;div class=&quot;error&quot;&gt;&lt;p&gt;'+tagsl10n.noPerm+&quot;&lt;/p&gt;&lt;/div&gt;&quot;);tr.children().css(&quot;backgroundColor&quot;,&quot;&quot;)}else{$(&quot;#ajax-response&quot;).empty().append('&lt;div class=&quot;error&quot;&gt;&lt;p&gt;'+tagsl10n.broken+&quot;&lt;/p&gt;&lt;/div&gt;&quot;);tr.children().css(&quot;backgroundColor&quot;,&quot;&quot;)}}});tr.children().css(&quot;backgroundColor&quot;,&quot;#f33&quot;)}return false});$(&quot;#submit&quot;).click(function(){var form=$(this).parents(&quot;form&quot;);if(!validateForm(form)){return false}$.post(ajaxurl,$(&quot;#addtag&quot;).serialize(),function(r){$(&quot;#ajax-response&quot;).empty();var res=wpAjax.parseAjaxResponse(r,&quot;ajax-response&quot;);if(!res){return}var parent=form.find(&quot;select#parent&quot;).val();if(parent&gt;0&amp;&amp;$(&quot;#tag-&quot;+parent).length&gt;0){$(&quot;#the-list #tag-&quot;+parent).after(res.responses[0].supplemental.noparents)}else{$(&quot;#the-list&quot;).prepend(res.responses[0].supplemental.parents)}if(form.find(&quot;select#parent&quot;)){var term=res.responses[1].supplemental;var indent=&quot;&quot;;for(var i=0;i&lt;res.responses[1].position;i++){indent+=&quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;}form.find(&quot;select#parent option:selected&quot;).after('&lt;option value=&quot;'+term.term_id+'&quot;&gt;'+indent+term.name+&quot;&lt;/option&gt;&quot;)}$('input[type=&quot;text&quot;]:visible, textarea:visible',form).val(&quot;&quot;)});return false})});
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludescategorytemplatephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/category-template.php (13085 => 13086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/category-template.php        2010-02-13 05:35:47 UTC (rev 13085)
+++ trunk/wp-includes/category-template.php        2010-02-13 05:40:47 UTC (rev 13086)
</span><span class="lines">@@ -364,6 +364,12 @@
</span><span class="cx">                 $output = &quot;&lt;select name='$name' id='$name' class='$class' $tab_index_attribute&gt;\n&quot;;
</span><span class="cx">         else
</span><span class="cx">                 $output = '';
</span><ins>+        
+        if ( empty($categories) &amp;&amp; ! $r['hide_if_empty'] &amp;&amp; !empty($show_option_none) ) {
+                $show_option_none = apply_filters( 'list_cats', $show_option_none );
+                $output .= &quot;\t&lt;option value='-1' selected='selected'&gt;$show_option_none&lt;/option&gt;\n&quot;;
+        }
+        
</ins><span class="cx">         if ( ! empty( $categories ) ) {
</span><span class="cx"> 
</span><span class="cx">                 if ( $show_option_all ) {
</span></span></pre>
</div>
</div>

</body>
</html>