Showing posts with label Extensions. Show all posts
Showing posts with label Extensions. Show all posts

Monday, October 31, 2011

Get All indexOf From An Array - Array.allIndexOf()

This array function is an extension of Array.indexOf(), if it exists, and will return all indexes of the search element. It's named allIndexOf(). This code extends javascript and does not require jQuery. It is designed to work in older versions of IE as well, albeit a tiny bit slower.

Originally if you wanted the second instance of a search element, you'd have to call "indexOf" twice. The second time with the starting index of the first result (plus one), or once with a guessed starting index. This should simplify the process for getting any or all of the indexes.

/*
Array.allIndexOf(searchElement)
  Array [Array] - the array to search within for the searchElement
  searchElement [String] - the desired element with which to find starting indexes
*/
(function(){
  Array.prototype.allIndexOf = function(searchElement) {
    if (this === null) { return [-1]; }
    var len = this.length,
    hasIndexOf = Array.prototype.indexOf, // you know, because of IE
    i = (hasIndexOf) ? this.indexOf(searchElement) : 0,
    n,
    indx = 0,
    result = [];
    if (len === 0 || i === -1) { return [-1]; }
    if (hasIndexOf) {
      // Array.indexOf does exist
      for (n = 0; n <= len; n++) {
        i = this.indexOf(searchElement, indx);
        if (i !== -1) {
          indx = i + 1;
          result.push(i);
        } else {
          return result;
        }
      }
      return result;
    } else {
    // Array.indexOf doesn't exist
      for (n = 0; n <= len; n++) {
        if (this[n] === searchElement) {
          result.push(n);
        }
      }
      return (result.length > 0) ? result : [-1];
    }
  };
})();
Use it as follows:
var s = ["red","green","blue","red","yellow","blue","green","purple","red"];
s.allIndexOf("r"); // result [ -1 ]
s.allIndexOf("red"); // result [ 0,3,8 ]
s.allIndexOf("blue"); // result [ 2,5 ]
Try out your own strings in the demo below or full screen.

Get All indexOf From A Search String - String.allIndexOf()

This string function is an extension of String.indexOf() and will return all indexes of a search string. It's named allIndexOf. This code extends javascript and does not require jQuery.

Originally if you wanted the second instance of a search string, you'd have to call "indexOf" twice. The second time with the starting index of the first result (plus one), or once with a guessed starting index. This should simplify the process for getting any or all of the indexes. And yes, I woke up with a strange urge to write this function LOL.

/*
String.allIndexOf(searchstring, ignoreCase)
  String [String] - the string to search within for the searchstring
  searchstring [String] - the desired string with which to find starting indexes
  ignoreCase [Boolean] - set to true to make both the string and searchstring case insensitive
*/
(function(){
  String.prototype.allIndexOf = function(string, ignoreCase) {
    if (this === null) { return [-1]; }
    var t = (ignoreCase) ? this.toLowerCase() : this,
    s = (ignoreCase) ? string.toString().toLowerCase() : string.toString(),
    i = this.indexOf(s),
    len = this.length,
    n,
    indx = 0,
    result = [];
    if (len === 0 || i === -1) { return [i]; } // "".indexOf("") is 0
    for (n = 0; n <= len; n++) {
      i = t.indexOf(s, indx);
      if (i !== -1) {
        indx = i + 1;
        result.push(i);
      } else {
        return result;
      }
    }
    return result;
  }
})();
Use it as follows:
var s = "The rain in Spain stays mainly in the plain";
s.allIndexOf("ain"); // result [ 5,14,25,40 ]
s.allIndexOf("the"); // result [ 34 ]
s.allIndexOf("THE", true); // result [ 0,34 ]
Try out your own strings in the demo below or full screen.

Thursday, October 20, 2011

jQuery Rename Attribute (renameAttr)

I woke up this morning with a very unusual urge to make a rename attribute function for jQuery. I know, right.. that's just too weird! So after messing around with it, I decided that it needed to update the data as well. Here is the code I ended up with:

jQuery.fn.extend({
  renameAttr: function( name, newName, removeData ) {
    var val;
    return this.each(function() {
      val = jQuery.attr( this, name );
      jQuery.attr( this, newName, val );
      jQuery.removeAttr( this, name );
      // remove original data
      if (removeData !== false){
        jQuery.removeData( this, name.replace('data-','') );
      }
    });
  }
});

Use it as follows:
// $(selector).renameAttr(original-attr, new-attr, removeData);

// removeData flag is true by default
$('#test').renameAttr('data-test', 'data-new' );

// removeData flag set to false will not remove the
// .data("test") value
$('#test').renameAttr('data-test', 'data-new', false );

Basically, it adds a new attribute with the same value and removes the old one. It automatically removes the jQuery data for the original attribute unless you set the "removeData" flag to false. Check out this demo

Thursday, May 13, 2010

jQuery Selectors - Adding a :contains exact match


This post has been updated to make these selectors work with jQuery 1.8


I have included a demo to show you the utility of two selectors that you can easily add to your jQuery library.

The standard ":contains()" selector matches the contents of the element in a case sensitive manner. But it is limited and there have been many times that I've needed to exactly match the contents of an element, so I threw together these two useful selectors.

In this demo, you can see the difference when you see what "td:contains(2)" matches - doing so will match all table cells that contain a "2" including dates that begin and end with "2" and the event titles that contains a "2".

":containsExact()" will grab the innerHTML from the element (the date span in this case) and exactly match it. I made this selector case-insensitve so you won't have to worry about the text case.

":containsExactCase()" will grab the innerHTML from the element (the event span in this case) and exactly match the contents in a case-sensitive manner. Try both "Vacation" and "vacation" in the demo.

":containsRegex()" will grab the innerHTML from the element (also the event span in this case) and use regex to match the contents in either a case-sensitive or insensitive manner (depending on the regex "i" flag). NOTE: because of the way jQuery 1.8 handles the text inside this selector, if parenthesis are used, the text must be wrapped in quotes, e.g. /(red|blue|yellow)/gi will now cause an error, so wrap it in quotes "/(red|blue|yellow)/gi" see the example below:


To include these selectors, just add the following code outside of any $(document).ready(function(){...})
$.extend( $.expr[":"], {
 containsExact: $.expr.createPseudo ?
  $.expr.createPseudo(function(text) {
   return function(elem) {
    return $.trim(elem.innerHTML.toLowerCase()) === text.toLowerCase();
   };
  }) :
  // support: jQuery <1.8
  function(elem, i, match) {
   return $.trim(elem.innerHTML.toLowerCase()) === match[3].toLowerCase();
  },

 containsExactCase: $.expr.createPseudo ?
  $.expr.createPseudo(function(text) {
   return function(elem) {
    return $.trim(elem.innerHTML) === text;
   };
  }) :
  // support: jQuery <1.8
  function(elem, i, match) {
   return $.trim(elem.innerHTML) === match[3];
  },

 containsRegex: $.expr.createPseudo ?
  $.expr.createPseudo(function(text) {
   var reg = /^\/((?:\\\/|[^\/]) )\/([mig]{0,3})$/.exec(text);
   return function(elem) {
    return RegExp(reg[1], reg[2]).test($.trim(elem.innerHTML));
   };
  }) :
  // support: jQuery <1.8
  function(elem, i, match) {
   var reg = /^\/((?:\\\/|[^\/]) )\/([mig]{0,3})$/.exec(match[3]);
   return RegExp(reg[1], reg[2]).test($.trim(elem.innerHTML));
  }

});