Amazon Interview Question
Web DevelopersTeam: AWS
Country: United States
Interview Type: Phone Interview
This is the answer I gave:
<div id="hydra">
<button onclick="strikeDown(this);">Head</button>
</div>
<script>
function strikeDown(button){
$(this).remove();
$('#hydra').append('<button onclick="strikeDown(this);">Head</button>');
$('#hydra').append('<button onclick="strikeDown(this);">Head</button>');
}
</script>
The interviewer didn't comment on whether or not this was the best answer, he only mentioned it was correct.
Slight changes and this will work -
<div id="hydra">
<button class="btn">Head</button>
</div>
<script>
$(function() {
$('body').on('click', '.btn', function() {
$(this).remove();
$('#hydra').append('<button class="btn">Head1</button>');
$('#hydra').append('<button class="btn">Head2</button>');
});
});
function strikeDown(button) {
alert(this);
$(this).remove();
//$('#hydra').append('<button onclick="strikeDown(this);">Head1</button>');
//$('#hydra').append('<button onclick="strikeDown(this);">Head2</button>');
}
</script>
Forgot to remove the strikeDown function.
Don't know how to edit a reply. ( Ignore previous reply, this is cleaner) -
<div id="hydra">
<button class="btn">Head</button>
</div>
<script>
$(function() {
$('body').on('click', '.btn', function() {
$(this).remove();
$('#hydra').append('<button class="btn">Head</button>');
$('#hydra').append('<button class="btn">Head</button>');
});
});
</script>
<div id="hydra">
<button onclick="strikeDown(this);">Head</button>
</div>
<script>
function strikeDown(button){
$(button).remove();
$('#hydra').append('<button onclick="strikeDown(button);">Head</button>');
$('#hydra').append('<button onclick="strikeDown(button);">Head</button>');
}
</script>
Thought this was a neat way to see how someone handles event replication through js (ideally with jq for ease). My take on it, without any html required:
var hydra = $("<button>Hydra</button>").click(function(){
$(this).parent()
.append(hydra.clone(true))
.append(hydra.clone(true))
.end().attr('disabled',true); /* disable vs remove the item, so we can actually see the 2 elements added, else it looks like only one is, if you remove the first */
});
$('body').append(hydra.clone(true));
<div id="doubleHolder">
<button class="double">double</button>
</div>
<script>
document.getElementById('doubleHolder').addEventListener('click', function (e) {
if(e.target.classList.contains('double')){
var btn = document.createElement('button');
btn.setAttribute('class', 'double');
btn.innerHTML = 'double';
var btn2 = document.createElement('button');
btn2.setAttribute('class', 'double');
btn2.innerHTML = 'double';
this.appendChild(btn);
this.appendChild(btn2);
this.removeChild(e.target);
}
});
</script>
What I think many people do not consider is the fact that the two new buttons created should behave like the original one (the head), that is, after the head has gone the two should also be gone on 'click' and add two heads to the page.
It appears therefore that the interviewer wants to see if the applicant as an understanding of recursion.
A solution in vanilla JavaScript (aka without any libraries such as jQuery) would look like this:
<body>
<div id="container"></div>
<script>
var container = document.querySelector('#container');
var button = document.createElement('button');
var count = 1;
var max = 2;
function addNewButton() {
var currentButton = this;
for( var i = 0; i < max; i++ ) {
var newButton = document.createElement('button');
count++;
newButton.textContent = 'button ' + count;
newButton.addEventListener('click', addNewButton, false);
container.appendChild(newButton);
}
container.removeChild(currentButton);
}
button.textContent = 'button ' + count;
button.addEventListener('click', addNewButton, false);
container.appendChild(button, container);
</script>
</body>
I used YUI but should work with any other toolkit in similar manner.
<!DOCTYPE html>
<html>
<head>
<title>Hydra - Delete one button & produce two more!</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body id="hydrabody">
<button class="hydrahead">Hydra Head</button>
</body>
<script src="yui"></script>
<script>
YUI().use('node', 'event',function (Y) {
var hydra = function(e){
Y.one(e.target).remove();
var twoheads = Y.Node.create('<button class="hydrahead">Hydra Head</button><button class="hydrahead">Hydra Head</button>');
Y.one('#hydrabody').insert(twoheads);
};
Y.one('#hydrabody').delegate('click', hydra, 'button');
});
</script>
</html>
Added a few more line to have proper name for the button so that the creation can be traced back. Also, this is without jQuery.
<head>
<meta charset="utf-8" />
<title>Hydra</title>
<script>
function createButton(container, n) {
var btn = document.createElement('button');
btn.innerHTML = n;
btn.style.margin = "5px";
btn.onclick = function () { btnClick(this, container); };
container.appendChild(btn);
}
function btnClick(element, container) {
var name = element.innerText;
createButton(container, name + '.1');
createButton(container, name + '.2');
container.removeChild(element);
};
function load() {
var container = document.getElementById('containerDiv');
createButton(container, 1);
}
</script>
</head>
<body onload="load()">
<div id="containerDiv"></div>
</body>
Interesting thought process. Kill off one head and get two exponentially. Not adding anything new here, but it is a little more succinct:
$('body').on('click','.hydra', function() {
//find all the heads currently on the page - we start with one defined
var buttons = $('.hydra');
//we set up a template (probably should be declared elsewhere)
var buttonTempate = "<button class='hydra'>Hydra</button>";
// Loop over each button, removing it and adding two more
$.each(buttons, function(button) {
this.remove();
$('body').append(buttonTempate,buttonTempate);
})
});
That is an interesting question. Here is a fully functional code that does not use jQuery:
<!DOCTYPE html>
<html>
<body onload='makeBtn()'>
<p>Click the button to make a two buttons</p>
<script>
var removeAndCreateMore = function() {
"use strict";
document.body.removeChild(this);
console.log(this);
makeBtn();
makeBtn();
};
var btnIdx = 0;
var makeBtn = function makeBtn() {
"use strict";
var btn = document.createElement("BUTTON");
var t = document.createTextNode(btnIdx++);
btn.appendChild(t);
btn.onclick = removeAndCreateMore;
document.body.appendChild(btn);
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hydra</title>
<script type='text/javascript' src='udacity_Front_End_Web_Developer_nano/Project_5/final_project/js/jquery-2.1.3.min.js'></script>
<style type="text/css">
* { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; }
</style>
</head>
<body>
<div id="container">
<button>hydra</button>
</div>
<script type="text/javascript">
(function () {
'use strict';
$('#container').delegate('button', 'click', function () {
$(this).detach();
$( [1, 2] ).each ( function () { $( '#container' ).append( " <button>hydra</button>" ) ;
} );
} );
} ) ();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hydra</title>
<script type='text/javascript' src='udacity_Front_End_Web_Developer_nano/Project_5/final_project/js/jquery-2.1.3.min.js'></script>
<style type="text/css">
* { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; }
</style>
</head>
<body>
<div id="container">
<button>hydra</button>
</div>
<script type="text/javascript">
(function () {
'use strict';
$('#container').delegate('button', 'click', function () {
$(this).detach();
$( [1, 2] ).each ( function () { $( '#container' ).append( " <button>hydra</button>" ) ;
} );
} );
} ) ();
</script>
</body>
</html>
I decided to do something a little different, and copy the clicked button instead of producing one from a template. This way if another function (or the user, or whoever) makes modifications to the button, those modifications will also be copied. (In two sections because jsFiddle)
<body id="body">
<button type="button" onClick="doThing(this)">Hydra Button!</button>
</body>
doThing = function(clickedElement){
var parent = clickedElement.parentElement;
var button1 = clickedElement.cloneNode(true);
var button2 = clickedElement.cloneNode(true);
parent.appendChild(button1);
parent.appendChild(button2);
parent.removeChild(clickedElement);
}
window.onload = function() {
spawnHead();
};
var headNumber = 0;
function spawnHead() {
++headNumber;
var head = document.createElement('BUTTON');
var text = document.createTextNode('Hydra Head ' + headNumber + '!');
head.appendChild(text);
head.addEventListener('click',function(event) {
cutHead(event);
});
document.body.appendChild(head);
}
function cutHead(event){
document.body.removeChild(event.currentTarget);
setTimeout(function() {spawnHead()}, 1000);
setTimeout(function() {spawnHead()}, 3000);
}
Instead of attaching event listeners to each new node. Use event delegation and check what was clicked
HTML:
<button id="hydra">HydraBoss</button>
JS:
const hydra = document.getElementById('hydra')
let count = 0
function destroy(e) {
let currId = e.target.id
if(currId.indexOf('hydra') > -1) {
let node = e.target
let child1 = document.createElement('button')
child1.id = 'hydra-' + ++count
child1.textContent = 'hydra-' + count
let child2 = document.createElement('button')
child2.id = 'hydra-' + ++count
child2.textContent = 'hydra-' + count
node.parentNode.appendChild(child1)
node.parentNode.appendChild(child2)
node.parentNode.removeChild(node)
}
}
document.addEventListener('click', destroy)
There are a couple pitfalls such as apply a click listener to buttons.... The following would apply multiple listeners to buttons and may cause multiple heads to appear. Additionally, it does not create new buttons, just copies of the one being destroyed.
$(document).ready(function(){
attack();
});
function attack(){
$('button').click(function(){
$(this).destroy();
$('#hydra').append(this);
$('#hydra').append(this);
attack();
});
};
- Sumitro November 23, 2013