БлогNot. Полезные мини-скрипты на JavaScript

Полезные мини-скрипты на JavaScript

сейчас в списке: 15 мини-скриптов Этот список будет включать в себя небольшие задачи на 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">&nbsp;</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 getDaysInMonth (month, year) { return new Date(year, month, 0).getDate(); } //arg. Month is 1..12
  let s = '<table class="mtab">'+"\n", d = new Date(y,m,1), w = d.getDay(), maxd = getDaysInMonth(m+1,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>

теги: javascript список учебное алгоритм

26.04.2020, 15:25; рейтинг: 157