Category: 6 months training

Implementing Drag And Drop

Today we will be implementing the Drag and Drop API. so these are the functions below that will be adding the event listeners

// drop event Handler
var handleDrop = function(e) {
if(e.preventDefault) { e.preventDefault(); }
if(e.stopPropagation) { e.stopPropagation(); }
console.log(‘handling drop,’,e.pageX,e.pageY,e);
const elemId = e.dataTransfer.getData(‘textId’);
const domElem = document.getElementById(elemId); = addPixels(pageY) || addPixels(e.pageY); = addPixels(pageX) || addPixels(e.pageX)
return false;

// drag Start Handler…
var handleDragStart = function(event){
var handleDragEnter = function(e) {
return false;

var handleDragOver = function(e) {
pageX = e.pageX;
pageY = e.pageY;
return false;

var handleDragLeave = function(e) {
return false;
//handle drag end….
var handleDragEnd = function(e) {
console.log(e,e.pageX,e.pageY,””) = 1;

The above methods as explained in the previous post as well, will be the event listeners for the various drag and drop event listeners.

var addingDragDropEventListeners = function(elem) {
elem.addEventListener(‘dragenter’, handleDragEnter);
elem.addEventListener(‘dragleave’, handleDragLeave);
return elem;

This method as it’s name specifies about adding the drag and drop event listeners to the specified DOM element.

This will add the drag and drop to the current element :). This is all about how I add the drag and drop API to the text box.

Drag And Drop API

Drag and drop (DnD) is a first class citizen in HTML5! The spec defines an event-based mechanism, JavaScript API, and additional markup for declaring that just about any type of element be draggable on a page

Creating draggable content

Making an object draggable is simple. Set the draggable=true attribute on the element you want to make moveable. Just about anything can be drag-enabled, including images, links, files, or other DOM nodes.

The basic markup may look something like this:

class="column" draggable="true">
class="column" draggable="true">
class="column" draggable="true">

For example, dragging the logo on produces a ghost image:

Dragging an image in the browser

Listening for Dragging Events

There are a number of different events to attach to for monitoring the entire drag and drop process:

  • dragstart
  • drag
  • dragenter
  • dragleave
  • dragover
  • drop
  • dragend

1. Starting a Drag

Once you have draggable="true" attributes defined on your content, attachdragstart event handlers to kick off the DnD sequence for each column.

This code will set the column’s opacity to 40% when the user begins dragging it:

function handleDragStart(e) { = '0.4';  // this / is the source node.

var cols = document.querySelectorAll('#columns .column');
[], function(col) {
  col.addEventListener('dragstart', handleDragStart, false);

2. dragenter, dragover, and dragleave

dragenter, dragover, and dragleave event handlers can be used to provide additional visual cues during the drag process. For example, when a column is hovered over during a drag, its border could become dashed. This will let users know the columns are also drop targets.

.column.over {
  border: 2px dashed #000;
function handleDragStart(e) { = '0.4';  // this / is the source node.

function handleDragOver(e) {
  if (e.preventDefault) {
    e.preventDefault(); // Necessary. Allows us to drop.

  e.dataTransfer.dropEffect = 'move';  // See the section on the DataTransfer object.

  return false;

function handleDragEnter(e) {
  // this / is the current hover target.

function handleDragLeave(e) {
  this.classList.remove('over');  // this / is previous target element.

var cols = document.querySelectorAll('#columns .column');
[], function(col) {
  col.addEventListener('dragstart', handleDragStart, false);
  col.addEventListener('dragenter', handleDragEnter, false);
  col.addEventListener('dragover', handleDragOver, false);
  col.addEventListener('dragleave', handleDragLeave, false);

There are a couple of points worth covering in this code:

  • The this/ changes for each type of event, depending on where we are in the DnD event model.
  • In the case of dragging something like a link, we need to prevent the browser’s default behavior, which is to navigate to that link. To do this, call e.preventDefault() in the dragover event. Another good practice is to return false in that same handler. Browsers are somewhat inconsistent about needing these, but they don’t hurt to add.
  • dragenter is used to toggle the ‘over’ class instead of the dragover. If we were to use dragover, our CSS class would be toggled many times as the event dragover continued to fire on a column hover. Ultimately, that would cause the browser’s renderer to do a large amount of unnecessary work. Keeping redraws to a minimum is always a good idea.

3. Completing a Drag

To process the actual drop, add an event listener for the drop and dragend events. In this handler, you’ll need to prevent the browser’s default behavior for drops, which is typically some sort of annoying redirect. You can prevent the event from bubbling up the DOM by calling e.stopPropagation().

The DataTransfer object

The dataTransfer property is where all the DnD magic happens. It holds the piece of data sent in a drag action. dataTransfer is set in the dragstart event and read/handled in the drop event. Calling e.dataTransfer.setData(format, data) will set the object’s content to the mimetype and data payload passed as arguments.

Dragging properties

The dataTransfer object exposes properties to provide visual feedback to the user during the drag process. These properties can also be used to control how each drop target responds to a particular data type.

Restricts what ‘type of drag’ the user can perform on the element. It is used in the drag-and-drop processing model to initialize the dropEffect during thedragenter and dragover events. The property can be set to the following values: none, copy, copyLink, copyMove, link, linkMove, move, all, and uninitialized.
Controls the feedback that the user is given during the dragenter anddragover events. When the user hovers over a target element, the browser’s cursor will indicate what type of operation is going to take place (e.g. a copy, a move, etc.). The effect can take on one of the following values: none, copy, link, move.
    e.dataTransfer.setDragImage(imgElement, x, y)
Instead of using the browser’s default ‘ghost image’ feedback, you can optionally set a drag icon

var dragIcon = document.createElement('img');
dragIcon.src = 'logo.png';
dragIcon.width = 100;
e.dataTransfer.setDragImage(dragIcon, -10, -10);


No one will argue that HTML5’s DnD model is complicated compared to other solutions like JQuery UI. However, any time you can take advantage of the browser’s native APIs, do so! After all, that’s the whole point of HTML5…which is to standardize and make available a rich set of APIs that are native to the browser.

Integrating Barcharts in React application

Today I will integrate the BarCharts into my application. It’s will be really easy but have to see that bar charts will be updating. So let’s start by first adding the bar-charts and then checking what needs to be done to overcome any issue faced.

Following is the charts component that will add the charts to the application.

export default class MyChart extends Component {
constructor(props) {
this.state = {
data : getDefaultData()
componentDidMount() {
let site =;
let siteData = convertRdDataToAnnotations(site.rdData);
data : newChartData(siteData)
componentWillReceiveProps(nextProps) {
let site =;
let siteData = convertRdDataToAnnotations(site.rdData);
data : newChartData(siteData)
shouldComponentUpdate(nextProps,nextState) {
let currentData =[0].data;
let newData =[0].data;
for(let i = 0; i < currentData.length; ++i) {
if(currentData[i] !== newData[i] ) {
return true;
return false;
render() {
let {data} = this.state
return (


The only new function I am adding is the componentWillReceiveProps. I will come to it for sure later on this post. First, let’s see the function that will create the data for the charts.

const convertRdDataToAnnotations = function(rdData, siteUrl){

let pdfDataAnnotations = [],
pdfgeneralAnnotations = [],
pdfImageAnnotations = [],
pdfTextAnnotations = []
console.log(rdData,”rdData that is being passed”);
if(typeof rdData == ‘undefined’){
return {
data: pdfDataAnnotations.length,
image: pdfImageAnnotations.length,
general: pdfgeneralAnnotations.length,
text : pdfTextAnnotations.length
else if(typeof rdData !== ‘object’){
console.log(“not object”);
return {
data: pdfDataAnnotations.length,
image: pdfImageAnnotations.length,
general: pdfgeneralAnnotations.length,
text : pdfTextAnnotations.length
else if(rdData.commentBoxes || rdData.totalElements) {
// Pdf Data Anntotions Data
pdfDataAnnotations = rdData.highlighters.filter(function( obj ) {
return obj.type == “normal”;
// Pdf Image Anntotions Data
pdfImageAnnotations = rdData.highlighters.filter(function( obj ) {
return obj.type == “image”;
// pdfImageAnnotations.highlighters = highlighterArr;

//pdf general Annotation
pdfgeneralAnnotations = rdData.circles.filter(function( obj ) {
return obj.type == “normal”;

pdfTextAnnotations = rdData.textHighlighters;

return {
data: pdfDataAnnotations.length,
image: pdfImageAnnotations.length,
general: pdfgeneralAnnotations.length,
text : pdfTextAnnotations.length
//let status = generatePdf(pdfDataAnnotations, pdfImageAnnotations, pdfgeneralAnnotations, siteUrl);
// console.log(status,”pdf generated status”);
//return status;

This function will create a data for the charts and then we will be changing this data to the format in which chart.js will accept the data.

const newChartData = ({general,data,image,text}) => {
return {
labels: [“General”, “Data”, “Images”,”Text”],
datasets: [{
label: ‘# of Anotations’,
data: [general, data, image,text],
backgroundColor: [
‘rgba(22, 159, 12, 0.2)’,
‘rgba(54, 162, 235, 0.2)’,
‘rgba(255, 206, 86, 0.2)’,
‘rgba(106, 106, 86, 0.2)’
borderColor: [
‘rgba(22, 159, 12, 1)’,
‘rgba(54, 162, 235, 1)’,
‘rgba(255, 206, 86, 1)’,
‘rgba(106, 106, 86, 1)’
borderWidth: 1
options: {
scales: {
yAxes: [{
ticks: {

The above function will be creating the data in the format in which barcharts will be accepting it. Now everything is done, but how will the charts.js will update it based on the new data. So this life cycle method of React come to our rescue, what it will do is update the charts based on the component’s data.

componentWillReceiveProps(nextProps) {
let site =;
let siteData = convertRdDataToAnnotations(site.rdData);
data : newChartData(siteData)

This will update the state based on new Data.

Charts.js Basics

I chose Chart.js because it can be learned and leveraged quickly. It’s designed with simplicity in mind, yet is extremely customizable. In my experience, charting libraries fall onto a spectrum of complexity, where more complex libraries offer deeper customization.

Installing Chart.js

Again, Chart.js is focused on being easy. Easy to learn, easy to leverage, and easy to install. If you’d like to dive into the actual code, check out the GitHub project.

You only need two things to use Chart.js.

1) The library – for this guide, I recommend using a CDN because it’s the easiest way to get up and running fast.

<script src=""></script>

2) A <canvas> element, as Chart.js leverages HTML5 canvas.

</canvas><canvas id="myChart"></canvas>

Alternatively, you can use a package manager to download the library.

Line Chart

This is all you need to create a minimum line chart in Chart.js. Just put it inside of a <script></script> somewhere in your <body> after you declare the HTML5 canvas.

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['M', 'T', 'W', 'T', 'F', 'S', 'S'],
    datasets: [{
      label: 'apples',
      data: [12, 19, 3, 17, 6, 3, 7],
      backgroundColor: "rgba(153,255,51,0.4)"
    }, {
      label: 'oranges',
      data: [2, 29, 5, 5, 2, 3, 10],
      backgroundColor: "rgba(255,153,0,0.4)"

If this code looks intense, don’t worry! All Chart.js examples follow the above format for the most part, so you only have to learn it once. Lets go line by line to understand what’s happening.

var ctx = document.getElementById("myChart").getContext('2d');

This line gets a reference to the <canvas> element we created earlier, then calls the getContext method on it. The getContext method returns an object that provides methods and properties for drawing on the canvas. We store this in a variable named ctx.

var myChart = new Chart(ctx, {
  type: 'line',
  data: // array of line data goes here

Here we are creating the chart object. I’ve excluded the data for a moment to focus on the type property, which determines the type of chart we want. Chart.js’ new Chart() constructor takes two parameters:

  1. Either a reference to a </canvas><canvas> element that the chart will be rendered on, or a reference to its 2d drawing context (here we are using the 2d context). Regardless of which you use, the Chart.js convention is to call it ctx.
  2. An object literal containing the data and the configuration options that Chart.js will use to build your chart. The required properties are type and data. In our example type is ‘line’ because we want a line chart. data is the data you used to populate the chart.

Bar Chart

Bar charts are (mostly) just line charts that look a bit different. By changing one line of our previous example, we can create a bar chart.

type: 'line'


type: 'bar'

Yes, it’s really that easy.

The full documentation on bar charts can be found here.

Here’s the full code for this example:

var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
  type: 'bar',
  data: {
    labels: ["M", "T", "W", "R", "F", "S", "S"],
    datasets: [{
      label: 'apples',
      data: [12, 19, 3, 17, 28, 24, 7]
    }, {
      label: 'oranges',
      data: [30, 29, 5, 5, 20, 3, 10]

Polar Charts

Polar charts give each data point an equal amount of radial space. Segments with larger values extend further from the center of the graph. Here’s the polar chart for our apples data set.

As usual, specifying that this is a polar chart can be done with a single line. Change:

type: 'radar'


type: 'polarArea'

But, the polar area is the first chart I’ve covered that can’t be used to compare two data sets. The previous examples were different ways of contrasting two arrays of equal length, whereas the polar chart (and pie chart, which will be covered next) only visualize a single group of numbers.

Here’s the full code for this example:

var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
  type: 'polarArea',
  data: {
    labels: ["M", "T", "W", "T", "F", "S", "S"],
    datasets: [{
      backgroundColor: [
      data: [12, 19, 3, 17, 28, 24, 7]

Today I took my time to learn the charts.js basics and tomorrow I will integrate the same into my React application.

Loading and Re-rendering Data

Now the major step is to do in my project is to do loading and re-rendering of the data. These 2 areas are the major things which are equally important and are related sections.
First I will try to explain the 2 things:-


The Loading of the Data refers to getting and creating the basic DOM elements which we have stored in the database.


Re Rendering of the data refers to the fitting of the DOM elements when browser window or screen size changes. This is the major component for our tool.

Ironically, first I will start with the Re-rendering of the data despite the title of the post contains the Loading first in the name.
So for the Re-rendering of the data we need to an event window.onResize.

// Re Render the Data….
var reRenderTheData = function() {
console.log(rdData, ‘rdData’);
rdData.highlighters.forEach((highLighterObj, index) => {
rdData.circles.forEach((dotObj, index) => {
let dotElement = document.getElementById(;
let highlighterElement = document.getElementById(dotObj.highlighterID);
let commentElement = document.getElementById(rdData.commentBoxes[index].id);
renderElementFromDOM(dotObj, dotElement, highlighterElement);
renderElementFromDOM(rdData.commentBoxes[index], commentElement, dotElement);
rdData.textHighlighters.forEach((textObj,index) => {

// This function will re render the component based on UniqueString elements.
var renderElementFromUniqueString = function(elementObj) {
let originalElement = loadElementFromUnqiueSelector(elementObj.element);
let element = document.getElementById(;
console.log(element, “highlighter element from dom”)
renderElementFromDOM(elementObj, element, originalElement);

// This function will re render the component based on the DOM elements..
// dot(type = highlighter) requires highlighter(DOM elements) to get there styles.
var renderElementFromDOM = function(elementObj, rdElement, domElement) {
if(elementObj.elemType == ‘dot’ && elementObj.type == ‘normal’) { =; = elementObj.left;
}else {
var getAllElementstyles = window.getComputedStyle(domElement, null);
if (getAllElementstyles.display == ‘none’) { = ‘none’;
else { = ‘block’;
if (elementObj.elemType == ‘highlighter’ || elementObj.elemType == ‘text’) {
// Here the rdElement is the dom element
let elemBoundingRect = domElement.getBoundingClientRect();
let dataObj = {
width: elemBoundingRect.width,
height: elemBoundingRect.height,
top: getTop(domElement),
left: elemBoundingRect.left
renderHighlighterCommonPart(rdElement, dataObj);
} else if (elementObj.elemType == ‘dot’ && elementObj.type == ‘highlighter’) {
// this is highligher dot..
let elemBoundingRect = domElement.getBoundingClientRect();
let dataObj = {
top: getTop(domElement),
left: elemBoundingRect.left
// Render the comment correctly as well = addPixels(; = addPixels(dataObj.left);
else {
// this is comment

let elemBoundingRect = domElement.getBoundingClientRect();
let dataObj = {
top: getTop(domElement),
left: elemBoundingRect.left

if (elementObj.type == ‘highlighter’) { = + COMMENTBOX_HEIGHT / 2 + ‘px’; = addPixels(dataObj.left);
} else { = + HALF_CIRCLE + ‘px’; = dataObj.left + HALF_CIRCLE + ‘px’;

These are basically 3 functions
reRenderTheData, renderElementFromUniqueString, renderElementFromDOM.

reRenderTheData is the main function which encloses the 2 other functions renderElementFromUniqueString –> which is a function which generates a DOM element from the unique string.

renderElementFromDOM —> To this function we basically pass the actual DOM element and then , using it’s present styles re rendering the style of the elements.
Now since the elements are being rendered properly, now it’s time to make an API call and get the actual data.


loadBasicComponents: This is the function which is going to load and create the new elements

var loadBasicComponents = function(rdData) {, “rdData”)
rdData.highlighters.forEach((highObj, index) => {
let dataObj = giveStylesToHighlighterObj(highObj);
let highLight = createHighLighter(dataObj);

// when you store your colors = highObj.backgroundColor;
highLight.children[0].style.backgroundColor = highObj.backgroundColor;

if(highObj.type == ‘image’) {
let imageElem = loadElementFromUnqiueSelector(highObj.element);
if(highObj.newSource) {
imageElem.addEventListener(‘click’, () => predictImageTool(imageElem, highObj.originalSource, dataObj, highObj), false)

rdData.textHighlighters.forEach((textHighObj, index) => {
let dataObj = giveStylesToHighlighterObj(textHighObj)
let highLight = createTextHighLighter(dataObj);
// when you store your colors = textHighObj.backgroundColor;
highLight.children[0].style.backgroundColor = textHighObj.backgroundColor;
highLight.children[0].style.borderColor = textHighObj.backgroundColor;
highLight.children[0].addEventListener(‘click’,() => openTextControlBox(textHighObj.element,,false);
highLight.children[1].style.backgroundColor = textHighObj.backgroundColor;
let textElem = loadElementFromUnqiueSelector(textHighObj.element)
if(textHighObj.newStyles) { = textHighObj.newStyles.fontFamily; = textHighObj.newStyles.fontWeight; = textHighObj.newStyles.fontStyle;
rdData.circles.forEach((circleObj, index) => {
if (circleObj.type == ‘highlighter’) {
circleObj.highlighter = true;
console.log(circleObj, “circle-obj”)
var dot = createDot(circleObj);
if (circleObj.type == ‘highlighter’) {
let highlighterDOM = document.getElementById(circleObj.highlighterID);
let highlighterStyles = highlighterDOM.getBoundingClientRect(); = addPixels(getTop(highlighterDOM)); = addPixels(highlighterStyles.left);
} =; = circleObj.backgroundColor;
dot.setAttribute(‘data-commentbox’, circleObj.commentID);
dot.addEventListener(‘click’, commentBoxHighLighterToggle, false);
let commentBox = createComment(dot);
if (circleObj.type == ‘highlighter’) { = removePixels( + COMMENTBOX_HEIGHT / 2 + ‘px’;
commentBox.children[1].value = rdData.commentBoxes[index].comment;

// Reloading the count of variables.
if(rdData.totalElements) {
highlighterCount = rdData.totalElements.highlighterCount || 0;
dotCommentCount = rdData.totalElements.dotCommentCount || 0;
textHighlighterCount = rdData.totalElements.textHighlighterCount || 0;
}else {
highlighterCount = 0;
dotCommentCount = 0;
textHighlighterCount = 0;

Highlighters and general elements are rendered using the loadBasicComponents and then the re-renderfunction will help us to resize the elements.

Encryption/Decryption using cryptr

Now the next hurdle was to load the data in such a way that it should be available to any person who is visiting the link of annotated site but only the users who are authorized and created that site are able to save the site data.
So for that I am using the encryption and decryption of the userId’s. 


Encryption is a security method in which information is encoded in such a way that only authorized user can read it. It uses encryption algorithm to generate ciphertext that can only be read if decrypted.

Types of Encryption

There are two types of encryptions schemes as listed below:

  • Symmetric Key encryption
  • Public Key encryption


Symmetric key encryption algorithm uses same cryptographic keys for both encryption and decryption of cipher text.



Public key encryption algorithm uses pair of keys, one of which is a secret key and one of which is public. These two keys are mathematically linked with each other.



Decryption is the process of taking encoded or encrypted text or other data and converting it back into text that you or the computer can read and understand. This term could be used to describe a method of un-encrypting the data manually or with un-encrypting the data using the proper codes or keys.

Data may be encrypted to make it difficult for someone to steal the information. Some companies also encrypt data for general protection of company data and trade secrets. If this data needs to be viewable, it may require decryption. If a decryption passcode or key is not available, special software may be needed to decrypt the data using algorithms to crack the decryption and make the data readable.

So for using the encryption and decryption in my application, I am using cryptr npm package.


cryptr is a simple encrypt and decrypt module for node.js

It is for doing simple encryption of values UTF-8 strings that need to be decrypted at a later time.

If you require anything more than that you probably want to use something more advanced or crypto directly.

The Cryptr constructor takes 1 required and 1 optional argument.

Cryptr(secret[, algorithm])

If an algorithm is not provided it defaults to aes-256-ctr.


Passwords should be a one way hash. Use bcrypt for that.


npm install cryptr
How I am using this library is on the user creation I am storing the encryption of user inside another collection crypted users.

// on the creation of user
Accounts.onCreateUser((options,user) => {
console.log(“user created “,user._id,user);
if(user._id) {
const encryptedString = cryptr.encrypt(user._id),
decryptedString = cryptr.decrypt(encryptedString);

console.log(encryptedString,”encrypte”); // 8db06003a73db491e9a27ae9e10d106d29
console.log(decryptedString,user._id,”decrypted”); // bacon
if(encryptedString && decryptedString) {
const cryptId = CryptedUsers.insert({userId : user._id, encryptedUserId: encryptedString, date : new Date()})
return user;
return user;

Storing the encrypted form of users and then using that encrypted user inside the mongo collection for loading of data.

Saving the Annotated Data

Now the biggest hurdle is to create the annotated data for storing in the database and then delivering that data to the user whenever he/she needs the data again. So first we will be creating objects that will be stored inside of the mongo collection.

Following are the methods that are self-explanatory as well. There are 3 methods basically createDot , createComment, createHighlighterObj. All will be going to create an object that will be stored in the database.

//This function will create 2 things
//create a circle DOM obj.
// highlighter ====> param will tell whether this circle is a highlighter circle / or normal one.
var createDot = function({
}) {
let commentCircle = document.createElement(‘div’); = commentCircleID;
commentCircle.className = ‘rd-circle’; = CURRENT_COLOR;
commentCircle.setAttribute(‘data-commentbox’, commentBoxID);
commentCircle.setAttribute(‘data-dot-type’, type);

if (highlighter)
commentCircle.setAttribute(‘data-highlighter’, highlighterID)

if (type == ‘normal’) { = top; = left;
return commentCircle;

// render the highlighter common part…
var renderHighlighterCommonPart = function(newElement, dataObj) {
// step 2 : A new Elem should be created which has same styles as of highlightedElem and append it to body = addPixels(dataObj.width); = addPixels(dataObj.height); = addPixels(; = addPixels(dataObj.left);
return newElement;

// Type can have 2 values,
// normal —> In normal highlighter we will create a dot as well
// image —-> In image highlighter we will create a dotted bordered element around image.
var createHighLighter = function(dataObj) {
let newElement = document.createElement(‘div’);

var deleteDiv = document.createElement(‘div’);
// deleteDiv.className = ‘rd-highlighter-delete-btn’;
// let buttonChild = document.createElement(‘button’);
deleteDiv.className = “rd-circle-close”; = CURRENT_COLOR;
let divText = document.createTextNode(“x”);
deleteDiv.addEventListener(‘click’, deleteHighlighter, false);
// deleteDiv.appendChild(buttonChild); = ‘absolute’;
let divWidth = dataObj.width – 17; = “pointer”; “auto”; = -2 + “px”; = -2 + “px”;
newElement.appendChild(deleteDiv); =;
newElement.className = ‘rd-new-highlight’;
newElement.setAttribute(‘data-rdhighlighter-type’, dataObj.type);
newElement = renderHighlighterCommonPart(newElement, dataObj);
// = ‘none’;
if (dataObj.type == ‘image’) { = ‘2px dotted ‘+CURRENT_COLOR;
} else { = ‘2px solid ‘+CURRENT_COLOR;
} = “transparent”;
// =;
return newElement;

/// Since commentBox Appears where there are dot objects so we will
// make the comment Boxes appear right there using that dot circle.
var createComment = function(commentCircleDOMObj) {
let commentDiv = document.createElement(“div”);
let highLighter = commentCircleDOMObj.getAttribute(‘data-highlighter’);

commentDiv.className = ‘rd-comment’; = commentCircleDOMObj.getAttribute(‘data-commentBox’);
if (highLighter) = removePixels( + COMMENTBOX_HEIGHT / 2 + ‘px’;
else =; =;

let pChild = document.createElement(‘p’);
let pChildText = document.createTextNode(‘Comment For’);

let textAreaChild = document.createElement(‘textarea’);
let ParentDiv = document.createElement(‘div’); = “flex”;
let okButtonChild = document.createElement(‘button’);
let okButtonText = document.createTextNode(‘OK’)

// Binding the current Comment Button with the commentCircle
okButtonChild.setAttribute(‘data-highlighter’, commentCircleDOMObj.getAttribute(‘data-highlighter’));
okButtonChild.addEventListener(‘click’, commentClick, false)

let delButtonChild = document.createElement(‘button’);
let delButtonText = document.createTextNode(‘DELETE’)

// Binding the current Comment Button with the commentCircle
delButtonChild.setAttribute(‘data-highlighter’, commentCircleDOMObj.getAttribute(‘data-highlighter’));
delButtonChild.addEventListener(‘click’, deleteCommentBox, false)


return commentDiv;

To actually save the data the user have to click on the save button and then make a call to the API. This facility of saving the data is only available to the authorized users 🙂 so adding the desired security automatically to your applications.

var saveData = function() {
console.log(rdData, “rdData…………”);
let fetchPath = API_PATH + ‘save-data’;
console.log(localStorage.getItem(‘authToken’), localStorage.getItem(‘userId’))

//Saving the count of variables as well…
rdData.totalElements.highlighterCount = highlighterCount;
rdData.totalElements.dotCommentCount = dotCommentCount;
rdData.totalElements.textHighlighterCount = textHighlighterCount;

// Call the api to save the data.
fetch(fetchPath, {
method: ‘post’,
headers: {
‘Accept’: ‘application/json, text/plain, */*’,
‘Content-Type’: ‘application/json’,
‘X-Auth-Token’: localStorage.getItem(‘authToken’),
‘X-User-Id’: localStorage.getItem(‘userId’)
mode: ‘cors’,
body: JSON.stringify({
data: rdData,
.then(res => res.json())
.then(res => {
if (res.status == ‘success’) {
alert(‘Data has been saved successfully’)
} else if (res.statusCode == 500 || res.status == ‘error’) {
alert(‘There has been some error while saving the data’);
.catch(e => {

This method here shown will make an API call to the backend and will be saving the data in the mongo collection using fetch API. 

This is the backend API method to store the data.

//Path api/save-data
Api.addRoute(‘save-data’,{authRequired: true},{
post: function() {
let data =;
let userId = this.user._id;
let siteUrl = this.bodyParams.url;
let checkExistence = MirroredSites.find({userId : userId, url : siteUrl}).fetch();
//console.log(“does exist”);
let rdDataId = MirroredSites.update({userId : userId, url : siteUrl},{$set : {rdData : data}});
return {
status : ‘success’,
statusCode : 200,
data : “data is entered into the collection”,
rdDataId : rdDataId
console.log(“does not exist”);
return {
status : ‘error’,
statusCode : 500,
data : ‘user with this url is not found’,
else {
return {
status : ‘error’,
statusCode : 500,
data : ‘can not find user’

Designing & Testing of the tools

The tools are good but before testing the actual usage first we need to make sure that tool should look good. So for that I am going to design how the tool should look. I have come up with the following bit of code that gives us the following data.

.rd-toolbx-btn {
background: none;
border: 5px solid #efefef;
display: block;
width: 60px;
height: 60px;
box-shadow: 0 0 2px 0 #efefef;
background-color: rgba(0,0,0,0.8);
color: #efefef;
cursor: pointer;
border-radius: 50%;
font-family: ‘Pacifico’, cursive;
letter-spacing: 1.5px;
transition: all .12s linear;
.rd-toolbx-btn:hover {
display: block;
width: 85px;
height: 85px;

.rd-toolbx-btn:hover > .rd-tool-text {
display: inline-block;

.rd-toolbx-btn:hover > .rd-tool-icon {
left: 15px;

.rd-tool-text {
display: none;

.rd-tool-icon {
display: block;
width: 32px;
height: 32px;
position: relative;
left: 3px;

.rd-comment-tool-icon {
background-image : url(‘data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfhBQ4UAxFjQeJZAAACAElEQVRIx62Vv2taURTHP1defFIU6pCQJzh06OCQrVvJ4hSw4JKtf0XXUDoU945JIIQs/QMEC5k6R3AvdHEQfKBwzyMmRVPwdHipen1PY2u+b3r3nh/f+z33nmNIgfpSpW4qBARASKg/aBa/m0nS1iwvDIOdT/qeQkrckfn6+/NuuCZAN1f8qB94AcCEjulpH0xJy7zBB+CX+SKNV+M03gz27Y2oqKi0ouNB3tnLR8fSinftzWA/xd0eSE9UVNr2kBWwh9IWFZWePUhkj93tuXqsgXr2PA7hsOjmYvL2hA1gT+KDdHOzpagRZ9/EHSBmETVmhZN7UWmvJ+8eRNqicj8M4vynoqJz6eRCpo/VcL+pXCzIqaLRKRj1oyEFvhXfzQJMk9frb+piZmbVosbo5a4nVVMAc7VgZqCYEkJ0MbC50hoFqXrUgcnDdcL4CTxc70zwqXumAnT27tztFQwWsHcnHd6aikcAprfeOB2mpxBkCED7mxbQUbQPBE/UfvEo6aw8Ql6bkht6rvaSk/NnSgphhhC07Jhdkq6Acun8loEQeyYqY/f1g6iMHi/qCgzyMha1ZxmagJ89SmjcWG5eLrJH+EAT9eVWVFpLDH5qdr280hKVW/VJPiYAW1vvPn9MPMNz3rqhPENL27qpwtZtPWbxP4Nl69H2vMN1JtU/jPc/EI2kPED2/FoAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDUtMTRUMjA6MDM6MTcrMDI6MDDb4OLEAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTA1LTE0VDIwOjAzOjE3KzAyOjAwqr1aeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII=’)

.rd-circle-tool {
background-image: url(‘data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfhBQ4UCSYhE6/cAAADNUlEQVRIx41VPWxTVxT+rn+ShgCK+UliEBIWARQBykIUgWBBIMFQYKoQYojEQBiCFKAbEc1SRAcGhqidIlUZGDq0CxKCdKBupLCABFZUJANypNgE+37X77kFgp9Ph2fs5/deDHd679zvfOf3nqMQcqSTx3BGDSKJJIA88rKIPxJ/qo9BrPILKn3Vm3IB3ZjHgirUCkCkX/oxgsP4V83Gpta/xdpHOjhJm1k9VukLEusxZmlzUjrWUK/0Mc0ixyW+poE4x1lkOkgPQB9gjhmTwheOSTHDnD4QtJ7jXGmjH25tsbb4ZaWNnGOuxQvpYJqZoLo+R4eOPhdCkWHakwtOshjmPF/zLu/ydWggRU423bc5HgSVhynl3dZeSnk4hHycdj0MM81sWObNcf4GAHyufwqtSNZMA5BOWnqsXd55MywIQI/Rkk7oU3RC69oE7qeUDgfllT46+pTSP6t9iaMAsLzumztqBFEoRJSqzW76sRHMfTmqlkRQg8CRhQ9Xt/0HAPxLMjE1iAUX1vU9zuIXVCFSE4k8aNpa/S52VnZAqQgUYupSVx5TAIAFNRxDUhVcmIpLVf3akw0621vBbMObXXJR1VOuCpKMIFmrE3y6rXLyVJ9vm4/z8lTlPt12/2oFJEFbX2iUJmZu0eFMoTtMudDNGTrmlsQa9RmlAV+a663VN3mzaG32q1ubzaLJm+MtBf6BzyLIS79X2PMoOiTx2jU/Qe2axKNDPY9ahCm8icgiRlqhG1ZgieMnEAfWhhWfcABvQhqJOymlQ36C0iEKd3olxe2s6m9DWpkTXBblJpWnedpNmiguc6IFd4NLEkXwMfGxmQaA8gCfcJWrfFIegIt77AlJ8RXddmp9zvZWOuYEwFHaZt6kTMrM0+YoYE7Qsbc2OuIyP5Z2fLbpGSgcopRO6nusckqiACBRTrGq75VOUszBuvp+855Xm+54RprEmKbwlT7ijVcfYZbCv90xttTFF/qBeHeKd6iKKg5KJFBGZXa5XybBOb5d6fcBvnasW3v5kv9Ye0KuvrxYgHfbSD40iTWu2622eo16zcXmYwK+YrlWf++ttAtJhQlb1vuVxEw7gv8BJKD1k1XMK7IAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDUtMTRUMjA6MDk6MzgrMDI6MDB4rwWZAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTA1LTE0VDIwOjA5OjM4KzAyOjAwCfK9JQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII=’)

.rd-predict-image {
background-image: url(‘data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfhBQ4UCy2E9xTWAAACU0lEQVRIx+2Uu2sUURTGv7sbNtkNG/PGnexGDYKFgk0UFIwWQlYStUljo4JgbROwEyxi/oCUFiIKQSImTcRHqcFGLCw0aSJumInJznx3dtlE3cexyMPZTIbdBUu/6s655/7OueecuQpV0hNQxYnugqqgToX2fB+Qu005vZntqxdQpdVWLlMovF//maoMmsfkF9aAykLDsc2YfXxrtdziTOrBBo6ux9cTHHK+cmrvDu/oi9JUE8DXFAqFD6vtEmGB3yRcuwa3kQcAjOa6vBvZLjzAjCrXcQk+387hSZCHhN1hOxkI0E+56A67R7cysNtE+UJM8TOpxwIA7qlMdDeW4py+5QO81ePOOepAhMf1GYUV3txjPU+XV3iBhZoIM8Z3vOe322m6fExhsSbC6Zfm/ex2mj8pdSGC1BAi1+30+6dwP8Ruy3hSzoRSkkISKZWUEjbQhR9YQQYryMhSxyv1G7DToVk0Ayipa+0z3ip/pFD0Fz1up50TbAcAiegjHOJ1zrJMYVZPBGQhIX6nUJhfjwc099HWrDqjAQg9RptC0fPOZR6WyM5BUfle97QzyQKFZWd6pyp/Ec7Idg0koi/hKg6phBhowxoy2EASfVCwlCkmFkrTPaa3nNu1+OSZ+9yxYjhstdOMtRoVIxQtW01m3EbENSpG53t/R8IvpEW9VN6b4gaATVgwxVSbklAGDHQCQIfvBwPyvcXBjjf+FyeKAQwob4cDFF/DvP9Zb1j/Af8WIIuBXkvBAE+zRfFsaET6cRAJJFRUVpUlFiz5UJ7ryQcB/gD1Qlxq4LAVuQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wNS0xNFQyMDoxMTo0NSswMjowMMHk8nQAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDUtMTRUMjA6MTE6NDUrMDI6MDCwuUrIAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg==’)

I will try to explain what each thing will do one by one.

.rd-toolbx-button , .rd-toolbx-button:hover:- These are the actual styles of the toolbox buttons and the :hover will add the effect when we try to mouse over the tool buttons.

.rd-tool-text, .rd-tool-icon:- These are the classes which will be styling the text inside the tool buttons and the icons. And then later on I am going to add the background Image to each button using data-uri. 

.rd-predict-image :- These classes will hold the background url for the predict image tool.

here is the visual picture of the tool described on one of the sites we have scraped


The 3 tools are up and ready, now was the time to see the tools in action. So first step we will going to scrape any random site which is going to be our companion website where most of our tools are built and tested in initial stages.

Here are the result of the tools tested. The results are very good uptil now.


The next thing is to saving the data, loading the data, deleting it. Creating a complete CRUD and after that re rendering the data to make it responsive.

Playing around with Redux

What is Redux?

Redux is a framework that controls states in a JavaScript app. According to the official site:
Redux is a predictable state container for JavaScript apps.

There are many states in an app that will change depending on time, user behavior, or a plethora of different reasons. Thus, if we consider an app as the process to change its own state, the view a user sees is how the states are presented.

For example, in a TODO list app, when we create a new todo item, we actually changed the state of an app from one without that TODO item to one with the TODO item. In addition, because the app’s state has changed, and the view is how a state is presented, we will see the new TODO item in our view.

If an app’s state unfortunately does not behave as expected, then it’s time to debug the app. E.g. If we add a new TODO item but our state appears to have added two items instead of just one, we will have to spend time on figuring out which state change went wrong. Sounds pretty simple on paper, right? If you think this process will be easy, you’re too naïve…. Real-world apps are often much more complex, and there are a lot of
factors that will make this debugging process a nightmare, such as having a bad coding habit, flaws in the framework design, not investing time in writing unit tests, etc.

Redux’s framework is designed to ease the debugging process. To be more specific, Redux is a framework that extends the ideas of Flux and simplifies redundant things. As it puts it on its official site:
Redux evolves the ideas of Flux, but avoids its complexity by taking cues from Elm.

What was wrong with the original MVC frameworks?

Originally, there were many MVC frameworks out there of different sizes and shapes, but generally can be either categorized as MVCs or an extension of MVC.

Flux/Redux attempts to resolve the problem where bugs are difficult to trace when a model has been continuously updated as an app is being used.

Just as illustrated in the following chart:
As seen in the image, any given view could affect any model, and vice versa. The problem with this is when there are many views and models and one of the model’s state changed into something we didn’t expect, we are unable to efficiently trace which view or which model caused the problem, since there are way too many possibilities.

Flux/Redux makes debugging apps easier by removing the model (aka store) setter, and then letting the store update its own state via an action (which is the “unidirection data flow” mentioned on React’s official site.) In addition, the dispatch of an action cannot dispatch another action. This way, a store will be actively updated as opposed to passively updated, and whenever there is a bug, we can refer to the problematic store to see what events have happened before. This makes bug hunting easier, since we’ve essentially zeroed down the possibilities that caused a bug.

Want to speed up your learning process? Learn React with a Live Expert

How does Redux Work?

Redux can be broken down into the following:
store: manages the states. Mainly there is a dispatch method to dispatch an action. In a Redux app, you can obtain its states via store.getState()
action: a simple, plain JavaScript object. An action can also be considered as a command to change a state.
reducer: decides how to change a state after receiving an action, and thus can be considered the entrance of a state change. A reducer is comprised of functions, and it changes states by taking an action as an argument, in which it then returns a new state.
middleware: the middleman between a store.dispatch() and a reducer. Its purpose is to intercept an action that has been dispatched, and modify or even cancel the action before it reaches the reducer.
As shown above, if we added a new TODO item in a Redux app, we will first create an action with a type ADD_TODO, and then dispatch the action through store.dispatch().

// actionCreator

export function addTodo(text) {
  return { type: types.ADD_TODO, text };

store.dispatch(addTodo({ text: 'Clean bedroom' });

Afterwards, this action will enter the middleware, and finally enter the reducer. Inside the reducer, the state will change accordingly to the action’s type.

// reducer

function todos(state, action) {
  switch(action.type) {
    case 'ADD_TODO':
      // handle action and return new state here


And so, we’ve completed the most basic behavior of updating a state.

In a more complex app, we will need to split up a store’s state into different pieces like we’d do when namespacing. You can do this in Redux by creating different reducers to manage different areas of a state, and then merge them together through combineReducers.

The process should look like this:

Async & Middleware

We’ve already introduced state updating, but a front-end app is never that simple~

Here we’ll go over how to handle asynchronous behavior in a Redux app. In this section, we’ll examine the process of sending an HTTP request to understand how async works in Redux.

The Sample Situation

Let’s say we have an app that a list called questions. At some point (e.g. a user clicks a button), we will need to send a request to our server to obtain the data in questions. While sending this request, we need to reflect the sending state in our store, and if the request has been made successfully, we will need to put the data of questions in our store. If the HTTP request failed, we will need to reflect the failure info in our store.

The Straightforward Solution

One naive way to approach this situation is to dispatch different events at different times. In the code below, I used superagent to make my requests.

import request from 'superagent';


store.dispatch({ type: SENDING_QUESTIONS });
  .end((err, res)=> {
    if (err) {
        error: err
    } else {
        questions: res.response

This way, we can achieve async behavior in a Redux app. However, this approach is not suitable if we have to send many HTTP requests, since we need to add async behavior to every request and this makes it difficult to maintain our code. Furthermore, this approach is also not easy to test, especially since asynchronous code is more difficult to understand and test in general. Finally, if we use this approach in a React app, we will be forced to code this logic into a React Component.

How I am using redux is here. Store is the place where I am using all my reducers.


Why ApplyMiddleware ? what is Middle ware now ?

As stated before, in Redux a middleware is like the negotiator between store.dispatch and reducer. To be more specific, the store.dispatch() we call is actually comprised of layers of middleware, and the reducer is in the innermost layer.

We can visualize this via the following image:

Through a middleware, we can extract the above-mentioned asynchronous API request and place them in the same middleware. I am using Redux-Thunk middleware.

Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.

Flickr API To Get Images

The Image Recognization is done using the Clarifia API. Now the next thing and major task are to get the Images out of the tags. Like for the following image

The Clarifia will give us the tags mountains, snow, road, grass. Now for the tags Clarifia also offers the image data but it’s image gallery can’t be bigger than world’s most popular image hosting and sharing resource Flickr.

Flickr (pronounced “flicker”) is an image hosting and video hosting website and web services suite that was created by Ludicorp in 2004 and acquired by Yahoo on March 20, 2005.[4] In addition to being a popular website for users to share and embed personal photographs, and effectively an online community, the service is widely used by photo researchers and by bloggers to host images that they embed in blogs and social media.[5]

The Verge reported in March 2013 that Flickr had a total of 87 million registered members and more than 3.5 million new images uploaded daily.[6] In August 2011 the site reported that it was hosting more than 6 billion images and this number continues to grow steadily according to reporting sources.[7] Photos and videos can be accessed from Flickr without the need to register an account but an account must be made in order to upload content onto the website.

So the next step is to get the API key of the flickr and using that to get the images from the tags.

The next step is obtaining an application key. Flickr uses this app key to keep tabs on our usage and other statistics. Head on over here and apply for your own API key.

Since our usage of this particular API key is purely educational we choose to obtain a non-commercial key.

Fill in all the details the form requires with special attention to the description of the project. The devs at Flickr actually read this description if your app misbehaves in some way to make sure it is legit. So spend that extra minute describing your masterpiece.

A successful registration yields you this page. Do note down the api key and the shared secret for later use.

The Flickr API provides a number of methods which may or may not require authentication. Each method takes a number of arguments which modify its behavior and payload. Responses can be received in a number of formats including JSON, XML, SOAP and REST. All these requests can be made to end points corresponding the format you’ve chosen to make the request in. For example, we’ll be using REST for the rest of this article and so our URL end point would be

There are a number of methods which pull in public data and thus require no authentication of any sort. We just need the api key we had obtained earlier along with any required arguments of the method in question. Lets take a look at an example.

The getPublicGroups method is an example of a method which doesn’t require authentication and which pulls in public data. We pass in the user id of the user and our api key and the API responds in the format you requested with a list of groups the user is part of.

We’d send in a request to this URL.

Replace your_api_key with the key we obtained earlier and user_id_x with a valid NSID. Since I like my responses to be in JSON, I can add another parameter asking the API to respond with a JSON payload.

The API will send a response like so:

So I am using Flickr in my Project as following :


Having other custom code as well to remove the Child nodes and creating the new nodes having images in them.