$.fn.textOptions(options)

by Laurens Maneschijn

HTML

<pre class="intro">
Experimental different implementation of $.text() :

<b>$.textOptions( [obj] ) :</b>
- if <code>obj.filter</code> given:
  if <code>typeof obj.filter === 'function'</code>
    Only return text of (child) elements that return true for given function.
    (e.g. <code>function(text, textnode, parentnode, childidx){ return $(parentnode).is('a,b'); }</code>)
  else:
    Only return text of (child) elements that pass this jQuery selector filter.
    (i.e. <code>$(el).is(obj.filter) === true</code> )
- if <code>obj.nodecallback</code> given:
  For each (child) element; apply this function to modify text from this element.
  (e.g. give $.trim to trim whitespace from each element text value)

<b>$.textFilter( filter, nodecallback ) :</b>
  shorthand for: <code>$.textOptions( {filter:filter, nodecallback:nodecallback });</code>
</pre>

<table>
<thead>
  <tr>
    <th>col a</th>
    <th>col b</th>
  </tr>
</thead>
<tbody>
  <tr>
    <td>td 1 1</td>
    <td>td 1 2 aaa <b>bold</b> bbb <a href="#">anch</a> ccc </td>
  </tr>
  <tr>
    <td>td 2 1</td>
    <td>td 2 2 nested test:
      <x>
        x-before
        <y>
          y-before
          <z>z</z>
          y-after
        </y>
        x-after
      </x>
    </td>
  </tr>
  <tr>
    <td>td 3 1</td>
    <td>td 3 2
      <select>
        <option>option:1</option>
        <option selected>option:2</option>
        <option>option:3</option>
      </select>
    </td>
  </tr>
</tbody>
</table>

<button id="cleartests">Clear tests</button>
<button id="runtests">Run demo tests</button>
<button id="runtest">Run test:</button><br>
<textarea id="runtestcode">
$('table').textOptions( {
  // option : value ,  ...
} );</textarea>
<pre>$('table').textOptions( {
 // filter : function(text, textnode, parentnode, childidx){ return $(parentnode).is('a,b'); },
 // filter : 'a,b',
 // nodecallback : function(text, textnode, parentnode, childidx){return text;},
 // nodecallback : $.trim,
 // trim : true,
 // separator :...

CSS

* { line-height: 1;}
table { border-collapse: collapse; }
table thead tr th,
table tbody tr td {
  border: 1px solid #ddd;
}
table tbody tr td * { display:inline-block;margin:1px;padding:1px;border:1px dotted #ddd;}

.test,
.test pre {
  display: block;
  margin: 2px;
  padding: 2px;
  border: 1px solid #ddd;
}
.test{ margin-bottom:10px; }
.code {
  border: 1px solid #ddd;
  background-color:#eee;
}
.result {
  border: 1px solid #ddd;
  background-color:#eee;
}

textarea { width:100%; height:60px; }
code {
  display: inline-block;
  padding: 1px;
  margin: 2px;
  font-family: monospace;
  background-color: rgba(128, 128, 128, 0.2);
  outline: 1px dotted rgba(128, 128, 128, 0.5);
}
.intro {
  display: inline-block;
  margin: 5px;
  padding: 5px;
  background-color: rgba(255,255,255, 0.9);
}

JavaScript

(function($){
	if(!$ || ! $.fn || ! $.fn.jquery){
		return alert('$.fn.jquery missing');
	}

	function getTextOptions( elems , options) {
		var ret = "", elem;
		options = options || {};

		for ( var i = 0; elems[i]; i++ ) {
			elem = elems[i];
			var is_comment_node = elem.nodeType === 8;
			var is_text_node    = elem.nodeType === 3;
			var is_cdata_node   = elem.nodeType === 4;

			if ( is_comment_node ) {
				continue;
			}else if ( is_text_node || is_cdata_node ) {
				var elemp = elem.parentNode;

				// apply filters; if parentNode of textnode does not match filters, skip this textnode:
				if(options.no_unselected_option){
					if(elemp.tagName == 'OPTION' && !elemp.selected){
						continue;
					}
				}
				if ( $.isFunction(options.filter) ) {
					if ( ! options.filter.call(this, elem.nodeValue, elem, elemp, i) ){
						continue;
					}
				}else if ( options.filter ) {
					if( ! $(elemp).is(options.filter)){
						continue;
					}
				}

				// output per textnode handling:
        var sep = '', newtext = elem.nodeValue;
				if ( $.isFunction(options.nodecallback) ) {
          newtext = options.nodecallback.call(this, elem.nodeValue, elem, elemp, i);
        }
        if(options.trim){
          newtext = $.trim(newtext);
        }
        if(options.separator){
          sep = options.separator;
          if(options.no_empty_separator && $.trim(newtext) === '' ){
          	sep = '';
          }
        }
        ret += sep + newtext;

			} else {
				ret += getTextOptions( elem.childNodes , options );
			}
		}

		return ret;
	};

	$.getTextOptions = getTextOptions;

	$.fn.extend({
		textOptions: function( options ) {
			return $.getTextOptions( this , options );
		},
		textFiltered: function( filter, nodecallback ) {
			return $.getTextOptions( this , {filter:filter, nodecallback:nodecallback} );
		}
	});
})(window.$ || window.jQuery)




////////////////////
// run test...