Introduction
Vigenere Cipher is used to encode original string to random string, with a given keyword.
Components
- Keyword Input Component
- Keywords Display Component
- Source Text Input Component
- Source Text Display Component
- Cipher Text Display Component
Model & Events
Model
1
2
3
4
5
6
7let valid = true
let kw_to_be = []
let kw = []
let kw_idx = 0
let kw_char_row = []
let kw_num_row = []
let ciph_row = []Events
1
2
3
4
5
6
7
8
9
10
11// 2.1 keyword input event handler
function inputHandler(e){}
// 2.2 source click button event handler
function clickHandler(id){}
// 2.3 update button event handler
function updateBtnHandler(){}
// 2.4 clear button event handler
function clearBtnHandler(){}
Layout & Logic
Code Implementation
HTML
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
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- 1. Keyword Input Component -->
<h1><span>Configuration</span></h1> <p>Keyword</p>
<div className="comp">
<input id="inputBox" type="text" />
<button id="updateBtn" >Update</button>
<ul id="validation">
<li>Length of keyword should be in range: 3~8 </li>
<li>Characters should be uppercase</li>
</ul>
</div>
<!-- 2. Keyword Display Component -->
<table class="comp"><tbody>
<tr id="kwCharRow"></tr>
<tr id="kwNumRow"></tr>
</tbody></table>
<!-- 3. Source Text Input Component -->
<h1><span>Encoding</span></h1> <p>Source Text</p>
<table class="comp"><tbody>
<tr id="srcTextRow"></tr>
<tr id="ciphTextRow"></tr>
</tbody></table>
<!-- 4. Source Text Display Component -->
<div class="comp">
<input id="srcText" type="text" disabled />
<button id="clearBtn">Clear</button>
</div>
<!-- 5. Cipher Text Display Component -->
<div class="comp">
<p>Cipher Text</p>
<input id="ciphText" type="text" disabled />
</div>
<script src="script.js"></script>
</body>
</html>JS
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142(function (){
// 0.1 const
const CHAR_NUM = 26
const CHAR_CODE_A = 65
const CHAR_CODE_Z = 90
const CHAR_CODE_ALL = new Array(CHAR_NUM).fill(1).map( ( _, i ) => (CHAR_CODE_A+i) )
const CHAR_ALL = CHAR_CODE_ALL.map(item=>String.fromCharCode(item))
// 0.2 helper functions
const getEle = (id) => document.getElementById(id)
const setEleVal = (ele, val)=> {ele.value = val}
const creatEle = (tag) => document.createElement(tag)
const creatText = (str) => document.createTextNode(str)
const generateEle = ( tag, data, parent )=>{
let tempNode = document.createDocumentFragment()
data.forEach((item, index)=>{
const td = creatEle('TD')
const text = creatText(item)
if( tag === 'srcTextRow' ){
const btn = creatEle('BUTTON')
btn.appendChild(text)
btn.onclick = function(){clickHandler(index)}
td.appendChild(btn)
}else{
td.appendChild(text)
}
tempNode.appendChild(td)
})
while (parent.firstChild) { parent.removeChild(parent.firstChild) }
parent.appendChild(tempNode)
}
const updateCiphTextRow = (kw_idx)=>{
const offset = kw[kw_idx].charCodeAt(0) - CHAR_CODE_A
return CHAR_CODE_ALL.map(item=>{
const code = (item+offset <= CHAR_CODE_Z) ? (item+offset) : (item+offset-CHAR_NUM)
return String.fromCharCode(code)
})
}
const updateHighlightIndex = (id)=>{
kwCharRow.childNodes.forEach( function(item, index){
item.className = id===index ? "highlight" : ""
})
kwNumRow.childNodes.forEach( function(item, index){
item.className = id===index ? "highlight" : ""
})
}
// 0.3 DOM Elements
const inputBox = getEle("inputBox")
const errorHint = getEle("validation")
const updatBtn = getEle("updatBtn")
const kwCharRow = getEle("kwCharRow")
const kwNumRow = getEle("kwNumRow")
const srcTextRow = getEle("srcTextRow")
const ciphTextRow = getEle("ciphTextRow")
const srcText = getEle("srcText")
const clearBtn = getEle("clearBtn")
const ciphText = getEle("ciphText")
/*
1. models
*/
let valid = true
let kw_to_be = []
let kw = []
let kw_idx = 0
let kw_char_row = []
let kw_num_row = []
let ciph_row = []
/*
2. event handlers & DOM manipulation
*/
// 2.1 keyword input event handler
function inputHandler(e){
kw_to_be = e.target.value.split("")
const len = kw_to_be.length
const lenValid = (len>=3 && len<=8)
const caseValid = kw_to_be.every(
item => item==item.toUpperCase()
)
const validNew = lenValid && caseValid
if(valid!==validNew){
valid = validNew
errorHint.classList.toggle("invalid")
}
}
inputBox.oninput=inputHandler
// 2.2 source click button event handler
function clickHandler(id){
if(kw.length === 0 ) return
srcText.value = srcText.value + CHAR_ALL[id]
ciphText.value = ciphText.value + ciph_row[id]
kw_idx = kw_idx+1 < kw.length ? kw_idx+1 : kw_idx+1-kw.length
ciph_row = updateCiphTextRow(kw_idx)
generateEle("ciphTextRow", ciph_row, ciphTextRow)
updateHighlightIndex(kw_idx)
}
// 2.3 update button event handler
function updateBtnHandler(){
if(!valid) return
kw = kw_to_be
kw_idx = 0
const kw_num = kw.map(item=>item.charCodeAt(0)-CHAR_CODE_A)
ciph_row = kw.length===0 ? [] : updateCiphTextRow(kw_idx)
generateEle("kwCharRow", kw, kwCharRow)
generateEle("kwNumRow", kw_num, kwNumRow)
generateEle("ciphTextRow", ciph_row, ciphTextRow)
updateHighlightIndex(kw_idx)
srcText.value = ""
ciphText.value = ""
}
updateBtn.onclick=updateBtnHandler
// 2.4 clear button event handler
function clearBtnHandler(){
kw_idx = 0
ciph_row = updateCiphTextRow(kw_idx)
updateHighlightIndex(kw_idx)
generateEle("ciphTextRow", ciph_row, ciphTextRow)
srcText.value = ""
ciphText.value = ""
}
clearBtn.onclick=clearBtnHandler
// populate 'A'~'Z' in srcTextRow
let tempNode = document.createDocumentFragment()
generateEle("srcTextRow", CHAR_ALL, srcTextRow)
})();CSS
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
44table{
border: 1px solid black;
border-collapse:collapse;
text-align: center;
}
table td {
border: 1px solid black;
padding: 5px;
width: 20px;
height: 20px;
}
h1{
margin-top: 30px;
}
h1 span{
color: grey;
border-bottom: 1px solid ;
}
input[disabled]{
background-color:#F5F5DC;
width: 200px;
}
ul{
display: none;
}
.invalid{
display: block;
color: red;
}
.highlight{
background-color: yellow;
}
.comp{
margin: 5px 0;
}