From 2a70f7b64b8f1a960fb5e3bfcf5eef96c3a037a8 Mon Sep 17 00:00:00 2001 From: Tobias Sachs Date: Sun, 29 May 2016 17:22:50 +0200 Subject: [PATCH 1/2] Make ia7 floorplan setup interactive web/ia7/include/javascript.js: * If you append '&show_pos' to the flooplan URL you it enables drag&drop item positioning: grab fp items with the mouse and drop them where you would like to have tem positioned. perl code do do the positioning is generated below the fp. Copy and paste this code into your favourite mh code file. For me this is 'zzzzzzz_fp_positions.pl', the weird name makes sure to load this file last and all the items do exist. * use the actual display width of fp image is used as the base for resizing (instead of $(window).width() to make the floorplan work on bigger screens too. For those the the floorplan image is smaller than the windows width) * scale the item icons proportional to the original size of the fp background image. This means when you create your background image you should choose the image size it in a way that the XXX_48.png variants of the icons fit well into it. * coordinates of fp items are now the center of the items icon and not the top left corner. lib/json_server.pl: * add querry to get a list of available iconsets --- lib/json_server.pl | 8 + web/ia7/include/javascript.js | 759 +++++++++++++++++++++++++--------- 2 files changed, 571 insertions(+), 196 deletions(-) diff --git a/lib/json_server.pl b/lib/json_server.pl index 3857bbfe9..8dc59fd71 100644 --- a/lib/json_server.pl +++ b/lib/json_server.pl @@ -626,6 +626,14 @@ sub json_get { } } + if ( $path[0] eq 'fp_icon_sets' ){ + my $p = "../web/ia7/graphics/*default_".$args{px}[0].".png"; + my @icons = glob($p); + s/^..\/web// for @icons; + $json_data{'icon_sets'} = []; + push( @{ $json_data{'fp_icon_sets'} }, @icons); + } + # List speak phrases if ( $path[0] eq 'print_speaklog' || $path[0] eq '' ) { my ( @log, @tmp ); diff --git a/web/ia7/include/javascript.js b/web/ia7/include/javascript.js index e481e6172..0adb8713a 100644 --- a/web/ia7/include/javascript.js +++ b/web/ia7/include/javascript.js @@ -597,7 +597,7 @@ var loadList = function() { // This is not an entity, likely a value of the root obj continue; } - if (json_store.objects[entity].hidden != undefined){ + if (json_store.objects[entity].hidden !== undefined){ // This is an entity with the hidden property, so skip it continue; } @@ -733,7 +733,8 @@ var loadList = function() { for (var i = 0; i < json_store.objects[entity].states.length; i++){ if (filterSubstate(json_store.objects[entity].states[i]) == 1) continue; possible_states++; - if (json_store.objects[entity].states[i] !== json_store.objects[entity].state) new_state = json_store.objects[entity].states[i] + if (json_store.objects[entity].states[i] !== json_store.objects[entity].state) new_state = json_store.objects[entity].states[i]; + } if ((possible_states > 2) || (new_state == "")) alert("Check configuration of "+entity+". "+possible_states+" states detected for direct control object. State is "+new_state); url= '/SET;none?select_item='+entity+'&select_state='+new_state; @@ -1614,197 +1615,563 @@ var graph_rrd = function(start,group,time) { }); }; -var floorplan = function(group,time) { - var URLHash = URLToHash(); - var baseimg_width; - if (typeof time === 'undefined'){ - $('#list_content').html("
"); - $('#floorplan').append("
"); - time = 0; - $('#graphic').prepend('
'); - baseimg_width = $(window).width(); - if (baseimg_width > 990) baseimg_width = 800; - $('#fp_graphic').attr("width",baseimg_width+"px"); - } - - if (updateSocket !== undefined && updateSocket.readyState != 4){ - // Only allow one update thread to run at once - updateSocket.abort(); - } - //resize window if changed - window.onresize = function(){ - baseimg_width = $(window).width(); - if (baseimg_width > 990) baseimg_width = 800; - $('#fp_graphic').attr("width",baseimg_width+"px"); - // update the location of all the objects... - $(".floorplan_item").each(function(index) { - var classstr = $(this).attr("class"); - var coords = classstr.split(/coords=/)[1]; - var fp_location = coords.split(/x/); - var location = get_fp_location(fp_location,0); - $(this).attr("style",location); - //iphone scale - var baseimg_width = $(window).width(); - if (baseimg_width < 500) { - $(this).attr('src',$(this).attr('src').replace('48.png','32.png')) - } else { - $(this).attr('src',$(this).attr('src').replace('32.png','48.png')) - } +/////////////// Floorplan ////////////////////////////////////////////////////////// +var fp_display_width=0; // updated by fp_resize_floorplan_image +var fp_display_height=0; // updated by fp_resize_floorplan_image +var fp_scale = 100; // updated by fp_reposition_entities +var fp_grabbed_entity = null; // store item for drag & drop +var fp_icon_select_item_id = null; // store item id on right click for icon set selection - }); - } +var noDragDrop = function() { + return false; +}; - var path_str = "/objects"; - var arg_str = "parents="+group+"&fields=fp_location,state,states,state_log,fp_icons,fp_icon_set,img,link,label,type&long_poll=true&time="+time; - - updateSocket = $.ajax({ - type: "GET", - url: "/LONG_POLL?json('GET','"+path_str+"','"+arg_str+"')", - dataType: "json", - success: function( json, statusText, jqXHR ) { - var requestTime = time; - if (jqXHR.status == 200) { - JSONStore(json); - for (var entity in json.data) { - for (var i=0 ; i < json.data[entity].fp_location.length-1; i=i+2){ //allow for multiple graphics - var location = get_fp_location(json.data[entity].fp_location,i); - var popover = 0; - if ((json.data[entity].type == "FPCamera_Item") || - (json_store.ia7_config.prefs.fp_state_popovers == "yes")) popover = 1 - var popover_html = ""; - if (popover) popover_html = 'data-toggle="popover" data-trigger="focus" tabindex="0"' - - var image = get_fp_image(json.data[entity]); - if ($('#entity_'+entity+'_'+i).length > 0) { - $('#entity_'+entity+'_'+i).attr('src',"/ia7/graphics/"+image); - } else { - $('#graphic').append(''); - } - // create unique popovers for Camera items - if (json.data[entity].type == "FPCamera_Item") { - var name = entity; - if (json.data[entity].label !== undefined) name = json.data[entity].label - var a_start = ""; - var a_end = ""; - if (json.data[entity].link !== undefined) { - a_start = '' - a_end = ''; - } - $('[data-toggle="popover"]').popover({ - placement : 'auto bottom', //placement of the popover. also can use top, bottom, left or right - title : name, - html: 'true', //needed to show html of course - content : '
'+a_start+''+a_end+'
' - }); - } else { - if (popover) { - - $('[data-toggle="popover"]').popover({ - placement : 'auto bottom', //placement of the popover. also can use top, bottom, left or right - title : function() { - var fp_entity = $(this).attr("id").match(/entity_(.*)_\d+$/)[1]; //strip out entity_ and ending _X ... item names can have underscores in them. - var name = fp_entity; - if (json_store.objects[fp_entity].label !== undefined) name = json_store.objects[fp_entity].label; - return name+" - "+json_store.objects[fp_entity].state; - }, - html: 'true', //needed to show html of course - content : function() { - var fp_entity = $(this).attr("id").match(/entity_(.*)_\d+$/)[1]; //strip out entity_ and ending _X ... item names can have underscores in them. - var po_states = json_store.objects[fp_entity].states; - var html = '
'; - // HP need to have at least 2 states to be a controllable object... - if (po_states.length > 1) { - html = '
'; - var buttons = 0; - var stategrp = 0; - for (var i = 0; i < po_states.length; i++){ - if (filterSubstate(po_states[i]) == 1) { - continue - } else { - buttons++ - //} - if (buttons > 2) { - stategrp++; - html += "
"; - buttons = 1; - } - - var color = getButtonColor(po_states[i]) -//TODO disabled override - var disabled = "" - if (po_states[i] == json_store.objects[fp_entity].state) { - disabled = "disabled"; - } - html += "
" - return html - } +var fp_getOrCreateIcon = function (json, entity, i, coords, show_pos){ + var popover = 0; + if ((json.data[entity].type === "FPCamera_Item") || (json_store.ia7_config.prefs.fp_state_popovers === "yes")) + popover = 1; + + var popover_html = ""; + if (popover) + popover_html = 'data-toggle="popover" data-trigger="focus" tabindex="0"'; + + var entityId = 'entity_'+entity+'_'+i; + if ($('#' + entityId).length === 0) { + var html = '' + // this span somehow magically make resizing the icons work + ''+ + ''; + if (coords !== ""){ + $('#graphic').append(html); + } + else { + $('#fp_positionless_items').append(html); + } + } + var E = $('#'+entityId); + E.bind("dragstart", noDragDrop); + var image = get_fp_image(json.data[entity]); + E.attr('src',"/ia7/graphics/"+image); + if (show_pos) + E.css("border","1px solid black"); + + return E; +}; - }); - } else { - $('#entity_'+entity+'_'+i).click( function () { - var fp_entity = $(this).attr("id").match(/entity_(.*)_\d+$/)[1]; //strip out entity_ and ending _X ... item names can have underscores in them. - create_state_modal(fp_entity); - }); - } - $('#entity_'+entity+'_'+i).mayTriggerLongClicks().on( 'longClick', function() { - var fp_entity = $(this).attr("id").match(/entity_(.*)_\d+$/)[1]; //strip out entity_ and ending _X ... item names can have underscores in them. - create_state_modal(fp_entity); - }); - } - } - } - requestTime = json.meta.time; - } - if (jqXHR.status == 200 || jqXHR.status == 204) { - //Call update again, if page is still here - //KRK best way to handle this is likely to check the URL hash - if ($('#floorplan').length !== 0){ - //If the floorplan page is still active request more data - floorplan(group,requestTime); - } - } - } - }); +var fp_resize_floorplan_image = function(){ + var floor_width = $("#fp_graphic").width(); + $("#fp_graphic").attr("width", "1px"); + + fp_display_width = $("#graphic").width(); + console.log("FP: resize "+ floor_width + " => " + fp_display_width); + $('#fp_graphic').attr("width",fp_display_width+"px"); + fp_display_height = $("#fp_graphic").height(); }; -//have to figure out height, and the jumps at 991 and 1200 -var get_fp_location = function(item,index) { - var baseimg_width = $(window).width(); - //var baseimg_height = $(window).height() - 60; - var baseimg_height = $('#fp_graphic').height(); - var tmargin = 0; - var lmargin = 0; - if (baseimg_width > 990) { - lmargin = (baseimg_width - 980) / 2; - tmargin = 20; - if (baseimg_width > 1200) { - lmargin = (baseimg_width - 1180) / 2; - } - baseimg_width = 800; +var fp_reposition_entities = function(){ + var t0 = performance.now(); + var offset = $("#fp_graphic").offset(); + var width = fp_display_width; + var hight = fp_display_height; + var onePercentWidthInPx = width/100; + var onePercentHeightInPx = hight/100; + var fp_get_offset_from_location = function(item) { + var y = item[0]; + var x = item[1]; + var newy = offset.top + y * onePercentHeightInPx; + var newx = offset.left + x * onePercentWidthInPx; + return { + "top": newy, + "left": newx + }; + }; + var nwidth = $("#fp_graphic").get(0).naturalWidth; + fp_scale = Math.round( width/nwidth * 100); + + // update the location of all the objects... + $(".floorplan_item").each(function(index) { + var classstr = $(this).attr("class"); + var coords = classstr.split(/coords=/)[1]; + $(this).width(fp_scale + "%"); + + if (coords.length === 0){ + return; + } + var fp_location = coords.split(/x/); + var fp_offset = fp_get_offset_from_location(fp_location); + + // this seems to make the repositioning slow + // ~ 300+ms on my nexus7 firefox-beta vs <100ms with this code commented out + // var baseimg_width = $("#fp_graphic").width(); + // if (baseimg_width < 500) { + // $(this).attr('src',$(this).attr('src').replace('48.png','32.png')); + // } else { + // $(this).attr('src',$(this).attr('src').replace('32.png','48.png')); + // } + + var adjust = $(this).width()/2; + var fp_off_center = { + "top": fp_offset.top - adjust, + "left": fp_offset.left - adjust + }; + fp_set_pos($(this).attr('id'), fp_off_center); + }); - } - var location = "position: absolute; "; - var top = parseInt((baseimg_height * item[index] / 100)+tmargin); - var left = parseInt((baseimg_width * item[index+1] / 100)+lmargin); - location += "top: "+top+"px;"; - location += "left: "+left+"px"; - return location; -} + $('.icon_select img').each(function(){ + $(this).width(fp_scale + "%"); + }); + var t1 = performance.now(); + console.log("FP: reposition and scale: " +Math.round(t1 - t0) + "ms "); +}; + +var fp_set_pos = function(id, offset){ + var item = $('#' + id); + // do not move the span, this make the popup to narrow somehow + // item.closest("span").offset(offset); + item.offset(offset); +}; + +var fp_is_point_on_fp = function (p){ + var offset = $("#fp_graphic").offset(); + var width = $("#fp_graphic").width(); + var height = $("#fp_graphic").height(); + if (p.top < offset.top) + return false; + if (p.top > offset.top + height) + return false; + if (p.left < offset.left) + return false; + if (p.left > offset.left + width) + return false; + + return true; +}; +var floorplan = function(group,time) { + var URLHash = URLToHash(); + var baseimg_width; + if (typeof time === 'undefined'){ + //var window_width = $(window).width(); + $('#list_content').html("
"); + if (URLHash.show_pos){ + // add elememnts to show current position on floorplan + $('#floorplan').append("
    " + + "
  1. grab icon and drop it on apropriate position on the flooplan
  2. " + + "
  3. right click item to select another iconset
  4. "+ + "
  5. to remove the item from the perl code drop it besides the fp background image
  6. "+ + "
  7. repeat 1/2/3 for all items you'd like to change
  8. "+ + "
  9. copy the generated perl code into your usercode file
  10. " + + "
" + + "
y,x = " + + "
"); + } + $('#floorplan').append("
"); + time = 0; + $('#graphic').prepend('
'); + if (URLHash.show_pos){ + $('#fp_graphic').css("border","1px solid black"); + $('#list_content').append("
"); + $('#list_content').append("
");
+        }
+        $('#fp_graphic').bind("load", function () {
+            console.log("FP: background loaded.");
+            fp_resize_floorplan_image();
+            floorplan(group, time);
+        });
+        $('#fp_graphic').attr("src", '/ia7/graphics/floorplan-'+group+'.png');
+        return;
+    }
+
+    if (updateSocket !== undefined && updateSocket.readyState !== 4){
+        // Only allow one update thread to run at once
+        updateSocket.abort();
+    }
+
+    if (URLHash.show_pos){
+        // update positon
+
+        $(document).mousemove(function(e){
+            var offset = $("#fp_graphic").offset();
+            var width = $("#fp_graphic").width();
+            var hight = $("#fp_graphic").height();
+            var  l = e.pageX - offset.left;
+            var  t = e.pageY - offset.top;
+
+            //var pos =   Math.round((t/hight) *100) +"," + Math.round((l/width)*100);
+            var pos =  (t/hight) *100 +"," + (l/width)*100;
+            //console.log("floorplanpos: " + pos );
+            $('#debug_pos').text(pos);
+            if (fp_grabbed_entity !== null){
+                //var itemCenterOffset = Math.round(fp_grabbed_entity.width/2);
+                var itemCenterOffset = fp_grabbed_entity.width/2;
+                var newPos = {
+                    "top": e.pageY - itemCenterOffset,
+                    "left": e.pageX - itemCenterOffset
+                };
+                fp_set_pos(fp_grabbed_entity.id, newPos);
+                //console.log(fp_grabbed_entity.id +" pos: " +newPos.top + " x " + newPos.left);
+                //fp_grabbed_entity.class.replace("coords=.*", "coords="+pos);
+            }
+        });
+
+        $(window).mousedown(function(e){
+            if (e.which === 1 && e.target.id.indexOf("entity_") >= 0){
+                fp_grabbed_entity = e.target;
+                e.stopPropagation();
+                return true;
+            }
+        });
+
+        $(window).mouseup(function(e){
+            if (fp_grabbed_entity === null)
+                return;
+
+            set_set_coordinates_from_offset(fp_grabbed_entity.id);
+            fp_reposition_entities();
+            fp_grabbed_entity = null;
+        });
+
+    }
+
+    var set_set_coordinates_from_offset = function (id)
+    {
+        var E = $('#'+id);
+        var offsetE = E.offset();
+        offsetE.top += E.width()/2;
+        offsetE.left += E.width()/2;
+        var offsetP = $("#fp_graphic").offset();
+        var width = fp_display_width;
+        var hight = fp_display_height;
+        var onePercentWidthInPx = width/100;
+        var onePercentHeightInPx = hight/100;
+
+        var newy =  (offsetE.top - offsetP.top) / onePercentHeightInPx;
+        var newx =  (offsetE.left - offsetP.left) / onePercentWidthInPx;
+        var coords = newy+"x"+newx;
+        var name = id.match(/entity_(.*)_(\d)+$/)[1];
+        var codeLines = $("#fp_pos_perl_code").text().split('\n');
+        var newCode = "";
+        if (fp_is_point_on_fp(offsetE) === false){
+            E.attr("class", "entity="+id+" floorplan_item coords=");
+            E.attr("src", "/ia7/graphics/fp_unknown_info_48.png");
+            for (var i = 0; i< codeLines.length; i++)
+            {
+                var line = codeLines[i];
+                if (line.startsWith("$"+name) === false && line !== "")
+                {
+                    newCode += line + "\n";
+                }
+            }
+        }
+        else{
+            E.attr("class", "entity="+id+" floorplan_item coords="+coords);
+            var coordIdx = id.match(/entity_(.*)_(\d)+$/)[2];
+
+            var itemUpdated = false;
+            for (var i = 0; i< codeLines.length; i++)
+            {
+                var line = codeLines[i];
+                if (line.startsWith("$"+name+"->set_fp_location"))
+                {
+                    var m = line.match(/.*\((.*)\).*/);
+                    oldCoords = m[1].split(",");
+                    oldCoords[+coordIdx] = newy;
+                    oldCoords[+coordIdx+1] = newx;
+                    var newline = "$" + name + "->set_fp_location("+ oldCoords.join(",") + ");\n";
+                    newCode += newline;
+                    itemUpdated = true;
+                }
+                else if (line !== "")
+                {
+                    newCode += line + "\n";
+                }
+            }
+            if (itemUpdated === false)
+            {
+                var newline = "$" + name + "->set_fp_location("+ newy +","+ newx + ");\n";
+                newCode += newline;
+            }
+        }
+        newCode = newCode.split('\n').sort().join('\n');
+        $("#fp_pos_perl_code").text(newCode);
+    };
+
+    // reposition on window size change
+    window.onresize = function(){
+        if ($('#floorplan').length === 0)
+        {
+            window.onresize = null;
+            return;
+        }
+
+        console.log("FP: window resized");
+        fp_resize_floorplan_image();
+        fp_reposition_entities();
+    };
+
+    var path_str = "/objects";
+    var fields = "fields=fp_location,state,states,fp_icons,fp_icon_set,img,link,label,type";
+    if (json_store.ia7_config.prefs.state_log_show === "yes")
+        fields += ",state_log";
+
+    var arg_str = "parents="+group+"&"+fields+"&long_poll=true&time="+time;
+
+    updateSocket = $.ajax({
+        type: "GET",
+        url: "/LONG_POLL?json('GET','"+path_str+"','"+arg_str+"')",
+        dataType: "json",
+        error: function(xhr, textStatus, errorThrown){
+            //   console.log('FP: request failed: "' + textStatus + '" "'+JSON.stringify(errorThrown, undefined,2)+'"');
+        },
+        success: function( json, statusText, jqXHR ) {
+            //  console.log('FP: request succeeded: "' + statusText + '" "'+JSON.stringify(jqXHR, undefined,2)+'"');
+            var requestTime = time;
+            if (jqXHR.status === 200) {
+                var t0 = performance.now();
+                JSONStore(json);
+                for (var entity in json.data) {
+                    if (URLHash.show_pos && requestTime === 0){
+                        perl_pos_coords = "";
+                    }
+                    for (var i=0 ; i < json.data[entity].fp_location.length-1; i=i+2){ //allow for multiple graphics
+                        var popover = 0;
+                        if ((json.data[entity].type === "FPCamera_Item") || (json_store.ia7_config.prefs.fp_state_popovers === "yes"))
+                            popover = 1;
+
+                        if (URLHash.show_pos && requestTime === 0){
+                            if (perl_pos_coords.length !== 0){
+                                perl_pos_coords += ", ";
+                            }
+                            perl_pos_coords += "" + json.data[entity].fp_location[i]+','+json.data[entity].fp_location[i+1];
+                        }
+
+                        var coords= json.data[entity].fp_location[i]+'x'+json.data[entity].fp_location[i+1];
+                        var E = fp_getOrCreateIcon(json, entity, i, coords, URLHash.show_pos);
+
+                        if (URLHash.show_pos === undefined)
+                        {
+                            // create unique popovers for Camera items
+                            if (json.data[entity].type === "FPCamera_Item") {
+                                var name = entity;
+                                if (json.data[entity].label !== undefined)
+                                    name = json.data[entity].label;
+
+                                var a_start = "";
+                                var a_end = "";
+                                if (json.data[entity].link !== undefined) {
+                                    a_start = '';
+                                    a_end = '';
+                                }
+
+                                $('[data-toggle="popover"]').popover({
+                                    placement : 'auto bottom', //placement of the popover. also can use top, bottom, left or right
+                                    title : name,
+                                    html: 'true', //needed to show html of course
+                                    content : '
'+a_start+''+a_end+'
' + }); + } else { + if (popover) { + + $('[data-toggle="popover"]').popover({ + placement : 'auto bottom', //placement of the popover. also can use top, bottom, left or right + title : function() { + var fp_entity = $(this).attr("id").match(/entity_(.*)_\d+$/)[1]; //strip out entity_ and ending _X ... item names can have underscores in them. + var name = fp_entity; + if (json_store.objects[fp_entity].label !== undefined) name = json_store.objects[fp_entity].label; + var ackt = E.offset(); + return name+ " - "+json_store.objects[fp_entity].state; + }, + html: 'true', //needed to show html of course + content : function() { + var fp_entity = $(this).attr("id").match(/entity_(.*)_\d+$/)[1]; //strip out entity_ and ending _X ... item names can have underscores in them. + var po_states = json_store.objects[fp_entity].states; + var html = '
'; + // HP need to have at least 2 states to be a controllable object... + if (po_states.length > 1) { + html = '
'; + var buttons = 0; + var stategrp = 0; + for (var i = 0; i < po_states.length; i++){ + if (filterSubstate(po_states[i]) !== 1) { + buttons++; + if (buttons > 2) { + stategrp++; + html += "
"; + buttons = 1; + } + + var color = getButtonColor(po_states[i]); + //TODO disabled override + var disabled = ""; + if (po_states[i] === json_store.objects[fp_entity].state) { + disabled = "disabled"; + } + html += "
"; + //console.log("html="+html) + } + return html; + } + }); + } else { + E.click( function () { + //var fp_entity = $(this).attr("id").split(/entity_/)[1]; // + var fp_entity = $(this).attr("id").match(/entity_(.*)_\d+$/)[1]; //strip out entity_ and ending _X ... item names can have underscores in them. + //alert("entity="+fp_entity); + create_state_modal(fp_entity); + }); + } + E.mayTriggerLongClicks().on( 'longClick', function() { + var fp_entity = $(this).attr("id").match(/entity_(.*)_\d+$/)[1]; //strip out entity_ and ending _X ... item names can have underscores in them. + create_state_modal(fp_entity); + }); + } + } + } + + if (URLHash.show_pos && requestTime === 0){ + if (perl_pos_coords.length===0) + { + fp_getOrCreateIcon(json, entity, 0, "", URLHash.show_pos); + } + else{ + var oldCode = $('#fp_pos_perl_code').text(); + if (oldCode.length !== 0) + oldCode += "\n"; + + var perl_pos_code = ""; + var iconset = json.data[entity].fp_icon_set; + if (iconset !== undefined){ + perl_pos_code += '$' + entity + '->set_fp_icon_set("'; + perl_pos_code += iconset + '");\n'; + } + perl_pos_code += "$" + entity + "->set_fp_location("; + perl_pos_code += perl_pos_coords + ");"; + perl_pos_code = oldCode + perl_pos_code; + perl_pos_code = perl_pos_code.split('\n').sort().join('\n'); + $('#fp_pos_perl_code').text(perl_pos_code); + } + } + } + fp_reposition_entities(); + if (requestTime === 0 && URLHash.show_pos){ + $('#list_content').append("

 

"); + $.ajax({ + type: "GET", + url: "/LONG_POLL?json('GET','fp_icon_sets','px=48')", + dataType: "json", + error: function(xhr, textStatus, errorThrown){ + console.log('FP: request iconsets failed: "' + textStatus + '" "'+JSON.stringify(errorThrown, undefined,2)+'"'); + }, + success: function( json, statusText, jqXHR ) { + console.log('FP: request iconsets: "' + statusText + '" "'+JSON.stringify(jqXHR, undefined,2)+'"'); + var requestTime = time; + if (jqXHR.status === 200) { + var iconlist = '\n"; + $('#list_content').append(iconlist); + + // Trigger action when the contexmenu is about to be shown + $(".floorplan_item").bind("contextmenu", function (event) { + + event.preventDefault(); + + fp_icon_select_item_id = $(this).attr('id'); + $(".icon_select").finish().toggle(100); + $(".icon_select").offset({ + top: event.pageY, + left: event.pageX + }); + }); + + + // If the document is clicked somewhere + $(document).bind("mousedown", function (e) { + if ($(e.target).parents(".icon_select").length === 0) { + $(".icon_select").hide(100); + fp_icon_select_item_id = null; + } + }); + + + // If the menu element is clicked + $(".icon_select img").click(function(){ + var img = $(this).attr("src"); + $('#'+fp_icon_select_item_id).attr('src', img); + var name = fp_icon_select_item_id.match(/entity_(.*)_(\d)+$/)[1]; + + var codeLines = $("#fp_pos_perl_code").text().split('\n'); + var newCode = ""; + + var icon_set_name = img.match(/.*fp_(.*)_(.*)_48.png/)[1]; + var itemUpdated = false; + for (var i = 0; i< codeLines.length; i++) + { + var line = codeLines[i]; + if (line.startsWith("$"+name+"->set_fp_icon_set")) + { + var newline = "$" + name + '->set_fp_icon_set("'+ icon_set_name+ '");\n'; + newCode += newline; + itemUpdated = true; + } + else if (line !== "") + { + newCode += line + "\n"; + } + } + if (itemUpdated === false) + { + var newline = "$" + name + '->set_fp_icon_set("'+ icon_set_name +'");\n'; + newCode += newline; + } + newCode = newCode.split('\n').sort().join('\n'); + $("#fp_pos_perl_code").text(newCode); + $(".icon_select").hide(100); + fp_icon_select_item_id = null; + }); + } + } + }); + } + requestTime = json.meta.time; + var t1 = performance.now(); + console.log("FP: long poll " +Math.round(t1 - t0) + "ms"); + } + if (jqXHR.status === 200 || jqXHR.status === 204) { + //Call update again, if page is still here + //KRK best way to handle this is likely to check the URL hash + if ($('#floorplan').length !== 0){ + //If the floorplan page is still active request more data + // and we are not editing the fp + if (URLHash.show_pos === undefined) + floorplan(group,requestTime); + } + } + } + }); +}; var get_fp_image = function(item,size,orientation) { var image_name; - var image_color = getButtonColor(item.state) + var image_color = getButtonColor(item.state); var baseimg_width = $(window).width(); - var image_size = "48" - if (baseimg_width < 500) image_size = "32" // iphone scaling + var image_size = "48"; + // if (baseimg_width < 500) image_size = "32" // iphone scaling + //kvar image_size = "32" if (item.fp_icons !== undefined) { if (item.fp_icons[item.state] !== undefined) return item.fp_icons[item.state]; } @@ -1812,35 +2179,35 @@ var get_fp_image = function(item,size,orientation) { return "fp_"+item.fp_icon_set+"_"+image_color+"_"+image_size+".png"; } // if item.fp_icons.return item.fp_icons[state]; - if(item.type == "Light_Item" || item.type == "Fan_Light" || - item.type == "Insteon_Device" || item.type == "UPB_Link" || - item.type == "Insteon::SwitchLinc" || item.type == "Insteon::SwitchLincRelay" || - item.type == "Insteon::KeyPadLinc" || - item.type == "EIB_Item" || item.type == "EIB1_Item" || - item.type == "EIB2_Item" || item.type == "EIO_Item" || - item.type == "UIO_Item" || item.type == "X10_Item" || - item.type == "xPL_Plugwise" || item.type == "X10_Appliance") { + if(item.type === "Light_Item" || item.type === "Fan_Light" || + item.type === "Insteon_Device" || item.type === "UPB_Link" || + item.type === "Insteon::SwitchLinc" || item.type === "Insteon::SwitchLincRelay" || + item.type === "Insteon::KeyPadLinc" || + item.type === "EIB_Item" || item.type === "EIB1_Item" || + item.type === "EIB2_Item" || item.type === "EIO_Item" || + item.type === "UIO_Item" || item.type === "X10_Item" || + item.type === "xPL_Plugwise" || item.type === "X10_Appliance") { return "fp_light_"+image_color+"_"+image_size+".png"; } - if(item.type == "Motion_Item" || item.type == "X10_Sensor" || - item.type == "Insteon::MotionSensor" ) { + if(item.type === "Motion_Item" || item.type === "X10_Sensor" || + item.type === "Insteon::MotionSensor" ) { return "fp_motion_"+image_color+"_"+image_size+".png"; } - if(item.type == "Door_Item" || item.type == "Insteon::IOLinc_door") { + if(item.type === "Door_Item" || item.type === "Insteon::IOLinc_door") { return "fp_door_"+image_color+"_"+image_size+".png"; } - if(item.type == "FPCamera_Item" ) { + if(item.type === "FPCamera_Item" ) { return "fp_camera_default_"+image_size+".png"; } return "fp_unknown_info_"+image_size+".png"; -} +}; var create_img_popover = function(entity) { } From 46de08654c0026c47d980a72f2325edfd59b5561 Mon Sep 17 00:00:00 2001 From: Tobias Sachs Date: Sun, 29 May 2016 19:10:44 +0200 Subject: [PATCH 2/2] do not access ia7_config.state_colors if it was not defined in user config --- web/ia7/include/javascript.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/ia7/include/javascript.js b/web/ia7/include/javascript.js index 0adb8713a..c9d31e840 100644 --- a/web/ia7/include/javascript.js +++ b/web/ia7/include/javascript.js @@ -771,7 +771,8 @@ var getButtonColor = function (state) { } else if (state == "cooling" || state == "cool") { color = "info"; } - if (json_store.ia7_config.state_colors[state] !== undefined) { + if (json_store.ia7_config.state_colors !== undefined + && json_store.ia7_config.state_colors[state] !== undefined) { color = "purple"; if (json_store.ia7_config.state_colors[state] == "green") { color = "success";