Ticket #14691: tags-with-commas.3.diff
File tags-with-commas.3.diff, 11.4 KB (added by , 11 years ago) |
---|
-
tests/qunit/index.html
13 13 <!-- Tested files --> 14 14 <script src="../../src/wp-includes/js/zxcvbn.min.js"></script> 15 15 <script src="../../src/wp-admin/js/password-strength-meter.js"></script> 16 <script src="../../src/wp-admin/js/post.js"></script> 16 17 17 18 <!-- Unit tests --> 18 19 <script src="wp-admin/js/password-strength-meter.js"></script> 20 <script src="wp-admin/js/post.js"></script> 19 21 20 22 </head> 21 23 <body> -
tests/qunit/wp-admin/js/post.js
1 var postL10n = { 2 comma: ',' 3 } 4 5 jQuery( function() { 6 module( 'post-tags-metabox' ); 7 8 // mock the tags div 9 var tagsDiv = jQuery( '<div />' ).addClass('tagsdiv').append( 10 jQuery( '<textarea>' ).val( 'tag1,tag2,"tag,with,comma"' ).addClass('the-tags') 11 ).append( 12 jQuery( '<div />' ).addClass('tagchecklist') 13 ); 14 15 test( "tags should be parsed from textarea return ['tag2', 'tag1']", function() { 16 17 tagBox.quickClicks( tagsDiv ) 18 19 ok( tagsDiv.data('tags').indexOf( 'tag2') > -1 ) 20 ok( tagsDiv.data('tags').indexOf( 'tag1') > -1 ) 21 ok( tagsDiv.data('tags').indexOf( 'tag,with,comma') > -1 ) 22 ok( tagsDiv.data('tags').length == 3 ) 23 }); 24 25 test( "DOM input elements should exist for each tag", function() { 26 ok( tagsDiv.find( 'input[value="tag1"]' ).length == 1, 'DOM element was not found for tag' ) 27 }) 28 29 test( "removing a tag should remove from tags data", function() { 30 tagBox.removeTag(tagsDiv, 'tag1') 31 ok( tagsDiv.data('tags').indexOf( 'tag1') == -1, 'Tag is still found after removing' ) 32 }) 33 34 test( "removing a tag should remove the tag DOM input element", function() { 35 ok( tagsDiv.find( 'input[value="tag1"]' ).length == 0, 'DOM element was still found for removed tag' ) 36 }) 37 38 test( "tags should be parsed from textarea using both quotes", function() { 39 40 tagsDiv.find( 'textarea' ).val('tag1,"tag,2",\'tag,3\'') 41 tagBox.quickClicks( tagsDiv ) 42 43 ok( tagsDiv.data('tags').indexOf( 'tag1') > -1 ) 44 ok( tagsDiv.data('tags').indexOf( 'tag,2') > -1 ) 45 ok( tagsDiv.data('tags').indexOf( 'tag,3') > -1 ) 46 ok( tagsDiv.data('tags').length == 3 ) 47 }); 48 49 test( "tags should be parsed from textarea when using an i18n comma", function() { 50 51 // test using a different comma (arabic comma) 52 postL10n.comma = "\u060C" 53 54 tagsDiv.find( 'textarea' ).val('tag1\u060Ctag2\u060C"tag\u060Cwith\u060Ccomma"') 55 tagBox.quickClicks( tagsDiv ) 56 57 ok( tagsDiv.data('tags').indexOf( 'tag2') > -1 ) 58 ok( tagsDiv.data('tags').indexOf( 'tag1') > -1 ) 59 ok( tagsDiv.data('tags').indexOf( 'tag\u060Cwith\u060Ccomma') > -1 ) 60 ok( tagsDiv.data('tags').length == 3 ) 61 }); 62 63 }); -
src/wp-includes/js/jquery/suggest.js
244 244 } else { 245 245 $currentVal = ""; 246 246 } 247 $input.val( $currentVal + $currentResult.text() + options.multipleSep); 247 248 if ( $currentResult.text().match( jQuery.trim( options.multipleSep ) ) ) 249 $input.val( $currentVal + '"' + $currentResult.text() + '"' + options.multipleSep); 250 else 251 $input.val( $currentVal + $currentResult.text() + options.multipleSep); 248 252 $input.focus(); 249 253 } else { 250 254 $input.val($currentResult.text()); -
src/wp-admin/includes/taxonomy.php
229 229 if ( is_wp_error($tags) ) 230 230 return $tags; 231 231 232 foreach ( $tags as $tag ) 233 $tag_names[] = $tag->name; 232 foreach ( $tags as $tag ) { 233 if ( strpos( $tag->name, ',' ) !== false ) 234 $tag_names[] = '"' . $tag->name . '"'; 235 else 236 $tag_names[] = $tag->name; 237 } 238 234 239 $tags_to_edit = join( ',', $tag_names ); 235 240 $tags_to_edit = esc_attr( $tags_to_edit ); 236 241 $tags_to_edit = apply_filters( 'terms_to_edit', $tags_to_edit, $taxonomy ); -
src/wp-admin/includes/meta-boxes.php
364 364 <div class="jaxtag"> 365 365 <div class="nojs-tags hide-if-js"> 366 366 <p><?php echo $taxonomy->labels->add_or_remove_items; ?></p> 367 <textarea name="<?php echo "tax_input[$tax_name]"; ?>" rows="3" cols="20" class="the-tags" id="tax-input-<?php echo $tax_name; ?>" <?php disabled( ! $user_can_assign_terms ); ?>><?php echo str_replace( ',', $comma . ' ', get_terms_to_edit( $post->ID, $tax_name )); // textarea_escaped by esc_attr() ?></textarea></div>367 <textarea name="<?php echo "tax_input[$tax_name]"; ?>" rows="3" cols="20" class="the-tags" id="tax-input-<?php echo $tax_name; ?>" <?php disabled( ! $user_can_assign_terms ); ?>><?php echo get_terms_to_edit( $post->ID, $tax_name ); // textarea_escaped by esc_attr() ?></textarea></div> 368 368 <?php if ( $user_can_assign_terms ) : ?> 369 369 <div class="ajaxtag hide-if-no-js"> 370 370 <label class="screen-reader-text" for="new-tag-<?php echo $tax_name; ?>"><?php echo $box['title']; ?></label> -
src/wp-admin/js/post.js
14 14 (function($){ 15 15 16 16 tagBox = { 17 clean : function(tags) {18 var comma = postL10n.comma;19 if ( ',' !== comma )20 tags = tags.replace(new RegExp(comma, 'g'), ',');21 tags = tags.replace(/\s*,\s*/g, ',').replace(/,+/g, ',').replace(/[,\s]+$/, '').replace(/^[,\s]+/, '');22 if ( ',' !== comma )23 tags = tags.replace(/,/g, comma);24 return tags;25 },26 17 27 parseTags : function(el) { 28 var id = el.id, num = id.split('-check-num-')[1], taxbox = $(el).closest('.tagsdiv'), 29 thetags = taxbox.find('.the-tags'), comma = postL10n.comma, 30 current_tags = thetags.val().split(comma), new_tags = []; 31 delete current_tags[num]; 18 quickClicks : function(el) { 19 20 var thetags = $('.the-tags', el); 21 var current_tags = this.getTagsFromString( thetags.val(), postL10n.comma ); 32 22 33 $.each( current_tags, function(key, val) { 34 val = $.trim(val); 35 if ( val ) { 36 new_tags.push(val); 37 } 38 }); 23 thetags.html(''); 24 $(el).data( 'tags',[]); 39 25 40 thetags.val( this.clean( new_tags.join(comma) ) ); 41 42 this.quickClicks(taxbox); 43 return false; 26 for (var i = current_tags.length - 1; i >= 0; i--) { 27 this.addTag( $(el), current_tags[i] ); 28 } 44 29 }, 45 30 46 quickClicks : function(el) { 47 var thetags = $('.the-tags', el), 48 tagchecklist = $('.tagchecklist', el), 49 id = $(el).attr('id'), 50 current_tags, disabled; 31 addTag: function( el, tag ) { 32 var span, xbutton, thetags = $('.the-tags', el), disabled, t = this; 51 33 52 if ( !thetags.length ) 34 tag = $.trim(tag) 35 36 if ( el.data( 'tags' ).indexOf( tag ) > -1 ) 53 37 return; 54 38 39 el.data( 'tags' ).push( tag ) 55 40 disabled = thetags.prop('disabled'); 56 41 57 current_tags = thetags.val().split(postL10n.comma); 58 tagchecklist.empty(); 42 // Create a new span, and ensure the text is properly escaped. 43 span = $('<span />').text( tag ); 44 span.append( jQuery( '<input type="hidden" name="' + thetags.attr('name') + '[]" />' ).val( tag ) ) 59 45 60 $.each( current_tags, function( key, val ) { 61 var span, xbutton; 46 // If tags editing isn't disabled, create the X button. 47 if ( ! disabled ) { 48 xbutton = $( '<a class="ntdelbutton">X</a>' ); 49 xbutton.click( function() { 50 t.removeTag(el, tag); 51 }); 62 52 63 val = $.trim( val ); 53 span.prepend(' ').prepend( xbutton ); 54 } 64 55 65 if ( ! val ) 66 return; 56 el.find('.tagchecklist').append(span); 67 57 68 // Create a new span, and ensure the text is properly escaped. 69 span = $('<span />').text( val ); 58 }, 70 59 71 // If tags editing isn't disabled, create the X button. 72 if ( ! disabled ) { 73 xbutton = $( '<a id="' + id + '-check-num-' + key + '" class="ntdelbutton">X</a>' ); 74 xbutton.click( function(){ tagBox.parseTags(this); }); 75 span.prepend(' ').prepend( xbutton ); 76 } 60 removeTag: function( el, tag ) { 77 61 78 // Append the span to the tag list. 79 tagchecklist.append( span ); 80 }); 62 el.find( '.tagchecklist input[value="' + tag + '"]').remove(); 63 delete el.data('tags')[el.data('tags').indexOf(tag)]; 81 64 }, 82 65 83 flushTags : function(el, a, f) { 84 a = a || false; 85 var tags = $('.the-tags', el), 86 newtag = $('input.newtag', el), 87 comma = postL10n.comma, 88 newtags, text; 66 getTagsFromString: function(tags_string, comma) { 89 67 90 text = a ? $(a).text() : newtag.val(); 91 tagsval = tags.val(); 92 newtags = tagsval ? tagsval + comma + text : text; 68 // pull out all quoted strings 69 var quoted_tags = tags_string.match( /("|')(.+?)\1/g ); 93 70 94 newtags = this.clean( newtags ); 95 newtags = array_unique_noempty( newtags.split(comma) ).join(comma); 96 tags.val(newtags); 97 this.quickClicks(el); 71 if ( quoted_tags ) { 72 for (var i = quoted_tags.length - 1; i >= 0; i--) { 73 tags_string = tags_string.replace( quoted_tags[i], '' ); 74 quoted_tags[i] = quoted_tags[i].substr( 1, quoted_tags[i].length - 2 ); 75 }; 76 } 98 77 99 if ( !a ) 100 newtag.val(''); 101 if ( 'undefined' == typeof(f) ) 102 newtag.focus(); 78 var tags = tags_string.split(comma); 103 79 104 return false; 80 if ( quoted_tags ) 81 return array_unique_noempty( quoted_tags.concat(tags) ); 82 83 return array_unique_noempty( tags ); 105 84 }, 106 85 86 submitAddTag: function(el) { 87 88 var newtag = $('input.newtag', el), 89 new_tags = this.getTagsFromString( newtag.val(), postL10n.comma ) 90 91 newtag.val(''); 92 93 for (var i = new_tags.length - 1; i >= 0; i--) { 94 this.addTag( $(el), new_tags[i] ); 95 } 96 }, 97 107 98 get : function(id) { 108 var tax = id.substr(id.indexOf('-')+1) ;99 var tax = id.substr(id.indexOf('-')+1), t = this; 109 100 110 101 $.post(ajaxurl, {'action':'get-tagcloud', 'tax':tax}, function(r, stat) { 111 102 if ( 0 == r || 'success' != stat ) … … 113 104 114 105 r = $('<p id="tagcloud-'+tax+'" class="the-tagcloud">'+r+'</p>'); 115 106 $('a', r).click(function(){ 116 t agBox.flushTags( $(this).closest('.inside').children('.tagsdiv'), this);107 t.addTag( $(this).closest('.inside').children('.tagsdiv'), $(this).text() ) 117 108 return false; 118 109 }); 119 110 … … 129 120 }); 130 121 131 122 $('input.tagadd', ajaxtag).click(function(){ 132 t. flushTags( $(this).closest('.tagsdiv') );123 t.submitAddTag( $(this).closest('.tagsdiv') ); 133 124 }); 134 125 135 126 $('div.taghint', ajaxtag).click(function(){ … … 143 134 $(this).parent().siblings('.taghint').css('visibility', 'hidden'); 144 135 }).keyup(function(e){ 145 136 if ( 13 == e.which ) { 146 tagBox. flushTags( $(this).closest('.tagsdiv') );137 tagBox.submitAddTag( $(this).closest('.tagsdiv') ); 147 138 return false; 148 139 } 149 140 }).keypress(function(e){ … … 159 150 // save tags on post save/publish 160 151 $('#post').submit(function(){ 161 152 $('div.tagsdiv').each( function() { 162 t agBox.flushTags(this, false, 1);153 t.submitAddTag($(this)); 163 154 }); 164 155 }); 165 156 … … 353 344 jQuery(document).ready( function($) { 354 345 var stamp, visibility, sticky = '', last = 0, co = $('#content'); 355 346 347 if ( typeof postboxes == 'undefined' ) 348 return 349 356 350 postboxes.add_postbox_toggles(pagenow); 357 351 358 352 // Post locks: contain focus inside the dialog. If the dialog is shown, focus the first item.