Полезные мини-скрипты на JavaScript
сейчас в списке: 33 скрипта Этот список будет включать в себя небольшие задачи на JavaScript, поменьше объёмом, чем вот эти, и, в общем, представляющие собой законченные мини-приложения, если вставить код в тело любого документа HTML5 в кодировке Юникода UTF-8.
Полезные алгоритмы есть также в этой заметке (с JS-массивами), на сайте nickolay.info в разделе по JavaScript и просто по соответствующему тегу блога.
Список будет пополняться, для быстрого поиска на странице нужного слова используйте комбинацию клавиш Ctrl+F в браузере.
1. Разметить строку посимвольно случайными тегами из разрешённого набора, аналог текстовой капчи
<div id="captcha"></div> <script> function rndFormat (text) { let tags = [ '<i>', '<b>', '<u>', '<sup>', '<sub>', '<big>', '<small>' ]; let result = ''; for (let i=0; i<text.length; i++) { let num=Math.floor(Math.random()*tags.length); result += tags[num] + text[i] + '</' + tags[num].substring(1); } return result; } document.getElementById('captcha').innerHTML = rndFormat('Hello!'); </script>
2. Проверить корректность даты
Проще всего задействовать стандартный объект Date
.
<script> function validate_date (id) { let arrD = document.getElementById(id).value.split('.'); arrD[1]--;//у обьекта date отсчет месяцев начинается с нуля let dt = new Date(arrD[0], arrD[1], arrD[2]); //встроенный обьект return ( (dt.getFullYear() == arrD[0]) && (dt.getMonth() == arrD[1]) && (dt.getDate() == arrD[2]) ? true : false); } </script> <input type="text" id="dt0" size="25" maxlength="10" placeholder="дата в формате ГГГГ.ММ.ДД"> <input type="button" value="Проверить" onclick="document.getElementById('dateResult').innerHTML = validate_date('dt0');"> <span id="dateResult"></span>
3. Найти день недели по формуле Зеллера
Здесь мы получаем день недели не из объекта, а считаем по формуле. Без parseInt
в функции будет считать неправильно :)
Функция pad
дополняет слева натуральное число n
до size
разрядов нулями.
<script> function weekday (id) { let arrD = document.getElementById(id).value.split('.'); let y = parseInt(arrD[0]), m = parseInt(arrD[1]), d = parseInt(arrD[2]), dday = -1; //корректность даты не проверяется! if (m<3) { m+=12; y--; } let n = y%100, c = Math.floor(y/100); dday= (Math.floor((m+1)*26/10)+d+n+Math.floor(n/4)+Math.floor(c/4)-2*c) % 7; let wday = new Array ('Сб','Вс','Пн','Вт','Ср','Чт','Пт'); function pad (n,size) { return String(Array(size-1).fill('0').join('')+n).slice(-size); } return pad(arrD[2],2)+'.'+pad(arrD[1],2)+'.'+pad(arrD[0],4)+'='+wday[dday]; } </script> <input type="text" id="dt0" size="25" maxlength="10" placeholder="дата в формате ГГГГ.ММ.ДД"> <input type="button" value="Вычислить" onclick="document.getElementById('dateResult').innerHTML = weekday('dt0');"> <span id="dateResult"></span>
4. По заданным интенсивностям красного, зелёного и синего цветов получить строку вида rgb(23,100,134)
Дополнительно код показывает цвет фоном раздела rgbResult
.
<script> function rgb (r0=0,g0=0,b0=0) { let r = Math.max(0,Math.min(r0,255)), g = Math.max(0,Math.min(g0,255)), b = Math.max(0,Math.min(b0,255)); return 'rgb('+r+','+g+','+b+')'; } function pad3 (i) { return String('00' + i).slice(-3); } //'0'=>'000', '10'=>'010' </script> <div id="rgbResult"> </div> <span id="red_sel" style="font-family: monospace; background-color: red;">128</span> <input type="range" id="red_val" min="0" max="255" step="1" value="128" onchange="document.getElementById('red_sel').innerHTML = pad3(this.value);"> <span id="green_sel" style="font-family: monospace; background-color: green;">128</span> <input type="range" id="green_val" min="0" max="255" step="1" value="128" onchange="document.getElementById('green_sel').innerHTML = pad3(this.value);"> <span id="blue_sel" style="font-family: monospace; background-color: #3333ff;">128</span> <input type="range" id="blue_val" min="0" max="255" step="1" value="128" onchange="document.getElementById('blue_sel').innerHTML = pad3(this.value);"> <input type="button" value="Выполнить" onclick="let c = rgb(document.getElementById('red_val').value, document.getElementById('green_val').value, document.getElementById('blue_val').value); document.getElementById('rgbResult').style.backgroundColor = c; document.getElementById('rgbString').innerHTML = c;"> <span id="rgbString" style="font-family: monospace;"></span>
5. Выбрать случайную строку из набора строк (случайный элемент массива)
<script> function randomText() { let arr= [ 'Текст 1', 'Текст 2', 'Текст 3', 'Текст 4', 'Текст 5', 'Текст 6', 'Текст 7', 'Текст 8', 'Текст "9"', 'Текст \'10\'' ]; return arr[Math.floor(Math.random()*arr.length)]; } </script> <div onclick="this.innerHTML=randomText();">Нажми меня!</div>
6. Поменять местами два значения в форме
<form> <input type="text" id="a" size="4" maxlength="3"> <input type="text" id="b" size="4" maxlength="3"> <input type="button" value="Поменять местами" onclick="f('a','b'); return false;"> </form> <script> function f(id1,id2) { let a = document.getElementById(id1).value; let b = document.getElementById(id2).value; let temp = a; a = b; b = temp; document.getElementById(id1).value = a; document.getElementById(id2).value = b; } </script>
Если значения должны быть целыми числами и обмен выполняется с проверкой и коррекцией данных, то так (обмен делается арифметически для разнообразия):
<form> <input type="text" id="a" size="4" maxlength="3"> <input type="text" id="b" size="4" maxlength="3"> <input type="button" value="OK" onclick="f('a','b'); return false;"> </form> <script> function f(id1,id2) { let a = parseInt(document.getElementById(id1).value); if (isNaN(a)) a = 0; let b = parseInt(document.getElementById(id2).value); if (isNaN(b)) b = 0; a += b; b = a - b; a -= b; document.getElementById('a').value = a; document.getElementById('b').value = b; } </script>
7. Табулировать произвольную функцию одного аргумента в заданных пределах
Пределы и функция передаются аргументами в tab
.
<div id="table"></div> <script> function tab (x1,dx,x2,f) { let s='<pre>'+"\n"; for (let x=x1; x<=x2; x+=dx) { s += x.toFixed(3).toString().padStart(10)+' '+f(x).toFixed(3).toString().padStart(10)+"\n"; } return s+'</pre>'; } let f = function (x) { return Math.sin(x); } let div = document.getElementById('table'); div.innerHTML = tab(0,Math.PI/10,2*Math.PI,f); </script>
8. Заменить символы табуляции пробелами без изменения внешнего вида текста
Как известно, табуляция позволяет "перескочить" в текстовом редакторе на следующую позицию, кратную восьми (необязательно, но чаще всего). Если размер табуляции в вашем текстовом редакторе иной - текст может "разъехаться" далеко вправо и стать нечитабельным. В общем, бывает спокойнее, когда символа табуляции нет совсем, а выравнивание текста терять обычно не хочется (имеются в виду, конечно, редакторы неформатированного текста и с моноширинными шрифтами, которыми, как правило, программисты пишут листинги).
Код, показанный ниже, удаляет из элемента src
символы табуляции, стараясь корректно заменить их пробелами, и помещает результат обработки в элемент res
.
<script> function detab (text, tsize = 8) { let arr = text.split("\n"); let res = ''; for (let i = 0; i<arr.length; i++) { let str = arr[i], newstr = ''; for (let k = 0; k < str.length; k++) { if (str[k] == '\t') { let newlen = newstr.length; for (let j = 0; j < tsize - newlen % tsize; j++) newstr += ' '; } else newstr += str[k]; } res += newstr + (i<arr.length-1 ? '\n' : ''); } return res; } </script> <textarea id="src" rows="5" cols="90" style="font-family: monospace;"> 123 вторая позиция, в следующей строке одни табуляции 0 11 222 3333 4444 55555 666666 7777777 88888888 9 </textarea> <br> <textarea id="res" rows="5" cols="90" style="font-family: monospace;"></textarea> <br> <button onclick="document.getElementById('res').value = detab (document.getElementById('src').value);"> ok</button>
9. Как "подогнать" размеры канвы под нужные пиксельные размеры рисунка?
<canvas id="canvas1" style="border: 1px dotted red;"></canvas> <img id="image1" src="kar.jpg" style="visibility: hidden;"> <script> let canvas = document.getElementById('canvas1'); let ctx = canvas.getContext('2d'); let imageObj = new Image(); imageObj.src = document.getElementById("image1").src; imageObj.onload = function () { canvas.width = imageObj.width; canvas.height = imageObj.height; ctx.drawImage(imageObj,0,0,imageObj.width,imageObj.height,0,0,canvas.width,canvas.height); }; </script>
Здесь оригинальный рисунок (с именем kar.jpg
из текущей папки скрипта) скрыт стилем, а показан размещённый в канве.
Можно, конечно, и масштабировать рисунок по канве как здесь, и перестраивать изображение при масштабировании окна.
10. Как загрузить файл с рисунком на canvas? Как обработать файл на canvas попиксельно?
Для загрузки файла используется современный подход через FileReader. Рисунок загружается в верхнюю канву, а результат его попиксельной обработки фильтром - в нижнюю. В данном случае фильтрация функцией sepia сводится к наложению одноимённого эффекта.
<input type="file" id="imageLoader"> <br> <canvas id="sourceCanvas"></canvas> <br> <canvas id="targetCanvas"></canvas> <script> let imageLoader = document.getElementById('imageLoader'); imageLoader.addEventListener('change', handleImage, false); let sourceCanvas = document.getElementById('sourceCanvas'); let ctx = sourceCanvas.getContext('2d'); let targetCanvas = document.getElementById('targetCanvas'); function handleImage (e) { let reader = new FileReader(); reader.onload = function (event) { let img = new Image(); img.onload = function() { sourceCanvas.width = targetCanvas.width = img.width; sourceCanvas.height = targetCanvas.height = img.height; ctx.drawImage (img, 0, 0, img.width, img.height); let data = ctx.getImageData(0,0,img.width, img.height); sepia (data, img); } img.src = event.target.result; } reader.readAsDataURL (e.target.files[0]); } function sepia (imageData, img) { let pixels = imageData.data; for (let i = 0; i < pixels.length; i += 4) { let r = pixels[i]; let g = pixels[i + 1]; let b = pixels[i + 2]; pixels[i] = (r * 0.393)+(g * 0.769)+(b * 0.189); pixels[i + 1] = (r * 0.349)+(g * 0.686)+(b * 0.168); pixels[i + 2] = (r * 0.272)+(g * 0.534)+(b * 0.131); } let ctx = targetCanvas.getContext("2d"); ctx.drawImage (img, 0, 0, img.width, img.heigth); ctx.putImageData (imageData, 0, 0); } </script>
11. Как умножить 2 длинных натуральных числа?
В блоге есть подобное на C++, но компилировать-то обычно лень, пусть будет ещё на JS.
<script> function mult(strNum1,strNum2){ let a1 = strNum1.split("").reverse(); let a2 = strNum2.toString().split("").reverse(); let aResult = new Array(); for ( let iterNum1 = 0; iterNum1 < a1.length; iterNum1++ ) { for ( let iterNum2 = 0; iterNum2 < a2.length; iterNum2++ ) { let idxIter = iterNum1 + iterNum2; aResult[idxIter] = a1[iterNum1] * a2[iterNum2] + ( idxIter >= aResult.length ? 0 : aResult[idxIter] ); if ( aResult[idxIter] > 9 ) { aResult[idxIter + 1] = Math.floor( aResult[idxIter] / 10 ) + ( idxIter + 1 >= aResult.length ? 0 : aResult[idxIter + 1] ); aResult[idxIter] %= 10; } } } return aResult.reverse().join(""); } </script> <input type="text" maxlength="99" size="100" id="num1"> <br> <input type="text" maxlength="99" size="100" id="num2"> <br> <input type="button" value="Умножить" onclick="document.getElementById('res').innerHTML= mult(document.getElementById('num1').value,document.getElementById('num2').value);"> <div id="res"></div>
12. Сгенерировать случайный текст на основе последовательности фраз
Примерно как здесь, только проще и на стороне клиента.
<div id="textContent"></div> <script> function generateText (id, n) { let count = parseInt(n); if (isNaN(count) || count<1) count = 1; let w1 = new Array ("Товарищи,", "С другой стороны", "Равным образом", "Не следует однако забывать, что", "Таким образом,", "Повседневная практика показывает, что", "Разнообразный и богатый опыт", "Задача организации, в особенности же", "Идейные соображения высшего порядка, а также"); let w2 = new Array ("реализация намеченных плановых заданий", "рамки и место обучения кадров", "постоянный количественный рост и сфера нашей активности", "сложившаяся структура организации", "новая модель организационной деятельности", "дальнейшее развитие различных форм деятельности", "постоянное информационно-пропагандистское обеспечение нашей деятельности", "укрепление и развитие структуры", "консультация с широким активом", "начало повседневной работы по формированию позиции"); let w3 = new Array ("играет важную роль в формировании", "требует определения и уточнения", "способствует подготовке и реализации", "обеспечивает широкому кругу специалистов участие в формировании", "позволяет выполнить важные задания по разработке", "в значительной степени обусловливает создание", "позволяет оценить значение", "представляет собой интересный эксперимент проверки", "влечет за собой процесс внедрения и модернизации"); let w4 = new Array ("существенных финансовых и административных условий", "дальнейших направлений развития", "системы массового участия", "позиций, занимаемых участниками в отношении поставленных задач", "новых предложений", "направлений прогрессивного развития", "системы обучения кадров, соответствующей насущным потребностям", "соответствующих условий активизации", "модели развития", "форм воздействия"); let phrase = ""; for (let i = 0; i < count; i++) { let rnd1 = Math.floor(Math.random() * w1.length); let rnd2 = Math.floor(Math.random() * w2.length); let rnd3 = Math.floor(Math.random() * w3.length); let rnd4 = Math.floor(Math.random() * w4.length); phrase += "<p>" + w1[rnd1] + " " + w2[rnd2] + " " + w3[rnd3] + " " + w4[rnd4] + ".</p>\n"; } document.getElementById(id).innerHTML = phrase; } generateText('textContent',4); //id раздела, количество предложений </script>
13. Составить частотную таблицу слов в документе
Что входит в "слова" - видно из text.replace
, таблица формируется просто по порядку встречаемости слов в тексте. Предполагается только латиница и/или кириллица, регистр символов должен игнорироваться.
<p>Текст</p> <textarea id="input_text"></textarea> <br> <button id="btn">Анализировать</button> <table width="200" style="border-collapse: collapse;"> <caption>Таблица частот слов</caption> <thead> <tr> <th>Слово</th> <th>Частота</th> </tr> <thead> <tbody id="tbody"></tbody> </table> <script> let input = document.getElementById('input_text'); let btn = document.getElementById('btn'); let tbody = document.getElementById('tbody'); let wordsArray = []; function countFrequency() { if (tbody.hasChildNodes()) { while (tbody.firstChild) { tbody.removeChild(tbody.firstChild); } } let text = input.value.toString(); text = text.replace(/[^\w\s\A-Za-zА-Яа-яЁё0-9\-]/gi,' '); //что входит в "слова" words = text.split(/\s/).filter(function(x){return x.length>0; }); //убрали пустые for (let word of words) { word = word.toLowerCase(); let row = document.getElementById('tr-'+word); if (row == null) { let tr = document.createElement('tr'); tr.id = 'tr-'+word; let td1 = document.createElement('td'); let td2 = document.createElement('td'); td1.innerHTML = word; td2.innerHTML = 1; tr.appendChild(td1); tr.appendChild(td2); tbody.appendChild(tr); } else { let value = row.childNodes[1].innerHTML; value++; row.childNodes[1].innerHTML = value; } } } btn.addEventListener('click',countFrequency); </script>
14. Получить в разделе документа календарь на произвольные месяц и год
Всё пишется в раздел с id="calendar"
<style> .mtab { margin: 0 auto; width: 32rem; font-family: monospace; border-spacing: 1.5rem 0; } .mrow { } .mcol { text-align: left; } .mp { margin: 0.25rem 0; } </style> <div class="mtab"> <form name="dataForm" id="dataForm" class="mtab"> <select size="1" name="monthList" id="monthList"></select> <script> let d = new Date(), m = d.getMonth(), str = ''; let names = new Array ('Январь','Февраль','Март','Апрель','Май','Июнь', 'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'); for (let i=0; i<12; i++) str += '<option value="'+i+'"'+(i==m?' selected':'')+'>'+names[i]+'</option>'+"\n"; document.getElementById('monthList').innerHTML = str+"\n"; </script> <select size="1" name="yearsList" id="yearsList"></select> <script> let y = d.getFullYear(), y2 = y + 100, y1 = 1582; str = ''; for (let i=y2; i>=y1; i--) str += '<option value="'+i+'"'+(i==y?' selected':'')+'>'+i+'</option>'+"\n"; document.getElementById('yearsList').innerHTML = str+"\n"; </script> <input type="button" value="Сформировать" onclick="Calendar(document.dataForm.monthList.options[document.dataForm.monthList.selectedIndex].value, document.dataForm.yearsList.options[document.dataForm.yearsList.selectedIndex].value,'calendar');"> <input type="button" value="Текущий" onclick="currentCalendar('calendar');"> </form> </div> <div id="calendar" class="mtab"></div> <script> function Calendar(m,y,id) { //месяц (с 0), год (полный), id раздела, куда вставить календарь function isLeapYear (y) { return (((y%4==0) && (y%100!=0) || (y%400==0)) ? true : false); } function getDaysInMonth (m,y) { let mondays = [31,28,31,30,31,30,31,31,30,31,30,31]; if (isLeapYear (y) == true) mondays[1]=29; return (mondays[m]); } let s = '<table class="mtab">'+"\n", d = new Date(y,m,1), w = d.getDay(), maxd = getDaysInMonth(m,y); if (w == 0) w = 6; else w--; let arr = Array(maxd).fill(0).map(function(val,index){return index+1;}); //1..maxd for (let i=0; i<w; i++) arr.unshift(' '); //пустые дни впереди for (let i=arr.length; i<42; i++) arr.push(' '); //пустые дни в конце s += '<tr class="mrow">'+"\n"; let wd = new Array ('Пн','Вт','Ср','Чт','Пт','Сб','Вс'); for (let i=0; i<7; i++) s += '<th>'+wd[i]+'</th>'+"\n"; s += '</tr>'+"\n"; let k = 0; for (let r=0; r<6; r++) { s += '<tr class="mrow">'+"\n"; for (let c=0; c<7; c++) { s += '<td class="mcol"><p class="mp">'+arr[k++]+'</p></td>'+"\n"; } s += '</tr>'+"\n"; } s += '</table>'+"\n"; document.getElementById(id).innerHTML = s; } function currentCalendar (id) { let d = new Date(), m = d.getMonth(), y = d.getFullYear(); document.dataForm.monthList.selectedIndex = m; document.dataForm.yearsList.selectedIndex = 100; Calendar(m,y,id); } </script> <noscript> <div class="mtab">Включите JavaScript для работы приложения</div> </noscript>
15. Получить список тегов документа
Берутся теги внутри <body>
<script> function getTags() { function walk(node) { var child, next; if (node.nodeType) { if (node.tagName !== undefined) tags.push(node.tagName); child = node.firstChild; while ( child ) { next = child.nextSibling; walk(child); child = next; } } } let elem = document.body; let tags = new Array(); walk (elem); return tags.join("\n"); //список названий тегов, разделенных переводом строки } </script> <p>Просто, чтоб были теги</p> <p></p> <img></img> <img></img> <img></img> <h5></h5> <p></p> <h5></h5> <button onclick="document.getElementById('result').innerHTML = getTags();">OK</button> <pre id="result"></pre>
16. Дата плюс/минус количество дней
В зависимости от знака второго аргумента, получаем новую дату, отстоящую от даты первого аргумента назад или вперёд на нужно количество дней.
<script> function getDateAgo (date, days) { let dateCopy = new Date(date); dateCopy.setDate(date.getDate() + days); return dateCopy; } alert( getDateAgo(new Date(), -30)); </script>
17. Самосчётная функция
Без привлечения внешней переменной считаем , сколько раз была вызвана функция
<script> function cnt() { if ( typeof(cnt.c) == 'undefined' ) { cnt.c = 0; } cnt.c++; return cnt.c; } cnt(); cnt(); let n=cnt(); alert(n); </script>
18. Упрощение дроби
Вводим из формы целые значения для числителя и знаменателя, сокращаем дробь, учитывая знак и особые случаи.
<form name="dataform"> <p>Введите числитель: <input type="number" name="num" value="0"></input></p> <p>Введите знаменатель: <input type="number" name="denom" value="0"></input></p> <input type="button" value="Упростить" onclick="document.getElementById('result').innerHTML = simplifyFraction(document.dataform.num.value,document.dataform.denom.value);"> </form> <div id="result"></div> <script> function simplifyFraction (num,denom) { let M = parseInt(num), N = parseInt(denom); let sgn = 0; if (M<0) sgn++; if (N<0) sgn++; sgn %= 2; //- на - дает снова + let m = Math.abs(M), n = Math.abs(N); M = m, N = n; if (!n) return (sgn?'-':'')+'∞'; for (let i = 2; i <= m; i++) { if (m % i == 0 && n % i == 0) { M = m / i; N = n / i; } } return (sgn?'-':'') + M + (N!=1 ? '/'+N : ''); } </script>
19. Отрисовка на канве геометрического примитива
Здесь мы изобразим суперэллипс.
<canvas id="canvas" style="border: 1px dotted red;"></canvas> <script> function start (id,n,a,b) { function point (x, y) { ctx.fillRect( x, y, 1, 1); } let canvas = document.getElementById(id); const PADDING = 20; //отступ let size = 2*Math.max(a,b)+PADDING; //размер канвы зависит от a,b canvas.width = canvas.height = size; let ctx = canvas.getContext( "2d" ); ctx.rect (0, 0, canvas.width, canvas.height); ctx.fillStyle = "#fff"; ctx.fill(); //белая заливка ctx.fillStyle = "#000"; //отрисовка чёрным for (let t=0; t <= 2*360; t += 0.1) { //прорисовываем дважды для надёжности x = Math.pow( Math.abs( Math.cos( t ) ), 2 / n ) * a * Math.sign( Math.cos( t ) ); y = Math.pow( Math.abs( Math.sin( t ) ), 2 / n ) * b * Math.sign( Math.sin( t ) ); point (x + ( canvas.width >> 1 ), y + ( canvas.height >> 1 )); } } start ('canvas',2.5,200,200); </script>

нарисованный суперэллипс, скриншот
20. Как извлечь из текстового содержимого только числа в любой допустимой записи?
Метод getArrayFromTextarea
извлекает и возвращает массив чисел из значения текстового контейнера с id==srcId
. Обратите внимание также на "гибкую" функцию очистки полей clearMe
.
<script> function getArrayFromTextarea (srcId) { let text = document.getElementById(srcId).value; let arr = text.split(/\s+/); arr = arr.filter( function(item){ return item!='' && !isNaN(item) && isFinite(item); }); return arr; } function clearMe (...ids) { //очистить элементы из ids if (ids === undefined) return; for (let id in ids) { let elem = document.getElementById(ids[id]); if (!elem) continue; elem.value = ''; } } function selectMe (id) { //выделить элемент с id document.getElementById(id).focus(); document.getElementById(id).select(); } </script> <noscript> <p>Включите Javascript в браузере для работы приложения</p> </noscript> <p>Введите или вставьте числа:</p> <p><textarea id="src" rows="5" cols="90" style="font=family: monospace;"></textarea></p> <p>Результат обработки:</p> <p><textarea id="res" rows="5" cols="90" style="font=family: monospace;"></textarea></p> <p> <button onclick="document.getElementById('res').value = getArrayFromTextarea('src').join('\n'); selectMe('res');">Выполнить</button> <button onclick="clearMe('src','res');">Очистить</button> </p>
21. Можно ли делать арифметические действия с длинными целыми числами нативными методами, а не "вручную", как в задаче 11?
В Javascript уже есть BigInt, правда, работает не везде.
В этом скрипте также особо вычурная функция clearMe
очистки нужных свойств у нужных элементов.
<script> function actionMe (id1, id2, action) { let n1 = BigInt(document.getElementById(id1).value), n2 = BigInt(document.getElementById(id2).value), res; switch (action) { case '*': res = n1 * n2; break; //добавьте другие действия default: res = 'Неверная операция'; break; } return res; } function clearMe (...ids) { //очистить свойства элемент property у элементов с id="item" из ids if (ids === undefined) return; for (let id in ids) { let idn = ids[id].item; let elem = document.getElementById(idn); if (!elem) continue; let prop = ids[id].property; if (!prop) continue; elem[prop] = ''; } } </script> <noscript> <p>Включите Javascript в браузере для работы приложения</p> </noscript> <p>Число 1: <input type="text" id="n1" size="80" maxlength="128" pattern="-?\d+"></p> <p>Число 2: <input type="text" id="n2" size="80" maxlength="128" pattern="-?\d+"></p> <p> <button onclick="document.getElementById('result').innerHTML = actionMe('n1','n2','*');">[*]</button> <button onclick="clearMe( {item: 'n1', property: 'value'}, {item: 'n2', property: 'value'}, {item: 'result', property: 'innerHTML'}, );">clear</button> </p> <p id="result"></p>
22. Как измерить время выполнения вычислительного процесса?
<script> let start, end; start = new Date(); for (let i = 0; i < 1e7; i++) { //10 миллионов шагов Math.sqrt(i); } end = new Date(); alert ((end.getTime() - start.getTime()) + ' мсек'); </script>
23. Как создать на странице динамический элемент, настроить его атрибуты и стилевые селекторы, добавить обработчик события и выполнение кода по таймеру?
Все ответы - в этом небольшом коде с комментариями.
<div id="content"></div> <!-- Элемент для контента --> <script> function onload (id) { //Функция-обёртка приложения let elem = document.getElementById(id); //Получить основной элемент для контента if (!elem) { console.log('Item id='+id+' not found'); return; } let child = document.createElement('p'); //Создать новый абзац child.setAttribute('align', 'center'); //Так можно настроить атрибуты тега child.style.backgroundColor = '#999'; //И стилевые селекторы child.innerHTML = 'Click me'; //И содержимое HTML child.addEventListener ('click', function(e) { click1(e); }); //Добавить обработчик события для элемента elem.appendChild (child); //Добавить сам элемент в основной function reDraw () { child.innerHTML = new Date(); } //Перерисовка function click1 (e) { //Выполнить reDraw и назначить её вызов с таймером 1 сек. reDraw(); let timer = setInterval(function () { reDraw(); }, 1000); } } window.addEventListener('load', function (e) { onload('content'); }, false); //Выполнить функцию-обёртку по загрузке страницы, без захвата событий </script>
24. Как избежать обращения из функций к "внешним" по отношению к коду элементам HTML?
Передавать в функции аргументами нужные данные из элементов HTML, если эти данные требуются функциям.
Функции пусть выполняют свою работу - получают данные через аргументы и возвращают результат работы в виде переменной, массива или объекта.
А если писать каждый раз
document.getElementById(id).value
или
document.getElementById(id).innerHTML
слишком долго, простейшем случае можно сделать объект-"обёртку" с именами методов покороче, например, как $
в этом коде:
<script> function truncate (src, maxlen) { return src.length < maxlen ? src : src.substring(0,maxlen)+'...'; } let $ = { get (id) { return document.getElementById(id) ? document.getElementById(id) : null; }, getVal (id) { return document.getElementById(id) ? document.getElementById(id).value : null; }, getHTML (id) { return document.getElementById(id) ? document.getElementById(id).innerHTML : null; }, setVal (id, val) { if (document.getElementById(id)) document.getElementById(id).value = val; }, setHTML (id, html) { if (document.getElementById(id)) document.getElementById(id).innerHTML = html; } }; </script> <textarea name="str" id="str"></textarea> <br><input type="text" name="maxlength" id="maxlength" value="10"> <br><textarea name="myResult" id="myResult" readonly></textarea> <br><input type="button" value="Выполнить" onclick="$.setVal('myResult',truncate($.getVal('str'),$.getVal('maxlength')));">
25. Как программно выделить нужную часть текста в текстовом поле ввода?
Можно, например, так (идентификатор элемента и номера позиций в тексте передаются аргументами функции).
<input type="text" id="txt"> <input type="button" value="Выделить" onclick="createSelection('txt', 1, 3);"> <script> function createSelection(id, start, end) { let field = document.getElementById (id); if (field.createTextRange) { let selRange = field.createTextRange(); selRange.collapse(true); selRange.moveStart('character', start); selRange.moveEnd('character', end); selRange.select(); field.focus(); } else if (field.setSelectionRange) { field.focus(); field.setSelectionRange(start, end); } else if (typeof field.selectionStart != 'undefined') { field.selectionStart = start; field.selectionEnd = end; field.focus(); } } </script>
26. Как реализовать операции над множествами?
В современных версиях Javascript есть отдельный объект Set.
<script> function isSuperset (set, subset) { for (let elem of subset) { if (!set.has(elem)) return false; } return true; } function union (setA, setB) { let _union = new Set(setA); for (let elem of setB) _union.add(elem); return _union; } function intersection (setA, setB) { let _intersection = new Set(); for (let elem of setB) { if (setA.has(elem)) _intersection.add(elem); } return _intersection; } function difference(setA, setB) { let _difference = new Set(setA); for (let elem of setB) _difference.delete(elem); return _difference; } let setA = new Set([1, 2, 3, 4]), setB = new Set([2, 3]), setC = new Set([3, 4, 5, 6]); console.log ( isSuperset(setA, setB) ); // => true console.log ( union(setA, setC) ); // => Set [1, 2, 3, 4, 5, 6] console.log ( intersection(setA, setC) ); // => Set [3, 4] console.log ( difference(setA, setC) ); // => Set [1, 2] </script>
27. Как выделить все вхождения регулярного выражения в строку?
В нашем случае выделение сводится к подчёркиванию найденных вхождений, но принцип обработки не изменится и для других подобных задач.
<p id="result"></p> <script> let str = 'Привет, я очередная строка текста "№;%::?6абв с цифрами 123 и буквами 456! Привет!!'; //строка откуда-то let reg = /[а-яё]+/gi; //регулярка, модификатор g - глобально, i - без регистра букв let res = selectByRegex (str,reg); //найти и выделить все вхождения reg в str document.getElementById('result').innerHTML = res ? res : 'не найдено'; function selectByRegex (str,reg) { //Аргументы - строка, регулярка. Вернёт строку, где всё найденное подчёркнуто (или null) let str2 = ''; let matches = str.match (reg); if (!matches) return null; //console.log(matches); for (let m in matches) { let before = str.indexOf(matches[m]); if (before > -1) { //часть до вхождения let bstr = str.substring(0,before); str2 += bstr; //добавить в целевую строку str = str.substring (bstr.length); //и убрать из исходной } str2 += '<u>' + matches[m] + '</u>'; //подчеркнуть вхождения str = str.substring (matches[m].length); //и убрать обработанное } str2 += str; //хвост строки, если есть return str2; } </script>
28. Почему я не могу ввести текст регулярного выражения в поле ввода или строку и потом использовать его в RegExp?
Потому что в поле формы (или в переменную) Вы вводите строку, а регулярное выражение - это объект. Помочь может показанный ниже код, который конструирует регулярку из поля ввода с id="regexp"
и применяет её к строке из поля ввода с id="source"
. Сама функция обработки findAllRegexFromInput
просто составляет массив из вхождений регулярного выражения в строку и возвращает строку со списком вхождений, разделённых переводами строк.
<p> Текст: <input type="text" size="80" id="source" value="Привет, я очередная строка текста "№;%::?6абв с цифрами 123 и буквами 456! Привет!!"> RegExp: / <input type="text" size="15" id="regexp" value="[а-яё]+"> / <input type="checkbox" id="gFlag" checked><label for="gFlag">G</label> <input type="checkbox" id="iFlag" checked><label for="iFlag">I</label> <input type="button" value="Выполнить" onclick=" let str = document.getElementById('source').value, regStr = document.getElementById('regexp').value; //В регулярке только основная часть, без обрамления / ... / let flags = ''; if (document.getElementById('gFlag').checked) flags += 'g'; if (document.getElementById('iFlag').checked) flags += 'i'; let reg = new RegExp(regStr, flags); //Флаги приходится обрабатывать отдельно let res = findAllRegexFromInput (str, reg); document.getElementById('result').innerHTML = res ? res : 'не найдено';" > </p> <p id="result"></p> <script> function findAllRegexFromInput (str, reg) { let arr = []; let matches = str.match (reg); if (!matches) return null; for (let m in matches) arr.push (matches[m]); return arr.join("<br>\n"); } </script>
29. Для внешнего файла .js вместо кириллицы в браузере показываются "кракозябры", хотя везде кодировка UTF-8. Как исправить?
Под "кракозябрами" имеется в виду, прежде всего, испорченный Юникод.
Если вдруг ваш сервер не отдаёт в заголовке HTTP-запроса кодировку для js-файлов, укажите дополнительный атрибут charset
в теге подключения скрипта, то есть, не
<script src="js/script.js"></script>
а
<script src="js/script.js" charset="utf-8"></script>
30. Как преобразовать строку в последовательность Юникод-символов и наоборот?
То есть, "foo АЯая № bar" становится "foo \u0410\u042f\u0430\u044f \u2116 bar", а потом всё обратно.
<div id="result"></div> <script> function chars2utf (s) { return s.replace (/[\u0080-\uFFFF]/g, function (s) { return "\\u" + ('000' + s.charCodeAt(0).toString(16)).substr(-4); } ); } function utf2chars (s) { let decoded = JSON.parse('{"data": "'+ s +'"}'); //Декодируем обратно //метод escape устарел! return decoded.data; } let s = chars2utf('foo АЯая № bar'); document.getElementById('result').innerHTML = s; // "foo \u0410\u042f\u0430\u044f \u2116 bar" s = utf2chars (s); alert (s); //foo АЯая № bar </script> <noscript>Включите Javascript в браузере!</noscript>
При декодировании в строке не должно быть двойных кавычек или они должны быть перед прямым преобразованием экранированы по принципу "
-> \\"
31. Как получить callback-функцию из строки с записью нужного оператора?
"Опасная" функция eval
не нужна. Просто укажите там, где нужна callback-функция, конструкцию вида
new Function(callback)()где
callback
- строка с оператором Javascript.
Пример (использует локальную копию мини-фреймворка Fader):
<script src="http://blog.kislenko.net/archives/13965.js" charset="utf-8"></script> <script> let buttonsSwitch3 = true; function fadeDemo3(elem,value,callback) { if (buttonsSwitch3){ Fader.fadeOutElement(elem, Math.abs(parseFloat(value)), new Function(callback)() ); } else { Fader.fadeInElement(elem, Math.abs(parseFloat(value)), new Function(callback)() ); } buttonsSwitch3 = !buttonsSwitch3; } </script> <p>Задержка анимации: <input type="number" id="fadeNumber3" min="0" max="1" value="0.1" step="0.1" size="3" maxlength="3"> <input type="button" value="Выполнить" id="fadeButton3" onclick="fadeDemo3(document.getElementById('fadeId3'),document.getElementById('fadeNumber3').value, document.getElementById('funcSelector').value);"> </p> <p>Выберите функцию для выполнения после эффекта: <select id="funcSelector"> <option value="" selected>Ничего не делать</option> <option value="alert('ok')">Вывести окно сообщения</option> <option value="location.assign('http://disney.ru')">Перейти на другой сайт</option> <option value="document.body.style.backgroundColor = 'yellow'">Изменить фон страницы</option> <option value="location.reload()">Перезагрузить страницу</option> </select> </p> <p id="fadeId3"><i>Элемент для проверки эффектов "fadeOutElement"/"fadeInElement"</i></p> <p>На самом деле, из-за асинхронного выполнения Javascript функция необязательно будет срабатывать после завершения эффекта.</p>
Файл с фреймворком Fader из примера (прямая ссылка на файл .js) (3 Кб)
32. Как динамически создать "стек" элементов с обработчиками событий?
См. также пример 23. На самом деле, в том и удобство, что нет никакой разницы между элементами, прописанными в разметке и созданными динамически.
Например, здесь мы создаём "стек" из элементов <textarea> и назначаем динамически создаваемым элементам обработчики событий (клика по <textarea>).
<input type="button" onclick="addItem();" value="Добавить"> <input type="button" onclick="deleteItem();" value="Удалить"> </p> <script> let i = 1; function addItem() { let elem = document.createElement('textarea'); if (!elem) { alert ('Adding error'); return; } elem.setAttribute ('id','area_' + i); elem.setAttribute ('onclick','clickItem("area_' + i + '");'); elem.value = i; document.body.appendChild (elem); i++; } function deleteItem() { let elem = document.getElementById('area_'+(i-1)); if (!elem) { alert ('Deleting error'); return; } document.body.removeChild (elem); if (i > 1) i--; } function clickItem (id) { let elem = document.getElementById(id); if (!elem) return; alert ('Ok, my id is '+id); } </script>
33. Как принудительно вывести вещественные числа с разделителем дробной части - запятой?
В примере пишем в элемент 10000 чисел, довольно быстро, так как split + join заведомо быстрее, чем RegExp.
<pre> <div id="resRandom"></div> </pre> <script> let n = 10000, s = ''; for (let i=0; i<n; i++) { s += Math.random().toString().split('.').join(',') + "\n"; } document.getElementById('resRandom').innerHTML = s; </script>
26.04.2020, 15:25; рейтинг: 652