Skip to content
This repository has been archived by the owner on Apr 6, 2020. It is now read-only.

5.3. Tutorial 3 Enhancing an existing IA (Encryption)

s.mombuleau edited this page Dec 4, 2018 · 2 revisions

Enhancing the Encryption IA

In this third tutorial, we are going to enhance an existing IA: the encryption IA!

The Encryption IA is a simple IA that takes a hash algorithm as the keyword (md5, sha1, sha256) and then the string to hash:

http://localhost:3002/?q=sha256%20no%20tracking
{
    "runtime": "nodejs",
    "template_name": "encryption",
    "display_name": "hash",
    "images_path": "ia/img/",
    "data": {
        "result": "87c9b69c9e6b164a2ab9350dfebf4e3a5814e5abb8dcb6c5f9c7df3191b835c0",
        "stringToHash": "no tracking",
        "hash": "SHA256"
    },
    "query": "sha256 no tracking",
    "status": "success",
    "cacheExpirationTime": 200,
    "files": [
        {
            "url": "ia/template/en_gb/encryption.js?deef78e5a4f7bc21f549c05b7038f8508caa9631",
            "type": "template"
        }
    ]
}

What we want to achieve is simple: we want to change the template to add a link to copy the hash to the clipboard.

Let's code!

Our IA already exists so we don't have to generate it. We are going to edit a few files and create a new one.

Template

The first file we are going to edit is the template file. This is where we are going to add the link over the hash, to copy the hash to the clipboard:

app/src/modules/encryption/public/encryption.dot
<div class="ia__encryption">
    <span class="ia__encryption__icon icon icon-md5"></span>
    <span class="ia__encryption__result">
        <a href="#" id="copy-hash" title="{{= _("Copy to clipboard", "encryption") }}">{{= it.data.result }}</a>
    </span>
    <div class="ia__encryption__description">
        {{= _("Hash","encryption") }} {{= it.data.hash }} :&nbsp;
        <span class="ia__encryption__description--query">
		{{! it.data.stringToHash }}
	</span>
    </div>
</div>

We added a <a></a> element around our result. This element has its id set to copy-hash so we can add an event listener in our JavaScript file and copy the hash to the clipboard when it's clicked.

Stylesheet

The link is inside a span element and is going to need styling, so we will add a rule in our scss file for the a element:

app/src/modules/encryption/public/css/encryption.scss
.ia__encryption__result {
    ...
    
    a {
        color: rgba(48, 52, 58, 0.95);
        text-decoration : none;
    }
}
Scripting

In order for our link to actually copy the hash to our clipboard, we are going to need to add a javascript function. So we will need to add a javascript script to our project! Let's edit our main js file to add that option. Anywhere you want inside the module.exports scope, add this line to tell our project that it should use a javascript script:

app/src/modules/encryption/encryption.js
script: "encryption_script"

By adding that, our project will know we have to include a javascript file. It will look for a file named encryption_script.js in src/modules/encryption/public/javascript/. This file shouldn't exist yet, nor should the public/javascript folder. Create both! And let's edit our new javascript file:

app/src/modules/encryption/public/javascript/encryption_script.js
var IARuntime = function() {
    function Encryption (iaData) {
        // constructor
    }

    Encryption.prototype.run = function() {
        // function that's gonna run at runtime
    };

    Encryption.prototype.stop = function() {
        // function that's gonna run upon exit
    };

    return Encryption;
}();

As you can see, this javascript file must follow a few rules: it must declare a IARunTime class containing a constructor, a run() function and a stop() function.

The constructor is where we will initialize the important variables we're going to need. The run() function is going to be ran at runtime. This is where we will add the eventListener on our hash. The stop() function is going to be ran upon exit. This is where we will delete everything we created to copy the text to the clipboard.

As usual, we won't explain the actual code much, but here is how your file should look like. Refer to the comments for more information:

app/src/modules/encryption/public/javascript/encryption_script.js
var IARuntime = function() {
    function Encryption (iaData) {
    }

    /**
     * gets a string, sets it to the fake textarea and copies it to the clipboard
     * @param text
     */
    Encryption.prototype.copyHash = function(text) {
        var it = this;
        it.existsTextarea.value = text;
        it.existsTextarea.select();

        try {
            document.execCommand('copy');
        } catch (err) {
            throw err
        }
    };

    /**
     * runs at runtime
     */
    Encryption.prototype.run = function() {
        var it = this;
        // declares our fake textarea
        it.textArea_id = "copy-hash-clipboard";
        it.existsTextarea = document.getElementById(it.textArea_id);
        if(!it.existsTextarea){
            // if it doesn't exist, creates it
            var textarea = document.createElement("textarea");
            textarea.id = it.textArea_id;

            // place in top-left corner of screen
            textarea.style.position = 'fixed';
            textarea.style.top = 0;
            textarea.style.left = 0;

            // give it a 1px² size so it's not visible, remove borders etc.
            textarea.style.width = '1px';
            textarea.style.height = '1px';
            textarea.style.padding = 0;
            textarea.style.border = 'none';
            textarea.style.outline = 'none';
            textarea.style.boxShadow = 'none';
            textarea.style.background = 'transparent';

            // append it to the page
            document.querySelector("body").appendChild(textarea);
            it.existsTextarea = document.getElementById(it.textArea_id);
        }

        // handling clicks on "copy-hash" link
        var hashLink = document.getElementById("copy-hash");
        hashLink.addEventListener('click', function(e){
            it.copyHash(e.target.innerHTML);
        });
    };

    /**
     * runs upon exit
     */
    Encryption.prototype.stop = function() {
        var it = this;
        if (it.existsTextarea){
            var elem = document.getElementById(it.textArea_id);
            elem.parentNode.removeChild(elem);
        }
    };

    return Encryption;
}();

In the run() method, we created a fake textarea to hold the hash, so we can copy it to our clipboard (execCommand only works on inputs and textareas). We then declared an Event Listener on the link of the hash so when it's clicked, we trigger the function copyHash that we created.

Of course, you can also declare functions outside the IARunTime class, and they will be available for calling in your .dot file. However, you should ALWAYS have a IARunTime class in your script file, even if it's empty.

Sandbox testing

Now that we made sure that our data is correct, we're going to test how our IA looks like. For that purpose, let's hit the sandbox: http://localhost:3030/?q=sha256 copy to clipboard Make sure that:

  • Your IA is triggered correctly,
  • Your IA blends in correctly with Qwant's layout
  • Your IA actually gives the right result and works the way you intended (click on the hash!)