Created
July 30, 2018 13:06
-
-
Save bruno2ms/ef4abb7b337b390f46bd1acaab2dd778 to your computer and use it in GitHub Desktop.
Textarea handle tab
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const tab = (text, start = 0, end = start, tab_size = 4) => { | |
let tab = ' '.repeat(tab_size); | |
let lines = splitLines(text); | |
let indexes = getStartIndexes(lines); | |
indexes.push(text.length); | |
if (start == end) { | |
return `${text.slice(0, start)}${tab}${text.slice(start, text.length)}`; | |
} else if (lines.length == 1) { | |
return `${tab}${text}`; | |
} else { | |
return lines.map((line, idx) => { | |
if (start < indexes[idx + 1] && end > indexes[idx]) { | |
return `${tab}${line}`; | |
} else { | |
return `${line}`; | |
} | |
}).join(''); | |
} | |
}; | |
export const backTab = (text, start = 0, end = start, tab_size = 4) => { | |
let lines = splitLines(text); | |
let indexes = getStartIndexes(lines); | |
const regex = /^(\s{0,4})(.*)/gm; | |
const subst = `$2`; | |
indexes.push(text.length); | |
if (start == end) { | |
return `${text.slice(0, start)}${tab}${text.slice(start, text.length)}`; | |
} else if (lines.length == 1) { | |
return text.replace(regex, subst); | |
} else { | |
return lines.map((line, idx) => { | |
if (start < indexes[idx + 1] && end > indexes[idx]) { | |
return line.replace(regex, subst); | |
} else { | |
return `${line}`; | |
} | |
}).join(''); | |
} | |
} | |
export const splitLines = str => { | |
const regex = /^.*\n?/gm; | |
let match; | |
let split = []; | |
while ((match = regex.exec(str)) !== null) { | |
if (match.index === regex.lastIndex) { | |
regex.lastIndex++; | |
} | |
match.forEach(match => { | |
split.push(match); | |
}); | |
} | |
return split; | |
}; | |
export const getStartIndexes = textArray => { | |
let startIndexes = [0]; | |
textArray.forEach((el, idx) => { | |
if (idx > 0) { | |
startIndexes.push(startIndexes[idx - 1] + textArray[idx - 1].length); | |
} | |
}); | |
return startIndexes; | |
}; | |
export const verifyTab = (e) => { | |
const keyCode = e.keyCode || e.which; | |
const target = e.currentTarget; | |
const start = target.selectionStart; | |
const end = target.selectionEnd; | |
const length = target.value.length; | |
if (keyCode == 9 && e.shiftKey) { | |
target.value = backTab(target.value, target.selectionStart, target.selectionEnd); | |
if (start == end) { | |
target.selectionStart = target.selectionEnd = start - 4; | |
} else { | |
target.setSelectionRange(start - 4, end + target.value.length - length); | |
} | |
e.preventDefault(); | |
} else if (keyCode == 9) { | |
target.value = tab(target.value, target.selectionStart, target.selectionEnd); | |
if (start == end) { | |
target.selectionStart = target.selectionEnd = start + 4; | |
} else { | |
target.setSelectionRange(start + 4, end + target.value.length - length); | |
} | |
e.preventDefault(); | |
} | |
}; | |
// let textarea = document.getElementById('textarea'); | |
// textarea.addEventListener('keydown', verifyTab); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { tab, splitLines, getStartIndexes, backTab } from './tab.js'; | |
let single_line = 'abcde'; | |
let multi_line = `abcde | |
abcde | |
abcde | |
abcde`; | |
test('tab single line', () => { | |
expect(tab(single_line)).toBe(' abcde'); | |
}); | |
test('tab single line with start index on 3', () => { | |
expect(tab(single_line, 3)).toBe('abc de'); | |
}); | |
test('tab multi line text with start index on 0', () => { | |
expect(tab(multi_line, 0)).toBe(` abcde | |
abcde | |
abcde | |
abcde`); | |
}); | |
test('split lines of single line text', () => { | |
expect(splitLines(single_line)).toEqual([single_line]); | |
}); | |
test('split lines of multiline text', () => { | |
expect(splitLines(multi_line)).toEqual(['abcde\n', 'abcde\n', 'abcde\n', 'abcde']); | |
}); | |
test('get indexes of single line text', () => { | |
expect(getStartIndexes(splitLines(single_line))).toEqual([0]); | |
}); | |
test('get indexes of multiline text', () => { | |
expect(getStartIndexes(splitLines(multi_line))).toEqual([0, 6, 12, 18]); | |
}); | |
test('tab single line text with start 1 and end 2', () => { | |
expect(tab(single_line, 1, 2)).toBe(' abcde'); | |
}); | |
test('tab multiline text with indexes 1 and 2', () => { | |
expect(tab(multi_line, 1, 2)).toBe(` abcde | |
abcde | |
abcde | |
abcde`); | |
}); | |
test('tab multiline text with indexes 1 and 7', () => { | |
expect(tab(multi_line, 1, 7)).toBe(` abcde | |
abcde | |
abcde | |
abcde`); | |
}); | |
test('tab multiline text with indexes 5 and 7', () => { | |
expect(tab(multi_line, 5, 7)).toBe(` abcde | |
abcde | |
abcde | |
abcde`); | |
}); | |
test('tab multiline text with indexes 18 and 19', () => { | |
expect(tab(multi_line, 18, 19)).toBe(`abcde | |
abcde | |
abcde | |
abcde`); | |
}); | |
test('tab multiline text with indexes 15 and 19', () => { | |
expect(tab(multi_line, 15, 19)).toBe(`abcde | |
abcde | |
abcde | |
abcde`); | |
}); | |
test('tab single line text with start 1 and end 2', () => { | |
expect(backTab(' abcde', 1, 2)).toBe(single_line); | |
}); | |
test('tab multiline text with indexes 21 and 31', () => { | |
let text = `abcde | |
abcde | |
abcde | |
abcde` | |
expect(backTab(text, 21, 31)).toBe(multi_line); | |
}); | |
test('tab multiline text with indexes 21 and 31', () => { | |
let text = ` abcde | |
abcde | |
abcde | |
abcde` | |
expect(backTab(text, 1, 2)).toBe(multi_line); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment