Compoot
Compoot

Reputation: 2387

How to open url in new tab from JavaScript script

I am developing a chatbot using peekabot (link provided below for documentation and official example), and want to be able to open a URL in a new tab (as you would have the option to do using plain html) when a user clicks on an option. Linked with this is the fact that the URL button that is generated is styled wrong (shows up as blank without the label text on mouse-hover-over).

I have included the whole script below for context, but the bit I am referring to is:

6: {
            text: 'You should check it out on test preview',
            options: [{
                text: "PREVIEW THIS LINK",
                url: "www.google.com"
            }]
        },

The above is option 6 and on clicking it the user should go to the URL (e.g. google.com) but open in a new tab and also not be blank (the button link is blank on hover over for some reason)

I have tried: url: "www.google.com" target="_blank (see below) but this breaks the whole javascript code.

6: {
                text: 'You should check it out on test preview',
                options: [{
                    text: "PREVIEW THIS LINK",
                    url: "www.google.com" target="_blank
                }]
            },

I have also tried:

url: "www.google.com target="_blank" 

and

url: "www.google.com target=_blank"

neither works.

For an answer:

  1. Solution for opening the URL in a new tab
  2. Correction so that the button link (for the URL) is not BLANK on hover-over. (when you move the mouse away from the button link, the text appears)

This is the official site - https://peekobot.github.io/peekobot/ but irritatingly even in their example - the url to GitHub is opened in the same tab.

The whole script below for context:

</script>
<script type="text/javascript" src="<?php echo base_url(''); ?>js/bot.js>v=1"></script>

<script>
const chat = {
    1: {
        text: 'Some Text here',
        options: [{
            text: 'More Text here',
            next: 101
        },
     {
            text: '??',
            next: 201
        }
        ,
         {
            text: '?????',
            next: 301
        }   
    ]
    },
    101: {
        text: 'Some information here,
        options: [{
            text: 'That is great, thanks!',
            next: 102
        },
        {
            text: 'I would like some more info please.',
            next: 103
        }]
    },
    102: {
        text: 'Thanks and Goodbye',
        url: siteurl + "index.php/student/test",
        options: [{
            text: 'Bye and thank you.',
            next: 3
        },
        {
            text: 'I would like some more info please.',
            next: 104
        }]
    },
    103: {
        text: 'Info here',
        options: [{
            text: 'That is great, thanks!',
            next: 103
        },
        {
            text: 'I would like some more info please.',
            next: 104
        }]
    },
    5: {
        text: 'Aah, you\'re missing out!',
        next: 6
    },
    6: {
        text: 'You should check it out on test preview',
        options: [{
            text: "Go to PRIVIEW",
            url: "www.google.com"
        }]
    },
    
};


const bot = function () {

    const peekobot = document.getElementById('peekobot');
    const container = document.getElementById('peekobot-container');
    const inner = document.getElementById('peekobot-inner');
    let restartButton = null;

    const sleep = function (ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    };

    const scrollContainer = function () {
        inner.scrollTop = inner.scrollHeight;
    };

    const insertNewChatItem = function (elem) {
        //container.insertBefore(elem, peekobot);
        peekobot.appendChild(elem);
        scrollContainer();
        //debugger;
        elem.classList.add('activated');
    };

    const printResponse = async function (step) {
        const response = document.createElement('div');
        response.classList.add('chat-response');
        response.innerHTML = step.text;
        insertNewChatItem(response);

        await sleep(1500);

        if (step.options) {
            const choices = document.createElement('div');
            choices.classList.add('choices');
            step.options.forEach(function (option) {
                const button = document.createElement(option.url ? 'a' : 'button');
                button.classList.add('choice');
                button.innerHTML = option.text;
                if (option.url) {
                    button.href = option.url;
                } else {
                    button.dataset.next = option.next;
                }
                choices.appendChild(button);
            });
            insertNewChatItem(choices);
        } else if (step.next) {
            printResponse(chat[step.next]);
        }
    };

    const printChoice = function (choice) {
        const choiceElem = document.createElement('div');
        choiceElem.classList.add('chat-ask');
        choiceElem.innerHTML = choice.innerHTML;
        insertNewChatItem(choiceElem);
    };

    const disableAllChoices = function () {
        const choices = document.querySelectorAll('.choice');
        choices.forEach(function (choice) {
            choice.disabled = 'disabled';
        });
        return;
    };

    const handleChoice = async function (e) {

        if (!e.target.classList.contains('choice') || 'A' === e.target.tagName) {
            // Target isn't a button, but could be a child of a button.
            var button = e.target.closest('#peekobot-container .choice');

            if (button !== null) {
                button.click();
            }

            return;
        }

        e.preventDefault();
        const choice = e.target;

        disableAllChoices();

        printChoice(choice);
        scrollContainer();

        await sleep(1500);

        if (choice.dataset.next) {
            printResponse(chat[choice.dataset.next]);
        }
        // Need to disable buttons here to prevent multiple choices
    };

    const handleRestart = function () {
        startConversation();
    }

    const startConversation = function () {
        printResponse(chat[1]);
    }

    const init = function () {
        container.addEventListener('click', handleChoice);

        restartButton = document.createElement('button');
        restartButton.innerText = "Restart";
        restartButton.classList.add('restart');
        restartButton.addEventListener('click', handleRestart);

        container.appendChild(restartButton);

        startConversation();
    };

    init();
}

bot();
</script>

UPDATE:

Based on a suggestion below, I've tried:

if (step.options) {
            const choices = document.createElement('div');
            choices.classList.add('choices');
            step.options.forEach(function (option) {
                const button = document.createElement(option.url ? 'a' : 'button');
                button.classList.add('choice');
                button.innerHTML = option.text;
                if (option.url) {
                    button.href = option.url;
            if (option.target) {
      button.target = option.target;
                } else {
                    button.dataset.next = option.next;
                }
                choices.appendChild(button);
            });
            insertNewChatItem(choices);
        } else if (step.next) {
            printResponse(chat[step.next]);
        }
    };

This breaks the whole code so the chatbot doesn't run at all.

Upvotes: 1

Views: 379

Answers (1)

dmikester1
dmikester1

Reputation: 1362

What I'm thinking is you would have to modify the code or get the author to modify the code for you.

I'm looking at the main js code here: https://github.com/Peekobot/peekobot/blob/master/peekobot.js

This snippet is what I am looking at:

step.options.forEach(function (option) {
                const button = document.createElement(option.url ? 'a' : 'button');
                button.classList.add('choice');
                button.innerHTML = option.text;
                if (option.url) {
                    button.href = option.url;
                } else {
                    button.dataset.next = option.next;
                }
                choices.appendChild(button);
            });

That last part would get changed to something like this, I would think.

if (option.url) {
   button.href = option.url;
   if (option.target) {
      button.target = option.target;
   }
} else {
...

Upvotes: 1

Related Questions