Skip to content

Instantly share code, notes, and snippets.

@bruno2ms
Created July 30, 2018 13:06
Show Gist options
  • Save bruno2ms/ef4abb7b337b390f46bd1acaab2dd778 to your computer and use it in GitHub Desktop.
Save bruno2ms/ef4abb7b337b390f46bd1acaab2dd778 to your computer and use it in GitHub Desktop.
Textarea handle tab
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);
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