IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Texte personnalisé en fonction des paramètres d'URL ?


Sujet :

JavaScript

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Responsable marketing opérationnel
    Inscrit en
    Novembre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Responsable marketing opérationnel
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2014
    Messages : 8
    Points : 1
    Points
    1
    Par défaut Texte personnalisé en fonction des paramètres d'URL ?
    bonjour à tous,
    je ne sais pas développer, mais j'ai quelques notions basiques, alors merci de votre indulgence pour mon premier message

    ce que je voudrais faire est simple, mais assez cool :

    j'ai trouvé ce code ici pour remplacer du texte HTML avec du javascript :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <h1 id="header">Georges</h1>
            <script>
              var element = document.getElementById("header");
              element.innerHTML = "Adrien";
            </script>
    A la place du element.innerHTML = "Adrien", j'aimerais définir une variable "nom", que l'URL contienne la valeur, je ne sais pas si je suis clair...
    ...autrement dit, j'aimerais que le texte du H1 soit remplacé par une valeur contenue dans une variable "nom" présente dans l'URL, par exemple http://www.mondomaine.com/?nom=Adrien

    Est ce que c'est possible avec Javascript, comment modifier le code svp ?

    ca m'aiderait beaucoup !

    Adrien

  2. #2
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Voilà une petite fonction pour récupérer un paramètre d'URL:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    function getURLParameter(name) {    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
        var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
            results = regex.exec(location.search);
        return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
    }
    Pour l'utiliser ensuite, c'est très simple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    element.innerHTML = getURLParameter("nom");
    One Web to rule them all

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Responsable marketing opérationnel
    Inscrit en
    Novembre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Responsable marketing opérationnel
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2014
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    mais...c'est génial !

    merci infiniment Sylvain.


    je n'aurais jamais cru trouver si vite la solution grâce à ce forum

    bon week end !
    Adrien

  4. #4
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 122
    Points
    44 122
    Par défaut
    Bonjour,
    @SylvainPV : a mettre en complément dans la FAQ.

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Responsable marketing opérationnel
    Inscrit en
    Novembre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Responsable marketing opérationnel
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2014
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Bonjour à tous,

    un petit complément suite à l'utilisation de cette fonction. Ca fonctionne très bien, mais avec un paragraphe entier dans la variable (attention juste aux caractères spéciaux, certains ne passent pas le caractère '%').

    Le scénario pour lequel j'utilise la fonction est celui-là :

    - je fournis un lien vers une page A à un utilisateur. Le lien contient des variables, et la page insèrera ces variables dans le contenu, grâce à la super fonction de SylvainPV.

    Maintenant, si l'utilisateur navigue et clique sur une page B, les variables ne sont malheureusement pas "emmenées avec" et donc, plus moyen d'avoir un contenu personnalisé...

    Sauriez-vous s'il y a un moyen de faire cela ?

    J'ai très peu de liens internes car le site ne fait que 4 pages, peut-etre en insérant les variables dans l'attibut href des liens ??

    Merci encore, c'est déjà super comme cela.
    Adrien

  6. #6
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    Une version plus évoluée
    utilisée par ExtJS elle reste aisément compréhensible pour s'en inspirer.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    function getFromQueryString (queryString, recursive) {
            var parts = queryString.replace(/^\?/, '').split('&'),
                object = {},
                temp, components, name, value, i, ln,
                part, j, subLn, matchedKeys, matchedName,
                keys, key, nextKey;
     
            for (i = 0, ln = parts.length; i < ln; i++) {
                part = parts[i];
     
                if (part.length > 0) {
                    components = part.split('=');
                    name = decodeURIComponent(components[0]);
                    value = (components[1] !== undefined) ? decodeURIComponent(components[1]) : '';
     
                    if (!recursive) {
                        if (object.hasOwnProperty(name)) {
                            if (!Ext.isArray(object[name])) {
                                object[name] = [object[name]];
                            }
     
                            object[name].push(value);
                        }
                        else {
                            object[name] = value;
                        }
                    }
                    else {
                        matchedKeys = name.match(/(\[):?([^\]]*)\]/g);
                        matchedName = name.match(/^([^\[]+)/);
     
                        //<debug error>
                        if (!matchedName) {
                            throw new Error('[getFromQueryString] Malformed query string given, failed parsing name from "' + part + '"');
                        }
                        //</debug>
     
                        name = matchedName[0];
                        keys = [];
     
                        if (matchedKeys === null) {
                            object[name] = value;
                            continue;
                        }
     
                        for (j = 0, subLn = matchedKeys.length; j < subLn; j++) {
                            key = matchedKeys[j];
                            key = (key.length === 2) ? '' : key.substring(1, key.length - 1);
                            keys.push(key);
                        }
     
                        keys.unshift(name);
     
                        temp = object;
     
                        for (j = 0, subLn = keys.length; j < subLn; j++) {
                            key = keys[j];
     
                            if (j === subLn - 1) {
                                if (Ext.isArray(temp) && key === '') {
                                    temp.push(value);
                                }
                                else {
                                    temp[key] = value;
                                }
                            }
                            else {
                                if (temp[key] === undefined || typeof temp[key] === 'string') {
                                    nextKey = keys[j+1];
     
                                    temp[key] = (Ext.isNumeric(nextKey) || nextKey === '') ? [] : {};
                                }
     
                                temp = temp[key];
                            }
                        }
                    }
                }
            }
     
            return object;
        }
    A+JYT

  7. #7
    Rédacteur/Modérateur

    Avatar de SpaceFrog
    Homme Profil pro
    Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Inscrit en
    Mars 2002
    Messages
    39 637
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2002
    Messages : 39 637
    Points : 66 658
    Points
    66 658
    Billets dans le blog
    1
    Ma page Developpez - Mon Blog Developpez
    Président du CCMPTP (Comité Contre le Mot "Problème" dans les Titres de Posts)
    Deux règles du succès: 1) Ne communiquez jamais à quelqu'un tout votre savoir...
    Votre post est résolu ? Alors n'oubliez pas le Tag

    Venez sur le Chat de Développez !

  8. #8
    Nouveau Candidat au Club
    Homme Profil pro
    Responsable marketing opérationnel
    Inscrit en
    Novembre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Responsable marketing opérationnel
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2014
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    @sekaijin @SpaceFrog : bonjour, un grand Merci pour votre aide. désolé pour ne pas avoir regardé dans la FAQ.

    POurriez vous me dire comment utiliser cette fonctions @sekaikin ou ce script @spacefrog dans les liens svp ?

    je ne connais pas la syntaxe, et suis un complet newbie...sorry.


    si dans une url du type : www.monsite.fr/?var1=value1&?var2=value2

    je cherche à transformer un lien vers
    www.monsite.fr/destination.html
    en
    http://www.monsite.fr/destination.ht...1&?var2=value2


    a quoi devrait ressembler le lien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <a href="destination.html/?getFromQueryString (var1, value1)">Lien</a>
    ou

    ... ?

    avec le script de la FAQ, je vois encore moins mais je sens que c'est facile pour qui a le savoir....

  9. #9
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    J'ai l'impression que tu vas dans la mauvaise direction. Si tu as plusieurs variables JavaScript à partager entre tes pages, est-ce qu'il ne faudrait pas faire ta navigation en AJAX ?
    One Web to rule them all

  10. #10
    Nouveau Candidat au Club
    Homme Profil pro
    Responsable marketing opérationnel
    Inscrit en
    Novembre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Responsable marketing opérationnel
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2014
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    @SylvainPV : Merci de soulever la question..

    j'ai pensé à JS d'abord parce que j'ai vu un script JS qui se rapprochait de mon besoin, et parce que j'ai déjà inséré des scripts JS (sans forcément en comprendre le contenu)

    Là, mon besoin concerne vraiment un mini-site de 4 pages pour faire un CV et une lettre de motivation avec des variables pour personnaliser.

    Avec ton script, j'arrive a vraiment bien personnaliser la page sur laquelle atterit le destinataire.
    Mais après je ne maitrise pas.

    Qu'est ce qui est le plus simple à faire ? modifier les quelques liens de mes pages avec les scripts proposés par sekaijin et SpaceFrog ? ou passer en Ajax ?

    Merci
    Adrien

  11. #11
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    intégré à ExtJS depuis la version 4
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Ext.Object.fromQueryString("foo=1&bar=2"); // returns {foo: '1', bar: '2'}
    Ext.Object.fromQueryString("foo=&bar=2"); // returns {foo: null, bar: '2'}
    Ext.Object.fromQueryString("some%20price=%24300"); // returns {'some price': '$300'}
    Ext.Object.fromQueryString("colors=red&colors=green&colors=blue"); // returns {colors: ['red', 'green', 'blue']}
     
    Ext.Object.fromQueryString(
        "username=Jacky&"+
        "dateOfBirth[day]=1&dateOfBirth[month]=2&dateOfBirth[year]=1911&"+
        "hobbies[0]=coding&hobbies[1]=eating&hobbies[2]=sleeping&"+
        "hobbies[3][0]=nested&hobbies[3][1]=stuff", true);
     
    // returns
    {
        username: 'Jacky',
        dateOfBirth: {
            day: '1',
            month: '2',
            year: '1911'
        },
        hobbies: ['coding', 'eating', 'sleeping', ['nested', 'stuff']]
    }
    A+JYT

  12. #12
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Il ne va pas utiliser ExtJS pour un mini-site de 4 pages avec un CV...

    Je pense qu'une façon "propre" de gérer des variables JavaScript communes entre des pages est soit de les stocker en session (cookie), soit de ne pas changer concrètement de pages et naviguer en AJAX. Si tu connais un peu AJAX, n'hésite pas à modifier ta navigation: ça te permettra de faire de plus belles transitions à coups d'animations et de fondus, c'est toujours très sympathique pour un site perso (c'est ce que je fais pour le mien)

    Pour la façon "sale" mais la plus rapide dans ton cas, tu peux modifier tous les liens de ta page en rajoutant les queryString comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    [].forEach.call(document.getElementsByTagName("a"), function(link){
       link.search = window.location.search;
    });
    Note que tous les liens de la page seront modifiés, et les queryString existantes écrasées. Si tu ne veux en modifier que quelques-uns, tu peux rajouter une classe particulière aux liens en question.
    One Web to rule them all

  13. #13
    Nouveau Candidat au Club
    Homme Profil pro
    Responsable marketing opérationnel
    Inscrit en
    Novembre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Responsable marketing opérationnel
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2014
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Sylvain,
    bien compris tes propositions intéressantes de passer par un cookie ou ajax, j'ai essayé rapidement la solution sale cependant : ca fonctionne quasiment au poil merci !!!

    j'ai du placé le script avant /body pour que ca fonctionne, et il reste bizarrement quelques liens ou ca ne marche pas. je vais fouine.

    feedback : sympa l'idée des transitions instantanées en ajax sur ton portfolio, mais chez moi, y avait beaucoup de lag (genre au moins 10 sec) ce qui fait qu'on clique dans tous les sens au bout de 4 sec.

    Merci encore !
    Adrien

  14. #14
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    non je ne proposais pas d'utiliser ExtJS
    Je le présentais car je trouve la fonction plutôt pas mal
    retrouner l'ensemble des varaibles de la queryString sous forme de membre d'un objet et ce de façon récursive et structure.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    getFromQueryString(
        "username=Jacky&"+                                                                            //simple sting
        "dateOfBirth[day]=1&dateOfBirth[month]=2&dateOfBirth[year]=1911&"+  //objet
        "hobbies[0]=coding&hobbies[1]=eating&hobbies[2]=sleeping&"+            //tableau indicé
        "hobbies[3][0]=nested&hobbies[3][1]=stuff&"+                                     //élément d'un tableau qui est un tableau
        "colors=red&colors=green&colors=blue", true);                                     //tableau sans indice
     
    // returns
    {
        username: 'Jacky',
        dateOfBirth: {
            day: '1',
            month: '2',
            year: '1911'
        },
        colors: ['red', 'green', 'blue'],
        hobbies: ['coding', 'eating', 'sleeping', ['nested', 'stuff']]
    }
    Je pense que s'inspirer du principe pour proposer une telle fonction dans la FAQ serais pas mal.
    A+JYT

  15. #15
    Nouveau Candidat au Club
    Homme Profil pro
    Responsable marketing opérationnel
    Inscrit en
    Novembre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Responsable marketing opérationnel
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2014
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Hello à tous,

    @SylvainPV,

    Sur cette première page, cela fonctionne parfaitement...

    mais j'ai beau chercher, si tu cliques pour aller sur la page CV, les paramètres sont bien présents dans l'URL, mais ne sont reportés sur aucun lien... donc sur la page suivante, il n'y a plus de paramètres d'URL.

    Ca te dérangerait d'y jeter un oeil ?...

    désolé de pousser un peu :/

    Adrien

  16. #16
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Il y a des erreurs JavaScript dans ton code avec les innerHTML, je vois des exceptions en console. L'exécution du bloc courant JavaScript s'arrête lorsque ces exceptions sont remontées.
    One Web to rule them all

  17. #17
    Nouveau Candidat au Club
    Homme Profil pro
    Responsable marketing opérationnel
    Inscrit en
    Novembre 2014
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Responsable marketing opérationnel
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2014
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Merci Sylvain,
    ta remarque m'a permis de comprendre ce qui bloquait, bien que je ne maitrise pas vraiment Firebug (j'aimerais bien apprendre d'ailleurs).

    Ce qui bloque, c'est quand il y a un a une définition d'un élément dans le script, alors que le dit élément n'existe pas dans le HTML :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     var element = document.getElementById("societe");
    element.innerHTML = getURLParameter("soc");
    Si pas de bloc avec un id=societe --> le script bloquait

    Comme je n'avais pas besoin de TOUS les éléments de personnalisation sur TOUTES les pages, voilà la source de l'erreur.

    Pour supprimer l'erreur, ce n'est pas très propre, mais, j'ai ajouté tous les éléments HTML correspondant aux variables sur Toutes les pages.... avec un display:none

    Merci encore pour ton aide !

  18. #18
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Citation Envoyé par adrien5555 Voir le message
    Pour supprimer l'erreur, ce n'est pas très propre, mais, j'ai ajouté tous les éléments HTML correspondant aux variables sur Toutes les pages.... avec un display:none
    En effet c'est tout sauf propre ! Un simple if aurait suffit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var element = document.getElementById("societe");
    if(element){
       element.innerHTML = getURLParameter("soc");
    }
    One Web to rule them all

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 02/02/2009, 16h45
  2. Envoyer des paramètres à une url
    Par joKED dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 08/03/2007, 12h22
  3. Query.SQL.Text avec la valeur des paramètres
    Par Guile dans le forum Bases de données
    Réponses: 3
    Dernier message: 04/02/2007, 11h13
  4. Recherche des enregistrements en fonction des paramètres
    Par infoctet dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 10/01/2007, 09h51
  5. Passer des paramètres à l'URL de retour d'une action
    Par et.rond.et.rond dans le forum JSF
    Réponses: 2
    Dernier message: 03/08/2006, 23h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo