48 votes

JavaScript : Inverser la couleur sur tous les éléments d'une page

Note : Je conserve une version actualisée du bookmarklet dans ma question qui fonctionne bien et qui est basée sur la réponse de Jacob. Si vous cherchez un bookmarklet à utiliser, utilisez celui-là. Voir la réponse fantastique de leosok si vous voulez juste quelque chose d'étonnant qui fonctionne sur chrome.

Je veux pouvoir inverser la couleur de tous les éléments d'une page avec un bookmarklet JavaScript. Je sais que pour inverser une couleur, il faut soustraire chacune des valeurs hexagonales RVB de 255(xFF), mais au-delà, je ne sais pas comment procéder.

Comment puis-je y parvenir ?

Utilisation de jQuery est acceptable, et il ne doit fonctionner que sur Chrome, mais s'il fonctionnait sur Firefox, ce serait un plus.

Ceci exclut les images - les couleurs de l'arrière-plan, du texte et des liens doivent toutes être inversées. En gros, tout ce qui tire sa couleur de CSS.

UPDATE Voici un bookmarklet mis à jour qui corrige le problème des éléments imbriqués et qui fonctionnera sur de nombreux sites différents (dont celui-ci).

UPDATE2 Ajout d'une prise en charge de la transparence, pour les éléments dont la couleur de fond par défaut est rgba(0, 0, 0, 0). Plus de sites devraient fonctionner maintenant avec la mise à jour.

javascript: (function ($) {
    function load_script(src, callback) {
        var s = document.createElement('script');
        s.src = src;
        s.onload = callback;
        document.getElementsByTagName('head')[0].appendChild(s);
    }

    function invertElement() {
        var colorProperties = ['color', 'background-color'];
        var color = null;
        for (var prop in colorProperties) {
            prop = colorProperties[prop];
            if (!$(this).css(prop)) continue;
            if ($(this).data(prop) != $(this).css(prop)) continue;

            if (($(this).css(prop) === 'rgba(0, 0, 0, 0)') || ($(this).css(prop) === 'transparent')) {
                if ($(this).is('body')) {
                    $(this).css(prop, 'black');
                    continue;
                } else {
                    continue;
                }
            }
            color = new RGBColor($(this).css(prop));
            if (color.ok) {
                $(this).css(prop, 'rgb(' + (255 - color.r) + ',' + (255 - color.g) + ',' + (255 - color.b) + ')');
            }
            color = null;
        }
    }

    function setColorData() {
        var colorProperties = ['color', 'background-color'];
        for (var prop in colorProperties) {
            prop = colorProperties[prop];
            $(this).data(prop, $(this).css(prop));
        }
    }

    function invertColors() {
        $(document).live('DOMNodeInserted', function(e) {
            var $toInvert = $(e.target).find('*').andSelf();
            $toInvert.each(setColorData);
            $toInvert.each(invertElement);
        });
        $('*').each(setColorData);
        $('*').each(invertElement);
        $('iframe').each(function () {
            $(this).contents().find('*').each(setColorData);
            $(this).contents().find('*').each(invertElement);
        });
    }
    load_script('http://www.phpied.com/files/rgbcolor/rgbcolor.js', function () {
        if (!window.jQuery) load_script('https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js', invertColors);
        else invertColors();
    });

})(jQuery);

Maintenant, il fonctionne avec la plupart des sites que j'ai essayés. Les images d'arrière-plan peuvent toutefois poser un problème.

0 votes

Apparemment, il n'est pas possible de mettre des commentaires en ligne dans un bookmarklet car ils sont convertis en une seule ligne.

0 votes

J'ai supprimé le commentaire qui cassait le bookmarklet, et maintenant il suffit de faire $('*') pour la sélection de tous les éléments de sorte qu'il inclut maintenant l'élément <html> (qui peut apparemment avoir une couleur de fond).

0 votes

Il est préférable d'écrire un auto-réponse que de continuer à éditer le message original comme ça. Je me rends compte que c'est un wiki communautaire maintenant, mais cela fait toujours un fil de discussion maladroit pour obtenir des informations - les réponses devraient aller dans le champ "réponses" afin qu'elles puissent être votées et évaluées sur leurs propres mérites.

70voto

Jacob Relkin Points 90729

Tout d'abord, prenez l'impressionnant RGBColor classe aquí .

C'est parti :

Exemple de jsFiddle

//set up color properties to iterate through
var colorProperties = ['color', 'background-color'];

//iterate through every element in reverse order...
$("*").get().reverse().each(function() {
    var color = null;

    for (var prop in colorProperties) {
        prop = colorProperties[prop];

        //if we can't find this property or it's null, continue
        if (!$(this).css(prop)) continue; 

        //create RGBColor object
        color = new RGBColor($(this).css(prop));

        if (color.ok) { 
            //good to go, let's build up this RGB baby!
            //subtract each color component from 255
            $(this).css(prop, 'rgb(' + (255 - color.r) + ', ' + (255 - color.g) + ', ' + (255 - color.b) + ')');
        }
        color = null; //some cleanup
    }
});

Capture d'écran :

alt text

EDIT : Voici un bookmarklet que vous pouvez maintenant copier-coller dans votre navigateur ( http://jsfiddle.net/F7HqS/1/ )

javascript:function load_script(src,callback){var s=document.createElement('script');s.src=src;s.onload=callback;document.getElementsByTagName('head')[0].appendChild(s);}function invertColors(){var colorProperties=['color','background-color'];$('*').each(function(){var color=null;for(var prop in colorProperties){prop=colorProperties[prop];if(!$(this).css(prop))continue;color=new RGBColor($(this).css(prop));if(color.ok){$(this).css(prop,'rgb('+(255-color.r)+','+(255-color.g)+','+(255-color.b)+')');}color=null;}});}load_script('http://www.phpied.com/files/rgbcolor/rgbcolor.js',function(){if(!window.jQuery)load_script('https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js',invertColors);else invertColors();});

1 votes

+1 C'est très bien, mais j'ai du mal à le transformer en bookmarklet.

1 votes

@Muhd Voir ma réponse mise à jour, il suffit de saisir ce code et de le coller dans la barre d'adresse d'un navigateur avec javascript:

1 votes

C'est super cool ! Cependant, lorsqu'il est utilisé sur cette page, il n'inverse pas correctement le texte de ma question ou de votre réponse. Je me demande pourquoi.

47voto

leosok Points 83

Ma solution semble fonctionner uniquement pour Chrome pour le moment, mais elle inverse tout (y compris les images et les iframes) comme on le voit ici :

enter image description here

De plus, il ne fait pas appel à des bibliothèques externes et est très simple : il suffit d'ajouter un bouton -webkit-filter: invert(100%) à la html -sélecteur.

javascript: (
function () { 
// the css we are going to inject
var css = 'html {-webkit-filter: invert(100%);' +
    '-moz-filter: invert(100%);' + 
    '-o-filter: invert(100%);' + 
    '-ms-filter: invert(100%); }',

head = document.getElementsByTagName('head')[0],
style = document.createElement('style');

// a hack, so you can "invert back" clicking the bookmarklet again
if (!window.counter) { window.counter = 1;} else  { window.counter ++;
if (window.counter % 2 == 0) { var css ='html {-webkit-filter: invert(0%); -moz-filter:    invert(0%); -o-filter: invert(0%); -ms-filter: invert(0%); }'}
 };

style.type = 'text/css';
if (style.styleSheet){
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}

//injecting the css to the head
head.appendChild(style);
}());

Voici le violon : http://jsfiddle.net/nikita_turing/jVKw6/3/ avec le bookmarklet inclus. Si quelqu'un a une idée sur la façon de le faire fonctionner pour Firefox (SVG-Filters ?), allez-y !

1 votes

J'ai trouvé une solution pour Firefox. Je l'ai ajoutée à votre code. Bricolez ici : jsfiddle.net/jVKw6/4

1 votes

Et voici un code complet qui fonctionne aussi bien sur IE que sur Firefox ! jsfiddle.net/jVKw6/8

1 votes

@Renanlf J'ai créé un bookmarklet avec votre code JSFiddle, mais rien ne se passe. Veuillez m'aider.

3voto

Zig Mandel Points 6161

J'ai nettoyé les commentaires d'une des réponses (par leosok) ci-dessus, de sorte qu'il fonctionnera comme un bookmarklet dans chrome. Notez que cette solution est plus efficace que le point culminant actuel ici, plus il fonctionne même si le html change après que vous exécutez le script.

javascript:(function () { 
    var css = 'html {-webkit-filter: invert(100%);' + '-moz-filter: invert(100%);' + '-o-filter: invert(100%);' + '-ms-filter: invert(100%); }';
    var head = document.getElementsByTagName('head')[0];
    var style = document.createElement('style');
    if (!window.counter) { 
        window.counter = 1;
    } else { 
        window.counter++;
        if (window.counter % 2 == 0) { 
            var css = 'html {-webkit-filter: invert(0%); -moz-filter: invert(0%); -o-filter: invert(0%); -ms-filter: invert(0%); }'
        } 
    }
    style.type = 'text/css';
    if (style.styleSheet) {
        style.styleSheet.cssText = css;
    } else {
        style.appendChild(document.createTextNode(css));
    }
    head.appendChild(style);
}());

Une ligne pour le bookmarklet. créez un bookmark, puis modifiez l'url en ceci : javascript:(function () { var css = 'html {-webkit-filter: invert(100%);' + '-moz-filter: invert(100%);' + '-o-filter: invert(100%);' + '-ms-filter: invert(100%); }'; var head = document.getElementsByTagName('head')[0]; var style = document.createElement('style'); if (!window.counter) { window.counter = 1; } else { window.counter++; if (window.counter % 2 == 0) { var css = 'html {-webkit-filter: invert(0%); -moz-filter: invert(0%); -o-filter: invert(0%); -ms-filter: invert(0%); }' } } style.type = 'text/css'; if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } head.appendChild(style); }());

0 votes

Voir mon commentaire ci-dessus que j'ai posté dans la réponse acceptée. J'ai même posté des captures d'écran en utilisant le bookmarklet que vous avez posté comme filtre d'inversion et en effectuant une fermeture complète et un rechargement entre chacune d'entre elles en utilisant la page d'accueil du site LifeHacker comme exemple, comme vous pouvez le voir, seule la solution qui produit une page qui est un tant soit peu lisible, et qui a l'air plutôt bonne, est celle qui utilise la classe RGBcolor de Stoyan.

2voto

astryk Points 148

La réponse acceptée est tout à fait correcte, avec un petit défaut. Chaque fois que vous basculez l'inversion, cela ajoute une AUTRE balise de style à l'en-tête. Faites plutôt ceci

  // the css we are going to inject
  let css = 'html {-webkit-filter: invert(100%);' +
    '-moz-filter: invert(100%);' +
    '-o-filter: invert(100%);' +
    '-ms-filter: invert(100%); }';

  let head = $('head')[0];
  let invertStyle = $('#invert')[0];

  if (invertStyle) {
    head.removeChild(invertStyle);
  } else {
    let style = document.createElement('style');

    style.type = 'text/css';
    style.id = 'invert';
    if (style.styleSheet){
      style.styleSheet.cssText = css;
    } else {
      style.appendChild(document.createTextNode(css));
    }

    //injecting the css to the head
    head.appendChild(style);
  }

De cette façon, il vous suffit d'enlever la balise si vous voulez annuler votre inversion. Ça marche bien !

0 votes

Tout d'abord, vous avez absolument tort de dire que la réponse acceptée est correcte. J'ai même posté des captures d'écran dans les commentaires ci-dessus pour montrer à quel point elle est incorrecte. Cette mise à jour postée ici produit malheureusement exactement les mêmes résultats totalement illisibles et horribles qui inversent simplement toutes les images incluses, mais en manquent certaines et ne sont généralement pas utilisables, alors que des années plus tard, la classe RGBcolor de Stoyan produit toujours des résultats très acceptables, et répond également toujours à l'exigence de la question originale de l'OP d'EXCLURE les images - même après plusieurs années de changements de normes, etc !

1voto

i_grok Points 258

Je me suis dit que ce serait amusant d'essayer d'inverser les images. Il n'a pas fallu longtemps pour trouver une bibliothèque Javascript appropriée pour l'édition d'images : http://www.pixastic.com/lib/

Vous ne pouvez probablement pas charger toute cette bibliothèque dans un bookmarklet, mais si vous l'hébergez vous-même, vous pouvez ajouter quelque chose comme ceci à la fin du bookmarklet (après invertColors) :

load_script('http://www.example.com/pixastic.invert.js', function () {$('img').each(function() {try{$(this).pixastic("invert");} catch(e) {}})})

Je pense qu'il est utile de noter que si votre objectif est de rendre noir une page à fond blanc (ou vice versa), il est préférable d'utiliser quelque chose de plus simple.

Je viens d'essayer le bookmarklet de Jacob et je l'ai comparé à une version plus naïve que j'ai trouvée sur les forums de support de Google : http://www.google.com/support/forum/p/Chrome/thread?tid=26affebdd0da12d9&hl=en

L'inversion de Jacob semble fonctionner moins fréquemment et prend un peu plus de temps sur les grandes pages. Je pense que je vais finir par utiliser la version naïve plus fréquemment.

0 votes

Il serait plus utile si vous pouviez l'appliquer aux images d'arrière-plan.

0 votes

Et je pense que ma version actualisée du marque-page de Jacob est bien meilleure que celle que vous avez citée (surtout parce qu'elle préserve la variété des couleurs).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X