Commits

Ashley Felton committed c7a4f4f

Added JS/CSS for toggle buttons. Basic view & template for LED controller.

Comments (0)

Files changed (7)

temper/__init__.py

 from flaskext.cache import Cache
 
 # Configure application
-DEBUG = False
+DEBUG = True
 CACHE_TYPE = 'simple'
 CACHE_DEFAULT_TIMEOUT = 60 * 5  # Cache for 5 minutes by default.
 CACHE_THRESHOLD = 20

temper/static/css/bootstrap-toggle-buttons.css

+/* line 12, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button {
+  display: inline-block;
+  cursor: pointer;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  -ms-border-radius: 5px;
+  -o-border-radius: 5px;
+  border-radius: 5px;
+  border: 1px solid;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  position: relative;
+  text-align: left;
+  min-height: 25px;
+  max-height: 25px;
+  overflow: hidden;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -khtml-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+/* line 32, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button.deactivate {
+  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
+  opacity: 0.5;
+  cursor: default !important;
+}
+/* line 35, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button.deactivate label, .toggle-button.deactivate span {
+  cursor: default !important;
+}
+/* line 39, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button > div {
+  display: inline-block;
+  width: 150px;
+  position: absolute;
+  top: 0;
+}
+/* line 45, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button > div.disabled {
+  left: -50%;
+}
+/* line 49, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button input[type=checkbox] {
+  display: none;
+}
+/* line 57, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button span, .toggle-button label {
+  cursor: pointer;
+  position: relative;
+  float: left;
+  display: inline-block;
+  height: 25px;
+}
+/* line 65, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button label {
+  background: #fefefe;
+  margin-left: -4px;
+  margin-right: -4px;
+  border: 1px solid #E6E6E6;
+  margin-top: -1px;
+  z-index: 100;
+  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #fefefe), color-stop(100%, #e6e6e6));
+  background-image: -webkit-linear-gradient(top, #fefefe, #e6e6e6);
+  background-image: -moz-linear-gradient(top, #fefefe, #e6e6e6);
+  background-image: -o-linear-gradient(top, #fefefe, #e6e6e6);
+  background-image: linear-gradient(top, #fefefe, #e6e6e6);
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+  -ms-border-radius: 4px;
+  -o-border-radius: 4px;
+  border-radius: 4px;
+}
+/* line 77, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button span {
+  color: #fefefe;
+  text-align: center;
+  font-weight: bold;
+  line-height: 25px;
+  z-index: 1;
+}
+/* line 84, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button span.labelLeft {
+  -moz-border-radius-topleft: 4px;
+  -webkit-border-top-left-radius: 4px;
+  border-top-left-radius: 4px;
+  -moz-border-radius-bottomleft: 4px;
+  -webkit-border-bottom-left-radius: 4px;
+  border-bottom-left-radius: 4px;
+  padding-left: 3px;
+}
+/* line 89, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button span.labelRight {
+  -moz-border-radius-topright: 4px;
+  -webkit-border-top-right-radius: 4px;
+  border-top-right-radius: 4px;
+  -moz-border-radius-bottomright: 4px;
+  -webkit-border-bottom-right-radius: 4px;
+  border-bottom-right-radius: 4px;
+  color: black;
+  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #fefefe), color-stop(100%, #e6e6e6));
+  background-image: -webkit-linear-gradient(top, #fefefe, #e6e6e6);
+  background-image: -moz-linear-gradient(top, #fefefe, #e6e6e6);
+  background-image: -o-linear-gradient(top, #fefefe, #e6e6e6);
+  background-image: linear-gradient(top, #fefefe, #e6e6e6);
+  padding-right: 3px;
+}
+/* line 97, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button span.primary, .toggle-button span.labelLeft {
+  color: #fefefe;
+  background: #0088cc;
+  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #0088cc), color-stop(100%, #0055cc));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0055cc);
+  background-image: -moz-linear-gradient(top, #0088cc, #0055cc);
+  background-image: -o-linear-gradient(top, #0088cc, #0055cc);
+  background-image: linear-gradient(top, #0088cc, #0055cc);
+}
+/* line 102, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button span.info {
+  color: #fefefe;
+  background: #5bc0de;
+  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #5bc0de), color-stop(100%, #2f96b4));
+  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
+  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
+  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
+  background-image: linear-gradient(top, #5bc0de, #2f96b4);
+}
+/* line 108, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button span.success {
+  color: #fefefe;
+  background: #62c462;
+  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #62c462), color-stop(100%, #51a351));
+  background-image: -webkit-linear-gradient(top, #62c462, #51a351);
+  background-image: -moz-linear-gradient(top, #62c462, #51a351);
+  background-image: -o-linear-gradient(top, #62c462, #51a351);
+  background-image: linear-gradient(top, #62c462, #51a351);
+}
+/* line 114, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button span.warning {
+  color: #fefefe;
+  background: #dbb450;
+  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dbb450), color-stop(100%, #f89406));
+  background-image: -webkit-linear-gradient(top, #dbb450, #f89406);
+  background-image: -moz-linear-gradient(top, #dbb450, #f89406);
+  background-image: -o-linear-gradient(top, #dbb450, #f89406);
+  background-image: linear-gradient(top, #dbb450, #f89406);
+}
+/* line 120, ../sass/bootstrap-toggle-buttons.scss */
+.toggle-button span.danger {
+  color: #fefefe;
+  background: #ee5f5b;
+  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ee5f5b), color-stop(100%, #bd362f));
+  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
+  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
+  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
+  background-image: linear-gradient(top, #ee5f5b, #bd362f);
+}

temper/static/js/jquery.toggle.buttons.js

+!function ($) {
+  "use strict";
+  // version: 2.0
+  // by Mattia Larentis - follow me on twitter! @SpiritualGuru
+
+  $.fn.toggleButtons = function (method) {
+    var $element
+      , $div
+      , transitionSpeed = 0.05
+      , methods = {
+        init: function (opt) {
+          this.each(function () {
+            var $spanLeft
+              , $spanRight
+              , options;
+
+            $element = $(this);
+            $element.addClass('toggle-button');
+
+            options = $.extend({}, $.fn.toggleButtons.defaults, opt);
+            $(this).data('options', options);
+
+            $spanLeft = $('<span></span>').addClass("labelLeft").text(options.label.enabled === undefined ? "ON" : options.label.enabled);
+            $spanRight = $('<span></span>').addClass("labelRight").text(options.label.disabled === undefined ? "OFF " : options.label.disabled);
+
+            // html layout
+            $div = $element.find('input').wrap($('<div></div>')).parent();
+            $div.append($spanLeft);
+            $div.append($('<label></label>').attr('for', $element.find('input').attr('id')));
+            $div.append($spanRight);
+
+            if ($element.find('input').is(':checked'))
+              $element.find('>div').css('left', "0");
+            else $element.find('>div').css('left', "-50%");
+
+            if (options.animated) {
+              if (options.transitionSpeed !== undefined)
+                if (/^(\d*%$)/.test(options.transitionSpeed))  // is a percent value?
+                  transitionSpeed = 0.05 * parseInt(options.transitionSpeed) / 100;
+                else
+                  transitionSpeed = options.transitionSpeed;
+            }
+            else transitionSpeed = 0;
+
+            $(this).data('transitionSpeed', transitionSpeed * 1000);
+
+
+            options["width"] /= 2;
+
+            // size of the bootstrap-toggle-button
+            $element
+              .css('width', options.width * 2)
+              .find('>div').css('width', options.width * 3)
+              .find('>span, >label').css('width', options.width);
+
+            if ($element.find('input').is(':disabled'))
+              $(this).addClass('deactivate');
+
+            $spanLeft.addClass(options.style.enabled === undefined ? "" : options.style.enabled)
+            $spanRight.addClass(options.style.disabled === undefined ? "" : options.style.disabled)
+
+
+            var changeStatus = function ($this) {
+              $this.siblings('label').trigger('mousedown').trigger('mouseup').trigger('click');
+            };
+
+            $spanLeft.on('click', function (e) {
+              changeStatus($(this));
+            });
+            $spanRight.on('click', function (e) {
+              changeStatus($(this));
+            });
+
+            $('.toggle-button').find('input').on('change', function (e) {
+              var $element = $(this).parent()
+                , active = $(this).is(':checked')
+                , $toggleButton = $(this).closest('.toggle-button');
+
+              e.preventDefault();
+              e.stopImmediatePropagation();
+
+              $element.animate({'left': active ? '0' : '-50%'}, $toggleButton.data('transitionSpeed'));
+
+              options = $toggleButton.data('options');
+              options.onChange($element, active, e);
+            });
+
+            $('.toggle-button').find('label').on('mousedown', function (e) {
+              e.preventDefault();
+              e.stopImmediatePropagation();
+
+              if ($(this).closest('.toggle-button').is('.deactivate'))
+                $(this).unbind('click');
+              else {
+                $(this).on('mousemove', function (e) {
+                  var $element = $(this).closest('.toggle-button')
+                    , relativeX = e.pageX - $element.offset().left
+                    , percent = ((relativeX / (options.width * 2)) * 100);
+
+                  if (percent < 25)
+                    percent = 25;
+                  else if (percent > 75)
+                    percent = 75;
+
+                  $element.find('>div').css('left', (percent - 75) + "%")
+                });
+
+                $(this).on('click', function (e) {
+                  var $target = $(e.target)
+                    , $input = $target.siblings('input');
+
+                  e.stopImmediatePropagation();
+                  e.preventDefault();
+                  $(this).unbind('mouseleave');
+
+                  $input.attr('checked', !($input.is(':checked'))).trigger('change');
+                });
+
+                $(this).on('mouseleave', function (e) {
+                  var $myCheckBox = $(this).siblings('input');
+
+                  e.preventDefault();
+                  e.stopImmediatePropagation();
+
+                  $(this).unbind('mouseleave');
+                  $(this).trigger('mouseup');
+
+                  if (parseInt($(this).parent().css('left')) < -25)
+                    $myCheckBox.attr('checked', false);
+                  else $myCheckBox.attr('checked', true);
+
+                  $myCheckBox.trigger('change');
+                });
+
+                $(this).on('mouseup', function (e) {
+                  e.stopImmediatePropagation();
+                  e.preventDefault();
+                  $(this).unbind('mousemove');
+                });
+              }
+            });
+          });
+        },
+        toggleActivation: function () {
+          $(this).toggleClass('deactivate');
+        }
+      };
+
+    if (methods[method])
+      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
+    else if (typeof method === 'object' || !method)
+      return methods.init.apply(this, arguments);
+    else
+      $.error('Method ' + method + ' does not exist on jQuery.tooltip');
+  };
+
+  $.fn.toggleButtons.defaults = {
+    onChange: function () {
+    },
+    width: 100,
+    animated: true,
+    transitionSpeed: undefined,
+    label: {
+      enabled: undefined,
+      disabled: undefined
+    },
+    style: {
+      enabled: undefined,
+      disabled: undefined
+    }
+  };
+}($);

temper/templates/base.html

                 }
             }
         </style>
+        {% block extra_css %}{% endblock %}
         <script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>
         <script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.1.0/respond.min.js"></script>
     </head>

temper/templates/index.html

 {% block body %}
 <div class="row-fluid">
     <div class="span12">
-        <h1>Hello, world!</h1>
-        <p>This is the landing page for my Raspberry Pi web server.</p>
+        <h1>Hello, World!</h1>
+        <p>This is the landing page for projects relating to my Raspberry Pi:</p>
+        <ul>
+            <li><a href="/temps">Temperature logger</a></li>
+            <li><a href="/leds">LED controller</a></li>
+        </ul>
     </div>
 </div>
 {% endblock %}

temper/templates/leds.html

+{% extends "base.html" %}
+
+{% block extra_css %}
+<link rel="stylesheet" href="/static/css/bootstrap-toggle-buttons.css">
+{% endblock %}
+
+
+{% block body %}
+<div class="row-fluid">
+    <div class="span12">
+        <h1>LED Controller</h1>
+        <label for="gpio17-toggle-button">GPIO pin 17:</label>
+        <div id="gpio17-toggle-button" data-gpio="17">
+            <input id="checkbox-gpio17" type="checkbox" value="gpio17" checked="checked">
+        </div>
+    </div>
+</div>
+{% endblock %}
+
+{% block extra_js %}
+<script src="/static/js/jquery.toggle.buttons.js"></script>
+<script type="text/javascript">
+    $('#gpio17-toggle-button').toggleButtons({
+        onChange: function ($el, status, e) {
+            //console.log($el, status);
+            //console.log($($el).parent().data("gpio"));
+            $.post("/gpio_mode", {gpio: 17, mode: 0},
+                function(data) {
+                    console.log(data);
+                }
+            )
+        }
+    });
+</script>
+{% endblock %}
 import json
-from flask import request, render_template
+from flask import request, render_template, jsonify
 from temper import app, utils, cache
 from datetime import datetime
 
 
 
 @app.route('/')
+def index():
+    return render_template('index.html')
+
 @app.route('/temps')
 @cache.cached()
 def temps_week():
     log_date = datetime.strptime(log_date, '%Y-%m-%d')
     temps_li = utils.read_log(log_date)
     return render_template('temp_graph.html', log_date=log_date, temps_li=json.dumps(temps_li))
+
+
+@app.route('/leds')
+def led_controller():
+    return render_template('leds.html')
+
+
+@app.route('/gpio_mode', methods=['POST'])
+def gpio_mode():
+    # Read the GPIO and mode arguments from the POST request.
+    gpio = int(request.form['gpio'])
+    mode = int(request.form['mode'])
+    return jsonify({'gpio': gpio, 'mode': mode})
+#if gpio and mode:  # NOTE: mode == 0 evaluates to False. Duh!
+    #    return jsonify({'gpio': gpio, 'mode': mode})
+    #else:
+    #    return '{}'
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.