cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

Quick-add: + add another resource

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              <div ng-app="app">
  
  <script type="text/ng-template" id="bower_components/device-directive-ng/dist/views/templates/compact.html">
  <div class="ly-compact ly-device ly-device-{{device.id}} ly-type-{{type.id}}" ng-class="{'ly-sensor': !hasFunctions}">

  <!-- ---------------- -->
  <!--  Device Message  -->
  <!-- ---------------- -->

  <div class="ly-message ly-generic-message ly-animation-fast" ng-if="view.path=='/message'">
    <p class="ly-description">{{message.title}}</p>
    <p class="ly-description-sub">{{message.description}}</p>
  </div>

  <!-- ----------------- -->
  <!--  Loading message  -->
  <!-- ----------------- -->

  <div class="ly-message ly-loading" ng-if="view.path=='/loading'">
    <p class="ly-description">Loading Device</p>
    <div class="ly-spinner">
      <div class="ly-bounce-1"></div>
      <div class="ly-bounce-2"></div>
      <div class="ly-bounce-3"></div>
    </div>
  </div>


  <!--  Device Content  -->

  <div class="ly-content" ng-class="{'ly-animation': view.path=='/default'}" ng-if="view.path!='/loading' && view.path!='/message'">


    <!-- Device status -->

    <div class="ly-status">


      <!-- Default function circle button -->

      <div class="ly-execute" ng-click="execute(status.function)">
        <button class="ly-button"></button>
        <div class="ly-spinner ly-animation" ng-if="device.pending">
          <div class="ly-bounce-1"></div>
          <div class="ly-bounce-2"></div>
          <div class="ly-bounce-3"></div>
        </div>
      </div>

      <!-- Description -->

      <div class="ly-description" ng-click="fire('open')">
        <p class="ly-name">{{device.name}}</p>
        <p class="ly-extras ly-updated-animation">
        {{status.name || 'Undefined status'}}
        </p>
        <p class="ly-open-button">
        <i class="fa fa-angle-right"></i>
        </p>
      </div>
    </div>

    <!-- Device functions -->

    <div class="ly-functions" ng-if="hasFunctions">
      <div class="ly-function-container" ng-repeat="function in functions">

        <!-- Function form -->

        <div class="ly-function-form ly-modal ly-animation-fast" ng-if="function.visibleForm">
          <div class="ly-modal-backdrop" ng-click="function.visibleForm=false"></div>
          <div class="ly-modal-window">
            <a class="ly-close" href="" ng-click="function.visibleForm=false">×</a>
            <div class="ly-header">
              <p class="ly-name">{{function.name}}</p>
            </div>
            <form class="ly-form" ng-submit="execute(function)">
              <div class="ly-fields">
                <div class="ly-field ly-editable"
                  ng-repeat="property in function.properties"
                  ng-class="{'ly-no-underline': (property.type=='range' || property.type=='color') }"
                  ng-if="property.toFill">

                  <p class="ly-description">
                    <span>Set {{property.name | lowercase}}</span>
                    <span ng-if="property.type=='range'">to {{property.expected}}</span>
                  </p>

                  <input class="ly-value ly-{{property.type}}"
                    type="{{property.type}}"
                    min="{{property.range.min}}"
                    max="{{property.range.max}}"
                    step="{{property.range.step}}"
                    ng-if="property.accepted==null"
                    ng-model="property.expected">
                  </input>

                  <select class="ly-value"
                    ng-model="property.expected"
                    ng-options="key as value for (key , value) in property.accepted"
                    ng-if="property.accepted && property.type=='text'">
                  </select>

                </div>
              </div>
              <div class="ly-actions">
                <button class="ly-button ly-update-button" ng-click="execute(function)">Execute</button>
              </div>
            </form>
          </div>
        </div>

      </div>
    </div>

  </div>
  </div>

  </script>

  <device device-id="1" device-template="bower_components/device-directive-ng/dist/views/templates/compact.html"></device>

</div>
            
          
!
            
              /*
 * Fonts
 */

@font-face {
  font-family: 'Lato';
}

/*
 * Device component reset
 */

.ly-device * {
  font-size: 1em;
  font-family: "Lato", "Helvetica Neue", sans-serif;
  background: none repeat scroll 0 0 transparent;
  border: medium none;
  border-spacing: 0;
  font-size: 1em;
  font-weight: 100;
  list-style: none outside none;
  margin: 0;
  padding: 0;
  text-align: left;
  text-decoration: none;
  text-indent: 0;
  line-height: 1.2em;
}

.ly-device .fa {
  font-family: FontAwesome;
}


/*
 * Device generics
 */

.ly-device {
  font-family: "Lato", "Helvetica Neue", sans-serif;
  background-color: #fff;
  color: #333;
  border: 1px solid #eee;
  position: relative;
}

.ly-device p {
  margin: 0;
}

.ly-device .ly-error {
  color: #FF7373 !important;
}



/*
 * Links
 */

.ly-device a {
  text-decoration: none;
  color: #239cbb
}


/*
 * Buttons
 */

.ly-device .ly-modal .ly-button {
  background-color: #239cbb;
  padding: 0.6em 0;
  cursor: pointer;
  color: #fff;
  text-align: center;
}

.ly-device .ly-button {
  cursor: pointer;
}


/*
 * Link and button transitions
 */

.ly-device .ly-button,
.ly-device a {
  -webkit-transition: color 0.3s ease, text-decoration 0.3s ease, background 0.3s ease;
  -moz-transition: color 0.3s ease, text-decoration 0.3s ease, background 0.3s ease;
  transition: color 0.3s ease, text-decoration 0.3s ease, background 0.3s ease;
}


/*
 * Device spinner
 */

.ly-device .ly-spinner > div {
  width: .5em;
  height: .5em;
  background-color: #bbb;
  border-radius: 100%;
  display: inline-block;

  -webkit-animation: bouncedelay 1.4s infinite ease-in-out;
  animation: bouncedelay 1.4s infinite ease-in-out;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}

.ly-device .ly-spinner .ly-bounce-1 {
  -webkit-animation-delay: -0.32s;
  animation-delay: -0.32s;
}

.ly-device .ly-spinner .ly-bounce-2 {
  -webkit-animation-delay: -0.16s;
  animation-delay: -0.16s;
}

@-webkit-keyframes bouncedelay {
  0%, 80%, 100% { -webkit-transform: scale(0.0) }
  40% { -webkit-transform: scale(1.0) }
}

@keyframes bouncedelay {
  0%, 80%, 100% {
    transform: scale(0.0);
    -webkit-transform: scale(0.0);
  } 40% {
    transform: scale(1.0);
    -webkit-transform: scale(1.0);
  }
}



/*
 * Device loading section
 */

.ly-device .ly-message {
  /*background-color: #d5d5d5;*/
  padding: 1em;
  color: #aaa;
}

.ly-device .ly-message .ly-spinner,
.ly-device .ly-message .ly-description,
.ly-device .ly-message .ly-description-sub {
  text-align: center
}

.ly-device .ly-message .ly-description {
  font-size: 1.4em;
}


/*
 * Header section
 */

.ly-device .ly-header {
  /*background-color: #ddd;*/
}

.ly-device .ly-header {
  padding: 0.6em;
  border-bottom: 1px solid #f8f8f8;
}

.ly-device .ly-header .ly-name {
  font-size: 2em;
}

.ly-device .ly-header .ly-menu {
  padding-left: 0;
  padding-right: 0;
  list-style: none;
  display: inline;
}

.ly-device .ly-header .ly-menu li {
  display: inline;
  padding-right: 0.4em;
}

.ly-device .ly-header .ly-menu li a {
  font-size: 1em;
  text-decoration: none;
}


/*
 * Status section
 */

.ly-device .ly-status {
  /*background-color: #e5e5e5;*/
}

.ly-device .ly-status {
  padding: 1em 0.6em;
  border-bottom: 1px solid #f8f8f8;
  cursor: pointer;
}

.ly-device .ly-status .ly-execute {
  position: relative;
  float: left;
}

.ly-device .ly-status .ly-execute .ly-button {
  float: left;
  width: 2.8em;
  height: 2.8em;
  border: 3px solid #239cbb;
  border-radius: 100%;
}

.ly-device .ly-status .ly-execute .ly-spinner {
  position: absolute;
  top: 0.6em;
  left: 0.7em;
}

.ly-device .ly-status .ly-execute .ly-spinner > div {
  width: .25em;
  height: .25em;
  background-color: #239cbb;
}

.ly-device .ly-status .ly-description {
  margin-left: 3.5em;
}

.ly-device .ly-status .ly-description .ly-name {
  font-size: 1.7em;
  color: #239cbb;
  line-height: 1.05em;
}

.ly-device .ly-status .ly-description .ly-extras {
  font-size: 0.9em;
  color: #888;
}

.ly-device .ly-status-disabled {
  cursor: default;
}

.ly-device .ly-status-disabled .ly-description .ly-name {
  color: #666;
}

.ly-device .ly-status-disabled .ly-execute .ly-button {
  border: 2px solid #aaa;
  cursor: default !important;
}


/*
 * Function
 */

.ly-device .ly-functions {
  /*background-color: #eee;*/
}

.ly-device .ly-functions {
  padding: 0.6em 0em;
  border-bottom: 1px solid #f8f8f8;
}

.ly-device .ly-function {
  padding: 0.3em 1em 0.3em 1.1em;
  padding-bottom: 0.6em;
  cursor: pointer;
}

.ly-device .ly-function .ly-execute {
  clear: both;
}

.ly-device .ly-function .ly-execute .ly-button {
  float: left;
  width: 1.8em;
  height: 1.8em;
  border: 2.5px solid #239cbb;
  border-radius: 100%;
}

.ly-device .ly-function .ly-execute .ly-name {
  margin-left: 2em;
  font-size: 1.5em;
}


/*
 * Modals
 */

.ly-device .ly-modal .ly-modal-backdrop {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  width: 100%;
  height:100%;
  z-index: 2000;
  opacity: 0.9;
  background-color: #eee;
}

.ly-device .ly-modal .ly-modal-window {
  position: absolute;
  z-index: 2001;
  top: 0;
  left: 0;
  width: 100.6%;
  background: #fff;
  border: 1px solid #eee;
  margin-top: -1px;
  margin-right: -1px;
  margin-left: -1px;
}

.ly-device .ly-modal .ly-modal-window .ly-close {
  position: absolute;
  color: #aaa;
  font-size: 2.5em;
  line-height: 1em;
  right: 0.3em;
  top: 0em;
  z-index: 2000;
}


.ly-device .ly-modal .ly-modal-window .ly-subheader {
  font-size: 1.3em;
  padding: .7em .6em;
  background-color: #f8f8f8;
  border-top: 1px solid #eee;
  border-bottom: 1px solid #eee;
}

/*
 * Function form
 */

.ly-device .ly-form .ly-head {
  padding: 0.6em;
  border-bottom: 1px solid #eee;
}

.ly-device .ly-form .ly-head .ly-name {
  font-size: 2.2em;
}

.ly-device .ly-form .ly-description {
  font-size: 1.2em;
}

.ly-device .ly-form .ly-fields {
  padding: 0.6em 0em;
  padding-bottom: 1em;
  margin-bottom: 1em;
}

.ly-device .ly-form .ly-field {
  padding: 0.3em 1em;
}

.ly-device .ly-form .ly-field .ly-description {
  margin-bottom:0.5em;
}

.ly-device .ly-form .ly-field .ly-name {
  color: #999;
  font-size: 0.9em;
}

.ly-device .ly-form .ly-button {
  font-family: "Lato", "Helvetica Neue", sans-serif;
  position: absolute;
  width: 100%;
  padding: 0;
  padding-top: 0.7em;
  padding-bottom: 0.7em;
  font-size: 1.5em;
  text-transform: uppercase;
  box-shadow: 1px 1px 3px #999;
}

.ly-device .ly-form .ly-field input[type="range"] {
  width: 93%
}

.ly-device .ly-form .ly-field .ly-color {
  height: 1.8em;
}

.ly-device .ly-form .ly-field .ly-range {
  margin-top: 2.3em !important;
}



/*
 * Properties
 */

.ly-device .ly-properties {
  /*background-color: #f4f4f4;*/
}

.ly-device .ly-properties {
  padding: 0.6em 0em;
}

.ly-device .ly-property {
  position: relative;
  padding: 0.3em 1.2em 0.3em 1.3em;
  clear: both;
}

.ly-device .ly-property .ly-button {
  float: left;
  width: 1.4em;
  height: 1.4em;
  border: 1.5px solid #aaa;
  border-radius: 100%;
  cursor: default;
}

.ly-device .ly-property .ly-description {
  margin-left: 2.4em;
  font-size: 1.2em;
}

.ly-device .ly-property  .ly-description .ly-name {
  color: #aaa;
  font-size: 0.9em;
}

.ly-device .ly-property  .ly-description .ly-color-ball {
  border: 10px solid;
  border-radius: 100%;
  float: right;
}

/*.ly-sensor .ly-properties .ly-property {*/
  /*padding-left: 0.8em;*/
/*}*/

/*.ly-sensor .ly-properties .ly-description {*/
  /*margin-left: 2.0em;*/
/*}*/


/*
 * Settings
 */

.ly-device .ly-form .ly-fields {
  padding: 0;
}

.ly-device .ly-form .ly-field {
  padding: 0;
  height: 3.4em;
  position: relative;
  /*border-bottom: 1px solid #f8f8f8;*/
}

.ly-device .ly-form .ly-editable {
  height: 4.2em;
}

.ly-device .ly-form .ly-no-underline .ly-value {
  border-bottom: none !important;
}

.ly-device .ly-form .ly-field .ly-description {
  position: absolute;
  padding: 1em 1em 0;
  color: #bbb;
  font-size: 0.8em;
  text-transform: uppercase;
}

.ly-device .ly-form .ly-field .ly-value {
  position: absolute;
  color: #666;
  font-family: "Lato", "Helvetica Neue", sans-serif;
  font-size: 1em;
  width: 92%;
  margin: 2em 0.8em 0.8em;
}

.ly-device .ly-form .ly-editable .ly-value {
  padding-bottom: 0.1em;
  border-bottom: 1px dashed #ddd;
}

.ly-device .ly-form .ly-actions .ly-button {
  font-size: 1.2em;
  margin-left: 3.5%;
  margin-bottom: .8em;
  width: 93%;
  position: relative;
}

.ly-device .ly-form .ly-actions .ly-delete-action {
  padding-top: 1em;
  padding-bottom: 1em;
  background-color: #f8f8f8;
  font-size: 1.2em;
  padding-left: .8em;
}

.ly-device .ly-form .ly-actions .ly-delete-link,
.ly-device .ly-form .ly-actions .ly-delete-link:hover {
  color: rgb(233, 0, 0);
}



.ly-device .ly-form .ly-field ::-webkit-input-placeholder { color:#ddd; font-weight: 100; }
.ly-device .ly-form .ly-field ::-moz-placeholder { color:#ddd; } /* firefox 19+ */
.ly-device .ly-form .ly-field :-ms-input-placeholder { color:#ddd; } /* ie */
.ly-device .ly-form .ly-field input:-moz-placeholder { color:#ddd; }

.ly-device .ly-form .ly-field select {
  background: transparent;
  -webkit-appearance: none;
}

button:focus,
select:focus,
input:focus {
  outline: 0;
}


/*
 * Settings (Delete)
 */

.ly-device .ly-modal .ly-info {
  color: rgb(223, 0, 0);
  font-size: 1.2em;
  padding: 0.5em;
  padding-top: 1em;
}

.ly-device .ly-delete .ly-value {
  font-size: 1.3em;
  margin: 0.5em 0.5em 0.8em;
}

.ly-device .ly-delete .ly-field {
  height: 5.5em;
}

.ly-device .ly-delete .ly-actions .ly-cancel-button {
  background-color: #ccc;
}

.ly-device .ly-settings .ly-actions {
  margin-top: 1em;
}

.ly-device .ly-settings .ly-settings-device .ly-header {
  border-bottom: none;
}

.ly-device .ly-settings .ly-actions .ly-disabled-button {
  background-color: #ccc !important;
}

.ly-device .ly-settings .ly-actions .ly-disabled-button:hover {
  background-color: #ccc !important;
  cursor: not-allowed;
}


/*
 * Elements animation
 */

.ly-animation.ng-enter {
  -webkit-animation: fadeIn 0.6s;
  animation: fadeIn 0.6s;
}

.ly-animation.ng-leave {
  -webkit-animation: fadeOut 0.6s;
  animation: fadeOut 0.6s;
}

.ly-animation-fast.ng-enter {
  -webkit-animation: fadeIn 0.3s;
  animation: fadeIn 0.3s;
}

.ly-animation-fast.ng-leave {
  -webkit-animation: fadeOut 0.3s;
  animation: fadeOut 0.3s;
}


/* Override animated.css */

.animated {
  -webkit-animation-duration: 0.5s;
  animation-duration: 0.5s;
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}

@-webkit-keyframes flipInX {
  0% {
    -webkit-transform: perspective(400px) rotateX(90deg);
    transform: perspective(400px) rotateX(90deg);
    opacity: 0;
  }

  40% {
    -webkit-transform: perspective(400px) rotateX(-30deg);
    transform: perspective(400px) rotateX(-30deg);
  }

  70% {
    -webkit-transform: perspective(400px) rotateX(30deg);
    transform: perspective(400px) rotateX(30deg);
  }

  100% {
    -webkit-transform: perspective(400px) rotateX(0deg);
    transform: perspective(400px) rotateX(0deg);
    opacity: 1;
  }
}

@keyframes flipInX {
  0% {
    -webkit-transform: perspective(400px) rotateX(90deg);
    -ms-transform: perspective(400px) rotateX(90deg);
    transform: perspective(400px) rotateX(90deg);
    opacity: 0;
  }

  40% {
    -webkit-transform: perspective(400px) rotateX(-30deg);
    -ms-transform: perspective(400px) rotateX(-30deg);
    transform: perspective(400px) rotateX(-30deg);
  }

  70% {
    -webkit-transform: perspective(400px) rotateX(30deg);
    -ms-transform: perspective(400px) rotateX(30deg);
    transform: perspective(400px) rotateX(30deg);
  }

  100% {
    -webkit-transform: perspective(400px) rotateX(0deg);
    -ms-transform: perspective(400px) rotateX(0deg);
    transform: perspective(400px) rotateX(0deg);
    opacity: 1;
  }
}

.flipInX {
  -webkit-backface-visibility: visible !important;
  -ms-backface-visibility: visible !important;
  backface-visibility: visible !important;
  -webkit-animation-name: flipInX;
  animation-name: flipInX;
}



/*
 * Compact personalizations
 */

.ly-compact .ly-functions {
  padding: 0em;
  border-bottom: none;
}

.ly-compact .ly-open-button {
  color: #239cbb;
  position: absolute;
  top: -0.05em;
  right: 0.1em;
  font-size: 4.2em;
}

            
          
!
            
              var app = angular.module('app', ['lelylan.directives.device', 'ngMockE2E']);

// mock all requests we need
app.run(function($httpBackend, $timeout, Profile) {
  Profile.set({id: '1'});

  device = {
  "id": "1",
  "uri": "http://www.example.com/devices/1",
  "name": "Closet dimmer",
  "categories": ["lights"],
  "pending": false,
  "activated": true,
  "type": {
    "id": "1",
    "uri": "https://type.lelylan.com/types/dimmer"
  },
  "properties": [{
    "id": "1",
    "uri": "https://type.lelylan.com/properties/status",
    "value": "off",
    "expected": "off",
    "pending": false,
    "accepted": null
  }, {
    "id": "2",
    "uri": "https://type.lelylan.com/properties/intensity",
    "expected": "0",
    "value": "0",
    "pending": false,
    "accepted": null
  }],
  "physical": {
    "uri": "https://node.lelylan.com/mqtt/devices/1"
  },
  "maker": {
    "id": "1",
    "uri": "http://api.lelylan.com/people/1"
  },
  "owner": {
    "id": "2",
    "uri": "http://api.lelylan.com/people/2"
  },
  "created_at": "2011-06-20T15:54:42Z",
  "updated_at": "2011-04-23T15:55:31Z",
  "updated_from": "you"
  }
  
  type = {
    "id": "1",
    "uri": "http://www.example.com/types/50042612d033a9b4ac0007fa",
    "name": "Dimmer",
    "description": "Dimmer description",
    "categories": ["lights"],
    "owner": {
      "id": "1",
      "uri": "http://api.lelylan.com/people/1"
    },
    "created_at": "2012-07-16T14:32:50Z",
    "updated_at": "2012-07-16T14:32:50Z",
    "properties": [{
      "id": "1",
      "uri": "http://www.example.com/properties/status",
      "name": "Status",
      "type": "text",
      "default": "0",
      "accepted": { "on": "On", "off": "Off" },
      "created_at": "2012-07-16T14:32:50Z",
      "updated_at": "2012-07-16T14:32:50Z"
    },
    {
      "uri": "http://www.example.com/properties/intensity",
      "id": "2",
      "name": "Intensity",
      "type": "range",
      "range": { "min": "0", "max": "100", "step": "1" },
      "default": "0",
      "created_at": "2012-07-16T14:32:50Z",
      "updated_at": "2012-07-16T14:32:50Z"
    }],
    "functions": [{
        "uri": "http://www.example.com/functions/50042612d033a9b4ac0007f0",
        "id": "1",
        "name": "Turn on",
        "created_at": "2012-07-16T14:32:50Z",
        "updated_at": "2012-07-16T14:32:50Z",
        "properties": [{
          "id": "1",
          "uri": "http://www.example.com/properties/status",
          "expected": "on"
        }]
    },
    {
        "uri": "http://www.example.com/functions/50042612d033a9b4ac0007f2",
        "id": "2",
        "name": "Turn off",
        "created_at": "2012-07-16T14:32:50Z",
        "updated_at": "2012-07-16T14:32:50Z",
        "properties": [{
          "id": "1",
          "uri": "http://www.example.com/properties/status",
          "expected": "off"
        }]
    },
    {
        "uri": "http://www.example.com/functions/50042612d033a9b4ac0007f5",
        "id": "3",
        "name": "Set intensity",
        "created_at": "2012-07-16T14:32:50Z",
        "updated_at": "2012-07-16T14:32:50Z",
        "properties": [{
          "id": "1",
          "uri": "http://www.example.com/properties/status",
          "expected": "on"
        },
        {
          "id": "2",
          "uri": "http://www.example.com/properties/intensity",
          "expected": null
        }]
    }],
    "statuses": [{
        "uri": "http://www.example.com/statuses/50042612d033a9b4ac0007f8",
        "id": "50042612d033a9b4ac0007f8",
        "name": "On",
        "created_at": "2012-07-16T14:32:50Z",
        "updated_at": "2012-07-16T14:32:50Z",
        "function": {
          "id": "2",
          "uri": "http://www.example.com/functions/turn-off"
        },
        "properties": [{
          "id": "1",
          "uri": "http://www.example.com/properties/status",
          "pending": false,
          "values": ["on"],
          "ranges": []
        }]
      }, {
        "uri": "http://www.example.com/statuses/50042612d033a9b4ac0007f8",
        "id": "50042612d033a9b4ac0007f8",
        "name": "Off",
        "created_at": "2012-07-16T14:32:50Z",
        "updated_at": "2012-07-16T14:32:50Z",
        "function": {
          "id": "1",
          "uri": "http://www.example.com/functions/turn-on"
        },
        "properties": [{
          "id": "1",
          "uri": "http://www.example.com/properties/status",
          "pending": false,
          "values": ["off"],
          "ranges": []
        }]
    }]
  };
  
  privates = {
    "uri": "http://api.lelylan.com/devices/5042344b95fc441000000001",
    "id": "1",
    "name": "Closet dimmer",
    "secret": "secret",
    "activation_code": "activation_code"
  }

  $httpBackend.when('GET', /\/templates\//).passThrough();

  $httpBackend.whenGET('http://api.lelylan.com/devices/1').respond(device);
  $httpBackend.whenPUT('http://api.lelylan.com/devices/1')
    .respond(function(method, url, data, headers) { return [200, updateDevice(data), {}]; });
  $httpBackend.whenPUT('http://api.lelylan.com/devices/1/properties')
    .respond(function(method, url, data, headers) { return [200,  updateDeviceProperties(data), {}]; });
  $httpBackend.whenDELETE('http://api.lelylan.com/devices/1').respond(device);
  $httpBackend.whenGET('http://api.lelylan.com/types/1').respond(type);
  $httpBackend.whenGET('http://api.lelylan.com/devices/1/privates').respond(privates);

  var updateDevice = function(data) {
    data = angular.fromJson(data);
    device.updated_at   = new Date();
    device.name         = data.name;
    device.physical.uri = data.physical.uri;
    return device;
  }

  var updateDeviceProperties = function(data) {
    data = angular.fromJson(data);
    device.updated_at = new Date();
    _.each(data.properties, function(property) {
      var result = _.find(device.properties, function(_property) { return _property.id == property.id; } );
      result.expected = result.value = property.expected; });
    return device;
  }
});

// hack to make the anchor links work
app.run(function($rootScope, $location, $anchorScroll) {
  $rootScope.$on('$routeChangeSuccess', function(newRoute, oldRoute) { });
});

app.config(['$locationProvider', function ($locationProvider) {
  $locationProvider.html5Mode(true);
  $locationProvider.hashPrefix('!');
}]);

            
          
!
999px
Loading ..................

Console