matches-selector.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /**
  2. * matchesSelector v1.0.3
  3. * matchesSelector( element, '.selector' )
  4. * MIT license
  5. */
  6. /*jshint browser: true, strict: true, undef: true, unused: true */
  7. /*global define: false, module: false */
  8. ( function( ElemProto ) {
  9. 'use strict';
  10. var matchesMethod = ( function() {
  11. // check for the standard method name first
  12. if ( ElemProto.matches ) {
  13. return 'matches';
  14. }
  15. // check un-prefixed
  16. if ( ElemProto.matchesSelector ) {
  17. return 'matchesSelector';
  18. }
  19. // check vendor prefixes
  20. var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
  21. for ( var i=0, len = prefixes.length; i < len; i++ ) {
  22. var prefix = prefixes[i];
  23. var method = prefix + 'MatchesSelector';
  24. if ( ElemProto[ method ] ) {
  25. return method;
  26. }
  27. }
  28. })();
  29. // ----- match ----- //
  30. function match( elem, selector ) {
  31. return elem[ matchesMethod ]( selector );
  32. }
  33. // ----- appendToFragment ----- //
  34. function checkParent( elem ) {
  35. // not needed if already has parent
  36. if ( elem.parentNode ) {
  37. return;
  38. }
  39. var fragment = document.createDocumentFragment();
  40. fragment.appendChild( elem );
  41. }
  42. // ----- query ----- //
  43. // fall back to using QSA
  44. // thx @jonathantneal https://gist.github.com/3062955
  45. function query( elem, selector ) {
  46. // append to fragment if no parent
  47. checkParent( elem );
  48. // match elem with all selected elems of parent
  49. var elems = elem.parentNode.querySelectorAll( selector );
  50. for ( var i=0, len = elems.length; i < len; i++ ) {
  51. // return true if match
  52. if ( elems[i] === elem ) {
  53. return true;
  54. }
  55. }
  56. // otherwise return false
  57. return false;
  58. }
  59. // ----- matchChild ----- //
  60. function matchChild( elem, selector ) {
  61. checkParent( elem );
  62. return match( elem, selector );
  63. }
  64. // ----- matchesSelector ----- //
  65. var matchesSelector;
  66. if ( matchesMethod ) {
  67. // IE9 supports matchesSelector, but doesn't work on orphaned elems
  68. // check for that
  69. var div = document.createElement('div');
  70. var supportsOrphans = match( div, 'div' );
  71. matchesSelector = supportsOrphans ? match : matchChild;
  72. } else {
  73. matchesSelector = query;
  74. }
  75. // transport
  76. if ( typeof define === 'function' && define.amd ) {
  77. // AMD
  78. define( function() {
  79. return matchesSelector;
  80. });
  81. } else if ( typeof exports === 'object' ) {
  82. module.exports = matchesSelector;
  83. }
  84. else {
  85. // browser global
  86. window.matchesSelector = matchesSelector;
  87. }
  88. })( Element.prototype );