NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name CSSResolver // @namespace me.markh.cssresolver // @description Easily resolve the shortest css route to any element on the page. // @include * // @version 1 // @grant GM_setClipboard // @require http://code.jquery.com/jquery-1.11.2.min.js // ==/UserScript== this.$ = this.jQuery = jQuery.noConflict(true); if (!("contextMenu" in document.documentElement && "HTMLMenuItemElement" in window)) return; ; jQuery(function () { jQuery.fn.fcss = function (iselect, $that, depth) { depth = depth || 1; iselect = iselect || ['']; $that = $that || [null]; var selectors = []; var uniques = []; //if(depth > 5) return []; var k_combinations = function (set, k) { var i, j, combs, head, tailcombs; if (k > set.length || k <= 0) { return []; } if (k == set.length) { return [set]; } if (k == 1) { combs = []; for (i = 0; i < set.length; i++) { combs.push([set[i]]); } return combs; } // Assert {1 < k < set.length} combs = []; for (i = 0; i < set.length - k + 1; i++) { head = set.slice(i, i + 1); tailcombs = k_combinations(set.slice(i + 1), k - 1); for (j = 0; j < tailcombs.length; j++) { combs.push(head.concat(tailcombs[j])); } } return combs; } var combinations = function (set) { var k, i, combs, k_combs; combs = []; // Calculate all non-empty k-combinations for (k = 1; k <= set.length; k++) { k_combs = k_combinations(set, k); for (i = 0; i < k_combs.length; i++) { combs.push(k_combs[i]); } } return combs; } $(this).each(function () { var $this = $(this); for (var idx in this.attributes) { var attr = this.attributes[idx]; if (typeof(attr.value) != 'undefined') { if (attr.name.substr(0, 5) == 'data-' && (attr.name.substr(0, 15) !== 'data-validation' ) || (['name', 'id', 'type'].indexOf(attr.name) >= 0)) { selectors.push('[' + attr.name + '=\'' + attr.value + '\']'); } } } if(typeof(this.className)!=='undefined'){ var classes = this.className.split(' '); classes.forEach(function (cls) { if (cls.trim() !== '') selectors.push('.' + cls); }); } var combos = combinations(selectors); var unique = []; iselect.forEach(function (ctx) { combos.forEach(function (combo) { var strCombo = (combo.join('') + ' ' + ctx).trim(); var $combo = $(strCombo); if ($combo.length == 1) { //console.log({combo:$combo[0],that: $that[0],tthis:$this[0], c: ($that[0]===null)?$this[0]:$that[0]}); if ($combo[0] == (($that[0]===null)?$this[0]:$that[0])) { unique.push(strCombo); } } }); }); unique.sort(function (a, b) { return a.length - b.length; }); if (unique.length > 0) { uniques.push(unique); } else { if (['BODY', 'HTML'].indexOf(this.tagName) < 0) { uniques = $this.parent().fcss(combos, ($that[0]===null)? $this : $that, depth + 1); } } }); return uniques.length == 0 ? [] : (uniques.length > 1 ? uniques : uniques[0]); }; }); var body = document.body; body.addEventListener("contextmenu", initMenu, false); var menu = body.appendChild(document.createElement('menu')); menu.outerHTML = '<menu id="css-selector-menu" type="context">\ <menu id="css-selector-menu-label" label="CSS Selectors"></menu>\ </menu>'; function hello(val){ GM_setClipboard(val); } function initMenu(aEvent){ var node = aEvent.target; var selectors=$(node).fcss().splice(0,10); if(selectors.length > 0){ body.setAttribute('contextmenu','css-selector-menu'); $('#css-selector-menu-label').attr('label', 'CSS Selectors ('+selectors.length+')'); $('#css-selector-menu-label').children().remove(); selectors.forEach(function(selector){ var item=$('<menuitem>'); item.attr('label',selector); item.data('selector',selector); $('#css-selector-menu-label').append(item); item.on('click',function(){ hello(selector); }) }) }else{ body.removeAttribute('contextmenu'); } }