Пример создания калькулятора на основе HTML-элемента input type=”range”. Это слайдер, у которого можно плавно изменять значения при помощи ползунка. Текущее значение хранится в атрибуте value данного элемента.
На этом принципе и основана работа калькулятора, который рассмотрим ниже.
Что будет считать калькулятор? В качестве примера - сумму чаевых в кафе. Есть основная сумма ($), задается процент (%) чаевых для основной суммы.
Нужно посчитать результирующую сумму ($).
HTML разметка
Разметка калькулятора основана на элементах form, input type=”text”, input type=”range”. Она простая и представлена ниже:
<divclass="wrapper"><h1class="wrapper__title">javascript slider calculator</h1><formclass="calculator"><divclass="calculator__row"><labelfor="bill">enter the bill amount for your meal: $</label><inputtype="text"id="bill"class="calculator__bill"value="5"required/></div><divclass="calculator__row"><labelfor="tip">tip amount: <spanclass="tip-amount"></span></label><inputtype="range"min="0"max="100"value="0"step="1"class="calculator__tip"id="tip"required/></div><divclass="calculator__row"><h2class="calculator__info">tip to leave: <spanclass="calculator__result"></span></h2></div></form></div>
CSS стили
Стилизация для калькулятора также не отличается объемом и сложностью. Что-либо отмечать отдельно нет необходимости:
Функция для вычисления результирующей суммы “повешена” на элемент input type=”range” и событие change.
Другими словами, при перемещении ползунка слайдера каждый раз будет вызываться функция и производится пересчет на основе изменившегося значения атрибута value.
Принцип работы функции следующий. “Забираем” значения из элементов input type=”text” и input type=”range”. Первое значение - эту основная сумма ($); второе значение - процент (%) от основной суммы ($).
Получаем результирующую сумму путем сложения - основной суммы ($) + процент (%) от основной суммы. Результирующий вывод округляем до двух значений после запятой при помощи метода toFixed().
Помимо этого, проверяем правильность и наличие ввода в поле основной суммы ($) input type=”text”. Условие будет верным, если поле ввода окажется не пустым и содержащим только цифры:
// RANGE FUNCTION// ----------------------------------------------------------calculatorTip.on('change',function(){if(calculatorBill.val()===''||isNaN(calculatorBill.val())){alert('Enter bill amount, please!')}else{amount=calculatorBill.val()*1;}tipAmount.text(calculatorTip.val()+'%');percent=calculatorTip.val()*1;result=amount+amount*(percent/100);calculatorResult.text(result.toFixed(2)+'$');});
Для “украшательства” можно создать еще одну функцию, которая будет запускаться при загрузке страницы и инициализировать значения суммы ($), процентов (%) от суммы и результирующей суммы ($):
Обзор посвящен созданию JavaScript-калькулятора. Домашнее задание для каждого начинающего JavaScript-ниндзя! ) В коде используется не чистый JavaScript, а JavaScript + jQuery.
Пример и материал не является оригинальным, основан на зарубежном источнике. Указывать источник не буду, потому что это не имеет смысла - таких кратких видеоуроков просто огромное количество - выбирай любой, какой понравится. )
HTML разметка
HTML-разметка для будущего калькулятора основана на HTML-элементах form, input, button. Ничего сверхестественного в ней нет.
Единственный момент - вопрос компоновки кнопок, куда правильно “засунуть” кнопки с арифметическими операциями:
Переходим к самому интересному - созданию JavaScript-кода для калькулятора. В своем примере я использовал JavaScript + jQuery.
Последний применил только из-за удобства манипуляции с DOM. Недавно узнал о существовании библиотеки Underscore.js как альтернативы jQuery, но меньшего размера. Надо опробовать Underscore.js обязательно! )
Первым делом инициализируем кнопки калькулятора. Для этого забираем значения из атрибута value кнопок button и динамически вставляем в HTML-разметку:
Исходный вид калькулятора подготовили - он теперь выглядит как настоящий калькулятор! Если не принимать во внимание кошмарных цветов и их сочетания ) Ну мы не дизайнеры, нам простительно )
Теперь стоит задача - при нажатии на кнопку калькулятора чтобы ее значение появлялось в окошке последнего. Тоже ничего сложного, если подумать.
Просто нужно забрать у активной кнопки значение ее атрибута value и передать как значение элемента input.
Небольшая тонкость здесь - нужно конкатенировать текущее значение элемента button с текущим значением элемента input; иначе будет происходить простое замещение предыдущего значения элемента input текущим значением элемента button:
// ADD NUMBERS TO INPUTcalcButton.on('click',function(){calcDisplay.val(calcDisplay.val()+$(this).attr('value'));});
Полная очистка экрана калькулятора элементарно проста - достаточно при нажатии на соответствующую кнопку передать в элемент input пустое значение:
Дальше уже немного интереснее - будем оживлять кнопку =. То есть - ввели в окошко калькулятора, к примеру, 2 + 3. По нажатии на кнопку = в окошке должен появиться результат этой арифметической операции.
На помощь приходит функция JavaScript под названием eval(). На javascript.ru эта функция подробно расписана.
В результате код для “оживления” кнопки = будет выглядеть “скромно”:
// SHOW RESULTcalcEqual.on('click',function(){calcDisplay.val(eval(calcDisplay.val()));});
Наш калькулятор почти готов. Осталось добавить жизни к двум последним кнопкам - возведения в степень и посимвольной очистки экрана калькулятора.
Для возведения в степень воспользуемся стандартной JavaScript-библиотекой Math и ее методом pow().
Заберем у элемента input его текущее значение и передадим в качестве одного из аргументов в метод pow(). Второй аргумент в нашем случае - это константа 3:
// POWER BUTTONcalcPower.on('click',function(){calcDisplay.val(Math.pow(calcDisplay.val(),3));});
Последний шаг к успеху создания калькулятора - это “оживление” кнопки посимвольной очистки экрана калькулятора.
В этом случае воспользуемся стандартным методом JavaScript - substring(). Это метод JavaScript(), который извлекает из строки подстроку и возвращает ее в виде новой строки - почитать с примерами.
В качестве аргументов принимает два параметра - начальную и конечную позицию, которые выступают как начальный и конечный индекс массива. Массивом в данном случае является строка.
Функция (на кнопке посимвольной очистки) в нашем случае будет работать так - забираем у элемента input его текущее значение. Значение возвращается в виде строки, конечно.
Поэтому находим ее длину (length) и укорачиваем на один (последний) символ - length - 1. Таким образом мы динамически укорачиваем текущее значение в окне калькулятора на один символ.
Затем нам нужно заменить текущее значение окна калькулятора укороченным на один символ значением. Для этого берем метод substring() и с помощью него “обрезаем” текущую строку; этот метод возвращает “обрезанный” вариант. Нам осталось только вставить его в окно калькулятора.
Вот наш калькулятор и готов - ниже полный JavaScript-код:
$(document).ready(function(){// VARIABLESvarcalc=$('.calculator');varcalcDisplay=calc.find('.calculator__display');varcalcKeys=calc.find('.calculator__key');varcalcButton=calc.find('.calculator__button');varcalcClear=calc.find('.calculator__clear');varcalcEqual=calc.find('.calculator__key--equal');varcalcPower=calc.find('.calculator__power');varcalcSpace=calc.find('.calculator__backspace');// INIT CALC KEYScalcKeys.each(function(){varcurrent=$(this).attr('value');$(this).text(current);});// ADD NUMBERS TO INPUTcalcButton.on('click',function(){calcDisplay.val(calcDisplay.val()+$(this).attr('value'));});// CLEAR INPUTcalcClear.on('click',function(){calcDisplay.val('');});// SHOW RESULTcalcEqual.on('click',function(){calcDisplay.val(eval(calcDisplay.val()));});// POWER BUTTONcalcPower.on('click',function(){calcDisplay.val(Math.pow(calcDisplay.val(),3));});// BACKSPACE BUTTONcalcSpace.on('click',function(){// http://www.w3schools.com/jsref/jsref_substring.aspcalcDisplay.val(calcDisplay.val().substring(0,calcDisplay.val().length-1));});});
Конечно, примеры кода из этой статьи хоть и не являются укороченными, но не дают полного представления о разрабатываемом нами калькуляторе.
Поэтому привожу ссылку на готовый вариант калькулятора, который создавался в этой статье. На CodePen можно его посмотреть и разобрать детально (при желании).
Как вариант для сравнения, можно взглянуть на более сложный пример создания калькулятора, на чистом JavaScript. Пример был найден мною на просторах CodePen.
Заключение
Рассмотренный в статье пример лично для меня оказался на удивление прост - я ожидал большей (и более запутанной) кучи кода.
На этом все. В дальнейшем буду продолжать флудить на тему JavaScript, ибо для себя с удивлением обнаружил, что мне в последнее вермя доставляет удовольствие разбирать и рассматривать готовые примеры на JavaScript.
Единственное, что меня огорчает - тот факт, что они чужие )
Имеется такая задача - на странице расположен блок. Страница скроллится, то есть наличествует событие scroll.
Нужно сделать так, чтобы при возникновении события scroll и выполнении определенного условия срабатывала некая функция. Но при этом срабатывала только один раз!
Вариантов решения этой задачи может быть несколько. В этой статье будут показаны два из них. Все они будут выполнены на JavaScript + jQuery.
Вариант первый - метод off()
Этот способ основан на методе jQuery - .off(). Как говорится в описании, метод .off() удаляет событие, вызванное с помощью метода .on(). То есть, выполняет обратную операцию.
Что мы имеем в этом коде? Видим, что на окно window повешен обработчик ( метод .on()) события scroll.
При возникновении этого события выполняется проверка условия. Если условие true, то для каждого из элементов коллекции spins выполнить функцию.
Как только функция закончит свою работу, выполнение кода перемещается на строку $(window).off(‘scroll’). Эта строка “говорит” - на объекте window остановить событие scroll.
Мы получили нужный результат - при событии scroll и выполнении условия функция выполнится только один раз.
Один важный момент - после выполнения строки $(window).off(‘scroll’) событие scroll будет “прибито” и дальнейшие попытки повесить handler на него не увенчаются успехом.
Другими словами, если дальше на странице есть еще элементы, на которых нужно обработать событие scroll, то ничего не получится.
Вариант второй - маркер
Второй способ не использует метод .off(), но применяет специальный маркер. Код простой, но эффективный. И в этом случае событие scroll не “убивается”, а функция исполняется один раз:
varmarker=true;functioncount(){// function code here ...marker=false;}$(window).on('scroll',function(){if($(window).scrollTop()>overview.offset().top-$(window).height()*0.5){if(marker){count();}}});
Что есть в этом коде? Есть глобальная переменная marker, у которой изначально значение true.
При выполнении условия функция count() запускается и по ходу дела меняет значение marker на противоположный. Таким образом функция count() сработает только один раз.
Но событие scroll останется “невредимым”.
Заключение
За бортом остался еще один jQuery-метод - .one(). Его задача - также запустить на исполнение функцию только один раз.
Например, в коде ниже клик мыши на каждом из элементов коллекции likeLinks сработает только один раз:
varlikeLinks=$('.overlay__link-heart');likeLinks.one('click',function(){// увеличить значение счетчика на единицу при клике// -----------------------------------------------------------varcurrentCount=$(this).find('.overlay__link-count');currentCount.html(currentCount.html()*1+1);
Однако, применить метод .one() для обработки события scroll и вызова на исполнение функции только один раз у меня не получилось. Событие scroll вообще не срабатывало.
На этом все. Похоже на то, что все верно написал и описал. Но если будут здравые комментарии и замечания, то буду только рад )
P.S. Сразу на ум пришло одно у самого себя - заменить $( window ) на переменную. Но уже лень менять. )
Создание игры Dice Game (игра в кости) на JavaScript. Вот нашлось время и силы познакомиться с игрой такого типа. Сразу оговорюсь, что материал и пример не мой, а взят из зарубежного ресурса для изучения.
В примере рассмотрен основной принцип создания игры Dice. Можно сказать - чисто схематично. Однако этого достаточно, чтобы остальное дополнить по необходимости.
Код оказался на удивление прост. Я не сомневаюсь, что в Интернете есть примеры более сложного и совершенного JavaScript-кода для игр подобного типа. Но цель статьи - познакомиться с основным принципом создания игры, не более.
HTML разметка и стили
Разметка очень простая и состоит из четырех элементов:
Сгенерируем два случайных числа из диапазона от 1 до 6. Игральная кость имеет шесть сторон - поэтому такой диапазон. Эти числа будут иммитацией одной из шести сторон каждой игральной кости.
Другими словами. На всех сторонах игрального кубика “выбито” точками число - от 1 до 6. Поэтому можно сказать иначе - диапазон от 1 до 6 - это диапазон возможных значений, которые выпадают на каждой из игральных костей:
Переменная diceTotal служит для информативных целей - будем показывать сообщение о том, сколько в сумме выпало очков на игральных костях.
Осталось поместить случайно сгенерированную пару чисел в HTML-код. Помимо этого вывести информационное сообщение, сколько очков в сумме выпало. И предупредить, если на обеих костях выпавшее число одинаковое - тогда предоставить игроку еще один ход:
window.addEventListener('DOMContentLoaded',function(){functionrollDice(){vardiceSide1=document.getElementById('dice-side-1');vardiceSide2=document.getElementById('dice-side-2');varstatus=document.getElementById('status');varside1=Math.floor(Math.random()*6)+1;varside2=Math.floor(Math.random()*6)+1;vardiceTotal=side1+side2;diceSide1.innerHTML=side1;diceSide2.innerHTML=side2;status.innerHTML='You rolled '+diceTotal+'.';if(side1===side2){status.innerHTML+=' Doubles! You get a free turn!';}}},false);
Наш JavaScript-код готов и выглядит таким несложным способом:
window.addEventListener('DOMContentLoaded',function(){functionrollDice(){vardiceSide1=document.getElementById('dice-side-1');vardiceSide2=document.getElementById('dice-side-2');varstatus=document.getElementById('status');varside1=Math.floor(Math.random()*6)+1;varside2=Math.floor(Math.random()*6)+1;vardiceTotal=side1+side2;diceSide1.innerHTML=side1;diceSide2.innerHTML=side2;status.innerHTML='You rolled '+diceTotal+'.';if(side1===side2){status.innerHTML+=' Doubles! You get a free turn!';}}varbuttonRollDice=document.querySelector('.dice-roll');buttonRollDice.addEventListener('click',rollDice,false);},false);
В заключение, как мне кажется, стоит сказать пару слов по поводу рассмотренного примера. Он является достаточно схематичным. Однако никто не мешает дополнить код возможностью смены изображений, иммитирующих грани костей.
Плюс - добавить анимацию. И получится весьма неплохой результат, как мне представляется.
Знакомство с техникой Drag-and-Drop и механизмом ее реализации с помощью JavaScript. Данный обзор не претендует на полноту покрытия материала. Задача статьи - познакомиться с созданием Drag-and-Drop на JavaScript. Понять сам принцип механизма и научиться применять основные инструменты для его реализации.
Определение Drag-and-Drop
Сам механизм Drag-and-Drop интуитивно понятен - “схватил-перетащил-бросил”. Преимущество внедрения Drag-and-Drop в интерфейсы заключается в упрощении реализации задач; в уменьшении количества пунктов меню типа “Copy-Paste”.
События Drag-and-Drop
Механизм Drag-and-Drop имеет в своем составе целую группу событий, с помощью которых можно контролировать процесс перетаскивания:
dragstart - пользователь начинает перетаскивание элемента
dragenter - перетаскиваемый элемент входит в область целевого объекта
dragover - перетаскиваемый элемент перемещается в области целевого объекта
dragleave - перетаскиваемый элемент покидает область целевого объекта
drag - момент начала процесса перетаскивания объекта
drop - момент, когда отпускается зажатая клавиша мыши (перетаскиваемый объект “роняется”)
dragend - момент завершения процесса перетаскивания объекта
Объект dataTransfer
Механизм Drag-and-Drop также имеет в своем составе объект dataTransfer, который служит для вспомогательных целей. В этом объекте хранится необходимая информация о событии перетаскивания. Помимо этого, в объект dataTransfer можно добавлять данные; а также считывать из него данные.
Свойства (наиболее важные) объекта dataTransfer:
dataTransfer.effectAllowed - задаем тип перетаскивания, которое пользователь может выполнять с элементом
dataTransfer.dropEffect - задаем внешний вид курсора мыши в соответствии с заданным типом перетаскивания
Методы (наиболее важные) объекта dataTransfer:
setData() - добавляет данные в нужном формате
clearData() - удаляет данные
setDragImage() - устанавливает изображение для перетаскивания с координатами курсора (0, 0 — левый верхний угол)
getData() - возвращает данные
Ниже будет рассматриваться практический пример реализации Drag-and-Drop на JavaScript.
Заголовок id=”dropStatus” будет отображать текущее состояние процесса Drag-and-Drop. В него мы будет отправлять информацию о текущем состоянии Drag-and-Drop при помощи событий, о который говорилось выше.
Заголовок id=”dropTitle” служит просто для декоративных целей.
Блок id=”dropZone” является целевой областью - в нее мы будет перетаскивать объекты.
Объекты id=”object1”, id=”object2”, id=”object3” - это перетаскиваемые объекты; их мы будем перемещать в область блока id=”dropZone”.
Кнопка id=”readDropZone” будет выводить информацию об перемещенных объектах.
Прежде чем детально рассматривать работу каждой из будущих функций по обработке событий, мне кажется, будет лучше просто понять, какие события и куда мы будем “вешать”.
Итак, начнем с перетаскиваемых элементов id=”object1”, id=”object2”, id=”object3”. На каждый из них мы повесим два события:
dragstart - событие начала процесса перетаскивания элемента
dragend - событие окончания процесса перетаскивания элемента
Для каждого из элементов, при возникновении на нем события, мы будем запускать соответствующую функцию dragStart или dragEnd:
Обратим внимание на строку el.setAttribute(‘draggable’, ‘true’); - здесь мы динамически добавляем для всех элементов с классом .objects атрибут draggable=”true”, тем самым делая (благодаря HTML5) эти элементы доступными для перетаскивания.
На элемент id=”dropZone” мы “повесим” гораздо больше событий:
dragenter - перетаскиваемый объект (например, id=”object1”) входит в область целевого объекта (id=”dropZone”)
dragleave - перетаскиваемый объект (например, id=”object1”) выходит из области целевого объекта (id=”dropZone”)
dragover - перетаскиваемый объект (например, id=”object1”) перемещается внутри области целевого объекта (id=”dropZone”)
drop - перетаскиваемый объект (например, id=”object1”) помещается внутри целевого объекта (id=”dropZone”)
И конечно же, для каждого события будет своя функция. JavaScript-код в итоге будет выглядеть таким образом:
Далее будет детально останавливаться на каждой из функций - что она делает и для чего.
Функция dragStart (event)
Начнем с начала и запустим функцию для обработки старта события перетаскивания - события dragstart. Хочу сразу оговориться, что в процессе написания кода для обработки события перетаскивания важно четко представлять себе, какое событие и на каком элементе происходит.
В данном случае мы будем обрабатывать событие dragstart, которое возникает на перетаскиваемом элементе (id=”object1”, id=”object2” или id=”object3” - не важно).
Событие dragstart в момент своего возникновения автоматически генерирует объект dataTransfer, который (как мне кажется) можно в общих чертах сравнить с событийным объектом Event; последний также хранит в себе множество данных о произошедшем событии. Некоторыми методами и свойствами объекта Event мы воспользуемся в нашем примере:
vardropStatus=document.querySelector('#dropStatus');...functiondragStart(event){dropStatus.innerHTML='Dragging the '+event.target.getAttribute('id');event.dataTransfer.dropEffect='move';event.dataTransfer.setData('text',event.target.getAttribute('id'));}
Функция dragStart при возникновении события “берет” элемент dropStatus и методом innerHTML “пихает” внутрь него строку, часть которой представляет из себя значение атрибута id элемента, на котором произошло событие (event.target).
Для объекта dataTransfer задается значение его свойства dropEffect - move.
В третьей строке для объекта dataTransfer с помощью метода setData() задается имя переменной text и значение для этой переменной - ID текущего элемента.
Функции dragEnter(), dragLeave(), dragOver()
Три функции, каждая из которых отслеживает событие, возникающее на элементе dropZone:
functiondragEnter(event){dropStatus.innerHTML='You are dragging over '+event.target.getAttribute('id');this.classList.add('over');}functiondragLeave(event){dropStatus.innerHTML='You left the '+event.target.getAttribute('id');this.classList.remove('over');this.removeAttribute('class');}functiondragOver(event){event.preventDefault();}
Первые две функции - dragEnter (event) и dragLeave (event) очень похожи между собой. Каждая из них манипулирует содержимым заголовка dropStatus, сигнализируя о происходящем событии.
Третья функция dragOver (event) может показаться странной. Все ее назначение - это отмена действия по-умолчанию. Что это за действие по-умолчанию? Дело в том, что у браузеров имеется свой собственный (помимо HTML5) механизм реализации события перетаскивания Drag-and-Drop. И если его не отключить, то он не даст срабатывать нашему механизму.
Функция dragDrop (event)
Самая большая и самая важная функция в нашем коде. Она также срабатывает на событие, возникающее на элементе dropZone:
vardroppedIN=false;...functiondragDrop(event){event.preventDefault();varelementID=event.dataTransfer.getData('text');varelement=document.getElementById(elementID);event.target.appendChild(element);element.removeAttribute('draggable');element.classList.add('dragged');element.style.cursor='default';droppedIN=true;dropStatus.innerHTML='Element '+elementID+' dropped into the '+event.target.getAttribute('id');}
В строке event.preventDefault(); мы снова отменяем действие по-умолчанию. На этот раз это касается самого перетаскиваемого элемента - ведь он может быть ссылкой и браузер выполнит переход по ней (действие по-умолчанию), что нам совсем не нужно.
В строке:
varelementID=event.dataTransfer.getData('text');
… мы из объекта dataTransfer получаем ID перетаскиваемого элемента. Вы же помните, что в функции dragStart (event) с помощью строки:
И помещаем его внутрь текущего активного элемента:
event.target.appendChild(element);
Далее убираем у перетаскиваемого элемента атрибут draggable - он больше не перетаскиваемый. Визуально сигнализируем об этом, изменив вид курсора мыши:
element.style.cursor='default';
И сообщаем об изменившемся статусе в заголовке:
dropStatus.innerHTML='Element '+elementID+' dropped into the '+event.target.getAttribute('id');
Отдельного упоминания стоит строка droppedIN = true;. Это флаг, с помощью которого мы определяем, произошло ли событие drop или нет.
Может случиться так, что объект мы перетащили в область элемента dropZone, но передумали его помещать туда. И “отпустили” перетаскиваемый элемент за областью элемента dropZone. В результате событие dragend произошло, но событие drop не выполнилось.
Такую ситуацию обрабатывает функция dragEnd():
functiondragEnd(){if(droppedIN===false){dropStatus.innerHTML='You let the '+event.target.getAttribute('id')+' to go!';}droppedIN=false;}
Функция readZone ()
Последняя функция из нашего примера - это функция-счетчик. Ее задача - просто посчитать, сколько элементов на данный момент мы “бросили” в область dropZone:
functionreadZone(){vardropZoneChild=dropZone.children;for(vari=0;i<dropZoneChild.length;i++){alert('Object '+dropZoneChild[i].getAttribute('id')+' is in '+dropZone.getAttribute('id'));}}
Нажимаем кнопку dropButton и alert’ом последовательно выводим все элементы, помещенные внутрь объекта dropZone.
Вот, в принципе, и все, что можно вкратце сказать. Осталось только взглянуть на готовый пример работы кода - JavaScript - Drag’n’Drop - Part 2.
На этом все. Здоровая критика и полезные замечания только приветствуются.
Этот скромный обзор не смог бы появиться, если бы не было двух полезных для меня ресурсов: