Статьи

Создание невероятного калькулятора jQuery

Конечно, приятно иметь открыватель писем рядом с вашей почтовой корзиной, рожок для обуви рядом с лоферами и фонарик у тумбочки. Точно так же хорошо иметь калькулятор под рукой, когда вам нужно выполнить некоторую математику. Из этого туториала и загрузки вы узнаете, как правильно его разместить на любом сайте.



Некоторые кнопки с номерами от 1 до 9, пара функций и большая кнопка «равно». Это все калькулятор, верно? Должен быть кусок пирога. Любой язык программирования может легко справиться с этим. Конечно, но даже в таком простом, как калькулятор, есть несколько вещей, которые нужно учитывать при разработке того , как именно он работает.

Скринкаст , сопровождающий эту статью, будет сосредоточен в основном на этих вещах, а не на простом кодировании. Пока эта письменная часть будет ориентирована на код. Тем не менее, вот краткий обзор некоторых мелких деталей пользовательского интерфейса:

  • Когда калькулятор загружается, на дисплее отображается 0 (ноль). Нажатие на номер 2 не делает номер 02, это просто 2.
  • Когда вы нажимаете функциональную клавишу, число, отображаемое в данный момент на дисплее, «блокируется» как первое число в расчете, но оно просто остается там, где оно есть. При нажатии другого номера номер заменяется.
  • Если нажата функциональная клавиша, а затем нажата другая функциональная клавиша, самая последняя нажатая клавиша — это функция, которая будет использоваться.
  • После выполнения расчета возможны два сценария. А) Нажимается новый номер. Это полностью сбросит калькулятор и начнет заново с этого номера. B) нажата функциональная клавиша, которая фиксирует сумму как «первое» число, позволяя выполнить второе вычисление для суммы
  • Кнопка очистки должна вести себя так, как рекламируется, и полностью сбрасывать калькулятор
  • При необходимости необходимо использовать визуальную обратную связь, но, что более важно, функциональность должна соответствовать стандарту, установленному миллионами калькуляторов для настольных компьютеров по всему миру /

Список можно продолжить, но вы видите, что даже самые простые интерфейсы требуют большого внимания.


Ничего особенного здесь. Нам нужен контейнер для калькулятора, нам нужен дисплей, и нам нужно несколько кнопок. <div>, <input> и <a> будут хороши. JavaScript выполняет всю работу здесь, не происходит «изящной деградации». Если JavaScript отключен, этот калькулятор не будет работать, поэтому мы просто полностью его скрываем. Итак, мы не собираемся превращать это в настоящую <форму>, так почему же <input>? Входы позволяют вводить текст вручную, что мы допустим. Они позволяют легко выбирать и имеют атрибут «значение», который удобен для получения и настройки.

Вот весь комплект и kaboodle:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<div id=»calculator»>
  
    <input type=»text» id=»display» />
          
    <a class=»num-button seven» href=»#»>7</a>
    <a class=»num-button eight» href=»#»>8</a>
    <a class=»num-button nine» href=»#»>9</a>
      
    <a class=»num-button four» href=»#»>4</a>
    <a class=»num-button five» href=»#»>5</a>
    <a class=»num-button six» href=»#»>6</a>
      
    <a class=»num-button one» href=»#»>1</a>
    <a class=»num-button two» href=»#»>2</a>
    <a class=»num-button three» href=»#»>3</a>
      
    <a class=»num-button zero» href=»#»>0</a>
    <a class=»num-button dot» href=»#»>.</a>
    <a class=»clear-button clear» href=»#»>C</a>
      
    <a class=»function-button add» href=»#»> </a>
    <a class=»function-button subtract» href=»#»>&ndash;</a>
    <a class=»function-button multiply» href=»#»>x</a>
    <a class=»function-button divide» href=»#»>/</a>
      
    <a class=»equals-button» href=»#»>=</a>
          
</div>



Нам нужно всего несколько. Фон всего калькулятора, кнопка стиля «число», кнопка стиля «функция» и кнопка «равно». Каждому числу и функции не нужно свое собственное изображение, мы просто наложим текст прямо поверх. Я думаю, что «Arial Black» делает хороший жирный и похожий на калькулятор шрифт.

Позже, когда мы сделаем калькулятор открытым и закрытым, мы будем использовать графику «мини» калькулятора и кнопку «закрыть».


Опять ничего особенного Абсолютное позиционирование делает большую часть тяжелой работы, заставляя вещи идти туда, куда они должны идти. Мы устанавливаем позицию: относительную на самом калькуляторе, и тогда мы можем абсолютно свободно позиционироваться внутри него.

Вот много из этого:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
* { margin: 0;
body { font: 25px «Arial Black», Arial, Sans-Serif;
  
#page-wrap { width: 500px;
  
h1 { font-size: 22px;
p { font: 14px Arial, Sans-Serif;
a { color: black;
  
#calculator { width: 266px;
                  position: relative;
  
#display { background: none;
                  top: 15px;
                  font: 35px «Arial Black», Arial, Sans-Serif;
                      
.num-button { width: 44px;
                      background: url(../images/button-bg.png) no-repeat;
                  position: absolute;
.clear-button { width: 44px;
                      background: url(../images/button-bg.png) no-repeat;
                  position: absolute;
.function-button { width: 44px;
                      background: url(../images/function-button-bg.png) no-repeat;
                  position: absolute;
.function-button:active,
.pendingFunction { background-position: bottom left;
                      
.seven { top: 86px;
.eight { top: 86px;
.nine { top: 86px;
  
/* … the rest of the buttons … */
  
.multiply { top: 188px;
.divide { top: 237px;
  
.equals-button { width: 206px;
                  background: url(../images/equals-bg.png) no-repeat;
                  display: block;

В самом HTML у нас есть несколько вызовов, чтобы подготовиться к написанию собственного jQuery JavaScript. А именно, загружая библиотеки jQuery и jQuery UI и вызывая наш скоро существующий файл JavaScript.

1
2
3
4
5
6
<script src=»http://www.google.com/jsapi» type=»text/javascript»></script>
<script type=»text/javascript»>
    google.load(«jquery», «1.3.1»);
</script>
<script type=»text/javascript» src=»js/jquery-ui-personalized-1.6rc6.min.js»></script>
<script type=»text/javascript» src=»js/example.js»></script>

Давайте введем самые основы. Нам понадобится классическое утверждение «Когда DOM будет готов», чтобы начать работу. Это является общим для всего JavaScript, так как мы не хотим ничего делать с элементами до того, как они все загрузятся. Затем мы устанавливаем некоторые основные события, которые, как мы знаем, произойдут. У нас будет событие нажатия и функция для каждого типа кнопки. Мы также вызовем функцию пользовательского интерфейса jQuery, чтобы сделать наш калькулятор перетаскиваемым, а также крошечную функцию, позволяющую переключать его видимость.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$(function(){
          
    $(«.num-button»).click(function(){
        // do stuff
    });
      
    $(«.clear-button»).click(function(){
        // do stuff
    });
      
    $(«.function-button»).click(function(){
        // do stuff
    });
      
    $(«.equals-button»).click(function(){
         // do stuff
    });
      
    $(«#calculator»).draggable();
      
    $(«#opener, #closer»).click(function(){
        $(«#opener»).toggle();
        $(«#calculator»).toggle();
    });
      
});

Переменные в JavaScript являются локальными по отношению к функции, в которой они созданы. Когда вам нужно передать одну в другую, вы делаете это, передавая ее в качестве параметра при вызове новой функции. Это все хорошо, но у нас их семь, и большинству наших функций так или иначе понадобятся все из них. Это могло бы стать немного волосатым, если бы они проходили все время. Что нам действительно нужно, так это глобальные переменные, но, насколько я понимаю, это вроде нет-нет (что-то с нарушением пространства имен).

В любом случае, у jQuery есть лучший способ справиться с этим — функция data () . Мы можем прикрепить «данные» к любому объекту jQuery, и эти данные перемещаются вместе с этим объектом, куда бы они ни направлялись. По сути, как атрибут, только вы не можете увидеть его в DOM. Это в основном делает то, что глобальные переменные сделали бы для нас, и это так же просто в использовании. Вот биты данных, которые мы будем использовать:

  • ValueOne — первое число в уравнении
  • ValueOneLocked — это первый номер готов к работе?
  • ValueTwo — второе число в уравнении
  • ValueTwoLocked — готов ли второй номер?
  • isPendingFunction — выбрана ли функция?
  • thePendingFunction — какая из них?
  • fromPrevious — был ли произведен расчет ПРОСТО?

Мы собираемся добавить эти биты данных к входу #display, который будет своего рода мозгом нашего калькулятора. В некотором смысле имеет смысл. Нам нужно установить значения по умолчанию для всех этих битов данных, но давайте подумаем. Мы могли бы сделать это правильно в основной функции, но давайте будем умными и абстрагируем это от функции. Будет несколько сценариев, которые нам понадобятся для сброса этих значений, поэтому давайте создадим функцию с именем resetCalculator для выполнения этой работы. Затем мы можем вызывать эту функцию всякий раз, когда нам это нужно. Давайте также примем параметр числа и сбросим калькулятор на это значение. Когда калькулятор загрузится, это будет ноль, но после функции мы сбросим снова только сброс к окончательному значению вычисления.

01
02
03
04
05
06
07
08
09
10
11
function resetCalculator(curValue) {
    $(«#display»).val(curValue);
    $(«.function-button»).removeClass(«pendingFunction»);
    $(«#display»).data(«isPendingFunction», false);
    $(«#display»).data(«thePendingFunction», «»);
    $(«#display»).data(«valueOneLocked», false);
    $(«#display»).data(«valueTwoLocked», false);
    $(«#display»).data(«valueOne», curValue);
    $(«#display»).data(«valueTwo», 0);
    $(«#display»).data(«fromPrevious», false);
}

Оказывается, что калькулятор, когда вы щелкаете по числу, является самым сложным фрагментом кода во всем этом. Калькулятор может находиться в четырех «состояниях», и он будет вести себя по-разному, когда вы нажимаете на число в зависимости от этого состояния. Они есть:

  • A) Нажатие на номер в совершенно новом состоянии (на дисплее отображается ноль), или когда ни один номер еще не заблокирован.
  • B) Нажатие на номер после выбора функциональной кнопки.
  • C) Нажатие на номер после выбора функциональной кнопки и ввода дополнительных номеров.
  • D) Нажатие на номер после только что выполненного расчета.

Наше поведение должно быть следующим:

  • А) Добавьте новый номер к тому, что уже есть. Если это ноль, замените это.
  • Б) Заблокируйте первый номер, замените дисплей новым номером.
  • В) Добавить новый номер к тому, что уже есть.
  • D) Сброс калькулятора на этот номер.

И вот все это в коде:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
$(«.num-button»).click(function(){
  
    if ($(«#display»).data(«fromPrevious») == true) {
  
        resetCalculator($(this).text());
      
    } else if (($(«#display»).data(«isPendingFunction») == true) && ($(«#display»).data(«valueOneLocked») == false)) {
      
        $(«#display»).data(«valueOne», $(«#display»).val());
        $(«#display»).data(«valueOneLocked», true);
      
        $(«#display»).val($(this).text());
        $(«#display»).data(«valueTwo», $(«#display»).val());
        $(«#display»).data(«valueTwoLocked», true);
  
    // Clicking a number AGAIN, after first number locked and already value for second number
    } else if (($(«#display»).data(«isPendingFunction») == true) && ($(«#display»).data(«valueOneLocked») == true)) {
  
        var curValue = $(«#display»).val();
        var toAdd = $(this).text();
  
        var newValue = curValue toAdd;
  
        $(«#display»).val(newValue);
      
        $(«#display»).data(«valueTwo», $(«#display»).val());
        $(«#display»).data(«valueTwoLocked», true);
  
    // Clicking on a number fresh
    } else {
  
        var curValue = $(«#display»).val();
        if (curValue == «0») {
            curValue = «»;
        }
  
        var toAdd = $(this).text();
  
        var newValue = curValue toAdd;
  
        $(«#display»).val(newValue);
  
    }
      
});

С функциональной кнопкой легче иметь дело. В основном, когда вы нажимаете на нее, она блокирует первый номер, чтобы цифровые кнопки знали, что пора начинать второй номер. Однако есть одно особое соображение, и это то, что нужно сделать, если функциональная кнопка нажата сразу после выполнения расчета. В этом случае первое число должно быть зафиксировано как окончательное значение и уже готово принять это второе число. Это позволяет объединять расчеты, что весьма полезно.

При нажатии все функциональные кнопки очищаются от специального класса «pendingFunction», а затем этот класс применяется к конкретному нажатому. Это дает нам элемент управления CSS, чтобы переместить фоновую позицию и дать некоторую визуальную обратную связь, которая является активной в настоящее время функцией.


01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
$(«.function-button»).click(function(){
  
    if ($(«#display»).data(«fromPrevious») == true) {
        resetCalculator($(«#display»).val());
        $(«#display»).data(«valueOneLocked», false);
        $(«#display»).data(«fromPrevious», false)
    }
      
    // Let it be known that a function has been selected
    var pendingFunction = $(this).text();
    $(«#display»).data(«isPendingFunction», true);
    $(«#display»).data(«thePendingFunction», pendingFunction);
      
    // Visually represent the current function
    $(«.function-button»).removeClass(«pendingFunction»);
    $(this).addClass(«pendingFunction»);
});

Функция равенства также довольно проста. Первое, что мы делаем, это проверяем, готовы ли мы на самом деле делать какие-либо вычисления. Мы знаем это, если ОБА номера заблокированы. Если это так, сделайте небольшую математическую операцию, чтобы получить окончательное число, а затем «сбросьте» калькулятор на это окончательное значение (и установите для «fromPrevious» значение true, чтобы мы знали деликатное состояние, в котором мы находимся).

Если номера не заблокированы …. ничего не делать.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$(«.equals-button»).click(function(){
  
    if (($(«#display»).data(«valueOneLocked») == true) && ($(«#display»).data(«valueTwoLocked») == true)) {
          
        if ($(«#display»).data(«thePendingFunction») == » «) {
            var finalValue = parseFloat($(«#display»).data(«valueOne»)) parseFloat($(«#display»).data(«valueTwo»));
        } else if ($(«#display»).data(«thePendingFunction») == «%u2013») {
            var finalValue = parseFloat($(«#display»).data(«valueOne»)) — parseFloat($(«#display»).data(«valueTwo»));
        } else if ($(«#display»).data(«thePendingFunction») == «x») {
            var finalValue = parseFloat($(«#display»).data(«valueOne»)) * parseFloat($(«#display»).data(«valueTwo»));
        } else if ($(«#display»).data(«thePendingFunction») == «/») {
            var finalValue = parseFloat($(«#display»).data(«valueOne»)) / parseFloat($(«#display»).data(«valueTwo»));
        }
          
        $(«#display»).val(finalValue);
                      
        resetCalculator(finalValue);
        $(«#display»).data(«fromPrevious», true);
                      
    } else {
        // both numbers are not locked, do nothing.
    }
      
});

И последнее, но не менее важное: кнопка очистки — самая простая из всех. Нажмите его, очистите счетчик до нуля.

1
2
3
$(«.clear-button»).click(function(){
    resetCalculator(«0»);
});



Это делает это люди. Я надеюсь, что между живым примером, скринкастом и этим письменным уроком это была полезная учебная сессия. Я, конечно, узнал несколько вещей при его создании. Если вы можете придумать какие-либо чрезвычайно полезные приложения этого, свяжитесь со мной и дайте мне знать.