Floor plan suggestions

Ok, another basic question. I have added the following template to my index.HTML

        <template>
          <div style="position:relative; width:120px; top:100px; left:100px;">
            <label for="range-10">Circuit: </label>
            <b-form-input id="range-10" v-model="input_brigthness" type="range" min="0" max="100"></b-form-input>
            <div class="mt-2">Brightness: {{ input_brigthness }}</div>
          </div>
        </template>

and also added the variable "input_brightness" to my index.JS file in the data section.
Now I want to do something when the slider has been changed by the user.

I notice that @bulbclicked was used with a method defined in the index.JS file ="myClick"

<div id="floorplan" style="position:relative; left: -400px; width: 1920px; height:30em; background:url(./images/groundfloor.PNG);">
            <bulb id="avmain1p" :color="isonavmain1p ?  'orange' : 'grey'"      :glow="isonavmain1p"    :clickable="true"  x="920" y="190" @bulbclicked="myClick" title="Office Main"> <circle cx="50" cy="50" r="50"/></bulb>
            <div style="position:absolute; top:194px; left:950px; font-size: 70%; color: #383737"> {{value_avmain1p}} </div>
        </div>

But I can't find the equivalent for the slider i.e. type ="range"

I have found the following on the tinternet.

template

<div id="app">
    {{ message }}
    <span id="slider-value-upper" class="lower">{{myValue}}</span><br />
    <input v-model="myValue">
</div>
js code

new Vue({
    el: '#app',
    data: {
        message: 'Watch example',
        myValue: 50
    },
    watch: {
        'myValue': function(val, oldVal){
        if (val < 50) {
            this.message= 'value too low!';
        }else{
          this.message= 'value is ok';
        }
      }
    }
})

I'm reluctant to use it as I think there may be a better way then looking for a change in value.

What I really want is for the value to only be picked up when the user releases from pressing / dragging on the slider, otherwise presumably i'll be spamming my HA system with lots of new brightness values for my light which I do not want to do for performance reasons.
I should add, that I really cannot allow this type of behaviour otherwise if lots of lights are being changed simultaneously they will overload the zwave network.

Search and ye shall find......

<input type="range" min="0" max="1" 
       onmouseup="callfunction()" 
       ontouchend="callfunction()">

It looks like stackoverflow is a good place to find answers on bootstrap...

Apologies, I'll try to stop asking these types of questions on this forum.... :slight_smile:

Hi Alex,

your research on the issue can work .. but there is an easier way to change the vue variable only when the user releases the slider bar. By using the prop lazy

 <b-form-input lazy id="range-10" v-model="input_brigthness" type="range" min="0" max="100"></b-form-input>

this way you avoid additional code and its a bit cleaner since its already supported on bootstrap-vue

1 Like

I think that the point is that using the v-model, you need to use a computed or method? I'm tired so I can't quite remember which. But the model needs to be dynamic so that you can use a function instead of a static value. Then the function contains a uibuilder.send({...})

I think its in watch .. it watches if the vue variable input_brigthness has changed

watch: {

input_brigthness(val, oldVal) {

 uibuilder.send({           // maybe you need to use this.uibuilder here
     'payload': this.input_brigthness,   // or val since we are passing it
     'topic': 'light1 brightness'})}
      }

untested .. you need input_brigthness in you Vue data part ..

You shouldn't really need to use watch with Vue. It is virtually never needed.

You can use the input or change events on the component directly

1 Like

Julian is right .. its a little bit messy to trigger your events with watch especially if you have many sliders and buttons. So to refactor to a working example all made possible with uibuilder ofcourse :sunglasses:

<template>
  <div>
    <label for="range-2">Example range with step value</label>
    <b-form-input lazy v-on:change="sliderChange(value)" id="range-2" v-model="value" type="range" min="0" max="5" step="0.5"></b-form-input>
    <div class="mt-2">Value: {{ value }}</div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        value: '2'
      }}, 

methods: {

sliderChange: function(value)  {
console.log(value);  // uibuilder.send({...})
}
 } 

  }
</script>

Also if you are just starting with Vue may i recommend some excellent resources

  1. The Net Ninja Vue tutorial
  2. Traversy - Vue JS Crash Course
1 Like

Thank you all for your replies.

When I get a break from work and family etc ie between 8pm and midnight on the weekend I'll look into all your suggestions.

Hi Julian,
I'm sneaking this in here because it's also about floor plans!
I've been hacking away at your automation example with the tabs. It has some interesting bits that I'm sure to use.

My issue is getting mouse clicks to work on my SVG. easy enough in the HTML, but i'm loading an SVG using the .

     <b-tabs card id="tabs" v-model="tabIndex" @input="changeTab">
                    <b-tab title="Ground">
                        <b-container id="plan">
                            <h2>Ground Floor</h2>

                            <div id="houseplan" style="position:relative; width:100%; height:70em;">
                                <object ref='houseSVG' id="floorplan" data='./common/images/greenembrace.svg' type='image/svg+xml'></object>
                            </div>
                        </b-container>
                    </b-tab>

I'm loading the SVG bucause it's too large in terms of maintenance to be included in the HTML.
at the bottom of the HTML i've got:


    <!-- These MUST be in the right order. -->
    <script src="../uibuilder/vendor/socket.io/socket.io.js"></script>
    <script src="./uibuilderfe.min.js"></script>
    <!-- === Vendor Libraries - Load in the right order === -->
    <script src="https://cdn.jsdelivr.net/npm/lodash@4/lodash.min.js"></script>
    <script src="../uibuilder/vendor/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/babel-polyfill@latest/dist/polyfill.min.js"></script>
    <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js"></script>
    <!-- <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.min.js"></script> -->
    <!-- === Custom code goes in here === -->
    <script src="./index.js"></script>

    <script type="text/javascript">
        window.addEventListener("load", function() {
            let svgObject = document.getElementById('floorplan').contentDocument;
            let svg = svgObject.getElementById('svg8');
            let elements = svg.getElementsByTagName('circle');
            console.log(elements);
            l = elements.length;
            for (i = 0; i < l; i++) {
                elements[i].style.cursor = "pointer";
                elements[i].setAttributeNS('uibuilber', 'v-on:click', "light");

            }
        });
    </script>

</body>

I'm turning various points (light locations) ON as hot spots for the mouse (this works fine) and also injecting the VUE 'v-on:click... ' into the attribute settings of the SVG elements. It ends up in the code but is not responsive to clicking, I'm thinking it's done to late for VUE to know it's there.

Any pointers, I'm sorry it's OT

Why do you have that last section of JS tacked on as a separate script?

I think you need to put that into the mounted function inside your Vue app so that the Vue part is already active AND the svg file has been loaded before you try to add the event listener?

Thanks Julian, Something come up I'll get back to you on this.

@All, Ok, I tested the suggestions and they work. Thank you again!

@UnborN Started watching the ninja tuts (they are great!), but got distracted building out the floor plan. It's slow going.

I'm now trying to figure out how to change the colour of a bootstrap button (dynamically and individually per button) as I am using them as UI clickable objects for each LED strip.

There isn't an out of the box answer, but I'm sure it will look easy when I figure it out!

Hmmm... maybe I picked the wrong component.

The good news is that I now have prototyped bulbs on my floor plan that reflect reality and I can also select individual bulbs and change their brightness values. If I make changes to lights external to the webpage, the brightness values update to reflect reality, so it's pretty much a working model.

In the immediate, I now need to get the following working:

  1. Change colour of individual buttons (or maybe use a different component) to get them to reflect the colours of the RGBW LED stirips
  2. Add a colour picker to allow colour changes to RGBW LED strips

I tried to implement this:

<div id="hslflat"></div>
<script>
    $("#hslflat").ColorPickerSliders({
        color: "rgb(36, 170, 242)",
        flat: true,
        order: {
            hsl: 1,
            cie: 2,
            preview: 3
        }
    });
</script>

but it's getting too late now to figure it out. I like the idea of a slide more than then HSV flat, but in the end either could work

I think i'll go back to the tutorials for a bit :slight_smile:

Making progress with the basics:

<input type="color" name="ColorPicker" >

EDIT: In the end, everything is very simple. It just takes a long time for me to figure it out. Doh!

1 Like

did you manage to get your event handler working? I would be interested if you did, i cannot get this to work.

I have event handling working for my slider. I can change the brightness of a selected light on my floorplan. Both the slider and brightness value next to my bulb report correctly if I change the brightness from outside of the floor plan i.e. directly form another input into my HA system.

I'll post the code now:

In my HTML file:

        <template>
            <div style="position:relative; width:200px; top:100px; left:100px;">
                <label for="range-10">Circuit: {{ input_circuit }} </label>
                <b-form-input lazy v-on:change="sliderChange(input_brigthness)" id="range-10" v-model="input_brigthness" type="range" min="0" max="100"></b-form-input>
                <div class="mt-2">Brightness: {{ input_brigthness }}</div>
            </div>
        </template>

in my JS file under data I have defined the data variable:

var app1 = new Vue({
    el: '#app',
    data: {

        isonavmain1p:false,
        isonavspots:false,
        isonloungelights:false,

        value_avmain1p:"",
        value_avspots:"",
        value_loungelights:"",

        input_circuit:"nothing selected",
        input_brigthness:0,

In my JS file under methods I have created this function (method)

        // Called if slider value has been changed
        sliderChange: function(input_brigthness)  {
        console.log(input_brigthness);  

        // Send to Node Red //
        uibuilder.send({
            'topic': this.input_circuit,
            'payload': Number(input_brigthness),
        })
        }, // -- End of  -- //

There is a little bit more I had to do around the edges to get this to work i.e. add the light noded to my canvas and connected it to the cache node which connects to uibuilder and also have recipient light node on the output of the uibuilder node to send the brightness updates to my HA system:


What I'm stuck on now is getting the selected colour from my colour picker to pass through to a function (method), so I can change a light circuits colour .... I'm watching tutorials and scouring the web to figure this out.....

I'm going a bit bonkers with the colour picker. Every snippet I try doesn't work e.g. from this site: https://mdbootstrap.com/plugins/jquery/color-picker/

I can never see the colour picker on my webpage, but if I enter this code I can see the colour picker:


        <template>
            <div style="position:relative; width:100px; top:150px; left:100px;">
                <input  @change="colourChange(color)"  id="cp1" type="color"  ></input>
            </div>
        </template>

However I can't seem to get it to return the selected colour....

Proper school-boy error. I didn't define my "input_colour" variable correctly!!!!
Now it works :flushed:

Very nice work Alex ..

Regarding the colorpicker ... bootstrap-vue has one :wink: .. so try to keep to bootstrap-vue that is already included with uibuilder (if you can) instead of looking for other components

i read your posts above and its looking good ... all the best

ps. maybe you can use a switch node after your uibuilder node to switch messages based on their topic .. to route msgs to the correct light, device based on topic

That looks different to the one that I am using.I'll check it out tomorrow/kater.

Thanks!