Comportements déroutant ...

Pour toutes les discussions javascript, jQuery et autres frameworks
Répondre
GeGaX
Messages : 26
Enregistré le : 20 févr. 2018, 21:56

Comportements déroutant ...

Message par GeGaX » 20 sept. 2018, 19:58

Bonjour,

J'ai, avec de l'aide, effectué quelques améliorations sur mon extension pour Google Chrome.

Je rencontre 2 soucis qui me dépassent complètement ...(Je vais détailler au maximum pour être sur de bien traduire ce que je rencontre)

# Fonctionnement OK avec Adblock / NOK sans Adblock.

-- Avec Adblock
Image

-- Sans Adblock
Image

J'ai identifié d'où vient mon problème ...

Voici un bout du code source de la page zezo (j'vais expliquer pourquoi je vous montre ça ensuite)
Image
[...]
Image

Je dois récupérer la valeur de la variable "scale" (1er screen du code source) puis je récupère les valeurs "left" et "top" (2nd screen du code source) pour calculer les positions GPS (longitude et latitude)

Dans mon code ça se traduit comme ceci
myscript.js

Code : Tout sélectionner

"use strict";

const pattern = /updi\(event,'([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}) ([A-Z]{3,4}).*(T[+-]{1}.*?[0-9]{1,}:[0-9]{2}).*<br>Distances:.*?([0-9]{1,}\.[0-9]{1,}nm)\/([0-9]{1,}\.[0-9]{1,}nm)<br><b>Wind:<\/b> ([0-9]*?.*) (.*? kt).*\(<b>TWA(.*?)<\/b>\)<br><b>Heading:<\/b>(.*?)<b>Sail:<\/b>(.*?)<br><b>Boat Speed:<\/b>(.*?)'/g
const points = [];

/**
 * Calculate latitude using the scale of the display and the css top property
 * @param top
 * @param scale
 * @returns {number}
 */
function getLatitude(top, scale) {
    return 90 - ((top + 2) / scale);
}

/**
 * Calculate longitude using the scale of the display and the css left property
 * @param left
 * @param scale
 * @returns {number}
 */
function getLongitude(left, scale) {
    if (((left + 2 / scale) >= -180) || ((left + 2 / scale) <= 180)) {
        return (left + 2) / scale;
    } else {
        return ((left  + 2) / scale) - 360;
    }
}

try {
    let textContent = document.scripts[1].textContent;
    let scale = /var scale = ([0-9]{1,3})/.exec(textContent)[1];
    console.log(scale);
         
    let layer = document.getElementById("dot_layer");
    Array.prototype.slice.call(layer.getElementsByTagName("img")).forEach(function (element) {
        let event = element.getAttribute("onmouseover");
        if (event !== null) {

            // Get the two css properties used to calculate both longitude and latitude
            let style = element.getAttribute("style");
            let cssProperties = style.split(";");
            let left = parseInt(cssProperties[1].split(":")[1].replace("px",""),10);
            let top =  parseInt(cssProperties[2].split(":")[1].replace("px",""),10);

            let match = pattern.exec(event);

            const date = match[1];
            const time = match[2];
            const timezone = match[3];
            const ttw = match[4];
            const dtw = match[5];
            const dtg = match[6];
            const twd = match[7];
            const tws = match[8];
            const twa = match[9];
            const btw = match[10];
            const sail = match[11];
            const stw = match[12];

            let race = document.title;

            points.push({
                race : race,
                longitude : getLongitude(left, scale),
                latitude : getLatitude(top, scale),
                date : date,
                time : time,
                timezone : timezone,
                ttw : ttw,
                dtw : dtw,
                dtg : dtg,
                twd : twd,
                tws : tws,
                twa : twa,
                btw : btw,
                sail : sail,
                stw : stw
            });
            pattern.lastIndex = 0;
        }
    });

    chrome.runtime.sendMessage(points);
} catch (e) {
    console.error(e);
    chrome.runtime.sendMessage([]);
}
Le soucis se situe à la récupération de la valeur "scale", si je la mets cette valeur "en dur" dans le code, l'extension fonctionne correctement avec ou sans Adblock ...
Qu'est ce que je fais de mal ? (C'est là que vous intervenez, j'espère ..., moi j'ai le cerveau en ébullition à force de chercher, modifier et autres ... je comprends pas ...)


# Scroll tableau et Checkbox Local Time
Une popup est limitée à 800px(width) x 600px(height) et comme le tableau peut être assez long, je "perds" l'affichage de la checkbox, le bouton GPX, la version et la zone où est généré le fichier GPX.
Je me suis dis qu'il serait top de mettre en place un scroll sur le tableau avec un "thead" fixe, c'est donc ce que j'ai fais.

Voici les screens avant la mise en place de ce "scroll"

-- Checkbox "Local Time" désactivée
Image
[...]
Image

-- Checkbox "Local Time" activée
Image
[...]
Image

Les colonnes "Date", "Time" et "TZ"(=TimeZone) s'affichent en convertissant du format UTC vers UTC+2 dans l'exemple.
En réalité les "Date", "Time" et "TZ" des instructions sont données en UTC, CET ou CEST. Avec la librairie moment-timezone.js, il est possible de convertir ces instructions en locale partout sur la planète.

-- Mise en place du scroll sur le tableau
popup.html

Code : Tout sélectionner

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" type="text/css" href="popup.css">
    </head>
    <style>

    </style>
    <body>
        <main>
            <div class="table-container">
                <div class="theader-fixe">
                </div>
                <div class="tbody-scroll">
                    <table>
                        <thead>
                            <tr>
                                <th>Date</th>
                                <th>Time</th>
                                <th title="Timezone">TZ</th>
                                <th>Position</th>
                                <th title="Time To Waypoint">TTW</th>
                                <th title="Distance To Waypoint">DTW</th>
                                <th title="Distance To Go">DTG</th>
                                <th title="True Wind Direction">TWD</th>
                                <th title="True Wind Speed">TWS</th>
                                <th title="True Wind Angle">TWA</th>
                                <th title="Bearing To Waypoint">BTW</th>
                                <th>Sail</th>
                                <th title="Speed Through Water">STW</th>
                                <th title="Average True Wind Angle">ATWA</th>
                                <th title="Average Bearing To Waypoint">ABTW</th>
                            </tr>
                        </thead>
                        <tbody id="pointsTable">
                        </tbody>
                    </table>
                </div>
                <br />
                <div id="localtimeDiv">
                    <input type="checkbox" id="localtime" tabindex="-1">
                    <label>Local Time</label>
                </div>
                <div id="versionDiv">
                    <label>Version</label>
                    <label id="version"></label>
                </div>
                <div id="gpxDiv">
                    <input class="cssButton" type="button" id="gpxExport" value=".GPX" tabindex="-1">
                </div>
                <textarea id="gpxOutput" rows="2" readonly tabindex="-1">...::: Click on GPX button for generate file :::...
Select All | Copy selection | Paste on your text editor | Save the file with the .gpx extension</textarea>
            </div>
        </main>
        <script src="bundle.js"></script>
        <script>"use strict";
        // réalisation et injection de la copie de la table
        var tableRef = document.querySelector(".tbody-scroll table");
        var headerFixe = document.querySelector(".theader-fixe");
        headerFixe.appendChild(tableRef.cloneNode(true));
        // ajustement hauteur de scroll propre
        var nbLigne = 27;
        if (nbLigne < tableRef.rows.length - 1) { // on ne tient pas compte du header
            var bodyScroll = document.querySelector(".tbody-scroll");
            var rect1 = tableRef.rows[0].getBoundingClientRect();
            var rect2 = tableRef.rows[nbLigne + 1].getBoundingClientRect();
            bodyScroll.style.height = (rect2.top - rect1.top) + "px";
        }
        // calcul pour réajustement
        var hEntete = tableRef.tHead.offsetHeight;
        // calcul largeur scroll-barre
        var w_1 = tableRef.offsetWidth;
        var w_2 = tableRef.parentNode.offsetWidth;
        // réajustement du header fixe
        headerFixe.style.height = hEntete + "px";
        headerFixe.style.width = "calc(100% - " + (w_2 - w_1) + "px)";
        // synchronisation des scrolls
        bodyScroll.onscroll = function () {
            tableClone.style.marginLeft = -this.scrollLeft + "px";
        }
        </script>
    </body>
</html>
Ce code me donne le même rendu que les 2 screens ci dessus, donc ça fonctionne pas (La checkbox "Local Time" fait son job, ça à son importance pour plus tard)

Comme ça fonctionne pas, je regarde ce que me dit la console, et là j'ai ceci
Image

Image

Je comprends que Google Chrome n'est pas fan de code JS dans le fichier html, je le modifie donc comme ceci
popup.html

Code : Tout sélectionner

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" type="text/css" href="popup.css">
    </head>
    <style>

    </style>
    <body>
        <main>
            <div class="table-container">
                <div class="theader-fixe">
                </div>
                <div class="tbody-scroll">
                    <table>
                        <thead>
                            <tr>
                                <th>Date</th>
                                <th>Time</th>
                                <th title="Timezone">TZ</th>
                                <th>Position</th>
                                <th title="Time To Waypoint">TTW</th>
                                <th title="Distance To Waypoint">DTW</th>
                                <th title="Distance To Go">DTG</th>
                                <th title="True Wind Direction">TWD</th>
                                <th title="True Wind Speed">TWS</th>
                                <th title="True Wind Angle">TWA</th>
                                <th title="Bearing To Waypoint">BTW</th>
                                <th>Sail</th>
                                <th title="Speed Through Water">STW</th>
                                <th title="Average True Wind Angle">ATWA</th>
                                <th title="Average Bearing To Waypoint">ABTW</th>
                            </tr>
                        </thead>
                        <tbody id="pointsTable">
                        </tbody>
                    </table>
                </div>
                <br />
                <div id="localtimeDiv">
                    <input type="checkbox" id="localtime" tabindex="-1">
                    <label>Local Time</label>
                </div>
                <div id="versionDiv">
                    <label>Version</label>
                    <label id="version"></label>
                </div>
                <div id="gpxDiv">
                    <input class="cssButton" type="button" id="gpxExport" value=".GPX" tabindex="-1">
                </div>
                <textarea id="gpxOutput" rows="2" readonly tabindex="-1">...::: Click on GPX button for generate file :::...
Select All | Copy selection | Paste on your text editor | Save the file with the .gpx extension</textarea>
            </div>
        </main>
        <script src="bundle.js"></script>
        <script src="resizeTables.js"></script>
    </body>
</html>
resizeTables.js

Code : Tout sélectionner

"use strict";
// réalisation et injection de la copie de la table
var tableRef = document.querySelector(".tbody-scroll table");
var headerFixe = document.querySelector(".theader-fixe");
headerFixe.appendChild(tableRef.cloneNode(true));
// ajustement hauteur de scroll propre
var nbLigne = 27;
if (nbLigne < tableRef.rows.length - 1) { // on ne tient pas compte du header
    var bodyScroll = document.querySelector(".tbody-scroll");
    var rect1 = tableRef.rows[0].getBoundingClientRect();
    var rect2 = tableRef.rows[nbLigne + 1].getBoundingClientRect();
    bodyScroll.style.height = (rect2.top - rect1.top) + "px";
}
// calcul pour réajustement
var hEntete = tableRef.tHead.offsetHeight;
// calcul largeur scroll-barre
var w_1 = tableRef.offsetWidth;
var w_2 = tableRef.parentNode.offsetWidth;
// réajustement du header fixe
headerFixe.style.height = hEntete + "px";
headerFixe.style.width = "calc(100% - " + (w_2 - w_1) + "px)";
// synchronisation des scrolls
bodyScroll.onscroll = function () {
    tableClone.style.marginLeft = -this.scrollLeft + "px";
}
-- Scroll tableau et Local Time désactivée
Image

Super, tout fonctionne c'était pas si compliqué !!! :D

-- Scroll tableau et Local Time activée
Image

Et là c'est le drame, "thead" a bien les colonnes qui se déplacent vers la droite car les valeurs de TZ sont passées de UTC à UTC+2 mais que pour "thead" ... les colonnes du tableau restent au "Date", "Time" et "TZ" de l'UTC l'affichage de la conversion ne se fait pas ... :shock:

Donc idem que pour le 1er point, qu'est ce que je fais de mal ? Ça aussi je comprends pas et j'espère que vous pourrez m'aiguiller ...


Merci d'avoir pris le temps de me lire, j'espère que vous saurez me donner des explications / corrections pour résoudre ces 2 points qui me dépassent et auxquels je comprends rien ...

Je mets une archive de l'extension complète, peut être que je me suis planté ailleurs ... le code concernant la mise en forme du tableau se trouve dans "bundle.js" et commence à la ligne 8280 (avant ce sont les librairies xml et moment-timezone).

Route zezo v3.1.zip

Au plaisir de vous lire ;)

GeGaX
Messages : 26
Enregistré le : 20 févr. 2018, 21:56

Re: Comportements déroutant ...

Message par GeGaX » 21 sept. 2018, 18:28

Je reviens sur un point, celui où je disais que Google Chrome n'aime pas du code JS sur un fichier html.

Enfaite il est possible de le faire sous réserve de le "déclarer" comme "safe" dans manifest.json

Pour ce faire il suffit de récupérer le ('sha256-XXX=') et de mettre ceci dans le manifest.json

Code : Tout sélectionner

{
    "manifest_version": 2,
    "name": "Route zezo.org v3.1",
    "description": "Extract route for MultiRaces",
    "version": "3.1",
    "page_action": {
        "default_icon": "icon.png",
        "default_popup": "popup.html"
    },
    "permissions": ["tabs","storage"],
    "content_scripts": [
        {
            "matches": ["http://*.zezo.org/*/chart.pl*"],
            "js": ["myscript.js"]
        }
    ],
    "content_security_policy": "script-src 'self' 'sha256-kbBt+geyuTGD4n894ScFEcsN+WQdV+N+IVcbKRMB9AQ='; object-src 'self'",
    "icons": {
        "16": "icon16.png",
        "48": "icon48.png",
        "128": "icon128.png"
    },
    "background": {
        "scripts": ["eventPage.js"]
    }
}
Quoi qu'il en soit les 2 méthodes :
# code dans popup.html + "content_security_policy": "script-src 'self' 'sha256-kbBt+geyuTGD4n894ScFEcsN+WQdV+N+IVcbKRMB9AQ='; object-src 'self'", dans manifest.json
OU
# code dans resizeTables.js et <script src="resizeTables.js"></script> dans popup.html

me donnent exactement le même comportement ... du coup je tourne en rond comme un poisson dans son bocal

Un coup de pouce serait le bienvenu ...
Merci

GeGaX
Messages : 26
Enregistré le : 20 févr. 2018, 21:56

Re: Comportements déroutant ...

Message par GeGaX » 25 sept. 2018, 22:35

Bonsoir,
Seul ce point reste à corriger

# Fonctionnement OK avec Adblock / NOK sans Adblock.

-- Avec Adblock
Image

-- Sans Adblock
Image

J'ai identifié d'où vient mon problème ...

Voici un bout du code source de la page zezo (j'vais expliquer pourquoi je vous montre ça ensuite)
Image
[...]
Image

Je dois récupérer la valeur de la variable "scale" (1er screen du code source) puis je récupère les valeurs "left" et "top" (2nd screen du code source) pour calculer les positions GPS (longitude et latitude)

Dans mon code ça se traduit comme ceci
myscript.js

Code : Tout sélectionner

"use strict";

const pattern = /updi\(event,'([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}) ([A-Z]{3,4}).*(T[+-]{1}.*?[0-9]{1,}:[0-9]{2}).*<br>Distances:.*?([0-9]{1,}\.[0-9]{1,}nm)\/([0-9]{1,}\.[0-9]{1,}nm)<br><b>Wind:<\/b> ([0-9]*?.*) (.*? kt).*\(<b>TWA(.*?)<\/b>\)<br><b>Heading:<\/b>(.*?)<b>Sail:<\/b>(.*?)<br><b>Boat Speed:<\/b>(.*?)'/g
const points = [];

/**
 * Calculate latitude using the scale of the display and the css top property
 * @param top
 * @param scale
 * @returns {number}
 */
function getLatitude(top, scale) {
    return 90 - ((top + 2) / scale);
}

/**
 * Calculate longitude using the scale of the display and the css left property
 * @param left
 * @param scale
 * @returns {number}
 */
function getLongitude(left, scale) {
    if (((left + 2 / scale) >= -180) || ((left + 2 / scale) <= 180)) {
        return (left + 2) / scale;
    } else {
        return ((left  + 2) / scale) - 360;
    }
}

try {
    let textContent = document.scripts[1].textContent;
    let scale = /var scale = ([0-9]{1,3})/.exec(textContent)[1];
    console.log(scale);
         
    let layer = document.getElementById("dot_layer");
    Array.prototype.slice.call(layer.getElementsByTagName("img")).forEach(function (element) {
        let event = element.getAttribute("onmouseover");
        if (event !== null) {

            // Get the two css properties used to calculate both longitude and latitude
            let style = element.getAttribute("style");
            let cssProperties = style.split(";");
            let left = parseInt(cssProperties[1].split(":")[1].replace("px",""),10);
            let top =  parseInt(cssProperties[2].split(":")[1].replace("px",""),10);

            let match = pattern.exec(event);

            const date = match[1];
            const time = match[2];
            const timezone = match[3];
            const ttw = match[4];
            const dtw = match[5];
            const dtg = match[6];
            const twd = match[7];
            const tws = match[8];
            const twa = match[9];
            const btw = match[10];
            const sail = match[11];
            const stw = match[12];

            let race = document.title;

            points.push({
                race : race,
                longitude : getLongitude(left, scale),
                latitude : getLatitude(top, scale),
                date : date,
                time : time,
                timezone : timezone,
                ttw : ttw,
                dtw : dtw,
                dtg : dtg,
                twd : twd,
                tws : tws,
                twa : twa,
                btw : btw,
                sail : sail,
                stw : stw
            });
            pattern.lastIndex = 0;
        }
    });

    chrome.runtime.sendMessage(points);
} catch (e) {
    console.error(e);
    chrome.runtime.sendMessage([]);
}
Le soucis se situe à la récupération de la valeur "scale", si je la mets cette valeur "en dur" dans le code, l'extension fonctionne correctement avec ou sans Adblock ...
Qu'est ce que je fais de mal ? (C'est là que vous intervenez, j'espère ..., moi j'ai le cerveau en ébullition à force de chercher, modifier et autres ... je comprends pas ...)
Je suis preneur de toutes pistes/méthodes pour résoudre ce "bug"
Merci

GeGaX
Messages : 26
Enregistré le : 20 févr. 2018, 21:56

Re: Comportements déroutant ...

Message par GeGaX » 26 sept. 2018, 23:05

Bonjour,
Je peux mieux définir le point concernant Adblock après plusieurs recherches.

Je suis confronté à un soucis lors de l'extraction d'une valeur contenue dans la balise <script> du code source.

Le soucis n'est pas lié à la valeur en elle même mais à une pub, et lorsque Adblock est activé, l'extraction se fait correctement comme le but est de pas pénaliser l'auteur du site je souhaite que ça fonctionne avec Adblock désactivé.

Je me suis aperçu, quand Adblock est désactivé, qu'il y a 2 fichiers avec le même nom et bien sur je "tape" sur le mauvais.

Image

Le fichier avec l'icône grise contient le code source celui en jaune contient quelque chose en rapport avec la pub qui s'affiche sur la page web.

Avec ce bout de code

Code : Tout sélectionner

[...]
try {
    let textContent = document.scripts[1].textContent;
    console.log(textContent);
    let scale = /var scale = ([0-9]{1,3})/.exec(textContent)[1];
    console.log(scale);
[...]
textContent est vide puisqu'il "tape" sur le fichier avec l'icône jaune, mais me retourne la valeur de scale quand il "tape" sur le fichier avec l'icône grise.

Pour palier à ça, j'aimerais mettre en place un "if (textContent === "") {...};" après "let textContent = ..." qui testerait si textContent est vide ou s'il trouve ses infos.
Mais je sais pas comment lui dire que s'il trouve rien, il faut qu'il aille chercher ça dans l'autre fichier (qui possède exactement le même nom)

Vous pourriez m'indiquer la méthode ?

Merci

GeGaX
Messages : 26
Enregistré le : 20 févr. 2018, 21:56

Re: Comportements déroutant ...

Message par GeGaX » 28 sept. 2018, 13:59

Résolu avec ce code

Code : Tout sélectionner

let scale;
for (const script of document.scripts) {
if(script.textContent.includes("var scale")){
scale = /var scale = ([0-9]{1,3})/.exec(script.textContent)[1];
break;
}
}

Répondre