From 3cfb6aa02516135fb174ab1b30620f2007924663 Mon Sep 17 00:00:00 2001
From: 13693261870 <252740454@qq.com>
Date: 星期二, 03 九月 2024 10:36:53 +0800
Subject: [PATCH] 添加2个接口

---
 TEWin/FrmWin.cs                                            |    9 
 TEWin/Resources/DisplayByAttribute/ToolIcon.png            |    0 
 TEWin/Resources/DisplayByAttribute/Lang.js                 |   28 
 TEWin/Resources/DisplayByAttribute/jscolor.js              | 1855 ++++++++++++++++++++++++++++++++++++++++++++
 TEWin/TEWin.csproj                                         |   21 
 TEWin/FrmTool.cs                                           |    2 
 TEWin/Resources/DisplayByAttribute/1033/Lang.js            |   28 
 TEWin/Resources/DisplayByAttribute/DisplayByAttribute.html |  422 ++++++++++
 TEWin/Resources/DisplayByAttribute/2052/Lang.js            |   28 
 TEWin/Resources/DisplayByAttribute/Launch.html             |  110 ++
 10 files changed, 2,502 insertions(+), 1 deletions(-)

diff --git a/TEWin/FrmTool.cs b/TEWin/FrmTool.cs
index 39244bc..3e67beb 100644
--- a/TEWin/FrmTool.cs
+++ b/TEWin/FrmTool.cs
@@ -17,7 +17,7 @@
             "褰卞儚鏁版嵁", "鍦板舰鏁版嵁", "妯″瀷鏁版嵁(osgb)", "妯″瀷鏁版嵁(obj)", "缂栬緫鏁版嵁", "鐐归噺绠�", 
             "鍧″悜鍒嗘瀽", "绾块噺绠�", "闈㈤噺绠�", "浣撻噺绠�", "瑙掗噺绠�", "绌洪棿缁熻", "绌洪棿鍒嗘瀽", 
             "鍓栭潰鍒嗘瀽", "鍧″害鍒嗘瀽", "绛夊�肩嚎", "鍓栧垏鍒嗘瀽", "鍦扮悊鍦烘櫙浜у搧缁勮", "浼犵粺4D浜у搧娲剧敓", 
-            "鎵撳紑fly", "鍔犺浇shp", "璇诲彇shp" };
+            "鎵撳紑fly", "鍔犺浇shp", "璇诲彇shp", "鎸夌収灞炴�ф樉绀�", "鎸夌収灞炴�ц缃鑹�" };
 
         public FrmTool(FrmWin win)
         {
diff --git a/TEWin/FrmWin.cs b/TEWin/FrmWin.cs
index 2a29dc5..dc5d562 100644
--- a/TEWin/FrmWin.cs
+++ b/TEWin/FrmWin.cs
@@ -208,6 +208,10 @@
                     LoadShp(); break;
                 case 0xd9: // 璇诲彇shp
                     ReadShp(); break;
+                case 0xda: // 鎸夌収灞炴�ф樉绀�
+                    DisplayByAttribute(0, "鎸夌収灞炴�ф樉绀�"); break;
+                case 0xdb: // 鎸夌収灞炴�ц缃鑹�
+                    DisplayByAttribute(1, "鎸夌収灞炴�ц缃鑹�"); break;
             }
         }
 
@@ -585,6 +589,11 @@
             RunExe(GetAbsolutePath("osgblabPath"), null, false);
         }
 
+        private void DisplayByAttribute(int type, String name)
+        {
+            this.ShowHtml(name, mainUrl + @"\Resources\DisplayByAttribute\DisplayByAttribute.html?Type=" + type + "&lang=2052", 20, 20, 365, 355);
+        }
+
         #region 鍔犺浇shp + 璇诲彇shp
         private void LoadShp()
         {
diff --git a/TEWin/Resources/DisplayByAttribute/1033/Lang.js b/TEWin/Resources/DisplayByAttribute/1033/Lang.js
new file mode 100644
index 0000000..6f408bf
--- /dev/null
+++ b/TEWin/Resources/DisplayByAttribute/1033/Lang.js
@@ -0,0 +1,28 @@
+锘縎GLang.lang = $.extend(SGLang.lang, {
+    ToolTitle: "SkylineGlobe - Skyline Software Systems, Inc.",
+    Text_DisplayByAttributeCaption: "Display By Attribute",
+    Text_ColorizeByAttributeCaption: "Colorize By Attribute",
+    help: "Help",
+    Text_DisplayByAttrBtn: "Display by<br> Attribute",
+    Text_ColorizeByAttrBtn: "Colorize by<br> Attribute",
+    Text_Layer: "Layer:",
+    Text_Attribute: "Attribute:",
+    Text_3DMLNotFound: "Please select a 3D Mesh layer from the Project Tree and run this tool again. ",
+    Text_ErrorWhileExit: "Unexpected error occurred while trying to exit the Display By Attribute tool. ",
+    Text_TooManyAttributes: "There are too many unique values for this <b>Attribute</b> field. Select a different <b>Attribute</b>. ",
+    Text_SetAll: "Set all to:",
+    Text_All: "All",
+    Text_Set: "Set",
+    Text_Empty: "-EMPTY-",
+    Text_Reshuffle: "Reshuffle",
+    Text_Opacity: "Opacity:",
+    Text_Default: "Default Color",
+    Text_SGSTooOld: "Operation is only supported by SkylineGlobe Server v7.2 or higher. ",
+    Text_Save: "Save",
+    Text_SaveMessage: "Setting was saved successfully.",
+    Text_AlertCaption: "TerraExplorer",
+
+
+    Text999: ""
+});
+
diff --git a/TEWin/Resources/DisplayByAttribute/2052/Lang.js b/TEWin/Resources/DisplayByAttribute/2052/Lang.js
new file mode 100644
index 0000000..f9ca9fd
--- /dev/null
+++ b/TEWin/Resources/DisplayByAttribute/2052/Lang.js
@@ -0,0 +1,28 @@
+锘縎GLang.lang = $.extend(SGLang.lang, {
+    ToolTitle: "SmartEarth - 娉扮憺鏁板垱绉戞妧锛堝寳浜級鏈夐檺鍏徃",
+    Text_DisplayByAttributeCaption: "鎸夌収灞炴�ф樉绀�",
+    Text_ColorizeByAttributeCaption: "鎸夌収灞炴�ц缃鑹�",
+    help: "甯姪",
+    Text_DisplayByAttrBtn: "鎸夌収<br> 灞炴�ф樉绀�",
+    Text_ColorizeByAttrBtn: "鎸夌収<br> 灞炴�ц缃鑹�",
+    Text_Layer: "鍥惧眰:",
+    Text_Attribute: "灞炴��:",
+    Text_3DMLNotFound: "璇峰湪宸ョ▼鏍戜腑閫夋嫨3DML鍥惧眰骞堕噸鏂拌繍琛屾宸ュ叿. ",
+    Text_ErrorWhileExit: "閫�鍑烘寜灞炴�ф樉绀哄伐鍏锋椂鍙戠敓鎰忓閿欒. ",
+    Text_TooManyAttributes: "<b>灞炴��</b> 瀛楁涓湁澶鍞竴鍊�. 璇烽�夋嫨涓嶅悓鐨� <b>灞炴��</b>. ",
+    Text_SetAll: "璁剧疆鎵�鏈�:",
+    Text_All: "鎵�鏈�",
+    Text_Set: "璁剧疆",
+    Text_Empty: "-绌�-",
+    Text_Reshuffle: "閲嶆柊閰嶇疆",
+    Text_Opacity: "閫忔槑搴�:",
+    Text_Default: "榛樿棰滆壊",
+    Text_SGSTooOld: "鍙敮鎸丼martEarth Server v7.2鎴栨洿楂樼増鏈�. ",
+    Text_Save: "淇濆瓨",
+    Text_SaveMessage: "璁剧疆淇濆瓨鎴愬姛.",
+    Text_AlertCaption: "路",
+
+
+    Text999: ""
+});
+
diff --git a/TEWin/Resources/DisplayByAttribute/DisplayByAttribute.html b/TEWin/Resources/DisplayByAttribute/DisplayByAttribute.html
new file mode 100644
index 0000000..0105399
--- /dev/null
+++ b/TEWin/Resources/DisplayByAttribute/DisplayByAttribute.html
@@ -0,0 +1,422 @@
+锘�<html>
+    <head>
+<meta http-equiv="X-UA-Compatible" content="IE=9" />
+        <title>Image Comparison Tool</title>
+<link rel="StyleSheet" href="../Style.css" type="text/css">
+<style>
+.TintColorButton {border-color: black;border-width:1px;  height:12px;width:15px;margin-right:5px;margin-left:1px;margin-bottom: 4px;}
+</style> 
+</head>
+<body style="border: 0px;overflow:hidden; margin:0;" id="Body"  class="hideUntillTranslated" onload="Init()" onunload="exitTool();">
+
+    <table id="topPanel" cellpadding ="3px" style="background-color: #151515" cellspacing = "0" border="0" width="100%"  class="s8w">
+            <tr valign="top">
+            <!-- <td rowspan=2>
+                <img src="ToolIcon.png"  style="margin-left: 5px; margin-right: 10px; ">
+            </td> -->
+            <td style="width:60px;" align="center">
+                    <span class="i18n s8w" style="margin-right: 0px;">Text_Layer</span>
+            </td>
+            <td style="width:calc(100%-60px);" align="left">
+                    <select id="LayersListID" class="SelectDark"  style="width:100%; " onchange="FindAttributes();">
+                    </select>
+             </td>
+        <tr>
+                <td style="width:60px;" align="center">
+                        <span class="i18n s8w"  style="margin-right: 0px;">Text_Attribute</span>
+                </td>
+                <td style="width:calc(100%-60px);" align="left">
+                        <select id="AttributesListID" class="SelectDark"   style="width:100%; " onchange="ShowAttributeValues(false);">
+                        </select>
+                 </td>
+            </tr>
+    </table>
+    <!-- This is the header of the Display by Attribute result. Added dynamically when needed  -->
+    <div id="visibilityHeader"  style="display:none; visibility: hidden;"> 
+        <div  class="s8"  style="background-color:#DFDEDF; padding-bottom:3px;padding-top: 3px;margin-bottom: 3px;"> 
+                    <input type="checkbox"  checked="checked" value="All" onchange="CheckAll(this);" />
+                <span class="i18n">Text_All</span><br>
+        </div>
+    </div>
+
+    <!-- This is the header of the Colorize by Attribute result. Added dynamically when needed  -->
+    <div id="colorizeHeader" class="s8"  style="display:none; visibility: hidden;"> 
+       <div  class="s8"  style="background-color:#DFDEDF; padding-bottom:3px;padding-top: 3px;margin-bottom: 3px;"> 
+            <span class="i18n">Text_SetAll</span>
+            <input id="AllColors" class="jscolor s6 TintColorButton" value="ffffff" style="width:40px;text-align: center" />
+            <input type="button" class="MenuButtonSmall  i18n" onclick="setAllColors();" value="Text_Set" />
+            <hr style="width:1px; height:20px; display: inline; margin-left: 3px; margin-right: 3px; ">
+            <input type="button" class="MenuButtonSmall  i18n" onclick="reshuffleColors();" value="Text_Reshuffle" />
+            <hr style="width:1px; height:20px; display: inline; margin-left: 3px; margin-right: 3px; ">
+            <span class="i18n">Text_Opacity</span>&nbsp;&nbsp;
+            <input id="opacityID"  value="50" style="width:25px;" onkeypress="if (event.keyCode == 13) {setOpacity($(this));}" onchange="setOpacity($(this));"/>%
+        </div>    
+    </div>    
+
+    <div id="AttributesDiv" style="width:100%; height:90%; overflow-y:auto" class="s8"></div>
+
+    <table id="bottomPanel" cellpadding ="3px" style="background-color: #151515" cellspacing = "0" border="0" width="100%"  class="s9w">
+        <tr valign="top">
+            <td align="right">
+                    <input type="button" id="SaveID" class="MenuButtonSmallWhite MenuButtonLast i18n" onclick="Save(true);" value="Text_Save" />
+                </td>
+        </tr>
+    </table>
+    
+<script src="../jquery/jquery-1.10.2.js"  type="text/javascript"></script>
+<script src="./jscolor.js" type="text/javascript" ></script>
+<script language="javascript" src="../ToolsCommon71.js"></script>
+<script language="jscript">
+
+var SGWorld = new ActiveXObject("TerraExplorerX.SGWorld71");
+
+var gDebug = false;
+var gType=0;
+var gSaved = false;
+var g3DMLID;
+var g3DMLObj;
+var gFeatures;
+var gQueryBulk = 50000;
+var gOpacity = 128;
+var gLayersProperties=[];
+var gLayersColor=[];
+var gColors = ["ff0000","00ff00","0000ff","ff00ff","ffff00","00ffff","800000","808000","000080","800080","008080","ccff66","ff66ff","00cc99","0099ff","333399","663300","b35900","999966","b3e6b3","19004d"];
+
+$(window).resize(function(e) {
+    $("#AttributesDiv").height($( window ).height()-$("#topPanel").height()-$("#bottomPanel").height());
+});
+
+//--------------
+//  Init
+function Init() {
+    try {
+        $("#AttributesDiv").height($( window ).height()-80);
+        gType = GetParamValue("Type", 0);
+        g3DMLID  = GetParamValue("ID", "");
+        if (g3DMLID=="")
+            g3DMLID = SGWorld.ProjectTree.GetNextItem (SGWorld.ProjectTree.RootID,10); 
+
+        g3DMLObj = SGWorld.Creator.GetObject(g3DMLID);
+        if (g3DMLObj.ObjectType == 39){ // feature layer under 3DML - get the parent 3DML
+                g3DMLID = SGWorld.ProjectTree.GetNextItem (g3DMLID,15);
+                g3DMLObj = SGWorld.Creator.GetObject(g3DMLID);
+            }
+
+        if (g3DMLObj.ObjectType != 38){
+            TEAlert (SGLang.i18n("Text_AlertCaption"), SGLang.i18n("Text_3DMLNotFound"));
+            return;
+        }
+
+        FindLayers();
+        FindAttributes();
+    }
+    catch (e) { TEAlert (SGLang.i18n("Text_AlertCaption"),SGLang.i18n("Text_3DMLNotFound") ); exitTool(); return;}
+}
+//--------------
+//  FindLayers
+function FindLayers() {
+
+    try{
+        for (var i=0; i<g3DMLObj.FeatureLayers.Count; i++){
+            $('#LayersListID').append($('<option>', { 
+                value: g3DMLObj.FeatureLayers.Item(i).ID,
+                text : g3DMLObj.FeatureLayers.Item(i).TreeItem.Name 
+            }));
+
+            var FeatureLayerID = $('#LayersListID').val();
+
+        }
+        Save(false); // save initial visibility state for all layers
+    }
+    catch (e) {if (gDebug) alert(e.message);}
+}
+//--------------
+//  FindAttributes
+function FindAttributes() {
+    try{
+        $('#AttributesListID').html("");
+        var FeatureLayerID = $('#LayersListID').val();
+        var featureLayer = SGWorld.Creator.GetObject(FeatureLayerID);
+        var firstFeature = featureLayer.ExecuteQuery ("",1,"",SGWorld.Creator.GeometryCreator.CreatePolygonGeometry(null));
+        for (var i=0; i<firstFeature.Item(0).FeatureAttributes.Count; i++) {
+            $('#AttributesListID').append($('<option>', { 
+                    value: i,
+                    text : firstFeature.Item(0).FeatureAttributes.Item(i).Name 
+                }));
+        }
+        ShowAttributeValues(true);
+    }
+    catch (e) {$("#AttributesDiv").html("");}
+}
+//--------------
+//  ShowAttributeValues
+function ShowAttributeValues(fromInit) {
+    
+    try {
+        var FeatureLayerID = $('#LayersListID').val();
+        var featureLayer = SGWorld.Creator.GetObject(FeatureLayerID);
+        var attributeIndex = $('#AttributesListID').val();
+        var attributeName  = $('#AttributesListID').children("option").filter(":selected").text()
+        var serverPrefix = (checkUrl(g3DMLObj.path))?"SQL: ":"";
+        try{
+         gFeatures = featureLayer.ExecuteQuery (serverPrefix+attributeName+" Like '%%' or "+attributeName+" is null GROUP BY lower("+attributeName+")",gQueryBulk,"",SGWorld.Creator.GeometryCreator.CreatePolygonGeometry(null));
+        }
+        catch (e) { if (serverPrefix!="") TEAlert (SGLang.i18n("Text_AlertCaption"), SGLang.i18n("Text_SGSTooOld") ); else TEAlert (SGLang.i18n("Text_AlertCaption"),e.message); exitTool(); return;}
+
+// Need a try-catch and a message telling that the SGS server is lower then 7.2
+        if (gFeatures.Count>=gQueryBulk) {
+            if (fromInit && !$('#AttributesListID').children("option").filter(":selected").is ($('#AttributesListID').children().last())){
+                $('#AttributesListID option:selected').next().attr('selected', 'selected');
+                ShowAttributeValues(fromInit);
+                return;
+            }
+            htmlText = "<br><label class='s9red' >"+SGLang.i18n("Text_TooManyAttributes")+"</label><br>";
+            $("#AttributesDiv").html(htmlText);
+            if (gType==0)
+                featureLayer.FeatureProperties.SetClassification ("Visibility", "");
+            else
+                featureLayer.FeatureProperties.Tint = SGWorld.Creator.CreateColor(255,255,255,0);
+            return;
+        }
+
+        var htmlText = "";
+        var attributes=[];
+        for (var i=0; i<gFeatures.Count; i++) {
+            if (gFeatures.Item(i).FeatureAttributes.Item(attributeIndex).Value == "")
+                attributes.push (SGLang.i18n("Text_Empty"));
+            else
+                attributes.push (gFeatures.Item(i).FeatureAttributes.Item(attributeIndex).Value);
+        }
+        attributes.sort();
+        
+        if (gType==0) {    // Visibility
+            htmlText += $("#visibilityHeader").html();
+
+            for (var i=0; i<gFeatures.Count; i++) {
+                var uniqueValue = attributes[i];
+                htmlText += '<input id="' + uniqueValue + '" type="checkbox"  checked="checked" name="' + uniqueValue + '" value="' + uniqueValue + '" onchange="ChangeSelection();">';
+                htmlText += '<label for="' + uniqueValue + '">'+uniqueValue+'</label><br>';
+            }
+            $("#AttributesDiv").html(htmlText);
+            ChangeSelection();
+        }
+        else {
+            htmlText += $("#colorizeHeader").html();
+
+            for (var i=0; i<gFeatures.Count; i++) {
+                var uniqueValue = attributes[i];
+                htmlText += '<input id="' + uniqueValue + '" class="jscolor TintColorButton s6" onchange="ChangeTintColor();" value="'+getRandomColor(i)+'" style="width:40px;text-align: center;"  />';
+                htmlText += '<label for="' + uniqueValue + '">'+uniqueValue+'</label><br>';
+            }
+            
+            $("#AttributesDiv").html(htmlText);
+            setTimeout ("ChangeTintColor();",10);
+            jscolor.installByClassName("jscolor");
+        }
+    }
+     catch (e) {if (gDebug) alert(e.message);}
+}
+//--------------
+//  getRandomColor
+function getRandomColor(index) {
+    var color;
+    if (index<20)
+        color = gColors[index];
+    else
+        color =  componentToHex(Math.round(Math.random()*255)) + componentToHex(Math.round(Math.random()*255)) + componentToHex(Math.round(Math.random()*255));
+
+    return color;
+}
+//--------------
+//  componentToHex
+function componentToHex(c) {
+    var hex = c.toString(16);
+    return hex.length == 1 ? "0" + hex : hex;
+}
+
+//--------------
+//  CheckAll
+function CheckAll(t) {
+    var checkValue = $(t).is(":checked");//  $(this).val();
+    $('#AttributesDiv').find(':checkbox').each(function() {
+            this.checked = checkValue;
+    });
+    ChangeSelection();
+
+}
+//--------------
+//  checkUrl
+function checkUrl(s) {
+     var regexp = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/
+     return regexp.test(s); 
+}
+//--------------
+//  ChangeSelection
+function ChangeSelection() {
+    try{
+        var attName = $('#AttributesListID').children("option").filter(":selected").text();
+        var query="";
+        var first=true;
+        var checkAll=true;
+        $('#AttributesDiv').find(':checkbox').each(function(index) {
+            if (index!=0) {  // ignore first checkbox (All)
+                if ($(this).prop("checked")){
+                    if (!first)
+                            query += " OR ";
+                    var attValue = $(this).attr('name');
+                    var find = "'";
+                    var re = new RegExp(find, 'g');
+                    attValue = attValue.replace(re, "''");
+                    if (attValue==SGLang.i18n("Text_Empty"))
+                        attValue="";
+                    query += "\""+attName+"\" = '"+attValue+"'";
+                    first=false;
+                }
+                else
+                    checkAll=false;
+            }  
+        });
+        if (checkAll)
+            query = "";
+        else if (query=="")
+            query = "\""+attName+"\" = '-9999'"; // in case of all checkboxes are off this fake query should hide all elements
+        var FeatureLayerID = $('#LayersListID').val();
+        var featureLayer = SGWorld.Creator.GetObject(FeatureLayerID);
+        featureLayer.FeatureProperties.SetClassification ("Visibility", query);
+    }
+    catch (e) {if (gDebug) alert(e.message);}
+}
+//--------------
+//  setAllColors
+function setAllColors(){
+    var allColors;
+    $('#AttributesDiv').find('.jscolor').each(function(index) {
+            if (index==0)
+                allColors = $(this)[0].jscolor.toHEXString();
+            else 
+                $(this)[0].jscolor.fromString(allColors);
+        });
+    setTimeout ("ChangeTintColor();",10);
+}
+//--------------
+//  reshuffleColors
+function reshuffleColors(){
+    $('#AttributesDiv').find('.jscolor').each(function(index) {
+            if (index>0)
+                $(this)[0].jscolor.fromString(getRandomColor(index+100)); 
+        });
+    setTimeout ("ChangeTintColor();",10);
+}
+//--------------
+//  setOpacity
+function setOpacity(t) {
+    var n = parseFloat(t.val());
+    if ( isNaN(n) || n < 0 || n > 100){
+        t.val("50");
+    }
+    gOpacity=t.val()*2.56;
+    ChangeTintColor();
+}
+//--------------
+//  ChangeTintColor
+function ChangeTintColor() {
+    try{
+        var attName = $('#AttributesListID').children("option").filter(":selected").text();
+        var query="<Classification FuncType='0'>";
+        var first=true;
+        $('#AttributesDiv').find('.jscolor').each(function(index) {
+                var attValue = $(this).attr('id');
+                var find = "'";
+                var re = new RegExp(find, 'g');
+                attValue = attValue.replace(re, "''");
+                var HexColor = rgb2hex($(this).css("backgroundColor"));
+                var BGRcolor = HexColor.substr(4,2)+HexColor.substr(2,2)+HexColor.substr(0,2);
+                var color = parseInt(BGRcolor, 16);
+                attValue= htmlSpecialChars(attValue);
+                if (attValue==SGLang.i18n("Text_Empty"))
+                    attValue="";
+                if (index==0)   // default color
+                    query+= '<DefaultValue>'+color+'</DefaultValue>';
+                else
+                    query += '<Class><Condition>&lt;"['+attName+']"="'+attValue+'"&gt;</Condition><Value>'+color+'</Value></Class>';
+        });
+        query +="</Classification>";
+        var FeatureLayerID = $('#LayersListID').val();
+        var featureLayer = SGWorld.Creator.GetObject(FeatureLayerID);
+        featureLayer.FeatureProperties.Tint = SGWorld.Creator.CreateColor(255,255,255,gOpacity);
+        featureLayer.FeatureProperties.SetClassification ("Tint Color", query);
+    }
+    catch (e) {if (gDebug) alert(e.message);}
+}
+//--------------
+//  htmlSpecialChars
+function htmlSpecialChars(unsafe) {
+    return unsafe
+    .replace(/&/g, "&amp;")
+    .replace(/</g, "&lt;")
+    .replace(/>/g, "&gt;");
+    //.replace(/"/g, "&quot;");
+}
+//--------------
+//  rgb2hex
+function rgb2hex(rgb) {
+    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
+    function hex(x) {
+        return ("0" + parseInt(x).toString(16)).slice(-2);
+    }
+    return  hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
+}
+
+//--------------
+//  Save
+function Save(fromButton) {
+    
+    try{
+        for (var i=0; i<g3DMLObj.FeatureLayers.Count; i++){
+            if (gType==0)
+                gLayersProperties[i] = g3DMLObj.FeatureLayers.Item(i).FeatureProperties.GetClassification("Visibility");
+            else{
+                gLayersProperties[i] = g3DMLObj.FeatureLayers.Item(i).FeatureProperties.GetClassification("Tint Color");
+                if (gLayersProperties[i]=="")
+                    gLayersColor[i] = g3DMLObj.FeatureLayers.Item(i).FeatureProperties.Tint.ToABGRColor();
+            }
+        }
+        if (fromButton){
+            TEAlert (SGLang.i18n("Text_AlertCaption"),SGLang.i18n("Text_SaveMessage"),true);
+            gSaved = true;
+        }
+    }
+    catch (e) {  if (gDebug) alert(e.message);}
+}
+//--------------
+//  exitTool
+function exitTool() {
+    try {
+        for (var i=0; i<g3DMLObj.FeatureLayers.Count; i++){
+            if (gType==0) // Display by Attribute
+                g3DMLObj.FeatureLayers.Item(i).FeatureProperties.SetClassification("Visibility",gLayersProperties[i]);
+            else  // Colorize
+            {
+                if (gLayersProperties[i]!=""){
+                    g3DMLObj.FeatureLayers.Item(i).FeatureProperties.Tint = SGWorld.Creator.CreateColor(255,255,255,gOpacity);
+                    g3DMLObj.FeatureLayers.Item(i).FeatureProperties.SetClassification("Tint Color",gLayersProperties[i]);
+                }
+                else
+                    g3DMLObj.FeatureLayers.Item(i).FeatureProperties.Tint.FromABGRColor(gLayersColor[i]);
+            }
+       }
+       //SGWorld.Window.RemovePopupByCaption(SGLang.i18n("ToolName"));
+
+    }
+    catch (e) { if (gDebug) alert(SGLang.i18n("Text_ErrorWhileExit") +e.message); }
+}
+      
+</script>
+
+</body>
+</html>
+
+
+
+
+<!--Sig:00000040tBCwtQRZuIXgN24Lj4YU5Nf2MZ#8T7hT69FZiWKHZmovcNw7BskI03tkmCVWphsMcqiEZKR#.X4OjlCpiy8mXbJJ-->
diff --git a/TEWin/Resources/DisplayByAttribute/Lang.js b/TEWin/Resources/DisplayByAttribute/Lang.js
new file mode 100644
index 0000000..6f408bf
--- /dev/null
+++ b/TEWin/Resources/DisplayByAttribute/Lang.js
@@ -0,0 +1,28 @@
+锘縎GLang.lang = $.extend(SGLang.lang, {
+    ToolTitle: "SkylineGlobe - Skyline Software Systems, Inc.",
+    Text_DisplayByAttributeCaption: "Display By Attribute",
+    Text_ColorizeByAttributeCaption: "Colorize By Attribute",
+    help: "Help",
+    Text_DisplayByAttrBtn: "Display by<br> Attribute",
+    Text_ColorizeByAttrBtn: "Colorize by<br> Attribute",
+    Text_Layer: "Layer:",
+    Text_Attribute: "Attribute:",
+    Text_3DMLNotFound: "Please select a 3D Mesh layer from the Project Tree and run this tool again. ",
+    Text_ErrorWhileExit: "Unexpected error occurred while trying to exit the Display By Attribute tool. ",
+    Text_TooManyAttributes: "There are too many unique values for this <b>Attribute</b> field. Select a different <b>Attribute</b>. ",
+    Text_SetAll: "Set all to:",
+    Text_All: "All",
+    Text_Set: "Set",
+    Text_Empty: "-EMPTY-",
+    Text_Reshuffle: "Reshuffle",
+    Text_Opacity: "Opacity:",
+    Text_Default: "Default Color",
+    Text_SGSTooOld: "Operation is only supported by SkylineGlobe Server v7.2 or higher. ",
+    Text_Save: "Save",
+    Text_SaveMessage: "Setting was saved successfully.",
+    Text_AlertCaption: "TerraExplorer",
+
+
+    Text999: ""
+});
+
diff --git a/TEWin/Resources/DisplayByAttribute/Launch.html b/TEWin/Resources/DisplayByAttribute/Launch.html
new file mode 100644
index 0000000..90c2fcb
--- /dev/null
+++ b/TEWin/Resources/DisplayByAttribute/Launch.html
@@ -0,0 +1,110 @@
+锘�<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title>ToolTitle</title>
+
+
+    <script language="javascript" src="../ToolsCommon.js"></script>
+
+    <link rel="StyleSheet" href="../Style.css" type="text/css">
+    <style>
+        .MenuButton
+        {
+            height: 78px;
+            width: 65px;
+            margin: 5px;
+            white-space: normal;s
+        }
+        .MenuButtonHighlight
+        {
+            color: Red;
+            font-weight: bold;
+        }
+    </style>
+</head>
+<body leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" style="border: 0;
+    overflow: auto;" id="Body" onload="Init()" onunload="exitTool();" >
+    <!--oncontextmenu="return false;"  onclick="bHide=true;HideOptionsNow()" > -->
+       <table border="0" width="100%" cellspacing="0" cellpadding="2">
+        <tr>
+            <td id="TopAreaTD" height="50px" width="100%" valign="middle" style="background-color: #CAD8E2">
+                <table border="0" width="100%" cellspacing="0" cellpadding="0">
+                    <tr>
+                        <td width="12px">
+                        </td>
+                        <td width="55px">
+                            <img src="images/ImageComparisonIcon.gif" />
+                        </td>
+                        <td id="TitleTD" align="center" class="s12b  i18n">
+                            ToolName
+                        </td>
+                        <td valign="top" align="right" id="CloseHelpTd">
+							<img src="../CommonImg/help.gif" border="0" class="i18n" alt="help" title="help" onclick="DisplayHelpPopup6 (SGLang.i18nFile('help.html'),SGLang.i18n('help'))" style="cursor: pointer;">
+						</td>
+                    </tr>
+                </table>
+            </td>
+        </tr>
+        <tr height="1px">
+            <td style="background-repeat: repeat-x;" background="../CommonImg/separator.gif">
+            </td>
+        </tr>
+        <tr>
+            <td>
+                <br />
+            </td>
+        </tr>
+    </table>
+    <table>
+       
+        <tr class="s8">
+            <td colspan="2">
+                    <button id="Button4" class="MenuButton" onclick="DisplayByAttribute(0)"><span class="i18n">Text_DisplayByAttrBtn</span></button> 
+                    <button id="Button4" class="MenuButton" onclick="DisplayByAttribute(1)"><span class="i18n">Text_ColorizeByAttrBtn</span></button> 
+                </td>
+        </tr>
+    </table>
+    <object id="SGWorld" classid="CLSID:3a4f91b1-65a8-11d5-85c1-0001023952c1" style="visibility:hidden;height:0 "></object>
+
+<script language="JavaScript">
+
+//--------------
+// Init
+function Init() {
+}
+
+//------------------
+// Reset
+//------------------
+function Reset(FirstTime, FromMouseInputMode) {
+
+}
+//---------------
+// exitTool
+function exitTool() {
+    try {
+    }
+    catch (e) { return }
+   
+
+}
+
+//--------------
+// DisplayByAttribute
+function DisplayByAttribute(Type) {
+    var url = abspath() + "/DisplayByAttribute.html?Type="+Type ;
+    if (Type==0)
+        var name = SGLang.i18n("Text_DisplayByAttributeCaption");
+    else
+    var name = SGLang.i18n("Text_ColorizeByAttributeCaption");
+    var popupMsg = SGWorld.Creator.CreatePopupMessage(name, url, 10, 10, 360, 350, -1);
+
+    popupMsg.Flags = 2 + 32+128 + 2048;
+    SGWorld.Window.ShowPopup(popupMsg);
+}
+</script>
+
+</body>
+</html>
+
+
+<!--Sig:00000040AKc8HyzeAumZyfidSovnIa0aNP9iirTTYRM8EPxwjg9Hm0O11G6afif0ZaTzMgRkgBxJNPvOIAA0IPw4gvoTGEJJ-->
diff --git a/TEWin/Resources/DisplayByAttribute/ToolIcon.png b/TEWin/Resources/DisplayByAttribute/ToolIcon.png
new file mode 100644
index 0000000..f711b74
--- /dev/null
+++ b/TEWin/Resources/DisplayByAttribute/ToolIcon.png
Binary files differ
diff --git a/TEWin/Resources/DisplayByAttribute/jscolor.js b/TEWin/Resources/DisplayByAttribute/jscolor.js
new file mode 100644
index 0000000..e650a69
--- /dev/null
+++ b/TEWin/Resources/DisplayByAttribute/jscolor.js
@@ -0,0 +1,1855 @@
+/**
+ * jscolor - JavaScript Color Picker
+ *
+ * @link    http://jscolor.com
+ * @license For open source use: GPLv3
+ *          For commercial use: JSColor Commercial License
+ * @author  Jan Odvarko
+ * @version 2.0.5
+ *
+ * See usage examples at http://jscolor.com/examples/
+ */
+
+
+"use strict";
+
+
+if (!window.jscolor) { window.jscolor = (function () {
+
+
+var jsc = {
+
+
+	register : function () {
+		jsc.attachDOMReadyEvent(jsc.init);
+		jsc.attachEvent(document, 'mousedown', jsc.onDocumentMouseDown);
+		jsc.attachEvent(document, 'touchstart', jsc.onDocumentTouchStart);
+		jsc.attachEvent(window, 'resize', jsc.onWindowResize);
+	},
+
+
+	init : function () {
+		if (jsc.jscolor.lookupClass) {
+			jsc.jscolor.installByClassName(jsc.jscolor.lookupClass);
+		}
+	},
+
+
+	tryInstallOnElements : function (elms, className) {
+		var matchClass = new RegExp('(^|\\s)(' + className + ')(\\s*(\\{[^}]*\\})|\\s|$)', 'i');
+
+		for (var i = 0; i < elms.length; i += 1) {
+			if (elms[i].type !== undefined && elms[i].type.toLowerCase() == 'color') {
+				if (jsc.isColorAttrSupported) {
+					// skip inputs of type 'color' if supported by the browser
+					continue;
+				}
+			}
+			var m;
+			if (!elms[i].jscolor && elms[i].className && (m = elms[i].className.match(matchClass))) {
+				var targetElm = elms[i];
+				var optsStr = null;
+
+				var dataOptions = jsc.getDataAttr(targetElm, 'jscolor');
+				if (dataOptions !== null) {
+					optsStr = dataOptions;
+				} else if (m[4]) {
+					optsStr = m[4];
+				}
+
+				var opts = {};
+				if (optsStr) {
+					try {
+						opts = (new Function ('return (' + optsStr + ')'))();
+					} catch(eParseError) {
+						jsc.warn('Error parsing jscolor options: ' + eParseError + ':\n' + optsStr);
+					}
+				}
+				targetElm.jscolor = new jsc.jscolor(targetElm, opts);
+			}
+		}
+	},
+
+
+	isColorAttrSupported : (function () {
+		var elm = document.createElement('input');
+		if (elm.setAttribute) {
+			elm.setAttribute('type', 'color');
+			if (elm.type.toLowerCase() == 'color') {
+				return true;
+			}
+		}
+		return false;
+	})(),
+
+
+	isCanvasSupported : (function () {
+		var elm = document.createElement('canvas');
+		return !!(elm.getContext && elm.getContext('2d'));
+	})(),
+
+
+	fetchElement : function (mixed) {
+		return typeof mixed === 'string' ? document.getElementById(mixed) : mixed;
+	},
+
+
+	isElementType : function (elm, type) {
+		return elm.nodeName.toLowerCase() === type.toLowerCase();
+	},
+
+
+	getDataAttr : function (el, name) {
+		var attrName = 'data-' + name;
+		var attrValue = el.getAttribute(attrName);
+		if (attrValue !== null) {
+			return attrValue;
+		}
+		return null;
+	},
+
+
+	attachEvent : function (el, evnt, func) {
+		if (el.addEventListener) {
+			el.addEventListener(evnt, func, false);
+		} else if (el.attachEvent) {
+			el.attachEvent('on' + evnt, func);
+		}
+	},
+
+
+	detachEvent : function (el, evnt, func) {
+		if (el.removeEventListener) {
+			el.removeEventListener(evnt, func, false);
+		} else if (el.detachEvent) {
+			el.detachEvent('on' + evnt, func);
+		}
+	},
+
+
+	_attachedGroupEvents : {},
+
+
+	attachGroupEvent : function (groupName, el, evnt, func) {
+		if (!jsc._attachedGroupEvents.hasOwnProperty(groupName)) {
+			jsc._attachedGroupEvents[groupName] = [];
+		}
+		jsc._attachedGroupEvents[groupName].push([el, evnt, func]);
+		jsc.attachEvent(el, evnt, func);
+	},
+
+
+	detachGroupEvents : function (groupName) {
+		if (jsc._attachedGroupEvents.hasOwnProperty(groupName)) {
+			for (var i = 0; i < jsc._attachedGroupEvents[groupName].length; i += 1) {
+				var evt = jsc._attachedGroupEvents[groupName][i];
+				jsc.detachEvent(evt[0], evt[1], evt[2]);
+			}
+			delete jsc._attachedGroupEvents[groupName];
+		}
+	},
+
+
+	attachDOMReadyEvent : function (func) {
+		var fired = false;
+		var fireOnce = function () {
+			if (!fired) {
+				fired = true;
+				func();
+			}
+		};
+
+		if (document.readyState === 'complete') {
+			setTimeout(fireOnce, 1); // async
+			return;
+		}
+
+		if (document.addEventListener) {
+			document.addEventListener('DOMContentLoaded', fireOnce, false);
+
+			// Fallback
+			window.addEventListener('load', fireOnce, false);
+
+		} else if (document.attachEvent) {
+			// IE
+			document.attachEvent('onreadystatechange', function () {
+				if (document.readyState === 'complete') {
+					document.detachEvent('onreadystatechange', arguments.callee);
+					fireOnce();
+				}
+			})
+
+			// Fallback
+			window.attachEvent('onload', fireOnce);
+
+			// IE7/8
+			if (document.documentElement.doScroll && window == window.top) {
+				var tryScroll = function () {
+					if (!document.body) { return; }
+					try {
+						document.documentElement.doScroll('left');
+						fireOnce();
+					} catch (e) {
+						setTimeout(tryScroll, 1);
+					}
+				};
+				tryScroll();
+			}
+		}
+	},
+
+
+	warn : function (msg) {
+		if (window.console && window.console.warn) {
+			window.console.warn(msg);
+		}
+	},
+
+
+	preventDefault : function (e) {
+		if (e.preventDefault) { e.preventDefault(); }
+		e.returnValue = false;
+	},
+
+
+	captureTarget : function (target) {
+		// IE
+		if (target.setCapture) {
+			jsc._capturedTarget = target;
+			jsc._capturedTarget.setCapture();
+		}
+	},
+
+
+	releaseTarget : function () {
+		// IE
+		if (jsc._capturedTarget) {
+			jsc._capturedTarget.releaseCapture();
+			jsc._capturedTarget = null;
+		}
+	},
+
+
+	fireEvent : function (el, evnt) {
+		if (!el) {
+			return;
+		}
+		if (document.createEvent) {
+			var ev = document.createEvent('HTMLEvents');
+			ev.initEvent(evnt, true, true);
+			el.dispatchEvent(ev);
+		} else if (document.createEventObject) {
+			var ev = document.createEventObject();
+			el.fireEvent('on' + evnt, ev);
+		} else if (el['on' + evnt]) { // alternatively use the traditional event model
+			el['on' + evnt]();
+		}
+	},
+
+
+	classNameToList : function (className) {
+		return className.replace(/^\s+|\s+$/g, '').split(/\s+/);
+	},
+
+
+	// The className parameter (str) can only contain a single class name
+	hasClass : function (elm, className) {
+		if (!className) {
+			return false;
+		}
+		return -1 != (' ' + elm.className.replace(/\s+/g, ' ') + ' ').indexOf(' ' + className + ' ');
+	},
+
+
+	// The className parameter (str) can contain multiple class names separated by whitespace
+	setClass : function (elm, className) {
+		var classList = jsc.classNameToList(className);
+		for (var i = 0; i < classList.length; i += 1) {
+			if (!jsc.hasClass(elm, classList[i])) {
+				elm.className += (elm.className ? ' ' : '') + classList[i];
+			}
+		}
+	},
+
+
+	// The className parameter (str) can contain multiple class names separated by whitespace
+	unsetClass : function (elm, className) {
+		var classList = jsc.classNameToList(className);
+		for (var i = 0; i < classList.length; i += 1) {
+			var repl = new RegExp(
+				'^\\s*' + classList[i] + '\\s*|' +
+				'\\s*' + classList[i] + '\\s*$|' +
+				'\\s+' + classList[i] + '(\\s+)',
+				'g'
+			);
+			elm.className = elm.className.replace(repl, '$1');
+		}
+	},
+
+
+	getStyle : function (elm) {
+		return window.getComputedStyle ? window.getComputedStyle(elm) : elm.currentStyle;
+	},
+
+
+	setStyle : (function () {
+		var helper = document.createElement('div');
+		var getSupportedProp = function (names) {
+			for (var i = 0; i < names.length; i += 1) {
+				if (names[i] in helper.style) {
+					return names[i];
+				}
+			}
+		};
+		var props = {
+			borderRadius: getSupportedProp(['borderRadius', 'MozBorderRadius', 'webkitBorderRadius']),
+			boxShadow: getSupportedProp(['boxShadow', 'MozBoxShadow', 'webkitBoxShadow'])
+		};
+		return function (elm, prop, value) {
+			switch (prop.toLowerCase()) {
+			case 'opacity':
+				var alphaOpacity = Math.round(parseFloat(value) * 100);
+				elm.style.opacity = value;
+				elm.style.filter = 'alpha(opacity=' + alphaOpacity + ')';
+				break;
+			default:
+				elm.style[props[prop]] = value;
+				break;
+			}
+		};
+	})(),
+
+
+	setBorderRadius : function (elm, value) {
+		jsc.setStyle(elm, 'borderRadius', value || '0');
+	},
+
+
+	setBoxShadow : function (elm, value) {
+		jsc.setStyle(elm, 'boxShadow', value || 'none');
+	},
+
+
+	getElementPos : function (e, relativeToViewport) {
+		var x=0, y=0;
+		var rect = e.getBoundingClientRect();
+		x = rect.left;
+		y = rect.top;
+		if (!relativeToViewport) {
+			var viewPos = jsc.getViewPos();
+			x += viewPos[0];
+			y += viewPos[1];
+		}
+		return [x, y];
+	},
+
+
+	getElementSize : function (e) {
+		return [e.offsetWidth, e.offsetHeight];
+	},
+
+
+	// get pointer's X/Y coordinates relative to viewport
+	getAbsPointerPos : function (e) {
+		if (!e) { e = window.event; }
+		var x = 0, y = 0;
+		if (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) {
+			// touch devices
+			x = e.changedTouches[0].clientX;
+			y = e.changedTouches[0].clientY;
+		} else if (typeof e.clientX === 'number') {
+			x = e.clientX;
+			y = e.clientY;
+		}
+		return { x: x, y: y };
+	},
+
+
+	// get pointer's X/Y coordinates relative to target element
+	getRelPointerPos : function (e) {
+		if (!e) { e = window.event; }
+		var target = e.target || e.srcElement;
+		var targetRect = target.getBoundingClientRect();
+
+		var x = 0, y = 0;
+
+		var clientX = 0, clientY = 0;
+		if (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) {
+			// touch devices
+			clientX = e.changedTouches[0].clientX;
+			clientY = e.changedTouches[0].clientY;
+		} else if (typeof e.clientX === 'number') {
+			clientX = e.clientX;
+			clientY = e.clientY;
+		}
+
+		x = clientX - targetRect.left;
+		y = clientY - targetRect.top;
+		return { x: x, y: y };
+	},
+
+
+	getViewPos : function () {
+		var doc = document.documentElement;
+		return [
+			(window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0),
+			(window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
+		];
+	},
+
+
+	getViewSize : function () {
+		var doc = document.documentElement;
+		return [
+			(window.innerWidth || doc.clientWidth),
+			(window.innerHeight || doc.clientHeight),
+		];
+	},
+
+
+	redrawPosition : function () {
+
+		if (jsc.picker && jsc.picker.owner) {
+			var thisObj = jsc.picker.owner;
+
+			var tp, vp;
+
+			if (thisObj.fixed) {
+				// Fixed elements are positioned relative to viewport,
+				// therefore we can ignore the scroll offset
+				tp = jsc.getElementPos(thisObj.targetElement, true); // target pos
+				vp = [0, 0]; // view pos
+			} else {
+				tp = jsc.getElementPos(thisObj.targetElement); // target pos
+				vp = jsc.getViewPos(); // view pos
+			}
+
+			var ts = jsc.getElementSize(thisObj.targetElement); // target size
+			var vs = jsc.getViewSize(); // view size
+			var ps = jsc.getPickerOuterDims(thisObj); // picker size
+			var a, b, c;
+			switch (thisObj.position.toLowerCase()) {
+				case 'left': a=1; b=0; c=-1; break;
+				case 'right':a=1; b=0; c=1; break;
+				case 'top':  a=0; b=1; c=-1; break;
+				default:     a=0; b=1; c=1; break;
+			}
+			var l = (ts[b]+ps[b])/2;
+
+			// compute picker position
+			if (!thisObj.smartPosition) {
+				var pp = [
+					tp[a],
+					tp[b]+ts[b]-l+l*c
+				];
+			} else {
+				var pp = [
+					-vp[a]+tp[a]+ps[a] > vs[a] ?
+						(-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) :
+						tp[a],
+					-vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
+						(-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :
+						(tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
+				];
+			}
+
+			var x = pp[a];
+			var y = pp[b];
+			var positionValue = thisObj.fixed ? 'fixed' : 'absolute';
+			var contractShadow =
+				(pp[0] + ps[0] > tp[0] || pp[0] < tp[0] + ts[0]) &&
+				(pp[1] + ps[1] < tp[1] + ts[1]);
+
+			jsc._drawPosition(thisObj, x, y, positionValue, contractShadow);
+		}
+	},
+
+
+	_drawPosition : function (thisObj, x, y, positionValue, contractShadow) {
+		var vShadow = contractShadow ? 0 : thisObj.shadowBlur; // px
+
+		jsc.picker.wrap.style.position = positionValue;
+		jsc.picker.wrap.style.left = x + 'px';
+		jsc.picker.wrap.style.top = y + 'px';
+
+		jsc.setBoxShadow(
+			jsc.picker.boxS,
+			thisObj.shadow ?
+				new jsc.BoxShadow(0, vShadow, thisObj.shadowBlur, 0, thisObj.shadowColor) :
+				null);
+	},
+
+
+	getPickerDims : function (thisObj) {
+		var displaySlider = !!jsc.getSliderComponent(thisObj);
+		var dims = [
+			2 * thisObj.insetWidth + 2 * thisObj.padding + thisObj.width +
+				(displaySlider ? 2 * thisObj.insetWidth + jsc.getPadToSliderPadding(thisObj) + thisObj.sliderSize : 0),
+			2 * thisObj.insetWidth + 2 * thisObj.padding + thisObj.height +
+				(thisObj.closable ? 2 * thisObj.insetWidth + thisObj.padding + thisObj.buttonHeight : 0)
+		];
+		return dims;
+	},
+
+
+	getPickerOuterDims : function (thisObj) {
+		var dims = jsc.getPickerDims(thisObj);
+		return [
+			dims[0] + 2 * thisObj.borderWidth,
+			dims[1] + 2 * thisObj.borderWidth
+		];
+	},
+
+
+	getPadToSliderPadding : function (thisObj) {
+		return Math.max(thisObj.padding, 1.5 * (2 * thisObj.pointerBorderWidth + thisObj.pointerThickness));
+	},
+
+
+	getPadYComponent : function (thisObj) {
+		switch (thisObj.mode.charAt(1).toLowerCase()) {
+			case 'v': return 'v'; break;
+		}
+		return 's';
+	},
+
+
+	getSliderComponent : function (thisObj) {
+		if (thisObj.mode.length > 2) {
+			switch (thisObj.mode.charAt(2).toLowerCase()) {
+				case 's': return 's'; break;
+				case 'v': return 'v'; break;
+			}
+		}
+		return null;
+	},
+
+
+	onDocumentMouseDown : function (e) {
+		if (!e) { e = window.event; }
+		var target = e.target || e.srcElement;
+
+		if (target._jscLinkedInstance) {
+			if (target._jscLinkedInstance.showOnClick) {
+				target._jscLinkedInstance.show();
+			}
+		} else if (target._jscControlName) {
+			jsc.onControlPointerStart(e, target, target._jscControlName, 'mouse');
+		} else {
+			// Mouse is outside the picker controls -> hide the color picker!
+			if (jsc.picker && jsc.picker.owner) {
+				jsc.picker.owner.hide();
+			}
+		}
+	},
+
+
+	onDocumentTouchStart : function (e) {
+		if (!e) { e = window.event; }
+		var target = e.target || e.srcElement;
+
+		if (target._jscLinkedInstance) {
+			if (target._jscLinkedInstance.showOnClick) {
+				target._jscLinkedInstance.show();
+			}
+		} else if (target._jscControlName) {
+			jsc.onControlPointerStart(e, target, target._jscControlName, 'touch');
+		} else {
+			if (jsc.picker && jsc.picker.owner) {
+				jsc.picker.owner.hide();
+			}
+		}
+	},
+
+
+	onWindowResize : function (e) {
+		jsc.redrawPosition();
+	},
+
+
+	onParentScroll : function (e) {
+		// hide the picker when one of the parent elements is scrolled
+		if (jsc.picker && jsc.picker.owner) {
+			jsc.picker.owner.hide();
+		}
+	},
+
+
+	_pointerMoveEvent : {
+		mouse: 'mousemove',
+		touch: 'touchmove'
+	},
+	_pointerEndEvent : {
+		mouse: 'mouseup',
+		touch: 'touchend'
+	},
+
+
+	_pointerOrigin : null,
+	_capturedTarget : null,
+
+
+	onControlPointerStart : function (e, target, controlName, pointerType) {
+		var thisObj = target._jscInstance;
+
+		jsc.preventDefault(e);
+		jsc.captureTarget(target);
+
+		var registerDragEvents = function (doc, offset) {
+			jsc.attachGroupEvent('drag', doc, jsc._pointerMoveEvent[pointerType],
+				jsc.onDocumentPointerMove(e, target, controlName, pointerType, offset));
+			jsc.attachGroupEvent('drag', doc, jsc._pointerEndEvent[pointerType],
+				jsc.onDocumentPointerEnd(e, target, controlName, pointerType));
+		};
+
+		registerDragEvents(document, [0, 0]);
+
+		if (window.parent && window.frameElement) {
+			var rect = window.frameElement.getBoundingClientRect();
+			var ofs = [-rect.left, -rect.top];
+			registerDragEvents(window.parent.window.document, ofs);
+		}
+
+		var abs = jsc.getAbsPointerPos(e);
+		var rel = jsc.getRelPointerPos(e);
+		jsc._pointerOrigin = {
+			x: abs.x - rel.x,
+			y: abs.y - rel.y
+		};
+
+		switch (controlName) {
+		case 'pad':
+			// if the slider is at the bottom, move it up
+			switch (jsc.getSliderComponent(thisObj)) {
+			case 's': if (thisObj.hsv[1] === 0) { thisObj.fromHSV(null, 100, null); }; break;
+			case 'v': if (thisObj.hsv[2] === 0) { thisObj.fromHSV(null, null, 100); }; break;
+			}
+			jsc.setPad(thisObj, e, 0, 0);
+			break;
+
+		case 'sld':
+			jsc.setSld(thisObj, e, 0);
+			break;
+		}
+
+		jsc.dispatchFineChange(thisObj);
+	},
+
+
+	onDocumentPointerMove : function (e, target, controlName, pointerType, offset) {
+		return function (e) {
+			var thisObj = target._jscInstance;
+			switch (controlName) {
+			case 'pad':
+				if (!e) { e = window.event; }
+				jsc.setPad(thisObj, e, offset[0], offset[1]);
+				jsc.dispatchFineChange(thisObj);
+				break;
+
+			case 'sld':
+				if (!e) { e = window.event; }
+				jsc.setSld(thisObj, e, offset[1]);
+				jsc.dispatchFineChange(thisObj);
+				break;
+			}
+		}
+	},
+
+
+	onDocumentPointerEnd : function (e, target, controlName, pointerType) {
+		return function (e) {
+			var thisObj = target._jscInstance;
+			jsc.detachGroupEvents('drag');
+			jsc.releaseTarget();
+			// Always dispatch changes after detaching outstanding mouse handlers,
+			// in case some user interaction will occur in user's onchange callback
+			// that would intrude with current mouse events
+			jsc.dispatchChange(thisObj);
+		};
+	},
+
+
+	dispatchChange : function (thisObj) {
+		if (thisObj.valueElement) {
+			if (jsc.isElementType(thisObj.valueElement, 'input')) {
+				jsc.fireEvent(thisObj.valueElement, 'change');
+			}
+		}
+	},
+
+
+	dispatchFineChange : function (thisObj) {
+		if (thisObj.onFineChange) {
+			var callback;
+			if (typeof thisObj.onFineChange === 'string') {
+				callback = new Function (thisObj.onFineChange);
+			} else {
+				callback = thisObj.onFineChange;
+			}
+			callback.call(thisObj);
+		}
+	},
+
+
+	setPad : function (thisObj, e, ofsX, ofsY) {
+		var pointerAbs = jsc.getAbsPointerPos(e);
+		var x = ofsX + pointerAbs.x - jsc._pointerOrigin.x - thisObj.padding - thisObj.insetWidth;
+		var y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.insetWidth;
+
+		var xVal = x * (360 / (thisObj.width - 1));
+		var yVal = 100 - (y * (100 / (thisObj.height - 1)));
+
+		switch (jsc.getPadYComponent(thisObj)) {
+		case 's': thisObj.fromHSV(xVal, yVal, null, jsc.leaveSld); break;
+		case 'v': thisObj.fromHSV(xVal, null, yVal, jsc.leaveSld); break;
+		}
+	},
+
+
+	setSld : function (thisObj, e, ofsY) {
+		var pointerAbs = jsc.getAbsPointerPos(e);
+		var y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.insetWidth;
+
+		var yVal = 100 - (y * (100 / (thisObj.height - 1)));
+
+		switch (jsc.getSliderComponent(thisObj)) {
+		case 's': thisObj.fromHSV(null, yVal, null, jsc.leavePad); break;
+		case 'v': thisObj.fromHSV(null, null, yVal, jsc.leavePad); break;
+		}
+	},
+
+
+	_vmlNS : 'jsc_vml_',
+	_vmlCSS : 'jsc_vml_css_',
+	_vmlReady : false,
+
+
+	initVML : function () {
+		if (!jsc._vmlReady) {
+			// init VML namespace
+			var doc = document;
+			if (!doc.namespaces[jsc._vmlNS]) {
+				doc.namespaces.add(jsc._vmlNS, 'urn:schemas-microsoft-com:vml');
+			}
+			if (!doc.styleSheets[jsc._vmlCSS]) {
+				var tags = ['shape', 'shapetype', 'group', 'background', 'path', 'formulas', 'handles', 'fill', 'stroke', 'shadow', 'textbox', 'textpath', 'imagedata', 'line', 'polyline', 'curve', 'rect', 'roundrect', 'oval', 'arc', 'image'];
+				var ss = doc.createStyleSheet();
+				ss.owningElement.id = jsc._vmlCSS;
+				for (var i = 0; i < tags.length; i += 1) {
+					ss.addRule(jsc._vmlNS + '\\:' + tags[i], 'behavior:url(#default#VML);');
+				}
+			}
+			jsc._vmlReady = true;
+		}
+	},
+
+
+	createPalette : function () {
+
+		var paletteObj = {
+			elm: null,
+			draw: null
+		};
+
+		if (jsc.isCanvasSupported) {
+			// Canvas implementation for modern browsers
+
+			var canvas = document.createElement('canvas');
+			var ctx = canvas.getContext('2d');
+
+			var drawFunc = function (width, height, type) {
+				canvas.width = width;
+				canvas.height = height;
+
+				ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+				var hGrad = ctx.createLinearGradient(0, 0, canvas.width, 0);
+				hGrad.addColorStop(0 / 6, '#F00');
+				hGrad.addColorStop(1 / 6, '#FF0');
+				hGrad.addColorStop(2 / 6, '#0F0');
+				hGrad.addColorStop(3 / 6, '#0FF');
+				hGrad.addColorStop(4 / 6, '#00F');
+				hGrad.addColorStop(5 / 6, '#F0F');
+				hGrad.addColorStop(6 / 6, '#F00');
+
+				ctx.fillStyle = hGrad;
+				ctx.fillRect(0, 0, canvas.width, canvas.height);
+
+				var vGrad = ctx.createLinearGradient(0, 0, 0, canvas.height);
+				switch (type.toLowerCase()) {
+				case 's':
+					vGrad.addColorStop(0, 'rgba(255,255,255,0)');
+					vGrad.addColorStop(1, 'rgba(255,255,255,1)');
+					break;
+				case 'v':
+					vGrad.addColorStop(0, 'rgba(0,0,0,0)');
+					vGrad.addColorStop(1, 'rgba(0,0,0,1)');
+					break;
+				}
+				ctx.fillStyle = vGrad;
+				ctx.fillRect(0, 0, canvas.width, canvas.height);
+			};
+
+			paletteObj.elm = canvas;
+			paletteObj.draw = drawFunc;
+
+		} else {
+			// VML fallback for IE 7 and 8
+
+			jsc.initVML();
+
+			var vmlContainer = document.createElement('div');
+			vmlContainer.style.position = 'relative';
+			vmlContainer.style.overflow = 'hidden';
+
+			var hGrad = document.createElement(jsc._vmlNS + ':fill');
+			hGrad.type = 'gradient';
+			hGrad.method = 'linear';
+			hGrad.angle = '90';
+			hGrad.colors = '16.67% #F0F, 33.33% #00F, 50% #0FF, 66.67% #0F0, 83.33% #FF0'
+
+			var hRect = document.createElement(jsc._vmlNS + ':rect');
+			hRect.style.position = 'absolute';
+			hRect.style.left = -1 + 'px';
+			hRect.style.top = -1 + 'px';
+			hRect.stroked = false;
+			hRect.appendChild(hGrad);
+			vmlContainer.appendChild(hRect);
+
+			var vGrad = document.createElement(jsc._vmlNS + ':fill');
+			vGrad.type = 'gradient';
+			vGrad.method = 'linear';
+			vGrad.angle = '180';
+			vGrad.opacity = '0';
+
+			var vRect = document.createElement(jsc._vmlNS + ':rect');
+			vRect.style.position = 'absolute';
+			vRect.style.left = -1 + 'px';
+			vRect.style.top = -1 + 'px';
+			vRect.stroked = false;
+			vRect.appendChild(vGrad);
+			vmlContainer.appendChild(vRect);
+
+			var drawFunc = function (width, height, type) {
+				vmlContainer.style.width = width + 'px';
+				vmlContainer.style.height = height + 'px';
+
+				hRect.style.width =
+				vRect.style.width =
+					(width + 1) + 'px';
+				hRect.style.height =
+				vRect.style.height =
+					(height + 1) + 'px';
+
+				// Colors must be specified during every redraw, otherwise IE won't display
+				// a full gradient during a subsequential redraw
+				hGrad.color = '#F00';
+				hGrad.color2 = '#F00';
+
+				switch (type.toLowerCase()) {
+				case 's':
+					vGrad.color = vGrad.color2 = '#FFF';
+					break;
+				case 'v':
+					vGrad.color = vGrad.color2 = '#000';
+					break;
+				}
+			};
+			
+			paletteObj.elm = vmlContainer;
+			paletteObj.draw = drawFunc;
+		}
+
+		return paletteObj;
+	},
+
+
+	createSliderGradient : function () {
+
+		var sliderObj = {
+			elm: null,
+			draw: null
+		};
+
+		if (jsc.isCanvasSupported) {
+			// Canvas implementation for modern browsers
+
+			var canvas = document.createElement('canvas');
+			var ctx = canvas.getContext('2d');
+
+			var drawFunc = function (width, height, color1, color2) {
+				canvas.width = width;
+				canvas.height = height;
+
+				ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+				var grad = ctx.createLinearGradient(0, 0, 0, canvas.height);
+				grad.addColorStop(0, color1);
+				grad.addColorStop(1, color2);
+
+				ctx.fillStyle = grad;
+				ctx.fillRect(0, 0, canvas.width, canvas.height);
+			};
+
+			sliderObj.elm = canvas;
+			sliderObj.draw = drawFunc;
+
+		} else {
+			// VML fallback for IE 7 and 8
+
+			jsc.initVML();
+
+			var vmlContainer = document.createElement('div');
+			vmlContainer.style.position = 'relative';
+			vmlContainer.style.overflow = 'hidden';
+
+			var grad = document.createElement(jsc._vmlNS + ':fill');
+			grad.type = 'gradient';
+			grad.method = 'linear';
+			grad.angle = '180';
+
+			var rect = document.createElement(jsc._vmlNS + ':rect');
+			rect.style.position = 'absolute';
+			rect.style.left = -1 + 'px';
+			rect.style.top = -1 + 'px';
+			rect.stroked = false;
+			rect.appendChild(grad);
+			vmlContainer.appendChild(rect);
+
+			var drawFunc = function (width, height, color1, color2) {
+				vmlContainer.style.width = width + 'px';
+				vmlContainer.style.height = height + 'px';
+
+				rect.style.width = (width + 1) + 'px';
+				rect.style.height = (height + 1) + 'px';
+
+				grad.color = color1;
+				grad.color2 = color2;
+			};
+			
+			sliderObj.elm = vmlContainer;
+			sliderObj.draw = drawFunc;
+		}
+
+		return sliderObj;
+	},
+
+
+	leaveValue : 1<<0,
+	leaveStyle : 1<<1,
+	leavePad : 1<<2,
+	leaveSld : 1<<3,
+
+
+	BoxShadow : (function () {
+		var BoxShadow = function (hShadow, vShadow, blur, spread, color, inset) {
+			this.hShadow = hShadow;
+			this.vShadow = vShadow;
+			this.blur = blur;
+			this.spread = spread;
+			this.color = color;
+			this.inset = !!inset;
+		};
+
+		BoxShadow.prototype.toString = function () {
+			var vals = [
+				Math.round(this.hShadow) + 'px',
+				Math.round(this.vShadow) + 'px',
+				Math.round(this.blur) + 'px',
+				Math.round(this.spread) + 'px',
+				this.color
+			];
+			if (this.inset) {
+				vals.push('inset');
+			}
+			return vals.join(' ');
+		};
+
+		return BoxShadow;
+	})(),
+
+
+	//
+	// Usage:
+	// var myColor = new jscolor(<targetElement> [, <options>])
+	//
+
+	jscolor : function (targetElement, options) {
+
+		// General options
+		//
+		this.value = null; // initial HEX color. To change it later, use methods fromString(), fromHSV() and fromRGB()
+		this.valueElement = targetElement; // element that will be used to display and input the color code
+		this.styleElement = targetElement; // element that will preview the picked color using CSS backgroundColor
+		this.required = true; // whether the associated text <input> can be left empty
+		this.refine = true; // whether to refine the entered color code (e.g. uppercase it and remove whitespace)
+		this.hash = false; // whether to prefix the HEX color code with # symbol
+		this.uppercase = true; // whether to show the color code in upper case
+		this.onFineChange = null; // called instantly every time the color changes (value can be either a function or a string with javascript code)
+		this.activeClass = 'jscolor-active'; // class to be set to the target element when a picker window is open on it
+		this.overwriteImportant = false; // whether to overwrite colors of styleElement using !important
+		this.minS = 0; // min allowed saturation (0 - 100)
+		this.maxS = 100; // max allowed saturation (0 - 100)
+		this.minV = 0; // min allowed value (brightness) (0 - 100)
+		this.maxV = 100; // max allowed value (brightness) (0 - 100)
+
+		// Accessing the picked color
+		//
+		this.hsv = [0, 0, 100]; // read-only  [0-360, 0-100, 0-100]
+		this.rgb = [255, 255, 255]; // read-only  [0-255, 0-255, 0-255]
+
+		// Color Picker options
+		//
+		this.width = 181; // width of color palette (in px)
+		this.height = 101; // height of color palette (in px)
+		this.showOnClick = true; // whether to display the color picker when user clicks on its target element
+		this.mode = 'HSV'; // HSV | HVS | HS | HV - layout of the color picker controls
+		this.position = 'bottom'; // left | right | top | bottom - position relative to the target element
+		this.smartPosition = true; // automatically change picker position when there is not enough space for it
+		this.sliderSize = 16; // px
+		this.crossSize = 8; // px
+		this.closable = false; // whether to display the Close button
+		this.closeText = 'Close';
+		this.buttonColor = '#000000'; // CSS color
+		this.buttonHeight = 18; // px
+		this.padding = 12; // px
+		this.backgroundColor = '#FFFFFF'; // CSS color
+		this.borderWidth = 1; // px
+		this.borderColor = '#BBBBBB'; // CSS color
+		this.borderRadius = 8; // px
+		this.insetWidth = 1; // px
+		this.insetColor = '#BBBBBB'; // CSS color
+		this.shadow = true; // whether to display shadow
+		this.shadowBlur = 15; // px
+		this.shadowColor = 'rgba(0,0,0,0.2)'; // CSS color
+		this.pointerColor = '#4C4C4C'; // px
+		this.pointerBorderColor = '#FFFFFF'; // px
+        this.pointerBorderWidth = 1; // px
+        this.pointerThickness = 2; // px
+		this.zIndex = 1000;
+		this.container = null; // where to append the color picker (BODY element by default)
+
+
+		for (var opt in options) {
+			if (options.hasOwnProperty(opt)) {
+				this[opt] = options[opt];
+			}
+		}
+
+
+		this.hide = function () {
+			if (isPickerOwner()) {
+				detachPicker();
+			}
+		};
+
+
+		this.show = function () {
+			drawPicker();
+		};
+
+
+		this.redraw = function () {
+			if (isPickerOwner()) {
+				drawPicker();
+			}
+		};
+
+
+		this.importColor = function () {
+			if (!this.valueElement) {
+				this.exportColor();
+			} else {
+				if (jsc.isElementType(this.valueElement, 'input')) {
+					if (!this.refine) {
+						if (!this.fromString(this.valueElement.value, jsc.leaveValue)) {
+							if (this.styleElement) {
+								this.styleElement.style.backgroundImage = this.styleElement._jscOrigStyle.backgroundImage;
+								this.styleElement.style.backgroundColor = this.styleElement._jscOrigStyle.backgroundColor;
+								this.styleElement.style.color = this.styleElement._jscOrigStyle.color;
+							}
+							this.exportColor(jsc.leaveValue | jsc.leaveStyle);
+						}
+					} else if (!this.required && /^\s*$/.test(this.valueElement.value)) {
+						this.valueElement.value = '';
+						if (this.styleElement) {
+							this.styleElement.style.backgroundImage = this.styleElement._jscOrigStyle.backgroundImage;
+							this.styleElement.style.backgroundColor = this.styleElement._jscOrigStyle.backgroundColor;
+							this.styleElement.style.color = this.styleElement._jscOrigStyle.color;
+						}
+						this.exportColor(jsc.leaveValue | jsc.leaveStyle);
+
+					} else if (this.fromString(this.valueElement.value)) {
+						// managed to import color successfully from the value -> OK, don't do anything
+					} else {
+						this.exportColor();
+					}
+				} else {
+					// not an input element -> doesn't have any value
+					this.exportColor();
+				}
+			}
+		};
+
+
+		this.exportColor = function (flags) {
+			if (!(flags & jsc.leaveValue) && this.valueElement) {
+				var value = this.toString();
+				if (this.uppercase) { value = value.toUpperCase(); }
+				if (this.hash) { value = '#' + value; }
+
+				if (jsc.isElementType(this.valueElement, 'input')) {
+					this.valueElement.value = value;
+				} else {
+					this.valueElement.innerHTML = value;
+				}
+			}
+			if (!(flags & jsc.leaveStyle)) {
+				if (this.styleElement) {
+					var bgColor = '#' + this.toString();
+					var fgColor = this.isLight() ? '#000' : '#FFF';
+
+					this.styleElement.style.backgroundImage = 'none';
+					this.styleElement.style.backgroundColor = bgColor;
+					this.styleElement.style.color = fgColor;
+
+					if (this.overwriteImportant) {
+						this.styleElement.setAttribute('style',
+							'background: ' + bgColor + ' !important; ' +
+							'color: ' + fgColor + ' !important;'
+						);
+					}
+				}
+			}
+			if (!(flags & jsc.leavePad) && isPickerOwner()) {
+				redrawPad();
+			}
+			if (!(flags & jsc.leaveSld) && isPickerOwner()) {
+				redrawSld();
+			}
+		};
+
+
+		// h: 0-360
+		// s: 0-100
+		// v: 0-100
+		//
+		this.fromHSV = function (h, s, v, flags) { // null = don't change
+			if (h !== null) {
+				if (isNaN(h)) { return false; }
+				h = Math.max(0, Math.min(360, h));
+			}
+			if (s !== null) {
+				if (isNaN(s)) { return false; }
+				s = Math.max(0, Math.min(100, this.maxS, s), this.minS);
+			}
+			if (v !== null) {
+				if (isNaN(v)) { return false; }
+				v = Math.max(0, Math.min(100, this.maxV, v), this.minV);
+			}
+
+			this.rgb = HSV_RGB(
+				h===null ? this.hsv[0] : (this.hsv[0]=h),
+				s===null ? this.hsv[1] : (this.hsv[1]=s),
+				v===null ? this.hsv[2] : (this.hsv[2]=v)
+			);
+
+			this.exportColor(flags);
+		};
+
+
+		// r: 0-255
+		// g: 0-255
+		// b: 0-255
+		//
+		this.fromRGB = function (r, g, b, flags) { // null = don't change
+			if (r !== null) {
+				if (isNaN(r)) { return false; }
+				r = Math.max(0, Math.min(255, r));
+			}
+			if (g !== null) {
+				if (isNaN(g)) { return false; }
+				g = Math.max(0, Math.min(255, g));
+			}
+			if (b !== null) {
+				if (isNaN(b)) { return false; }
+				b = Math.max(0, Math.min(255, b));
+			}
+
+			var hsv = RGB_HSV(
+				r===null ? this.rgb[0] : r,
+				g===null ? this.rgb[1] : g,
+				b===null ? this.rgb[2] : b
+			);
+			if (hsv[0] !== null) {
+				this.hsv[0] = Math.max(0, Math.min(360, hsv[0]));
+			}
+			if (hsv[2] !== 0) {
+				this.hsv[1] = hsv[1]===null ? null : Math.max(0, this.minS, Math.min(100, this.maxS, hsv[1]));
+			}
+			this.hsv[2] = hsv[2]===null ? null : Math.max(0, this.minV, Math.min(100, this.maxV, hsv[2]));
+
+			// update RGB according to final HSV, as some values might be trimmed
+			var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]);
+			this.rgb[0] = rgb[0];
+			this.rgb[1] = rgb[1];
+			this.rgb[2] = rgb[2];
+
+			this.exportColor(flags);
+		};
+
+
+		this.fromString = function (str, flags) {
+			var m;
+			if (m = str.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i)) {
+				// HEX notation
+				//
+
+				if (m[1].length === 6) {
+					// 6-char notation
+					this.fromRGB(
+						parseInt(m[1].substr(0,2),16),
+						parseInt(m[1].substr(2,2),16),
+						parseInt(m[1].substr(4,2),16),
+						flags
+					);
+				} else {
+					// 3-char notation
+					this.fromRGB(
+						parseInt(m[1].charAt(0) + m[1].charAt(0),16),
+						parseInt(m[1].charAt(1) + m[1].charAt(1),16),
+						parseInt(m[1].charAt(2) + m[1].charAt(2),16),
+						flags
+					);
+				}
+				return true;
+
+			} else if (m = str.match(/^\W*rgba?\(([^)]*)\)\W*$/i)) {
+				var params = m[1].split(',');
+				var re = /^\s*(\d*)(\.\d+)?\s*$/;
+				var mR, mG, mB;
+				if (
+					params.length >= 3 &&
+					(mR = params[0].match(re)) &&
+					(mG = params[1].match(re)) &&
+					(mB = params[2].match(re))
+				) {
+					var r = parseFloat((mR[1] || '0') + (mR[2] || ''));
+					var g = parseFloat((mG[1] || '0') + (mG[2] || ''));
+					var b = parseFloat((mB[1] || '0') + (mB[2] || ''));
+					this.fromRGB(r, g, b, flags);
+					return true;
+				}
+			}
+			return false;
+		};
+
+
+		this.toString = function () {
+			return (
+				(0x100 | Math.round(this.rgb[0])).toString(16).substr(1) +
+				(0x100 | Math.round(this.rgb[1])).toString(16).substr(1) +
+				(0x100 | Math.round(this.rgb[2])).toString(16).substr(1)
+			);
+		};
+
+
+		this.toHEXString = function () {
+			return '#' + this.toString().toUpperCase();
+		};
+
+
+		this.toRGBString = function () {
+			return ('rgb(' +
+				Math.round(this.rgb[0]) + ',' +
+				Math.round(this.rgb[1]) + ',' +
+				Math.round(this.rgb[2]) + ')'
+			);
+		};
+
+
+		this.isLight = function () {
+			return (
+				0.213 * this.rgb[0] +
+				0.715 * this.rgb[1] +
+				0.072 * this.rgb[2] >
+				255 / 2
+			);
+		};
+
+
+		this._processParentElementsInDOM = function () {
+			if (this._linkedElementsProcessed) { return; }
+			this._linkedElementsProcessed = true;
+
+			var elm = this.targetElement;
+			do {
+				// If the target element or one of its parent nodes has fixed position,
+				// then use fixed positioning instead
+				//
+				// Note: In Firefox, getComputedStyle returns null in a hidden iframe,
+				// that's why we need to check if the returned style object is non-empty
+				var currStyle = jsc.getStyle(elm);
+				if (currStyle && currStyle.position.toLowerCase() === 'fixed') {
+					this.fixed = true;
+				}
+
+				if (elm !== this.targetElement) {
+					// Ensure to attach onParentScroll only once to each parent element
+					// (multiple targetElements can share the same parent nodes)
+					//
+					// Note: It's not just offsetParents that can be scrollable,
+					// that's why we loop through all parent nodes
+					if (!elm._jscEventsAttached) {
+						jsc.attachEvent(elm, 'scroll', jsc.onParentScroll);
+						elm._jscEventsAttached = true;
+					}
+				}
+			} while ((elm = elm.parentNode) && !jsc.isElementType(elm, 'body'));
+		};
+
+
+		// r: 0-255
+		// g: 0-255
+		// b: 0-255
+		//
+		// returns: [ 0-360, 0-100, 0-100 ]
+		//
+		function RGB_HSV (r, g, b) {
+			r /= 255;
+			g /= 255;
+			b /= 255;
+			var n = Math.min(Math.min(r,g),b);
+			var v = Math.max(Math.max(r,g),b);
+			var m = v - n;
+			if (m === 0) { return [ null, 0, 100 * v ]; }
+			var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);
+			return [
+				60 * (h===6?0:h),
+				100 * (m/v),
+				100 * v
+			];
+		}
+
+
+		// h: 0-360
+		// s: 0-100
+		// v: 0-100
+		//
+		// returns: [ 0-255, 0-255, 0-255 ]
+		//
+		function HSV_RGB (h, s, v) {
+			var u = 255 * (v / 100);
+
+			if (h === null) {
+				return [ u, u, u ];
+			}
+
+			h /= 60;
+			s /= 100;
+
+			var i = Math.floor(h);
+			var f = i%2 ? h-i : 1-(h-i);
+			var m = u * (1 - s);
+			var n = u * (1 - s * f);
+			switch (i) {
+				case 6:
+				case 0: return [u,n,m];
+				case 1: return [n,u,m];
+				case 2: return [m,u,n];
+				case 3: return [m,n,u];
+				case 4: return [n,m,u];
+				case 5: return [u,m,n];
+			}
+		}
+
+
+		function detachPicker () {
+			jsc.unsetClass(THIS.targetElement, THIS.activeClass);
+			jsc.picker.wrap.parentNode.removeChild(jsc.picker.wrap);
+			delete jsc.picker.owner;
+		}
+
+
+		function drawPicker () {
+
+			// At this point, when drawing the picker, we know what the parent elements are
+			// and we can do all related DOM operations, such as registering events on them
+			// or checking their positioning
+			THIS._processParentElementsInDOM();
+
+			if (!jsc.picker) {
+				jsc.picker = {
+					owner: null,
+					wrap : document.createElement('div'),
+					box : document.createElement('div'),
+					boxS : document.createElement('div'), // shadow area
+					boxB : document.createElement('div'), // border
+					pad : document.createElement('div'),
+					padB : document.createElement('div'), // border
+					padM : document.createElement('div'), // mouse/touch area
+					padPal : jsc.createPalette(),
+					cross : document.createElement('div'),
+					crossBY : document.createElement('div'), // border Y
+					crossBX : document.createElement('div'), // border X
+					crossLY : document.createElement('div'), // line Y
+					crossLX : document.createElement('div'), // line X
+					sld : document.createElement('div'),
+					sldB : document.createElement('div'), // border
+					sldM : document.createElement('div'), // mouse/touch area
+					sldGrad : jsc.createSliderGradient(),
+					sldPtrS : document.createElement('div'), // slider pointer spacer
+					sldPtrIB : document.createElement('div'), // slider pointer inner border
+					sldPtrMB : document.createElement('div'), // slider pointer middle border
+					sldPtrOB : document.createElement('div'), // slider pointer outer border
+					btn : document.createElement('div'),
+					btnT : document.createElement('span') // text
+				};
+
+				jsc.picker.pad.appendChild(jsc.picker.padPal.elm);
+				jsc.picker.padB.appendChild(jsc.picker.pad);
+				jsc.picker.cross.appendChild(jsc.picker.crossBY);
+				jsc.picker.cross.appendChild(jsc.picker.crossBX);
+				jsc.picker.cross.appendChild(jsc.picker.crossLY);
+				jsc.picker.cross.appendChild(jsc.picker.crossLX);
+				jsc.picker.padB.appendChild(jsc.picker.cross);
+				jsc.picker.box.appendChild(jsc.picker.padB);
+				jsc.picker.box.appendChild(jsc.picker.padM);
+
+				jsc.picker.sld.appendChild(jsc.picker.sldGrad.elm);
+				jsc.picker.sldB.appendChild(jsc.picker.sld);
+				jsc.picker.sldB.appendChild(jsc.picker.sldPtrOB);
+				jsc.picker.sldPtrOB.appendChild(jsc.picker.sldPtrMB);
+				jsc.picker.sldPtrMB.appendChild(jsc.picker.sldPtrIB);
+				jsc.picker.sldPtrIB.appendChild(jsc.picker.sldPtrS);
+				jsc.picker.box.appendChild(jsc.picker.sldB);
+				jsc.picker.box.appendChild(jsc.picker.sldM);
+
+				jsc.picker.btn.appendChild(jsc.picker.btnT);
+				jsc.picker.box.appendChild(jsc.picker.btn);
+
+				jsc.picker.boxB.appendChild(jsc.picker.box);
+				jsc.picker.wrap.appendChild(jsc.picker.boxS);
+				jsc.picker.wrap.appendChild(jsc.picker.boxB);
+			}
+
+			var p = jsc.picker;
+
+			var displaySlider = !!jsc.getSliderComponent(THIS);
+			var dims = jsc.getPickerDims(THIS);
+			var crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize);
+			var padToSliderPadding = jsc.getPadToSliderPadding(THIS);
+			var borderRadius = Math.min(
+				THIS.borderRadius,
+				Math.round(THIS.padding * Math.PI)); // px
+			var padCursor = 'crosshair';
+
+			// wrap
+			p.wrap.style.clear = 'both';
+			p.wrap.style.width = (dims[0] + 2 * THIS.borderWidth) + 'px';
+			p.wrap.style.height = (dims[1] + 2 * THIS.borderWidth) + 'px';
+			p.wrap.style.zIndex = THIS.zIndex;
+
+			// picker
+			p.box.style.width = dims[0] + 'px';
+			p.box.style.height = dims[1] + 'px';
+
+			p.boxS.style.position = 'absolute';
+			p.boxS.style.left = '0';
+			p.boxS.style.top = '0';
+			p.boxS.style.width = '100%';
+			p.boxS.style.height = '100%';
+			jsc.setBorderRadius(p.boxS, borderRadius + 'px');
+
+			// picker border
+			p.boxB.style.position = 'relative';
+			p.boxB.style.border = THIS.borderWidth + 'px solid';
+			p.boxB.style.borderColor = THIS.borderColor;
+			p.boxB.style.background = THIS.backgroundColor;
+			jsc.setBorderRadius(p.boxB, borderRadius + 'px');
+
+			// IE hack:
+			// If the element is transparent, IE will trigger the event on the elements under it,
+			// e.g. on Canvas or on elements with border
+			p.padM.style.background =
+			p.sldM.style.background =
+				'#FFF';
+			jsc.setStyle(p.padM, 'opacity', '0');
+			jsc.setStyle(p.sldM, 'opacity', '0');
+
+			// pad
+			p.pad.style.position = 'relative';
+			p.pad.style.width = THIS.width + 'px';
+			p.pad.style.height = THIS.height + 'px';
+
+			// pad palettes (HSV and HVS)
+			p.padPal.draw(THIS.width, THIS.height, jsc.getPadYComponent(THIS));
+
+			// pad border
+			p.padB.style.position = 'absolute';
+			p.padB.style.left = THIS.padding + 'px';
+			p.padB.style.top = THIS.padding + 'px';
+			p.padB.style.border = THIS.insetWidth + 'px solid';
+			p.padB.style.borderColor = THIS.insetColor;
+
+			// pad mouse area
+			p.padM._jscInstance = THIS;
+			p.padM._jscControlName = 'pad';
+			p.padM.style.position = 'absolute';
+			p.padM.style.left = '0';
+			p.padM.style.top = '0';
+			p.padM.style.width = (THIS.padding + 2 * THIS.insetWidth + THIS.width + padToSliderPadding / 2) + 'px';
+			p.padM.style.height = dims[1] + 'px';
+			p.padM.style.cursor = padCursor;
+
+			// pad cross
+			p.cross.style.position = 'absolute';
+			p.cross.style.left =
+			p.cross.style.top =
+				'0';
+			p.cross.style.width =
+			p.cross.style.height =
+				crossOuterSize + 'px';
+
+			// pad cross border Y and X
+			p.crossBY.style.position =
+			p.crossBX.style.position =
+				'absolute';
+			p.crossBY.style.background =
+			p.crossBX.style.background =
+				THIS.pointerBorderColor;
+			p.crossBY.style.width =
+			p.crossBX.style.height =
+				(2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px';
+			p.crossBY.style.height =
+			p.crossBX.style.width =
+				crossOuterSize + 'px';
+			p.crossBY.style.left =
+			p.crossBX.style.top =
+				(Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2) - THIS.pointerBorderWidth) + 'px';
+			p.crossBY.style.top =
+			p.crossBX.style.left =
+				'0';
+
+			// pad cross line Y and X
+			p.crossLY.style.position =
+			p.crossLX.style.position =
+				'absolute';
+			p.crossLY.style.background =
+			p.crossLX.style.background =
+				THIS.pointerColor;
+			p.crossLY.style.height =
+			p.crossLX.style.width =
+				(crossOuterSize - 2 * THIS.pointerBorderWidth) + 'px';
+			p.crossLY.style.width =
+			p.crossLX.style.height =
+				THIS.pointerThickness + 'px';
+			p.crossLY.style.left =
+			p.crossLX.style.top =
+				(Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2)) + 'px';
+			p.crossLY.style.top =
+			p.crossLX.style.left =
+				THIS.pointerBorderWidth + 'px';
+
+			// slider
+			p.sld.style.overflow = 'hidden';
+			p.sld.style.width = THIS.sliderSize + 'px';
+			p.sld.style.height = THIS.height + 'px';
+
+			// slider gradient
+			p.sldGrad.draw(THIS.sliderSize, THIS.height, '#000', '#000');
+
+			// slider border
+			p.sldB.style.display = displaySlider ? 'block' : 'none';
+			p.sldB.style.position = 'absolute';
+			p.sldB.style.right = THIS.padding + 'px';
+			p.sldB.style.top = THIS.padding + 'px';
+			p.sldB.style.border = THIS.insetWidth + 'px solid';
+			p.sldB.style.borderColor = THIS.insetColor;
+
+			// slider mouse area
+			p.sldM._jscInstance = THIS;
+			p.sldM._jscControlName = 'sld';
+			p.sldM.style.display = displaySlider ? 'block' : 'none';
+			p.sldM.style.position = 'absolute';
+			p.sldM.style.right = '0';
+			p.sldM.style.top = '0';
+			p.sldM.style.width = (THIS.sliderSize + padToSliderPadding / 2 + THIS.padding + 2 * THIS.insetWidth) + 'px';
+			p.sldM.style.height = dims[1] + 'px';
+			p.sldM.style.cursor = 'default';
+
+			// slider pointer inner and outer border
+			p.sldPtrIB.style.border =
+			p.sldPtrOB.style.border =
+				THIS.pointerBorderWidth + 'px solid ' + THIS.pointerBorderColor;
+
+			// slider pointer outer border
+			p.sldPtrOB.style.position = 'absolute';
+			p.sldPtrOB.style.left = -(2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px';
+			p.sldPtrOB.style.top = '0';
+
+			// slider pointer middle border
+			p.sldPtrMB.style.border = THIS.pointerThickness + 'px solid ' + THIS.pointerColor;
+
+			// slider pointer spacer
+			p.sldPtrS.style.width = THIS.sliderSize + 'px';
+			p.sldPtrS.style.height = sliderPtrSpace + 'px';
+
+			// the Close button
+			function setBtnBorder () {
+				var insetColors = THIS.insetColor.split(/\s+/);
+				var outsetColor = insetColors.length < 2 ? insetColors[0] : insetColors[1] + ' ' + insetColors[0] + ' ' + insetColors[0] + ' ' + insetColors[1];
+				p.btn.style.borderColor = outsetColor;
+			}
+			p.btn.style.display = THIS.closable ? 'block' : 'none';
+			p.btn.style.position = 'absolute';
+			p.btn.style.left = THIS.padding + 'px';
+			p.btn.style.bottom = THIS.padding + 'px';
+			p.btn.style.padding = '0 15px';
+			p.btn.style.height = THIS.buttonHeight + 'px';
+			p.btn.style.border = THIS.insetWidth + 'px solid';
+			setBtnBorder();
+			p.btn.style.color = THIS.buttonColor;
+			p.btn.style.font = '12px sans-serif';
+			p.btn.style.textAlign = 'center';
+			try {
+				p.btn.style.cursor = 'pointer';
+			} catch(eOldIE) {
+				p.btn.style.cursor = 'hand';
+			}
+			p.btn.onmousedown = function () {
+				THIS.hide();
+			};
+			p.btnT.style.lineHeight = THIS.buttonHeight + 'px';
+			p.btnT.innerHTML = '';
+			p.btnT.appendChild(document.createTextNode(THIS.closeText));
+
+			// place pointers
+			redrawPad();
+			redrawSld();
+
+			// If we are changing the owner without first closing the picker,
+			// make sure to first deal with the old owner
+			if (jsc.picker.owner && jsc.picker.owner !== THIS) {
+				jsc.unsetClass(jsc.picker.owner.targetElement, THIS.activeClass);
+			}
+
+			// Set the new picker owner
+			jsc.picker.owner = THIS;
+
+			// The redrawPosition() method needs picker.owner to be set, that's why we call it here,
+			// after setting the owner
+			if (jsc.isElementType(container, 'body')) {
+				jsc.redrawPosition();
+			} else {
+				jsc._drawPosition(THIS, 0, 0, 'relative', false);
+			}
+
+			if (p.wrap.parentNode != container) {
+				container.appendChild(p.wrap);
+			}
+
+			jsc.setClass(THIS.targetElement, THIS.activeClass);
+		}
+
+
+		function redrawPad () {
+			// redraw the pad pointer
+			switch (jsc.getPadYComponent(THIS)) {
+			case 's': var yComponent = 1; break;
+			case 'v': var yComponent = 2; break;
+			}
+			var x = Math.round((THIS.hsv[0] / 360) * (THIS.width - 1));
+			var y = Math.round((1 - THIS.hsv[yComponent] / 100) * (THIS.height - 1));
+			var crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize);
+			var ofs = -Math.floor(crossOuterSize / 2);
+			jsc.picker.cross.style.left = (x + ofs) + 'px';
+			jsc.picker.cross.style.top = (y + ofs) + 'px';
+
+			// redraw the slider
+			switch (jsc.getSliderComponent(THIS)) {
+			case 's':
+				var rgb1 = HSV_RGB(THIS.hsv[0], 100, THIS.hsv[2]);
+				var rgb2 = HSV_RGB(THIS.hsv[0], 0, THIS.hsv[2]);
+				var color1 = 'rgb(' +
+					Math.round(rgb1[0]) + ',' +
+					Math.round(rgb1[1]) + ',' +
+					Math.round(rgb1[2]) + ')';
+				var color2 = 'rgb(' +
+					Math.round(rgb2[0]) + ',' +
+					Math.round(rgb2[1]) + ',' +
+					Math.round(rgb2[2]) + ')';
+				jsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2);
+				break;
+			case 'v':
+				var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 100);
+				var color1 = 'rgb(' +
+					Math.round(rgb[0]) + ',' +
+					Math.round(rgb[1]) + ',' +
+					Math.round(rgb[2]) + ')';
+				var color2 = '#000';
+				jsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2);
+				break;
+			}
+		}
+
+
+		function redrawSld () {
+			var sldComponent = jsc.getSliderComponent(THIS);
+			if (sldComponent) {
+				// redraw the slider pointer
+				switch (sldComponent) {
+				case 's': var yComponent = 1; break;
+				case 'v': var yComponent = 2; break;
+				}
+				var y = Math.round((1 - THIS.hsv[yComponent] / 100) * (THIS.height - 1));
+				jsc.picker.sldPtrOB.style.top = (y - (2 * THIS.pointerBorderWidth + THIS.pointerThickness) - Math.floor(sliderPtrSpace / 2)) + 'px';
+			}
+		}
+
+
+		function isPickerOwner () {
+			return jsc.picker && jsc.picker.owner === THIS;
+		}
+
+
+		function blurValue () {
+			THIS.importColor();
+		}
+
+
+		// Find the target element
+		if (typeof targetElement === 'string') {
+			var id = targetElement;
+			var elm = document.getElementById(id);
+			if (elm) {
+				this.targetElement = elm;
+			} else {
+				jsc.warn('Could not find target element with ID \'' + id + '\'');
+			}
+		} else if (targetElement) {
+			this.targetElement = targetElement;
+		} else {
+			jsc.warn('Invalid target element: \'' + targetElement + '\'');
+		}
+
+		if (this.targetElement._jscLinkedInstance) {
+			jsc.warn('Cannot link jscolor twice to the same element. Skipping.');
+			return;
+		}
+		this.targetElement._jscLinkedInstance = this;
+
+		// Find the value element
+		this.valueElement = jsc.fetchElement(this.valueElement);
+		// Find the style element
+		this.styleElement = jsc.fetchElement(this.styleElement);
+
+		var THIS = this;
+		var container =
+			this.container ?
+			jsc.fetchElement(this.container) :
+			document.getElementsByTagName('body')[0];
+		var sliderPtrSpace = 3; // px
+
+		// For BUTTON elements it's important to stop them from sending the form when clicked
+		// (e.g. in Safari)
+		if (jsc.isElementType(this.targetElement, 'button')) {
+			if (this.targetElement.onclick) {
+				var origCallback = this.targetElement.onclick;
+				this.targetElement.onclick = function (evt) {
+					origCallback.call(this, evt);
+					return false;
+				};
+			} else {
+				this.targetElement.onclick = function () { return false; };
+			}
+		}
+
+		/*
+		var elm = this.targetElement;
+		do {
+			// If the target element or one of its offsetParents has fixed position,
+			// then use fixed positioning instead
+			//
+			// Note: In Firefox, getComputedStyle returns null in a hidden iframe,
+			// that's why we need to check if the returned style object is non-empty
+			var currStyle = jsc.getStyle(elm);
+			if (currStyle && currStyle.position.toLowerCase() === 'fixed') {
+				this.fixed = true;
+			}
+
+			if (elm !== this.targetElement) {
+				// attach onParentScroll so that we can recompute the picker position
+				// when one of the offsetParents is scrolled
+				if (!elm._jscEventsAttached) {
+					jsc.attachEvent(elm, 'scroll', jsc.onParentScroll);
+					elm._jscEventsAttached = true;
+				}
+			}
+		} while ((elm = elm.offsetParent) && !jsc.isElementType(elm, 'body'));
+		*/
+
+		// valueElement
+		if (this.valueElement) {
+			if (jsc.isElementType(this.valueElement, 'input')) {
+				var updateField = function () {
+					THIS.fromString(THIS.valueElement.value, jsc.leaveValue);
+					jsc.dispatchFineChange(THIS);
+				};
+				jsc.attachEvent(this.valueElement, 'keyup', updateField);
+				jsc.attachEvent(this.valueElement, 'input', updateField);
+				jsc.attachEvent(this.valueElement, 'blur', blurValue);
+				this.valueElement.setAttribute('autocomplete', 'off');
+			}
+		}
+
+		// styleElement
+		if (this.styleElement) {
+			this.styleElement._jscOrigStyle = {
+				backgroundImage : this.styleElement.style.backgroundImage,
+				backgroundColor : this.styleElement.style.backgroundColor,
+				color : this.styleElement.style.color
+			};
+		}
+
+		if (this.value) {
+			// Try to set the color from the .value option and if unsuccessful,
+			// export the current color
+			this.fromString(this.value) || this.exportColor();
+		} else {
+			this.importColor();
+		}
+	}
+
+};
+
+
+//================================
+// Public properties and methods
+//================================
+
+
+// By default, search for all elements with class="jscolor" and install a color picker on them.
+//
+// You can change what class name will be looked for by setting the property jscolor.lookupClass
+// anywhere in your HTML document. To completely disable the automatic lookup, set it to null.
+//
+jsc.jscolor.lookupClass = 'jscolor';
+
+
+jsc.jscolor.installByClassName = function (className) {
+	var inputElms = document.getElementsByTagName('input');
+	var buttonElms = document.getElementsByTagName('button');
+
+	jsc.tryInstallOnElements(inputElms, className);
+	jsc.tryInstallOnElements(buttonElms, className);
+};
+
+
+jsc.register();
+
+
+return jsc.jscolor;
+
+
+})(); }
diff --git a/TEWin/TEWin.csproj b/TEWin/TEWin.csproj
index f4e1367..dc5a4ee 100644
--- a/TEWin/TEWin.csproj
+++ b/TEWin/TEWin.csproj
@@ -895,6 +895,27 @@
     <EmbeddedResource Include="Resources\data\T0061_璺彛_闈�1.shp.xml">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </EmbeddedResource>
+    <EmbeddedResource Include="Resources\DisplayByAttribute\1033\Lang.js">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\DisplayByAttribute\2052\Lang.js">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\DisplayByAttribute\DisplayByAttribute.html">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\DisplayByAttribute\jscolor.js">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\DisplayByAttribute\Lang.js">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\DisplayByAttribute\Launch.html">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\DisplayByAttribute\ToolIcon.png">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </EmbeddedResource>
     <Content Include="Resources\log4net4.dll" />
     <Content Include="Resources\Newtonsoft.Json.dll" />
   </ItemGroup>

--
Gitblit v1.9.3