aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeshu-Kumar-M <seshu.kumar.m@huawei.com>2016-09-21 17:35:24 +0800
committerSeshu-Kumar-M <seshu.kumar.m@huawei.com>2016-09-21 17:35:24 +0800
commitb25ec693119cc0c5089b7e01fbccc17698e963b6 (patch)
tree86b881da7cbdc0efb7dee70ec632b417a997e1a7
parentc021b369485a1665c7e7d16608fa2db09bfeffbb (diff)
GSO3 added the new folder structure
Change-Id: Id277f2fc8c21d9cd5027090611e233670e036d46 Signed-off-by: Seshu-Kumar-M <seshu.kumar.m@huawei.com>
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/RMain.css211
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/VMMain.css653
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/bootstrap-table.min.css1
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/bootstrap.min.css7
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/gsolcmmain.html231
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/License.txt362
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/add.pngbin0 -> 1104 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/arrow-down-enable.pngbin0 -> 1035 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/collapse_arrow.pngbin0 -> 1174 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/delete.pngbin0 -> 1100 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/edit.bak.pngbin0 -> 3045 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/edit.pngbin0 -> 3045 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/expand_arrow.pngbin0 -> 1182 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/ideo_default_select.pngbin0 -> 1035 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/import.pngbin0 -> 1250 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/line.pngbin0 -> 139 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/loading-spinner-grey.gifbin0 -> 5203 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/openo.pngbin0 -> 49007 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_l.pngbin0 -> 1066 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_left_disabled.pngbin0 -> 1066 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_r.pngbin0 -> 1070 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/reset.pngbin0 -> 2863 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_asc.pngbin0 -> 1118 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_both.pngbin0 -> 1136 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_desc.pngbin0 -> 1127 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/bootstrap-table.min.js8
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/bootstrap.min.js6
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/brs.js343
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/gsolcm.js461
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/jquery-1.11.2.min.js4
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/rest.js81
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Edge.js33
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Node.js35
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Topology.js113
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEDOWN.pngbin0 -> 2354 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEDOWN_selected.pngbin0 -> 2351 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK.pngbin0 -> 3347 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK_EDGE.pngbin0 -> 3076 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK_selected.pngbin0 -> 3347 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEUP.pngbin0 -> 2823 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEUP_selected.pngbin0 -> 2485 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER.pngbin0 -> 2823 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_0.pngbin0 -> 2551 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_0_selected.pngbin0 -> 2108 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_1.pngbin0 -> 2619 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_1_selected.pngbin0 -> 2318 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_2.pngbin0 -> 2615 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_2_selected.pngbin0 -> 2335 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_3.pngbin0 -> 2842 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_3_selected.pngbin0 -> 2514 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_selected.pngbin0 -> 2485 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/cloud.pngbin0 -> 2239 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/cloudroute.pngbin0 -> 16526 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/crossSubnet.pngbin0 -> 1093 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/delete_asbr.pngbin0 -> 1315 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/mark_sink.pngbin0 -> 1998 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/mark_source.pngbin0 -> 2069 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/networkdown.pngbin0 -> 3694 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_gray.pngbin0 -> 17990 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_green.pngbin0 -> 17995 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_red.pngbin0 -> 17992 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/router.pngbin0 -> 2823 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/router_selected.pngbin0 -> 2485 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/site.pngbin0 -> 2301 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/siteIcon_feature.pngbin0 -> 1222 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/site_selected.pngbin0 -> 1898 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/sitedown.pngbin0 -> 2291 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/sitedown_selected.pngbin0 -> 1888 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/u1963.pngbin0 -> 238 bytes
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/LICENSE.txt12
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/jquery-3.1.0.min.js4
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/plugins/sigma.renderers.customShapes.min.js1
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/plugins/sigma.renderers.edgeLabels.min.js1
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/sigma.min.js5
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/sigma.require.js12224
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/underlay.js120
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/vpn.js307
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/overlayvpn.html153
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/overlayvpn_topo.html42
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/sdnovpn.html117
-rw-r--r--openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/underlayvpn.html225
81 files changed, 15760 insertions, 0 deletions
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/RMain.css b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/RMain.css
new file mode 100644
index 00000000..1b8488aa
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/RMain.css
@@ -0,0 +1,211 @@
+/* Copyright 2016, Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#iemp_layout_container {
+ padding: 0px;
+ margin: 1px auto;
+ width: 100%;
+ height: 100%;
+}
+#iemp_layout_container .three-cols-layout {
+ width: 100%;
+ height: 100%;
+ border-collapse: collapse;
+ margin-left: 0px;
+ margin-top: 0px;
+ margin-right: 0px;
+ margin-bottom: 0px;
+}
+#iemp_layout_container .three-cols-layout {
+ width: 100%;
+ height: 100%;
+ border-collapse: collapse;
+ margin-left: 0px;
+ margin-top: 0px;
+ margin-right: 0px;
+ margin-bottom: 0px;
+}
+#iemp_layout_container .three-cols-column.three-cols-left {
+ width: 215px;
+ background-color: #f5f5f5;
+}
+.accordion_parent {
+ position: relative;
+ width: 220px;
+ background-color: #f5f5f5;
+}
+.openo-accordion-resizable-handle {
+ z-index: 1!important;
+ cursor: e-resize;
+ width: 7px;
+ right: -5px;
+ top: 0;
+ height: 100%;
+ position: absolute;
+ font-size: .1px;
+ display: block;
+}
+.openoAccordian_accordionmenu {
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
+ line-height: 17px;
+}
+.openoAccordian_accordionmenu li {
+ min-width: 75px;
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
+ color: #000;
+ clear: both;
+}
+.openo_accordion_ui-icon-collapse, .openo_accordion_ui-icon-expand {
+ display: block;
+ float: left;
+ margin-bottom: -1px;
+ border-bottom: 1px solid #e5e5e5;
+ cursor: pointer;
+ width: 13px;
+ padding-top: 26px;
+}
+.openo_accordion_ui-icon-expand {
+ background: url(../images/collapse_arrow.png) right 20px no-repeat;
+ margin-top: 8px;
+}
+.openo_accordion_ui-icon-expand.current{
+ background: url(../images/expand_arrow.png) right 20px no-repeat;
+}
+.openoAccordian_showHideArrow_hide, .openoAccordian_showHideArrow_show {
+ display: block;
+ position: absolute;
+ right: 0;
+ top: 4px;
+ width: 18px;
+ height: 41px;
+ cursor: pointer;
+ background-color: #f5f5f5;
+}
+.openoAccordian_showHideArrow_hide {
+ background-image: url(../images/openo.png);
+ background-position: -7px 0!important;
+ border-collapse: separate;
+ /*box-shadow: inset -1px 0 0 #e5e5e5;*/
+}
+a.header.opened, a.header.closed {
+ font-size: 16px;
+ padding-top: 24px;
+ padding-bottom: 25px;
+ color: #999999;
+}
+.openoAccordian_accordionmenu .closed, .openoAccordian_accordionmenu .opened {
+ padding-right: 10px;
+ background-position: 98% 50%;
+ background-repeat: no-repeat;
+}
+.openoAccordian_accordionmenu li a {
+ padding: 11px 10px 12px;
+ color: #333333;
+ margin-right: 1px;
+ margin-top: -1px;
+ text-align: left!important;
+ font-family: "Microsoft Yahei",SimSun,Arial,Tahoma;
+ font-size: 14px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ border-top: 1px solid #e5e5e5;
+ border-bottom: 1px solid #e5e5e5;
+ /*height: 19px;*/
+}
+.openoAccordian_accordionmenu ul {
+ margin: 0;
+ padding: 0;
+ overflow: hidden;
+}
+.openoAccordian_accordionmenu a {
+ display: block;
+ text-decoration: none;
+}
+a {
+ color: #428bca;
+ text-decoration: none;
+ background: 0 0;
+}
+.bar{
+ height: 834px;
+ width: 18px;
+ background: #f8f8f8;
+ display: none;
+}
+.bar span{
+ width: 13px;
+ height: 34px;
+ background-image: url(../images/openo.png);
+ background-position: -39px 0!important;
+ display: block;
+ /*margin-top: -430px;*/
+}
+#accordionmenuid_ul_0_0_brAppTopMenuID_UL li{
+ cursor: pointer;
+}
+#puer_base_openo{
+ border: 1px solid #ddd;
+}
+.openo_accordion_selected {
+ margin-left: 0;
+ margin-right: 0;
+ background: #fafafa;
+ border-left: 3px solid #4ac9ff!important;
+ box-shadow: none;
+ position: relative;
+}
+a:hover{
+ color: #4ac9ff!important;
+}
+.openoAccordian_accordionmenu li.openo_accordion_selected a {
+ position: relative;
+ left: -3px;
+ color: #009ae7;
+}
+.openo-accordion-resizable-handle {
+ z-index: 1!important;
+ cursor: e-resize;
+ width: 7px;
+ right: -5px;
+ top: 0;
+ height: 100%;
+ position: absolute;
+ font-size: .1px;
+ display: block;
+}
+#iframeContainer iframe {
+ width: 100%;
+ height: 100%;
+ border: 0;
+}
+#accordionContent, #iframeContainer {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ width: 100%;
+ height: 100%;
+}
+.openoAccordian_showHideArrow_show {
+ background-image: url(../images/openo.png);
+ background-position: -39px 0!important;
+ box-shadow: inset 1px 0 0 #e5e5e5,inset -1px 0 0 #e5e5e5;
+} \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/VMMain.css b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/VMMain.css
new file mode 100644
index 00000000..e625e907
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/VMMain.css
@@ -0,0 +1,653 @@
+/* Copyright 2016, Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+body{
+ font-family: '微软雅黑';
+ font-size: 12px;
+ color: #333;
+ background: #fafafa;
+}
+button{
+ outline: none;
+}
+ul,li{
+ list-style: none;
+ padding:0;
+ margin:0;
+}
+.titleFont{
+ font-size: 16px;
+}
+.separator-line{
+ height: 1px;
+ width: 100%;
+ border:1px solid #ddd;
+ margin: 6px 0 15px 0;
+}
+.uploadBtn{
+ overflow: hidden;
+}
+.creat-btn {
+ padding: 0 14px;
+ height: 24px;
+ float: left;
+ cursor: pointer;
+ text-decoration: none;
+ outline: 0;
+ border: 1px solid #d3d3d3;
+ text-align: center;
+ box-shadow: 0 1px 1px rgba(0,0,0,.05);
+ background: #fafafa;
+ background: -moz-linear-gradient(top,#fff,#fafafa);
+ background: -webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#fafafa));
+ background: -webkit-linear-gradient(top,#fff,#fafafa);
+ background: linear-gradient(to bottom,#fff,#fafafa);
+ border-radius: 6px;
+ background: #fff url(../images/add.png) no-repeat 5px center;
+ padding-left: 20px;
+}
+.creat-btn:hover {
+ color: #009ae7;
+ border: 1px solid #4AC9FF
+}
+.creat-btn:active {
+ color: #000;
+ border: 1px solid #4AC9FF
+}
+/*.creat-btn{
+ background: #fff url(../image/add.png) no-repeat 5px center;
+ border: 1px solid #ddd;
+ float: left;
+}
+.creat-btn:hover{
+ background: #428bca;
+ color: #fff;
+ border:1px solid #428bca;
+}*/
+.search{
+ width: 310px;
+ height: 30px;
+ float:right;
+}
+.search-text{
+ width: 250px;
+ float: left;
+ margin-right: 6px;
+}
+.search-btn{
+ height: 30px;
+ background: #fff;
+ border: 1px solid #ddd;
+ float: left;
+}
+#ict_virtualApplication_table_div{
+ margin-top: 15px;
+}
+.table>thead>tr.active>th{
+ border: 1px solid #ddd!important;
+ border-bottom: 0;
+ background: #f0f0f0;
+}
+/*.table tbody tr:hover{
+ background: #e6fbe0!important;
+}*/
+.table tbody tr:last-child{
+ border-bottom: 1px solid #ddd;
+}
+.table-btn{
+ border: 1px solid #ccc;
+ border-radius: 3px;
+}
+.delete-btn{
+ background: url(../image/delete.png) no-repeat;
+ width: 16px;
+ height: 16px;
+ border: none;
+}
+.detail-btn{
+ background: url(../image/openo.png) no-repeat -343px -283px;
+ width: 16px;
+ height: 16px;
+ border: none;
+}
+.detail-btn.current{
+ background-position: -7px -314px;
+}
+.detail{
+ height: 200px;
+ border: 1px solid #ddd;
+ margin-top: 60px;
+}
+
+.detail-top ul{
+ height: 50px;
+ line-height: 50px;
+ border-bottom: 1px solid #ddd;
+ padding-left: 0px;
+ background: #fafafa;
+}
+.detail-top ul li{
+ float:left;
+ width: 120px;
+ text-align: center;
+ border-right: 1px solid #ddd;
+ cursor: pointer;
+}
+.detail-top ul li.current{
+ background: #fff;
+}
+.vmapp-margin{
+ margin-bottom: 10px;
+}
+.control-label .required{
+ color: #e02222;
+ font-size: 12px;
+ padding-left: 2px;
+}
+.form-group .control-label{
+ font-size: 12px;
+ font-weight: 400;
+}
+legend{
+ font-size: 12px;
+ font-weight: bold;
+}
+.pageGro{
+ width: 250px;
+ float: right;
+}
+.pageUp,.pageDown,.pageList,.pageList li{
+ float: left;
+ cursor: pointer;
+}
+.pageUp,.pageDown{
+ width: 60px;
+ height: 30px;
+ border: 1px solid #ddd;
+ text-align: center;
+ line-height: 30px;
+}
+.pageList li{
+ width: 30px;
+ height: 30px;
+ border: 1px solid #ddd;
+ text-align: center;
+ line-height: 30px;
+ border-left: none;
+}
+.pageList li.active{
+ background: #428bca;
+ color: #fff;
+ border-color: #428bca;
+}
+.pageDown{
+ border-left: none;
+}
+.headerLinkP{
+ padding-top: 17px;
+}
+.headerLinkP span{
+ font-size: 12px;
+ color: #666;
+ font-weight: normal!important;
+}
+label{
+ font-weight: normal!important;
+}
+table.userform tbody tr td {
+ display: table-cell;
+ padding-right: 10px;
+ padding-top: 10px;
+ font-size: 12px;
+ color: #333;
+}
+.table th,.table td{
+ padding-top: 3px!important;
+ padding-bottom: 3px!important;
+}
+.openoBrowseButton_element {
+ display: table;
+}
+.openo {
+ font-family: "Microsoft Yahei",SimSun,Arial,Tahoma;
+ font-size: 12px;
+ color: #000;
+}
+.openoBrowseButton_input {
+ width: 198px;
+ position: relative;
+ border: 1px solid #c3c3c3!important;
+ height: 26px;
+ background-color: #f3f3f3;
+ border-radius: 4px 0 0 4px;
+ border-right: none;
+ padding: 0;
+}
+.buttonClassDefault, .buttonClassDefault:active {
+ cursor: pointer;
+ background-image: url(../images/openo.png);
+ background-position: -154px -7px!important;
+}
+.openoBrowseButton_button {
+ width: 27px;
+ border: 0;
+ float: right;
+ position: relative;
+ height: 26px;
+ right: 0;
+ top: 0;
+ border-radius: 0 4px 4px 0;
+ border-right: 1px solid #c3c3c3;
+ border-left: none;
+}
+.openo .openo-input, .openo.openo-input {
+ outline: 0;
+ border: 1px solid #c3c3c3;
+ box-shadow: 1px 1px #f6f6f6 inset;
+ background-color: #fff;
+ height: 26px;
+}
+.openoInput_openoDefaultText {
+ padding: 0 0 0 6px;
+ border-radius: 4px;
+ color: #000;
+ display: inline-block;
+ outline: 0;
+ box-shadow: 1px 1px #f6f6f6 inset;
+ font-size: 12px;
+ background: #fff;
+}
+div.openo-select {
+ border: 1px solid #c3c3c3;
+ border-radius: 4px;
+ background: url(../images/arrow-down-enable.png) right no-repeat #fff;
+ line-height: 24px;
+ padding-left: 3px;
+ display: block;
+}
+div.openo-select>input.openo-select-input {
+ border: none;
+ outline: 0;
+ line-height: 21px;
+ height: 21px;
+ padding-left: 3px;
+ border-right: solid 1px #c3c3c3;
+}
+.openo .openo-ellipsis, .openo.openo-ellipsis {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+a.openoButton_buttonClass, a.openoButton_buttonDisableClass, div.openoButton_buttonClass, div.openoButton_buttonDisableClass {
+ height: 26px;
+ float: left;
+ cursor: pointer;
+ text-decoration: none;
+ outline: 0;
+ border: 1px solid #d3d3d3;
+ text-align: center;
+ box-shadow: 0 1px 1px rgba(0,0,0,.05);
+ background: #fafafa;
+ background: -moz-linear-gradient(top,#fff,#fafafa);
+ background: -webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(100%,#fafafa));
+ background: -webkit-linear-gradient(top,#fff,#fafafa);
+ background: linear-gradient(to bottom,#fff,#fafafa);
+ border-radius: 6px;
+}
+.openoButton_buttonInnerClass{
+ padding: 0 19px;
+ border-radius: 6px;
+}
+.openoButton_buttonCenterText {
+ color: #000;
+ line-height: 24px;
+ white-space: nowrap;
+ width: auto!important;
+}
+.userHeader {
+ clear: left;
+ overflow: hidden;
+ margin-bottom: 10px;
+ padding: 10px 10px 0px 0px;
+}
+.openoButton_buttonGroupClass {
+ display: inline;
+}
+.openoButton_buttonGroupClass div.openoButton_buttonClass_parent:first-child {
+ margin-left: 0;
+}
+.openoButton_buttonLeftImg {
+ margin-right: 5px;
+}
+.openoButton_buttonLeftImg, .openoButton_buttonRightImg {
+ display: inline-block;
+ vertical-align: top;
+ width: 16px;
+ height: 16px;
+ margin-top: 4px;
+}
+.openo-table-pagination-wrapper {
+ height: 37px;
+}
+.openo-pagination {
+ display: block;
+ float: left;
+ overflow: hidden;
+ padding: 5px 0 0;
+ margin-top: 8px;
+}
+.openoPagination_openoPaginationLengthOptions:not(msie8) {
+ line-height: 24px;
+}
+.openoPagination_openoPaginationLengthOptions {
+ white-space: normal;
+ height: 24px;
+ float: left;
+ outline: 0;
+ line-height: 20px;
+ margin: 0 5px;
+}
+.openo-pagination-select {
+ height: 26px;
+ line-height: 22px;
+ text-align: center;
+ margin-right: -2px;
+ border: 1px solid #e0e0e0;
+ border-radius: 5px 0 0 5px;
+ padding: 1px;
+}
+.openoPagination_openoPaginationLengthOptions span {
+ background-color: #fff!important;
+}
+.openo-pagination-theme a, .openo-pagination-theme span {
+ float: left;
+ color: #666;
+ font: 12px Lucida Grande,Verdana,Arial,Helvetica,sans-serif;
+ line-height: 24px;
+ font-weight: 400;
+ text-align: center;
+ border: 1px solid #e0e0e0;
+ text-decoration: none!important;
+ padding: 0 7px;
+ border-radius: 3px;
+ background: #fff;
+}
+.openo-pagination-selectspan {
+ background: url(../images/ideo_default_select.png) left no-repeat!important;
+ float: right!important;
+ width: 26px;
+ height: 26px;
+ cursor: pointer;
+}
+.openo-pagination-theme label {
+ padding-top: 6px;
+ vertical-align: middle;
+ margin-right: 20px;
+ margin-top: -1px;
+ float: left;
+ display: inline-block;
+ height: 20px;
+ font: 12px Lucida Grande,Verdana,Arial,Helvetica,sans-serif;
+}
+.openo-pagination li, .openo-pagination ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ float: left;
+}
+dd, dl, dt, li {
+ color: #000;
+}
+.openo-pagination-theme a, .openo-pagination-theme span.current {
+ margin: 0 5px 0 0;
+}
+.openo .openo-disabled, .openo.openo-disabled {
+ border-color: #c3c3c3!important;
+ color: #666!important;
+ opacity: .3;
+ filter: alpha(opacity=30);
+}
+.openo-pagination-theme .prev {
+ background: 0 0;
+ float: left;
+}
+.openo-pagination-theme .current {
+ text-decoration: none!important;
+ float: left;
+ padding-left: 6px;
+ height: 24px;
+ color: #fff;
+ display: inline;
+ border-color: #00adf5;
+ background: #4ad2ff;
+}
+.openo-pagination-theme a, .openo-pagination-theme span {
+ float: left;
+ color: #666;
+ font: 12px Lucida Grande,Verdana,Arial,Helvetica,sans-serif;
+ line-height: 24px;
+ font-weight: 400;
+ text-align: center;
+ border: 1px solid #e0e0e0;
+ text-decoration: none!important;
+ padding: 0 7px;
+ border-radius: 3px;
+ background: #fff;
+}
+.openo-pagination-theme .prev.openo-disabled:before {
+ background: url(../images/page_left_disabled.png) 50% 45% no-repeat;
+}
+.openo-pagination-theme .prev.openo-disabled:before {
+ background: url(../images/page_left_disabled.png) 50% 45% no-repeat;
+}
+.openo-pagination-theme .prev:before {
+ background: url(../images/page_l.png) 50% 45% no-repeat;
+}
+.openo-pagination-theme .next:after, .openo-pagination-theme .prev:before {
+ display: inline-block;
+ content: "";
+ vertical-align: middle;
+ width: 10px;
+ height: 24px;
+}
+.openo-pagination-theme .prev:before {
+ background: url(../images/page_l.png) 50% 45% no-repeat;
+}
+.openo-pagination-theme .next:after, .openo-pagination-theme .prev:before {
+ display: inline-block;
+ content: "";
+ vertical-align: middle;
+ width: 10px;
+ height: 24px;
+}
+pagination ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ float: left;
+}
+.openo-pagination li, .openo-pagination ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ float: left;
+}
+.openoPagination_gototext {
+ background: #FFF;
+ outline: 0;
+ width: 29px;
+ float: left;
+ height: 26px;
+ line-height: 24px;
+ border-radius: 4px;
+ border: 1px solid #c3c3c3;
+ padding: 0 0 0 5px;
+ margin: 0;
+ color: #666;
+ min-width: 50px;
+}
+.openoPagination_gotoimage {
+ width: 29px;
+ height: 26px;
+ line-height: 26px;
+ background-color: #FFF;
+ background-image: url(/portal/themes/default/components/openo/images/openo.png);
+ padding-left: 21px;
+ float: left;
+ margin-left: 5px;
+ border: 1px solid #e0e0e0;
+ border-radius: 4px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ background-position: -184px -181px!important;
+}
+.openo-pagination-theme .ellipse {
+ float: left;
+ margin-left: -8px;
+ margin-right: -4px;
+ background: 0 0;
+ border: none;
+ border-radius: 0;
+ box-shadow: none;
+ font-weight: 700;
+ cursor: default;
+}
+.openo.openo-disabled {
+ border-color: #c3c3c3!important;
+ color: #666!important;
+ opacity: .3;
+ filter: alpha(opacity=30);
+}
+.openo-pagination-theme .prev {
+ background: 0 0;
+ float: left;
+}
+.openo-pagination-theme .current {
+ text-decoration: none!important;
+ float: left;
+ padding-left: 6px;
+ height: 26px;
+ color: #fff;
+ display: inline;
+ /*border-color: #00adf5;
+ background: #4ad2ff;*/
+ border: 1px solid #e0e0e0;
+}
+.openo-pagination-theme .next:after {
+ background: url(../images/page_r.png) 50% 45% no-repeat;
+}
+.openoButton_buttonGroupClass div.openoButton_buttonClass_parent, .openoButton_buttonRightImg {
+ margin-left: 5px;
+}
+
+html, body {
+ height: 99%;
+ width: 98%;
+}
+.cotentBody {
+ padding: 0px 20px 0px 20px;
+}
+
+div.openoButton_buttonClass:hover {
+ border: 1px solid #4ac9ff;
+}
+div.openoButton_button_default:hover .openoButton_buttonCenterText {
+ color: #009ae7;
+}
+.header_lineimg {
+ height: 1px;
+ width: 100%;
+ margin-top: 17px;
+}
+.openo.openo-hide {
+ display: none;
+}
+div.openo-select-popup-container {
+ position: absolute;
+ border: 1px solid #4ac9ff;
+ border-top: none;
+ border-radius: 0 0 4px 4px;
+ max-height: 202px;
+ overflow-y: auto;
+ background-color: #fff;
+ z-index: 880;
+}
+div.openo-select-popup-container>div.openo-select-item {
+ display: block;
+}
+.openo .openo-ellipsis, .openo.openo-ellipsis {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+div.openo-select-popup-container>div.openo-select-item>label {
+ padding-top: 3px;
+ padding-bottom: 3px;
+ line-height: 20px;
+}
+.openo .openo-ellipsis, .openo.openo-ellipsis {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+.openo-select-item label {
+ margin-left: 4px;
+ margin-right: 4px;
+ white-space: nowrap;
+}
+div.openo-select-popup-container>div.openo-select-item.openo-item-selected, div.openo-select-popup-container>div.openo-select-item:hover {
+ background-color: #f1f1f1;
+ color: #008fd6;
+}
+div.openo-select.openo-focus {
+ border: 1px solid #4ac9ff;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ border-bottom-color: #ddd;
+}
+.openo-pagination-theme a:hover {
+ border-color: #4ac9ff;
+ cursor: pointer;
+}
+.SDBtn{
+ background: #fff;
+ color: #333;
+ border: 1px solid #ddd;
+}
+.SDBtn:hover{
+ color: #009ae7;
+ border: 1px solid #4AC9FF
+}
+table tbody tr.even:hover td, table tbody tr.odd:hover td {
+ background-color: #e6fbe0;
+}
+table tr.openoTable_row_selected td {
+ background: #e8f8fe!important;
+ border-bottom: 1px solid #e8e8e8!important;
+}
+.modal-body{
+ padding: 0!important;
+}
+.form-control{
+ height: 26px!important;
+}
+.form-group .control-label {
+ margin-left: 20px;
+}
+
+.form-horizontal .control-label {
+ text-align: left;
+} \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/bootstrap-table.min.css b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/bootstrap-table.min.css
new file mode 100644
index 00000000..d72d0655
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/bootstrap-table.min.css
@@ -0,0 +1 @@
+.fixed-table-container .bs-checkbox,.fixed-table-container .no-records-found{text-align:center}.fixed-table-body thead th .th-inner,.table td,.table th{box-sizing:border-box}.bootstrap-table .table{margin-bottom:0!important;border-bottom:1px solid #ddd;border-collapse:collapse!important;border-radius:1px}.bootstrap-table .table:not(.table-condensed),.bootstrap-table .table:not(.table-condensed)>tbody>tr>td,.bootstrap-table .table:not(.table-condensed)>tbody>tr>th,.bootstrap-table .table:not(.table-condensed)>tfoot>tr>td,.bootstrap-table .table:not(.table-condensed)>tfoot>tr>th,.bootstrap-table .table:not(.table-condensed)>thead>tr>td{padding:8px}.bootstrap-table .table.table-no-bordered>tbody>tr>td,.bootstrap-table .table.table-no-bordered>thead>tr>th{border-right:2px solid transparent}.bootstrap-table .table.table-no-bordered>tbody>tr>td:last-child{border-right:none}.fixed-table-container{position:relative;clear:both;border:1px solid #ddd;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px}.fixed-table-container.table-no-bordered{border:1px solid transparent}.fixed-table-footer,.fixed-table-header{overflow:hidden}.fixed-table-footer{border-top:1px solid #ddd}.fixed-table-body{overflow-x:auto;overflow-y:auto;height:100%}.fixed-table-container table{width:100%}.fixed-table-container thead th{height:0;padding:0;margin:0;border-left:1px solid #ddd}.fixed-table-container thead th:focus{outline:transparent solid 0}.fixed-table-container thead th:first-child{border-left:none;border-top-left-radius:4px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px}.fixed-table-container tbody td .th-inner,.fixed-table-container thead th .th-inner{padding:8px;line-height:24px;vertical-align:top;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fixed-table-container thead th .sortable{cursor:pointer;background-position:right;background-repeat:no-repeat;padding-right:30px}.fixed-table-container thead th .both{background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC')}.fixed-table-container thead th .asc{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==)}.fixed-table-container thead th .desc{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII=)}.fixed-table-container th.detail{width:30px}.fixed-table-container tbody td{border-left:1px solid #ddd}.fixed-table-container tbody tr:first-child td{border-top:none}.fixed-table-container tbody td:first-child{border-left:none}.fixed-table-container tbody .selected td{background-color:#f5f5f5}.fixed-table-container .bs-checkbox .th-inner{padding:8px 0}.fixed-table-container input[type=radio],.fixed-table-container input[type=checkbox]{margin:0 auto!important}.fixed-table-pagination .pagination-detail,.fixed-table-pagination div.pagination{margin-top:10px;margin-bottom:10px}.fixed-table-pagination div.pagination .pagination{margin:0}.fixed-table-pagination .pagination a{padding:6px 12px;line-height:1.428571429}.fixed-table-pagination .pagination-info{line-height:34px;margin-right:5px}.fixed-table-pagination .btn-group{position:relative;display:inline-block;vertical-align:middle}.fixed-table-pagination .dropup .dropdown-menu{margin-bottom:0}.fixed-table-pagination .page-list{display:inline-block}.fixed-table-toolbar .columns-left{margin-right:5px}.fixed-table-toolbar .columns-right{margin-left:5px}.fixed-table-toolbar .columns label{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429}.fixed-table-toolbar .bs-bars,.fixed-table-toolbar .columns,.fixed-table-toolbar .search{position:relative;margin-top:10px;margin-bottom:10px;line-height:34px}.fixed-table-pagination li.disabled a{pointer-events:none;cursor:default}.fixed-table-loading{display:none;position:absolute;top:42px;right:0;bottom:0;left:0;z-index:99;background-color:#fff;text-align:center}.fixed-table-body .card-view .title{font-weight:700;display:inline-block;min-width:30%;text-align:left!important}.table td,.table th{vertical-align:middle}.fixed-table-toolbar .dropdown-menu{text-align:left;max-height:300px;overflow:auto}.fixed-table-toolbar .btn-group>.btn-group{display:inline-block;margin-left:-1px!important}.fixed-table-toolbar .btn-group>.btn-group>.btn{border-radius:0}.fixed-table-toolbar .btn-group>.btn-group:first-child>.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.fixed-table-toolbar .btn-group>.btn-group:last-child>.btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.bootstrap-table .table>thead>tr>th{vertical-align:bottom;border-bottom:1px solid #ddd}.bootstrap-table .table thead>tr>th{padding:0;margin:0}.bootstrap-table .fixed-table-footer tbody>tr>td{padding:0!important}.bootstrap-table .fixed-table-footer .table{border-bottom:none;border-radius:0;padding:0!important}.pull-right .dropdown-menu{right:0;left:auto}p.fixed-table-scroll-inner{width:100%;height:200px}div.fixed-table-scroll-outer{top:0;left:0;visibility:hidden;width:200px;height:150px;overflow:hidden} \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/bootstrap.min.css b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/bootstrap.min.css
new file mode 100644
index 00000000..679272d2
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/css/bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v3.1.1 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none!important;color:#000!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}input[type=date]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:400;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle=buttons]>.btn>input[type=radio],[data-toggle=buttons]>.btn>input[type=checkbox]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{float:none;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#428bca;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:gray}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5) 0),color-stop(rgba(0,0,0,.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001) 0),color-stop(rgba(0,0,0,.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}@media print{.hidden-print{display:none!important}} \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/gsolcmmain.html b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/gsolcmmain.html
new file mode 100644
index 00000000..b878e10e
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/gsolcmmain.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html>
+<!--
+
+ Copyright 2016, Huawei Technologies Co., Ltd.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Lifecycle Manager</title>
+ <link href="css/bootstrap.min.css" rel="stylesheet" />
+ <link href="css/VMMain.css" rel="stylesheet" />
+ <link href="css/bootstrap-table.min.css" rel="stylesheet" />
+ <script type="text/javascript" src="js/jquery-1.11.2.min.js"></script>
+ <script type="text/javascript" src="js/bootstrap.min.js"></script>
+ <script type="text/javascript" src="js/rest.js"></script>
+ <script type="text/javascript" src="js/bootstrap-table.min.js"></script>
+ <script type="text/javascript" src="js/gsolcm.js"></script>
+ <script type="text/javascript">
+ $(document).ready(function() {
+ var jsondata = [];
+ //jsondata = loadNeData();
+ $('#sai').bootstrapTable({
+ //Assigning data to table
+ data: jsondata
+ });
+ new lcmHandler();
+ });
+
+ function operateFormatter(value, row, index) {
+ return [
+ '<img class="siteDeleteImg" src="images/delete.png" href="javascript:void(0)" style="cursor: pointer" name="title" title="Delete" />'
+ ].join('');
+
+ }
+ window.operateEvents = {
+ 'click .siteDeleteImg': function (e, value, row, index) {
+ // TO DO ajex call for delete
+ var result = deleteNe(row.id, row);
+ }
+ };
+
+ </script>
+</head>
+<body id="open_base_site_cotentBody" class="cotentBody ng-scope">
+ <div class="container-fluid ms-controller">
+ <h3> Life Cycle Manager </h3>
+
+ <div class="uploadBtn">
+ <div id="open_base_tpL_userHeader" class="userHeader">
+ <div id="open_base_tpL_buttonGroup" class="openoButton_buttonGroupClass">
+ <div class="openo openo-widget-button openoButton_buttonClass_parent ng-isolate-scope openoButton_buttonClass defaultbutton openoButton_button_default" tabindex="0" id="false" text="res.brApp_ui_res_btn_create" icon-url="./images/add.png" cls="defaultbutton" click="clickAdd" style="display: inline-block; padding-left: 0px; padding-right: 0px;">
+ <div class="openoButton_buttonInnerClass openo-corner-all openoButton_Image" id="false_button">
+ <span class="openo-widget-button-image openoButton_buttonLeftImg" style="background-image: url(images/add.png);"></span>
+ <span class="openoButton_buttonCenterText openoButton_buttonCenterTextFont">Create</span>
+ <span class="openo-widget-button-image openoButton_buttonImgDefault"></span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="row-fluid" data-name="table_zone">
+ <div id="ict_virtualApplication_table_div">
+ <div>
+ <div class="top">
+ <table id="sai" data-pagination="true" data-page-size="5" data-pagination-first-text="First" data-pagination-pre-text="Previous" data-pagination-next-text="Next" data-pagination-last-text="Last">
+ <thead id="soverlayTable_thead" class="openo-table-thead">
+ <tr class="active">
+ <!--<th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayName" data-sortable="true">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayName_sorticon" class="openo-table-th-sorticon overflow_elip openoTable_sortable leftHeaderAlign openo-table-disable-element">Service ID
+ </span>
+ </div>
+ </th>-->
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayDesc" data-sortable="true">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayDesc_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Service Name
+ </span></div></th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayThincCPE" data-sortable="true">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayThincCPE_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Template Name
+ </span></div></th>
+ <!--<th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayPortVlanID" data-sortable="true">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayPortVlanID_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Service Type
+ </span></div></th> -->
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayDCName" data-sortable="true">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayDCName_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Service Instruction </span></div></th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayVPC" data-sortable="true">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayVPC_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Create Time
+ </span>
+ </div>
+ </th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayVPCCIDR" data-sortable="true">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayVPCCIDR_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Creator
+ </span>
+ </div>
+ </th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayOperation" align="center" data-formatter = "operateFormatter" data-events="operateEvents">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="portAction_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Action</span>
+ </div>
+ </th>
+ </tr></thead>
+
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- <div id="tpListopenotable_pagination_wrapper" class="openo-table-pagination-wrapper" style="display: block;"><div class="pagination-container openo-pagination-theme openo-pagination"><div class="openoPagination_openoPaginationLengthOptions" id="tpListopenotable_wrapper_div"><input readonly="true" class="openo-pagination-select openopaginationselect" value="" id="tpListopenotable_wrapper_input" actualval="20" style="width: 32px;"><span class="openo-pagination-selectspan openopaginationselectspan" id="tpListopenotable_wrapper_trigger"></span></div><label style="display: block;float:left;">Total records: 23</label><li class="active"><span class="current prev openo-disabled" id="tpListopenotable_wrapper_prev">&nbsp;</span></li><ul><li class="active"><span class="current" id="tpListopenotable_wrapper_page_link_1">1</span></li><li><a class="page-link" id="tpListopenotable_wrapper_page_link_2">2</a></li><li><a class="page-link" id="tpListopenotable_wrapper_page_link_3">3</a></li><li><a class="page-link next" id="tpListopenotable_wrapper_next">&nbsp;</a></li></ul></div></div> -->
+
+ <div id="vmAppDialog" class="modal fade" tabindex="-1" role="dialog"
+ aria-labelledby="myModalLabel" aria-hidden="false">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal"
+ aria-hidden="true">×
+ </button>
+ <h4 class="modal-title" id="myModalLabel">
+ <span>Create</span>
+ </h4>
+ </div>
+ <form class="form-horizontal" role="form" id="neForm">
+ <div id="wizard">
+ <div class="modal-body">
+ <ul class="nav nav-pills nav-justified vmapp-margin">
+
+ </ul>
+ <div class="tab-content">
+ <ul class="nav nav-tabs">
+ <li class="active"><a id= "basicInfoTab" href="#basicTab" data-toggle="tab">Basic Info</a></li>
+ <li ><a id="parameterTabHeader" href="#parameterTab" data-toggle="tab">Template Parameters</a></li>
+ </ul>
+ <div id="myTabContent" class="tab-content" >
+ <div class="tab-pane active" id="basicTab">
+ <div class="form-group" ms-class="has-error:vmAppDialog.name==''">
+ <label class="col-sm-3 control-label">
+ <span>Service Name</span>
+ <span class="required">*</span>
+ </label>
+ <div class="col-sm-7">
+ <input type="text" id="svcName" name="svcName" class="form-control" placeholder="Service Name"/>
+ </div>
+ </div>
+ <div class="form-group">
+ <label class="col-sm-3 control-label">
+ <span>Service Description</span>&nbsp;&nbsp;&nbsp;
+ </label>
+ <div class="col-sm-7">
+ <input type="text" id="svcDesc" name="svcDesc" class="form-control" placeholder="Service Description"/>
+ </div>
+ </div>
+ <div class="form-group" ms-class="has-error:vmAppDialog.name==''">
+ <label class="col-sm-3 control-label">
+ <span>Service Template</span>
+ <span class="required">*</span>
+ </label>
+ <div class="col-sm-7">
+ <select class="form-control" style ="padding-top: 0px;padding-bottom: 0px;" id="svcTempl"
+ name="svcTempl">
+ <option value="1.1">1.1</option>
+ <option value="1.2">1.2</option>
+ </select>
+ </div>
+ </div>
+ </div>
+ <div class="tab-pane" id="parameterTab">
+
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn SDBtn" data-dismiss="modal" aria-hidden="true" id="createNS">
+ <span id="nfv-virtualApplication-iui-text-cancelBtn">OK</span>
+ </button>
+ <button type="button" class="btn button-previous SDBtn">
+ <span id="nfv-virtualApplication-iui-text-previousBtn">Cancel</span>
+ </button>
+
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="filterTpLogicalType_select_popupcontainer" class="openo openo-select-popup-container openo-hide" style="width: 155px; max-height: 130px; left: 628px; top: 104px; z-index: 1761;">
+ <div class="openo-select-item openo-ellipsis " id="filterTpLogicalType_openo-select-id_0">
+ <label class="openo-ellipsis openo-select-blank-item" style="width: 100%; display: block; height: 20px;"></label>
+ </div>
+ <div class="openo-select-item openo-ellipsis " id="filterTpLogicalType_openo-select-id_1">
+ <label class="openo-ellipsis " style="width: 100%; display: block; height: 20px;">ETH</label>
+ </div>
+ <div class="openo-select-item openo-ellipsis " id="filterTpLogicalType_openo-select-id_2">
+ <label class="openo-ellipsis " style="width: 100%; display: block; height: 20px;" title="POS">POS</label>
+ </div>
+ <div class="openo-select-item openo-ellipsis " id="filterTpLogicalType_openo-select-id_3">
+ <label class="openo-ellipsis " style="width: 100%; display: block; height: 20px;">Trunk</label>
+ </div>
+ <div class="openo-select-item openo-ellipsis " id="filterTpLogicalType_openo-select-id_4">
+ <label class="openo-ellipsis " style="width: 100%; display: block; height: 20px;">Loopback</label>
+ </div>
+ </div>
+
+
+</body>
+</html>
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/License.txt b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/License.txt
new file mode 100644
index 00000000..8e698ecb
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/License.txt
@@ -0,0 +1,362 @@
+THIS LICENSE FILE CONTAINS THE LICENSE APPLICABLE DEPENDING ON THE TYPE OF CONTRIBUTIONS.
+
+APACHE LICENSE 2 IS APPLICABLE FOR SOURCE CODE, CREATIVE COMMONS ATTRIBUTION 4.0 INTERNATIONAL FOR DOCUMENTATION
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+Apache License Version 2.0, January 2004 http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Attribution 4.0 International
+
+https://creativecommons.org/licenses/by/4.0/legalcode
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an "as-is" basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More_considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+Creative Commons Attribution 4.0 International Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+ c. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+ d. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+ e. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+ f. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+ g. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+ h. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+ i. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+ j. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+ k. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+Section 2 -- Scope.
+
+ a. License grant.
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+ a. reproduce and Share the Licensed Material, in whole or
+ in part; and
+ b. produce, reproduce, and Share Adapted Material.
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+ 5. Downstream recipients.
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+ b. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+ b. Other rights.
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties.
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the following conditions.
+
+ a. Attribution.
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+ ii. a copyright notice;
+ iii. a notice that refers to this Public License;
+ iv. a notice that refers to the disclaimer of
+ warranties;
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+ 4. If You Share Adapted Material You produce, the Adapter's
+ License You apply must not prevent recipients of the Adapted
+ Material from complying with this Public License.
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database;
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material; and
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+ 2. upon express reinstatement by the Licensor.
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the "Licensor." The text of the Creative Commons public licenses is dedicated to the public domain under the CC0 Public Domain Dedication. Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.
+
+Creative Commons may be contacted at creativecommons.org. \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/add.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/add.png
new file mode 100644
index 00000000..d1f82993
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/add.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/arrow-down-enable.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/arrow-down-enable.png
new file mode 100644
index 00000000..dc8ddbe6
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/arrow-down-enable.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/collapse_arrow.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/collapse_arrow.png
new file mode 100644
index 00000000..8830741a
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/collapse_arrow.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/delete.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/delete.png
new file mode 100644
index 00000000..737f8797
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/delete.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/edit.bak.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/edit.bak.png
new file mode 100644
index 00000000..68d76257
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/edit.bak.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/edit.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/edit.png
new file mode 100644
index 00000000..68d76257
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/edit.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/expand_arrow.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/expand_arrow.png
new file mode 100644
index 00000000..f8935e1f
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/expand_arrow.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/ideo_default_select.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/ideo_default_select.png
new file mode 100644
index 00000000..50c3a251
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/ideo_default_select.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/import.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/import.png
new file mode 100644
index 00000000..8cfc5256
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/import.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/line.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/line.png
new file mode 100644
index 00000000..9d340a8d
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/line.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/loading-spinner-grey.gif b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/loading-spinner-grey.gif
new file mode 100644
index 00000000..6d614d3d
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/loading-spinner-grey.gif
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/openo.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/openo.png
new file mode 100644
index 00000000..328b7353
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/openo.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_l.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_l.png
new file mode 100644
index 00000000..e8b98c7c
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_l.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_left_disabled.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_left_disabled.png
new file mode 100644
index 00000000..f72a90bd
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_left_disabled.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_r.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_r.png
new file mode 100644
index 00000000..2e637eee
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/page_r.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/reset.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/reset.png
new file mode 100644
index 00000000..d57e9b39
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/reset.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_asc.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_asc.png
new file mode 100644
index 00000000..a88d7975
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_asc.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_both.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_both.png
new file mode 100644
index 00000000..18670406
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_both.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_desc.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_desc.png
new file mode 100644
index 00000000..def071ed
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/images/sort_desc.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/bootstrap-table.min.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/bootstrap-table.min.js
new file mode 100644
index 00000000..b6602c3f
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/bootstrap-table.min.js
@@ -0,0 +1,8 @@
+/*
+* bootstrap-table - v1.11.0 - 2016-07-02
+* https://github.com/wenzhixin/bootstrap-table
+* Copyright 2016 zhixin wen
+* Licensed MIT License
+*/
+!function(a){"use strict";var b=null,c=function(a){var b=arguments,c=!0,d=1;return a=a.replace(/%s/g,function(){var a=b[d++];return"undefined"==typeof a?(c=!1,""):a}),c?a:""},d=function(b,c,d,e){var f="";return a.each(b,function(a,b){return b[c]===e?(f=b[d],!1):!0}),f},e=function(b,c){var d=-1;return a.each(b,function(a,b){return b.field===c?(d=a,!1):!0}),d},f=function(b){var c,d,e,f=0,g=[];for(c=0;c<b[0].length;c++)f+=b[0][c].colspan||1;for(c=0;c<b.length;c++)for(g[c]=[],d=0;f>d;d++)g[c][d]=!1;for(c=0;c<b.length;c++)for(d=0;d<b[c].length;d++){var h=b[c][d],i=h.rowspan||1,j=h.colspan||1,k=a.inArray(!1,g[c]);for(1===j&&(h.fieldIndex=k,"undefined"==typeof h.field&&(h.field=k)),e=0;i>e;e++)g[c+e][k]=!0;for(e=0;j>e;e++)g[c][k+e]=!0}},g=function(){if(null===b){var c,d,e=a("<p/>").addClass("fixed-table-scroll-inner"),f=a("<div/>").addClass("fixed-table-scroll-outer");f.append(e),a("body").append(f),c=e[0].offsetWidth,f.css("overflow","scroll"),d=e[0].offsetWidth,c===d&&(d=f[0].clientWidth),f.remove(),b=c-d}return b},h=function(b,d,e,f){var g=d;if("string"==typeof d){var h=d.split(".");h.length>1?(g=window,a.each(h,function(a,b){g=g[b]})):g=window[d]}return"object"==typeof g?g:"function"==typeof g?g.apply(b,e):!g&&"string"==typeof d&&c.apply(this,[d].concat(e))?c.apply(this,[d].concat(e)):f},i=function(b,c,d){var e=Object.getOwnPropertyNames(b),f=Object.getOwnPropertyNames(c),g="";if(d&&e.length!==f.length)return!1;for(var h=0;h<e.length;h++)if(g=e[h],a.inArray(g,f)>-1&&b[g]!==c[g])return!1;return!0},j=function(a){return"string"==typeof a?a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;").replace(/`/g,"&#x60;"):a},k=function(b){var c=0;return b.children().each(function(){c<a(this).outerHeight(!0)&&(c=a(this).outerHeight(!0))}),c},l=function(a){for(var b in a){var c=b.split(/(?=[A-Z])/).join("-").toLowerCase();c!==b&&(a[c]=a[b],delete a[b])}return a},m=function(a,b,c){var d=a;if("string"!=typeof b||a.hasOwnProperty(b))return c?j(a[b]):a[b];var e=b.split(".");for(var f in e)d=d&&d[e[f]];return c?j(d):d},n=function(){return!!(navigator.userAgent.indexOf("MSIE ")>0||navigator.userAgent.match(/Trident.*rv\:11\./))},o=function(){Object.keys||(Object.keys=function(){var a=Object.prototype.hasOwnProperty,b=!{toString:null}.propertyIsEnumerable("toString"),c=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],d=c.length;return function(e){if("object"!=typeof e&&("function"!=typeof e||null===e))throw new TypeError("Object.keys called on non-object");var f,g,h=[];for(f in e)a.call(e,f)&&h.push(f);if(b)for(g=0;d>g;g++)a.call(e,c[g])&&h.push(c[g]);return h}}())},p=function(b,c){this.options=c,this.$el=a(b),this.$el_=this.$el.clone(),this.timeoutId_=0,this.timeoutFooter_=0,this.init()};p.DEFAULTS={classes:"table table-hover",locale:void 0,height:void 0,undefinedText:"-",sortName:void 0,sortOrder:"asc",sortStable:!1,striped:!1,columns:[[]],data:[],dataField:"rows",method:"get",url:void 0,ajax:void 0,cache:!0,contentType:"application/json",dataType:"json",ajaxOptions:{},queryParams:function(a){return a},queryParamsType:"limit",responseHandler:function(a){return a},pagination:!1,onlyInfoPagination:!1,sidePagination:"client",totalRows:0,pageNumber:1,pageSize:10,pageList:[10,25,50,100],paginationHAlign:"right",paginationVAlign:"bottom",paginationDetailHAlign:"left",paginationPreText:"&lsaquo;",paginationNextText:"&rsaquo;",search:!1,searchOnEnterKey:!1,strictSearch:!1,searchAlign:"right",selectItemName:"btSelectItem",showHeader:!0,showFooter:!1,showColumns:!1,showPaginationSwitch:!1,showRefresh:!1,showToggle:!1,buttonsAlign:"right",smartDisplay:!0,escape:!1,minimumCountColumns:1,idField:void 0,uniqueId:void 0,cardView:!1,detailView:!1,detailFormatter:function(){return""},trimOnSearch:!0,clickToSelect:!1,singleSelect:!1,toolbar:void 0,toolbarAlign:"left",checkboxHeader:!0,sortable:!0,silentSort:!0,maintainSelected:!1,searchTimeOut:500,searchText:"",iconSize:void 0,buttonsClass:"default",iconsPrefix:"glyphicon",icons:{paginationSwitchDown:"glyphicon-collapse-down icon-chevron-down",paginationSwitchUp:"glyphicon-collapse-up icon-chevron-up",refresh:"glyphicon-refresh icon-refresh",toggle:"glyphicon-list-alt icon-list-alt",columns:"glyphicon-th icon-th",detailOpen:"glyphicon-plus icon-plus",detailClose:"glyphicon-minus icon-minus"},customSearch:a.noop,customSort:a.noop,rowStyle:function(){return{}},rowAttributes:function(){return{}},footerStyle:function(){return{}},onAll:function(){return!1},onClickCell:function(){return!1},onDblClickCell:function(){return!1},onClickRow:function(){return!1},onDblClickRow:function(){return!1},onSort:function(){return!1},onCheck:function(){return!1},onUncheck:function(){return!1},onCheckAll:function(){return!1},onUncheckAll:function(){return!1},onCheckSome:function(){return!1},onUncheckSome:function(){return!1},onLoadSuccess:function(){return!1},onLoadError:function(){return!1},onColumnSwitch:function(){return!1},onPageChange:function(){return!1},onSearch:function(){return!1},onToggle:function(){return!1},onPreBody:function(){return!1},onPostBody:function(){return!1},onPostHeader:function(){return!1},onExpandRow:function(){return!1},onCollapseRow:function(){return!1},onRefreshOptions:function(){return!1},onRefresh:function(){return!1},onResetView:function(){return!1}},p.LOCALES={},p.LOCALES["en-US"]=p.LOCALES.en={formatLoadingMessage:function(){return"Loading, please wait..."},formatRecordsPerPage:function(a){return c("%s rows per page",a)},formatShowingRows:function(a,b,d){return c("Showing %s to %s of %s rows",a,b,d)},formatDetailPagination:function(a){return c("Showing %s rows",a)},formatSearch:function(){return"Search"},formatNoMatches:function(){return"No matching records found"},formatPaginationSwitch:function(){return"Hide/Show pagination"},formatRefresh:function(){return"Refresh"},formatToggle:function(){return"Toggle"},formatColumns:function(){return"Columns"},formatAllRows:function(){return"All"}},a.extend(p.DEFAULTS,p.LOCALES["en-US"]),p.COLUMN_DEFAULTS={radio:!1,checkbox:!1,checkboxEnabled:!0,field:void 0,title:void 0,titleTooltip:void 0,"class":void 0,align:void 0,halign:void 0,falign:void 0,valign:void 0,width:void 0,sortable:!1,order:"asc",visible:!0,switchable:!0,clickToSelect:!0,formatter:void 0,footerFormatter:void 0,events:void 0,sorter:void 0,sortName:void 0,cellStyle:void 0,searchable:!0,searchFormatter:!0,cardVisible:!0},p.EVENTS={"all.bs.table":"onAll","click-cell.bs.table":"onClickCell","dbl-click-cell.bs.table":"onDblClickCell","click-row.bs.table":"onClickRow","dbl-click-row.bs.table":"onDblClickRow","sort.bs.table":"onSort","check.bs.table":"onCheck","uncheck.bs.table":"onUncheck","check-all.bs.table":"onCheckAll","uncheck-all.bs.table":"onUncheckAll","check-some.bs.table":"onCheckSome","uncheck-some.bs.table":"onUncheckSome","load-success.bs.table":"onLoadSuccess","load-error.bs.table":"onLoadError","column-switch.bs.table":"onColumnSwitch","page-change.bs.table":"onPageChange","search.bs.table":"onSearch","toggle.bs.table":"onToggle","pre-body.bs.table":"onPreBody","post-body.bs.table":"onPostBody","post-header.bs.table":"onPostHeader","expand-row.bs.table":"onExpandRow","collapse-row.bs.table":"onCollapseRow","refresh-options.bs.table":"onRefreshOptions","reset-view.bs.table":"onResetView","refresh.bs.table":"onRefresh"},p.prototype.init=function(){this.initLocale(),this.initContainer(),this.initTable(),this.initHeader(),this.initData(),this.initFooter(),this.initToolbar(),this.initPagination(),this.initBody(),this.initSearchText(),this.initServer()},p.prototype.initLocale=function(){if(this.options.locale){var b=this.options.locale.split(/-|_/);b[0].toLowerCase(),b[1]&&b[1].toUpperCase(),a.fn.bootstrapTable.locales[this.options.locale]?a.extend(this.options,a.fn.bootstrapTable.locales[this.options.locale]):a.fn.bootstrapTable.locales[b.join("-")]?a.extend(this.options,a.fn.bootstrapTable.locales[b.join("-")]):a.fn.bootstrapTable.locales[b[0]]&&a.extend(this.options,a.fn.bootstrapTable.locales[b[0]])}},p.prototype.initContainer=function(){this.$container=a(['<div class="bootstrap-table">','<div class="fixed-table-toolbar"></div>',"top"===this.options.paginationVAlign||"both"===this.options.paginationVAlign?'<div class="fixed-table-pagination" style="clear: both;"></div>':"",'<div class="fixed-table-container">','<div class="fixed-table-header"><table></table></div>','<div class="fixed-table-body">','<div class="fixed-table-loading">',this.options.formatLoadingMessage(),"</div>","</div>",'<div class="fixed-table-footer"><table><tr></tr></table></div>',"bottom"===this.options.paginationVAlign||"both"===this.options.paginationVAlign?'<div class="fixed-table-pagination"></div>':"","</div>","</div>"].join("")),this.$container.insertAfter(this.$el),this.$tableContainer=this.$container.find(".fixed-table-container"),this.$tableHeader=this.$container.find(".fixed-table-header"),this.$tableBody=this.$container.find(".fixed-table-body"),this.$tableLoading=this.$container.find(".fixed-table-loading"),this.$tableFooter=this.$container.find(".fixed-table-footer"),this.$toolbar=this.$container.find(".fixed-table-toolbar"),this.$pagination=this.$container.find(".fixed-table-pagination"),this.$tableBody.append(this.$el),this.$container.after('<div class="clearfix"></div>'),this.$el.addClass(this.options.classes),this.options.striped&&this.$el.addClass("table-striped"),-1!==a.inArray("table-no-bordered",this.options.classes.split(" "))&&this.$tableContainer.addClass("table-no-bordered")},p.prototype.initTable=function(){var b=this,c=[],d=[];if(this.$header=this.$el.find(">thead"),this.$header.length||(this.$header=a("<thead></thead>").appendTo(this.$el)),this.$header.find("tr").each(function(){var b=[];a(this).find("th").each(function(){"undefined"!=typeof a(this).data("field")&&a(this).data("field",a(this).data("field")+""),b.push(a.extend({},{title:a(this).html(),"class":a(this).attr("class"),titleTooltip:a(this).attr("title"),rowspan:a(this).attr("rowspan")?+a(this).attr("rowspan"):void 0,colspan:a(this).attr("colspan")?+a(this).attr("colspan"):void 0},a(this).data()))}),c.push(b)}),a.isArray(this.options.columns[0])||(this.options.columns=[this.options.columns]),this.options.columns=a.extend(!0,[],c,this.options.columns),this.columns=[],f(this.options.columns),a.each(this.options.columns,function(c,d){a.each(d,function(d,e){e=a.extend({},p.COLUMN_DEFAULTS,e),"undefined"!=typeof e.fieldIndex&&(b.columns[e.fieldIndex]=e),b.options.columns[c][d]=e})}),!this.options.data.length){var e=[];this.$el.find(">tbody>tr").each(function(c){var f={};f._id=a(this).attr("id"),f._class=a(this).attr("class"),f._data=l(a(this).data()),a(this).find(">td").each(function(d){for(var g,h,i=a(this),j=+i.attr("colspan")||1,k=+i.attr("rowspan")||1;e[c]&&e[c][d];d++);for(g=d;d+j>g;g++)for(h=c;c+k>h;h++)e[h]||(e[h]=[]),e[h][g]=!0;var m=b.columns[d].field;f[m]=a(this).html(),f["_"+m+"_id"]=a(this).attr("id"),f["_"+m+"_class"]=a(this).attr("class"),f["_"+m+"_rowspan"]=a(this).attr("rowspan"),f["_"+m+"_colspan"]=a(this).attr("colspan"),f["_"+m+"_title"]=a(this).attr("title"),f["_"+m+"_data"]=l(a(this).data())}),d.push(f)}),this.options.data=d,d.length&&(this.fromHtml=!0)}},p.prototype.initHeader=function(){var b=this,d={},e=[];this.header={fields:[],styles:[],classes:[],formatters:[],events:[],sorters:[],sortNames:[],cellStyles:[],searchables:[]},a.each(this.options.columns,function(f,g){e.push("<tr>"),0===f&&!b.options.cardView&&b.options.detailView&&e.push(c('<th class="detail" rowspan="%s"><div class="fht-cell"></div></th>',b.options.columns.length)),a.each(g,function(a,f){var g="",h="",i="",j="",k=c(' class="%s"',f["class"]),l=(b.options.sortOrder||f.order,"px"),m=f.width;if(void 0===f.width||b.options.cardView||"string"==typeof f.width&&-1!==f.width.indexOf("%")&&(l="%"),f.width&&"string"==typeof f.width&&(m=f.width.replace("%","").replace("px","")),h=c("text-align: %s; ",f.halign?f.halign:f.align),i=c("text-align: %s; ",f.align),j=c("vertical-align: %s; ",f.valign),j+=c("width: %s; ",!f.checkbox&&!f.radio||m?m?m+l:void 0:"36px"),"undefined"!=typeof f.fieldIndex){if(b.header.fields[f.fieldIndex]=f.field,b.header.styles[f.fieldIndex]=i+j,b.header.classes[f.fieldIndex]=k,b.header.formatters[f.fieldIndex]=f.formatter,b.header.events[f.fieldIndex]=f.events,b.header.sorters[f.fieldIndex]=f.sorter,b.header.sortNames[f.fieldIndex]=f.sortName,b.header.cellStyles[f.fieldIndex]=f.cellStyle,b.header.searchables[f.fieldIndex]=f.searchable,!f.visible)return;if(b.options.cardView&&!f.cardVisible)return;d[f.field]=f}e.push("<th"+c(' title="%s"',f.titleTooltip),f.checkbox||f.radio?c(' class="bs-checkbox %s"',f["class"]||""):k,c(' style="%s"',h+j),c(' rowspan="%s"',f.rowspan),c(' colspan="%s"',f.colspan),c(' data-field="%s"',f.field),"tabindex='0'",">"),e.push(c('<div class="th-inner %s">',b.options.sortable&&f.sortable?"sortable both":"")),g=f.title,f.checkbox&&(!b.options.singleSelect&&b.options.checkboxHeader&&(g='<input name="btSelectAll" type="checkbox" />'),b.header.stateField=f.field),f.radio&&(g="",b.header.stateField=f.field,b.options.singleSelect=!0),e.push(g),e.push("</div>"),e.push('<div class="fht-cell"></div>'),e.push("</div>"),e.push("</th>")}),e.push("</tr>")}),this.$header.html(e.join("")),this.$header.find("th[data-field]").each(function(){a(this).data(d[a(this).data("field")])}),this.$container.off("click",".th-inner").on("click",".th-inner",function(c){var d=a(this);return b.options.detailView&&d.closest(".bootstrap-table")[0]!==b.$container[0]?!1:void(b.options.sortable&&d.parent().data().sortable&&b.onSort(c))}),this.$header.children().children().off("keypress").on("keypress",function(c){if(b.options.sortable&&a(this).data().sortable){var d=c.keyCode||c.which;13==d&&b.onSort(c)}}),a(window).off("resize.bootstrap-table"),!this.options.showHeader||this.options.cardView?(this.$header.hide(),this.$tableHeader.hide(),this.$tableLoading.css("top",0)):(this.$header.show(),this.$tableHeader.show(),this.$tableLoading.css("top",this.$header.outerHeight()+1),this.getCaret(),a(window).on("resize.bootstrap-table",a.proxy(this.resetWidth,this))),this.$selectAll=this.$header.find('[name="btSelectAll"]'),this.$selectAll.off("click").on("click",function(){var c=a(this).prop("checked");b[c?"checkAll":"uncheckAll"](),b.updateSelected()})},p.prototype.initFooter=function(){!this.options.showFooter||this.options.cardView?this.$tableFooter.hide():this.$tableFooter.show()},p.prototype.initData=function(a,b){this.data="append"===b?this.data.concat(a):"prepend"===b?[].concat(a).concat(this.data):a||this.options.data,this.options.data="append"===b?this.options.data.concat(a):"prepend"===b?[].concat(a).concat(this.options.data):this.data,"server"!==this.options.sidePagination&&this.initSort()},p.prototype.initSort=function(){var b=this,c=this.options.sortName,d="desc"===this.options.sortOrder?-1:1,e=a.inArray(this.options.sortName,this.header.fields);return this.options.customSort!==a.noop?void this.options.customSort.apply(this,[this.options.sortName,this.options.sortOrder]):void(-1!==e&&(this.options.sortStable&&a.each(this.data,function(a,b){b.hasOwnProperty("_position")||(b._position=a)}),this.data.sort(function(f,g){b.header.sortNames[e]&&(c=b.header.sortNames[e]);var i=m(f,c,b.options.escape),j=m(g,c,b.options.escape),k=h(b.header,b.header.sorters[e],[i,j]);return void 0!==k?d*k:((void 0===i||null===i)&&(i=""),(void 0===j||null===j)&&(j=""),b.options.sortStable&&i===j&&(i=f._position,j=g._position),a.isNumeric(i)&&a.isNumeric(j)?(i=parseFloat(i),j=parseFloat(j),j>i?-1*d:d):i===j?0:("string"!=typeof i&&(i=i.toString()),-1===i.localeCompare(j)?-1*d:d))})))},p.prototype.onSort=function(b){var c="keypress"===b.type?a(b.currentTarget):a(b.currentTarget).parent(),d=this.$header.find("th").eq(c.index());return this.$header.add(this.$header_).find("span.order").remove(),this.options.sortName===c.data("field")?this.options.sortOrder="asc"===this.options.sortOrder?"desc":"asc":(this.options.sortName=c.data("field"),this.options.sortOrder="asc"===c.data("order")?"desc":"asc"),this.trigger("sort",this.options.sortName,this.options.sortOrder),c.add(d).data("order",this.options.sortOrder),this.getCaret(),"server"===this.options.sidePagination?void this.initServer(this.options.silentSort):(this.initSort(),void this.initBody())},p.prototype.initToolbar=function(){var b,d,e=this,f=[],g=0,i=0;this.$toolbar.find(".bs-bars").children().length&&a("body").append(a(this.options.toolbar)),this.$toolbar.html(""),("string"==typeof this.options.toolbar||"object"==typeof this.options.toolbar)&&a(c('<div class="bs-bars pull-%s"></div>',this.options.toolbarAlign)).appendTo(this.$toolbar).append(a(this.options.toolbar)),f=[c('<div class="columns columns-%s btn-group pull-%s">',this.options.buttonsAlign,this.options.buttonsAlign)],"string"==typeof this.options.icons&&(this.options.icons=h(null,this.options.icons)),this.options.showPaginationSwitch&&f.push(c('<button class="btn'+c(" btn-%s",this.options.buttonsClass)+c(" btn-%s",this.options.iconSize)+'" type="button" name="paginationSwitch" title="%s">',this.options.formatPaginationSwitch()),c('<i class="%s %s"></i>',this.options.iconsPrefix,this.options.icons.paginationSwitchDown),"</button>"),this.options.showRefresh&&f.push(c('<button class="btn'+c(" btn-%s",this.options.buttonsClass)+c(" btn-%s",this.options.iconSize)+'" type="button" name="refresh" title="%s">',this.options.formatRefresh()),c('<i class="%s %s"></i>',this.options.iconsPrefix,this.options.icons.refresh),"</button>"),this.options.showToggle&&f.push(c('<button class="btn'+c(" btn-%s",this.options.buttonsClass)+c(" btn-%s",this.options.iconSize)+'" type="button" name="toggle" title="%s">',this.options.formatToggle()),c('<i class="%s %s"></i>',this.options.iconsPrefix,this.options.icons.toggle),"</button>"),this.options.showColumns&&(f.push(c('<div class="keep-open btn-group" title="%s">',this.options.formatColumns()),'<button type="button" class="btn'+c(" btn-%s",this.options.buttonsClass)+c(" btn-%s",this.options.iconSize)+' dropdown-toggle" data-toggle="dropdown">',c('<i class="%s %s"></i>',this.options.iconsPrefix,this.options.icons.columns),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">'),a.each(this.columns,function(a,b){if(!(b.radio||b.checkbox||e.options.cardView&&!b.cardVisible)){var d=b.visible?' checked="checked"':"";b.switchable&&(f.push(c('<li><label><input type="checkbox" data-field="%s" value="%s"%s> %s</label></li>',b.field,a,d,b.title)),i++)}}),f.push("</ul>","</div>")),f.push("</div>"),(this.showToolbar||f.length>2)&&this.$toolbar.append(f.join("")),this.options.showPaginationSwitch&&this.$toolbar.find('button[name="paginationSwitch"]').off("click").on("click",a.proxy(this.togglePagination,this)),this.options.showRefresh&&this.$toolbar.find('button[name="refresh"]').off("click").on("click",a.proxy(this.refresh,this)),this.options.showToggle&&this.$toolbar.find('button[name="toggle"]').off("click").on("click",function(){e.toggleView()}),this.options.showColumns&&(b=this.$toolbar.find(".keep-open"),i<=this.options.minimumCountColumns&&b.find("input").prop("disabled",!0),b.find("li").off("click").on("click",function(a){a.stopImmediatePropagation()}),b.find("input").off("click").on("click",function(){var b=a(this);e.toggleColumn(a(this).val(),b.prop("checked"),!1),e.trigger("column-switch",a(this).data("field"),b.prop("checked"))})),this.options.search&&(f=[],f.push('<div class="pull-'+this.options.searchAlign+' search">',c('<input class="form-control'+c(" input-%s",this.options.iconSize)+'" type="text" placeholder="%s">',this.options.formatSearch()),"</div>"),this.$toolbar.append(f.join("")),d=this.$toolbar.find(".search input"),d.off("keyup drop").on("keyup drop",function(b){e.options.searchOnEnterKey&&13!==b.keyCode||a.inArray(b.keyCode,[37,38,39,40])>-1||(clearTimeout(g),g=setTimeout(function(){e.onSearch(b)},e.options.searchTimeOut))}),n()&&d.off("mouseup").on("mouseup",function(a){clearTimeout(g),g=setTimeout(function(){e.onSearch(a)},e.options.searchTimeOut)}))},p.prototype.onSearch=function(b){var c=a.trim(a(b.currentTarget).val());this.options.trimOnSearch&&a(b.currentTarget).val()!==c&&a(b.currentTarget).val(c),c!==this.searchText&&(this.searchText=c,this.options.searchText=c,this.options.pageNumber=1,this.initSearch(),this.updatePagination(),this.trigger("search",c))},p.prototype.initSearch=function(){var b=this;if("server"!==this.options.sidePagination){if(this.options.customSearch!==a.noop)return void this.options.customSearch.apply(this,[this.searchText]);var c=this.searchText&&(this.options.escape?j(this.searchText):this.searchText).toLowerCase(),d=a.isEmptyObject(this.filterColumns)?null:this.filterColumns;this.data=d?a.grep(this.options.data,function(b){for(var c in d)if(a.isArray(d[c])&&-1===a.inArray(b[c],d[c])||b[c]!==d[c])return!1;return!0}):this.options.data,this.data=c?a.grep(this.data,function(d,f){for(var g=0;g<b.header.fields.length;g++)if(b.header.searchables[g]){var i,j=a.isNumeric(b.header.fields[g])?parseInt(b.header.fields[g],10):b.header.fields[g],k=b.columns[e(b.columns,j)];if("string"==typeof j){i=d;for(var l=j.split("."),m=0;m<l.length;m++)i=i[l[m]];k&&k.searchFormatter&&(i=h(k,b.header.formatters[g],[i,d,f],i))}else i=d[j];if("string"==typeof i||"number"==typeof i)if(b.options.strictSearch){if((i+"").toLowerCase()===c)return!0}else if(-1!==(i+"").toLowerCase().indexOf(c))return!0}return!1}):this.data}},p.prototype.initPagination=function(){if(!this.options.pagination)return void this.$pagination.hide();this.$pagination.show();var b,d,e,f,g,h,i,j,k,l=this,m=[],n=!1,o=this.getData(),p=this.options.pageList;if("server"!==this.options.sidePagination&&(this.options.totalRows=o.length),this.totalPages=0,this.options.totalRows){if(this.options.pageSize===this.options.formatAllRows())this.options.pageSize=this.options.totalRows,n=!0;else if(this.options.pageSize===this.options.totalRows){var q="string"==typeof this.options.pageList?this.options.pageList.replace("[","").replace("]","").replace(/ /g,"").toLowerCase().split(","):this.options.pageList;a.inArray(this.options.formatAllRows().toLowerCase(),q)>-1&&(n=!0)}this.totalPages=~~((this.options.totalRows-1)/this.options.pageSize)+1,this.options.totalPages=this.totalPages}if(this.totalPages>0&&this.options.pageNumber>this.totalPages&&(this.options.pageNumber=this.totalPages),this.pageFrom=(this.options.pageNumber-1)*this.options.pageSize+1,this.pageTo=this.options.pageNumber*this.options.pageSize,this.pageTo>this.options.totalRows&&(this.pageTo=this.options.totalRows),m.push('<div class="pull-'+this.options.paginationDetailHAlign+' pagination-detail">','<span class="pagination-info">',this.options.onlyInfoPagination?this.options.formatDetailPagination(this.options.totalRows):this.options.formatShowingRows(this.pageFrom,this.pageTo,this.options.totalRows),"</span>"),!this.options.onlyInfoPagination){m.push('<span class="page-list">');var r=[c('<span class="btn-group %s">',"top"===this.options.paginationVAlign||"both"===this.options.paginationVAlign?"dropdown":"dropup"),'<button type="button" class="btn'+c(" btn-%s",this.options.buttonsClass)+c(" btn-%s",this.options.iconSize)+' dropdown-toggle" data-toggle="dropdown">','<span class="page-size">',n?this.options.formatAllRows():this.options.pageSize,"</span>",' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">'];if("string"==typeof this.options.pageList){var s=this.options.pageList.replace("[","").replace("]","").replace(/ /g,"").split(",");p=[],a.each(s,function(a,b){p.push(b.toUpperCase()===l.options.formatAllRows().toUpperCase()?l.options.formatAllRows():+b)})}for(a.each(p,function(a,b){if(!l.options.smartDisplay||0===a||p[a-1]<=l.options.totalRows){var d;d=n?b===l.options.formatAllRows()?' class="active"':"":b===l.options.pageSize?' class="active"':"",r.push(c('<li%s><a href="javascript:void(0)">%s</a></li>',d,b))}}),r.push("</ul></span>"),m.push(this.options.formatRecordsPerPage(r.join(""))),m.push("</span>"),m.push("</div>",'<div class="pull-'+this.options.paginationHAlign+' pagination">','<ul class="pagination'+c(" pagination-%s",this.options.iconSize)+'">','<li class="page-pre"><a href="javascript:void(0)">'+this.options.paginationPreText+"</a></li>"),this.totalPages<5?(d=1,e=this.totalPages):(d=this.options.pageNumber-2,e=d+4,1>d&&(d=1,e=5),e>this.totalPages&&(e=this.totalPages,d=e-4)),this.totalPages>=6&&(this.options.pageNumber>=3&&(m.push('<li class="page-first'+(1===this.options.pageNumber?" active":"")+'">','<a href="javascript:void(0)">',1,"</a>","</li>"),d++),this.options.pageNumber>=4&&(4==this.options.pageNumber||6==this.totalPages||7==this.totalPages?d--:m.push('<li class="page-first-separator disabled">','<a href="javascript:void(0)">...</a>',"</li>"),e--)),this.totalPages>=7&&this.options.pageNumber>=this.totalPages-2&&d--,6==this.totalPages?this.options.pageNumber>=this.totalPages-2&&e++:this.totalPages>=7&&(7==this.totalPages||this.options.pageNumber>=this.totalPages-3)&&e++,b=d;e>=b;b++)m.push('<li class="page-number'+(b===this.options.pageNumber?" active":"")+'">','<a href="javascript:void(0)">',b,"</a>","</li>");this.totalPages>=8&&this.options.pageNumber<=this.totalPages-4&&m.push('<li class="page-last-separator disabled">','<a href="javascript:void(0)">...</a>',"</li>"),this.totalPages>=6&&this.options.pageNumber<=this.totalPages-3&&m.push('<li class="page-last'+(this.totalPages===this.options.pageNumber?" active":"")+'">','<a href="javascript:void(0)">',this.totalPages,"</a>","</li>"),m.push('<li class="page-next"><a href="javascript:void(0)">'+this.options.paginationNextText+"</a></li>","</ul>","</div>")}this.$pagination.html(m.join("")),this.options.onlyInfoPagination||(f=this.$pagination.find(".page-list a"),g=this.$pagination.find(".page-first"),h=this.$pagination.find(".page-pre"),i=this.$pagination.find(".page-next"),j=this.$pagination.find(".page-last"),k=this.$pagination.find(".page-number"),this.options.smartDisplay&&(this.totalPages<=1&&this.$pagination.find("div.pagination").hide(),(p.length<2||this.options.totalRows<=p[0])&&this.$pagination.find("span.page-list").hide(),this.$pagination[this.getData().length?"show":"hide"]()),n&&(this.options.pageSize=this.options.formatAllRows()),f.off("click").on("click",a.proxy(this.onPageListChange,this)),g.off("click").on("click",a.proxy(this.onPageFirst,this)),h.off("click").on("click",a.proxy(this.onPagePre,this)),i.off("click").on("click",a.proxy(this.onPageNext,this)),j.off("click").on("click",a.proxy(this.onPageLast,this)),k.off("click").on("click",a.proxy(this.onPageNumber,this)))},p.prototype.updatePagination=function(b){b&&a(b.currentTarget).hasClass("disabled")||(this.options.maintainSelected||this.resetRows(),this.initPagination(),"server"===this.options.sidePagination?this.initServer():this.initBody(),this.trigger("page-change",this.options.pageNumber,this.options.pageSize))},p.prototype.onPageListChange=function(b){var c=a(b.currentTarget);c.parent().addClass("active").siblings().removeClass("active"),this.options.pageSize=c.text().toUpperCase()===this.options.formatAllRows().toUpperCase()?this.options.formatAllRows():+c.text(),this.$toolbar.find(".page-size").text(this.options.pageSize),this.updatePagination(b)},p.prototype.onPageFirst=function(a){this.options.pageNumber=1,this.updatePagination(a)},p.prototype.onPagePre=function(a){this.options.pageNumber-1===0?this.options.pageNumber=this.options.totalPages:this.options.pageNumber--,this.updatePagination(a)},p.prototype.onPageNext=function(a){this.options.pageNumber+1>this.options.totalPages?this.options.pageNumber=1:this.options.pageNumber++,this.updatePagination(a)},p.prototype.onPageLast=function(a){this.options.pageNumber=this.totalPages,this.updatePagination(a)},p.prototype.onPageNumber=function(b){this.options.pageNumber!==+a(b.currentTarget).text()&&(this.options.pageNumber=+a(b.currentTarget).text(),this.updatePagination(b))},p.prototype.initBody=function(b){var f=this,g=[],i=this.getData();this.trigger("pre-body",i),this.$body=this.$el.find(">tbody"),this.$body.length||(this.$body=a("<tbody></tbody>").appendTo(this.$el)),this.options.pagination&&"server"!==this.options.sidePagination||(this.pageFrom=1,this.pageTo=i.length);for(var k=this.pageFrom-1;k<this.pageTo;k++){var l,n=i[k],o={},p=[],q="",r={},s=[];if(o=h(this.options,this.options.rowStyle,[n,k],o),o&&o.css)for(l in o.css)p.push(l+": "+o.css[l]);if(r=h(this.options,this.options.rowAttributes,[n,k],r))for(l in r)s.push(c('%s="%s"',l,j(r[l])));n._data&&!a.isEmptyObject(n._data)&&a.each(n._data,function(a,b){"index"!==a&&(q+=c(' data-%s="%s"',a,b))}),g.push("<tr",c(" %s",s.join(" ")),c(' id="%s"',a.isArray(n)?void 0:n._id),c(' class="%s"',o.classes||(a.isArray(n)?void 0:n._class)),c(' data-index="%s"',k),c(' data-uniqueid="%s"',n[this.options.uniqueId]),c("%s",q),">"),this.options.cardView&&g.push(c('<td colspan="%s"><div class="card-views">',this.header.fields.length)),!this.options.cardView&&this.options.detailView&&g.push("<td>",'<a class="detail-icon" href="javascript:">',c('<i class="%s %s"></i>',this.options.iconsPrefix,this.options.icons.detailOpen),"</a>","</td>"),a.each(this.header.fields,function(b,e){var i="",j=m(n,e,f.options.escape),l="",q={},r="",s=f.header.classes[b],t="",u="",v="",w="",x=f.columns[b];if(!(f.fromHtml&&"undefined"==typeof j||!x.visible||f.options.cardView&&!x.cardVisible)){if(o=c('style="%s"',p.concat(f.header.styles[b]).join("; ")),n["_"+e+"_id"]&&(r=c(' id="%s"',n["_"+e+"_id"])),n["_"+e+"_class"]&&(s=c(' class="%s"',n["_"+e+"_class"])),n["_"+e+"_rowspan"]&&(u=c(' rowspan="%s"',n["_"+e+"_rowspan"])),n["_"+e+"_colspan"]&&(v=c(' colspan="%s"',n["_"+e+"_colspan"])),n["_"+e+"_title"]&&(w=c(' title="%s"',n["_"+e+"_title"])),q=h(f.header,f.header.cellStyles[b],[j,n,k,e],q),q.classes&&(s=c(' class="%s"',q.classes)),q.css){var y=[];for(var z in q.css)y.push(z+": "+q.css[z]);o=c('style="%s"',y.concat(f.header.styles[b]).join("; "))}j=h(x,f.header.formatters[b],[j,n,k],j),n["_"+e+"_data"]&&!a.isEmptyObject(n["_"+e+"_data"])&&a.each(n["_"+e+"_data"],function(a,b){"index"!==a&&(t+=c(' data-%s="%s"',a,b))}),x.checkbox||x.radio?(l=x.checkbox?"checkbox":l,l=x.radio?"radio":l,i=[c(f.options.cardView?'<div class="card-view %s">':'<td class="bs-checkbox %s">',x["class"]||""),"<input"+c(' data-index="%s"',k)+c(' name="%s"',f.options.selectItemName)+c(' type="%s"',l)+c(' value="%s"',n[f.options.idField])+c(' checked="%s"',j===!0||j&&j.checked?"checked":void 0)+c(' disabled="%s"',!x.checkboxEnabled||j&&j.disabled?"disabled":void 0)+" />",f.header.formatters[b]&&"string"==typeof j?j:"",f.options.cardView?"</div>":"</td>"].join(""),n[f.header.stateField]=j===!0||j&&j.checked):(j="undefined"==typeof j||null===j?f.options.undefinedText:j,i=f.options.cardView?['<div class="card-view">',f.options.showHeader?c('<span class="title" %s>%s</span>',o,d(f.columns,"field","title",e)):"",c('<span class="value">%s</span>',j),"</div>"].join(""):[c("<td%s %s %s %s %s %s %s>",r,s,o,t,u,v,w),j,"</td>"].join(""),f.options.cardView&&f.options.smartDisplay&&""===j&&(i='<div class="card-view"></div>')),g.push(i)}}),this.options.cardView&&g.push("</div></td>"),g.push("</tr>")}g.length||g.push('<tr class="no-records-found">',c('<td colspan="%s">%s</td>',this.$header.find("th").length,this.options.formatNoMatches()),"</tr>"),this.$body.html(g.join("")),b||this.scrollTo(0),this.$body.find("> tr[data-index] > td").off("click dblclick").on("click dblclick",function(b){var d=a(this),g=d.parent(),h=f.data[g.data("index")],i=d[0].cellIndex,j=f.getVisibleFields(),k=j[f.options.detailView&&!f.options.cardView?i-1:i],l=f.columns[e(f.columns,k)],n=m(h,k,f.options.escape);if(!d.find(".detail-icon").length&&(f.trigger("click"===b.type?"click-cell":"dbl-click-cell",k,n,h,d),f.trigger("click"===b.type?"click-row":"dbl-click-row",h,g,k),
+"click"===b.type&&f.options.clickToSelect&&l.clickToSelect)){var o=g.find(c('[name="%s"]',f.options.selectItemName));o.length&&o[0].click()}}),this.$body.find("> tr[data-index] > td > .detail-icon").off("click").on("click",function(){var b=a(this),d=b.parent().parent(),e=d.data("index"),g=i[e];if(d.next().is("tr.detail-view"))b.find("i").attr("class",c("%s %s",f.options.iconsPrefix,f.options.icons.detailOpen)),d.next().remove(),f.trigger("collapse-row",e,g);else{b.find("i").attr("class",c("%s %s",f.options.iconsPrefix,f.options.icons.detailClose)),d.after(c('<tr class="detail-view"><td colspan="%s"></td></tr>',d.find("td").length));var j=d.next().find("td"),k=h(f.options,f.options.detailFormatter,[e,g,j],"");1===j.length&&j.append(k),f.trigger("expand-row",e,g,j)}f.resetView()}),this.$selectItem=this.$body.find(c('[name="%s"]',this.options.selectItemName)),this.$selectItem.off("click").on("click",function(b){b.stopImmediatePropagation();var c=a(this),d=c.prop("checked"),e=f.data[c.data("index")];f.options.maintainSelected&&a(this).is(":radio")&&a.each(f.options.data,function(a,b){b[f.header.stateField]=!1}),e[f.header.stateField]=d,f.options.singleSelect&&(f.$selectItem.not(this).each(function(){f.data[a(this).data("index")][f.header.stateField]=!1}),f.$selectItem.filter(":checked").not(this).prop("checked",!1)),f.updateSelected(),f.trigger(d?"check":"uncheck",e,c)}),a.each(this.header.events,function(b,c){if(c){"string"==typeof c&&(c=h(null,c));var d=f.header.fields[b],e=a.inArray(d,f.getVisibleFields());f.options.detailView&&!f.options.cardView&&(e+=1);for(var g in c)f.$body.find(">tr:not(.no-records-found)").each(function(){var b=a(this),h=b.find(f.options.cardView?".card-view":"td").eq(e),i=g.indexOf(" "),j=g.substring(0,i),k=g.substring(i+1),l=c[g];h.find(k).off(j).on(j,function(a){var c=b.data("index"),e=f.data[c],g=e[d];l.apply(this,[a,g,e,c])})})}}),this.updateSelected(),this.resetView(),this.trigger("post-body",i)},p.prototype.initServer=function(b,c,d){var e,f=this,g={},i={searchText:this.searchText,sortName:this.options.sortName,sortOrder:this.options.sortOrder};this.options.pagination&&(i.pageSize=this.options.pageSize===this.options.formatAllRows()?this.options.totalRows:this.options.pageSize,i.pageNumber=this.options.pageNumber),(d||this.options.url||this.options.ajax)&&("limit"===this.options.queryParamsType&&(i={search:i.searchText,sort:i.sortName,order:i.sortOrder},this.options.pagination&&(i.offset=this.options.pageSize===this.options.formatAllRows()?0:this.options.pageSize*(this.options.pageNumber-1),i.limit=this.options.pageSize===this.options.formatAllRows()?this.options.totalRows:this.options.pageSize)),a.isEmptyObject(this.filterColumnsPartial)||(i.filter=JSON.stringify(this.filterColumnsPartial,null)),g=h(this.options,this.options.queryParams,[i],g),a.extend(g,c||{}),g!==!1&&(b||this.$tableLoading.show(),e=a.extend({},h(null,this.options.ajaxOptions),{type:this.options.method,url:d||this.options.url,data:"application/json"===this.options.contentType&&"post"===this.options.method?JSON.stringify(g):g,cache:this.options.cache,contentType:this.options.contentType,dataType:this.options.dataType,success:function(a){a=h(f.options,f.options.responseHandler,[a],a),f.load(a),f.trigger("load-success",a),b||f.$tableLoading.hide()},error:function(a){f.trigger("load-error",a.status,a),b||f.$tableLoading.hide()}}),this.options.ajax?h(this,this.options.ajax,[e],null):(this._xhr&&4!==this._xhr.readyState&&this._xhr.abort(),this._xhr=a.ajax(e))))},p.prototype.initSearchText=function(){if(this.options.search&&""!==this.options.searchText){var a=this.$toolbar.find(".search input");a.val(this.options.searchText),this.onSearch({currentTarget:a})}},p.prototype.getCaret=function(){var b=this;a.each(this.$header.find("th"),function(c,d){a(d).find(".sortable").removeClass("desc asc").addClass(a(d).data("field")===b.options.sortName?b.options.sortOrder:"both")})},p.prototype.updateSelected=function(){var b=this.$selectItem.filter(":enabled").length&&this.$selectItem.filter(":enabled").length===this.$selectItem.filter(":enabled").filter(":checked").length;this.$selectAll.add(this.$selectAll_).prop("checked",b),this.$selectItem.each(function(){a(this).closest("tr")[a(this).prop("checked")?"addClass":"removeClass"]("selected")})},p.prototype.updateRows=function(){var b=this;this.$selectItem.each(function(){b.data[a(this).data("index")][b.header.stateField]=a(this).prop("checked")})},p.prototype.resetRows=function(){var b=this;a.each(this.data,function(a,c){b.$selectAll.prop("checked",!1),b.$selectItem.prop("checked",!1),b.header.stateField&&(c[b.header.stateField]=!1)})},p.prototype.trigger=function(b){var c=Array.prototype.slice.call(arguments,1);b+=".bs.table",this.options[p.EVENTS[b]].apply(this.options,c),this.$el.trigger(a.Event(b),c),this.options.onAll(b,c),this.$el.trigger(a.Event("all.bs.table"),[b,c])},p.prototype.resetHeader=function(){clearTimeout(this.timeoutId_),this.timeoutId_=setTimeout(a.proxy(this.fitHeader,this),this.$el.is(":hidden")?100:0)},p.prototype.fitHeader=function(){var b,d,e,f,h=this;if(h.$el.is(":hidden"))return void(h.timeoutId_=setTimeout(a.proxy(h.fitHeader,h),100));if(b=this.$tableBody.get(0),d=b.scrollWidth>b.clientWidth&&b.scrollHeight>b.clientHeight+this.$header.outerHeight()?g():0,this.$el.css("margin-top",-this.$header.outerHeight()),e=a(":focus"),e.length>0){var i=e.parents("th");if(i.length>0){var j=i.attr("data-field");if(void 0!==j){var k=this.$header.find("[data-field='"+j+"']");k.length>0&&k.find(":input").addClass("focus-temp")}}}this.$header_=this.$header.clone(!0,!0),this.$selectAll_=this.$header_.find('[name="btSelectAll"]'),this.$tableHeader.css({"margin-right":d}).find("table").css("width",this.$el.outerWidth()).html("").attr("class",this.$el.attr("class")).append(this.$header_),f=a(".focus-temp:visible:eq(0)"),f.length>0&&(f.focus(),this.$header.find(".focus-temp").removeClass("focus-temp")),this.$header.find("th[data-field]").each(function(){h.$header_.find(c('th[data-field="%s"]',a(this).data("field"))).data(a(this).data())});var l=this.getVisibleFields(),m=this.$header_.find("th");this.$body.find(">tr:first-child:not(.no-records-found) > *").each(function(b){var d=a(this),e=b;h.options.detailView&&!h.options.cardView&&(0===b&&h.$header_.find("th.detail").find(".fht-cell").width(d.innerWidth()),e=b-1);var f=h.$header_.find(c('th[data-field="%s"]',l[e]));f.length>1&&(f=a(m[d[0].cellIndex])),f.find(".fht-cell").width(d.innerWidth())}),this.$tableBody.off("scroll").on("scroll",function(){h.$tableHeader.scrollLeft(a(this).scrollLeft()),h.options.showFooter&&!h.options.cardView&&h.$tableFooter.scrollLeft(a(this).scrollLeft())}),h.trigger("post-header")},p.prototype.resetFooter=function(){var b=this,d=b.getData(),e=[];this.options.showFooter&&!this.options.cardView&&(!this.options.cardView&&this.options.detailView&&e.push('<td><div class="th-inner">&nbsp;</div><div class="fht-cell"></div></td>'),a.each(this.columns,function(a,f){var g,i="",j="",k=[],l={},m=c(' class="%s"',f["class"]);if(f.visible&&(!b.options.cardView||f.cardVisible)){if(i=c("text-align: %s; ",f.falign?f.falign:f.align),j=c("vertical-align: %s; ",f.valign),l=h(null,b.options.footerStyle),l&&l.css)for(g in l.css)k.push(g+": "+l.css[g]);e.push("<td",m,c(' style="%s"',i+j+k.concat().join("; ")),">"),e.push('<div class="th-inner">'),e.push(h(f,f.footerFormatter,[d],"&nbsp;")||"&nbsp;"),e.push("</div>"),e.push('<div class="fht-cell"></div>'),e.push("</div>"),e.push("</td>")}}),this.$tableFooter.find("tr").html(e.join("")),this.$tableFooter.show(),clearTimeout(this.timeoutFooter_),this.timeoutFooter_=setTimeout(a.proxy(this.fitFooter,this),this.$el.is(":hidden")?100:0))},p.prototype.fitFooter=function(){var b,c,d;return clearTimeout(this.timeoutFooter_),this.$el.is(":hidden")?void(this.timeoutFooter_=setTimeout(a.proxy(this.fitFooter,this),100)):(c=this.$el.css("width"),d=c>this.$tableBody.width()?g():0,this.$tableFooter.css({"margin-right":d}).find("table").css("width",c).attr("class",this.$el.attr("class")),b=this.$tableFooter.find("td"),void this.$body.find(">tr:first-child:not(.no-records-found) > *").each(function(c){var d=a(this);b.eq(c).find(".fht-cell").width(d.innerWidth())}))},p.prototype.toggleColumn=function(a,b,d){if(-1!==a&&(this.columns[a].visible=b,this.initHeader(),this.initSearch(),this.initPagination(),this.initBody(),this.options.showColumns)){var e=this.$toolbar.find(".keep-open input").prop("disabled",!1);d&&e.filter(c('[value="%s"]',a)).prop("checked",b),e.filter(":checked").length<=this.options.minimumCountColumns&&e.filter(":checked").prop("disabled",!0)}},p.prototype.toggleRow=function(a,b,d){-1!==a&&this.$body.find("undefined"!=typeof a?c('tr[data-index="%s"]',a):c('tr[data-uniqueid="%s"]',b))[d?"show":"hide"]()},p.prototype.getVisibleFields=function(){var b=this,c=[];return a.each(this.header.fields,function(a,d){var f=b.columns[e(b.columns,d)];f.visible&&c.push(d)}),c},p.prototype.resetView=function(a){var b=0;if(a&&a.height&&(this.options.height=a.height),this.$selectAll.prop("checked",this.$selectItem.length>0&&this.$selectItem.length===this.$selectItem.filter(":checked").length),this.options.height){var c=k(this.$toolbar),d=k(this.$pagination),e=this.options.height-c-d;this.$tableContainer.css("height",e+"px")}return this.options.cardView?(this.$el.css("margin-top","0"),this.$tableContainer.css("padding-bottom","0"),void this.$tableFooter.hide()):(this.options.showHeader&&this.options.height?(this.$tableHeader.show(),this.resetHeader(),b+=this.$header.outerHeight()):(this.$tableHeader.hide(),this.trigger("post-header")),this.options.showFooter&&(this.resetFooter(),this.options.height&&(b+=this.$tableFooter.outerHeight()+1)),this.getCaret(),this.$tableContainer.css("padding-bottom",b+"px"),void this.trigger("reset-view"))},p.prototype.getData=function(b){return!this.searchText&&a.isEmptyObject(this.filterColumns)&&a.isEmptyObject(this.filterColumnsPartial)?b?this.options.data.slice(this.pageFrom-1,this.pageTo):this.options.data:b?this.data.slice(this.pageFrom-1,this.pageTo):this.data},p.prototype.load=function(b){var c=!1;"server"===this.options.sidePagination?(this.options.totalRows=b.total,c=b.fixedScroll,b=b[this.options.dataField]):a.isArray(b)||(c=b.fixedScroll,b=b.data),this.initData(b),this.initSearch(),this.initPagination(),this.initBody(c)},p.prototype.append=function(a){this.initData(a,"append"),this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0)},p.prototype.prepend=function(a){this.initData(a,"prepend"),this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0)},p.prototype.remove=function(b){var c,d,e=this.options.data.length;if(b.hasOwnProperty("field")&&b.hasOwnProperty("values")){for(c=e-1;c>=0;c--)d=this.options.data[c],d.hasOwnProperty(b.field)&&-1!==a.inArray(d[b.field],b.values)&&this.options.data.splice(c,1);e!==this.options.data.length&&(this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0))}},p.prototype.removeAll=function(){this.options.data.length>0&&(this.options.data.splice(0,this.options.data.length),this.initSearch(),this.initPagination(),this.initBody(!0))},p.prototype.getRowByUniqueId=function(a){var b,c,d,e=this.options.uniqueId,f=this.options.data.length,g=null;for(b=f-1;b>=0;b--){if(c=this.options.data[b],c.hasOwnProperty(e))d=c[e];else{if(!c._data.hasOwnProperty(e))continue;d=c._data[e]}if("string"==typeof d?a=a.toString():"number"==typeof d&&(Number(d)===d&&d%1===0?a=parseInt(a):d===Number(d)&&0!==d&&(a=parseFloat(a))),d===a){g=c;break}}return g},p.prototype.removeByUniqueId=function(a){var b=this.options.data.length,c=this.getRowByUniqueId(a);c&&this.options.data.splice(this.options.data.indexOf(c),1),b!==this.options.data.length&&(this.initSearch(),this.initPagination(),this.initBody(!0))},p.prototype.updateByUniqueId=function(b){var c=this,d=a.isArray(b)?b:[b];a.each(d,function(b,d){var e;d.hasOwnProperty("id")&&d.hasOwnProperty("row")&&(e=a.inArray(c.getRowByUniqueId(d.id),c.options.data),-1!==e&&a.extend(c.options.data[e],d.row))}),this.initSearch(),this.initSort(),this.initBody(!0)},p.prototype.insertRow=function(a){a.hasOwnProperty("index")&&a.hasOwnProperty("row")&&(this.data.splice(a.index,0,a.row),this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0))},p.prototype.updateRow=function(b){var c=this,d=a.isArray(b)?b:[b];a.each(d,function(b,d){d.hasOwnProperty("index")&&d.hasOwnProperty("row")&&a.extend(c.options.data[d.index],d.row)}),this.initSearch(),this.initSort(),this.initBody(!0)},p.prototype.showRow=function(a){(a.hasOwnProperty("index")||a.hasOwnProperty("uniqueId"))&&this.toggleRow(a.index,a.uniqueId,!0)},p.prototype.hideRow=function(a){(a.hasOwnProperty("index")||a.hasOwnProperty("uniqueId"))&&this.toggleRow(a.index,a.uniqueId,!1)},p.prototype.getRowsHidden=function(b){var c=a(this.$body[0]).children().filter(":hidden"),d=0;if(b)for(;d<c.length;d++)a(c[d]).show();return c},p.prototype.mergeCells=function(b){var c,d,e,f=b.index,g=a.inArray(b.field,this.getVisibleFields()),h=b.rowspan||1,i=b.colspan||1,j=this.$body.find(">tr");if(this.options.detailView&&!this.options.cardView&&(g+=1),e=j.eq(f).find(">td").eq(g),!(0>f||0>g||f>=this.data.length)){for(c=f;f+h>c;c++)for(d=g;g+i>d;d++)j.eq(c).find(">td").eq(d).hide();e.attr("rowspan",h).attr("colspan",i).show()}},p.prototype.updateCell=function(a){a.hasOwnProperty("index")&&a.hasOwnProperty("field")&&a.hasOwnProperty("value")&&(this.data[a.index][a.field]=a.value,a.reinit!==!1&&(this.initSort(),this.initBody(!0)))},p.prototype.getOptions=function(){return this.options},p.prototype.getSelections=function(){var b=this;return a.grep(this.options.data,function(a){return a[b.header.stateField]})},p.prototype.getAllSelections=function(){var b=this;return a.grep(this.options.data,function(a){return a[b.header.stateField]})},p.prototype.checkAll=function(){this.checkAll_(!0)},p.prototype.uncheckAll=function(){this.checkAll_(!1)},p.prototype.checkInvert=function(){var b=this,c=b.$selectItem.filter(":enabled"),d=c.filter(":checked");c.each(function(){a(this).prop("checked",!a(this).prop("checked"))}),b.updateRows(),b.updateSelected(),b.trigger("uncheck-some",d),d=b.getSelections(),b.trigger("check-some",d)},p.prototype.checkAll_=function(a){var b;a||(b=this.getSelections()),this.$selectAll.add(this.$selectAll_).prop("checked",a),this.$selectItem.filter(":enabled").prop("checked",a),this.updateRows(),a&&(b=this.getSelections()),this.trigger(a?"check-all":"uncheck-all",b)},p.prototype.check=function(a){this.check_(!0,a)},p.prototype.uncheck=function(a){this.check_(!1,a)},p.prototype.check_=function(a,b){var d=this.$selectItem.filter(c('[data-index="%s"]',b)).prop("checked",a);this.data[b][this.header.stateField]=a,this.updateSelected(),this.trigger(a?"check":"uncheck",this.data[b],d)},p.prototype.checkBy=function(a){this.checkBy_(!0,a)},p.prototype.uncheckBy=function(a){this.checkBy_(!1,a)},p.prototype.checkBy_=function(b,d){if(d.hasOwnProperty("field")&&d.hasOwnProperty("values")){var e=this,f=[];a.each(this.options.data,function(g,h){if(!h.hasOwnProperty(d.field))return!1;if(-1!==a.inArray(h[d.field],d.values)){var i=e.$selectItem.filter(":enabled").filter(c('[data-index="%s"]',g)).prop("checked",b);h[e.header.stateField]=b,f.push(h),e.trigger(b?"check":"uncheck",h,i)}}),this.updateSelected(),this.trigger(b?"check-some":"uncheck-some",f)}},p.prototype.destroy=function(){this.$el.insertBefore(this.$container),a(this.options.toolbar).insertBefore(this.$el),this.$container.next().remove(),this.$container.remove(),this.$el.html(this.$el_.html()).css("margin-top","0").attr("class",this.$el_.attr("class")||"")},p.prototype.showLoading=function(){this.$tableLoading.show()},p.prototype.hideLoading=function(){this.$tableLoading.hide()},p.prototype.togglePagination=function(){this.options.pagination=!this.options.pagination;var a=this.$toolbar.find('button[name="paginationSwitch"] i');this.options.pagination?a.attr("class",this.options.iconsPrefix+" "+this.options.icons.paginationSwitchDown):a.attr("class",this.options.iconsPrefix+" "+this.options.icons.paginationSwitchUp),this.updatePagination()},p.prototype.refresh=function(a){a&&a.url&&(this.options.pageNumber=1),this.initServer(a&&a.silent,a&&a.query,a&&a.url),this.trigger("refresh",a)},p.prototype.resetWidth=function(){this.options.showHeader&&this.options.height&&this.fitHeader(),this.options.showFooter&&this.fitFooter()},p.prototype.showColumn=function(a){this.toggleColumn(e(this.columns,a),!0,!0)},p.prototype.hideColumn=function(a){this.toggleColumn(e(this.columns,a),!1,!0)},p.prototype.getHiddenColumns=function(){return a.grep(this.columns,function(a){return!a.visible})},p.prototype.getVisibleColumns=function(){return a.grep(this.columns,function(a){return a.visible})},p.prototype.toggleAllColumns=function(b){if(a.each(this.columns,function(a){this.columns[a].visible=b}),this.initHeader(),this.initSearch(),this.initPagination(),this.initBody(),this.options.showColumns){var c=this.$toolbar.find(".keep-open input").prop("disabled",!1);c.filter(":checked").length<=this.options.minimumCountColumns&&c.filter(":checked").prop("disabled",!0)}},p.prototype.showAllColumns=function(){this.toggleAllColumns(!0)},p.prototype.hideAllColumns=function(){this.toggleAllColumns(!1)},p.prototype.filterBy=function(b){this.filterColumns=a.isEmptyObject(b)?{}:b,this.options.pageNumber=1,this.initSearch(),this.updatePagination()},p.prototype.scrollTo=function(a){return"string"==typeof a&&(a="bottom"===a?this.$tableBody[0].scrollHeight:0),"number"==typeof a&&this.$tableBody.scrollTop(a),"undefined"==typeof a?this.$tableBody.scrollTop():void 0},p.prototype.getScrollPosition=function(){return this.scrollTo()},p.prototype.selectPage=function(a){a>0&&a<=this.options.totalPages&&(this.options.pageNumber=a,this.updatePagination())},p.prototype.prevPage=function(){this.options.pageNumber>1&&(this.options.pageNumber--,this.updatePagination())},p.prototype.nextPage=function(){this.options.pageNumber<this.options.totalPages&&(this.options.pageNumber++,this.updatePagination())},p.prototype.toggleView=function(){this.options.cardView=!this.options.cardView,this.initHeader(),this.initBody(),this.trigger("toggle",this.options.cardView)},p.prototype.refreshOptions=function(b){i(this.options,b,!0)||(this.options=a.extend(this.options,b),this.trigger("refresh-options",this.options),this.destroy(),this.init())},p.prototype.resetSearch=function(a){var b=this.$toolbar.find(".search input");b.val(a||""),this.onSearch({currentTarget:b})},p.prototype.expandRow_=function(a,b){var d=this.$body.find(c('> tr[data-index="%s"]',b));d.next().is("tr.detail-view")===(a?!1:!0)&&d.find("> td > .detail-icon").click()},p.prototype.expandRow=function(a){this.expandRow_(!0,a)},p.prototype.collapseRow=function(a){this.expandRow_(!1,a)},p.prototype.expandAllRows=function(b){if(b){var d=this.$body.find(c('> tr[data-index="%s"]',0)),e=this,f=null,g=!1,h=-1;if(d.next().is("tr.detail-view")?d.next().next().is("tr.detail-view")||(d.next().find(".detail-icon").click(),g=!0):(d.find("> td > .detail-icon").click(),g=!0),g)try{h=setInterval(function(){f=e.$body.find("tr.detail-view").last().find(".detail-icon"),f.length>0?f.click():clearInterval(h)},1)}catch(i){clearInterval(h)}}else for(var j=this.$body.children(),k=0;k<j.length;k++)this.expandRow_(!0,a(j[k]).data("index"))},p.prototype.collapseAllRows=function(b){if(b)this.expandRow_(!1,0);else for(var c=this.$body.children(),d=0;d<c.length;d++)this.expandRow_(!1,a(c[d]).data("index"))},p.prototype.updateFormatText=function(a,b){this.options[c("format%s",a)]&&("string"==typeof b?this.options[c("format%s",a)]=function(){return b}:"function"==typeof b&&(this.options[c("format%s",a)]=b)),this.initToolbar(),this.initPagination(),this.initBody()};var q=["getOptions","getSelections","getAllSelections","getData","load","append","prepend","remove","removeAll","insertRow","updateRow","updateCell","updateByUniqueId","removeByUniqueId","getRowByUniqueId","showRow","hideRow","getRowsHidden","mergeCells","checkAll","uncheckAll","checkInvert","check","uncheck","checkBy","uncheckBy","refresh","resetView","resetWidth","destroy","showLoading","hideLoading","showColumn","hideColumn","getHiddenColumns","getVisibleColumns","showAllColumns","hideAllColumns","filterBy","scrollTo","getScrollPosition","selectPage","prevPage","nextPage","togglePagination","toggleView","refreshOptions","resetSearch","expandRow","collapseRow","expandAllRows","collapseAllRows","updateFormatText"];a.fn.bootstrapTable=function(b){var c,d=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=a(this),f=e.data("bootstrap.table"),g=a.extend({},p.DEFAULTS,e.data(),"object"==typeof b&&b);if("string"==typeof b){if(a.inArray(b,q)<0)throw new Error("Unknown method: "+b);if(!f)return;c=f[b].apply(f,d),"destroy"===b&&e.removeData("bootstrap.table")}f||e.data("bootstrap.table",f=new p(this,g))}),"undefined"==typeof c?this:c},a.fn.bootstrapTable.Constructor=p,a.fn.bootstrapTable.defaults=p.DEFAULTS,a.fn.bootstrapTable.columnDefaults=p.COLUMN_DEFAULTS,a.fn.bootstrapTable.locales=p.LOCALES,a.fn.bootstrapTable.methods=q,a.fn.bootstrapTable.utils={sprintf:c,getFieldIndex:e,compareObjects:i,calculateObjectValue:h,getItemField:m,objectKeys:o,isIEBrowser:n},a(function(){a('[data-toggle="table"]').bootstrapTable()})}(jQuery); \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/bootstrap.min.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/bootstrap.min.js
new file mode 100644
index 00000000..b04a0e82
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/bootstrap.min.js
@@ -0,0 +1,6 @@
+/*!
+ * Bootstrap v3.1.1 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.isLoading=!1};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",f.resetText||d.data("resetText",d[e]()),d[e](f[b]||this.options[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},b.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});return this.$element.trigger(j),j.isDefaultPrevented()?void 0:(this.sliding=!0,f&&this.pause(),this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")),f&&this.cycle(),this)};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);!e&&f.toggle&&"show"==c&&(c=!c),e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(b){a(d).remove(),a(e).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown",h),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=" li:not(.divider):visible a",i=f.find("[role=menu]"+h+", [role=listbox]"+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j<i.length-1&&j++,~j||(j=0),i.eq(j).focus()}}}};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.dropdown.Constructor=f,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu], [role=listbox]",f.prototype.keydown)}(jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show().scrollTop(0),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)}))},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=a.support.transition&&c;if(this.$backdrop=a('<div class="modal-backdrop '+c+'" />').appendTo(document.body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());c.is("a")&&b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this,d=this.tip();this.setContent(),this.options.animation&&d.addClass("fade");var e="function"==typeof this.options.placement?this.options.placement.call(this,d[0],this.$element[0]):this.options.placement,f=/\s?auto?\s?/i,g=f.test(e);g&&(e=e.replace(f,"")||"top"),d.detach().css({top:0,left:0,display:"block"}).addClass(e),this.options.container?d.appendTo(this.options.container):d.insertAfter(this.$element);var h=this.getPosition(),i=d[0].offsetWidth,j=d[0].offsetHeight;if(g){var k=this.$element.parent(),l=e,m=document.documentElement.scrollTop||document.body.scrollTop,n="body"==this.options.container?window.innerWidth:k.outerWidth(),o="body"==this.options.container?window.innerHeight:k.outerHeight(),p="body"==this.options.container?0:k.offset().left;e="bottom"==e&&h.top+h.height+j-m>o?"top":"top"==e&&h.top-m-j<0?"bottom":"right"==e&&h.right+i>n?"left":"left"==e&&h.left-i<p?"right":e,d.removeClass(l).addClass(e)}var q=this.getCalculatedOffset(e,h,i,j);this.applyPlacement(q,e),this.hoverState=null;var r=function(){c.$element.trigger("shown.bs."+c.type)};a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,r).emulateTransitionEnd(150):r()}},b.prototype.applyPlacement=function(b,c){var d,e=this.tip(),f=e[0].offsetWidth,g=e[0].offsetHeight,h=parseInt(e.css("margin-top"),10),i=parseInt(e.css("margin-left"),10);isNaN(h)&&(h=0),isNaN(i)&&(i=0),b.top=b.top+h,b.left=b.left+i,a.offset.setOffset(e[0],a.extend({using:function(a){e.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),e.addClass("in");var j=e[0].offsetWidth,k=e[0].offsetHeight;if("top"==c&&k!=g&&(d=!0,b.top=b.top+g-k),/bottom|top/.test(c)){var l=0;b.left<0&&(l=-2*b.left,b.left=0,e.offset(b),j=e[0].offsetWidth,k=e[0].offsetHeight),this.replaceArrow(l-f+j,j,"left")}else this.replaceArrow(k-g,k,"top");d&&e.offset(b)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach(),c.$element.trigger("hidden.bs."+c.type)}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.hoverState=null,this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(a(c).is("body")?window:c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);{var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})}},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(b.RESET).addClass("affix");var a=this.$window.scrollTop(),c=this.$element.offset();return this.pinnedOffset=c.top-a},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"top"==this.affixed&&(e.top+=d),"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(b.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:c-h-this.$element.height()}))}}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/brs.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/brs.js
new file mode 100644
index 00000000..e975f6c6
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/brs.js
@@ -0,0 +1,343 @@
+/* Copyright 2016, Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+$('.siteDeleteImg').click(function(){
+ var data = $(this).parent().parent().parent().find('td:last').find('div:last').html();
+ alert(data);
+ var jsonObj = JSON.parse(data);
+ for(var i = 0; i < jsonObj.length; i++) {
+ var obj = jsonObj[i];
+ var rowData = [obj.tpName,obj.peName,obj.vlanId,obj.siteCidr,obj.ip];
+ $('#underlayTpDataTable').DataTable();
+ $('#underlayTpDataTable').dataTable().fnAddData(rowData);
+ }
+});
+
+
+function deleteSite(objectId){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/sites/"+objectId;
+ $
+ .ajax({
+ type : "DELETE",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ $('#site').bootstrapTable('remove', {
+ field: 'id',
+ values: [objectId]
+ });
+ alert("Delete Site successfull !!!");
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on deleting site: " + xhr.responseText);
+ }
+ });
+}
+function deleteLink(objectId){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/topological-links/"+objectId;
+ $
+ .ajax({
+ type : "DELETE",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ $('#link').bootstrapTable('remove', {
+ field: 'id',
+ values: [objectId]
+ });
+ alert("Delete Link successfull !!!");
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on deleting link : " + xhr.responseText);
+ }
+ });
+}
+
+function deleteNe(objectId){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/managed-elements/"+objectId;
+ $
+ .ajax({
+ type : "DELETE",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ $('#ne').bootstrapTable('remove', {
+ field: 'id',
+ values: [objectId]
+ });
+ alert("Delete NE successfull !!!");
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on deleting ne : " + xhr.responseText);
+ }
+ });
+}
+
+function deletePort(objectId){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/logical-termination-points/"+objectId;
+ $
+ .ajax({
+ type : "DELETE",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ $('#port').bootstrapTable('remove', {
+ field: 'id',
+ values: [objectId]
+ });
+ alert("Delete Port successfull !!!");
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on deleting port : " + xhr.responseText);
+ }
+ });
+}
+function loadSiteData(){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/sites";
+ $
+ .ajax({
+ type : "GET",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ $('#site').bootstrapTable({
+ data: jsonobj.sites
+ });
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on getting site data : " + xhr.responseText);
+ }
+ });
+}
+function loadLinkData(){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/topological-links";
+ $
+ .ajax({
+ type : "GET",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ $('#link').bootstrapTable({
+ data: jsonobj.topologicalLinks
+ });
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on getting link data : " + xhr.responseText);
+ }
+ });
+}
+function loadNeData(){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/managed-elements";
+ $
+ .ajax({
+ type : "GET",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ $('#ne').bootstrapTable({
+ data: jsonobj.managedElements
+ });
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on getting ne data : " + xhr.responseText);
+ }
+ });
+}
+function loadPortData(){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/logical-termination-points";
+ $
+ .ajax({
+ type : "GET",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ $('#port').bootstrapTable({
+ data: jsonobj.logicalTerminationPoints
+ });
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on getting port data : " + xhr.responseText);
+ }
+ });
+}
+$(function(){
+ $('.creat-btn').click(function(){
+ $('#vmAppDialog').addClass('in').css({'display':'block'});
+
+ });
+ $('.close,.button-previous').click(function(){
+ $('#vmAppDialog').removeClass('in').css('display','none');
+ });
+ $('.detail-top ul li').click(function(){
+ $(this).addClass('current').siblings().removeClass('current');
+ });
+ $('.para').click(function(){
+ if($('#serviceTemplateName').val() == ''){
+ alert('Please choose the service templet!');
+ $('#flavorTab').css('display','none');
+ }else{
+ $('#flavorTab').css('display','block');
+ }
+ $('#basicTab').css('display','block');
+ });
+ $('.basic').click(function(){
+ $('#flavorTab').css('display','none');
+ });
+
+ $('.table tbody tr').click(function(){
+ $(this).addClass('openoTable_row_selected').siblings().removeClass('openoTable_row_selected');
+ });
+ $('.table tr:odd').addClass('active');
+ $('#false').click(function(){
+ $('#vmAppDialog').addClass('in').css({'display':'block'});
+ });
+ $('.close,.button-previous').click(function(){
+ $('#vmAppDialog').removeClass('in').css('display','none');
+ });
+ $('#filterTpLogicalType').click(function(){
+ $('#filterTpLogicalType_select_popupcontainer').toggleClass('openo-hide');
+ $('#filterTpLogicalType').toggleClass('openo-focus');
+ var oLeft = $('#open_base_tpL_td6').offset().left;
+ var oTop = $('#open_base_tpL_td6').offset().top;
+ var oHeight = $('#open_base_tpL_td6').height();
+ $('#filterTpLogicalType_select_popupcontainer').css({'left':oLeft,'top':oTop + oHeight + 10});
+ });
+ $('div.openo-select-popup-container>div.openo-select-item>label').click(function(){
+ var Lvalue = $(this).html();
+ $('#filterTpLogicalType_select_input').attr('value',Lvalue);
+ $('#filterTpLogicalType_select_popupcontainer').addClass('openo-hide');
+ $('#filterTpLogicalType').removeClass('openo-focus');
+ });
+ $.fn.serializeObject = function() {
+ var o = {};
+ var a = this.serializeArray();
+ $.each(a, function() {
+ if (o[this.name] !== undefined) {
+ if (!o[this.name].push) {
+ o[this.name] = [ o[this.name] ];
+ }
+ o[this.name].push(this.value || '');
+ } else {
+ o[this.name] = this.value || '';
+ }
+ });
+ return o;
+ };
+ $('#createSite').click(function(){
+ var formData = JSON.stringify($("#vmAppForm").serializeObject());
+ var jsonobj = JSON.parse(formData);
+ var newJson = {"site": jsonobj};
+ formData = JSON.stringify(newJson);
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/sites";
+ $
+ .ajax({
+ type : "POST",
+ url : requestUrl,
+ contentType : "application/json",
+ dataType : "json",
+ data : formData,
+ success : function(jsonResp) {
+ alert("Site saved successfully!!!");
+ jsonobj["id"]= jsonResp.site.id;
+ $('#site').bootstrapTable("append", jsonobj);
+ $('#vmAppDialog').removeClass('in').css('display','none');
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ });
+
+ $('#createNe').click(function(){
+ var formData = JSON.stringify($("#neForm").serializeObject());
+ var jsonobj = JSON.parse(formData);
+ var newJson = {"managedElement": jsonobj};
+ formData = JSON.stringify(newJson);
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/managed-elements";
+ $
+ .ajax({
+ type : "POST",
+ url : requestUrl,
+ contentType : "application/json",
+ dataType : "json",
+ data : formData,
+ success : function(jsonResp) {
+ alert("NE saved successfully!!!");
+ jsonobj["id"]= jsonResp.managedElement.id;
+ $('#ne').bootstrapTable("append", jsonobj);
+ $('#vmAppDialog').removeClass('in').css('display','none');
+
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ });
+
+ $('#createPort').click(function(){
+ var formData = JSON.stringify($("#portForm").serializeObject());
+ var jsonobj = JSON.parse(formData);
+ var newJson = {"logicalTerminationPoint": jsonobj};
+ formData = JSON.stringify(newJson);
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/logical-termination-points";
+ $
+ .ajax({
+ type : "POST",
+ url : requestUrl,
+ contentType : "application/json",
+ dataType : "json",
+ data : formData,
+ success : function(jsonResp) {
+ alert("Port saved successfully!!!");
+ //TODO : hide model data window.
+ jsonobj["id"]= jsonResp.logicalTerminationPoint.id;
+ $('#port').bootstrapTable("append", jsonobj);
+ $('#vmAppDialog').removeClass('in').css('display','none');
+
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ });
+
+ $('#createLink').click(function(){
+ var formData = JSON.stringify($("#linkForm").serializeObject());
+ var jsonobj = JSON.parse(formData);
+ var newJson = {"topologicalLink": jsonobj};
+ formData = JSON.stringify(newJson);
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/topological-links";
+ $
+ .ajax({
+ type : "POST",
+ url : requestUrl,
+ contentType : "application/json",
+ dataType : "json",
+ data : formData,
+ success : function(jsonResp) {
+ alert("Link saved successfully!!!");
+ jsonobj["id"]= jsonResp.topologicalLink.id;
+ $('#link').bootstrapTable("append", jsonobj);
+ $('#vmAppDialog').removeClass('in').css('display','none');
+
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ });
+
+ }) \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/gsolcm.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/gsolcm.js
new file mode 100644
index 00000000..d8c3fa1d
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/gsolcm.js
@@ -0,0 +1,461 @@
+/*
+ * Copyright 2015 ZTE, Inc. and others. All rights reserved. (ZTE)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+var templateParameters = {
+ templateName: '',
+ parameters: []
+};
+
+var service_instance_insert_index = 0;
+
+var lcmHandler = function(){
+ this._addOwnEvents();
+};
+
+lcmHandler.prototype = {
+ _addOwnEvents : function () {
+ $('a[data-toggle="tab"]').on('show.bs.tab', this.beforeParameterTabShow);
+ $('#createNS').click(this.okAction);
+ },
+ beforeParameterTabShow : function (event) {
+ renderTemplateParametersTab();
+ },
+ okAction : function (event) {
+ var serviceInstance = {
+ serviceTemplateId: $('#svcTempl').val(),
+ serviceName: $('#svcName').val(),
+ serviceDescription: $('#svcDesc').val(),
+ serviceParameters: collectServiceParameters(templateParameters),
+ vimLocation: $('#vim_location').val()
+ }
+ var gatewayService = '/openoapi/servicegateway/v1/services';
+ var serviceTemplate = fetchServiceTemplateBy(serviceInstance.serviceTemplateId);
+ if(serviceTemplate === undefined) {
+ return;
+ }
+ if(serviceTemplate.csarType === 'GSAR') {
+ serviceInstance.serviceInstanceId = createGsoServiceInstance(gatewayService, serviceInstance);
+ }else if(serviceTemplate.csarType === 'NSAR' || serviceTemplate.csarType === 'NFAR') {
+ serviceInstance.serviceInstanceId = createNfvoServiceInstance(gatewayService, serviceInstance);
+ }else if(serviceTemplate.csarType === 'SSAR') {
+ serviceInstance.serviceInstanceId = createSdnoServiceInstance(gatewayService, serviceInstance);
+ }
+ if(serviceInstance.serviceInstanceId === undefined) {
+ return;
+ }
+ updateTable(serviceInstance);
+ }
+};
+
+function collectServiceParameters(parameters) {
+ var serviceParameters = {};
+ var i;
+ for( i = 0; i < parameters.length; i += 1) {
+ serviceParameters[parameters.name] = $('#' + parameters[i].id).val();
+ }
+ return serviceParameters;
+}
+
+function fetchServiceTemplateBy(templateId) {
+ var serviceTemplateUri = '/openoapi/catalog/v1/servicetemplates/'+ templateId;
+ var template;
+ $.ajax({
+ type : "GET",
+ async: false,
+ url : serviceTemplateUri,
+ contentType : "application/json",
+ dataType : "json",
+ success : function(jsonResp) {
+ template = {
+ name: jsonResp.templateName,
+ gsarId: jsonResp.csarId
+ }
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ if(template === undefined) {
+ return template;
+ }
+ var queryCsarUri = '/openoapi/catalog/v1/csars/' + template.gsarId;
+ $.ajax({
+ type : "GET",
+ async: false,
+ url : queryCsarUri,
+ contentType : "application/json",
+ dataType : "json",
+ success : function(jsonResp) {
+ template.csarType = jsonResp.type
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ return template;
+}
+
+function renderTemplateParametersTab() {
+ templateParameters = fetchTemplateParameterDefinitions(templateParameters);
+ var vims = fetchVimInfo();
+ var components = transfromToComponents(templateParameters.parameters, vims);
+ document.getElementById("parameterTab").innerHTML = components;
+}
+
+function fetchTemplateParameterDefinitions(parameters) {
+ var serviceTemplate = parameters.templateName;
+ var currentServiceTemplate = $("#svcTempl").val();
+ // Do not need to fetch template parameters if template do not change in UI.
+ if(serviceTemplate === currentServiceTemplate) {
+ return;
+ }
+ var queryParametersUri = '/openoapi/catalog/v1/servicetemplates/' + currentServiceTemplate + '/parameters';
+ var inputParameters = [];
+ $.ajax({
+ type : "GET",
+ async: false,
+ url : queryParametersUri,
+ contentType : "application/json",
+ dataType : "json",
+ success : function(jsonResp) {
+ var inputs = jsonResp.inputs;
+ var i;
+ for( i = 0; i < inputs.length; i += 1) {
+ inputParameters[i] = {
+ name: inputs[i].name,
+ type: inputs[i].type,
+ description: inputs[i].description,
+ defaultValue: inputs[i].defaultValue,
+ required: inputs[i].required,
+ id: 'parameter_' + i,
+ value: inputs[i].defaultValue
+ };
+ }
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ return { name: currentServiceTemplate, parameters: inputParameters };
+}
+
+function fetchVimInfo() {
+ var result = [];
+ var vimQueryUri = '/openoapi/extsys/v1/vims';
+ $.ajax({
+ type : "GET",
+ async: false,
+ url : vimQueryUri,
+ contentType : "application/json",
+ dataType : "json",
+ success : function(jsonResp) {
+ var vims = jsonResp;
+ var i;
+ for( i = 0; i < vims.length; i += 1) {
+ var option = '<option value="' + vims[i].vimId + '">'+vims[i].name+'</option>';
+ result[i] = {
+ vimId: vims[i].vimId,
+ vimName: vims[i].name
+ }
+ }
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ return result;
+}
+
+function transfromToComponents(parameters, vims) {
+ var components = '';
+ var i;
+ for( i = 0; i < parameters.length; i += 1) {
+ var component = '<div class="form-group">' +
+ '<label class="col-sm-3 control-label">' +
+ '<span>' + parameters[i].description + '</span>' + generateRequiredLabel(parameters[i]) +
+ '</label>' +
+ '<div class="col-sm-7">' +
+ '<input type="text" id="'+ parameters[i].id +'" name="parameter description" class="form-control" placeholder="' +
+ parameters[i].description + '" value="'+ parameters[i].value +'" />' +
+ '</div></div>';
+ components = components + component;
+ }
+ components = components + generateLocationComponent(vims);
+ return components;
+}
+
+function generateRequiredLabel(parameter) {
+ var requiredLabel = '';
+ if(parameter.required === 'true') {
+ requiredLabel = '<span class="required">*</span>';
+ }
+ return requiredLabel;
+}
+
+function generateLocationComponent(vims) {
+ var component = '<div class="form-group">' +
+ '<label class="col-sm-3 control-label">' +
+ '<span>Location</span>' +
+ '<span class="required">*</span>' +
+ '</label>' +
+ '<div class="col-sm-7">' +
+ '<select class="form-control" style ="padding-top: 0px;padding-bottom: 0px;"' +
+ ' id="vim_location" name="vim_location">' +
+ transformToOptions(vims) +
+ // '<option value="vimid">vim1 name</option>' +
+ '</select></div></div>';
+ return component;
+}
+
+function transformToOptions(vims) {
+ var options = '';
+ var i;
+ for( i = 0; i < vims.length; i += 1) {
+ var option = '<option value="' + vims[i].vimId + '">'+vims[i].vimName+'</option>';
+ options = options + option;
+ }
+ return options;
+}
+
+function createGsoServiceInstance(gatewayService, serviceInstance) {
+ serviceInstance.serviceParameters.location = serviceInstance.vimLocation;
+ var gsoLcmUri = '/openoapi/lifecyclemgr/v1/services';
+ var parameter = {
+ 'name': serviceInstance.serviceName,
+ 'description': serviceInstance.serviceDescription,
+ 'serviceDefId': serviceTemplate.gsarId,
+ 'templatedId': serviceInstance.serviceTemplateId,
+ 'templateName': serviceTemplate.templateName,
+ 'getewayUri': gsoLcmUrl,
+ 'parameters': serviceInstance.serviceParameters
+ };
+ var serviceInstanceId;
+ $.ajax({
+ type : "POST",
+ async: false,
+ url : gatewayService,
+ contentType : "application/json",
+ dataType : "json",
+ data : JSON.stringify(parameter),
+ success : function(jsonResp) {
+ if(jsonResp.result.errorCode != '200') {
+ alert("Create service instance Error!");
+ return;
+ }
+ serviceInstanceId = jsonResp.serviceId;
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ return serviceInstanceId;
+}
+
+function createNfvoServiceInstance(gatewayService, serviceInstance) {
+ var nfvoLcmNsUrl = '/openoapi/nslcm/v1.0/ns';
+ serviceInstance.serviceParameters.location = serviceInstance.vimLocation;
+ createServiceInstance(gatewayService, nfvoLcmNsUrl, serviceInstance);
+}
+
+function createServiceInstance(gatewayService, gatewayUri, serviceInstance) {
+ var nsInstanceId = createNetworkService(gatewayService, gatewayUri, serviceInstance);
+ if(nsInstanceId === undefined) {
+ return;
+ }
+ instantiateNetworkService(gatewayUri, nsInstanceId, serviceInstance);
+}
+
+function createNetworkService(gatewayService, gatewayUri, serviceInstance) {
+ var parameter = {
+ 'nsdId': serviceInstance.serviceTemplateId,
+ 'nsName': serviceInstance.serviceName,
+ 'description': serviceInstance.serviceDescription,
+ 'gatewayUri': gatewayUri
+ };
+ var nsInstanceId;
+ $.ajax({
+ type : "POST",
+ async: false,
+ url : gatewayService,
+ contentType : "application/json",
+ dataType : "json",
+ data : JSON.stringify(parameter),
+ success : function(jsonResp) {
+ nsInstanceId = jsonResp.nsInstanceId;
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ return nsInstanceId;
+}
+
+function instantiateNetworkService(gatewayUri, nsInstanceId, serviceInstance) {
+ var initNsUrl = gatewayUri + '/' + nsInstanceId + '/Instantiate'
+ var parameter = {
+ 'gatewayUri': initNsUrl,
+ 'nsInstanceId': nsInstanceId,
+ 'additionalParamForNs': serviceInstance.serviceParameters
+ };
+ var result = false;
+ $.ajax({
+ type : "POST",
+ async: false,
+ url : gatewayService,
+ contentType : "application/json",
+ dataType : "json",
+ data : JSON.stringify(parameter),
+ success : function(jsonResp) {
+ result = true;
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ return result;
+}
+
+function createSdnoServiceInstance(gatewayService, serviceInstance) {
+ var sdnoLcmNsUrl = '/openoapi/sdnonslcm/v1.0/ns';
+ createServiceInstance(gatewayService, sdnoLcmNsUrl, serviceInstance);
+}
+
+function updateTable(serviceInstance) {
+ appendOenRow();
+ addDeleteEventRegistration();
+}
+
+function appendOenRow() {
+ var index = service_instance_insert_index;
+ var creator = '';
+ $('#sai').append('<tr id="service_instance_' + index + '"></tr>');
+ $("#service_instance_" + index).html('<td><div class="DataTables_sort_wrapper openo-ellipsis "><span id="service_name" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">'+ serviceInstance.serviceName + '</span></td>' +
+ '<td><span class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">'+ serviceInstance.templateName + '</span></td>' +
+ '<td class="service_template_id"><span class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">'+ serviceInstance.serviceTemplateId + '</span><input type="hidden" value="'+serviceInstance.serviceInstanceId+'"/></td>' +
+ '<td><span class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">'+ formatDate(new Date()) + '</span></td>' +
+ '<td><span class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">'+ creator + '</span></td>' +
+ '<td><button class="data_delete_action"><img id="delete_action" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element " src="images/delete.png"></img></button></td>');
+ service_instance_insert_index += 1;
+}
+
+function formatDate(date) {
+ var year = date.getFullYear();
+ var month = date.getMonth() + 1;
+ var day = date.getDate();
+ var hh = date.getHours();
+ var mm = date.getMinutes();
+ var ss = date.getSeconds();
+ return year + "-" + month + "-" + day + " " + hh + ":" + mm + ":" + ss;
+}
+
+function addDeleteEventRegistration() {
+ $(".data_delete_action").click(function(event) {
+ var trElement = $(this).parents("tr")[0];
+ var tdElement = $(trElement).children("td.service_template_id")[0];
+ var spanElement = $(tdElement).children("span")[0];
+ var templateId = $(spanElement).text();
+ var inputElement = $(tdElement).children("input")[0];
+ var instanceId = $(inputElement).val();
+ var result = deleteServiceInstance(templateId, instanceId);
+ if(result) {
+ trElement.remove();
+ alert("Service instance deleted successfully!");
+ }
+ });
+}
+
+function deleteServiceInstance(templateId, instanceId) {
+ var serviceTemplate = fetchServiceTemplateBy(templateId);
+ if(serviceTemplate === undefined) {
+ return;
+ }
+ var gatewayService = '/openoapi/servicegateway/v1/services';
+ var result = false;
+ if(serviceTemplate.csarType === 'GSAR') {
+ result = deleteGsoServiceInstance(gatewayService, instanceId);
+ }else if(serviceTemplate.csarType === 'NSAR' || serviceTemplate.csarType === 'NFAR') {
+ result = deleteNfvoServiceInstance(gatewayService, instanceId);
+ }else if(serviceTemplate.csarType === 'SSAR') {
+ result = deleteSdnoServiceInstance(gatewayService, instanceId);
+ }
+ return result;
+}
+
+function deleteGsoServiceInstance(gatewayService, instanceId) {
+ var gsoLcmUrl = '/openoapi/lifecyclemgr/v1/services/'+ instanceId;
+ var operation = 'DELETE';
+ return sendDeleteRequest(operation, gatewayService, gsoLcmUrl);
+}
+
+function deleteNfvoServiceInstance(gatewayService, instanceId) {
+ var nfvoNsUrl = '/openoapi/nslcm/v1.0/ns/' + instanceId;
+ var nfvoNsTerminateUrl = nfvoNsUrl +'/terminate';
+ var terminateParameter = {
+ 'nsInstanceId': instanceId,
+ 'terminationType': "graceful",
+ 'gracefulTerminationTimeout': "60",
+ 'operation': "POST",
+ 'gatewayUri': nfvoNsTerminateUrl
+ };
+ var result = sendRequest(gatewayService, terminateParameter);
+ if(result) {
+ var serviceParameter = {
+ 'operation': "DELETE",
+ 'gatewayUri': nfvoNsUrl
+ };
+ result = sendRequest(gatewayService, serviceParameter);
+ }
+ return result;
+}
+
+function deleteSdnoServiceInstance(gatewayService, instanceId) {
+ var sdnoNsUrl = '/openoapi/sdnonslcm/v1.0/ns/' + instanceId;
+ var sdnoNsTerminateUrl = sdnoNsUrl + '/terminate';
+ var terminateParameter = {
+ 'nsInstanceId': instanceId,
+ 'terminationType': "graceful",
+ 'gracefulTerminationTimeout': "60",
+ 'operation': "POST",
+ 'gatewayUri': sdnoNsTerminateUrl
+ };
+ var result = sendDeleteRequest(gatewayService, terminateParameter);
+ if(result) {
+ var serviceParameter = {
+ 'operation': "DELETE",
+ 'gatewayUri': sdnoNsUrl
+ };
+ result = sendDeleteRequest(gatewayService, serviceParameter);
+ }
+ return result;
+}
+
+function sendDeleteRequest(gatewayService, parameter) {
+ var result = false;
+ $.ajax({
+ type : "DELETE",
+ async: false,
+ url : gatewayService,
+ contentType : "application/json",
+ dataType : "json",
+ data : JSON.stringify(parameter),
+ success : function(jsonResp) {
+ result = true;
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ return result;
+}
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/jquery-1.11.2.min.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/jquery-1.11.2.min.js
new file mode 100644
index 00000000..e6a051d0
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/jquery-1.11.2.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.11.2 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.2",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=mb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=nb(b);function qb(){}qb.prototype=d.filters=d.pseudos,d.setFilters=new qb,g=gb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?gb.error(a):z(a,i).slice(0)};function rb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;
+return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==cb()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===cb()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ab:bb):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:bb,isPropagationStopped:bb,isImmediatePropagationStopped:bb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ab,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ab,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ab,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=bb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,m(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=bb),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function db(a){var b=eb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var eb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fb=/ jQuery\d+="(?:null|\d+)"/g,gb=new RegExp("<(?:"+eb+")[\\s/>]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/<tbody/i,lb=/<|&#?\w+;/,mb=/<(?:script|style|link)/i,nb=/checked\s*(?:[^=]|=\s*.checked.)/i,ob=/^$|\/(?:java|ecma)script/i,pb=/^true\/(.*)/,qb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,rb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?"<table>"!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Cb[0].contentWindow||Cb[0].contentDocument).document,b.write(),b.close(),c=Eb(a,b),Cb.detach()),Db[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Gb=/^margin/,Hb=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ib,Jb,Kb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ib=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Hb.test(g)&&Gb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ib=function(a){return a.currentStyle},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Hb.test(g)&&!Kb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Lb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight),b.removeChild(i)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Mb=/alpha\([^)]*\)/i,Nb=/opacity\s*=\s*([^)]*)/,Ob=/^(none|table(?!-c[ea]).+)/,Pb=new RegExp("^("+S+")(.*)$","i"),Qb=new RegExp("^([+-])=("+S+")","i"),Rb={position:"absolute",visibility:"hidden",display:"block"},Sb={letterSpacing:"0",fontWeight:"400"},Tb=["Webkit","O","Moz","ms"];function Ub(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Tb.length;while(e--)if(b=Tb[e]+c,b in a)return b;return d}function Vb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fb(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wb(a,b,c){var d=Pb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Yb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ib(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Jb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Hb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xb(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Jb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ub(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ub(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Jb(a,b,d)),"normal"===f&&b in Sb&&(f=Sb[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Ob.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Rb,function(){return Yb(a,b,d)}):Yb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ib(a);return Wb(a,c,d?Xb(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Nb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Mb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Mb.test(f)?f.replace(Mb,e):f+" "+e)}}),m.cssHooks.marginRight=Lb(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Jb,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Gb.test(a)||(m.cssHooks[a+b].set=Wb)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ib(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Vb(this,!0)},hide:function(){return Vb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Zb(a,b,c,d,e){return new Zb.prototype.init(a,b,c,d,e)
+}m.Tween=Zb,Zb.prototype={constructor:Zb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px")},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Zb.propHooks.scrollTop=Zb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Zb.prototype.init,m.fx.step={};var $b,_b,ac=/^(?:toggle|show|hide)$/,bc=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cc=/queueHooks$/,dc=[ic],ec={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bc.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bc.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fc(){return setTimeout(function(){$b=void 0}),$b=m.now()}function gc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hc(a,b,c){for(var d,e=(ec[b]||[]).concat(ec["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ic(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fb(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fb(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ac.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fb(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hc(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jc(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kc(a,b,c){var d,e,f=0,g=dc.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$b||fc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$b||fc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jc(k,j.opts.specialEasing);g>f;f++)if(d=dc[f].call(j,a,k,j.opts))return d;return m.map(k,hc,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kc,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],ec[c]=ec[c]||[],ec[c].unshift(b)},prefilter:function(a,b){b?dc.unshift(a):dc.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kc(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gc(b,!0),a,d,e)}}),m.each({slideDown:gc("show"),slideUp:gc("hide"),slideToggle:gc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($b=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$b=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_b||(_b=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_b),_b=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lc=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lc,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mc,nc,oc=m.expr.attrHandle,pc=/^(?:checked|selected)$/i,qc=k.getSetAttribute,rc=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nc:mc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rc&&qc||!pc.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qc?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nc={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rc&&qc||!pc.test(c)?a.setAttribute(!qc&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=oc[b]||m.find.attr;oc[b]=rc&&qc||!pc.test(b)?function(a,b,d){var e,f;return d||(f=oc[b],oc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,oc[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rc&&qc||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mc&&mc.set(a,b,c)}}),qc||(mc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},oc.id=oc.name=oc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mc.set},m.attrHooks.contenteditable={set:function(a,b,c){mc.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sc=/^(?:input|select|textarea|button|object)$/i,tc=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sc.test(a.nodeName)||tc.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var uc=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(uc," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vc=m.now(),wc=/\?/,xc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yc,zc,Ac=/#.*$/,Bc=/([?&])_=[^&]*/,Cc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Dc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Ec=/^(?:GET|HEAD)$/,Fc=/^\/\//,Gc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hc={},Ic={},Jc="*/".concat("*");try{zc=location.href}catch(Kc){zc=y.createElement("a"),zc.href="",zc=zc.href}yc=Gc.exec(zc.toLowerCase())||[];function Lc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mc(a,b,c,d){var e={},f=a===Ic;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nc(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Oc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zc,type:"GET",isLocal:Dc.test(yc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nc(Nc(a,m.ajaxSettings),b):Nc(m.ajaxSettings,a)},ajaxPrefilter:Lc(Hc),ajaxTransport:Lc(Ic),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zc)+"").replace(Ac,"").replace(Fc,yc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yc[1]&&c[2]===yc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yc[3]||("http:"===yc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mc(Hc,k,b,v),2===t)return v;h=m.event&&k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Ec.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bc.test(e)?e.replace(Bc,"$1_="+vc++):e+(wc.test(e)?"&":"?")+"_="+vc++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mc(Ic,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Oc(k,v,c)),u=Pc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qc=/%20/g,Rc=/\[\]$/,Sc=/\r?\n/g,Tc=/^(?:submit|button|image|reset|file)$/i,Uc=/^(?:input|select|textarea|keygen)/i;function Vc(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rc.test(a)?d(a,e):Vc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vc(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vc(c,a[c],b,e);return d.join("&").replace(Qc,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Uc.test(this.nodeName)&&!Tc.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sc,"\r\n")}}):{name:b.name,value:c.replace(Sc,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zc()||$c()}:Zc;var Wc=0,Xc={},Yc=m.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Xc)Xc[a](void 0,!0)}),k.cors=!!Yc&&"withCredentials"in Yc,Yc=k.ajax=!!Yc,Yc&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xc[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zc(){try{return new a.XMLHttpRequest}catch(b){}}function $c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _c=[],ad=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_c.pop()||m.expando+"_"+vc++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ad.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ad.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ad,"$1"+e):b.jsonp!==!1&&(b.url+=(wc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_c.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bd=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bd)return bd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cd=a.document.documentElement;function dd(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dd(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cd;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cd})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dd(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=Lb(k.pixelPosition,function(a,c){return c?(c=Jb(a,b),Hb.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ed=a.jQuery,fd=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fd),b&&a.jQuery===m&&(a.jQuery=ed),m},typeof b===K&&(a.jQuery=a.$=m),m});
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/rest.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/rest.js
new file mode 100644
index 00000000..c27dbf07
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/rest.js
@@ -0,0 +1,81 @@
+/* Copyright 2016, Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+$(function(){
+ $('.creat-btn').click(function(){
+ $('#vmAppDialog').addClass('in').css({'display':'block'});
+
+ });
+ $('.close,.button-previous').click(function(){
+ $('#vmAppDialog').removeClass('in').css('display','none');
+ });
+ $('.detail-top ul li').click(function(){
+ $(this).addClass('current').siblings().removeClass('current');
+ });
+ $('.para').click(function(){
+ if($('#serviceTemplateName').val() == ''){
+ alert('Please choose the service templet!');
+ $('#flavorTab').css('display','none');
+ }else{
+ $('#flavorTab').css('display','block');
+ }
+ $('#basicTab').css('display','block');
+ });
+ $('.basic').click(function(){
+ $('#flavorTab').css('display','none');
+ });
+
+ $('.table tbody tr').click(function(){
+ $(this).addClass('openoTable_row_selected').siblings().removeClass('openoTable_row_selected');
+ });
+ $('.table tr:odd').addClass('active');
+ $('#false').click(function(){
+ $('#vmAppDialog').addClass('in').css({'display':'block'});
+ });
+ $('.close,.button-previous').click(function(){
+ $('#vmAppDialog').removeClass('in').css('display','none');
+ });
+ $('#filterTpLogicalType').click(function(){
+ $('#filterTpLogicalType_select_popupcontainer').toggleClass('openo-hide');
+ $('#filterTpLogicalType').toggleClass('openo-focus');
+ var oLeft = $('#open_base_tpL_td6').offset().left;
+ var oTop = $('#open_base_tpL_td6').offset().top;
+ var oHeight = $('#open_base_tpL_td6').height();
+ $('#filterTpLogicalType_select_popupcontainer').css({'left':oLeft,'top':oTop + oHeight + 10});
+ });
+ $('div.openo-select-popup-container>div.openo-select-item>label').click(function(){
+ var Lvalue = $(this).html();
+ $('#filterTpLogicalType_select_input').attr('value',Lvalue);
+ $('#filterTpLogicalType_select_popupcontainer').addClass('openo-hide');
+ $('#filterTpLogicalType').removeClass('openo-focus');
+ });
+ $.fn.serializeObject = function() {
+ var o = {};
+ var a = this.serializeArray();
+ $.each(a, function() {
+ if (o[this.name] !== undefined) {
+ if (!o[this.name].push) {
+ o[this.name] = [ o[this.name] ];
+ }
+ o[this.name].push(this.value || '');
+ } else {
+ o[this.name] = this.value || '';
+ }
+ });
+ return o;
+ };
+
+}) \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Edge.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Edge.js
new file mode 100644
index 00000000..fbdcbd10
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Edge.js
@@ -0,0 +1,33 @@
+/* Copyright 2016, Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var edgeColors = {
+ red : "#f00",
+ green: "#0f0",
+ blue: "#00f",
+ yellow: "#ff0",
+ grey: "#ddd",
+ black: "#000"
+}
+
+function Edge(id, label, source, target, size, color) {
+ this.id = id;
+ this.label = label;
+ this.source = source;
+ this.target = target;
+ this.type = 'line';
+ this.size = size;
+ this.color = edgeColors[color];
+}
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Node.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Node.js
new file mode 100644
index 00000000..340947f7
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Node.js
@@ -0,0 +1,35 @@
+/* Copyright 2016, Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var icon = {
+ type1 : "js/topo/img/NEUP.png",
+ type2 : "js/topo/img/NETWORK.png",
+ type3 : "js/topo/img/site.png"
+}
+function Node(id, label, size, type, x, y) {
+ this.id = id;
+ this.label = label;
+ this.type = "square";
+ this.x = x;
+ this.y = y;
+ this.size = size;
+ this.color = "white";
+ this.borderColor = "white";
+ this.image = {
+ url : icon[type],
+ scale : 1.0,
+ clip : 1.0
+ };
+}
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Topology.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Topology.js
new file mode 100644
index 00000000..d8d27df9
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/Topology.js
@@ -0,0 +1,113 @@
+/* Copyright 2016, Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function Topology(containerId) {
+
+ /**
+ * IMPORTANT: This only works with the canvas renderer. TBD in the future
+ * will also support the WebGL renderer.
+ */
+ sigma.utils.pkg('sigma.canvas.nodes');
+
+ this.s = new sigma({
+ graph : {
+ nodes : [],
+ edges : []
+ },
+ renderer : {
+ // IMPORTANT:
+ // This works only with the canvas renderer, so the
+ // renderer type set as "canvas" is necessary here.
+ container : document.getElementById(containerId),
+ type : 'canvas'
+ },
+ settings : {
+ minNodeSize : 4,
+ maxNodeSize : 48,
+ edgeLabelSize : 'proportional'
+ }
+ });
+ this.addNode = addNode;
+ this.addEdge = addEdge;
+}
+
+function addNode(node) {
+
+ this.s.graph.addNode(node);
+
+}
+
+function addEdge(edge) {
+ this.s.graph.addEdge(edge);
+}
+
+function init() {
+
+ var node1 = new Node("1", "ThinCPE", 8, "type1", 0.2, 0.5);
+ var node2 = new Node("2", "vCPE", 8, "type1", 0.5, 0.5);
+ var node3 = new Node("3", "VPC", 16, "type2", 0.8, 0.5);
+
+ var node4 = new Node("4", "Site", 16, "type3", 0.2, 0.55);
+ var node5 = new Node("5", "POP", 24, "type3", 0.5, 0.55);
+ var node6 = new Node("6", "DC", 32, "type3", 0.8, 0.55);
+
+ var node7 = new Node("7", "vFW", 6, "type1", 0.45, 0.45);
+ var node8 = new Node("8", "vLB", 6, "type1", 0.55, 0.45);
+
+ var edge1 = new Edge("e1", "VxLAN", "1", "2", 0.5, "blue");
+ var edge2 = new Edge("e2", "IPSec", "2", "3", 0.5, "green");
+
+ var edge3 = new Edge("e3", "in", "1", "4", 0.5, "grey");
+ var edge4 = new Edge("e4", "in", "2", "5", 0.5, "grey");
+ var edge5 = new Edge("e5", "in", "3", "6", 0.5, "grey");
+
+ var edge6 = new Edge("e6", "L2VPN", "4", "5", 0.5, "black");
+ var edge7 = new Edge("e7", "L3VPN", "5", "6", 0.5, "black");
+
+ var edge8 = new Edge("e8", "", "2", "7", 0.5, "yellow");
+ var edge9 = new Edge("e9", "", "7", "8", 0.5, "yellow");
+ var edge10 = new Edge("e10", "", "8", "2", 0.5, "yellow");
+
+ var topology = new Topology("container");
+
+ topology.addNode(node1);
+ topology.addNode(node2);
+ topology.addNode(node3);
+ topology.addNode(node4);
+ topology.addNode(node5);
+ topology.addNode(node6);
+ topology.addNode(node7);
+ topology.addNode(node8);
+
+ topology.addEdge(edge1);
+ topology.addEdge(edge2);
+ topology.addEdge(edge3);
+ topology.addEdge(edge4);
+ topology.addEdge(edge5);
+
+
+ topology.addEdge(edge6);
+ topology.addEdge(edge7);
+ topology.addEdge(edge8);
+ topology.addEdge(edge9);
+ topology.addEdge(edge10);
+
+ CustomShapes.init(topology.s);
+ topology.s.refresh();
+}
+
+$(document).ready(function() {
+ init();
+}); \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEDOWN.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEDOWN.png
new file mode 100644
index 00000000..a9bbe5e8
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEDOWN.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEDOWN_selected.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEDOWN_selected.png
new file mode 100644
index 00000000..9fc5aaa3
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEDOWN_selected.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK.png
new file mode 100644
index 00000000..931dbe7b
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK_EDGE.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK_EDGE.png
new file mode 100644
index 00000000..779bdd48
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK_EDGE.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK_selected.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK_selected.png
new file mode 100644
index 00000000..931dbe7b
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NETWORK_selected.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEUP.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEUP.png
new file mode 100644
index 00000000..b82ea857
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEUP.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEUP_selected.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEUP_selected.png
new file mode 100644
index 00000000..65f0dc8d
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/NEUP_selected.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER.png
new file mode 100644
index 00000000..b82ea857
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_0.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_0.png
new file mode 100644
index 00000000..2099f02f
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_0.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_0_selected.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_0_selected.png
new file mode 100644
index 00000000..5a0cf737
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_0_selected.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_1.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_1.png
new file mode 100644
index 00000000..1e958ade
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_1.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_1_selected.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_1_selected.png
new file mode 100644
index 00000000..429a0bed
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_1_selected.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_2.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_2.png
new file mode 100644
index 00000000..c947de26
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_2.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_2_selected.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_2_selected.png
new file mode 100644
index 00000000..bff92e0b
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_2_selected.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_3.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_3.png
new file mode 100644
index 00000000..1a3f560c
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_3.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_3_selected.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_3_selected.png
new file mode 100644
index 00000000..e00bf6df
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_3_selected.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_selected.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_selected.png
new file mode 100644
index 00000000..65f0dc8d
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/OTHER_selected.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/cloud.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/cloud.png
new file mode 100644
index 00000000..e14d0315
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/cloud.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/cloudroute.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/cloudroute.png
new file mode 100644
index 00000000..22d5542a
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/cloudroute.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/crossSubnet.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/crossSubnet.png
new file mode 100644
index 00000000..71216acd
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/crossSubnet.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/delete_asbr.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/delete_asbr.png
new file mode 100644
index 00000000..f9a06bd5
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/delete_asbr.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/mark_sink.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/mark_sink.png
new file mode 100644
index 00000000..2929f63c
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/mark_sink.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/mark_source.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/mark_source.png
new file mode 100644
index 00000000..30aa5bb4
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/mark_source.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/networkdown.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/networkdown.png
new file mode 100644
index 00000000..98c64360
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/networkdown.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_gray.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_gray.png
new file mode 100644
index 00000000..14c287d4
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_gray.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_green.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_green.png
new file mode 100644
index 00000000..70e91f5e
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_green.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_red.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_red.png
new file mode 100644
index 00000000..195df929
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/node_red.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/router.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/router.png
new file mode 100644
index 00000000..b82ea857
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/router.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/router_selected.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/router_selected.png
new file mode 100644
index 00000000..65f0dc8d
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/router_selected.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/site.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/site.png
new file mode 100644
index 00000000..b3538527
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/site.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/siteIcon_feature.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/siteIcon_feature.png
new file mode 100644
index 00000000..9ddf0a36
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/siteIcon_feature.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/site_selected.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/site_selected.png
new file mode 100644
index 00000000..b5c00ae9
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/site_selected.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/sitedown.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/sitedown.png
new file mode 100644
index 00000000..2db4850e
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/sitedown.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/sitedown_selected.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/sitedown_selected.png
new file mode 100644
index 00000000..2d5af835
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/sitedown_selected.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/u1963.png b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/u1963.png
new file mode 100644
index 00000000..631c9ac1
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/img/u1963.png
Binary files differ
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/LICENSE.txt b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/LICENSE.txt
new file mode 100644
index 00000000..81739df1
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/LICENSE.txt
@@ -0,0 +1,12 @@
+Copyright (C) 2013-2014, Alexis Jacomy, http://sigmajs.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/jquery-3.1.0.min.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/jquery-3.1.0.min.js
new file mode 100644
index 00000000..f6a6a99e
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/jquery-3.1.0.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v3.1.0 | (c) jQuery Foundation | jquery.org/license */
+!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.0",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null!=a?a<0?this[a+this.length]:this[a]:f.call(this)},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c<b?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:h,sort:c.sort,splice:c.splice},r.extend=r.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||r.isFunction(g)||(g={}),h===i&&(g=this,h--);h<i;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(r.isPlainObject(d)||(e=r.isArray(d)))?(e?(e=!1,f=c&&r.isArray(c)?c:[]):f=c&&r.isPlainObject(c)?c:{},g[b]=r.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},r.extend({expando:"jQuery"+(q+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===r.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=r.type(a);return("number"===b||"string"===b)&&!isNaN(a-parseFloat(a))},isPlainObject:function(a){var b,c;return!(!a||"[object Object]"!==k.call(a))&&(!(b=e(a))||(c=l.call(b,"constructor")&&b.constructor,"function"==typeof c&&m.call(c)===n))},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?j[k.call(a)]||"object":typeof a},globalEval:function(a){p(a)},camelCase:function(a){return a.replace(t,"ms-").replace(u,v)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(w(a)){for(c=a.length;d<c;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(s,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(w(Object(a))?r.merge(c,"string"==typeof a?[a]:a):h.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:i.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;d<c;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;f<g;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,f=0,h=[];if(w(a))for(d=a.length;f<d;f++)e=b(a[f],f,c),null!=e&&h.push(e);else for(f in a)e=b(a[f],f,c),null!=e&&h.push(e);return g.apply([],h)},guid:1,proxy:function(a,b){var c,d,e;if("string"==typeof b&&(c=a[b],b=a,a=c),r.isFunction(a))return d=f.call(arguments,2),e=function(){return a.apply(b||this,d.concat(f.call(arguments)))},e.guid=a.guid=a.guid||r.guid++,e},now:Date.now,support:o}),"function"==typeof Symbol&&(r.fn[Symbol.iterator]=c[Symbol.iterator]),r.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){j["[object "+b+"]"]=b.toLowerCase()});function w(a){var b=!!a&&"length"in a&&a.length,c=r.type(a);return"function"!==c&&!r.isWindow(a)&&("array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",M="\\["+K+"*("+L+")(?:"+K+"*([*^$|!~]?=)"+K+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+L+"))|)"+K+"*\\]",N=":("+L+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+M+")*)|.*)\\)|)",O=new RegExp(K+"+","g"),P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"label"in b&&b.disabled===a||"form"in b&&b.disabled===a||"form"in b&&b.disabled===!1&&(b.isDisabled===a||b.isDisabled!==!a&&("label"in b||!ea(b))!==a)}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c<b;c+=2)a.push(c);return a}),odd:pa(function(a,b){for(var c=1;c<b;c+=2)a.push(c);return a}),lt:pa(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function ra(){}ra.prototype=d.filters=d.pseudos,d.setFilters=new ra,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=Q.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function sa(a){for(var b=0,c=a.length,d="";b<c;b++)d+=a[b].value;return d}function ta(a,b,c){var d=b.dir,e=b.next,f=e||d,g=c&&"parentNode"===f,h=x++;return b.first?function(b,c,e){while(b=b[d])if(1===b.nodeType||g)return a(b,c,e)}:function(b,c,i){var j,k,l,m=[w,h];if(i){while(b=b[d])if((1===b.nodeType||g)&&a(b,c,i))return!0}else while(b=b[d])if(1===b.nodeType||g)if(l=b[u]||(b[u]={}),k=l[b.uniqueID]||(l[b.uniqueID]={}),e&&e===b.nodeName.toLowerCase())b=b[d]||b;else{if((j=k[f])&&j[0]===w&&j[1]===h)return m[2]=j[2];if(k[f]=m,m[2]=a(b,c,i))return!0}}}function ua(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d<e;d++)ga(a,b[d],c);return c}function wa(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;h<i;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function xa(a,b,c,d,e,f){return d&&!d[u]&&(d=xa(d)),e&&!e[u]&&(e=xa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||va(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:wa(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=wa(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i<f;i++)if(c=d.relative[a[i].type])m=[ta(ua(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;e<f;e++)if(d.relative[a[e].type])break;return xa(i>1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i<e&&ya(a.slice(i,e)),e<f&&ya(a=a.slice(e)),e<f&&sa(a))}m.push(c)}return ua(m)}function za(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(_,aa),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=V.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(_,aa),$.test(j[0].type)&&qa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&sa(j),!a)return G.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||$.test(a)&&qa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){if(r.isFunction(b))return r.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return r.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(C.test(b))return r.filter(b,a,c);b=r.filter(b,a)}return r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType})}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b<d;b++)if(r.contains(e[b],this))return!0}));for(c=this.pushStack([]),b=0;b<d;b++)r.find(a,e[b],c);return d>1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a<c;a++)if(r.contains(this,b[a]))return!0})},closest:function(a,b){var c,d=0,e=this.length,f=[],g="string"!=typeof a&&r(a);if(!A.test(a))for(;d<e;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/\S+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){r.each(b,function(b,c){r.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==r.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return r.each(arguments,function(a,b){var c;while((c=r.inArray(b,f,c))>-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b<f)){if(a=d.apply(h,i),a===c.promise())throw new TypeError("Thenable self-resolution");j=a&&("object"==typeof a||"function"==typeof a)&&a.then,r.isFunction(j)?e?j.call(a,g(f,c,M,e),g(f,c,N,e)):(f++,j.call(a,g(f,c,M,e),g(f,c,N,e),g(f,c,M,c.notifyWith))):(d!==M&&(h=void 0,i=[a]),(e||c.resolveWith)(h,i))}},k=e?j:function(){try{j()}catch(a){r.Deferred.exceptionHook&&r.Deferred.exceptionHook(a,k.stackTrace),b+1>=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,
+r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h<i;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},T=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function U(){this.expando=r.expando+U.uid++}U.uid=1,U.prototype={cache:function(a){var b=a[this.expando];return b||(b={},T(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[r.camelCase(b)]=c;else for(d in b)e[r.camelCase(d)]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][r.camelCase(b)]},access:function(a,b,c){return void 0===b||b&&"string"==typeof b&&void 0===c?this.get(a,b):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d=a[this.expando];if(void 0!==d){if(void 0!==b){r.isArray(b)?b=b.map(r.camelCase):(b=r.camelCase(b),b=b in d?[b]:b.match(K)||[]),c=b.length;while(c--)delete d[b[c]]}(void 0===b||r.isEmptyObject(d))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!r.isEmptyObject(b)}};var V=new U,W=new U,X=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Y=/[A-Z]/g;function Z(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Y,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c||"false"!==c&&("null"===c?null:+c+""===c?+c:X.test(c)?JSON.parse(c):c)}catch(e){}W.set(a,b,c)}else c=void 0;return c}r.extend({hasData:function(a){return W.hasData(a)||V.hasData(a)},data:function(a,b,c){return W.access(a,b,c)},removeData:function(a,b){W.remove(a,b)},_data:function(a,b,c){return V.access(a,b,c)},_removeData:function(a,b){V.remove(a,b)}}),r.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=W.get(f),1===f.nodeType&&!V.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=r.camelCase(d.slice(5)),Z(f,d,e[d])));V.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){W.set(this,a)}):S(this,function(b){var c;if(f&&void 0===b){if(c=W.get(f,a),void 0!==c)return c;if(c=Z(f,a),void 0!==c)return c}else this.each(function(){W.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?r.queue(this[0],a):void 0===b?this:this.each(function(){var c=r.queue(this,a,b);r._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&r.dequeue(this,a)})},dequeue:function(a){return this.each(function(){r.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=r.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=V.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var $=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,_=new RegExp("^(?:([+-])=|)("+$+")([a-z%]*)$","i"),aa=["Top","Right","Bottom","Left"],ba=function(a,b){return a=b||a,"none"===a.style.display||""===a.style.display&&r.contains(a.ownerDocument,a)&&"none"===r.css(a,"display")},ca=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};function da(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return r.css(a,b,"")},i=h(),j=c&&c[3]||(r.cssNumber[b]?"":"px"),k=(r.cssNumber[b]||"px"!==j&&+i)&&_.exec(r.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,r.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var ea={};function fa(a){var b,c=a.ownerDocument,d=a.nodeName,e=ea[d];return e?e:(b=c.body.appendChild(c.createElement(d)),e=r.css(b,"display"),b.parentNode.removeChild(b),"none"===e&&(e="block"),ea[d]=e,e)}function ga(a,b){for(var c,d,e=[],f=0,g=a.length;f<g;f++)d=a[f],d.style&&(c=d.style.display,b?("none"===c&&(e[f]=V.get(d,"display")||null,e[f]||(d.style.display="")),""===d.style.display&&ba(d)&&(e[f]=fa(d))):"none"!==c&&(e[f]="none",V.set(d,"display",c)));for(f=0;f<g;f++)null!=e[f]&&(a[f].style.display=e[f]);return a}r.fn.extend({show:function(){return ga(this,!0)},hide:function(){return ga(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){ba(this)?r(this).show():r(this).hide()})}});var ha=/^(?:checkbox|radio)$/i,ia=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,ja=/^$|\/(?:java|ecma)script/i,ka={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ka.optgroup=ka.option,ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead,ka.th=ka.td;function la(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function ma(a,b){for(var c=0,d=a.length;c<d;c++)V.set(a[c],"globalEval",!b||V.get(b[c],"globalEval"))}var na=/<|&#?\w+;/;function oa(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],n=0,o=a.length;n<o;n++)if(f=a[n],f||0===f)if("object"===r.type(f))r.merge(m,f.nodeType?[f]:f);else if(na.test(f)){g=g||l.appendChild(b.createElement("div")),h=(ia.exec(f)||["",""])[1].toLowerCase(),i=ka[h]||ka._default,g.innerHTML=i[1]+r.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;r.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",n=0;while(f=m[n++])if(d&&r.inArray(f,d)>-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=la(l.appendChild(f),"script"),j&&ma(g),c){k=0;while(f=g[k++])ja.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var pa=d.documentElement,qa=/^key/,ra=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,sa=/^([^.]*)(?:\.(.+)|)/;function ta(){return!0}function ua(){return!1}function va(){try{return d.activeElement}catch(a){}}function wa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)wa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ua;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(pa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c<arguments.length;c++)i[c]=arguments[c];if(b.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,b)!==!1){h=r.event.handlers.call(this,b,j),c=0;while((f=h[c++])&&!b.isPropagationStopped()){b.currentTarget=f.elem,d=0;while((g=f.handlers[d++])&&!b.isImmediatePropagationStopped())b.rnamespace&&!b.rnamespace.test(g.namespace)||(b.handleObj=g,b.data=g.data,e=((r.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(b.result=e)===!1&&(b.preventDefault(),b.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,b),b.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;c<h;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?r(e,this).index(i)>-1:r.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},addProp:function(a,b){Object.defineProperty(r.Event.prototype,a,{enumerable:!0,configurable:!0,get:r.isFunction(b)?function(){if(this.originalEvent)return b(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[a]},set:function(b){Object.defineProperty(this,a,{enumerable:!0,configurable:!0,writable:!0,value:b})}})},fix:function(a){return a[r.expando]?a:new r.Event(a)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==va()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===va()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&r.nodeName(this,"input"))return this.click(),!1},_default:function(a){return r.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},r.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},r.Event=function(a,b){return this instanceof r.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ta:ua,this.target=a.target&&3===a.target.nodeType?a.target.parentNode:a.target,this.currentTarget=a.currentTarget,this.relatedTarget=a.relatedTarget):this.type=a,b&&r.extend(this,b),this.timeStamp=a&&a.timeStamp||r.now(),void(this[r.expando]=!0)):new r.Event(a,b)},r.Event.prototype={constructor:r.Event,isDefaultPrevented:ua,isPropagationStopped:ua,isImmediatePropagationStopped:ua,isSimulated:!1,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ta,a&&!this.isSimulated&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ta,a&&!this.isSimulated&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ta,a&&!this.isSimulated&&a.stopImmediatePropagation(),this.stopPropagation()}},r.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(a){var b=a.button;return null==a.which&&qa.test(a.type)?null!=a.charCode?a.charCode:a.keyCode:!a.which&&void 0!==b&&ra.test(a.type)?1&b?1:2&b?3:4&b?2:0:a.which}},r.event.addProp),r.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){r.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||r.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),r.fn.extend({on:function(a,b,c,d){return wa(this,a,b,c,d)},one:function(a,b,c,d){return wa(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,r(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=ua),this.each(function(){r.event.remove(this,a,c,b)})}});var xa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,ya=/<script|<style|<link/i,za=/checked\s*(?:[^=]|=\s*.checked.)/i,Aa=/^true\/(.*)/,Ba=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Ca(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Da(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ea(a){var b=Aa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c<d;c++)r.event.add(b,e,j[e][c])}W.hasData(a)&&(h=W.access(a),i=r.extend({},h),W.set(b,i))}}function Ga(a,b){var c=b.nodeName.toLowerCase();"input"===c&&ha.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function Ha(a,b,c,d){b=g.apply([],b);var e,f,h,i,j,k,l=0,m=a.length,n=m-1,q=b[0],s=r.isFunction(q);if(s||m>1&&"string"==typeof q&&!o.checkClone&&za.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(m&&(e=oa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(la(e,"script"),Da),i=h.length;l<m;l++)j=e,l!==n&&(j=r.clone(j,!0,!0),i&&r.merge(h,la(j,"script"))),c.call(a[l],j,l);if(i)for(k=h[h.length-1].ownerDocument,r.map(h,Ea),l=0;l<i;l++)j=h[l],ja.test(j.type||"")&&!V.access(j,"globalEval")&&r.contains(k,j)&&(j.src?r._evalUrl&&r._evalUrl(j.src):p(j.textContent.replace(Ba,""),k))}return a}function Ia(a,b,c){for(var d,e=b?r.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||r.cleanData(la(d)),d.parentNode&&(c&&r.contains(d.ownerDocument,d)&&ma(la(d,"script")),d.parentNode.removeChild(d));return a}r.extend({htmlPrefilter:function(a){return a.replace(xa,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=la(h),f=la(a),d=0,e=f.length;d<e;d++)Ga(f[d],g[d]);if(b)if(c)for(f=f||la(a),g=g||la(h),d=0,e=f.length;d<e;d++)Fa(f[d],g[d]);else Fa(a,h);return g=la(h,"script"),g.length>0&&ma(g,!i&&la(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(la(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!ya.test(a)&&!ka[(ia.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c<d;c++)b=this[c]||{},1===b.nodeType&&(r.cleanData(la(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;r.inArray(this,a)<0&&(r.cleanData(la(this)),c&&c.replaceChild(b,this))},a)}}),r.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){r.fn[a]=function(a){for(var c,d=[],e=r(a),f=e.length-1,g=0;g<=f;g++)c=g===f?this:this.clone(!0),r(e[g])[b](c),h.apply(d,c.get());return this.pushStack(d)}});var Ja=/^margin/,Ka=new RegExp("^("+$+")(?!px)[a-z%]+$","i"),La=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)};!function(){function b(){if(i){i.style.cssText="box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",i.innerHTML="",pa.appendChild(h);var b=a.getComputedStyle(i);c="1%"!==b.top,g="2px"===b.marginLeft,e="4px"===b.width,i.style.marginRight="50%",f="4px"===b.marginRight,pa.removeChild(h),i=null}}var c,e,f,g,h=d.createElement("div"),i=d.createElement("div");i.style&&(i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",o.clearCloneStyle="content-box"===i.style.backgroundClip,h.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",h.appendChild(i),r.extend(o,{pixelPosition:function(){return b(),c},boxSizingReliable:function(){return b(),e},pixelMarginRight:function(){return b(),f},reliableMarginLeft:function(){return b(),g}}))}();function Ma(a,b,c){var d,e,f,g,h=a.style;return c=c||La(a),c&&(g=c.getPropertyValue(b)||c[b],""!==g||r.contains(a.ownerDocument,a)||(g=r.style(a,b)),!o.pixelMarginRight()&&Ka.test(g)&&Ja.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function Na(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Oa=/^(none|table(?!-c[ea]).+)/,Pa={position:"absolute",visibility:"hidden",display:"block"},Qa={letterSpacing:"0",fontWeight:"400"},Ra=["Webkit","Moz","ms"],Sa=d.createElement("div").style;function Ta(a){if(a in Sa)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ra.length;while(c--)if(a=Ra[c]+b,a in Sa)return a}function Ua(a,b,c){var d=_.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Va(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;f<4;f+=2)"margin"===c&&(g+=r.css(a,c+aa[f],!0,e)),d?("content"===c&&(g-=r.css(a,"padding"+aa[f],!0,e)),"margin"!==c&&(g-=r.css(a,"border"+aa[f]+"Width",!0,e))):(g+=r.css(a,"padding"+aa[f],!0,e),"padding"!==c&&(g+=r.css(a,"border"+aa[f]+"Width",!0,e)));return g}function Wa(a,b,c){var d,e=!0,f=La(a),g="border-box"===r.css(a,"boxSizing",!1,f);if(a.getClientRects().length&&(d=a.getBoundingClientRect()[b]),d<=0||null==d){if(d=Ma(a,b,f),(d<0||null==d)&&(d=a.style[b]),Ka.test(d))return d;e=g&&(o.boxSizingReliable()||d===a.style[b]),d=parseFloat(d)||0}return d+Va(a,b,c||(g?"border":"content"),e,f)+"px"}r.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Ma(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=r.camelCase(b),i=a.style;return b=r.cssProps[h]||(r.cssProps[h]=Ta(h)||h),g=r.cssHooks[b]||r.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=_.exec(c))&&e[1]&&(c=da(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(r.cssNumber[h]?"":"px")),o.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=r.camelCase(b);return b=r.cssProps[h]||(r.cssProps[h]=Ta(h)||h),g=r.cssHooks[b]||r.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Ma(a,b,d)),"normal"===e&&b in Qa&&(e=Qa[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),r.each(["height","width"],function(a,b){r.cssHooks[b]={get:function(a,c,d){if(c)return!Oa.test(r.css(a,"display"))||a.getClientRects().length&&a.getBoundingClientRect().width?Wa(a,b,d):ca(a,Pa,function(){return Wa(a,b,d)})},set:function(a,c,d){var e,f=d&&La(a),g=d&&Va(a,b,d,"border-box"===r.css(a,"boxSizing",!1,f),f);return g&&(e=_.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=r.css(a,b)),Ua(a,c,g)}}}),r.cssHooks.marginLeft=Na(o.reliableMarginLeft,function(a,b){if(b)return(parseFloat(Ma(a,"marginLeft"))||a.getBoundingClientRect().left-ca(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px"}),r.each({margin:"",padding:"",border:"Width"},function(a,b){r.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];d<4;d++)e[a+aa[d]+b]=f[d]||f[d-2]||f[0];return e}},Ja.test(a)||(r.cssHooks[a+b].set=Ua)}),r.fn.extend({css:function(a,b){return S(this,function(a,b,c){var d,e,f={},g=0;if(r.isArray(b)){for(d=La(a),e=b.length;g<e;g++)f[b[g]]=r.css(a,b[g],!1,d);return f}return void 0!==c?r.style(a,b,c):r.css(a,b)},a,b,arguments.length>1)}});function Xa(a,b,c,d,e){return new Xa.prototype.init(a,b,c,d,e)}r.Tween=Xa,Xa.prototype={constructor:Xa,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Xa.propHooks[this.prop];return a&&a.get?a.get(this):Xa.propHooks._default.get(this)},run:function(a){var b,c=Xa.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Xa.propHooks._default.set(this),this}},Xa.prototype.init.prototype=Xa.prototype,Xa.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Xa.propHooks.scrollTop=Xa.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Xa.prototype.init,r.fx.step={};var Ya,Za,$a=/^(?:toggle|show|hide)$/,_a=/queueHooks$/;function ab(){Za&&(a.requestAnimationFrame(ab),r.fx.tick())}function bb(){return a.setTimeout(function(){Ya=void 0}),Ya=r.now()}function cb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=aa[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function db(a,b,c){for(var d,e=(gb.tweeners[b]||[]).concat(gb.tweeners["*"]),f=0,g=e.length;f<g;f++)if(d=e[f].call(c,b,a))return d}function eb(a,b,c){var d,e,f,g,h,i,j,k,l="width"in b||"height"in b,m=this,n={},o=a.style,p=a.nodeType&&ba(a),q=V.get(a,"fxshow");c.queue||(g=r._queueHooks(a,"fx"),null==g.unqueued&&(g.unqueued=0,h=g.empty.fire,g.empty.fire=function(){g.unqueued||h()}),g.unqueued++,m.always(function(){m.always(function(){g.unqueued--,r.queue(a,"fx").length||g.empty.fire()})}));for(d in b)if(e=b[d],$a.test(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}n[d]=q&&q[d]||r.style(a,d)}if(i=!r.isEmptyObject(b),i||!r.isEmptyObject(n)){l&&1===a.nodeType&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=q&&q.display,null==j&&(j=V.get(a,"display")),k=r.css(a,"display"),"none"===k&&(j?k=j:(ga([a],!0),j=a.style.display||j,k=r.css(a,"display"),ga([a]))),("inline"===k||"inline-block"===k&&null!=j)&&"none"===r.css(a,"float")&&(i||(m.done(function(){o.display=j}),null==j&&(k=o.display,j="none"===k?"":k)),o.display="inline-block")),c.overflow&&(o.overflow="hidden",m.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]})),i=!1;for(d in n)i||(q?"hidden"in q&&(p=q.hidden):q=V.access(a,"fxshow",{display:j}),f&&(q.hidden=!p),p&&ga([a],!0),m.done(function(){p||ga([a]),V.remove(a,"fxshow");for(d in n)r.style(a,d,n[d])})),i=db(p?q[d]:0,d,m),d in q||(q[d]=i.start,p&&(i.end=i.start,i.start=0))}}function fb(a,b){var c,d,e,f,g;for(c in a)if(d=r.camelCase(c),e=b[d],f=a[c],r.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=r.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function gb(a,b,c){var d,e,f=0,g=gb.prefilters.length,h=r.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Ya||bb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;g<i;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),f<1&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:r.extend({},b),opts:r.extend(!0,{specialEasing:{},easing:r.easing._default},c),originalProperties:b,originalOptions:c,startTime:Ya||bb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=r.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;c<d;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(fb(k,j.opts.specialEasing);f<g;f++)if(d=gb.prefilters[f].call(j,a,k,j.opts))return r.isFunction(d.stop)&&(r._queueHooks(j.elem,j.opts.queue).stop=r.proxy(d.stop,d)),d;return r.map(k,db,j),r.isFunction(j.opts.start)&&j.opts.start.call(a,j),r.fx.timer(r.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}r.Animation=r.extend(gb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return da(c.elem,a,_.exec(b),c),c}]},tweener:function(a,b){r.isFunction(a)?(b=a,a=["*"]):a=a.match(K);for(var c,d=0,e=a.length;d<e;d++)c=a[d],gb.tweeners[c]=gb.tweeners[c]||[],gb.tweeners[c].unshift(b)},prefilters:[eb],prefilter:function(a,b){b?gb.prefilters.unshift(a):gb.prefilters.push(a)}}),r.speed=function(a,b,c){var e=a&&"object"==typeof a?r.extend({},a):{complete:c||!c&&b||r.isFunction(a)&&a,duration:a,easing:c&&b||b&&!r.isFunction(b)&&b};return r.fx.off||d.hidden?e.duration=0:e.duration="number"==typeof e.duration?e.duration:e.duration in r.fx.speeds?r.fx.speeds[e.duration]:r.fx.speeds._default,null!=e.queue&&e.queue!==!0||(e.queue="fx"),e.old=e.complete,e.complete=function(){r.isFunction(e.old)&&e.old.call(this),e.queue&&r.dequeue(this,e.queue)},e},r.fn.extend({fadeTo:function(a,b,c,d){return this.filter(ba).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=r.isEmptyObject(a),f=r.speed(b,c,d),g=function(){var b=gb(this,r.extend({},a),f);(e||V.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=r.timers,g=V.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&_a.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||r.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=V.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=r.timers,g=d?d.length:0;for(c.finish=!0,r.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;b<g;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),r.each(["toggle","show","hide"],function(a,b){var c=r.fn[b];r.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(cb(b,!0),a,d,e)}}),r.each({slideDown:cb("show"),slideUp:cb("hide"),slideToggle:cb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){r.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),r.timers=[],r.fx.tick=function(){var a,b=0,c=r.timers;for(Ya=r.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||r.fx.stop(),Ya=void 0},r.fx.timer=function(a){r.timers.push(a),a()?r.fx.start():r.timers.pop()},r.fx.interval=13,r.fx.start=function(){Za||(Za=a.requestAnimationFrame?a.requestAnimationFrame(ab):a.setInterval(r.fx.tick,r.fx.interval))},r.fx.stop=function(){a.cancelAnimationFrame?a.cancelAnimationFrame(Za):a.clearInterval(Za),Za=null},r.fx.speeds={slow:600,fast:200,_default:400},r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var hb,ib=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return S(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?hb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K);
+if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),hb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ib[b]||r.find.attr;ib[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=ib[g],ib[g]=e,e=null!=c(a,b,d)?g:null,ib[g]=f),e}});var jb=/^(?:input|select|textarea|button)$/i,kb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):jb.test(a.nodeName)||kb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});var lb=/[\t\r\n\f]/g;function mb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,mb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,mb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,mb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=mb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(c)+" ").replace(lb," ").indexOf(b)>-1)return!0;return!1}});var nb=/\r/g,ob=/[\x20\t\r\n\f]+/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(nb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:r.trim(r.text(a)).replace(ob," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type,g=f?null:[],h=f?e+1:d.length,i=e<0?h:f?e:0;i<h;i++)if(c=d[i],(c.selected||i===e)&&!c.disabled&&(!c.parentNode.disabled||!r.nodeName(c.parentNode,"optgroup"))){if(b=r(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=r.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=r.inArray(r.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ha.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,""),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Qb=[],Rb=/(=)\?(?=&|$)|\?\?/;r.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Qb.pop()||r.expando+"_"+rb++;return this[a]=!0,a}}),r.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Rb.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Rb.test(b.data)&&"data");if(h||"jsonp"===b.dataTypes[0])return e=b.jsonpCallback=r.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Rb,"$1"+e):b.jsonp!==!1&&(b.url+=(sb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||r.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?r(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Qb.push(e)),g&&r.isFunction(f)&&f(g[0]),g=f=void 0}),"script"}),o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="<form></form><form></form>",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=B.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=oa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))},r.fn.load=function(a,b,c){var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=r.trim(a.slice(h)),a=a.slice(0,h)),r.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&r.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?r("<div>").append(r.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},r.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){r.fn[b]=function(a){return this.on(b,a)}}),r.expr.pseudos.animated=function(a){return r.grep(r.timers,function(b){return a===b.elem}).length};function Sb(a){return r.isWindow(a)?a:9===a.nodeType&&a.defaultView}r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),d.width||d.height?(e=f.ownerDocument,c=Sb(e),b=e.documentElement,{top:d.top+c.pageYOffset-b.clientTop,left:d.left+c.pageXOffset-b.clientLeft}):d):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),r.nodeName(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||pa})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return S(this,function(a,d,e){var f=Sb(a);return void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Na(o.pixelPosition,function(a,c){if(c)return c=Ma(a,b),Ka.test(c)?r(a).position()[b]+"px":c})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return S(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),r.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),r.parseJSON=JSON.parse,"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var Tb=a.jQuery,Ub=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=Ub),b&&a.jQuery===r&&(a.jQuery=Tb),r},b||(a.jQuery=a.$=r),r});
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/plugins/sigma.renderers.customShapes.min.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/plugins/sigma.renderers.customShapes.min.js
new file mode 100644
index 00000000..36376881
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/plugins/sigma.renderers.customShapes.min.js
@@ -0,0 +1 @@
+(function(){"use strict";var a=[],b=function(b,c,d){a.push({name:b,drawShape:c,drawBorder:d})},c=function(){return a},d=function(a){return function(b,c,d,e,f,g){g.fillStyle=f,g.beginPath(),a(b,c,d,e,g),g.closePath(),g.fill()}},e=function(a){return function(b,c,d,e,f,g){g.strokeStyle=f,g.lineWidth=e/5,g.beginPath(),a(b,c,d,e,g),g.closePath(),g.stroke()}},f=function(a,b,c,d,e){var f=45*Math.PI/180;e.moveTo(b+d*Math.sin(f),c-d*Math.cos(f));for(var g=1;4>g;g++)e.lineTo(b+Math.sin(f+2*Math.PI*g/4)*d,c-Math.cos(f+2*Math.PI*g/4)*d)};b("square",d(f),e(f));var g=function(a,b,c,d,e){e.arc(b,c,d,0,2*Math.PI,!0)};b("circle",d(g),e(g));var h=function(a,b,c,d,e){e.moveTo(b-d,c),e.lineTo(b,c-d),e.lineTo(b+d,c),e.lineTo(b,c+d)};b("diamond",d(h),e(h));var i=function(a,b,c,d,e){var f=a.cross&&a.cross.lineWeight||5;e.moveTo(b-d,c-f),e.lineTo(b-d,c+f),e.lineTo(b-f,c+f),e.lineTo(b-f,c+d),e.lineTo(b+f,c+d),e.lineTo(b+f,c+f),e.lineTo(b+d,c+f),e.lineTo(b+d,c-f),e.lineTo(b+f,c-f),e.lineTo(b+f,c-d),e.lineTo(b-f,c-d),e.lineTo(b-f,c-f)};b("cross",d(i),e(i));var j=function(a,b,c,d,e){var f=a.equilateral&&a.equilateral.numPoints||5,g=(a.equilateral&&a.equilateral.rotate||0)*Math.PI/180,h=d;e.moveTo(b+h*Math.sin(g),c-h*Math.cos(g));for(var i=1;f>i;i++)e.lineTo(b+Math.sin(g+2*Math.PI*i/f)*h,c-Math.cos(g+2*Math.PI*i/f)*h)};b("equilateral",d(j),e(j));var k=function(a,b,c,d,e){var f=a.star&&a.star.numPoints||5,g=a.star&&a.star.innerRatio||.5,h=d,i=d*g,j=Math.PI/f;e.moveTo(b,c-d);for(var k=0;f>k;k++)e.lineTo(b+Math.sin(j+2*Math.PI*k/f)*i,c-Math.cos(j+2*Math.PI*k/f)*i),e.lineTo(b+Math.sin(2*Math.PI*(k+1)/f)*h,c-Math.cos(2*Math.PI*(k+1)/f)*h)};b("star",d(k),e(k));var l=function(a,b,c,d,e,f){f.fillStyle="yellow",f.beginPath(),f.arc(b,c,d,1.25*Math.PI,0,!1),f.arc(b,c,d,0,.75*Math.PI,!1),f.lineTo(b,c),f.closePath(),f.fill(),f.fillStyle="white",f.strokeStyle="black",f.beginPath(),f.arc(b+d/3,c-d/3,d/4,0,2*Math.PI,!1),f.closePath(),f.fill(),f.stroke(),f.fillStyle="black",f.beginPath(),f.arc(b+4*d/9,c-d/3,d/8,0,2*Math.PI,!1),f.closePath(),f.fill()};b("pacman",l,null),this.ShapeLibrary={enumerate:c,version:"0.1"}}).call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";if("undefined"==typeof ShapeLibrary)throw"ShapeLibrary is not declared";sigma.utils.pkg("sigma.canvas.nodes"),sigma.utils.pkg("sigma.svg.nodes");var b=a,c={},d=function(a){b=a},e=function(a,d,e,f,g){if(b&&a.image&&a.image.url){var h=a.image.url,i=a.image.h||1,j=a.image.w||1,k=a.image.scale||1,l=a.image.clip||1,m=c[h];m||(m=document.createElement("IMG"),m.src=h,m.status="loading",m.onerror=function(){console.log("error loading",h),m.status="error"},m.onload=function(){console.log("redraw on image load",h),m.status="ok",b.refresh()},c[h]=m);var n=i>j?j/i:1,o=j>i?i/j:1,p=f*k;g.save(),g.beginPath(),g.arc(d,e,f*l,0,2*Math.PI,!0),g.closePath(),g.clip(),"ok"===m.status&&g.drawImage(m,d+Math.sin(-0.7855)*p*n,e-Math.cos(-0.7855)*p*o,p*n*2*Math.sin(-0.7855)*-1,p*o*2*Math.cos(-0.7855)),g.restore()}},f=function(a,c,d){if(b&&a.image&&a.image.url){{var e=document.createElementNS(d("xmlns"),"circle"),f=document.createElementNS(d("xmlns"),"clipPath"),g=d("classPrefix")+"-clip-path-"+a.id,h=document.createElementNS(d("xmlns"),"defs"),i=document.createElementNS(d("xmlns"),"image");a.image.url}f.setAttributeNS(null,"id",g),f.appendChild(e),h.appendChild(f);var j=/MSIE [5-9]/.test(navigator.userAgent)?"":document.location.href;j=j.split("#")[0],i.setAttributeNS(null,"class",d("classPrefix")+"-node-image"),i.setAttributeNS(null,"clip-path","url("+j+"#"+g+")"),i.setAttributeNS(null,"pointer-events","none"),i.setAttributeNS("http://www.w3.org/1999/xlink","href",a.image.url),c.appendChild(h),c.appendChild(i)}},g=function(a,b,c){sigma.canvas.nodes[a]=function(a,d,f){var g=f("prefix")||"",h=a[g+"size"],i=a.color||f("defaultNodeColor"),j=a.borderColor||i,k=a[g+"x"],l=a[g+"y"];d.save(),b&&b(a,k,l,h,i,d),c&&c(a,k,l,h,j,d),e(a,k,l,h,d),d.restore()},sigma.svg.nodes[a]={create:function(a,b){var c=document.createElementNS(b("xmlns"),"g"),d=document.createElementNS(b("xmlns"),"circle");return c.setAttributeNS(null,"class",b("classPrefix")+"-node-group"),c.setAttributeNS(null,"data-node-id",a.id),d.setAttributeNS(null,"data-node-id",a.id),d.setAttributeNS(null,"class",b("classPrefix")+"-node"),d.setAttributeNS(null,"fill",a.color||b("defaultNodeColor")),c.appendChild(d),f(a,c,b),c},update:function(a,b,c){for(var d=c("classPrefix"),e=a.image.clip||1,f=a.image.h||1,g=a.image.w||1,h=c("prefix")||"",i=a.image.scale||1,j=a[h+"size"],k=a[h+"x"],l=a[h+"y"],m=i*j,n=f>g?g/f:1,o=g>f?f/g:1,p=0,q=b.childNodes;p<q.length;p++){var r=q[p].getAttribute("class");switch(r){case d+"-node":q[p].setAttributeNS(null,"cx",k),q[p].setAttributeNS(null,"cy",l),q[p].setAttributeNS(null,"r",j),c("freeStyle")||q[p].setAttributeNS(null,"fill",a.color||c("defaultNodeColor"));break;case d+"-node-image":q[p].setAttributeNS(null,"x",k+Math.sin(-0.7855)*m*n),q[p].setAttributeNS(null,"y",l-Math.cos(-0.7855)*m*o),q[p].setAttributeNS(null,"width",m*n*2*Math.sin(-0.7855)*-1),q[p].setAttributeNS(null,"height",m*o*2*Math.cos(-0.7855));break;default:var s=q[p].firstChild;if(null!=s){var t=d+"-clip-path-"+a.id;s.getAttribute("id")===t&&(s.firstChild.setAttributeNS(null,"cx",k),s.firstChild.setAttributeNS(null,"cy",l),s.firstChild.setAttributeNS(null,"r",e*j))}}}b.style.display=""}}};ShapeLibrary.enumerate().forEach(function(a){g(a.name,a.drawShape,a.drawBorder)}),this.CustomShapes={init:d,version:"0.1"}}.call(this); \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/plugins/sigma.renderers.edgeLabels.min.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/plugins/sigma.renderers.edgeLabels.min.js
new file mode 100644
index 00000000..5b6d07b2
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/plugins/sigma.renderers.edgeLabels.min.js
@@ -0,0 +1 @@
+(function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.settings");var a={defaultEdgeLabelColor:"#000",defaultEdgeLabelActiveColor:"#000",defaultEdgeLabelSize:10,edgeLabelSize:"fixed",edgeLabelSizePowRatio:1,edgeLabelThreshold:1};sigma.settings=sigma.utils.extend(sigma.settings||{},a),sigma.settings.drawEdgeLabels=!0}).call(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.canvas.edges.labels"),sigma.canvas.edges.labels.curve=function(a,b,c,d,e){if("string"==typeof a.label){var f=e("prefix")||"",g=a[f+"size"]||1;if(!(g<e("edgeLabelThreshold"))){var h,i,j,k=b[f+"size"],l=b[f+"x"],m=b[f+"y"],n=c[f+"x"],o=c[f+"y"],p=n-l,q=o-m,r=n>l?1:-1,s={},t=.5;b.id===c.id?(s=sigma.utils.getSelfLoopControlPoints(l,m,k),i=sigma.utils.getPointOnBezierCurve(t,l,m,n,o,s.x1,s.y1,s.x2,s.y2),j=Math.atan2(1,1)):(s=sigma.utils.getQuadraticControlPoint(l,m,n,o),i=sigma.utils.getPointOnQuadraticCurve(t,l,m,n,o,s.x,s.y),j=Math.atan2(q*r,p*r)),h="fixed"===e("edgeLabelSize")?e("defaultEdgeLabelSize"):e("defaultEdgeLabelSize")*g*Math.pow(g,-1/e("edgeLabelSizePowRatio")),d.save(),a.active?(d.font=[e("activeFontStyle"),h+"px",e("activeFont")||e("font")].join(" "),d.fillStyle="edge"===e("edgeActiveColor")?a.active_color||e("defaultEdgeActiveColor"):e("defaultEdgeLabelActiveColor")):(d.font=[e("fontStyle"),h+"px",e("font")].join(" "),d.fillStyle="edge"===e("edgeLabelColor")?a.color||e("defaultEdgeColor"):e("defaultEdgeLabelColor")),d.textAlign="center",d.textBaseline="alphabetic",d.translate(i.x,i.y),d.rotate(j),d.fillText(a.label,0,-g/2-3),d.restore()}}}}.call(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.canvas.edges.labels"),sigma.canvas.edges.labels.curvedArrow=function(a,b,c,d,e){sigma.canvas.edges.labels.curve(a,b,c,d,e)}}.call(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.canvas.edges.labels"),sigma.canvas.edges.labels.def=function(a,b,c,d,e){if("string"==typeof a.label&&b!=c){var f=e("prefix")||"",g=a[f+"size"]||1;if(!(g<e("edgeLabelThreshold"))){if(0===e("edgeLabelSizePowRatio"))throw'"edgeLabelSizePowRatio" must not be 0.';var h,i=(b[f+"x"]+c[f+"x"])/2,j=(b[f+"y"]+c[f+"y"])/2,k=c[f+"x"]-b[f+"x"],l=c[f+"y"]-b[f+"y"],m=b[f+"x"]<c[f+"x"]?1:-1,n=Math.atan2(l*m,k*m);h="fixed"===e("edgeLabelSize")?e("defaultEdgeLabelSize"):e("defaultEdgeLabelSize")*g*Math.pow(g,-1/e("edgeLabelSizePowRatio")),d.save(),a.active?(d.font=[e("activeFontStyle"),h+"px",e("activeFont")||e("font")].join(" "),d.fillStyle="edge"===e("edgeActiveColor")?a.active_color||e("defaultEdgeActiveColor"):e("defaultEdgeLabelActiveColor")):(d.font=[e("fontStyle"),h+"px",e("font")].join(" "),d.fillStyle="edge"===e("edgeLabelColor")?a.color||e("defaultEdgeColor"):e("defaultEdgeLabelColor")),d.textAlign="center",d.textBaseline="alphabetic",d.translate(i,j),d.rotate(n),d.fillText(a.label,0,-g/2-3),d.restore()}}}}.call(this); \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/sigma.min.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/sigma.min.js
new file mode 100644
index 00000000..a34250e0
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/sigma.min.js
@@ -0,0 +1,5 @@
+/* sigma.js - A JavaScript library dedicated to graph drawing. - Version: 1.1.0 - Author: Alexis Jacomy, Sciences-Po Médialab - License: MIT */
+(function(a){"use strict";var b={},c=function(a){var d,e,f,g,h;c.classes.dispatcher.extend(this);var i=this,j=a||{};if("string"==typeof j||j instanceof HTMLElement?j={renderers:[j]}:"[object Array]"===Object.prototype.toString.call(j)&&(j={renderers:j}),g=j.renderers||j.renderer||j.container,j.renderers&&0!==j.renderers.length||("string"==typeof g||g instanceof HTMLElement||"object"==typeof g&&"container"in g)&&(j.renderers=[g]),j.id){if(b[j.id])throw'sigma: Instance "'+j.id+'" already exists.';Object.defineProperty(this,"id",{value:j.id})}else{for(h=0;b[h];)h++;Object.defineProperty(this,"id",{value:""+h})}for(b[this.id]=this,this.settings=new c.classes.configurable(c.settings,j.settings||{}),Object.defineProperty(this,"graph",{value:new c.classes.graph(this.settings),configurable:!0}),Object.defineProperty(this,"middlewares",{value:[],configurable:!0}),Object.defineProperty(this,"cameras",{value:{},configurable:!0}),Object.defineProperty(this,"renderers",{value:{},configurable:!0}),Object.defineProperty(this,"renderersPerCamera",{value:{},configurable:!0}),Object.defineProperty(this,"cameraFrames",{value:{},configurable:!0}),Object.defineProperty(this,"camera",{get:function(){return this.cameras[0]}}),Object.defineProperty(this,"events",{value:["click","rightClick","clickStage","doubleClickStage","rightClickStage","clickNode","clickNodes","doubleClickNode","doubleClickNodes","rightClickNode","rightClickNodes","overNode","overNodes","outNode","outNodes","downNode","downNodes","upNode","upNodes"],configurable:!0}),this._handler=function(a){var b,c={};for(b in a.data)c[b]=a.data[b];c.renderer=a.target,this.dispatchEvent(a.type,c)}.bind(this),f=j.renderers||[],d=0,e=f.length;e>d;d++)this.addRenderer(f[d]);for(f=j.middlewares||[],d=0,e=f.length;e>d;d++)this.middlewares.push("string"==typeof f[d]?c.middlewares[f[d]]:f[d]);"object"==typeof j.graph&&j.graph&&(this.graph.read(j.graph),this.refresh()),window.addEventListener("resize",function(){i.settings&&i.refresh()})};if(c.prototype.addCamera=function(b){var d,e=this;if(!arguments.length){for(b=0;this.cameras[""+b];)b++;b=""+b}if(this.cameras[b])throw'sigma.addCamera: The camera "'+b+'" already exists.';return d=new c.classes.camera(b,this.graph,this.settings),this.cameras[b]=d,d.quadtree=new c.classes.quad,c.classes.edgequad!==a&&(d.edgequadtree=new c.classes.edgequad),d.bind("coordinatesUpdated",function(){e.renderCamera(d,d.isAnimated)}),this.renderersPerCamera[b]=[],d},c.prototype.killCamera=function(a){if(a="string"==typeof a?this.cameras[a]:a,!a)throw"sigma.killCamera: The camera is undefined.";var b,c,d=this.renderersPerCamera[a.id];for(c=d.length,b=c-1;b>=0;b--)this.killRenderer(d[b]);return delete this.renderersPerCamera[a.id],delete this.cameraFrames[a.id],delete this.cameras[a.id],a.kill&&a.kill(),this},c.prototype.addRenderer=function(a){var b,d,e,f,g=a||{};if("string"==typeof g?g={container:document.getElementById(g)}:g instanceof HTMLElement&&(g={container:g}),"string"==typeof g.container&&(g.container=document.getElementById(g.container)),"id"in g)b=g.id;else{for(b=0;this.renderers[""+b];)b++;b=""+b}if(this.renderers[b])throw'sigma.addRenderer: The renderer "'+b+'" already exists.';if(d="function"==typeof g.type?g.type:c.renderers[g.type],d=d||c.renderers.def,e="camera"in g?g.camera instanceof c.classes.camera?g.camera:this.cameras[g.camera]||this.addCamera(g.camera):this.addCamera(),this.cameras[e.id]!==e)throw"sigma.addRenderer: The camera is not properly referenced.";return f=new d(this.graph,e,this.settings,g),this.renderers[b]=f,Object.defineProperty(f,"id",{value:b}),f.bind&&f.bind(["click","rightClick","clickStage","doubleClickStage","rightClickStage","clickNode","clickNodes","clickEdge","clickEdges","doubleClickNode","doubleClickNodes","doubleClickEdge","doubleClickEdges","rightClickNode","rightClickNodes","rightClickEdge","rightClickEdges","overNode","overNodes","overEdge","overEdges","outNode","outNodes","outEdge","outEdges","downNode","downNodes","downEdge","downEdges","upNode","upNodes","upEdge","upEdges"],this._handler),this.renderersPerCamera[e.id].push(f),f},c.prototype.killRenderer=function(a){if(a="string"==typeof a?this.renderers[a]:a,!a)throw"sigma.killRenderer: The renderer is undefined.";var b=this.renderersPerCamera[a.camera.id],c=b.indexOf(a);return c>=0&&b.splice(c,1),a.kill&&a.kill(),delete this.renderers[a.id],this},c.prototype.refresh=function(b){var d,e,f,g,h,i,j=0;for(b=b||{},g=this.middlewares||[],d=0,e=g.length;e>d;d++)g[d].call(this,0===d?"":"tmp"+j+":",d===e-1?"ready:":"tmp"+ ++j+":");for(f in this.cameras)h=this.cameras[f],h.settings("autoRescale")&&this.renderersPerCamera[h.id]&&this.renderersPerCamera[h.id].length?c.middlewares.rescale.call(this,g.length?"ready:":"",h.readPrefix,{width:this.renderersPerCamera[h.id][0].width,height:this.renderersPerCamera[h.id][0].height}):c.middlewares.copy.call(this,g.length?"ready:":"",h.readPrefix),b.skipIndexation||(i=c.utils.getBoundaries(this.graph,h.readPrefix),h.quadtree.index(this.graph.nodes(),{prefix:h.readPrefix,bounds:{x:i.minX,y:i.minY,width:i.maxX-i.minX,height:i.maxY-i.minY}}),h.edgequadtree!==a&&h.settings("drawEdges")&&h.settings("enableEdgeHovering")&&h.edgequadtree.index(this.graph,{prefix:h.readPrefix,bounds:{x:i.minX,y:i.minY,width:i.maxX-i.minX,height:i.maxY-i.minY}}));for(g=Object.keys(this.renderers),d=0,e=g.length;e>d;d++)if(this.renderers[g[d]].process)if(this.settings("skipErrors"))try{this.renderers[g[d]].process()}catch(k){console.log('Warning: The renderer "'+g[d]+'" crashed on ".process()"')}else this.renderers[g[d]].process();return this.render(),this},c.prototype.render=function(){var a,b,c;for(c=Object.keys(this.renderers),a=0,b=c.length;b>a;a++)if(this.settings("skipErrors"))try{this.renderers[c[a]].render()}catch(d){this.settings("verbose")&&console.log('Warning: The renderer "'+c[a]+'" crashed on ".render()"')}else this.renderers[c[a]].render();return this},c.prototype.renderCamera=function(a,b){var c,d,e,f=this;if(b)for(e=this.renderersPerCamera[a.id],c=0,d=e.length;d>c;c++)if(this.settings("skipErrors"))try{e[c].render()}catch(g){this.settings("verbose")&&console.log('Warning: The renderer "'+e[c].id+'" crashed on ".render()"')}else e[c].render();else if(!this.cameraFrames[a.id]){for(e=this.renderersPerCamera[a.id],c=0,d=e.length;d>c;c++)if(this.settings("skipErrors"))try{e[c].render()}catch(g){this.settings("verbose")&&console.log('Warning: The renderer "'+e[c].id+'" crashed on ".render()"')}else e[c].render();this.cameraFrames[a.id]=requestAnimationFrame(function(){delete f.cameraFrames[a.id]})}return this},c.prototype.kill=function(){var a;this.dispatchEvent("kill"),this.graph.kill(),delete this.middlewares;for(a in this.renderers)this.killRenderer(this.renderers[a]);for(a in this.cameras)this.killCamera(this.cameras[a]);delete this.renderers,delete this.cameras;for(a in this)this.hasOwnProperty(a)&&delete this[a];delete b[this.id]},c.instances=function(a){return arguments.length?b[a]:c.utils.extend({},b)},c.version="1.1.0","undefined"!=typeof this.sigma)throw"An object called sigma is already in the global scope.";this.sigma=c}).call(this),function(a){"use strict";function b(a,c){var d,e,f,g;if(arguments.length)if(1===arguments.length&&Object(arguments[0])===arguments[0])for(a in arguments[0])b(a,arguments[0][a]);else if(arguments.length>1)for(g=Array.isArray(a)?a:a.split(/ /),d=0,e=g.length;d!==e;d+=1)f=g[d],C[f]||(C[f]=[]),C[f].push({handler:c})}function c(a,b){var c,d,e,f,g,h,i=Array.isArray(a)?a:a.split(/ /);if(arguments.length)if(b)for(c=0,d=i.length;c!==d;c+=1){if(h=i[c],C[h]){for(g=[],e=0,f=C[h].length;e!==f;e+=1)C[h][e].handler!==b&&g.push(C[h][e]);C[h]=g}C[h]&&0===C[h].length&&delete C[h]}else for(c=0,d=i.length;c!==d;c+=1)delete C[i[c]];else C=Object.create(null)}function d(a,b){var c,d,e,f,g,h,i=Array.isArray(a)?a:a.split(/ /);for(b=void 0===b?{}:b,c=0,e=i.length;c!==e;c+=1)if(h=i[c],C[h])for(g={type:h,data:b||{}},d=0,f=C[h].length;d!==f;d+=1)try{C[h][d].handler(g)}catch(j){}}function e(){var a,b,c,d,e=!1,f=s(),g=x.shift();if(c=g.job(),f=s()-f,g.done++,g.time+=f,g.currentTime+=f,g.weightTime=g.currentTime/(g.weight||1),g.averageTime=g.time/g.done,d=g.count?g.count<=g.done:!c,!d){for(a=0,b=x.length;b>a;a++)if(x[a].weightTime>g.weightTime){x.splice(a,0,g),e=!0;break}e||x.push(g)}return d?g:null}function f(a){var b=x.length;w[a.id]=a,a.status="running",b&&(a.weightTime=x[b-1].weightTime,a.currentTime=a.weightTime*(a.weight||1)),a.startTime=s(),d("jobStarted",q(a)),x.push(a)}function g(){var a,b,c;for(a in v)b=v[a],b.after?y[a]=b:f(b),delete v[a];for(u=!!x.length;x.length&&s()-t<B.frameDuration;)if(c=e()){i(c.id);for(a in y)y[a].after===c.id&&(f(y[a]),delete y[a])}u?(t=s(),d("enterFrame"),setTimeout(g,0)):d("stop")}function h(a,b){var c,e,f;if(Array.isArray(a)){for(A=!0,c=0,e=a.length;e>c;c++)h(a[c].id,p(a[c],b));A=!1,u||(t=s(),d("start"),g())}else if("object"==typeof a)if("string"==typeof a.id)h(a.id,a);else{A=!0;for(c in a)"function"==typeof a[c]?h(c,p({job:a[c]},b)):h(c,p(a[c],b));A=!1,u||(t=s(),d("start"),g())}else{if("string"!=typeof a)throw new Error("[conrad.addJob] Wrong arguments.");if(k(a))throw new Error('[conrad.addJob] Job with id "'+a+'" already exists.');if("function"==typeof b)f={id:a,done:0,time:0,status:"waiting",currentTime:0,averageTime:0,weightTime:0,job:b};else{if("object"!=typeof b)throw new Error("[conrad.addJob] Wrong arguments.");f=p({id:a,done:0,time:0,status:"waiting",currentTime:0,averageTime:0,weightTime:0},b)}v[a]=f,d("jobAdded",q(f)),u||A||(t=s(),d("start"),g())}return this}function i(a){var b,c,e,f,g=!1;if(Array.isArray(a))for(b=0,c=a.length;c>b;b++)i(a[b]);else{if("string"!=typeof a)throw new Error("[conrad.killJob] Wrong arguments.");for(e=[w,y,v],b=0,c=e.length;c>b;b++)a in e[b]&&(f=e[b][a],B.history&&(f.status="done",z.push(f)),d("jobEnded",q(f)),delete e[b][a],"function"==typeof f.end&&f.end(),g=!0);for(e=x,b=0,c=e.length;c>b;b++)if(e[b].id===a){e.splice(b,1);break}if(!g)throw new Error('[conrad.killJob] Job "'+a+'" not found.')}return this}function j(){var a,b=p(v,w,y);if(B.history)for(a in b)b[a].status="done",z.push(b[a]),"function"==typeof b[a].end&&b[a].end();return v={},y={},w={},x=[],u=!1,this}function k(a){var b=v[a]||w[a]||y[a];return b?p(b):null}function l(){var a;if("string"==typeof a1&&1===arguments.length)return B[a1];a="object"==typeof a1&&1===arguments.length?a1||{}:{},"string"==typeof a1&&(a[a1]=a2);for(var b in a)void 0!==a[b]?B[b]=a[b]:delete B[b];return this}function m(){return u}function n(){return z=[],this}function o(a,b){var c,d,e,f,g,h,i;if(!arguments.length){g=[];for(d in v)g.push(v[d]);for(d in y)g.push(y[d]);for(d in w)g.push(w[d]);g=g.concat(z)}if("string"==typeof a)switch(a){case"waiting":g=r(y);break;case"running":g=r(w);break;case"done":g=z;break;default:h=a}if(a instanceof RegExp&&(h=a),!h&&("string"==typeof b||b instanceof RegExp)&&(h=b),h){if(i="string"==typeof h,g instanceof Array)c=g;else if("object"==typeof g){c=[];for(d in g)c=c.concat(g[d])}else{c=[];for(d in v)c.push(v[d]);for(d in y)c.push(y[d]);for(d in w)c.push(w[d]);c=c.concat(z)}for(g=[],e=0,f=c.length;f>e;e++)(i?c[e].id===h:c[e].id.match(h))&&g.push(c[e])}return q(g)}function p(){var a,b,c={},d=arguments.length;for(a=d-1;a>=0;a--)for(b in arguments[a])c[b]=arguments[a][b];return c}function q(a){var b,c,d;if(!a)return a;if(Array.isArray(a))for(b=[],c=0,d=a.length;d>c;c++)b.push(q(a[c]));else if("object"==typeof a){b={};for(c in a)b[c]=q(a[c])}else b=a;return b}function r(a){var b,c=[];for(b in a)c.push(a[b]);return c}function s(){return Date.now?Date.now():(new Date).getTime()}if(a.conrad)throw new Error("conrad already exists");var t,u=!1,v={},w={},x=[],y={},z=[],A=!1,B={frameDuration:20,history:!0},C=Object.create(null);Array.isArray||(Array.isArray=function(a){return"[object Array]"===Object.prototype.toString.call(a)});var D={hasJob:k,addJob:h,killJob:i,killAll:j,settings:l,getStats:o,isRunning:m,clearHistory:n,bind:b,unbind:c,version:"0.1.0"};"undefined"!=typeof exports&&("undefined"!=typeof module&&module.exports&&(exports=module.exports=D),exports.conrad=D),a.conrad=D}(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";var b=this;sigma.utils=sigma.utils||{},sigma.utils.extend=function(){var a,b,c={},d=arguments.length;for(a=d-1;a>=0;a--)for(b in arguments[a])c[b]=arguments[a][b];return c},sigma.utils.dateNow=function(){return Date.now?Date.now():(new Date).getTime()},sigma.utils.pkg=function(a){return(a||"").split(".").reduce(function(a,b){return b in a?a[b]:a[b]={}},b)},sigma.utils.id=function(){var a=0;return function(){return++a}}();var c={};sigma.utils.floatColor=function(a){if(c[a])return c[a];var b=a,d=0,e=0,f=0;"#"===a[0]?(a=a.slice(1),3===a.length?(d=parseInt(a.charAt(0)+a.charAt(0),16),e=parseInt(a.charAt(1)+a.charAt(1),16),f=parseInt(a.charAt(2)+a.charAt(2),16)):(d=parseInt(a.charAt(0)+a.charAt(1),16),e=parseInt(a.charAt(2)+a.charAt(3),16),f=parseInt(a.charAt(4)+a.charAt(5),16))):a.match(/^ *rgba? *\(/)&&(a=a.match(/^ *rgba? *\( *([0-9]*) *, *([0-9]*) *, *([0-9]*) *(,.*)?\) *$/),d=+a[1],e=+a[2],f=+a[3]);var g=256*d*256+256*e+f;return c[b]=g,g},sigma.utils.zoomTo=function(a,b,c,d,e){var f,g,h,i=a.settings;g=Math.max(i("zoomMin"),Math.min(i("zoomMax"),a.ratio*d)),g!==a.ratio&&(d=g/a.ratio,h={x:b*(1-d)+a.x,y:c*(1-d)+a.y,ratio:g},e&&e.duration?(f=sigma.misc.animation.killAll(a),e=sigma.utils.extend(e,{easing:f?"quadraticOut":"quadraticInOut"}),sigma.misc.animation.camera(a,h,e)):(a.goTo(h),e&&e.onComplete&&e.onComplete()))},sigma.utils.getQuadraticControlPoint=function(a,b,c,d){return{x:(a+c)/2+(d-b)/4,y:(b+d)/2+(a-c)/4}},sigma.utils.getPointOnQuadraticCurve=function(a,b,c,d,e,f,g){return{x:Math.pow(1-a,2)*b+2*(1-a)*a*f+Math.pow(a,2)*d,y:Math.pow(1-a,2)*c+2*(1-a)*a*g+Math.pow(a,2)*e}},sigma.utils.getPointOnBezierCurve=function(a,b,c,d,e,f,g,h,i){var j=Math.pow(1-a,3),k=3*a*Math.pow(1-a,2),l=3*Math.pow(a,2)*(1-a),m=Math.pow(a,3);return{x:j*b+k*f+l*h+m*d,y:j*c+k*g+l*i+m*e}},sigma.utils.getSelfLoopControlPoints=function(a,b,c){return{x1:a-7*c,y1:b,x2:a,y2:b+7*c}},sigma.utils.getDistance=function(a,b,c,d){return Math.sqrt(Math.pow(c-a,2)+Math.pow(d-b,2))},sigma.utils.getCircleIntersection=function(a,b,c,d,e,f){var g,h,i,j,k,l,m,n,o;if(h=d-a,i=e-b,j=Math.sqrt(i*i+h*h),j>c+f)return!1;if(j<Math.abs(c-f))return!1;g=(c*c-f*f+j*j)/(2*j),n=a+h*g/j,o=b+i*g/j,k=Math.sqrt(c*c-g*g),l=-i*(k/j),m=h*(k/j);var p=n+l,q=n-l,r=o+m,s=o-m;return{xi:p,xi_prime:q,yi:r,yi_prime:s}},sigma.utils.isPointOnSegment=function(a,b,c,d,e,f,g){var h=Math.abs((b-d)*(e-c)-(a-c)*(f-d)),i=sigma.utils.getDistance(c,d,e,f),j=h/i;return g>j&&Math.min(c,e)<=a&&a<=Math.max(c,e)&&Math.min(d,f)<=b&&b<=Math.max(d,f)},sigma.utils.isPointOnQuadraticCurve=function(a,b,c,d,e,f,g,h,i){var j=sigma.utils.getDistance(c,d,e,f);if(Math.abs(a-c)>j||Math.abs(b-d)>j)return!1;for(var k,l=sigma.utils.getDistance(a,b,c,d),m=sigma.utils.getDistance(a,b,e,f),n=.5,o=m>l?-.01:.01,p=.001,q=100,r=sigma.utils.getPointOnQuadraticCurve(n,c,d,e,f,g,h),s=sigma.utils.getDistance(a,b,r.x,r.y);q-->0&&n>=0&&1>=n&&s>i&&(o>p||-p>o);)k=s,r=sigma.utils.getPointOnQuadraticCurve(n,c,d,e,f,g,h),s=sigma.utils.getDistance(a,b,r.x,r.y),s>k?(o=-o/2,n+=o):0>n+o||n+o>1?(o/=2,s=k):n+=o;return i>s},sigma.utils.isPointOnBezierCurve=function(a,b,c,d,e,f,g,h,i,j,k){var l=sigma.utils.getDistance(c,d,g,h);if(Math.abs(a-c)>l||Math.abs(b-d)>l)return!1;for(var m,n=sigma.utils.getDistance(a,b,c,d),o=sigma.utils.getDistance(a,b,e,f),p=.5,q=o>n?-.01:.01,r=.001,s=100,t=sigma.utils.getPointOnBezierCurve(p,c,d,e,f,g,h,i,j),u=sigma.utils.getDistance(a,b,t.x,t.y);s-->0&&p>=0&&1>=p&&u>k&&(q>r||-r>q);)m=u,t=sigma.utils.getPointOnBezierCurve(p,c,d,e,f,g,h,i,j),u=sigma.utils.getDistance(a,b,t.x,t.y),u>m?(q=-q/2,p+=q):0>p+q||p+q>1?(q/=2,u=m):p+=q;return k>u},sigma.utils.getX=function(b){return b.offsetX!==a&&b.offsetX||b.layerX!==a&&b.layerX||b.clientX!==a&&b.clientX},sigma.utils.getY=function(b){return b.offsetY!==a&&b.offsetY||b.layerY!==a&&b.layerY||b.clientY!==a&&b.clientY},sigma.utils.getPixelRatio=function(){var b=1;return window.screen.deviceXDPI!==a&&window.screen.logicalXDPI!==a&&window.screen.deviceXDPI>window.screen.logicalXDPI?b=window.screen.systemXDPI/window.screen.logicalXDPI:window.devicePixelRatio!==a&&(b=window.devicePixelRatio),b},sigma.utils.getWidth=function(b){var c=b.target.ownerSVGElement?b.target.ownerSVGElement.width:b.target.width;return"number"==typeof c&&c||c!==a&&c.baseVal!==a&&c.baseVal.value},sigma.utils.getCenter=function(a){var b=-1!==a.target.namespaceURI.indexOf("svg")?1:sigma.utils.getPixelRatio();return{x:sigma.utils.getWidth(a)/(2*b),y:sigma.utils.getHeight(a)/(2*b)}},sigma.utils.mouseCoords=function(a,b,c){return b=b||sigma.utils.getX(a),c=c||sigma.utils.getY(a),{x:b-sigma.utils.getCenter(a).x,y:c-sigma.utils.getCenter(a).y,clientX:a.clientX,clientY:a.clientY,ctrlKey:a.ctrlKey,metaKey:a.metaKey,altKey:a.altKey,shiftKey:a.shiftKey}},sigma.utils.getHeight=function(b){var c=b.target.ownerSVGElement?b.target.ownerSVGElement.height:b.target.height;return"number"==typeof c&&c||c!==a&&c.baseVal!==a&&c.baseVal.value},sigma.utils.getDelta=function(b){return b.wheelDelta!==a&&b.wheelDelta||b.detail!==a&&-b.detail},sigma.utils.getOffset=function(a){for(var b=0,c=0;a;)c+=parseInt(a.offsetTop),b+=parseInt(a.offsetLeft),a=a.offsetParent;return{top:c,left:b}},sigma.utils.doubleClick=function(a,b,c){var d,e=0;a._doubleClickHandler=a._doubleClickHandler||{},a._doubleClickHandler[b]=a._doubleClickHandler[b]||[],d=a._doubleClickHandler[b],d.push(function(a){return e++,2===e?(e=0,c(a)):void(1===e&&setTimeout(function(){e=0},sigma.settings.doubleClickTimeout))}),a.addEventListener(b,d[d.length-1],!1)},sigma.utils.unbindDoubleClick=function(a,b){for(var c,d=(a._doubleClickHandler||{})[b]||[];c=d.pop();)a.removeEventListener(b,c);delete(a._doubleClickHandler||{})[b]},sigma.utils.easings=sigma.utils.easings||{},sigma.utils.easings.linearNone=function(a){return a},sigma.utils.easings.quadraticIn=function(a){return a*a},sigma.utils.easings.quadraticOut=function(a){return a*(2-a)},sigma.utils.easings.quadraticInOut=function(a){return(a*=2)<1?.5*a*a:-.5*(--a*(a-2)-1)},sigma.utils.easings.cubicIn=function(a){return a*a*a},sigma.utils.easings.cubicOut=function(a){return--a*a*a+1},sigma.utils.easings.cubicInOut=function(a){return(a*=2)<1?.5*a*a*a:.5*((a-=2)*a*a+2)},sigma.utils.loadShader=function(a,b,c,d){var e,f=a.createShader(c);return a.shaderSource(f,b),a.compileShader(f),e=a.getShaderParameter(f,a.COMPILE_STATUS),e?f:(d&&d('Error compiling shader "'+f+'":'+a.getShaderInfoLog(f)),a.deleteShader(f),null)},sigma.utils.loadProgram=function(a,b,c,d,e){var f,g,h=a.createProgram();for(f=0;f<b.length;++f)a.attachShader(h,b[f]);if(c)for(f=0;f<c.length;++f)a.bindAttribLocation(h,locations?locations[f]:f,opt_attribs[f]);return a.linkProgram(h),g=a.getProgramParameter(h,a.LINK_STATUS),g?h:(e&&e("Error in program linking: "+a.getProgramInfoLog(h)),a.deleteProgram(h),null)},sigma.utils.pkg("sigma.utils.matrices"),sigma.utils.matrices.translation=function(a,b){return[1,0,0,0,1,0,a,b,1]},sigma.utils.matrices.rotation=function(a,b){var c=Math.cos(a),d=Math.sin(a);return b?[c,-d,d,c]:[c,-d,0,d,c,0,0,0,1]},sigma.utils.matrices.scale=function(a,b){return b?[a,0,0,a]:[a,0,0,0,a,0,0,0,1]},sigma.utils.matrices.multiply=function(a,b,c){var d=c?2:3,e=a[0*d+0],f=a[0*d+1],g=a[0*d+2],h=a[1*d+0],i=a[1*d+1],j=a[1*d+2],k=a[2*d+0],l=a[2*d+1],m=a[2*d+2],n=b[0*d+0],o=b[0*d+1],p=b[0*d+2],q=b[1*d+0],r=b[1*d+1],s=b[1*d+2],t=b[2*d+0],u=b[2*d+1],v=b[2*d+2];return c?[e*n+f*q,e*o+f*r,h*n+i*q,h*o+i*r]:[e*n+f*q+g*t,e*o+f*r+g*u,e*p+f*s+g*v,h*n+i*q+j*t,h*o+i*r+j*u,h*p+i*s+j*v,k*n+l*q+m*t,k*o+l*r+m*u,k*p+l*s+m*v]}}.call(this),function(a){"use strict";var b,c=0,d=["ms","moz","webkit","o"];for(b=0;b<d.length&&!a.requestAnimationFrame;b++)a.requestAnimationFrame=a[d[b]+"RequestAnimationFrame"],a.cancelAnimationFrame=a[d[b]+"CancelAnimationFrame"]||a[d[b]+"CancelRequestAnimationFrame"];a.requestAnimationFrame||(a.requestAnimationFrame=function(b){var d=(new Date).getTime(),e=Math.max(0,16-(d-c)),f=a.setTimeout(function(){b(d+e)},e);return c=d+e,f}),a.cancelAnimationFrame||(a.cancelAnimationFrame=function(a){clearTimeout(a)}),Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b,c,d=Array.prototype.slice.call(arguments,1),e=this;return b=function(){},c=function(){return e.apply(this instanceof b&&a?this:a,d.concat(Array.prototype.slice.call(arguments)))},b.prototype=this.prototype,c.prototype=new b,c})}(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.settings");var a={clone:!0,immutable:!0,verbose:!1,classPrefix:"sigma",defaultNodeType:"def",defaultEdgeType:"def",defaultLabelColor:"#000",defaultEdgeColor:"#000",defaultNodeColor:"#000",defaultLabelSize:14,edgeColor:"source",minArrowSize:0,font:"arial",fontStyle:"",labelColor:"default",labelSize:"fixed",labelSizeRatio:1,labelThreshold:8,webglOversamplingRatio:2,borderSize:0,defaultNodeBorderColor:"#000",hoverFont:"",singleHover:!0,hoverFontStyle:"",labelHoverShadow:"default",labelHoverShadowColor:"#000",nodeHoverColor:"node",defaultNodeHoverColor:"#000",labelHoverBGColor:"default",defaultHoverLabelBGColor:"#fff",labelHoverColor:"default",defaultLabelHoverColor:"#000",edgeHoverColor:"edge",edgeHoverSizeRatio:1,defaultEdgeHoverColor:"#000",edgeHoverExtremities:!1,drawEdges:!0,drawNodes:!0,drawLabels:!0,drawEdgeLabels:!1,batchEdgesDrawing:!1,hideEdgesOnMove:!1,canvasEdgesBatchSize:500,webglEdgesBatchSize:1e3,scalingMode:"inside",sideMargin:0,minEdgeSize:.5,maxEdgeSize:1,minNodeSize:1,maxNodeSize:8,touchEnabled:!0,mouseEnabled:!0,mouseWheelEnabled:!0,doubleClickEnabled:!0,eventsEnabled:!0,zoomingRatio:1.7,doubleClickZoomingRatio:2.2,zoomMin:.0625,zoomMax:2,mouseZoomDuration:200,doubleClickZoomDuration:200,mouseInertiaDuration:200,mouseInertiaRatio:3,touchInertiaDuration:200,touchInertiaRatio:3,doubleClickTimeout:300,doubleTapTimeout:300,dragTimeout:200,autoResize:!0,autoRescale:!0,enableCamera:!0,enableHovering:!0,enableEdgeHovering:!1,edgeHoverPrecision:5,rescaleIgnoreSize:!1,skipErrors:!1,nodesPowRatio:.5,edgesPowRatio:.5,animationsTime:200};sigma.settings=sigma.utils.extend(sigma.settings||{},a)}.call(this),function(){"use strict";var a=function(){Object.defineProperty(this,"_handlers",{value:{}})};a.prototype.bind=function(a,b){var c,d,e,f;if(1===arguments.length&&"object"==typeof arguments[0])for(a in arguments[0])this.bind(a,arguments[0][a]);else{if(2!==arguments.length||"function"!=typeof arguments[1])throw"bind: Wrong arguments.";for(f="string"==typeof a?a.split(" "):a,c=0,d=f.length;c!==d;c+=1)e=f[c],e&&(this._handlers[e]||(this._handlers[e]=[]),this._handlers[e].push({handler:b}))}return this},a.prototype.unbind=function(a,b){var c,d,e,f,g,h,i,j="string"==typeof a?a.split(" "):a;if(!arguments.length){for(g in this._handlers)delete this._handlers[g];return this}if(b)for(c=0,d=j.length;c!==d;c+=1){if(i=j[c],this._handlers[i]){for(h=[],e=0,f=this._handlers[i].length;e!==f;e+=1)this._handlers[i][e].handler!==b&&h.push(this._handlers[i][e]);this._handlers[i]=h}this._handlers[i]&&0===this._handlers[i].length&&delete this._handlers[i]}else for(c=0,d=j.length;c!==d;c+=1)delete this._handlers[j[c]];return this},a.prototype.dispatchEvent=function(a,b){var c,d,e,f,g,h,i,j=this,k="string"==typeof a?a.split(" "):a;for(b=void 0===b?{}:b,c=0,d=k.length;c!==d;c+=1)if(i=k[c],this._handlers[i]){for(h=j.getEvent(i,b),g=[],e=0,f=this._handlers[i].length;e!==f;e+=1)this._handlers[i][e].handler(h),this._handlers[i][e].one||g.push(this._handlers[i][e]);this._handlers[i]=g}return this},a.prototype.getEvent=function(a,b){return{type:a,data:b||{},target:this}},a.extend=function(b,c){var d;for(d in a.prototype)a.prototype.hasOwnProperty(d)&&(b[d]=a.prototype[d]);a.apply(b,c)},"undefined"!=typeof this.sigma?(this.sigma.classes=this.sigma.classes||{},this.sigma.classes.dispatcher=a):"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=a),exports.dispatcher=a):this.dispatcher=a}.call(this),function(){"use strict";var a=function(){var b,c,d={},e=Array.prototype.slice.call(arguments,0),f=function(a,b){var c,g,h,i;if(1===arguments.length&&"string"==typeof a){if(void 0!==d[a])return d[a];for(g=0,h=e.length;h>g;g++)if(void 0!==e[g][a])return e[g][a];return void 0}if("object"==typeof a&&"string"==typeof b)return void 0!==(a||{})[b]?a[b]:f(b);for(c="object"==typeof a&&void 0===b?a:{},"string"==typeof a&&(c[a]=b),g=0,i=Object.keys(c),h=i.length;h>g;g++)d[i[g]]=c[i[g]];return this};for(f.embedObjects=function(){var b=e.concat(d).concat(Array.prototype.splice.call(arguments,0));return a.apply({},b)},b=0,c=arguments.length;c>b;b++)f(arguments[b]);return f};"undefined"!=typeof this.sigma?(this.sigma.classes=this.sigma.classes||{},this.sigma.classes.configurable=a):"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=a),exports.configurable=a):this.configurable=a}.call(this),function(){"use strict";function a(a,b,c){var d=function(){var d,e;for(d in g[a])g[a][d].apply(b,arguments);e=c.apply(b,arguments);for(d in f[a])f[a][d].apply(b,arguments);return e};return d}function b(a){var b;for(b in a)"hasOwnProperty"in a&&!a.hasOwnProperty(b)||delete a[b];return a}var c=Object.create(null),d=Object.create(null),e=Object.create(null),f=Object.create(null),g=Object.create(null),h={immutable:!0,clone:!0},i=function(a){return h[a]},j=function(b){var d,f,g;g={settings:b||i,nodesArray:[],edgesArray:[],nodesIndex:Object.create(null),edgesIndex:Object.create(null),inNeighborsIndex:Object.create(null),outNeighborsIndex:Object.create(null),allNeighborsIndex:Object.create(null),inNeighborsCount:Object.create(null),outNeighborsCount:Object.create(null),allNeighborsCount:Object.create(null)};for(d in e)e[d].call(g);for(d in c)f=a(d,g,c[d]),this[d]=f,g[d]=f};j.addMethod=function(a,b){if("string"!=typeof a||"function"!=typeof b||2!==arguments.length)throw"addMethod: Wrong arguments.";if(c[a]||j[a])throw'The method "'+a+'" already exists.';return c[a]=b,f[a]=Object.create(null),g[a]=Object.create(null),this},j.hasMethod=function(a){return!(!c[a]&&!j[a])},j.attach=function(a,b,c,d){if("string"!=typeof a||"string"!=typeof b||"function"!=typeof c||arguments.length<3||arguments.length>4)throw"attach: Wrong arguments.";var h;if("constructor"===a)h=e;else if(d){if(!g[a])throw'The method "'+a+'" does not exist.';h=g[a]}else{if(!f[a])throw'The method "'+a+'" does not exist.';h=f[a]}if(h[b])throw'A function "'+b+'" is already attached to the method "'+a+'".';return h[b]=c,this},j.attachBefore=function(a,b,c){return this.attach(a,b,c,!0)},j.addIndex=function(a,b){if("string"!=typeof a||Object(b)!==b||2!==arguments.length)throw"addIndex: Wrong arguments.";if(d[a])throw'The index "'+a+'" already exists.';var c;d[a]=b;for(c in b){if("function"!=typeof b[c])throw"The bindings must be functions.";j.attach(c,a,b[c])}return this},j.addMethod("addNode",function(a){if(Object(a)!==a||1!==arguments.length)throw"addNode: Wrong arguments.";if("string"!=typeof a.id&&"number"!=typeof a.id)throw"The node must have a string or number id.";if(this.nodesIndex[a.id])throw'The node "'+a.id+'" already exists.';var b,c=a.id,d=Object.create(null);if(this.settings("clone"))for(b in a)"id"!==b&&(d[b]=a[b]);else d=a;return this.settings("immutable")?Object.defineProperty(d,"id",{value:c,enumerable:!0}):d.id=c,this.inNeighborsIndex[c]=Object.create(null),this.outNeighborsIndex[c]=Object.create(null),this.allNeighborsIndex[c]=Object.create(null),this.inNeighborsCount[c]=0,this.outNeighborsCount[c]=0,this.allNeighborsCount[c]=0,this.nodesArray.push(d),this.nodesIndex[d.id]=d,this}),j.addMethod("addEdge",function(a){if(Object(a)!==a||1!==arguments.length)throw"addEdge: Wrong arguments.";if("string"!=typeof a.id&&"number"!=typeof a.id)throw"The edge must have a string or number id.";if("string"!=typeof a.source&&"number"!=typeof a.source||!this.nodesIndex[a.source])throw"The edge source must have an existing node id.";if("string"!=typeof a.target&&"number"!=typeof a.target||!this.nodesIndex[a.target])throw"The edge target must have an existing node id.";if(this.edgesIndex[a.id])throw'The edge "'+a.id+'" already exists.';var b,c=Object.create(null);if(this.settings("clone"))for(b in a)"id"!==b&&"source"!==b&&"target"!==b&&(c[b]=a[b]);else c=a;return this.settings("immutable")?(Object.defineProperty(c,"id",{value:a.id,enumerable:!0}),Object.defineProperty(c,"source",{value:a.source,enumerable:!0}),Object.defineProperty(c,"target",{value:a.target,enumerable:!0})):(c.id=a.id,c.source=a.source,c.target=a.target),this.edgesArray.push(c),this.edgesIndex[c.id]=c,this.inNeighborsIndex[c.target][c.source]||(this.inNeighborsIndex[c.target][c.source]=Object.create(null)),this.inNeighborsIndex[c.target][c.source][c.id]=c,this.outNeighborsIndex[c.source][c.target]||(this.outNeighborsIndex[c.source][c.target]=Object.create(null)),this.outNeighborsIndex[c.source][c.target][c.id]=c,this.allNeighborsIndex[c.source][c.target]||(this.allNeighborsIndex[c.source][c.target]=Object.create(null)),this.allNeighborsIndex[c.source][c.target][c.id]=c,c.target!==c.source&&(this.allNeighborsIndex[c.target][c.source]||(this.allNeighborsIndex[c.target][c.source]=Object.create(null)),this.allNeighborsIndex[c.target][c.source][c.id]=c),this.inNeighborsCount[c.target]++,this.outNeighborsCount[c.source]++,this.allNeighborsCount[c.target]++,this.allNeighborsCount[c.source]++,this}),j.addMethod("dropNode",function(a){if("string"!=typeof a&&"number"!=typeof a||1!==arguments.length)throw"dropNode: Wrong arguments.";if(!this.nodesIndex[a])throw'The node "'+a+'" does not exist.';var b,c,d;for(delete this.nodesIndex[a],b=0,d=this.nodesArray.length;d>b;b++)if(this.nodesArray[b].id===a){this.nodesArray.splice(b,1);break}for(b=this.edgesArray.length-1;b>=0;b--)(this.edgesArray[b].source===a||this.edgesArray[b].target===a)&&this.dropEdge(this.edgesArray[b].id);delete this.inNeighborsIndex[a],delete this.outNeighborsIndex[a],delete this.allNeighborsIndex[a],delete this.inNeighborsCount[a],delete this.outNeighborsCount[a],delete this.allNeighborsCount[a];for(c in this.nodesIndex)delete this.inNeighborsIndex[c][a],delete this.outNeighborsIndex[c][a],delete this.allNeighborsIndex[c][a];return this}),j.addMethod("dropEdge",function(a){if("string"!=typeof a&&"number"!=typeof a||1!==arguments.length)throw"dropEdge: Wrong arguments.";if(!this.edgesIndex[a])throw'The edge "'+a+'" does not exist.';var b,c,d;for(d=this.edgesIndex[a],delete this.edgesIndex[a],b=0,c=this.edgesArray.length;c>b;b++)if(this.edgesArray[b].id===a){this.edgesArray.splice(b,1);break}return delete this.inNeighborsIndex[d.target][d.source][d.id],Object.keys(this.inNeighborsIndex[d.target][d.source]).length||delete this.inNeighborsIndex[d.target][d.source],delete this.outNeighborsIndex[d.source][d.target][d.id],Object.keys(this.outNeighborsIndex[d.source][d.target]).length||delete this.outNeighborsIndex[d.source][d.target],delete this.allNeighborsIndex[d.source][d.target][d.id],Object.keys(this.allNeighborsIndex[d.source][d.target]).length||delete this.allNeighborsIndex[d.source][d.target],d.target!==d.source&&(delete this.allNeighborsIndex[d.target][d.source][d.id],Object.keys(this.allNeighborsIndex[d.target][d.source]).length||delete this.allNeighborsIndex[d.target][d.source]),this.inNeighborsCount[d.target]--,this.outNeighborsCount[d.source]--,this.allNeighborsCount[d.source]--,this.allNeighborsCount[d.target]--,this}),j.addMethod("kill",function(){this.nodesArray.length=0,this.edgesArray.length=0,delete this.nodesArray,delete this.edgesArray,delete this.nodesIndex,delete this.edgesIndex,delete this.inNeighborsIndex,delete this.outNeighborsIndex,delete this.allNeighborsIndex,delete this.inNeighborsCount,delete this.outNeighborsCount,delete this.allNeighborsCount
+}),j.addMethod("clear",function(){return this.nodesArray.length=0,this.edgesArray.length=0,b(this.nodesIndex),b(this.edgesIndex),b(this.nodesIndex),b(this.inNeighborsIndex),b(this.outNeighborsIndex),b(this.allNeighborsIndex),b(this.inNeighborsCount),b(this.outNeighborsCount),b(this.allNeighborsCount),this}),j.addMethod("read",function(a){var b,c,d;for(c=a.nodes||[],b=0,d=c.length;d>b;b++)this.addNode(c[b]);for(c=a.edges||[],b=0,d=c.length;d>b;b++)this.addEdge(c[b]);return this}),j.addMethod("nodes",function(a){if(!arguments.length)return this.nodesArray.slice(0);if(1===arguments.length&&("string"==typeof a||"number"==typeof a))return this.nodesIndex[a];if(1===arguments.length&&"[object Array]"===Object.prototype.toString.call(a)){var b,c,d=[];for(b=0,c=a.length;c>b;b++){if("string"!=typeof a[b]&&"number"!=typeof a[b])throw"nodes: Wrong arguments.";d.push(this.nodesIndex[a[b]])}return d}throw"nodes: Wrong arguments."}),j.addMethod("degree",function(a,b){if(b={"in":this.inNeighborsCount,out:this.outNeighborsCount}[b||""]||this.allNeighborsCount,"string"==typeof a||"number"==typeof a)return b[a];if("[object Array]"===Object.prototype.toString.call(a)){var c,d,e=[];for(c=0,d=a.length;d>c;c++){if("string"!=typeof a[c]&&"number"!=typeof a[c])throw"degree: Wrong arguments.";e.push(b[a[c]])}return e}throw"degree: Wrong arguments."}),j.addMethod("edges",function(a){if(!arguments.length)return this.edgesArray.slice(0);if(1===arguments.length&&("string"==typeof a||"number"==typeof a))return this.edgesIndex[a];if(1===arguments.length&&"[object Array]"===Object.prototype.toString.call(a)){var b,c,d=[];for(b=0,c=a.length;c>b;b++){if("string"!=typeof a[b]&&"number"!=typeof a[b])throw"edges: Wrong arguments.";d.push(this.edgesIndex[a[b]])}return d}throw"edges: Wrong arguments."}),"undefined"!=typeof sigma?(sigma.classes=sigma.classes||Object.create(null),sigma.classes.graph=j):"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports.graph=j):this.graph=j}.call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.classes"),sigma.classes.camera=function(a,b,c,d){sigma.classes.dispatcher.extend(this),Object.defineProperty(this,"graph",{value:b}),Object.defineProperty(this,"id",{value:a}),Object.defineProperty(this,"readPrefix",{value:"read_cam"+a+":"}),Object.defineProperty(this,"prefix",{value:"cam"+a+":"}),this.x=0,this.y=0,this.ratio=1,this.angle=0,this.isAnimated=!1,this.settings="object"==typeof d&&d?c.embedObject(d):c},sigma.classes.camera.prototype.goTo=function(b){if(!this.settings("enableCamera"))return this;var c,d,e=b||{},f=["x","y","ratio","angle"];for(c=0,d=f.length;d>c;c++)if(e[f[c]]!==a){if("number"!=typeof e[f[c]]||isNaN(e[f[c]]))throw'Value for "'+f[c]+'" is not a number.';this[f[c]]=e[f[c]]}return this.dispatchEvent("coordinatesUpdated"),this},sigma.classes.camera.prototype.applyView=function(b,c,d){d=d||{},c=c!==a?c:this.prefix,b=b!==a?b:this.readPrefix;var e,f,g,h=d.nodes||this.graph.nodes(),i=d.edges||this.graph.edges(),j=Math.cos(this.angle),k=Math.sin(this.angle),l=Math.pow(this.ratio,this.settings("nodesPowRatio")),m=Math.pow(this.ratio,this.settings("edgesPowRatio")),n=(d.width||0)/2,o=(d.height||0)/2;for(e=0,f=h.length;f>e;e++)g=h[e],g[c+"x"]=(((g[b+"x"]||0)-this.x)*j+((g[b+"y"]||0)-this.y)*k)/this.ratio+n,g[c+"y"]=(((g[b+"y"]||0)-this.y)*j-((g[b+"x"]||0)-this.x)*k)/this.ratio+o,g[c+"size"]=(g[b+"size"]||0)/l;for(e=0,f=i.length;f>e;e++)i[e][c+"size"]=(i[e][b+"size"]||0)/m;return this},sigma.classes.camera.prototype.graphPosition=function(a,b,c){var d=0,e=0,f=Math.cos(this.angle),g=Math.sin(this.angle);return c||(d=-(this.x*f+this.y*g)/this.ratio,e=-(this.y*f-this.x*g)/this.ratio),{x:(a*f+b*g)/this.ratio+d,y:(b*f-a*g)/this.ratio+e}},sigma.classes.camera.prototype.cameraPosition=function(a,b,c){var d=0,e=0,f=Math.cos(this.angle),g=Math.sin(this.angle);return c||(d=-(this.x*f+this.y*g)/this.ratio,e=-(this.y*f-this.x*g)/this.ratio),{x:((a-d)*f-(b-e)*g)*this.ratio,y:((b-e)*f+(a-d)*g)*this.ratio}},sigma.classes.camera.prototype.getMatrix=function(){var a=sigma.utils.matrices.scale(1/this.ratio),b=sigma.utils.matrices.rotation(this.angle),c=sigma.utils.matrices.translation(-this.x,-this.y),d=sigma.utils.matrices.multiply(c,sigma.utils.matrices.multiply(b,a));return d},sigma.classes.camera.prototype.getRectangle=function(a,b){var c=this.cameraPosition(a,0,!0),d=this.cameraPosition(0,b,!0),e=this.cameraPosition(a/2,b/2,!0),f=this.cameraPosition(a/4,0,!0).x,g=this.cameraPosition(0,b/4,!0).y;return{x1:this.x-e.x-f,y1:this.y-e.y-g,x2:this.x-e.x+f+c.x,y2:this.y-e.y-g+c.y,height:Math.sqrt(Math.pow(d.x,2)+Math.pow(d.y+2*g,2))}}}.call(this),function(a){"use strict";function b(a,b){var c=b.x+b.width/2,d=b.y+b.height/2,e=a.y<d,f=a.x<c;return e?f?0:1:f?2:3}function c(a,b){for(var c=[],d=0;4>d;d++)a.x2>=b[d][0].x&&a.x1<=b[d][1].x&&a.y1+a.height>=b[d][0].y&&a.y1<=b[d][2].y&&c.push(d);return c}function d(a,b){for(var c=[],d=0;4>d;d++)j.collision(a,b[d])&&c.push(d);return c}function e(a,b){var c,d,e=b.level+1,f=Math.round(b.bounds.width/2),g=Math.round(b.bounds.height/2),h=Math.round(b.bounds.x),j=Math.round(b.bounds.y);switch(a){case 0:c=h,d=j;break;case 1:c=h+f,d=j;break;case 2:c=h,d=j+g;break;case 3:c=h+f,d=j+g}return i({x:c,y:d,width:f,height:g},e,b.maxElements,b.maxLevel)}function f(b,d,g){if(g.level<g.maxLevel)for(var h=c(d,g.corners),i=0,j=h.length;j>i;i++)g.nodes[h[i]]===a&&(g.nodes[h[i]]=e(h[i],g)),f(b,d,g.nodes[h[i]]);else g.elements.push(b)}function g(c,d){if(d.level<d.maxLevel){var e=b(c,d.bounds);return d.nodes[e]!==a?g(c,d.nodes[e]):[]}return d.elements}function h(b,c,d,e){if(e=e||{},c.level<c.maxLevel)for(var f=d(b,c.corners),g=0,i=f.length;i>g;g++)c.nodes[f[g]]!==a&&h(b,c.nodes[f[g]],d,e);else for(var j=0,k=c.elements.length;k>j;j++)e[c.elements[j].id]===a&&(e[c.elements[j].id]=c.elements[j]);return e}function i(a,b,c,d){return{level:b||0,bounds:a,corners:j.splitSquare(a),maxElements:c||20,maxLevel:d||4,elements:[],nodes:[]}}var j={pointToSquare:function(a){return{x1:a.x-a.size,y1:a.y-a.size,x2:a.x+a.size,y2:a.y-a.size,height:2*a.size}},isAxisAligned:function(a){return a.x1===a.x2||a.y1===a.y2},axisAlignedTopPoints:function(a){return a.y1===a.y2&&a.x1<a.x2?a:a.x1===a.x2&&a.y2>a.y1?{x1:a.x1-a.height,y1:a.y1,x2:a.x1,y2:a.y1,height:a.height}:a.x1===a.x2&&a.y2<a.y1?{x1:a.x1,y1:a.y2,x2:a.x2+a.height,y2:a.y2,height:a.height}:{x1:a.x2,y1:a.y1-a.height,x2:a.x1,y2:a.y1-a.height,height:a.height}},lowerLeftCoor:function(a){var b=Math.sqrt(Math.pow(a.x2-a.x1,2)+Math.pow(a.y2-a.y1,2));return{x:a.x1-(a.y2-a.y1)*a.height/b,y:a.y1+(a.x2-a.x1)*a.height/b}},lowerRightCoor:function(a,b){return{x:b.x-a.x1+a.x2,y:b.y-a.y1+a.y2}},rectangleCorners:function(a){var b=this.lowerLeftCoor(a),c=this.lowerRightCoor(a,b);return[{x:a.x1,y:a.y1},{x:a.x2,y:a.y2},{x:b.x,y:b.y},{x:c.x,y:c.y}]},splitSquare:function(a){return[[{x:a.x,y:a.y},{x:a.x+a.width/2,y:a.y},{x:a.x,y:a.y+a.height/2},{x:a.x+a.width/2,y:a.y+a.height/2}],[{x:a.x+a.width/2,y:a.y},{x:a.x+a.width,y:a.y},{x:a.x+a.width/2,y:a.y+a.height/2},{x:a.x+a.width,y:a.y+a.height/2}],[{x:a.x,y:a.y+a.height/2},{x:a.x+a.width/2,y:a.y+a.height/2},{x:a.x,y:a.y+a.height},{x:a.x+a.width/2,y:a.y+a.height}],[{x:a.x+a.width/2,y:a.y+a.height/2},{x:a.x+a.width,y:a.y+a.height/2},{x:a.x+a.width/2,y:a.y+a.height},{x:a.x+a.width,y:a.y+a.height}]]},axis:function(a,b){return[{x:a[1].x-a[0].x,y:a[1].y-a[0].y},{x:a[1].x-a[3].x,y:a[1].y-a[3].y},{x:b[0].x-b[2].x,y:b[0].y-b[2].y},{x:b[0].x-b[1].x,y:b[0].y-b[1].y}]},projection:function(a,b){var c=(a.x*b.x+a.y*b.y)/(Math.pow(b.x,2)+Math.pow(b.y,2));return{x:c*b.x,y:c*b.y}},axisCollision:function(a,b,c){for(var d=[],e=[],f=0;4>f;f++){var g=this.projection(b[f],a),h=this.projection(c[f],a);d.push(g.x*a.x+g.y*a.y),e.push(h.x*a.x+h.y*a.y)}var i=Math.max.apply(Math,d),j=Math.max.apply(Math,e),k=Math.min.apply(Math,d),l=Math.min.apply(Math,e);return i>=l&&j>=k},collision:function(a,b){for(var c=this.axis(a,b),d=!0,e=0;4>e;e++)d=d&&this.axisCollision(c[e],a,b);return d}},k=function(){this._geom=j,this._tree=null,this._cache={query:!1,result:!1}};k.prototype.index=function(a,b){if(!b.bounds)throw"sigma.classes.quad.index: bounds information not given.";var c=b.prefix||"";this._tree=i(b.bounds,0,b.maxElements,b.maxLevel);for(var d=0,e=a.length;e>d;d++)f(a[d],j.pointToSquare({x:a[d][c+"x"],y:a[d][c+"y"],size:a[d][c+"size"]}),this._tree);return this._cache={query:!1,result:!1},this._tree},k.prototype.point=function(a,b){return this._tree?g({x:a,y:b},this._tree)||[]:[]},k.prototype.area=function(a){var b,e,f=JSON.stringify(a);if(this._cache.query===f)return this._cache.result;j.isAxisAligned(a)?(b=c,e=j.axisAlignedTopPoints(a)):(b=d,e=j.rectangleCorners(a));var g=this._tree?h(e,this._tree,b):[],i=[];for(var k in g)i.push(g[k]);return this._cache.query=f,this._cache.result=i,i},"undefined"!=typeof this.sigma?(this.sigma.classes=this.sigma.classes||{},this.sigma.classes.quad=k):"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=k),exports.quad=k):this.quad=k}.call(this),function(a){"use strict";function b(a,b){var c=b.x+b.width/2,d=b.y+b.height/2,e=a.y<d,f=a.x<c;return e?f?0:1:f?2:3}function c(a,b){for(var c=[],d=0;4>d;d++)a.x2>=b[d][0].x&&a.x1<=b[d][1].x&&a.y1+a.height>=b[d][0].y&&a.y1<=b[d][2].y&&c.push(d);return c}function d(a,b){for(var c=[],d=0;4>d;d++)j.collision(a,b[d])&&c.push(d);return c}function e(a,b){var c,d,e=b.level+1,f=Math.round(b.bounds.width/2),g=Math.round(b.bounds.height/2),h=Math.round(b.bounds.x),j=Math.round(b.bounds.y);switch(a){case 0:c=h,d=j;break;case 1:c=h+f,d=j;break;case 2:c=h,d=j+g;break;case 3:c=h+f,d=j+g}return i({x:c,y:d,width:f,height:g},e,b.maxElements,b.maxLevel)}function f(b,d,g){if(g.level<g.maxLevel)for(var h=c(d,g.corners),i=0,j=h.length;j>i;i++)g.nodes[h[i]]===a&&(g.nodes[h[i]]=e(h[i],g)),f(b,d,g.nodes[h[i]]);else g.elements.push(b)}function g(c,d){if(d.level<d.maxLevel){var e=b(c,d.bounds);return d.nodes[e]!==a?g(c,d.nodes[e]):[]}return d.elements}function h(b,c,d,e){if(e=e||{},c.level<c.maxLevel)for(var f=d(b,c.corners),g=0,i=f.length;i>g;g++)c.nodes[f[g]]!==a&&h(b,c.nodes[f[g]],d,e);else for(var j=0,k=c.elements.length;k>j;j++)e[c.elements[j].id]===a&&(e[c.elements[j].id]=c.elements[j]);return e}function i(a,b,c,d){return{level:b||0,bounds:a,corners:j.splitSquare(a),maxElements:c||40,maxLevel:d||8,elements:[],nodes:[]}}var j={pointToSquare:function(a){return{x1:a.x-a.size,y1:a.y-a.size,x2:a.x+a.size,y2:a.y-a.size,height:2*a.size}},lineToSquare:function(a){return a.y1<a.y2?a.x1<a.x2?{x1:a.x1-a.size,y1:a.y1-a.size,x2:a.x2+a.size,y2:a.y1-a.size,height:a.y2-a.y1+2*a.size}:{x1:a.x2-a.size,y1:a.y1-a.size,x2:a.x1+a.size,y2:a.y1-a.size,height:a.y2-a.y1+2*a.size}:a.x1<a.x2?{x1:a.x1-a.size,y1:a.y2-a.size,x2:a.x2+a.size,y2:a.y2-a.size,height:a.y1-a.y2+2*a.size}:{x1:a.x2-a.size,y1:a.y2-a.size,x2:a.x1+a.size,y2:a.y2-a.size,height:a.y1-a.y2+2*a.size}},quadraticCurveToSquare:function(a,b){var c=sigma.utils.getPointOnQuadraticCurve(.5,a.x1,a.y1,a.x2,a.y2,b.x,b.y),d=Math.min(a.x1,a.x2,c.x),e=Math.max(a.x1,a.x2,c.x),f=Math.min(a.y1,a.y2,c.y),g=Math.max(a.y1,a.y2,c.y);return{x1:d-a.size,y1:f-a.size,x2:e+a.size,y2:f-a.size,height:g-f+2*a.size}},selfLoopToSquare:function(a){var b=sigma.utils.getSelfLoopControlPoints(a.x,a.y,a.size),c=Math.min(a.x,b.x1,b.x2),d=Math.max(a.x,b.x1,b.x2),e=Math.min(a.y,b.y1,b.y2),f=Math.max(a.y,b.y1,b.y2);return{x1:c-a.size,y1:e-a.size,x2:d+a.size,y2:e-a.size,height:f-e+2*a.size}},isAxisAligned:function(a){return a.x1===a.x2||a.y1===a.y2},axisAlignedTopPoints:function(a){return a.y1===a.y2&&a.x1<a.x2?a:a.x1===a.x2&&a.y2>a.y1?{x1:a.x1-a.height,y1:a.y1,x2:a.x1,y2:a.y1,height:a.height}:a.x1===a.x2&&a.y2<a.y1?{x1:a.x1,y1:a.y2,x2:a.x2+a.height,y2:a.y2,height:a.height}:{x1:a.x2,y1:a.y1-a.height,x2:a.x1,y2:a.y1-a.height,height:a.height}},lowerLeftCoor:function(a){var b=Math.sqrt(Math.pow(a.x2-a.x1,2)+Math.pow(a.y2-a.y1,2));return{x:a.x1-(a.y2-a.y1)*a.height/b,y:a.y1+(a.x2-a.x1)*a.height/b}},lowerRightCoor:function(a,b){return{x:b.x-a.x1+a.x2,y:b.y-a.y1+a.y2}},rectangleCorners:function(a){var b=this.lowerLeftCoor(a),c=this.lowerRightCoor(a,b);return[{x:a.x1,y:a.y1},{x:a.x2,y:a.y2},{x:b.x,y:b.y},{x:c.x,y:c.y}]},splitSquare:function(a){return[[{x:a.x,y:a.y},{x:a.x+a.width/2,y:a.y},{x:a.x,y:a.y+a.height/2},{x:a.x+a.width/2,y:a.y+a.height/2}],[{x:a.x+a.width/2,y:a.y},{x:a.x+a.width,y:a.y},{x:a.x+a.width/2,y:a.y+a.height/2},{x:a.x+a.width,y:a.y+a.height/2}],[{x:a.x,y:a.y+a.height/2},{x:a.x+a.width/2,y:a.y+a.height/2},{x:a.x,y:a.y+a.height},{x:a.x+a.width/2,y:a.y+a.height}],[{x:a.x+a.width/2,y:a.y+a.height/2},{x:a.x+a.width,y:a.y+a.height/2},{x:a.x+a.width/2,y:a.y+a.height},{x:a.x+a.width,y:a.y+a.height}]]},axis:function(a,b){return[{x:a[1].x-a[0].x,y:a[1].y-a[0].y},{x:a[1].x-a[3].x,y:a[1].y-a[3].y},{x:b[0].x-b[2].x,y:b[0].y-b[2].y},{x:b[0].x-b[1].x,y:b[0].y-b[1].y}]},projection:function(a,b){var c=(a.x*b.x+a.y*b.y)/(Math.pow(b.x,2)+Math.pow(b.y,2));return{x:c*b.x,y:c*b.y}},axisCollision:function(a,b,c){for(var d=[],e=[],f=0;4>f;f++){var g=this.projection(b[f],a),h=this.projection(c[f],a);d.push(g.x*a.x+g.y*a.y),e.push(h.x*a.x+h.y*a.y)}var i=Math.max.apply(Math,d),j=Math.max.apply(Math,e),k=Math.min.apply(Math,d),l=Math.min.apply(Math,e);return i>=l&&j>=k},collision:function(a,b){for(var c=this.axis(a,b),d=!0,e=0;4>e;e++)d=d&&this.axisCollision(c[e],a,b);return d}},k=function(){this._geom=j,this._tree=null,this._cache={query:!1,result:!1},this._enabled=!0};k.prototype.index=function(a,b){if(!this._enabled)return this._tree;if(!b.bounds)throw"sigma.classes.edgequad.index: bounds information not given.";var c,d,e,g,h,k=b.prefix||"";this._tree=i(b.bounds,0,b.maxElements,b.maxLevel);for(var l=a.edges(),m=0,n=l.length;n>m;m++)d=a.nodes(l[m].source),e=a.nodes(l[m].target),h={x1:d[k+"x"],y1:d[k+"y"],x2:e[k+"x"],y2:e[k+"y"],size:l[m][k+"size"]||0},"curve"===l[m].type||"curvedArrow"===l[m].type?d.id===e.id?(g={x:d[k+"x"],y:d[k+"y"],size:d[k+"size"]||0},f(l[m],j.selfLoopToSquare(g),this._tree)):(c=sigma.utils.getQuadraticControlPoint(h.x1,h.y1,h.x2,h.y2),f(l[m],j.quadraticCurveToSquare(h,c),this._tree)):f(l[m],j.lineToSquare(h),this._tree);return this._cache={query:!1,result:!1},this._tree},k.prototype.point=function(a,b){return this._enabled&&this._tree?g({x:a,y:b},this._tree)||[]:[]},k.prototype.area=function(a){if(!this._enabled)return[];var b,e,f=JSON.stringify(a);if(this._cache.query===f)return this._cache.result;j.isAxisAligned(a)?(b=c,e=j.axisAlignedTopPoints(a)):(b=d,e=j.rectangleCorners(a));var g=this._tree?h(e,this._tree,b):[],i=[];for(var k in g)i.push(g[k]);return this._cache.query=f,this._cache.result=i,i},"undefined"!=typeof this.sigma?(this.sigma.classes=this.sigma.classes||{},this.sigma.classes.edgequad=k):"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=k),exports.edgequad=k):this.edgequad=k}.call(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.captors"),sigma.captors.mouse=function(a,b,c){function d(a){var b,c,d;return y("mouseEnabled")&&(v.dispatchEvent("mousemove",sigma.utils.mouseCoords(a)),q)?(r=!0,s=!0,u&&clearTimeout(u),u=setTimeout(function(){r=!1},y("dragTimeout")),sigma.misc.animation.killAll(x),x.isMoving=!0,d=x.cameraPosition(sigma.utils.getX(a)-o,sigma.utils.getY(a)-p,!0),b=k-d.x,c=l-d.y,(b!==x.x||c!==x.y)&&(m=x.x,n=x.y,x.goTo({x:b,y:c})),a.preventDefault?a.preventDefault():a.returnValue=!1,a.stopPropagation(),!1):void 0}function e(a){if(y("mouseEnabled")&&q){q=!1,u&&clearTimeout(u),x.isMoving=!1;var b=sigma.utils.getX(a),c=sigma.utils.getY(a);r?(sigma.misc.animation.killAll(x),sigma.misc.animation.camera(x,{x:x.x+y("mouseInertiaRatio")*(x.x-m),y:x.y+y("mouseInertiaRatio")*(x.y-n)},{easing:"quadraticOut",duration:y("mouseInertiaDuration")})):(o!==b||p!==c)&&x.goTo({x:x.x,y:x.y}),v.dispatchEvent("mouseup",sigma.utils.mouseCoords(a)),r=!1}}function f(a){if(y("mouseEnabled"))switch(k=x.x,l=x.y,m=x.x,n=x.y,o=sigma.utils.getX(a),p=sigma.utils.getY(a),s=!1,t=(new Date).getTime(),a.which){case 2:break;case 3:v.dispatchEvent("rightclick",sigma.utils.mouseCoords(a,o,p));break;default:q=!0,v.dispatchEvent("mousedown",sigma.utils.mouseCoords(a,o,p))}}function g(){y("mouseEnabled")&&v.dispatchEvent("mouseout")}function h(a){if(y("mouseEnabled")){var b=sigma.utils.mouseCoords(a);b.isDragging=(new Date).getTime()-t>100&&s,v.dispatchEvent("click",b)}return a.preventDefault?a.preventDefault():a.returnValue=!1,a.stopPropagation(),!1}function i(a){var b,c,d;return y("mouseEnabled")?(c=1/y("doubleClickZoomingRatio"),v.dispatchEvent("doubleclick",sigma.utils.mouseCoords(a,o,p)),y("doubleClickEnabled")&&(b=x.cameraPosition(sigma.utils.getX(a)-sigma.utils.getCenter(a).x,sigma.utils.getY(a)-sigma.utils.getCenter(a).y,!0),d={duration:y("doubleClickZoomDuration")},sigma.utils.zoomTo(x,b.x,b.y,c,d)),a.preventDefault?a.preventDefault():a.returnValue=!1,a.stopPropagation(),!1):void 0}function j(a){var b,c,d;return y("mouseEnabled")&&y("mouseWheelEnabled")?(c=sigma.utils.getDelta(a)>0?1/y("zoomingRatio"):y("zoomingRatio"),b=x.cameraPosition(sigma.utils.getX(a)-sigma.utils.getCenter(a).x,sigma.utils.getY(a)-sigma.utils.getCenter(a).y,!0),d={duration:y("mouseZoomDuration")},sigma.utils.zoomTo(x,b.x,b.y,c,d),a.preventDefault?a.preventDefault():a.returnValue=!1,a.stopPropagation(),!1):void 0}var k,l,m,n,o,p,q,r,s,t,u,v=this,w=a,x=b,y=c;sigma.classes.dispatcher.extend(this),sigma.utils.doubleClick(w,"click",i),w.addEventListener("DOMMouseScroll",j,!1),w.addEventListener("mousewheel",j,!1),w.addEventListener("mousemove",d,!1),w.addEventListener("mousedown",f,!1),w.addEventListener("click",h,!1),w.addEventListener("mouseout",g,!1),document.addEventListener("mouseup",e,!1),this.kill=function(){sigma.utils.unbindDoubleClick(w,"click"),w.removeEventListener("DOMMouseScroll",j),w.removeEventListener("mousewheel",j),w.removeEventListener("mousemove",d),w.removeEventListener("mousedown",f),w.removeEventListener("click",h),w.removeEventListener("mouseout",g),document.removeEventListener("mouseup",e)}}}.call(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.captors"),sigma.captors.touch=function(a,b,c){function d(a){var b=sigma.utils.getOffset(B);return{x:a.pageX-b.left,y:a.pageY-b.top}}function e(a){if(D("touchEnabled")){var b,c,e,f,g,h;switch(E=a.touches,E.length){case 1:C.isMoving=!0,w=1,i=C.x,j=C.y,m=C.x,n=C.y,g=d(E[0]),q=g.x,r=g.y;break;case 2:return C.isMoving=!0,w=2,g=d(E[0]),h=d(E[1]),b=g.x,e=g.y,c=h.x,f=h.y,m=C.x,n=C.y,k=C.angle,l=C.ratio,i=C.x,j=C.y,q=b,r=e,s=c,t=f,u=Math.atan2(t-r,s-q),v=Math.sqrt((t-r)*(t-r)+(s-q)*(s-q)),a.preventDefault(),!1}}}function f(a){if(D("touchEnabled")){E=a.touches;var b=D("touchInertiaRatio");switch(z&&(x=!1,clearTimeout(z)),w){case 2:if(1===a.touches.length){e(a),a.preventDefault();break}case 1:C.isMoving=!1,A.dispatchEvent("stopDrag"),x&&(y=!1,sigma.misc.animation.camera(C,{x:C.x+b*(C.x-m),y:C.y+b*(C.y-n)},{easing:"quadraticOut",duration:D("touchInertiaDuration")})),x=!1,w=0}}}function g(a){if(!y&&D("touchEnabled")){var b,c,e,f,g,h,B,F,G,H,I,J,K,L,M,N,O;switch(E=a.touches,x=!0,z&&clearTimeout(z),z=setTimeout(function(){x=!1},D("dragTimeout")),w){case 1:F=d(E[0]),b=F.x,e=F.y,H=C.cameraPosition(b-q,e-r,!0),L=i-H.x,M=j-H.y,(L!==C.x||M!==C.y)&&(m=C.x,n=C.y,C.goTo({x:L,y:M}),A.dispatchEvent("mousemove",sigma.utils.mouseCoords(a,F.x,F.y)),A.dispatchEvent("drag"));break;case 2:F=d(E[0]),G=d(E[1]),b=F.x,e=F.y,c=G.x,f=G.y,I=C.cameraPosition((q+s)/2-sigma.utils.getCenter(a).x,(r+t)/2-sigma.utils.getCenter(a).y,!0),B=C.cameraPosition((b+c)/2-sigma.utils.getCenter(a).x,(e+f)/2-sigma.utils.getCenter(a).y,!0),J=Math.atan2(f-e,c-b)-u,K=Math.sqrt((f-e)*(f-e)+(c-b)*(c-b))/v,b=I.x,e=I.y,N=l/K,b*=K,e*=K,O=k-J,g=Math.cos(-J),h=Math.sin(-J),c=b*g+e*h,f=e*g-b*h,b=c,e=f,L=b-B.x+i,M=e-B.y+j,(N!==C.ratio||O!==C.angle||L!==C.x||M!==C.y)&&(m=C.x,n=C.y,o=C.angle,p=C.ratio,C.goTo({x:L,y:M,angle:O,ratio:N}),A.dispatchEvent("drag"))}return a.preventDefault(),!1}}function h(a){var b,c,e;return a.touches&&1===a.touches.length&&D("touchEnabled")?(y=!0,c=1/D("doubleClickZoomingRatio"),b=d(a.touches[0]),A.dispatchEvent("doubleclick",sigma.utils.mouseCoords(a,b.x,b.y)),D("doubleClickEnabled")&&(b=C.cameraPosition(b.x-sigma.utils.getCenter(a).x,b.y-sigma.utils.getCenter(a).y,!0),e={duration:D("doubleClickZoomDuration"),onComplete:function(){y=!1}},sigma.utils.zoomTo(C,b.x,b.y,c,e)),a.preventDefault?a.preventDefault():a.returnValue=!1,a.stopPropagation(),!1):void 0}var i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A=this,B=a,C=b,D=c,E=[];sigma.classes.dispatcher.extend(this),sigma.utils.doubleClick(B,"touchstart",h),B.addEventListener("touchstart",e,!1),B.addEventListener("touchend",f,!1),B.addEventListener("touchcancel",f,!1),B.addEventListener("touchleave",f,!1),B.addEventListener("touchmove",g,!1),this.kill=function(){sigma.utils.unbindDoubleClick(B,"touchstart"),B.addEventListener("touchstart",e),B.addEventListener("touchend",f),B.addEventListener("touchcancel",f),B.addEventListener("touchleave",f),B.addEventListener("touchmove",g)}}}.call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";if("undefined"==typeof conrad)throw"conrad is not declared";sigma.utils.pkg("sigma.renderers"),sigma.renderers.canvas=function(a,b,c,d){if("object"!=typeof d)throw"sigma.renderers.canvas: Wrong arguments.";if(!(d.container instanceof HTMLElement))throw"Container not found.";var e,f,g,h;for(sigma.classes.dispatcher.extend(this),Object.defineProperty(this,"conradId",{value:sigma.utils.id()}),this.graph=a,this.camera=b,this.contexts={},this.domElements={},this.options=d,this.container=this.options.container,this.settings="object"==typeof d.settings&&d.settings?c.embedObjects(d.settings):c,this.nodesOnScreen=[],this.edgesOnScreen=[],this.jobs={},this.options.prefix="renderer"+this.conradId+":",this.settings("batchEdgesDrawing")?(this.initDOM("canvas","edges"),this.initDOM("canvas","scene"),this.contexts.nodes=this.contexts.scene,this.contexts.labels=this.contexts.scene):(this.initDOM("canvas","scene"),this.contexts.edges=this.contexts.scene,this.contexts.nodes=this.contexts.scene,this.contexts.labels=this.contexts.scene),this.initDOM("canvas","mouse"),this.contexts.hover=this.contexts.mouse,this.captors=[],g=this.options.captors||[sigma.captors.mouse,sigma.captors.touch],e=0,f=g.length;f>e;e++)h="function"==typeof g[e]?g[e]:sigma.captors[g[e]],this.captors.push(new h(this.domElements.mouse,this.camera,this.settings));sigma.misc.bindEvents.call(this,this.options.prefix),sigma.misc.drawHovers.call(this,this.options.prefix),this.resize(!1)},sigma.renderers.canvas.prototype.render=function(b){b=b||{};var c,d,e,f,g,h,i,j,k,l,m,n,o,p={},q=this.graph,r=this.graph.nodes,s=(this.options.prefix||"",this.settings(b,"drawEdges")),t=this.settings(b,"drawNodes"),u=this.settings(b,"drawLabels"),v=this.settings(b,"drawEdgeLabels"),w=this.settings.embedObjects(b,{prefix:this.options.prefix});this.resize(!1),this.settings(b,"hideEdgesOnMove")&&(this.camera.isAnimated||this.camera.isMoving)&&(s=!1),this.camera.applyView(a,this.options.prefix,{width:this.width,height:this.height}),this.clear();for(e in this.jobs)conrad.hasJob(e)&&conrad.killJob(e);for(this.edgesOnScreen=[],this.nodesOnScreen=this.camera.quadtree.area(this.camera.getRectangle(this.width,this.height)),c=this.nodesOnScreen,d=0,f=c.length;f>d;d++)p[c[d].id]=c[d];if(s){for(c=q.edges(),d=0,f=c.length;f>d;d++)g=c[d],!p[g.source]&&!p[g.target]||g.hidden||r(g.source).hidden||r(g.target).hidden||this.edgesOnScreen.push(g);if(this.settings(b,"batchEdgesDrawing"))h="edges_"+this.conradId,n=w("canvasEdgesBatchSize"),l=this.edgesOnScreen,f=l.length,k=0,i=Math.min(l.length,k+n),j=function(){for(o=this.contexts.edges.globalCompositeOperation,this.contexts.edges.globalCompositeOperation="destination-over",m=sigma.canvas.edges,d=k;i>d;d++)g=l[d],(m[g.type||this.settings(b,"defaultEdgeType")]||m.def)(g,q.nodes(g.source),q.nodes(g.target),this.contexts.edges,w);if(v)for(m=sigma.canvas.edges.labels,d=k;i>d;d++)g=l[d],g.hidden||(m[g.type||this.settings(b,"defaultEdgeType")]||m.def)(g,q.nodes(g.source),q.nodes(g.target),this.contexts.labels,w);return this.contexts.edges.globalCompositeOperation=o,i===l.length?(delete this.jobs[h],!1):(k=i+1,i=Math.min(l.length,k+n),!0)},this.jobs[h]=j,conrad.addJob(h,j.bind(this));else{for(m=sigma.canvas.edges,c=this.edgesOnScreen,d=0,f=c.length;f>d;d++)g=c[d],(m[g.type||this.settings(b,"defaultEdgeType")]||m.def)(g,q.nodes(g.source),q.nodes(g.target),this.contexts.edges,w);if(v)for(m=sigma.canvas.edges.labels,c=this.edgesOnScreen,d=0,f=c.length;f>d;d++)c[d].hidden||(m[c[d].type||this.settings(b,"defaultEdgeType")]||m.def)(c[d],q.nodes(c[d].source),q.nodes(c[d].target),this.contexts.labels,w)}}if(t)for(m=sigma.canvas.nodes,c=this.nodesOnScreen,d=0,f=c.length;f>d;d++)c[d].hidden||(m[c[d].type||this.settings(b,"defaultNodeType")]||m.def)(c[d],this.contexts.nodes,w);if(u)for(m=sigma.canvas.labels,c=this.nodesOnScreen,d=0,f=c.length;f>d;d++)c[d].hidden||(m[c[d].type||this.settings(b,"defaultNodeType")]||m.def)(c[d],this.contexts.labels,w);return this.dispatchEvent("render"),this},sigma.renderers.canvas.prototype.initDOM=function(a,b){var c=document.createElement(a);c.style.position="absolute",c.setAttribute("class","sigma-"+b),this.domElements[b]=c,this.container.appendChild(c),"canvas"===a.toLowerCase()&&(this.contexts[b]=c.getContext("2d"))},sigma.renderers.canvas.prototype.resize=function(b,c){var d,e=this.width,f=this.height,g=sigma.utils.getPixelRatio();if(b!==a&&c!==a?(this.width=b,this.height=c):(this.width=this.container.offsetWidth,this.height=this.container.offsetHeight,b=this.width,c=this.height),e!==this.width||f!==this.height)for(d in this.domElements)this.domElements[d].style.width=b+"px",this.domElements[d].style.height=c+"px","canvas"===this.domElements[d].tagName.toLowerCase()&&(this.domElements[d].setAttribute("width",b*g+"px"),this.domElements[d].setAttribute("height",c*g+"px"),1!==g&&this.contexts[d].scale(g,g));return this},sigma.renderers.canvas.prototype.clear=function(){for(var a in this.contexts)this.contexts[a].clearRect(0,0,this.width,this.height);return this},sigma.renderers.canvas.prototype.kill=function(){for(var a,b;b=this.captors.pop();)b.kill();delete this.captors;for(a in this.domElements)this.domElements[a].parentNode.removeChild(this.domElements[a]),delete this.domElements[a],delete this.contexts[a];delete this.domElements,delete this.contexts},sigma.utils.pkg("sigma.canvas.nodes"),sigma.utils.pkg("sigma.canvas.edges"),sigma.utils.pkg("sigma.canvas.labels")}.call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.renderers"),sigma.renderers.webgl=function(a,b,c,d){if("object"!=typeof d)throw"sigma.renderers.webgl: Wrong arguments.";if(!(d.container instanceof HTMLElement))throw"Container not found.";var e,f,g,h;for(sigma.classes.dispatcher.extend(this),this.jobs={},Object.defineProperty(this,"conradId",{value:sigma.utils.id()}),this.graph=a,this.camera=b,this.contexts={},this.domElements={},this.options=d,this.container=this.options.container,this.settings="object"==typeof d.settings&&d.settings?c.embedObjects(d.settings):c,this.options.prefix=this.camera.readPrefix,Object.defineProperty(this,"nodePrograms",{value:{}}),Object.defineProperty(this,"edgePrograms",{value:{}}),Object.defineProperty(this,"nodeFloatArrays",{value:{}}),Object.defineProperty(this,"edgeFloatArrays",{value:{}}),Object.defineProperty(this,"edgeIndicesArrays",{value:{}}),this.settings(d,"batchEdgesDrawing")?(this.initDOM("canvas","edges",!0),this.initDOM("canvas","nodes",!0)):(this.initDOM("canvas","scene",!0),this.contexts.nodes=this.contexts.scene,this.contexts.edges=this.contexts.scene),this.initDOM("canvas","labels"),this.initDOM("canvas","mouse"),this.contexts.hover=this.contexts.mouse,this.captors=[],g=this.options.captors||[sigma.captors.mouse,sigma.captors.touch],e=0,f=g.length;f>e;e++)h="function"==typeof g[e]?g[e]:sigma.captors[g[e]],this.captors.push(new h(this.domElements.mouse,this.camera,this.settings));sigma.misc.bindEvents.call(this,this.camera.prefix),sigma.misc.drawHovers.call(this,this.camera.prefix),this.resize()},sigma.renderers.webgl.prototype.process=function(){var a,b,c,d,e,f,g=this.graph,h=sigma.utils.extend(h,this.options),i=this.settings(h,"defaultEdgeType"),j=this.settings(h,"defaultNodeType");for(d in this.nodeFloatArrays)delete this.nodeFloatArrays[d];for(d in this.edgeFloatArrays)delete this.edgeFloatArrays[d];for(d in this.edgeIndicesArrays)delete this.edgeIndicesArrays[d];for(a=g.edges(),b=0,c=a.length;c>b;b++)e=a[b].type||i,d=e&&sigma.webgl.edges[e]?e:"def",this.edgeFloatArrays[d]||(this.edgeFloatArrays[d]={edges:[]}),this.edgeFloatArrays[d].edges.push(a[b]);for(a=g.nodes(),b=0,c=a.length;c>b;b++)e=a[b].type||j,d=e&&sigma.webgl.nodes[e]?e:"def",this.nodeFloatArrays[d]||(this.nodeFloatArrays[d]={nodes:[]}),this.nodeFloatArrays[d].nodes.push(a[b]);for(d in this.edgeFloatArrays){for(f=sigma.webgl.edges[d],a=this.edgeFloatArrays[d].edges,this.edgeFloatArrays[d].array=new Float32Array(a.length*f.POINTS*f.ATTRIBUTES),b=0,c=a.length;c>b;b++)a[b].hidden||g.nodes(a[b].source).hidden||g.nodes(a[b].target).hidden||f.addEdge(a[b],g.nodes(a[b].source),g.nodes(a[b].target),this.edgeFloatArrays[d].array,b*f.POINTS*f.ATTRIBUTES,h.prefix,this.settings);"function"==typeof f.computeIndices&&(this.edgeIndicesArrays[d]=f.computeIndices(this.edgeFloatArrays[d].array))}for(d in this.nodeFloatArrays)for(f=sigma.webgl.nodes[d],a=this.nodeFloatArrays[d].nodes,this.nodeFloatArrays[d].array=new Float32Array(a.length*f.POINTS*f.ATTRIBUTES),b=0,c=a.length;c>b;b++)this.nodeFloatArrays[d].array||(this.nodeFloatArrays[d].array=new Float32Array(a.length*f.POINTS*f.ATTRIBUTES)),a[b].hidden||f.addNode(a[b],this.nodeFloatArrays[d].array,b*f.POINTS*f.ATTRIBUTES,h.prefix,this.settings);return this},sigma.renderers.webgl.prototype.render=function(b){var c,d,e,f,g,h,i=this,j=(this.graph,this.contexts.nodes),k=this.contexts.edges,l=this.camera.getMatrix(),m=sigma.utils.extend(b,this.options),n=this.settings(m,"drawLabels"),o=this.settings(m,"drawEdges"),p=this.settings(m,"drawNodes");this.resize(!1),this.settings(m,"hideEdgesOnMove")&&(this.camera.isAnimated||this.camera.isMoving)&&(o=!1),this.clear(),l=sigma.utils.matrices.multiply(l,sigma.utils.matrices.translation(this.width/2,this.height/2));for(f in this.jobs)conrad.hasJob(f)&&conrad.killJob(f);if(o)if(this.settings(m,"batchEdgesDrawing"))(function(){var a,b,c,d,e,f,g,h,i,j;c="edges_"+this.conradId,j=this.settings(m,"webglEdgesBatchSize"),a=Object.keys(this.edgeFloatArrays),a.length&&(b=0,i=sigma.webgl.edges[a[b]],e=this.edgeFloatArrays[a[b]].array,h=this.edgeIndicesArrays[a[b]],g=0,f=Math.min(g+j*i.POINTS,e.length/i.ATTRIBUTES),d=function(){return this.edgePrograms[a[b]]||(this.edgePrograms[a[b]]=i.initProgram(k)),f>g&&(k.useProgram(this.edgePrograms[a[b]]),i.render(k,this.edgePrograms[a[b]],e,{settings:this.settings,matrix:l,width:this.width,height:this.height,ratio:this.camera.ratio,scalingRatio:this.settings(m,"webglOversamplingRatio"),start:g,count:f-g,indicesData:h})),f>=e.length/i.ATTRIBUTES&&b===a.length-1?(delete this.jobs[c],!1):(f>=e.length/i.ATTRIBUTES?(b++,e=this.edgeFloatArrays[a[b]].array,i=sigma.webgl.edges[a[b]],g=0,f=Math.min(g+j*i.POINTS,e.length/i.ATTRIBUTES)):(g=f,f=Math.min(g+j*i.POINTS,e.length/i.ATTRIBUTES)),!0)},this.jobs[c]=d,conrad.addJob(c,d.bind(this)))}).call(this);else for(f in this.edgeFloatArrays)h=sigma.webgl.edges[f],this.edgePrograms[f]||(this.edgePrograms[f]=h.initProgram(k)),this.edgeFloatArrays[f]&&(k.useProgram(this.edgePrograms[f]),h.render(k,this.edgePrograms[f],this.edgeFloatArrays[f].array,{settings:this.settings,matrix:l,width:this.width,height:this.height,ratio:this.camera.ratio,scalingRatio:this.settings(m,"webglOversamplingRatio"),indicesData:this.edgeIndicesArrays[f]}));
+if(p){j.blendFunc(j.SRC_ALPHA,j.ONE_MINUS_SRC_ALPHA),j.enable(j.BLEND);for(f in this.nodeFloatArrays)h=sigma.webgl.nodes[f],this.nodePrograms[f]||(this.nodePrograms[f]=h.initProgram(j)),this.nodeFloatArrays[f]&&(j.useProgram(this.nodePrograms[f]),h.render(j,this.nodePrograms[f],this.nodeFloatArrays[f].array,{settings:this.settings,matrix:l,width:this.width,height:this.height,ratio:this.camera.ratio,scalingRatio:this.settings(m,"webglOversamplingRatio")}))}if(n)for(c=this.camera.quadtree.area(this.camera.getRectangle(this.width,this.height)),this.camera.applyView(a,a,{nodes:c,edges:[],width:this.width,height:this.height}),g=function(a){return i.settings({prefix:i.camera.prefix},a)},d=0,e=c.length;e>d;d++)c[d].hidden||(sigma.canvas.labels[c[d].type||this.settings(m,"defaultNodeType")]||sigma.canvas.labels.def)(c[d],this.contexts.labels,g);return this.dispatchEvent("render"),this},sigma.renderers.webgl.prototype.initDOM=function(a,b,c){var d=document.createElement(a),e=this;d.style.position="absolute",d.setAttribute("class","sigma-"+b),this.domElements[b]=d,this.container.appendChild(d),"canvas"===a.toLowerCase()&&(this.contexts[b]=d.getContext(c?"experimental-webgl":"2d",{preserveDrawingBuffer:!0}),c&&(d.addEventListener("webglcontextlost",function(a){a.preventDefault()},!1),d.addEventListener("webglcontextrestored",function(){e.render()},!1)))},sigma.renderers.webgl.prototype.resize=function(b,c){var d,e=this.width,f=this.height,g=sigma.utils.getPixelRatio();if(b!==a&&c!==a?(this.width=b,this.height=c):(this.width=this.container.offsetWidth,this.height=this.container.offsetHeight,b=this.width,c=this.height),e!==this.width||f!==this.height)for(d in this.domElements)this.domElements[d].style.width=b+"px",this.domElements[d].style.height=c+"px","canvas"===this.domElements[d].tagName.toLowerCase()&&(this.contexts[d]&&this.contexts[d].scale?(this.domElements[d].setAttribute("width",b*g+"px"),this.domElements[d].setAttribute("height",c*g+"px"),1!==g&&this.contexts[d].scale(g,g)):(this.domElements[d].setAttribute("width",b*this.settings("webglOversamplingRatio")+"px"),this.domElements[d].setAttribute("height",c*this.settings("webglOversamplingRatio")+"px")));for(d in this.contexts)this.contexts[d]&&this.contexts[d].viewport&&this.contexts[d].viewport(0,0,this.width*this.settings("webglOversamplingRatio"),this.height*this.settings("webglOversamplingRatio"));return this},sigma.renderers.webgl.prototype.clear=function(){return this.contexts.labels.clearRect(0,0,this.width,this.height),this.contexts.nodes.clear(this.contexts.nodes.COLOR_BUFFER_BIT),this.contexts.edges.clear(this.contexts.edges.COLOR_BUFFER_BIT),this},sigma.renderers.webgl.prototype.kill=function(){for(var a,b;b=this.captors.pop();)b.kill();delete this.captors;for(a in this.domElements)this.domElements[a].parentNode.removeChild(this.domElements[a]),delete this.domElements[a],delete this.contexts[a];delete this.domElements,delete this.contexts},sigma.utils.pkg("sigma.webgl.nodes"),sigma.utils.pkg("sigma.webgl.edges"),sigma.utils.pkg("sigma.canvas.labels")}.call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";if("undefined"==typeof conrad)throw"conrad is not declared";sigma.utils.pkg("sigma.renderers"),sigma.renderers.svg=function(a,b,c,d){if("object"!=typeof d)throw"sigma.renderers.svg: Wrong arguments.";if(!(d.container instanceof HTMLElement))throw"Container not found.";var e,f,g,h,i=this;for(sigma.classes.dispatcher.extend(this),this.graph=a,this.camera=b,this.domElements={graph:null,groups:{},nodes:{},edges:{},labels:{},hovers:{}},this.measurementCanvas=null,this.options=d,this.container=this.options.container,this.settings="object"==typeof d.settings&&d.settings?c.embedObjects(d.settings):c,this.settings("freeStyle",!!this.options.freeStyle),this.settings("xmlns","http://www.w3.org/2000/svg"),this.nodesOnScreen=[],this.edgesOnScreen=[],this.options.prefix="renderer"+sigma.utils.id()+":",this.initDOM("svg"),this.captors=[],g=this.options.captors||[sigma.captors.mouse,sigma.captors.touch],e=0,f=g.length;f>e;e++)h="function"==typeof g[e]?g[e]:sigma.captors[g[e]],this.captors.push(new h(this.domElements.graph,this.camera,this.settings));window.addEventListener("resize",function(){i.resize()}),sigma.misc.bindDOMEvents.call(this,this.domElements.graph),this.bindHovers(this.options.prefix),this.resize(!1)},sigma.renderers.svg.prototype.render=function(b){b=b||{};var c,d,e,f,g,h,i,j,k,l={},m=this.graph,n=this.graph.nodes,o=(this.options.prefix||"",this.settings(b,"drawEdges")),p=this.settings(b,"drawNodes"),q=(this.settings(b,"drawLabels"),this.settings.embedObjects(b,{prefix:this.options.prefix,forceLabels:this.options.forceLabels}));for(this.settings(b,"hideEdgesOnMove")&&(this.camera.isAnimated||this.camera.isMoving)&&(o=!1),this.camera.applyView(a,this.options.prefix,{width:this.width,height:this.height}),this.hideDOMElements(this.domElements.nodes),this.hideDOMElements(this.domElements.edges),this.hideDOMElements(this.domElements.labels),this.edgesOnScreen=[],this.nodesOnScreen=this.camera.quadtree.area(this.camera.getRectangle(this.width,this.height)),c=this.nodesOnScreen,d=0,f=c.length;f>d;d++)l[c[d].id]=c[d];for(c=m.edges(),d=0,f=c.length;f>d;d++)g=c[d],!l[g.source]&&!l[g.target]||g.hidden||n(g.source).hidden||n(g.target).hidden||this.edgesOnScreen.push(g);if(j=sigma.svg.nodes,k=sigma.svg.labels,p)for(c=this.nodesOnScreen,d=0,f=c.length;f>d;d++)c[d].hidden||this.domElements.nodes[c[d].id]||(e=(j[c[d].type]||j.def).create(c[d],q),this.domElements.nodes[c[d].id]=e,this.domElements.groups.nodes.appendChild(e),e=(k[c[d].type]||k.def).create(c[d],q),this.domElements.labels[c[d].id]=e,this.domElements.groups.labels.appendChild(e));if(p)for(c=this.nodesOnScreen,d=0,f=c.length;f>d;d++)c[d].hidden||((j[c[d].type]||j.def).update(c[d],this.domElements.nodes[c[d].id],q),(k[c[d].type]||k.def).update(c[d],this.domElements.labels[c[d].id],q));if(j=sigma.svg.edges,o)for(c=this.edgesOnScreen,d=0,f=c.length;f>d;d++)this.domElements.edges[c[d].id]||(h=n(c[d].source),i=n(c[d].target),e=(j[c[d].type]||j.def).create(c[d],h,i,q),this.domElements.edges[c[d].id]=e,this.domElements.groups.edges.appendChild(e));if(o)for(c=this.edgesOnScreen,d=0,f=c.length;f>d;d++)h=n(c[d].source),i=n(c[d].target),(j[c[d].type]||j.def).update(c[d],this.domElements.edges[c[d].id],h,i,q);return this.dispatchEvent("render"),this},sigma.renderers.svg.prototype.initDOM=function(a){var b,c,d,e=document.createElementNS(this.settings("xmlns"),a),f=this.settings("classPrefix");e.style.position="absolute",e.setAttribute("class",f+"-svg"),e.setAttribute("xmlns",this.settings("xmlns")),e.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink"),e.setAttribute("version","1.1");var g=document.createElement("canvas");g.setAttribute("class",f+"-measurement-canvas"),this.domElements.graph=this.container.appendChild(e);var h=["edges","nodes","labels","hovers"];for(d=0,c=h.length;c>d;d++)b=document.createElementNS(this.settings("xmlns"),"g"),b.setAttributeNS(null,"id",f+"-group-"+h[d]),b.setAttributeNS(null,"class",f+"-group"),this.domElements.groups[h[d]]=this.domElements.graph.appendChild(b);this.container.appendChild(g),this.measurementCanvas=g.getContext("2d")},sigma.renderers.svg.prototype.hideDOMElements=function(a){var b,c;for(c in a)b=a[c],sigma.svg.utils.hide(b);return this},sigma.renderers.svg.prototype.bindHovers=function(a){function b(b){var c=b.data.node,d=g.settings.embedObjects({prefix:a});if(d("enableHovering")){var h=(f[c.type]||f.def).create(c,g.domElements.nodes[c.id],g.measurementCanvas,d);g.domElements.hovers[c.id]=h,g.domElements.groups.hovers.appendChild(h),e=c}}function c(b){var c=b.data.node,d=g.settings.embedObjects({prefix:a});d("enableHovering")&&(g.domElements.groups.hovers.removeChild(g.domElements.hovers[c.id]),e=null,delete g.domElements.hovers[c.id],g.domElements.groups.nodes.appendChild(g.domElements.nodes[c.id]))}function d(){if(e){var b=g.settings.embedObjects({prefix:a});g.domElements.groups.hovers.removeChild(g.domElements.hovers[e.id]),delete g.domElements.hovers[e.id];var c=(f[e.type]||f.def).create(e,g.domElements.nodes[e.id],g.measurementCanvas,b);g.domElements.hovers[e.id]=c,g.domElements.groups.hovers.appendChild(c)}}var e,f=sigma.svg.hovers,g=this;this.bind("overNode",b),this.bind("outNode",c),this.bind("render",d)},sigma.renderers.svg.prototype.resize=function(b,c){var d=this.width,e=this.height,f=1;return b!==a&&c!==a?(this.width=b,this.height=c):(this.width=this.container.offsetWidth,this.height=this.container.offsetHeight,b=this.width,c=this.height),(d!==this.width||e!==this.height)&&(this.domElements.graph.style.width=b+"px",this.domElements.graph.style.height=c+"px","svg"===this.domElements.graph.tagName.toLowerCase()&&(this.domElements.graph.setAttribute("width",b*f),this.domElements.graph.setAttribute("height",c*f))),this},sigma.utils.pkg("sigma.svg.nodes"),sigma.utils.pkg("sigma.svg.edges"),sigma.utils.pkg("sigma.svg.labels")}.call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.renderers");var b,c=!!a.WebGLRenderingContext;if(c){b=document.createElement("canvas");try{c=!(!b.getContext("webgl")&&!b.getContext("experimental-webgl"))}catch(d){c=!1}}sigma.renderers.def=c?sigma.renderers.webgl:sigma.renderers.canvas}(this),function(){"use strict";sigma.utils.pkg("sigma.webgl.nodes"),sigma.webgl.nodes.def={POINTS:3,ATTRIBUTES:5,addNode:function(a,b,c,d,e){var f=sigma.utils.floatColor(a.color||e("defaultNodeColor"));b[c++]=a[d+"x"],b[c++]=a[d+"y"],b[c++]=a[d+"size"],b[c++]=f,b[c++]=0,b[c++]=a[d+"x"],b[c++]=a[d+"y"],b[c++]=a[d+"size"],b[c++]=f,b[c++]=2*Math.PI/3,b[c++]=a[d+"x"],b[c++]=a[d+"y"],b[c++]=a[d+"size"],b[c++]=f,b[c++]=4*Math.PI/3},render:function(a,b,c,d){var e,f=a.getAttribLocation(b,"a_position"),g=a.getAttribLocation(b,"a_size"),h=a.getAttribLocation(b,"a_color"),i=a.getAttribLocation(b,"a_angle"),j=a.getUniformLocation(b,"u_resolution"),k=a.getUniformLocation(b,"u_matrix"),l=a.getUniformLocation(b,"u_ratio"),m=a.getUniformLocation(b,"u_scale");e=a.createBuffer(),a.bindBuffer(a.ARRAY_BUFFER,e),a.bufferData(a.ARRAY_BUFFER,c,a.DYNAMIC_DRAW),a.uniform2f(j,d.width,d.height),a.uniform1f(l,1/Math.pow(d.ratio,d.settings("nodesPowRatio"))),a.uniform1f(m,d.scalingRatio),a.uniformMatrix3fv(k,!1,d.matrix),a.enableVertexAttribArray(f),a.enableVertexAttribArray(g),a.enableVertexAttribArray(h),a.enableVertexAttribArray(i),a.vertexAttribPointer(f,2,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,0),a.vertexAttribPointer(g,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,8),a.vertexAttribPointer(h,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,12),a.vertexAttribPointer(i,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,16),a.drawArrays(a.TRIANGLES,d.start||0,d.count||c.length/this.ATTRIBUTES)},initProgram:function(a){var b,c,d;return b=sigma.utils.loadShader(a,["attribute vec2 a_position;","attribute float a_size;","attribute float a_color;","attribute float a_angle;","uniform vec2 u_resolution;","uniform float u_ratio;","uniform float u_scale;","uniform mat3 u_matrix;","varying vec4 color;","varying vec2 center;","varying float radius;","void main() {","radius = a_size * u_ratio;","vec2 position = (u_matrix * vec3(a_position, 1)).xy;","center = position * u_scale;","center = vec2(center.x, u_scale * u_resolution.y - center.y);","position = position +","2.0 * radius * vec2(cos(a_angle), sin(a_angle));","position = (position / u_resolution * 2.0 - 1.0) * vec2(1, -1);","radius = radius * u_scale;","gl_Position = vec4(position, 0, 1);","float c = a_color;","color.b = mod(c, 256.0); c = floor(c / 256.0);","color.g = mod(c, 256.0); c = floor(c / 256.0);","color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;","color.a = 1.0;","}"].join("\n"),a.VERTEX_SHADER),c=sigma.utils.loadShader(a,["precision mediump float;","varying vec4 color;","varying vec2 center;","varying float radius;","void main(void) {","vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);","vec2 m = gl_FragCoord.xy - center;","float diff = radius - sqrt(m.x * m.x + m.y * m.y);","if (diff > 0.0)","gl_FragColor = color;","else","gl_FragColor = color0;","}"].join("\n"),a.FRAGMENT_SHADER),d=sigma.utils.loadProgram(a,[b,c])}}}(),function(){"use strict";sigma.utils.pkg("sigma.webgl.nodes"),sigma.webgl.nodes.fast={POINTS:1,ATTRIBUTES:4,addNode:function(a,b,c,d,e){b[c++]=a[d+"x"],b[c++]=a[d+"y"],b[c++]=a[d+"size"],b[c++]=sigma.utils.floatColor(a.color||e("defaultNodeColor"))},render:function(a,b,c,d){var e,f=a.getAttribLocation(b,"a_position"),g=a.getAttribLocation(b,"a_size"),h=a.getAttribLocation(b,"a_color"),i=a.getUniformLocation(b,"u_resolution"),j=a.getUniformLocation(b,"u_matrix"),k=a.getUniformLocation(b,"u_ratio"),l=a.getUniformLocation(b,"u_scale");e=a.createBuffer(),a.bindBuffer(a.ARRAY_BUFFER,e),a.bufferData(a.ARRAY_BUFFER,c,a.DYNAMIC_DRAW),a.uniform2f(i,d.width,d.height),a.uniform1f(k,1/Math.pow(d.ratio,d.settings("nodesPowRatio"))),a.uniform1f(l,d.scalingRatio),a.uniformMatrix3fv(j,!1,d.matrix),a.enableVertexAttribArray(f),a.enableVertexAttribArray(g),a.enableVertexAttribArray(h),a.vertexAttribPointer(f,2,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,0),a.vertexAttribPointer(g,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,8),a.vertexAttribPointer(h,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,12),a.drawArrays(a.POINTS,d.start||0,d.count||c.length/this.ATTRIBUTES)},initProgram:function(a){var b,c,d;return b=sigma.utils.loadShader(a,["attribute vec2 a_position;","attribute float a_size;","attribute float a_color;","uniform vec2 u_resolution;","uniform float u_ratio;","uniform float u_scale;","uniform mat3 u_matrix;","varying vec4 color;","void main() {","gl_Position = vec4(","((u_matrix * vec3(a_position, 1)).xy /","u_resolution * 2.0 - 1.0) * vec2(1, -1),","0,","1",");","gl_PointSize = a_size * u_ratio * u_scale * 2.0;","float c = a_color;","color.b = mod(c, 256.0); c = floor(c / 256.0);","color.g = mod(c, 256.0); c = floor(c / 256.0);","color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;","color.a = 1.0;","}"].join("\n"),a.VERTEX_SHADER),c=sigma.utils.loadShader(a,["precision mediump float;","varying vec4 color;","void main(void) {","float border = 0.01;","float radius = 0.5;","vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);","vec2 m = gl_PointCoord - vec2(0.5, 0.5);","float dist = radius - sqrt(m.x * m.x + m.y * m.y);","float t = 0.0;","if (dist > border)","t = 1.0;","else if (dist > 0.0)","t = dist / border;","gl_FragColor = mix(color0, color, t);","}"].join("\n"),a.FRAGMENT_SHADER),d=sigma.utils.loadProgram(a,[b,c])}}}(),function(){"use strict";sigma.utils.pkg("sigma.webgl.edges"),sigma.webgl.edges.def={POINTS:6,ATTRIBUTES:7,addEdge:function(a,b,c,d,e,f,g){var h=(a[f+"size"]||1)/2,i=b[f+"x"],j=b[f+"y"],k=c[f+"x"],l=c[f+"y"],m=a.color;if(!m)switch(g("edgeColor")){case"source":m=b.color||g("defaultNodeColor");break;case"target":m=c.color||g("defaultNodeColor");break;default:m=g("defaultEdgeColor")}m=sigma.utils.floatColor(m),d[e++]=i,d[e++]=j,d[e++]=k,d[e++]=l,d[e++]=h,d[e++]=0,d[e++]=m,d[e++]=k,d[e++]=l,d[e++]=i,d[e++]=j,d[e++]=h,d[e++]=1,d[e++]=m,d[e++]=k,d[e++]=l,d[e++]=i,d[e++]=j,d[e++]=h,d[e++]=0,d[e++]=m,d[e++]=k,d[e++]=l,d[e++]=i,d[e++]=j,d[e++]=h,d[e++]=0,d[e++]=m,d[e++]=i,d[e++]=j,d[e++]=k,d[e++]=l,d[e++]=h,d[e++]=1,d[e++]=m,d[e++]=i,d[e++]=j,d[e++]=k,d[e++]=l,d[e++]=h,d[e++]=0,d[e++]=m},render:function(a,b,c,d){var e,f=a.getAttribLocation(b,"a_color"),g=a.getAttribLocation(b,"a_position1"),h=a.getAttribLocation(b,"a_position2"),i=a.getAttribLocation(b,"a_thickness"),j=a.getAttribLocation(b,"a_minus"),k=a.getUniformLocation(b,"u_resolution"),l=a.getUniformLocation(b,"u_matrix"),m=a.getUniformLocation(b,"u_matrixHalfPi"),n=a.getUniformLocation(b,"u_matrixHalfPiMinus"),o=a.getUniformLocation(b,"u_ratio"),p=a.getUniformLocation(b,"u_scale");e=a.createBuffer(),a.bindBuffer(a.ARRAY_BUFFER,e),a.bufferData(a.ARRAY_BUFFER,c,a.STATIC_DRAW),a.uniform2f(k,d.width,d.height),a.uniform1f(o,d.ratio/Math.pow(d.ratio,d.settings("edgesPowRatio"))),a.uniform1f(p,d.scalingRatio),a.uniformMatrix3fv(l,!1,d.matrix),a.uniformMatrix2fv(m,!1,sigma.utils.matrices.rotation(Math.PI/2,!0)),a.uniformMatrix2fv(n,!1,sigma.utils.matrices.rotation(-Math.PI/2,!0)),a.enableVertexAttribArray(f),a.enableVertexAttribArray(g),a.enableVertexAttribArray(h),a.enableVertexAttribArray(i),a.enableVertexAttribArray(j),a.vertexAttribPointer(g,2,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,0),a.vertexAttribPointer(h,2,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,8),a.vertexAttribPointer(i,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,16),a.vertexAttribPointer(j,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,20),a.vertexAttribPointer(f,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,24),a.drawArrays(a.TRIANGLES,d.start||0,d.count||c.length/this.ATTRIBUTES)},initProgram:function(a){var b,c,d;return b=sigma.utils.loadShader(a,["attribute vec2 a_position1;","attribute vec2 a_position2;","attribute float a_thickness;","attribute float a_minus;","attribute float a_color;","uniform vec2 u_resolution;","uniform float u_ratio;","uniform float u_scale;","uniform mat3 u_matrix;","uniform mat2 u_matrixHalfPi;","uniform mat2 u_matrixHalfPiMinus;","varying vec4 color;","void main() {","vec2 position = a_thickness * u_ratio *","normalize(a_position2 - a_position1);","mat2 matrix = a_minus * u_matrixHalfPiMinus +","(1.0 - a_minus) * u_matrixHalfPi;","position = matrix * position + a_position1;","gl_Position = vec4(","((u_matrix * vec3(position, 1)).xy /","u_resolution * 2.0 - 1.0) * vec2(1, -1),","0,","1",");","float c = a_color;","color.b = mod(c, 256.0); c = floor(c / 256.0);","color.g = mod(c, 256.0); c = floor(c / 256.0);","color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;","color.a = 1.0;","}"].join("\n"),a.VERTEX_SHADER),c=sigma.utils.loadShader(a,["precision mediump float;","varying vec4 color;","void main(void) {","gl_FragColor = color;","}"].join("\n"),a.FRAGMENT_SHADER),d=sigma.utils.loadProgram(a,[b,c])}}}(),function(){"use strict";sigma.utils.pkg("sigma.webgl.edges"),sigma.webgl.edges.fast={POINTS:2,ATTRIBUTES:3,addEdge:function(a,b,c,d,e,f,g){var h=((a[f+"size"]||1)/2,b[f+"x"]),i=b[f+"y"],j=c[f+"x"],k=c[f+"y"],l=a.color;if(!l)switch(g("edgeColor")){case"source":l=b.color||g("defaultNodeColor");break;case"target":l=c.color||g("defaultNodeColor");break;default:l=g("defaultEdgeColor")}l=sigma.utils.floatColor(l),d[e++]=h,d[e++]=i,d[e++]=l,d[e++]=j,d[e++]=k,d[e++]=l},render:function(a,b,c,d){var e,f=a.getAttribLocation(b,"a_color"),g=a.getAttribLocation(b,"a_position"),h=a.getUniformLocation(b,"u_resolution"),i=a.getUniformLocation(b,"u_matrix");e=a.createBuffer(),a.bindBuffer(a.ARRAY_BUFFER,e),a.bufferData(a.ARRAY_BUFFER,c,a.DYNAMIC_DRAW),a.uniform2f(h,d.width,d.height),a.uniformMatrix3fv(i,!1,d.matrix),a.enableVertexAttribArray(g),a.enableVertexAttribArray(f),a.vertexAttribPointer(g,2,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,0),a.vertexAttribPointer(f,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,8),a.lineWidth(3),a.drawArrays(a.LINES,d.start||0,d.count||c.length/this.ATTRIBUTES)},initProgram:function(a){var b,c,d;return b=sigma.utils.loadShader(a,["attribute vec2 a_position;","attribute float a_color;","uniform vec2 u_resolution;","uniform mat3 u_matrix;","varying vec4 color;","void main() {","gl_Position = vec4(","((u_matrix * vec3(a_position, 1)).xy /","u_resolution * 2.0 - 1.0) * vec2(1, -1),","0,","1",");","float c = a_color;","color.b = mod(c, 256.0); c = floor(c / 256.0);","color.g = mod(c, 256.0); c = floor(c / 256.0);","color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;","color.a = 1.0;","}"].join("\n"),a.VERTEX_SHADER),c=sigma.utils.loadShader(a,["precision mediump float;","varying vec4 color;","void main(void) {","gl_FragColor = color;","}"].join("\n"),a.FRAGMENT_SHADER),d=sigma.utils.loadProgram(a,[b,c])}}}(),function(){"use strict";sigma.utils.pkg("sigma.webgl.edges"),sigma.webgl.edges.arrow={POINTS:9,ATTRIBUTES:11,addEdge:function(a,b,c,d,e,f,g){var h=(a[f+"size"]||1)/2,i=b[f+"x"],j=b[f+"y"],k=c[f+"x"],l=c[f+"y"],m=c[f+"size"],n=a.color;if(!n)switch(g("edgeColor")){case"source":n=b.color||g("defaultNodeColor");break;case"target":n=c.color||g("defaultNodeColor");break;default:n=g("defaultEdgeColor")}n=sigma.utils.floatColor(n),d[e++]=i,d[e++]=j,d[e++]=k,d[e++]=l,d[e++]=h,d[e++]=m,d[e++]=0,d[e++]=0,d[e++]=0,d[e++]=0,d[e++]=n,d[e++]=k,d[e++]=l,d[e++]=i,d[e++]=j,d[e++]=h,d[e++]=m,d[e++]=1,d[e++]=1,d[e++]=0,d[e++]=0,d[e++]=n,d[e++]=k,d[e++]=l,d[e++]=i,d[e++]=j,d[e++]=h,d[e++]=m,d[e++]=1,d[e++]=0,d[e++]=0,d[e++]=0,d[e++]=n,d[e++]=k,d[e++]=l,d[e++]=i,d[e++]=j,d[e++]=h,d[e++]=m,d[e++]=1,d[e++]=0,d[e++]=0,d[e++]=0,d[e++]=n,d[e++]=i,d[e++]=j,d[e++]=k,d[e++]=l,d[e++]=h,d[e++]=m,d[e++]=0,d[e++]=1,d[e++]=0,d[e++]=0,d[e++]=n,d[e++]=i,d[e++]=j,d[e++]=k,d[e++]=l,d[e++]=h,d[e++]=m,d[e++]=0,d[e++]=0,d[e++]=0,d[e++]=0,d[e++]=n,d[e++]=k,d[e++]=l,d[e++]=i,d[e++]=j,d[e++]=h,d[e++]=m,d[e++]=1,d[e++]=0,d[e++]=1,d[e++]=-1,d[e++]=n,d[e++]=k,d[e++]=l,d[e++]=i,d[e++]=j,d[e++]=h,d[e++]=m,d[e++]=1,d[e++]=0,d[e++]=1,d[e++]=0,d[e++]=n,d[e++]=k,d[e++]=l,d[e++]=i,d[e++]=j,d[e++]=h,d[e++]=m,d[e++]=1,d[e++]=0,d[e++]=1,d[e++]=1,d[e++]=n},render:function(a,b,c,d){var e,f=a.getAttribLocation(b,"a_pos1"),g=a.getAttribLocation(b,"a_pos2"),h=a.getAttribLocation(b,"a_thickness"),i=a.getAttribLocation(b,"a_tSize"),j=a.getAttribLocation(b,"a_delay"),k=a.getAttribLocation(b,"a_minus"),l=a.getAttribLocation(b,"a_head"),m=a.getAttribLocation(b,"a_headPosition"),n=a.getAttribLocation(b,"a_color"),o=a.getUniformLocation(b,"u_resolution"),p=a.getUniformLocation(b,"u_matrix"),q=a.getUniformLocation(b,"u_matrixHalfPi"),r=a.getUniformLocation(b,"u_matrixHalfPiMinus"),s=a.getUniformLocation(b,"u_ratio"),t=a.getUniformLocation(b,"u_nodeRatio"),u=a.getUniformLocation(b,"u_arrowHead"),v=a.getUniformLocation(b,"u_scale");e=a.createBuffer(),a.bindBuffer(a.ARRAY_BUFFER,e),a.bufferData(a.ARRAY_BUFFER,c,a.STATIC_DRAW),a.uniform2f(o,d.width,d.height),a.uniform1f(s,d.ratio/Math.pow(d.ratio,d.settings("edgesPowRatio"))),a.uniform1f(t,Math.pow(d.ratio,d.settings("nodesPowRatio"))/d.ratio),a.uniform1f(u,5),a.uniform1f(v,d.scalingRatio),a.uniformMatrix3fv(p,!1,d.matrix),a.uniformMatrix2fv(q,!1,sigma.utils.matrices.rotation(Math.PI/2,!0)),a.uniformMatrix2fv(r,!1,sigma.utils.matrices.rotation(-Math.PI/2,!0)),a.enableVertexAttribArray(f),a.enableVertexAttribArray(g),a.enableVertexAttribArray(h),a.enableVertexAttribArray(i),a.enableVertexAttribArray(j),a.enableVertexAttribArray(k),a.enableVertexAttribArray(l),a.enableVertexAttribArray(m),a.enableVertexAttribArray(n),a.vertexAttribPointer(f,2,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,0),a.vertexAttribPointer(g,2,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,8),a.vertexAttribPointer(h,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,16),a.vertexAttribPointer(i,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,20),a.vertexAttribPointer(j,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,24),a.vertexAttribPointer(k,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,28),a.vertexAttribPointer(l,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,32),a.vertexAttribPointer(m,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,36),a.vertexAttribPointer(n,1,a.FLOAT,!1,this.ATTRIBUTES*Float32Array.BYTES_PER_ELEMENT,40),a.drawArrays(a.TRIANGLES,d.start||0,d.count||c.length/this.ATTRIBUTES)},initProgram:function(a){var b,c,d;return b=sigma.utils.loadShader(a,["attribute vec2 a_pos1;","attribute vec2 a_pos2;","attribute float a_thickness;","attribute float a_tSize;","attribute float a_delay;","attribute float a_minus;","attribute float a_head;","attribute float a_headPosition;","attribute float a_color;","uniform vec2 u_resolution;","uniform float u_ratio;","uniform float u_nodeRatio;","uniform float u_arrowHead;","uniform float u_scale;","uniform mat3 u_matrix;","uniform mat2 u_matrixHalfPi;","uniform mat2 u_matrixHalfPiMinus;","varying vec4 color;","void main() {","vec2 pos = normalize(a_pos2 - a_pos1);","mat2 matrix = (1.0 - a_head) *","(","a_minus * u_matrixHalfPiMinus +","(1.0 - a_minus) * u_matrixHalfPi",") + a_head * (","a_headPosition * u_matrixHalfPiMinus * 0.6 +","(a_headPosition * a_headPosition - 1.0) * mat2(1.0)",");","pos = a_pos1 + (","(1.0 - a_head) * a_thickness * u_ratio * matrix * pos +","a_head * u_arrowHead * a_thickness * u_ratio * matrix * pos +","a_delay * pos * (","a_tSize / u_nodeRatio +","u_arrowHead * a_thickness * u_ratio",")",");","gl_Position = vec4(","((u_matrix * vec3(pos, 1)).xy /","u_resolution * 2.0 - 1.0) * vec2(1, -1),","0,","1",");","float c = a_color;","color.b = mod(c, 256.0); c = floor(c / 256.0);","color.g = mod(c, 256.0); c = floor(c / 256.0);","color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;","color.a = 1.0;","}"].join("\n"),a.VERTEX_SHADER),c=sigma.utils.loadShader(a,["precision mediump float;","varying vec4 color;","void main(void) {","gl_FragColor = color;","}"].join("\n"),a.FRAGMENT_SHADER),d=sigma.utils.loadProgram(a,[b,c])}}}(),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.canvas.labels"),sigma.canvas.labels.def=function(a,b,c){var d,e=c("prefix")||"",f=a[e+"size"];f<c("labelThreshold")||a.label&&"string"==typeof a.label&&(d="fixed"===c("labelSize")?c("defaultLabelSize"):c("labelSizeRatio")*f,b.font=(c("fontStyle")?c("fontStyle")+" ":"")+d+"px "+c("font"),b.fillStyle="node"===c("labelColor")?a.color||c("defaultNodeColor"):c("defaultLabelColor"),b.fillText(a.label,Math.round(a[e+"x"]+f+3),Math.round(a[e+"y"]+d/3)))}}.call(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.canvas.hovers"),sigma.canvas.hovers.def=function(a,b,c){var d,e,f,g,h,i=c("hoverFontStyle")||c("fontStyle"),j=c("prefix")||"",k=a[j+"size"],l="fixed"===c("labelSize")?c("defaultLabelSize"):c("labelSizeRatio")*k;b.font=(i?i+" ":"")+l+"px "+(c("hoverFont")||c("font")),b.beginPath(),b.fillStyle="node"===c("labelHoverBGColor")?a.color||c("defaultNodeColor"):c("defaultHoverLabelBGColor"),a.label&&c("labelHoverShadow")&&(b.shadowOffsetX=0,b.shadowOffsetY=0,b.shadowBlur=8,b.shadowColor=c("labelHoverShadowColor")),a.label&&"string"==typeof a.label&&(d=Math.round(a[j+"x"]-l/2-2),e=Math.round(a[j+"y"]-l/2-2),f=Math.round(b.measureText(a.label).width+l/2+k+7),g=Math.round(l+4),h=Math.round(l/2+2),b.moveTo(d,e+h),b.arcTo(d,e,d+h,e,h),b.lineTo(d+f,e),b.lineTo(d+f,e+g),b.lineTo(d+h,e+g),b.arcTo(d,e+g,d,e+g-h,h),b.lineTo(d,e+h),b.closePath(),b.fill(),b.shadowOffsetX=0,b.shadowOffsetY=0,b.shadowBlur=0),c("borderSize")>0&&(b.beginPath(),b.fillStyle="node"===c("nodeBorderColor")?a.color||c("defaultNodeColor"):c("defaultNodeBorderColor"),b.arc(a[j+"x"],a[j+"y"],k+c("borderSize"),0,2*Math.PI,!0),b.closePath(),b.fill());var m=sigma.canvas.nodes[a.type]||sigma.canvas.nodes.def;m(a,b,c),a.label&&"string"==typeof a.label&&(b.fillStyle="node"===c("labelHoverColor")?a.color||c("defaultNodeColor"):c("defaultLabelHoverColor"),b.fillText(a.label,Math.round(a[j+"x"]+k+3),Math.round(a[j+"y"]+l/3)))}}.call(this),function(){"use strict";sigma.utils.pkg("sigma.canvas.nodes"),sigma.canvas.nodes.def=function(a,b,c){var d=c("prefix")||"";b.fillStyle=a.color||c("defaultNodeColor"),b.beginPath(),b.arc(a[d+"x"],a[d+"y"],a[d+"size"],0,2*Math.PI,!0),b.closePath(),b.fill()}}(),function(){"use strict";sigma.utils.pkg("sigma.canvas.edges"),sigma.canvas.edges.def=function(a,b,c,d,e){var f=a.color,g=e("prefix")||"",h=a[g+"size"]||1,i=e("edgeColor"),j=e("defaultNodeColor"),k=e("defaultEdgeColor");if(!f)switch(i){case"source":f=b.color||j;break;case"target":f=c.color||j;break;default:f=k}d.strokeStyle=f,d.lineWidth=h,d.beginPath(),d.moveTo(b[g+"x"],b[g+"y"]),d.lineTo(c[g+"x"],c[g+"y"]),d.stroke()}}(),function(){"use strict";sigma.utils.pkg("sigma.canvas.edges"),sigma.canvas.edges.curve=function(a,b,c,d,e){var f=a.color,g=e("prefix")||"",h=a[g+"size"]||1,i=e("edgeColor"),j=e("defaultNodeColor"),k=e("defaultEdgeColor"),l={},m=b[g+"size"],n=b[g+"x"],o=b[g+"y"],p=c[g+"x"],q=c[g+"y"];if(l=b.id===c.id?sigma.utils.getSelfLoopControlPoints(n,o,m):sigma.utils.getQuadraticControlPoint(n,o,p,q),!f)switch(i){case"source":f=b.color||j;break;case"target":f=c.color||j;break;default:f=k}d.strokeStyle=f,d.lineWidth=h,d.beginPath(),d.moveTo(n,o),b.id===c.id?d.bezierCurveTo(l.x1,l.y1,l.x2,l.y2,p,q):d.quadraticCurveTo(l.x,l.y,p,q),d.stroke()}}(),function(){"use strict";sigma.utils.pkg("sigma.canvas.edges"),sigma.canvas.edges.arrow=function(a,b,c,d,e){var f=a.color,g=e("prefix")||"",h=e("edgeColor"),i=e("defaultNodeColor"),j=e("defaultEdgeColor"),k=a[g+"size"]||1,l=c[g+"size"],m=b[g+"x"],n=b[g+"y"],o=c[g+"x"],p=c[g+"y"],q=Math.max(2.5*k,e("minArrowSize")),r=Math.sqrt(Math.pow(o-m,2)+Math.pow(p-n,2)),s=m+(o-m)*(r-q-l)/r,t=n+(p-n)*(r-q-l)/r,u=(o-m)*q/r,v=(p-n)*q/r;if(!f)switch(h){case"source":f=b.color||i;break;case"target":f=c.color||i;break;default:f=j}d.strokeStyle=f,d.lineWidth=k,d.beginPath(),d.moveTo(m,n),d.lineTo(s,t),d.stroke(),d.fillStyle=f,d.beginPath(),d.moveTo(s+u,t+v),d.lineTo(s+.6*v,t-.6*u),d.lineTo(s-.6*v,t+.6*u),d.lineTo(s+u,t+v),d.closePath(),d.fill()}}(),function(){"use strict";sigma.utils.pkg("sigma.canvas.edges"),sigma.canvas.edges.curvedArrow=function(a,b,c,d,e){var f,g,h,i,j,k=a.color,l=e("prefix")||"",m=e("edgeColor"),n=e("defaultNodeColor"),o=e("defaultEdgeColor"),p={},q=a[l+"size"]||1,r=c[l+"size"],s=b[l+"x"],t=b[l+"y"],u=c[l+"x"],v=c[l+"y"],w=Math.max(2.5*q,e("minArrowSize"));if(p=b.id===c.id?sigma.utils.getSelfLoopControlPoints(s,t,r):sigma.utils.getQuadraticControlPoint(s,t,u,v),b.id===c.id?(f=Math.sqrt(Math.pow(u-p.x1,2)+Math.pow(v-p.y1,2)),g=p.x1+(u-p.x1)*(f-w-r)/f,h=p.y1+(v-p.y1)*(f-w-r)/f,i=(u-p.x1)*w/f,j=(v-p.y1)*w/f):(f=Math.sqrt(Math.pow(u-p.x,2)+Math.pow(v-p.y,2)),g=p.x+(u-p.x)*(f-w-r)/f,h=p.y+(v-p.y)*(f-w-r)/f,i=(u-p.x)*w/f,j=(v-p.y)*w/f),!k)switch(m){case"source":k=b.color||n;break;case"target":k=c.color||n;break;default:k=o}d.strokeStyle=k,d.lineWidth=q,d.beginPath(),d.moveTo(s,t),b.id===c.id?d.bezierCurveTo(p.x2,p.y2,p.x1,p.y1,g,h):d.quadraticCurveTo(p.x,p.y,g,h),d.stroke(),d.fillStyle=k,d.beginPath(),d.moveTo(g+i,h+j),d.lineTo(g+.6*j,h-.6*i),d.lineTo(g-.6*j,h+.6*i),d.lineTo(g+i,h+j),d.closePath(),d.fill()}}(),function(){"use strict";sigma.utils.pkg("sigma.canvas.edgehovers"),sigma.canvas.edgehovers.def=function(a,b,c,d,e){var f=a.color,g=e("prefix")||"",h=a[g+"size"]||1,i=e("edgeColor"),j=e("defaultNodeColor"),k=e("defaultEdgeColor");if(!f)switch(i){case"source":f=b.color||j;break;case"target":f=c.color||j;break;default:f=k}f="edge"===e("edgeHoverColor")?a.hover_color||f:a.hover_color||e("defaultEdgeHoverColor")||f,h*=e("edgeHoverSizeRatio"),d.strokeStyle=f,d.lineWidth=h,d.beginPath(),d.moveTo(b[g+"x"],b[g+"y"]),d.lineTo(c[g+"x"],c[g+"y"]),d.stroke()}}(),function(){"use strict";sigma.utils.pkg("sigma.canvas.edgehovers"),sigma.canvas.edgehovers.curve=function(a,b,c,d,e){var f=a.color,g=e("prefix")||"",h=e("edgeHoverSizeRatio")*(a[g+"size"]||1),i=e("edgeColor"),j=e("defaultNodeColor"),k=e("defaultEdgeColor"),l={},m=b[g+"size"],n=b[g+"x"],o=b[g+"y"],p=c[g+"x"],q=c[g+"y"];if(l=b.id===c.id?sigma.utils.getSelfLoopControlPoints(n,o,m):sigma.utils.getQuadraticControlPoint(n,o,p,q),!f)switch(i){case"source":f=b.color||j;break;case"target":f=c.color||j;break;default:f=k}f="edge"===e("edgeHoverColor")?a.hover_color||f:a.hover_color||e("defaultEdgeHoverColor")||f,d.strokeStyle=f,d.lineWidth=h,d.beginPath(),d.moveTo(n,o),b.id===c.id?d.bezierCurveTo(l.x1,l.y1,l.x2,l.y2,p,q):d.quadraticCurveTo(l.x,l.y,p,q),d.stroke()}}(),function(){"use strict";sigma.utils.pkg("sigma.canvas.edgehovers"),sigma.canvas.edgehovers.arrow=function(a,b,c,d,e){var f=a.color,g=e("prefix")||"",h=e("edgeColor"),i=e("defaultNodeColor"),j=e("defaultEdgeColor"),k=a[g+"size"]||1,l=c[g+"size"],m=b[g+"x"],n=b[g+"y"],o=c[g+"x"],p=c[g+"y"];
+k=a.hover?e("edgeHoverSizeRatio")*k:k;var q=2.5*k,r=Math.sqrt(Math.pow(o-m,2)+Math.pow(p-n,2)),s=m+(o-m)*(r-q-l)/r,t=n+(p-n)*(r-q-l)/r,u=(o-m)*q/r,v=(p-n)*q/r;if(!f)switch(h){case"source":f=b.color||i;break;case"target":f=c.color||i;break;default:f=j}f="edge"===e("edgeHoverColor")?a.hover_color||f:a.hover_color||e("defaultEdgeHoverColor")||f,d.strokeStyle=f,d.lineWidth=k,d.beginPath(),d.moveTo(m,n),d.lineTo(s,t),d.stroke(),d.fillStyle=f,d.beginPath(),d.moveTo(s+u,t+v),d.lineTo(s+.6*v,t-.6*u),d.lineTo(s-.6*v,t+.6*u),d.lineTo(s+u,t+v),d.closePath(),d.fill()}}(),function(){"use strict";sigma.utils.pkg("sigma.canvas.edgehovers"),sigma.canvas.edgehovers.curvedArrow=function(a,b,c,d,e){var f,g,h,i,j,k,l=a.color,m=e("prefix")||"",n=e("edgeColor"),o=e("defaultNodeColor"),p=e("defaultEdgeColor"),q={},r=e("edgeHoverSizeRatio")*(a[m+"size"]||1),s=c[m+"size"],t=b[m+"x"],u=b[m+"y"],v=c[m+"x"],w=c[m+"y"];if(q=b.id===c.id?sigma.utils.getSelfLoopControlPoints(t,u,s):sigma.utils.getQuadraticControlPoint(t,u,v,w),b.id===c.id?(f=Math.sqrt(Math.pow(v-q.x1,2)+Math.pow(w-q.y1,2)),g=2.5*r,h=q.x1+(v-q.x1)*(f-g-s)/f,i=q.y1+(w-q.y1)*(f-g-s)/f,j=(v-q.x1)*g/f,k=(w-q.y1)*g/f):(f=Math.sqrt(Math.pow(v-q.x,2)+Math.pow(w-q.y,2)),g=2.5*r,h=q.x+(v-q.x)*(f-g-s)/f,i=q.y+(w-q.y)*(f-g-s)/f,j=(v-q.x)*g/f,k=(w-q.y)*g/f),!l)switch(n){case"source":l=b.color||o;break;case"target":l=c.color||o;break;default:l=p}l="edge"===e("edgeHoverColor")?a.hover_color||l:a.hover_color||e("defaultEdgeHoverColor")||l,d.strokeStyle=l,d.lineWidth=r,d.beginPath(),d.moveTo(t,u),b.id===c.id?d.bezierCurveTo(q.x2,q.y2,q.x1,q.y1,h,i):d.quadraticCurveTo(q.x,q.y,h,i),d.stroke(),d.fillStyle=l,d.beginPath(),d.moveTo(h+j,i+k),d.lineTo(h+.6*k,i-.6*j),d.lineTo(h-.6*k,i+.6*j),d.lineTo(h+j,i+k),d.closePath(),d.fill()}}(),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.canvas.extremities"),sigma.canvas.extremities.def=function(a,b,c,d,e){(sigma.canvas.hovers[b.type]||sigma.canvas.hovers.def)(b,d,e),(sigma.canvas.hovers[c.type]||sigma.canvas.hovers.def)(c,d,e)}}.call(this),function(){"use strict";sigma.utils.pkg("sigma.svg.utils"),sigma.svg.utils={show:function(a){return a.style.display="",this},hide:function(a){return a.style.display="none",this}}}(),function(){"use strict";sigma.utils.pkg("sigma.svg.nodes"),sigma.svg.nodes.def={create:function(a,b){var c=(b("prefix")||"",document.createElementNS(b("xmlns"),"circle"));return c.setAttributeNS(null,"data-node-id",a.id),c.setAttributeNS(null,"class",b("classPrefix")+"-node"),c.setAttributeNS(null,"fill",a.color||b("defaultNodeColor")),c},update:function(a,b,c){var d=c("prefix")||"";return b.setAttributeNS(null,"cx",a[d+"x"]),b.setAttributeNS(null,"cy",a[d+"y"]),b.setAttributeNS(null,"r",a[d+"size"]),c("freeStyle")||b.setAttributeNS(null,"fill",a.color||c("defaultNodeColor")),b.style.display="",this}}}(),function(){"use strict";sigma.utils.pkg("sigma.svg.edges"),sigma.svg.edges.def={create:function(a,b,c,d){var e=a.color,f=(d("prefix")||"",d("edgeColor")),g=d("defaultNodeColor"),h=d("defaultEdgeColor");if(!e)switch(f){case"source":e=b.color||g;break;case"target":e=c.color||g;break;default:e=h}var i=document.createElementNS(d("xmlns"),"line");return i.setAttributeNS(null,"data-edge-id",a.id),i.setAttributeNS(null,"class",d("classPrefix")+"-edge"),i.setAttributeNS(null,"stroke",e),i},update:function(a,b,c,d,e){var f=e("prefix")||"";return b.setAttributeNS(null,"stroke-width",a[f+"size"]||1),b.setAttributeNS(null,"x1",c[f+"x"]),b.setAttributeNS(null,"y1",c[f+"y"]),b.setAttributeNS(null,"x2",d[f+"x"]),b.setAttributeNS(null,"y2",d[f+"y"]),b.style.display="",this}}}(),function(){"use strict";sigma.utils.pkg("sigma.svg.edges"),sigma.svg.edges.curve={create:function(a,b,c,d){var e=a.color,f=(d("prefix")||"",d("edgeColor")),g=d("defaultNodeColor"),h=d("defaultEdgeColor");if(!e)switch(f){case"source":e=b.color||g;break;case"target":e=c.color||g;break;default:e=h}var i=document.createElementNS(d("xmlns"),"path");return i.setAttributeNS(null,"data-edge-id",a.id),i.setAttributeNS(null,"class",d("classPrefix")+"-edge"),i.setAttributeNS(null,"stroke",e),i},update:function(a,b,c,d,e){var f=e("prefix")||"";b.setAttributeNS(null,"stroke-width",a[f+"size"]||1);var g=(c[f+"x"]+d[f+"x"])/2+(d[f+"y"]-c[f+"y"])/4,h=(c[f+"y"]+d[f+"y"])/2+(c[f+"x"]-d[f+"x"])/4,i="M"+c[f+"x"]+","+c[f+"y"]+" Q"+g+","+h+" "+d[f+"x"]+","+d[f+"y"];return b.setAttributeNS(null,"d",i),b.setAttributeNS(null,"fill","none"),b.style.display="",this}}}(),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.svg.labels"),sigma.svg.labels.def={create:function(a,b){var c=b("prefix")||"",d=a[c+"size"],e=document.createElementNS(b("xmlns"),"text"),f="fixed"===b("labelSize")?b("defaultLabelSize"):b("labelSizeRatio")*d,g="node"===b("labelColor")?a.color||b("defaultNodeColor"):b("defaultLabelColor");return e.setAttributeNS(null,"data-label-target",a.id),e.setAttributeNS(null,"class",b("classPrefix")+"-label"),e.setAttributeNS(null,"font-size",f),e.setAttributeNS(null,"font-family",b("font")),e.setAttributeNS(null,"fill",g),e.innerHTML=a.label,e.textContent=a.label,e},update:function(a,b,c){var d=c("prefix")||"",e=a[d+"size"],f="fixed"===c("labelSize")?c("defaultLabelSize"):c("labelSizeRatio")*e;return!c("forceLabels")&&e<c("labelThreshold")||"string"!=typeof a.label?void 0:(b.setAttributeNS(null,"x",Math.round(a[d+"x"]+e+3)),b.setAttributeNS(null,"y",Math.round(a[d+"y"]+f/3)),b.style.display="",this)}}}.call(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.svg.hovers"),sigma.svg.hovers.def={create:function(a,b,c,d){var e,f,g,h,i,j=(d("hoverFontStyle")||d("fontStyle"),d("prefix")||""),k=a[j+"size"],l="fixed"===d("labelSize")?d("defaultLabelSize"):d("labelSizeRatio")*k,m="node"===d("labelHoverColor")?a.color||d("defaultNodeColor"):d("defaultLabelHoverColor"),n=document.createElementNS(d("xmlns"),"g"),o=document.createElementNS(d("xmlns"),"rect"),p=document.createElementNS(d("xmlns"),"circle"),q=document.createElementNS(d("xmlns"),"text");return n.setAttributeNS(null,"class",d("classPrefix")+"-hover"),n.setAttributeNS(null,"data-node-id",a.id),"string"==typeof a.label&&(q.innerHTML=a.label,q.textContent=a.label,q.setAttributeNS(null,"class",d("classPrefix")+"-hover-label"),q.setAttributeNS(null,"font-size",l),q.setAttributeNS(null,"font-family",d("font")),q.setAttributeNS(null,"fill",m),q.setAttributeNS(null,"x",Math.round(a[j+"x"]+k+3)),q.setAttributeNS(null,"y",Math.round(a[j+"y"]+l/3)),e=Math.round(a[j+"x"]-l/2-2),f=Math.round(a[j+"y"]-l/2-2),g=Math.round(c.measureText(a.label).width+l/2+k+9),h=Math.round(l+4),i=Math.round(l/2+2),p.setAttributeNS(null,"class",d("classPrefix")+"-hover-area"),p.setAttributeNS(null,"fill","#fff"),p.setAttributeNS(null,"cx",a[j+"x"]),p.setAttributeNS(null,"cy",a[j+"y"]),p.setAttributeNS(null,"r",i),o.setAttributeNS(null,"class",d("classPrefix")+"-hover-area"),o.setAttributeNS(null,"fill","#fff"),o.setAttributeNS(null,"x",a[j+"x"]+i/4),o.setAttributeNS(null,"y",a[j+"y"]-i),o.setAttributeNS(null,"width",g),o.setAttributeNS(null,"height",h)),n.appendChild(p),n.appendChild(o),n.appendChild(q),n.appendChild(b),n}}}.call(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.middlewares"),sigma.utils.pkg("sigma.utils"),sigma.middlewares.rescale=function(a,b,c){var d,e,f,g,h,i,j,k,l=this.graph.nodes(),m=this.graph.edges(),n=this.settings.embedObjects(c||{}),o=n("bounds")||sigma.utils.getBoundaries(this.graph,a,!0),p=o.minX,q=o.minY,r=o.maxX,s=o.maxY,t=o.sizeMax,u=o.weightMax,v=n("width")||1,w=n("height")||1,x=n("autoRescale"),y={nodePosition:1,nodeSize:1,edgeSize:1};for(x instanceof Array||(x=["nodePosition","nodeSize","edgeSize"]),d=0,e=x.length;e>d;d++)if(!y[x[d]])throw new Error('The rescale setting "'+x[d]+'" is not recognized.');var z=~x.indexOf("nodePosition"),A=~x.indexOf("nodeSize"),B=~x.indexOf("edgeSize");for(j="outside"===n("scalingMode")?Math.max(v/Math.max(r-p,1),w/Math.max(s-q,1)):Math.min(v/Math.max(r-p,1),w/Math.max(s-q,1)),k=(n("rescaleIgnoreSize")?0:(n("maxNodeSize")||t)/j)+(n("sideMargin")||0),r+=k,p-=k,s+=k,q-=k,j="outside"===n("scalingMode")?Math.max(v/Math.max(r-p,1),w/Math.max(s-q,1)):Math.min(v/Math.max(r-p,1),w/Math.max(s-q,1)),n("maxNodeSize")||n("minNodeSize")?n("maxNodeSize")===n("minNodeSize")?(f=0,g=+n("maxNodeSize")):(f=(n("maxNodeSize")-n("minNodeSize"))/t,g=+n("minNodeSize")):(f=1,g=0),n("maxEdgeSize")||n("minEdgeSize")?n("maxEdgeSize")===n("minEdgeSize")?(h=0,i=+n("minEdgeSize")):(h=(n("maxEdgeSize")-n("minEdgeSize"))/u,i=+n("minEdgeSize")):(h=1,i=0),d=0,e=m.length;e>d;d++)m[d][b+"size"]=m[d][a+"size"]*(B?h:1)+(B?i:0);for(d=0,e=l.length;e>d;d++)l[d][b+"size"]=l[d][a+"size"]*(A?f:1)+(A?g:0),l[d][b+"x"]=(l[d][a+"x"]-(r+p)/2)*(z?j:1),l[d][b+"y"]=(l[d][a+"y"]-(s+q)/2)*(z?j:1)},sigma.utils.getBoundaries=function(a,b,c){var d,e,f=a.edges(),g=a.nodes(),h=-1/0,i=-1/0,j=1/0,k=1/0,l=-1/0,m=-1/0;if(c)for(d=0,e=f.length;e>d;d++)h=Math.max(f[d][b+"size"],h);for(d=0,e=g.length;e>d;d++)i=Math.max(g[d][b+"size"],i),l=Math.max(g[d][b+"x"],l),j=Math.min(g[d][b+"x"],j),m=Math.max(g[d][b+"y"],m),k=Math.min(g[d][b+"y"],k);return h=h||1,i=i||1,{weightMax:h,sizeMax:i,minX:j,minY:k,maxX:l,maxY:m}}}.call(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.middlewares"),sigma.middlewares.copy=function(a,b){var c,d,e;if(b+""!=a+""){for(e=this.graph.nodes(),c=0,d=e.length;d>c;c++)e[c][b+"x"]=e[c][a+"x"],e[c][b+"y"]=e[c][a+"y"],e[c][b+"size"]=e[c][a+"size"];for(e=this.graph.edges(),c=0,d=e.length;d>c;c++)e[c][b+"size"]=e[c][a+"size"]}}}.call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.misc.animation.running");var b=function(){var a=0;return function(){return""+ ++a}}();sigma.misc.animation.camera=function(c,d,e){if(!(c instanceof sigma.classes.camera&&"object"==typeof d&&d))throw"animation.camera: Wrong arguments.";if("number"!=typeof d.x&&"number"!=typeof d.y&&"number"!=typeof d.ratio&&"number"!=typeof d.angle)throw"There must be at least one valid coordinate in the given val.";var f,g,h,i,j,k,l=e||{},m=sigma.utils.dateNow();return k={x:c.x,y:c.y,ratio:c.ratio,angle:c.angle},j=l.duration,i="function"!=typeof l.easing?sigma.utils.easings[l.easing||"quadraticInOut"]:l.easing,f=function(){var b,e=l.duration?(sigma.utils.dateNow()-m)/l.duration:1;e>=1?(c.isAnimated=!1,c.goTo({x:d.x!==a?d.x:k.x,y:d.y!==a?d.y:k.y,ratio:d.ratio!==a?d.ratio:k.ratio,angle:d.angle!==a?d.angle:k.angle}),cancelAnimationFrame(g),delete sigma.misc.animation.running[g],"function"==typeof l.onComplete&&l.onComplete()):(b=i(e),c.isAnimated=!0,c.goTo({x:d.x!==a?k.x+(d.x-k.x)*b:k.x,y:d.y!==a?k.y+(d.y-k.y)*b:k.y,ratio:d.ratio!==a?k.ratio+(d.ratio-k.ratio)*b:k.ratio,angle:d.angle!==a?k.angle+(d.angle-k.angle)*b:k.angle}),"function"==typeof l.onNewFrame&&l.onNewFrame(),h.frameId=requestAnimationFrame(f))},g=b(),h={frameId:requestAnimationFrame(f),target:c,type:"camera",options:l,fn:f},sigma.misc.animation.running[g]=h,g},sigma.misc.animation.kill=function(a){if(1!==arguments.length||"number"!=typeof a)throw"animation.kill: Wrong arguments.";var b=sigma.misc.animation.running[a];return b&&(cancelAnimationFrame(a),delete sigma.misc.animation.running[b.frameId],"camera"===b.type&&(b.target.isAnimated=!1),"function"==typeof(b.options||{}).onComplete&&b.options.onComplete()),this},sigma.misc.animation.killAll=function(a){var b,c,d=0,e="string"==typeof a?a:null,f="object"==typeof a?a:null,g=sigma.misc.animation.running;for(c in g)e&&g[c].type!==e||f&&g[c].target!==f||(b=sigma.misc.animation.running[c],cancelAnimationFrame(b.frameId),delete sigma.misc.animation.running[c],"camera"===b.type&&(b.target.isAnimated=!1),d++,"function"==typeof(b.options||{}).onComplete&&b.options.onComplete());return d},sigma.misc.animation.has=function(a){var b,c="string"==typeof a?a:null,d="object"==typeof a?a:null,e=sigma.misc.animation.running;for(b in e)if(!(c&&e[b].type!==c||d&&e[b].target!==d))return!0;return!1}}.call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.misc"),sigma.misc.bindEvents=function(b){function c(a){a&&(h="x"in a.data?a.data.x:h,i="y"in a.data?a.data.y:i);var c,d,e,f,g,k,l,m,n=[],o=h+j.width/2,p=i+j.height/2,q=j.camera.cameraPosition(h,i),r=j.camera.quadtree.point(q.x,q.y);if(r.length)for(c=0,e=r.length;e>c;c++)if(f=r[c],g=f[b+"x"],k=f[b+"y"],l=f[b+"size"],!f.hidden&&o>g-l&&g+l>o&&p>k-l&&k+l>p&&Math.sqrt(Math.pow(o-g,2)+Math.pow(p-k,2))<l){for(m=!1,d=0;d<n.length;d++)if(f.size>n[d].size){n.splice(d,0,f),m=!0;break}m||n.push(f)}return n}function d(c){function d(a,b){for(r=!1,g=0;g<a.length;g++)if(b.size>a[g].size){a.splice(g,0,b),r=!0;break}r||a.push(b)}if(!j.settings("enableEdgeHovering"))return[];var e=sigma.renderers.canvas&&j instanceof sigma.renderers.canvas;if(!e)throw new Error("The edge events feature is not compatible with the WebGL renderer");c&&(h="x"in c.data?c.data.x:h,i="y"in c.data?c.data.y:i);var f,g,k,l,m,n,o,p,q,r,s=j.settings("edgeHoverPrecision"),t={},u=[],v=h+j.width/2,w=i+j.height/2,x=j.camera.cameraPosition(h,i),y=[];if(e){var z=j.camera.quadtree.area(j.camera.getRectangle(j.width,j.height));for(l=z,f=0,k=l.length;k>f;f++)t[l[f].id]=l[f]}if(j.camera.edgequadtree!==a&&(y=j.camera.edgequadtree.point(x.x,x.y)),y.length)for(f=0,k=y.length;k>f;f++)m=y[f],o=j.graph.nodes(m.source),p=j.graph.nodes(m.target),n=m[b+"size"]||m["read_"+b+"size"],!m.hidden&&!o.hidden&&!p.hidden&&(!e||t[m.source]||t[m.target])&&sigma.utils.getDistance(o[b+"x"],o[b+"y"],v,w)>o[b+"size"]&&sigma.utils.getDistance(p[b+"x"],p[b+"y"],v,w)>p[b+"size"]&&("curve"==m.type||"curvedArrow"==m.type?o.id===p.id?(q=sigma.utils.getSelfLoopControlPoints(o[b+"x"],o[b+"y"],o[b+"size"]),sigma.utils.isPointOnBezierCurve(v,w,o[b+"x"],o[b+"y"],p[b+"x"],p[b+"y"],q.x1,q.y1,q.x2,q.y2,Math.max(n,s))&&d(u,m)):(q=sigma.utils.getQuadraticControlPoint(o[b+"x"],o[b+"y"],p[b+"x"],p[b+"y"]),sigma.utils.isPointOnQuadraticCurve(v,w,o[b+"x"],o[b+"y"],p[b+"x"],p[b+"y"],q.x,q.y,Math.max(n,s))&&d(u,m)):sigma.utils.isPointOnSegment(v,w,o[b+"x"],o[b+"y"],p[b+"x"],p[b+"y"],Math.max(n,s))&&d(u,m));return u}function e(a){function b(a){j.settings("eventsEnabled")&&(j.dispatchEvent("click",a.data),i=c(a),k=d(a),i.length?(j.dispatchEvent("clickNode",{node:i[0],captor:a.data}),j.dispatchEvent("clickNodes",{node:i,captor:a.data})):k.length?(j.dispatchEvent("clickEdge",{edge:k[0],captor:a.data}),j.dispatchEvent("clickEdges",{edge:k,captor:a.data})):j.dispatchEvent("clickStage",{captor:a.data}))}function e(a){j.settings("eventsEnabled")&&(j.dispatchEvent("doubleClick",a.data),i=c(a),k=d(a),i.length?(j.dispatchEvent("doubleClickNode",{node:i[0],captor:a.data}),j.dispatchEvent("doubleClickNodes",{node:i,captor:a.data})):k.length?(j.dispatchEvent("doubleClickEdge",{edge:k[0],captor:a.data}),j.dispatchEvent("doubleClickEdges",{edge:k,captor:a.data})):j.dispatchEvent("doubleClickStage",{captor:a.data}))}function f(a){j.settings("eventsEnabled")&&(j.dispatchEvent("rightClick",a.data),i=c(a),k=d(a),i.length?(j.dispatchEvent("rightClickNode",{node:i[0],captor:a.data}),j.dispatchEvent("rightClickNodes",{node:i,captor:a.data})):k.length?(j.dispatchEvent("rightClickEdge",{edge:k[0],captor:a.data}),j.dispatchEvent("rightClickEdges",{edge:k,captor:a.data})):j.dispatchEvent("rightClickStage",{captor:a.data}))}function g(a){if(j.settings("eventsEnabled")){var b,c,d,e,f=[],g=[];for(b in l)f.push(l[b]);for(l={},c=0,d=f.length;d>c;c++)j.dispatchEvent("outNode",{node:f[c],captor:a.data});for(f.length&&j.dispatchEvent("outNodes",{nodes:f,captor:a.data}),m={},c=0,e=g.length;e>c;c++)j.dispatchEvent("outEdge",{edge:g[c],captor:a.data});g.length&&j.dispatchEvent("outEdges",{edges:g,captor:a.data})}}function h(a){if(j.settings("eventsEnabled")){i=c(a),k=d(a);var b,e,f,g,h=[],n=[],o={},p=i.length,q=[],r=[],s={},t=k.length;for(b=0;p>b;b++)f=i[b],o[f.id]=f,l[f.id]||(n.push(f),l[f.id]=f);for(e in l)o[e]||(h.push(l[e]),delete l[e]);for(b=0,p=n.length;p>b;b++)j.dispatchEvent("overNode",{node:n[b],captor:a.data});for(b=0,p=h.length;p>b;b++)j.dispatchEvent("outNode",{node:h[b],captor:a.data});for(n.length&&j.dispatchEvent("overNodes",{nodes:n,captor:a.data}),h.length&&j.dispatchEvent("outNodes",{nodes:h,captor:a.data}),b=0;t>b;b++)g=k[b],s[g.id]=g,m[g.id]||(r.push(g),m[g.id]=g);for(e in m)s[e]||(q.push(m[e]),delete m[e]);for(b=0,t=r.length;t>b;b++)j.dispatchEvent("overEdge",{edge:r[b],captor:a.data});for(b=0,t=q.length;t>b;b++)j.dispatchEvent("outEdge",{edge:q[b],captor:a.data});r.length&&j.dispatchEvent("overEdges",{edges:r,captor:a.data}),q.length&&j.dispatchEvent("outEdges",{edges:q,captor:a.data})}}var i,k,l={},m={};a.bind("click",b),a.bind("mousedown",h),a.bind("mouseup",h),a.bind("mousemove",h),a.bind("mouseout",g),a.bind("doubleclick",e),a.bind("rightclick",f),j.bind("render",h)}var f,g,h,i,j=this;for(f=0,g=this.captors.length;g>f;f++)e(this.captors[f])}}.call(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.misc"),sigma.misc.bindDOMEvents=function(a){function b(a){this.attr=function(b){return a.getAttributeNS(null,b)},this.tag=a.tagName,this.class=this.attr("class"),this.id=this.attr("id"),this.isNode=function(){return!!~this.class.indexOf(g.settings("classPrefix")+"-node")},this.isEdge=function(){return!!~this.class.indexOf(g.settings("classPrefix")+"-edge")},this.isHover=function(){return!!~this.class.indexOf(g.settings("classPrefix")+"-hover")}}function c(a){if(g.settings("eventsEnabled")){g.dispatchEvent("click",a);var c=new b(a.target);c.isNode()?g.dispatchEvent("clickNode",{node:h.nodes(c.attr("data-node-id"))}):g.dispatchEvent("clickStage"),a.preventDefault(),a.stopPropagation()}}function d(a){if(g.settings("eventsEnabled")){g.dispatchEvent("doubleClick",a);var c=new b(a.target);c.isNode()?g.dispatchEvent("doubleClickNode",{node:h.nodes(c.attr("data-node-id"))}):g.dispatchEvent("doubleClickStage"),a.preventDefault(),a.stopPropagation()}}function e(a){var c=a.toElement||a.target;if(g.settings("eventsEnabled")&&c){var d=new b(c);if(d.isNode())g.dispatchEvent("overNode",{node:h.nodes(d.attr("data-node-id"))});else if(d.isEdge()){var e=h.edges(d.attr("data-edge-id"));g.dispatchEvent("overEdge",{edge:e,source:h.nodes(e.source),target:h.nodes(e.target)})}}}function f(a){var c=a.fromElement||a.originalTarget;if(g.settings("eventsEnabled")){var d=new b(c);if(d.isNode())g.dispatchEvent("outNode",{node:h.nodes(d.attr("data-node-id"))});else if(d.isEdge()){var e=h.edges(d.attr("data-edge-id"));g.dispatchEvent("outEdge",{edge:e,source:h.nodes(e.source),target:h.nodes(e.target)})}}}var g=this,h=this.graph;a.addEventListener("click",c,!1),sigma.utils.doubleClick(a,"click",d),a.addEventListener("touchstart",c,!1),sigma.utils.doubleClick(a,"touchstart",d),a.addEventListener("mouseover",e,!0),a.addEventListener("mouseout",f,!0)}}.call(this),function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.misc"),sigma.misc.drawHovers=function(a){function b(){var b,f,g,h,i,j=c.contexts.hover.canvas,k=c.settings("defaultNodeType"),l=c.settings("defaultEdgeType"),m=sigma.canvas.hovers,n=sigma.canvas.edgehovers,o=sigma.canvas.extremities,p=c.settings.embedObjects({prefix:a});if(c.contexts.hover.clearRect(0,0,j.width,j.height),p("enableHovering")&&p("singleHover")&&Object.keys(d).length&&(h=d[Object.keys(d)[0]],(m[h.type]||m[k]||m.def)(h,c.contexts.hover,p)),p("enableHovering")&&!p("singleHover"))for(b in d)(m[d[b].type]||m[k]||m.def)(d[b],c.contexts.hover,p);if(p("enableEdgeHovering")&&p("singleHover")&&Object.keys(e).length&&(i=e[Object.keys(e)[0]],f=c.graph.nodes(i.source),g=c.graph.nodes(i.target),i.hidden||((n[i.type]||n[l]||n.def)(i,f,g,c.contexts.hover,p),p("edgeHoverExtremities")?(o[i.type]||o.def)(i,f,g,c.contexts.hover,p):((sigma.canvas.nodes[f.type]||sigma.canvas.nodes.def)(f,c.contexts.hover,p),(sigma.canvas.nodes[g.type]||sigma.canvas.nodes.def)(g,c.contexts.hover,p)))),p("enableEdgeHovering")&&!p("singleHover"))for(b in e)i=e[b],f=c.graph.nodes(i.source),g=c.graph.nodes(i.target),i.hidden||((n[i.type]||n[l]||n.def)(i,f,g,c.contexts.hover,p),p("edgeHoverExtremities")?(o[i.type]||o.def)(i,f,g,c.contexts.hover,p):((sigma.canvas.nodes[f.type]||sigma.canvas.nodes.def)(f,c.contexts.hover,p),(sigma.canvas.nodes[g.type]||sigma.canvas.nodes.def)(g,c.contexts.hover,p)))}var c=this,d={},e={};this.bind("overNode",function(a){var c=a.data.node;c.hidden||(d[c.id]=c,b())}),this.bind("outNode",function(a){delete d[a.data.node.id],b()}),this.bind("overEdge",function(a){var c=a.data.edge;c.hidden||(e[c.id]=c,b())}),this.bind("outEdge",function(a){delete e[a.data.edge.id],b()}),this.bind("render",function(){b()})}}.call(this); \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/sigma.require.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/sigma.require.js
new file mode 100644
index 00000000..08381e62
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/topo/sigma/sigma.require.js
@@ -0,0 +1,12224 @@
+;(function(undefined) {
+ 'use strict';
+
+ var __instances = {};
+
+ /**
+ * This is the sigma instances constructor. One instance of sigma represent
+ * one graph. It is possible to represent this grapĥ with several renderers
+ * at the same time. By default, the default renderer (WebGL + Canvas
+ * polyfill) will be used as the only renderer, with the container specified
+ * in the configuration.
+ *
+ * @param {?*} conf The configuration of the instance. There are a lot of
+ * different recognized forms to instantiate sigma, check
+ * example files, documentation in this file and unit
+ * tests to know more.
+ * @return {sigma} The fresh new sigma instance.
+ *
+ * Instanciating sigma:
+ * ********************
+ * If no parameter is given to the constructor, the instance will be created
+ * without any renderer or camera. It will just instantiate the graph, and
+ * other modules will have to be instantiated through the public methods,
+ * like "addRenderer" etc:
+ *
+ * > s0 = new sigma();
+ * > s0.addRenderer({
+ * > type: 'canvas',
+ * > container: 'my-container-id'
+ * > });
+ *
+ * In most of the cases, sigma will simply be used with the default renderer.
+ * Then, since the only required parameter is the DOM container, there are
+ * some simpler way to call the constructor. The four following calls do the
+ * exact same things:
+ *
+ * > s1 = new sigma('my-container-id');
+ * > s2 = new sigma(document.getElementById('my-container-id'));
+ * > s3 = new sigma({
+ * > container: document.getElementById('my-container-id')
+ * > });
+ * > s4 = new sigma({
+ * > renderers: [{
+ * > container: document.getElementById('my-container-id')
+ * > }]
+ * > });
+ *
+ * Recognized parameters:
+ * **********************
+ * Here is the exhaustive list of every accepted parameters, when calling the
+ * constructor with to top level configuration object (fourth case in the
+ * previous examples):
+ *
+ * {?string} id The id of the instance. It will be generated
+ * automatically if not specified.
+ * {?array} renderers An array containing objects describing renderers.
+ * {?object} graph An object containing an array of nodes and an array
+ * of edges, to avoid having to add them by hand later.
+ * {?object} settings An object containing instance specific settings that
+ * will override the default ones defined in the object
+ * sigma.settings.
+ */
+ var sigma = function(conf) {
+ // Local variables:
+ // ****************
+ var i,
+ l,
+ a,
+ c,
+ o,
+ id;
+
+ sigma.classes.dispatcher.extend(this);
+
+ // Private attributes:
+ // *******************
+ var _self = this,
+ _conf = conf || {};
+
+ // Little shortcut:
+ // ****************
+ // The configuration is supposed to have a list of the configuration
+ // objects for each renderer.
+ // - If there are no configuration at all, then nothing is done.
+ // - If there are no renderer list, the given configuration object will be
+ // considered as describing the first and only renderer.
+ // - If there are no renderer list nor "container" object, it will be
+ // considered as the container itself (a DOM element).
+ // - If the argument passed to sigma() is a string, it will be considered
+ // as the ID of the DOM container.
+ if (
+ typeof _conf === 'string' ||
+ _conf instanceof HTMLElement
+ )
+ _conf = {
+ renderers: [_conf]
+ };
+ else if (Object.prototype.toString.call(_conf) === '[object Array]')
+ _conf = {
+ renderers: _conf
+ };
+
+ // Also check "renderer" and "container" keys:
+ o = _conf.renderers || _conf.renderer || _conf.container;
+ if (!_conf.renderers || _conf.renderers.length === 0)
+ if (
+ typeof o === 'string' ||
+ o instanceof HTMLElement ||
+ (typeof o === 'object' && 'container' in o)
+ )
+ _conf.renderers = [o];
+
+ // Recense the instance:
+ if (_conf.id) {
+ if (__instances[_conf.id])
+ throw 'sigma: Instance "' + _conf.id + '" already exists.';
+ Object.defineProperty(this, 'id', {
+ value: _conf.id
+ });
+ } else {
+ id = 0;
+ while (__instances[id])
+ id++;
+ Object.defineProperty(this, 'id', {
+ value: '' + id
+ });
+ }
+ __instances[this.id] = this;
+
+ // Initialize settings function:
+ this.settings = new sigma.classes.configurable(
+ sigma.settings,
+ _conf.settings || {}
+ );
+
+ // Initialize locked attributes:
+ Object.defineProperty(this, 'graph', {
+ value: new sigma.classes.graph(this.settings),
+ configurable: true
+ });
+ Object.defineProperty(this, 'middlewares', {
+ value: [],
+ configurable: true
+ });
+ Object.defineProperty(this, 'cameras', {
+ value: {},
+ configurable: true
+ });
+ Object.defineProperty(this, 'renderers', {
+ value: {},
+ configurable: true
+ });
+ Object.defineProperty(this, 'renderersPerCamera', {
+ value: {},
+ configurable: true
+ });
+ Object.defineProperty(this, 'cameraFrames', {
+ value: {},
+ configurable: true
+ });
+ Object.defineProperty(this, 'camera', {
+ get: function() {
+ return this.cameras[0];
+ }
+ });
+ Object.defineProperty(this, 'events', {
+ value: [
+ 'click',
+ 'rightClick',
+ 'clickStage',
+ 'doubleClickStage',
+ 'rightClickStage',
+ 'clickNode',
+ 'clickNodes',
+ 'doubleClickNode',
+ 'doubleClickNodes',
+ 'rightClickNode',
+ 'rightClickNodes',
+ 'overNode',
+ 'overNodes',
+ 'outNode',
+ 'outNodes',
+ 'downNode',
+ 'downNodes',
+ 'upNode',
+ 'upNodes'
+ ],
+ configurable: true
+ });
+
+ // Add a custom handler, to redispatch events from renderers:
+ this._handler = (function(e) {
+ var k,
+ data = {};
+
+ for (k in e.data)
+ data[k] = e.data[k];
+
+ data.renderer = e.target;
+ this.dispatchEvent(e.type, data);
+ }).bind(this);
+
+ // Initialize renderers:
+ a = _conf.renderers || [];
+ for (i = 0, l = a.length; i < l; i++)
+ this.addRenderer(a[i]);
+
+ // Initialize middlewares:
+ a = _conf.middlewares || [];
+ for (i = 0, l = a.length; i < l; i++)
+ this.middlewares.push(
+ typeof a[i] === 'string' ?
+ sigma.middlewares[a[i]] :
+ a[i]
+ );
+
+ // Check if there is already a graph to fill in:
+ if (typeof _conf.graph === 'object' && _conf.graph) {
+ this.graph.read(_conf.graph);
+
+ // If a graph is given to the to the instance, the "refresh" method is
+ // directly called:
+ this.refresh();
+ }
+
+ // Deal with resize:
+ window.addEventListener('resize', function() {
+ if (_self.settings)
+ _self.refresh();
+ });
+ };
+
+
+
+
+ /**
+ * This methods will instantiate and reference a new camera. If no id is
+ * specified, then an automatic id will be generated.
+ *
+ * @param {?string} id Eventually the camera id.
+ * @return {sigma.classes.camera} The fresh new camera instance.
+ */
+ sigma.prototype.addCamera = function(id) {
+ var self = this,
+ camera;
+
+ if (!arguments.length) {
+ id = 0;
+ while (this.cameras['' + id])
+ id++;
+ id = '' + id;
+ }
+
+ if (this.cameras[id])
+ throw 'sigma.addCamera: The camera "' + id + '" already exists.';
+
+ camera = new sigma.classes.camera(id, this.graph, this.settings);
+ this.cameras[id] = camera;
+
+ // Add a quadtree to the camera:
+ camera.quadtree = new sigma.classes.quad();
+
+ // Add an edgequadtree to the camera:
+ if (sigma.classes.edgequad !== undefined) {
+ camera.edgequadtree = new sigma.classes.edgequad();
+ }
+
+ camera.bind('coordinatesUpdated', function(e) {
+ self.renderCamera(camera, camera.isAnimated);
+ });
+
+ this.renderersPerCamera[id] = [];
+
+ return camera;
+ };
+
+ /**
+ * This method kills a camera, and every renderer attached to it.
+ *
+ * @param {string|camera} v The camera to kill or its ID.
+ * @return {sigma} Returns the instance.
+ */
+ sigma.prototype.killCamera = function(v) {
+ v = typeof v === 'string' ? this.cameras[v] : v;
+
+ if (!v)
+ throw 'sigma.killCamera: The camera is undefined.';
+
+ var i,
+ l,
+ a = this.renderersPerCamera[v.id];
+
+ for (l = a.length, i = l - 1; i >= 0; i--)
+ this.killRenderer(a[i]);
+
+ delete this.renderersPerCamera[v.id];
+ delete this.cameraFrames[v.id];
+ delete this.cameras[v.id];
+
+ if (v.kill)
+ v.kill();
+
+ return this;
+ };
+
+ /**
+ * This methods will instantiate and reference a new renderer. The "type"
+ * argument can be the constructor or its name in the "sigma.renderers"
+ * package. If no type is specified, then "sigma.renderers.def" will be used.
+ * If no id is specified, then an automatic id will be generated.
+ *
+ * @param {?object} options Eventually some options to give to the renderer
+ * constructor.
+ * @return {renderer} The fresh new renderer instance.
+ *
+ * Recognized parameters:
+ * **********************
+ * Here is the exhaustive list of every accepted parameters in the "options"
+ * object:
+ *
+ * {?string} id Eventually the renderer id.
+ * {?(function|string)} type Eventually the renderer constructor or its
+ * name in the "sigma.renderers" package.
+ * {?(camera|string)} camera Eventually the renderer camera or its
+ * id.
+ */
+ sigma.prototype.addRenderer = function(options) {
+ var id,
+ fn,
+ camera,
+ renderer,
+ o = options || {};
+
+ // Polymorphism:
+ if (typeof o === 'string')
+ o = {
+ container: document.getElementById(o)
+ };
+ else if (o instanceof HTMLElement)
+ o = {
+ container: o
+ };
+
+ // If the container still is a string, we get it by id
+ if (typeof o.container === 'string')
+ o.container = document.getElementById(o.container);
+
+ // Reference the new renderer:
+ if (!('id' in o)) {
+ id = 0;
+ while (this.renderers['' + id])
+ id++;
+ id = '' + id;
+ } else
+ id = o.id;
+
+ if (this.renderers[id])
+ throw 'sigma.addRenderer: The renderer "' + id + '" already exists.';
+
+ // Find the good constructor:
+ fn = typeof o.type === 'function' ? o.type : sigma.renderers[o.type];
+ fn = fn || sigma.renderers.def;
+
+ // Find the good camera:
+ camera = 'camera' in o ?
+ (
+ o.camera instanceof sigma.classes.camera ?
+ o.camera :
+ this.cameras[o.camera] || this.addCamera(o.camera)
+ ) :
+ this.addCamera();
+
+ if (this.cameras[camera.id] !== camera)
+ throw 'sigma.addRenderer: The camera is not properly referenced.';
+
+ // Instantiate:
+ renderer = new fn(this.graph, camera, this.settings, o);
+ this.renderers[id] = renderer;
+ Object.defineProperty(renderer, 'id', {
+ value: id
+ });
+
+ // Bind events:
+ if (renderer.bind)
+ renderer.bind(
+ [
+ 'click',
+ 'rightClick',
+ 'clickStage',
+ 'doubleClickStage',
+ 'rightClickStage',
+ 'clickNode',
+ 'clickNodes',
+ 'clickEdge',
+ 'clickEdges',
+ 'doubleClickNode',
+ 'doubleClickNodes',
+ 'doubleClickEdge',
+ 'doubleClickEdges',
+ 'rightClickNode',
+ 'rightClickNodes',
+ 'rightClickEdge',
+ 'rightClickEdges',
+ 'overNode',
+ 'overNodes',
+ 'overEdge',
+ 'overEdges',
+ 'outNode',
+ 'outNodes',
+ 'outEdge',
+ 'outEdges',
+ 'downNode',
+ 'downNodes',
+ 'downEdge',
+ 'downEdges',
+ 'upNode',
+ 'upNodes',
+ 'upEdge',
+ 'upEdges'
+ ],
+ this._handler
+ );
+
+ // Reference the renderer by its camera:
+ this.renderersPerCamera[camera.id].push(renderer);
+
+ return renderer;
+ };
+
+ /**
+ * This method kills a renderer.
+ *
+ * @param {string|renderer} v The renderer to kill or its ID.
+ * @return {sigma} Returns the instance.
+ */
+ sigma.prototype.killRenderer = function(v) {
+ v = typeof v === 'string' ? this.renderers[v] : v;
+
+ if (!v)
+ throw 'sigma.killRenderer: The renderer is undefined.';
+
+ var a = this.renderersPerCamera[v.camera.id],
+ i = a.indexOf(v);
+
+ if (i >= 0)
+ a.splice(i, 1);
+
+ if (v.kill)
+ v.kill();
+
+ delete this.renderers[v.id];
+
+ return this;
+ };
+
+
+
+
+ /**
+ * This method calls the "render" method of each renderer, with the same
+ * arguments than the "render" method, but will also check if the renderer
+ * has a "process" method, and call it if it exists.
+ *
+ * It is useful for quadtrees or WebGL processing, for instance.
+ *
+ * @param {?object} options Eventually some options to give to the refresh
+ * method.
+ * @return {sigma} Returns the instance itself.
+ *
+ * Recognized parameters:
+ * **********************
+ * Here is the exhaustive list of every accepted parameters in the "options"
+ * object:
+ *
+ * {?boolean} skipIndexation A flag specifying wether or not the refresh
+ * function should reindex the graph in the
+ * quadtrees or not (default: false).
+ */
+ sigma.prototype.refresh = function(options) {
+ var i,
+ l,
+ k,
+ a,
+ c,
+ bounds,
+ prefix = 0;
+
+ options = options || {};
+
+ // Call each middleware:
+ a = this.middlewares || [];
+ for (i = 0, l = a.length; i < l; i++)
+ a[i].call(
+ this,
+ (i === 0) ? '' : 'tmp' + prefix + ':',
+ (i === l - 1) ? 'ready:' : ('tmp' + (++prefix) + ':')
+ );
+
+ // Then, for each camera, call the "rescale" middleware, unless the
+ // settings specify not to:
+ for (k in this.cameras) {
+ c = this.cameras[k];
+ if (
+ c.settings('autoRescale') &&
+ this.renderersPerCamera[c.id] &&
+ this.renderersPerCamera[c.id].length
+ )
+ sigma.middlewares.rescale.call(
+ this,
+ a.length ? 'ready:' : '',
+ c.readPrefix,
+ {
+ width: this.renderersPerCamera[c.id][0].width,
+ height: this.renderersPerCamera[c.id][0].height
+ }
+ );
+ else
+ sigma.middlewares.copy.call(
+ this,
+ a.length ? 'ready:' : '',
+ c.readPrefix
+ );
+
+ if (!options.skipIndexation) {
+ // Find graph boundaries:
+ bounds = sigma.utils.getBoundaries(
+ this.graph,
+ c.readPrefix
+ );
+
+ // Refresh quadtree:
+ c.quadtree.index(this.graph.nodes(), {
+ prefix: c.readPrefix,
+ bounds: {
+ x: bounds.minX,
+ y: bounds.minY,
+ width: bounds.maxX - bounds.minX,
+ height: bounds.maxY - bounds.minY
+ }
+ });
+
+ // Refresh edgequadtree:
+ if (
+ c.edgequadtree !== undefined &&
+ c.settings('drawEdges') &&
+ c.settings('enableEdgeHovering')
+ ) {
+ c.edgequadtree.index(this.graph, {
+ prefix: c.readPrefix,
+ bounds: {
+ x: bounds.minX,
+ y: bounds.minY,
+ width: bounds.maxX - bounds.minX,
+ height: bounds.maxY - bounds.minY
+ }
+ });
+ }
+ }
+ }
+
+ // Call each renderer:
+ a = Object.keys(this.renderers);
+ for (i = 0, l = a.length; i < l; i++)
+ if (this.renderers[a[i]].process) {
+ if (this.settings('skipErrors'))
+ try {
+ this.renderers[a[i]].process();
+ } catch (e) {
+ console.log(
+ 'Warning: The renderer "' + a[i] + '" crashed on ".process()"'
+ );
+ }
+ else
+ this.renderers[a[i]].process();
+ }
+
+ this.render();
+
+ return this;
+ };
+
+ /**
+ * This method calls the "render" method of each renderer.
+ *
+ * @return {sigma} Returns the instance itself.
+ */
+ sigma.prototype.render = function() {
+ var i,
+ l,
+ a,
+ prefix = 0;
+
+ // Call each renderer:
+ a = Object.keys(this.renderers);
+ for (i = 0, l = a.length; i < l; i++)
+ if (this.settings('skipErrors'))
+ try {
+ this.renderers[a[i]].render();
+ } catch (e) {
+ if (this.settings('verbose'))
+ console.log(
+ 'Warning: The renderer "' + a[i] + '" crashed on ".render()"'
+ );
+ }
+ else
+ this.renderers[a[i]].render();
+
+ return this;
+ };
+
+ /**
+ * This method calls the "render" method of each renderer that is bound to
+ * the specified camera. To improve the performances, if this method is
+ * called too often, the number of effective renderings is limitated to one
+ * per frame, unless you are using the "force" flag.
+ *
+ * @param {sigma.classes.camera} camera The camera to render.
+ * @param {?boolean} force If true, will render the camera
+ * directly.
+ * @return {sigma} Returns the instance itself.
+ */
+ sigma.prototype.renderCamera = function(camera, force) {
+ var i,
+ l,
+ a,
+ self = this;
+
+ if (force) {
+ a = this.renderersPerCamera[camera.id];
+ for (i = 0, l = a.length; i < l; i++)
+ if (this.settings('skipErrors'))
+ try {
+ a[i].render();
+ } catch (e) {
+ if (this.settings('verbose'))
+ console.log(
+ 'Warning: The renderer "' + a[i].id + '" crashed on ".render()"'
+ );
+ }
+ else
+ a[i].render();
+ } else {
+ if (!this.cameraFrames[camera.id]) {
+ a = this.renderersPerCamera[camera.id];
+ for (i = 0, l = a.length; i < l; i++)
+ if (this.settings('skipErrors'))
+ try {
+ a[i].render();
+ } catch (e) {
+ if (this.settings('verbose'))
+ console.log(
+ 'Warning: The renderer "' +
+ a[i].id +
+ '" crashed on ".render()"'
+ );
+ }
+ else
+ a[i].render();
+
+ this.cameraFrames[camera.id] = requestAnimationFrame(function() {
+ delete self.cameraFrames[camera.id];
+ });
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * This method calls the "kill" method of each module and destroys any
+ * reference from the instance.
+ */
+ sigma.prototype.kill = function() {
+ var k;
+
+ // Dispatching event
+ this.dispatchEvent('kill');
+
+ // Kill graph:
+ this.graph.kill();
+
+ // Kill middlewares:
+ delete this.middlewares;
+
+ // Kill each renderer:
+ for (k in this.renderers)
+ this.killRenderer(this.renderers[k]);
+
+ // Kill each camera:
+ for (k in this.cameras)
+ this.killCamera(this.cameras[k]);
+
+ delete this.renderers;
+ delete this.cameras;
+
+ // Kill everything else:
+ for (k in this)
+ if (this.hasOwnProperty(k))
+ delete this[k];
+
+ delete __instances[this.id];
+ };
+
+
+
+
+ /**
+ * Returns a clone of the instances object or a specific running instance.
+ *
+ * @param {?string} id Eventually an instance ID.
+ * @return {object} The related instance or a clone of the instances
+ * object.
+ */
+ sigma.instances = function(id) {
+ return arguments.length ?
+ __instances[id] :
+ sigma.utils.extend({}, __instances);
+ };
+
+
+
+ /**
+ * The current version of sigma:
+ */
+ sigma.version = '1.1.0';
+
+
+
+
+ /**
+ * EXPORT:
+ * *******
+ */
+ if (typeof this.sigma !== 'undefined')
+ throw 'An object called sigma is already in the global scope.';
+
+ this.sigma = sigma;
+
+}).call(this);
+
+/**
+ * conrad.js is a tiny JavaScript jobs scheduler,
+ *
+ * Version: 0.1.0
+ * Sources: http://github.com/jacomyal/conrad.js
+ * Doc: http://github.com/jacomyal/conrad.js#readme
+ *
+ * License:
+ * --------
+ * Copyright © 2013 Alexis Jacomy, Sciences-Po médialab
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * The Software is provided "as is", without warranty of any kind, express or
+ * implied, including but not limited to the warranties of merchantability,
+ * fitness for a particular purpose and noninfringement. In no event shall the
+ * authors or copyright holders be liable for any claim, damages or other
+ * liability, whether in an action of contract, tort or otherwise, arising
+ * from, out of or in connection with the software or the use or other dealings
+ * in the Software.
+ */
+(function(global) {
+ 'use strict';
+
+ // Check that conrad.js has not been loaded yet:
+ if (global.conrad)
+ throw new Error('conrad already exists');
+
+
+ /**
+ * PRIVATE VARIABLES:
+ * ******************
+ */
+
+ /**
+ * A flag indicating whether conrad is running or not.
+ *
+ * @type {Number}
+ */
+ var _lastFrameTime;
+
+ /**
+ * A flag indicating whether conrad is running or not.
+ *
+ * @type {Boolean}
+ */
+ var _isRunning = false;
+
+ /**
+ * The hash of registered jobs. Each job must at least have a unique ID
+ * under the key "id" and a function under the key "job". This hash
+ * contains each running job and each waiting job.
+ *
+ * @type {Object}
+ */
+ var _jobs = {};
+
+ /**
+ * The hash of currently running jobs.
+ *
+ * @type {Object}
+ */
+ var _runningJobs = {};
+
+ /**
+ * The array of currently running jobs, sorted by priority.
+ *
+ * @type {Array}
+ */
+ var _sortedByPriorityJobs = [];
+
+ /**
+ * The array of currently waiting jobs.
+ *
+ * @type {Object}
+ */
+ var _waitingJobs = {};
+
+ /**
+ * The array of finished jobs. They are stored in an array, since two jobs
+ * with the same "id" can happen at two different times.
+ *
+ * @type {Array}
+ */
+ var _doneJobs = [];
+
+ /**
+ * A dirty flag to keep conrad from starting: Indeed, when addJob() is called
+ * with several jobs, conrad must be started only at the end. This flag keeps
+ * me from duplicating the code that effectively adds a job.
+ *
+ * @type {Boolean}
+ */
+ var _noStart = false;
+
+ /**
+ * An hash containing some global settings about how conrad.js should
+ * behave.
+ *
+ * @type {Object}
+ */
+ var _parameters = {
+ frameDuration: 20,
+ history: true
+ };
+
+ /**
+ * This object contains every handlers bound to conrad events. It does not
+ * requirea any DOM implementation, since the events are all JavaScript.
+ *
+ * @type {Object}
+ */
+ var _handlers = Object.create(null);
+
+
+ /**
+ * PRIVATE FUNCTIONS:
+ * ******************
+ */
+
+ /**
+ * Will execute the handler everytime that the indicated event (or the
+ * indicated events) will be triggered.
+ *
+ * @param {string|array|object} events The name of the event (or the events
+ * separated by spaces).
+ * @param {function(Object)} handler The handler to bind.
+ * @return {Object} Returns conrad.
+ */
+ function _bind(events, handler) {
+ var i,
+ i_end,
+ event,
+ eArray;
+
+ if (!arguments.length)
+ return;
+ else if (
+ arguments.length === 1 &&
+ Object(arguments[0]) === arguments[0]
+ )
+ for (events in arguments[0])
+ _bind(events, arguments[0][events]);
+ else if (arguments.length > 1) {
+ eArray =
+ Array.isArray(events) ?
+ events :
+ events.split(/ /);
+
+ for (i = 0, i_end = eArray.length; i !== i_end; i += 1) {
+ event = eArray[i];
+
+ if (!_handlers[event])
+ _handlers[event] = [];
+
+ // Using an object instead of directly the handler will make possible
+ // later to add flags
+ _handlers[event].push({
+ handler: handler
+ });
+ }
+ }
+ }
+
+ /**
+ * Removes the handler from a specified event (or specified events).
+ *
+ * @param {?string} events The name of the event (or the events
+ * separated by spaces). If undefined,
+ * then all handlers are removed.
+ * @param {?function(Object)} handler The handler to unbind. If undefined,
+ * each handler bound to the event or the
+ * events will be removed.
+ * @return {Object} Returns conrad.
+ */
+ function _unbind(events, handler) {
+ var i,
+ i_end,
+ j,
+ j_end,
+ a,
+ event,
+ eArray = Array.isArray(events) ?
+ events :
+ events.split(/ /);
+
+ if (!arguments.length)
+ _handlers = Object.create(null);
+ else if (handler) {
+ for (i = 0, i_end = eArray.length; i !== i_end; i += 1) {
+ event = eArray[i];
+ if (_handlers[event]) {
+ a = [];
+ for (j = 0, j_end = _handlers[event].length; j !== j_end; j += 1)
+ if (_handlers[event][j].handler !== handler)
+ a.push(_handlers[event][j]);
+
+ _handlers[event] = a;
+ }
+
+ if (_handlers[event] && _handlers[event].length === 0)
+ delete _handlers[event];
+ }
+ } else
+ for (i = 0, i_end = eArray.length; i !== i_end; i += 1)
+ delete _handlers[eArray[i]];
+ }
+
+ /**
+ * Executes each handler bound to the event.
+ *
+ * @param {string} events The name of the event (or the events separated
+ * by spaces).
+ * @param {?Object} data The content of the event (optional).
+ * @return {Object} Returns conrad.
+ */
+ function _dispatch(events, data) {
+ var i,
+ j,
+ i_end,
+ j_end,
+ event,
+ eventName,
+ eArray = Array.isArray(events) ?
+ events :
+ events.split(/ /);
+
+ data = data === undefined ? {} : data;
+
+ for (i = 0, i_end = eArray.length; i !== i_end; i += 1) {
+ eventName = eArray[i];
+
+ if (_handlers[eventName]) {
+ event = {
+ type: eventName,
+ data: data || {}
+ };
+
+ for (j = 0, j_end = _handlers[eventName].length; j !== j_end; j += 1)
+ try {
+ _handlers[eventName][j].handler(event);
+ } catch (e) {}
+ }
+ }
+ }
+
+ /**
+ * Executes the most prioritary job once, and deals with filling the stats
+ * (done, time, averageTime, currentTime, etc...).
+ *
+ * @return {?Object} Returns the job object if it has to be killed, null else.
+ */
+ function _executeFirstJob() {
+ var i,
+ l,
+ test,
+ kill,
+ pushed = false,
+ time = __dateNow(),
+ job = _sortedByPriorityJobs.shift();
+
+ // Execute the job and look at the result:
+ test = job.job();
+
+ // Deal with stats:
+ time = __dateNow() - time;
+ job.done++;
+ job.time += time;
+ job.currentTime += time;
+ job.weightTime = job.currentTime / (job.weight || 1);
+ job.averageTime = job.time / job.done;
+
+ // Check if the job has to be killed:
+ kill = job.count ? (job.count <= job.done) : !test;
+
+ // Reset priorities:
+ if (!kill) {
+ for (i = 0, l = _sortedByPriorityJobs.length; i < l; i++)
+ if (_sortedByPriorityJobs[i].weightTime > job.weightTime) {
+ _sortedByPriorityJobs.splice(i, 0, job);
+ pushed = true;
+ break;
+ }
+
+ if (!pushed)
+ _sortedByPriorityJobs.push(job);
+ }
+
+ return kill ? job : null;
+ }
+
+ /**
+ * Activates a job, by adding it to the _runningJobs object and the
+ * _sortedByPriorityJobs array. It also initializes its currentTime value.
+ *
+ * @param {Object} job The job to activate.
+ */
+ function _activateJob(job) {
+ var l = _sortedByPriorityJobs.length;
+
+ // Add the job to the running jobs:
+ _runningJobs[job.id] = job;
+ job.status = 'running';
+
+ // Add the job to the priorities:
+ if (l) {
+ job.weightTime = _sortedByPriorityJobs[l - 1].weightTime;
+ job.currentTime = job.weightTime * (job.weight || 1);
+ }
+
+ // Initialize the job and dispatch:
+ job.startTime = __dateNow();
+ _dispatch('jobStarted', __clone(job));
+
+ _sortedByPriorityJobs.push(job);
+ }
+
+ /**
+ * The main loop of conrad.js:
+ * . It executes job such that they all occupate the same processing time.
+ * . It stops jobs that do not need to be executed anymore.
+ * . It triggers callbacks when it is relevant.
+ * . It starts waiting jobs when they need to be started.
+ * . It injects frames to keep a constant frapes per second ratio.
+ * . It stops itself when there are no more jobs to execute.
+ */
+ function _loop() {
+ var k,
+ o,
+ l,
+ job,
+ time,
+ deadJob;
+
+ // Deal with the newly added jobs (the _jobs object):
+ for (k in _jobs) {
+ job = _jobs[k];
+
+ if (job.after)
+ _waitingJobs[k] = job;
+ else
+ _activateJob(job);
+
+ delete _jobs[k];
+ }
+
+ // Set the _isRunning flag to false if there are no running job:
+ _isRunning = !!_sortedByPriorityJobs.length;
+
+ // Deal with the running jobs (the _runningJobs object):
+ while (
+ _sortedByPriorityJobs.length &&
+ __dateNow() - _lastFrameTime < _parameters.frameDuration
+ ) {
+ deadJob = _executeFirstJob();
+
+ // Deal with the case where the job has ended:
+ if (deadJob) {
+ _killJob(deadJob.id);
+
+ // Check for waiting jobs:
+ for (k in _waitingJobs)
+ if (_waitingJobs[k].after === deadJob.id) {
+ _activateJob(_waitingJobs[k]);
+ delete _waitingJobs[k];
+ }
+ }
+ }
+
+ // Check if conrad still has jobs to deal with, and kill it if not:
+ if (_isRunning) {
+ // Update the _lastFrameTime:
+ _lastFrameTime = __dateNow();
+
+ _dispatch('enterFrame');
+ setTimeout(_loop, 0);
+ } else
+ _dispatch('stop');
+ }
+
+ /**
+ * Adds one or more jobs, and starts the loop if no job was running before. A
+ * job is at least a unique string "id" and a function, and there are some
+ * parameters that you can specify for each job to modify the way conrad will
+ * execute it. If a job is added with the "id" of another job that is waiting
+ * or still running, an error will be thrown.
+ *
+ * When a job is added, it is referenced in the _jobs object, by its id.
+ * Then, if it has to be executed right now, it will be also referenced in
+ * the _runningJobs object. If it has to wait, then it will be added into the
+ * _waitingJobs object, until it can start.
+ *
+ * Keep reading this documentation to see how to call this method.
+ *
+ * @return {Object} Returns conrad.
+ *
+ * Adding one job:
+ * ***************
+ * Basically, a job is defined by its string id and a function (the job). It
+ * is also possible to add some parameters:
+ *
+ * > conrad.addJob('myJobId', myJobFunction);
+ * > conrad.addJob('myJobId', {
+ * > job: myJobFunction,
+ * > someParameter: someValue
+ * > });
+ * > conrad.addJob({
+ * > id: 'myJobId',
+ * > job: myJobFunction,
+ * > someParameter: someValue
+ * > });
+ *
+ * Adding several jobs:
+ * ********************
+ * When adding several jobs at the same time, it is possible to specify
+ * parameters for each one individually or for all:
+ *
+ * > conrad.addJob([
+ * > {
+ * > id: 'myJobId1',
+ * > job: myJobFunction1,
+ * > someParameter1: someValue1
+ * > },
+ * > {
+ * > id: 'myJobId2',
+ * > job: myJobFunction2,
+ * > someParameter2: someValue2
+ * > }
+ * > ], {
+ * > someCommonParameter: someCommonValue
+ * > });
+ * > conrad.addJob({
+ * > myJobId1: {,
+ * > job: myJobFunction1,
+ * > someParameter1: someValue1
+ * > },
+ * > myJobId2: {,
+ * > job: myJobFunction2,
+ * > someParameter2: someValue2
+ * > }
+ * > }, {
+ * > someCommonParameter: someCommonValue
+ * > });
+ * > conrad.addJob({
+ * > myJobId1: myJobFunction1,
+ * > myJobId2: myJobFunction2
+ * > }, {
+ * > someCommonParameter: someCommonValue
+ * > });
+ *
+ * Recognized parameters:
+ * **********************
+ * Here is the exhaustive list of every accepted parameters:
+ *
+ * {?Function} end A callback to execute when the job is ended. It is
+ * not executed if the job is killed instead of ended
+ * "naturally".
+ * {?Integer} count The number of time the job has to be executed.
+ * {?Number} weight If specified, the job will be executed as it was
+ * added "weight" times.
+ * {?String} after The id of another job (eventually not added yet).
+ * If specified, this job will start only when the
+ * specified "after" job is ended.
+ */
+ function _addJob(v1, v2) {
+ var i,
+ l,
+ o;
+
+ // Array of jobs:
+ if (Array.isArray(v1)) {
+ // Keep conrad to start until the last job is added:
+ _noStart = true;
+
+ for (i = 0, l = v1.length; i < l; i++)
+ _addJob(v1[i].id, __extend(v1[i], v2));
+
+ _noStart = false;
+ if (!_isRunning) {
+ // Update the _lastFrameTime:
+ _lastFrameTime = __dateNow();
+
+ _dispatch('start');
+ _loop();
+ }
+ } else if (typeof v1 === 'object') {
+ // One job (object):
+ if (typeof v1.id === 'string')
+ _addJob(v1.id, v1);
+
+ // Hash of jobs:
+ else {
+ // Keep conrad to start until the last job is added:
+ _noStart = true;
+
+ for (i in v1)
+ if (typeof v1[i] === 'function')
+ _addJob(i, __extend({
+ job: v1[i]
+ }, v2));
+ else
+ _addJob(i, __extend(v1[i], v2));
+
+ _noStart = false;
+ if (!_isRunning) {
+ // Update the _lastFrameTime:
+ _lastFrameTime = __dateNow();
+
+ _dispatch('start');
+ _loop();
+ }
+ }
+
+ // One job (string, *):
+ } else if (typeof v1 === 'string') {
+ if (_hasJob(v1))
+ throw new Error(
+ '[conrad.addJob] Job with id "' + v1 + '" already exists.'
+ );
+
+ // One job (string, function):
+ if (typeof v2 === 'function') {
+ o = {
+ id: v1,
+ done: 0,
+ time: 0,
+ status: 'waiting',
+ currentTime: 0,
+ averageTime: 0,
+ weightTime: 0,
+ job: v2
+ };
+
+ // One job (string, object):
+ } else if (typeof v2 === 'object') {
+ o = __extend(
+ {
+ id: v1,
+ done: 0,
+ time: 0,
+ status: 'waiting',
+ currentTime: 0,
+ averageTime: 0,
+ weightTime: 0
+ },
+ v2
+ );
+
+ // If none of those cases, throw an error:
+ } else
+ throw new Error('[conrad.addJob] Wrong arguments.');
+
+ // Effectively add the job:
+ _jobs[v1] = o;
+ _dispatch('jobAdded', __clone(o));
+
+ // Check if the loop has to be started:
+ if (!_isRunning && !_noStart) {
+ // Update the _lastFrameTime:
+ _lastFrameTime = __dateNow();
+
+ _dispatch('start');
+ _loop();
+ }
+
+ // If none of those cases, throw an error:
+ } else
+ throw new Error('[conrad.addJob] Wrong arguments.');
+
+ return this;
+ }
+
+ /**
+ * Kills one or more jobs, indicated by their ids. It is only possible to
+ * kill running jobs or waiting jobs. If you try to kill a job that does not
+ * exist or that is already killed, a warning will be thrown.
+ *
+ * @param {Array|String} v1 A string job id or an array of job ids.
+ * @return {Object} Returns conrad.
+ */
+ function _killJob(v1) {
+ var i,
+ l,
+ k,
+ a,
+ job,
+ found = false;
+
+ // Array of job ids:
+ if (Array.isArray(v1))
+ for (i = 0, l = v1.length; i < l; i++)
+ _killJob(v1[i]);
+
+ // One job's id:
+ else if (typeof v1 === 'string') {
+ a = [_runningJobs, _waitingJobs, _jobs];
+
+ // Remove the job from the hashes:
+ for (i = 0, l = a.length; i < l; i++)
+ if (v1 in a[i]) {
+ job = a[i][v1];
+
+ if (_parameters.history) {
+ job.status = 'done';
+ _doneJobs.push(job);
+ }
+
+ _dispatch('jobEnded', __clone(job));
+ delete a[i][v1];
+
+ if (typeof job.end === 'function')
+ job.end();
+
+ found = true;
+ }
+
+ // Remove the priorities array:
+ a = _sortedByPriorityJobs;
+ for (i = 0, l = a.length; i < l; i++)
+ if (a[i].id === v1) {
+ a.splice(i, 1);
+ break;
+ }
+
+ if (!found)
+ throw new Error('[conrad.killJob] Job "' + v1 + '" not found.');
+
+ // If none of those cases, throw an error:
+ } else
+ throw new Error('[conrad.killJob] Wrong arguments.');
+
+ return this;
+ }
+
+ /**
+ * Kills every running, waiting, and just added jobs.
+ *
+ * @return {Object} Returns conrad.
+ */
+ function _killAll() {
+ var k,
+ jobs = __extend(_jobs, _runningJobs, _waitingJobs);
+
+ // Take every jobs and push them into the _doneJobs object:
+ if (_parameters.history)
+ for (k in jobs) {
+ jobs[k].status = 'done';
+ _doneJobs.push(jobs[k]);
+
+ if (typeof jobs[k].end === 'function')
+ jobs[k].end();
+ }
+
+ // Reinitialize the different jobs lists:
+ _jobs = {};
+ _waitingJobs = {};
+ _runningJobs = {};
+ _sortedByPriorityJobs = [];
+
+ // In case some jobs are added right after the kill:
+ _isRunning = false;
+
+ return this;
+ }
+
+ /**
+ * Returns true if a job with the specified id is currently running or
+ * waiting, and false else.
+ *
+ * @param {String} id The id of the job.
+ * @return {?Object} Returns the job object if it exists.
+ */
+ function _hasJob(id) {
+ var job = _jobs[id] || _runningJobs[id] || _waitingJobs[id];
+ return job ? __extend(job) : null;
+ }
+
+ /**
+ * This method will set the setting specified by "v1" to the value specified
+ * by "v2" if both are given, and else return the current value of the
+ * settings "v1".
+ *
+ * @param {String} v1 The name of the property.
+ * @param {?*} v2 Eventually, a value to set to the specified
+ * property.
+ * @return {Object|*} Returns the specified settings value if "v2" is not
+ * given, and conrad else.
+ */
+ function _settings(v1, v2) {
+ var o;
+
+ if (typeof a1 === 'string' && arguments.length === 1)
+ return _parameters[a1];
+ else {
+ o = (typeof a1 === 'object' && arguments.length === 1) ?
+ a1 || {} :
+ {};
+ if (typeof a1 === 'string')
+ o[a1] = a2;
+
+ for (var k in o)
+ if (o[k] !== undefined)
+ _parameters[k] = o[k];
+ else
+ delete _parameters[k];
+
+ return this;
+ }
+ }
+
+ /**
+ * Returns true if conrad is currently running, and false else.
+ *
+ * @return {Boolean} Returns _isRunning.
+ */
+ function _getIsRunning() {
+ return _isRunning;
+ }
+
+ /**
+ * Unreference every job that is stored in the _doneJobs object. It will
+ * not be possible anymore to get stats about these jobs, but it will release
+ * the memory.
+ *
+ * @return {Object} Returns conrad.
+ */
+ function _clearHistory() {
+ _doneJobs = [];
+ return this;
+ }
+
+ /**
+ * Returns a snapshot of every data about jobs that wait to be started, are
+ * currently running or are done.
+ *
+ * It is possible to get only running, waiting or done jobs by giving
+ * "running", "waiting" or "done" as fist argument.
+ *
+ * It is also possible to get every job with a specified id by giving it as
+ * first argument. Also, using a RegExp instead of an id will return every
+ * jobs whose ids match the RegExp. And these two last use cases work as well
+ * by giving before "running", "waiting" or "done".
+ *
+ * @return {Array} The array of the matching jobs.
+ *
+ * Some call examples:
+ * *******************
+ * > conrad.getStats('running')
+ * > conrad.getStats('waiting')
+ * > conrad.getStats('done')
+ * > conrad.getStats('myJob')
+ * > conrad.getStats(/test/)
+ * > conrad.getStats('running', 'myRunningJob')
+ * > conrad.getStats('running', /test/)
+ */
+ function _getStats(v1, v2) {
+ var a,
+ k,
+ i,
+ l,
+ stats,
+ pattern,
+ isPatternString;
+
+ if (!arguments.length) {
+ stats = [];
+
+ for (k in _jobs)
+ stats.push(_jobs[k]);
+
+ for (k in _waitingJobs)
+ stats.push(_waitingJobs[k]);
+
+ for (k in _runningJobs)
+ stats.push(_runningJobs[k]);
+
+ stats = stats.concat(_doneJobs);
+ }
+
+ if (typeof v1 === 'string')
+ switch (v1) {
+ case 'waiting':
+ stats = __objectValues(_waitingJobs);
+ break;
+ case 'running':
+ stats = __objectValues(_runningJobs);
+ break;
+ case 'done':
+ stats = _doneJobs;
+ break;
+ default:
+ pattern = v1;
+ }
+
+ if (v1 instanceof RegExp)
+ pattern = v1;
+
+ if (!pattern && (typeof v2 === 'string' || v2 instanceof RegExp))
+ pattern = v2;
+
+ // Filter jobs if a pattern is given:
+ if (pattern) {
+ isPatternString = typeof pattern === 'string';
+
+ if (stats instanceof Array) {
+ a = stats;
+ } else if (typeof stats === 'object') {
+ a = [];
+
+ for (k in stats)
+ a = a.concat(stats[k]);
+ } else {
+ a = [];
+
+ for (k in _jobs)
+ a.push(_jobs[k]);
+
+ for (k in _waitingJobs)
+ a.push(_waitingJobs[k]);
+
+ for (k in _runningJobs)
+ a.push(_runningJobs[k]);
+
+ a = a.concat(_doneJobs);
+ }
+
+ stats = [];
+ for (i = 0, l = a.length; i < l; i++)
+ if (isPatternString ? a[i].id === pattern : a[i].id.match(pattern))
+ stats.push(a[i]);
+ }
+
+ return __clone(stats);
+ }
+
+
+ /**
+ * TOOLS FUNCTIONS:
+ * ****************
+ */
+
+ /**
+ * This function takes any number of objects as arguments, copies from each
+ * of these objects each pair key/value into a new object, and finally
+ * returns this object.
+ *
+ * The arguments are parsed from the last one to the first one, such that
+ * when two objects have keys in common, the "earliest" object wins.
+ *
+ * Example:
+ * ********
+ * > var o1 = {
+ * > a: 1,
+ * > b: 2,
+ * > c: '3'
+ * > },
+ * > o2 = {
+ * > c: '4',
+ * > d: [ 5 ]
+ * > };
+ * > __extend(o1, o2);
+ * > // Returns: {
+ * > // a: 1,
+ * > // b: 2,
+ * > // c: '3',
+ * > // d: [ 5 ]
+ * > // };
+ *
+ * @param {Object+} Any number of objects.
+ * @return {Object} The merged object.
+ */
+ function __extend() {
+ var i,
+ k,
+ res = {},
+ l = arguments.length;
+
+ for (i = l - 1; i >= 0; i--)
+ for (k in arguments[i])
+ res[k] = arguments[i][k];
+
+ return res;
+ }
+
+ /**
+ * This function simply clones an object. This object must contain only
+ * objects, arrays and immutable values. Since it is not public, it does not
+ * deal with cyclic references, DOM elements and instantiated objects - so
+ * use it carefully.
+ *
+ * @param {Object} The object to clone.
+ * @return {Object} The clone.
+ */
+ function __clone(item) {
+ var result, i, k, l;
+
+ if (!item)
+ return item;
+
+ if (Array.isArray(item)) {
+ result = [];
+ for (i = 0, l = item.length; i < l; i++)
+ result.push(__clone(item[i]));
+ } else if (typeof item === 'object') {
+ result = {};
+ for (i in item)
+ result[i] = __clone(item[i]);
+ } else
+ result = item;
+
+ return result;
+ }
+
+ /**
+ * Returns an array containing the values of an object.
+ *
+ * @param {Object} The object.
+ * @return {Array} The array of values.
+ */
+ function __objectValues(o) {
+ var k,
+ a = [];
+
+ for (k in o)
+ a.push(o[k]);
+
+ return a;
+ }
+
+ /**
+ * A short "Date.now()" polyfill.
+ *
+ * @return {Number} The current time (in ms).
+ */
+ function __dateNow() {
+ return Date.now ? Date.now() : new Date().getTime();
+ }
+
+ /**
+ * Polyfill for the Array.isArray function:
+ */
+ if (!Array.isArray)
+ Array.isArray = function(v) {
+ return Object.prototype.toString.call(v) === '[object Array]';
+ };
+
+
+ /**
+ * EXPORT PUBLIC API:
+ * ******************
+ */
+ var conrad = {
+ hasJob: _hasJob,
+ addJob: _addJob,
+ killJob: _killJob,
+ killAll: _killAll,
+ settings: _settings,
+ getStats: _getStats,
+ isRunning: _getIsRunning,
+ clearHistory: _clearHistory,
+
+ // Events management:
+ bind: _bind,
+ unbind: _unbind,
+
+ // Version:
+ version: '0.1.0'
+ };
+
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = conrad;
+ exports.conrad = conrad;
+ }
+ global.conrad = conrad;
+})(this);
+
+// Hardcoded export for the node.js version:
+var sigma = this.sigma,
+ conrad = this.conrad;
+
+sigma.conrad = conrad;
+
+// Dirty polyfills to permit sigma usage in node
+if (HTMLElement === undefined)
+ var HTMLElement = function() {};
+
+if (window === undefined)
+ var window = {
+ addEventListener: function() {}
+ };
+
+if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = sigma;
+ exports.sigma = sigma;
+}
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ var _root = this;
+
+ // Initialize packages:
+ sigma.utils = sigma.utils || {};
+
+ /**
+ * MISC UTILS:
+ */
+ /**
+ * This function takes any number of objects as arguments, copies from each
+ * of these objects each pair key/value into a new object, and finally
+ * returns this object.
+ *
+ * The arguments are parsed from the last one to the first one, such that
+ * when several objects have keys in common, the "earliest" object wins.
+ *
+ * Example:
+ * ********
+ * > var o1 = {
+ * > a: 1,
+ * > b: 2,
+ * > c: '3'
+ * > },
+ * > o2 = {
+ * > c: '4',
+ * > d: [ 5 ]
+ * > };
+ * > sigma.utils.extend(o1, o2);
+ * > // Returns: {
+ * > // a: 1,
+ * > // b: 2,
+ * > // c: '3',
+ * > // d: [ 5 ]
+ * > // };
+ *
+ * @param {object+} Any number of objects.
+ * @return {object} The merged object.
+ */
+ sigma.utils.extend = function() {
+ var i,
+ k,
+ res = {},
+ l = arguments.length;
+
+ for (i = l - 1; i >= 0; i--)
+ for (k in arguments[i])
+ res[k] = arguments[i][k];
+
+ return res;
+ };
+
+ /**
+ * A short "Date.now()" polyfill.
+ *
+ * @return {Number} The current time (in ms).
+ */
+ sigma.utils.dateNow = function() {
+ return Date.now ? Date.now() : new Date().getTime();
+ };
+
+ /**
+ * Takes a package name as parameter and checks at each lebel if it exists,
+ * and if it does not, creates it.
+ *
+ * Example:
+ * ********
+ * > sigma.utils.pkg('a.b.c');
+ * > a.b.c;
+ * > // Object {};
+ * >
+ * > sigma.utils.pkg('a.b.d');
+ * > a.b;
+ * > // Object { c: {}, d: {} };
+ *
+ * @param {string} pkgName The name of the package to create/find.
+ * @return {object} The related package.
+ */
+ sigma.utils.pkg = function(pkgName) {
+ return (pkgName || '').split('.').reduce(function(context, objName) {
+ return (objName in context) ?
+ context[objName] :
+ (context[objName] = {});
+ }, _root);
+ };
+
+ /**
+ * Returns a unique incremental number ID.
+ *
+ * Example:
+ * ********
+ * > sigma.utils.id();
+ * > // 1;
+ * >
+ * > sigma.utils.id();
+ * > // 2;
+ * >
+ * > sigma.utils.id();
+ * > // 3;
+ *
+ * @param {string} pkgName The name of the package to create/find.
+ * @return {object} The related package.
+ */
+ sigma.utils.id = (function() {
+ var i = 0;
+ return function() {
+ return ++i;
+ };
+ })();
+
+ /**
+ * This function takes an hexa color (for instance "#ffcc00" or "#fc0") or a
+ * rgb / rgba color (like "rgb(255,255,12)" or "rgba(255,255,12,1)") and
+ * returns an integer equal to "r * 255 * 255 + g * 255 + b", to gain some
+ * memory in the data given to WebGL shaders.
+ *
+ * Note that the function actually caches its results for better performance.
+ *
+ * @param {string} val The hexa or rgba color.
+ * @return {number} The number value.
+ */
+ var floatColorCache = {};
+
+ sigma.utils.floatColor = function(val) {
+
+ // Is the color already computed?
+ if (floatColorCache[val])
+ return floatColorCache[val];
+
+ var original = val,
+ r = 0,
+ g = 0,
+ b = 0;
+
+ if (val[0] === '#') {
+ val = val.slice(1);
+
+ if (val.length === 3) {
+ r = parseInt(val.charAt(0) + val.charAt(0), 16);
+ g = parseInt(val.charAt(1) + val.charAt(1), 16);
+ b = parseInt(val.charAt(2) + val.charAt(2), 16);
+ }
+ else {
+ r = parseInt(val.charAt(0) + val.charAt(1), 16);
+ g = parseInt(val.charAt(2) + val.charAt(3), 16);
+ b = parseInt(val.charAt(4) + val.charAt(5), 16);
+ }
+ } else if (val.match(/^ *rgba? *\(/)) {
+ val = val.match(
+ /^ *rgba? *\( *([0-9]*) *, *([0-9]*) *, *([0-9]*) *(,.*)?\) *$/
+ );
+ r = +val[1];
+ g = +val[2];
+ b = +val[3];
+ }
+
+ var color = (
+ r * 256 * 256 +
+ g * 256 +
+ b
+ );
+
+ // Caching the color
+ floatColorCache[original] = color;
+
+ return color;
+ };
+
+ /**
+ * Perform a zoom into a camera, with or without animation, to the
+ * coordinates indicated using a specified ratio.
+ *
+ * Recognized parameters:
+ * **********************
+ * Here is the exhaustive list of every accepted parameters in the animation
+ * object:
+ *
+ * {?number} duration An amount of time that means the duration of the
+ * animation. If this parameter doesn't exist the
+ * zoom will be performed without animation.
+ * {?function} onComplete A function to perform it after the animation. It
+ * will be performed even if there is no duration.
+ *
+ * @param {camera} The camera where perform the zoom.
+ * @param {x} The X coordiantion where the zoom goes.
+ * @param {y} The Y coordiantion where the zoom goes.
+ * @param {ratio} The ratio to apply it to the current camera ratio.
+ * @param {?animation} A dictionary with options for a possible animation.
+ */
+ sigma.utils.zoomTo = function(camera, x, y, ratio, animation) {
+ var settings = camera.settings,
+ count,
+ newRatio,
+ animationSettings,
+ coordinates;
+
+ // Create the newRatio dealing with min / max:
+ newRatio = Math.max(
+ settings('zoomMin'),
+ Math.min(
+ settings('zoomMax'),
+ camera.ratio * ratio
+ )
+ );
+
+ // Check that the new ratio is different from the initial one:
+ if (newRatio !== camera.ratio) {
+ // Create the coordinates variable:
+ ratio = newRatio / camera.ratio;
+ coordinates = {
+ x: x * (1 - ratio) + camera.x,
+ y: y * (1 - ratio) + camera.y,
+ ratio: newRatio
+ };
+
+ if (animation && animation.duration) {
+ // Complete the animation setings:
+ count = sigma.misc.animation.killAll(camera);
+ animation = sigma.utils.extend(
+ animation,
+ {
+ easing: count ? 'quadraticOut' : 'quadraticInOut'
+ }
+ );
+
+ sigma.misc.animation.camera(camera, coordinates, animation);
+ } else {
+ camera.goTo(coordinates);
+ if (animation && animation.onComplete)
+ animation.onComplete();
+ }
+ }
+ };
+
+ /**
+ * Return the control point coordinates for a quadratic bezier curve.
+ *
+ * @param {number} x1 The X coordinate of the start point.
+ * @param {number} y1 The Y coordinate of the start point.
+ * @param {number} x2 The X coordinate of the end point.
+ * @param {number} y2 The Y coordinate of the end point.
+ * @return {x,y} The control point coordinates.
+ */
+ sigma.utils.getQuadraticControlPoint = function(x1, y1, x2, y2) {
+ return {
+ x: (x1 + x2) / 2 + (y2 - y1) / 4,
+ y: (y1 + y2) / 2 + (x1 - x2) / 4
+ };
+ };
+
+ /**
+ * Compute the coordinates of the point positioned
+ * at length t in the quadratic bezier curve.
+ *
+ * @param {number} t In [0,1] the step percentage to reach
+ * the point in the curve from the context point.
+ * @param {number} x1 The X coordinate of the context point.
+ * @param {number} y1 The Y coordinate of the context point.
+ * @param {number} x2 The X coordinate of the ending point.
+ * @param {number} y2 The Y coordinate of the ending point.
+ * @param {number} xi The X coordinate of the control point.
+ * @param {number} yi The Y coordinate of the control point.
+ * @return {object} {x,y}.
+ */
+ sigma.utils.getPointOnQuadraticCurve = function(t, x1, y1, x2, y2, xi, yi) {
+ // http://stackoverflow.com/a/5634528
+ return {
+ x: Math.pow(1 - t, 2) * x1 + 2 * (1 - t) * t * xi + Math.pow(t, 2) * x2,
+ y: Math.pow(1 - t, 2) * y1 + 2 * (1 - t) * t * yi + Math.pow(t, 2) * y2
+ };
+ };
+
+ /**
+ * Compute the coordinates of the point positioned
+ * at length t in the cubic bezier curve.
+ *
+ * @param {number} t In [0,1] the step percentage to reach
+ * the point in the curve from the context point.
+ * @param {number} x1 The X coordinate of the context point.
+ * @param {number} y1 The Y coordinate of the context point.
+ * @param {number} x2 The X coordinate of the end point.
+ * @param {number} y2 The Y coordinate of the end point.
+ * @param {number} cx The X coordinate of the first control point.
+ * @param {number} cy The Y coordinate of the first control point.
+ * @param {number} dx The X coordinate of the second control point.
+ * @param {number} dy The Y coordinate of the second control point.
+ * @return {object} {x,y} The point at t.
+ */
+ sigma.utils.getPointOnBezierCurve =
+ function(t, x1, y1, x2, y2, cx, cy, dx, dy) {
+ // http://stackoverflow.com/a/15397596
+ // Blending functions:
+ var B0_t = Math.pow(1 - t, 3),
+ B1_t = 3 * t * Math.pow(1 - t, 2),
+ B2_t = 3 * Math.pow(t, 2) * (1 - t),
+ B3_t = Math.pow(t, 3);
+
+ return {
+ x: (B0_t * x1) + (B1_t * cx) + (B2_t * dx) + (B3_t * x2),
+ y: (B0_t * y1) + (B1_t * cy) + (B2_t * dy) + (B3_t * y2)
+ };
+ };
+
+ /**
+ * Return the coordinates of the two control points for a self loop (i.e.
+ * where the start point is also the end point) computed as a cubic bezier
+ * curve.
+ *
+ * @param {number} x The X coordinate of the node.
+ * @param {number} y The Y coordinate of the node.
+ * @param {number} size The node size.
+ * @return {x1,y1,x2,y2} The coordinates of the two control points.
+ */
+ sigma.utils.getSelfLoopControlPoints = function(x , y, size) {
+ return {
+ x1: x - size * 7,
+ y1: y,
+ x2: x,
+ y2: y + size * 7
+ };
+ };
+
+ /**
+ * Return the euclidian distance between two points of a plane
+ * with an orthonormal basis.
+ *
+ * @param {number} x1 The X coordinate of the first point.
+ * @param {number} y1 The Y coordinate of the first point.
+ * @param {number} x2 The X coordinate of the second point.
+ * @param {number} y2 The Y coordinate of the second point.
+ * @return {number} The euclidian distance.
+ */
+ sigma.utils.getDistance = function(x0, y0, x1, y1) {
+ return Math.sqrt(Math.pow(x1 - x0, 2) + Math.pow(y1 - y0, 2));
+ };
+
+ /**
+ * Return the coordinates of the intersection points of two circles.
+ *
+ * @param {number} x0 The X coordinate of center location of the first
+ * circle.
+ * @param {number} y0 The Y coordinate of center location of the first
+ * circle.
+ * @param {number} r0 The radius of the first circle.
+ * @param {number} x1 The X coordinate of center location of the second
+ * circle.
+ * @param {number} y1 The Y coordinate of center location of the second
+ * circle.
+ * @param {number} r1 The radius of the second circle.
+ * @return {xi,yi} The coordinates of the intersection points.
+ */
+ sigma.utils.getCircleIntersection = function(x0, y0, r0, x1, y1, r1) {
+ // http://stackoverflow.com/a/12219802
+ var a, dx, dy, d, h, rx, ry, x2, y2;
+
+ // dx and dy are the vertical and horizontal distances between the circle
+ // centers:
+ dx = x1 - x0;
+ dy = y1 - y0;
+
+ // Determine the straight-line distance between the centers:
+ d = Math.sqrt((dy * dy) + (dx * dx));
+
+ // Check for solvability:
+ if (d > (r0 + r1)) {
+ // No solution. circles do not intersect.
+ return false;
+ }
+ if (d < Math.abs(r0 - r1)) {
+ // No solution. one circle is contained in the other.
+ return false;
+ }
+
+ //'point 2' is the point where the line through the circle intersection
+ // points crosses the line between the circle centers.
+
+ // Determine the distance from point 0 to point 2:
+ a = ((r0 * r0) - (r1 * r1) + (d * d)) / (2.0 * d);
+
+ // Determine the coordinates of point 2:
+ x2 = x0 + (dx * a / d);
+ y2 = y0 + (dy * a / d);
+
+ // Determine the distance from point 2 to either of the intersection
+ // points:
+ h = Math.sqrt((r0 * r0) - (a * a));
+
+ // Determine the offsets of the intersection points from point 2:
+ rx = -dy * (h / d);
+ ry = dx * (h / d);
+
+ // Determine the absolute intersection points:
+ var xi = x2 + rx;
+ var xi_prime = x2 - rx;
+ var yi = y2 + ry;
+ var yi_prime = y2 - ry;
+
+ return {xi: xi, xi_prime: xi_prime, yi: yi, yi_prime: yi_prime};
+ };
+
+ /**
+ * Check if a point is on a line segment.
+ *
+ * @param {number} x The X coordinate of the point to check.
+ * @param {number} y The Y coordinate of the point to check.
+ * @param {number} x1 The X coordinate of the line start point.
+ * @param {number} y1 The Y coordinate of the line start point.
+ * @param {number} x2 The X coordinate of the line end point.
+ * @param {number} y2 The Y coordinate of the line end point.
+ * @param {number} epsilon The precision (consider the line thickness).
+ * @return {boolean} True if point is "close to" the line
+ * segment, false otherwise.
+ */
+ sigma.utils.isPointOnSegment = function(x, y, x1, y1, x2, y2, epsilon) {
+ // http://stackoverflow.com/a/328122
+ var crossProduct = Math.abs((y - y1) * (x2 - x1) - (x - x1) * (y2 - y1)),
+ d = sigma.utils.getDistance(x1, y1, x2, y2),
+ nCrossProduct = crossProduct / d; // normalized cross product
+
+ return (nCrossProduct < epsilon &&
+ Math.min(x1, x2) <= x && x <= Math.max(x1, x2) &&
+ Math.min(y1, y2) <= y && y <= Math.max(y1, y2));
+ };
+
+ /**
+ * Check if a point is on a quadratic bezier curve segment with a thickness.
+ *
+ * @param {number} x The X coordinate of the point to check.
+ * @param {number} y The Y coordinate of the point to check.
+ * @param {number} x1 The X coordinate of the curve start point.
+ * @param {number} y1 The Y coordinate of the curve start point.
+ * @param {number} x2 The X coordinate of the curve end point.
+ * @param {number} y2 The Y coordinate of the curve end point.
+ * @param {number} cpx The X coordinate of the curve control point.
+ * @param {number} cpy The Y coordinate of the curve control point.
+ * @param {number} epsilon The precision (consider the line thickness).
+ * @return {boolean} True if (x,y) is on the curve segment,
+ * false otherwise.
+ */
+ sigma.utils.isPointOnQuadraticCurve =
+ function(x, y, x1, y1, x2, y2, cpx, cpy, epsilon) {
+ // Fails if the point is too far from the extremities of the segment,
+ // preventing for more costly computation:
+ var dP1P2 = sigma.utils.getDistance(x1, y1, x2, y2);
+ if (Math.abs(x - x1) > dP1P2 || Math.abs(y - y1) > dP1P2) {
+ return false;
+ }
+
+ var dP1 = sigma.utils.getDistance(x, y, x1, y1),
+ dP2 = sigma.utils.getDistance(x, y, x2, y2),
+ t = 0.5,
+ r = (dP1 < dP2) ? -0.01 : 0.01,
+ rThreshold = 0.001,
+ i = 100,
+ pt = sigma.utils.getPointOnQuadraticCurve(t, x1, y1, x2, y2, cpx, cpy),
+ dt = sigma.utils.getDistance(x, y, pt.x, pt.y),
+ old_dt;
+
+ // This algorithm minimizes the distance from the point to the curve. It
+ // find the optimal t value where t=0 is the start point and t=1 is the end
+ // point of the curve, starting from t=0.5.
+ // It terminates because it runs a maximum of i interations.
+ while (i-- > 0 &&
+ t >= 0 && t <= 1 &&
+ (dt > epsilon) &&
+ (r > rThreshold || r < -rThreshold)) {
+ old_dt = dt;
+ pt = sigma.utils.getPointOnQuadraticCurve(t, x1, y1, x2, y2, cpx, cpy);
+ dt = sigma.utils.getDistance(x, y, pt.x, pt.y);
+
+ if (dt > old_dt) {
+ // not the right direction:
+ // halfstep in the opposite direction
+ r = -r / 2;
+ t += r;
+ }
+ else if (t + r < 0 || t + r > 1) {
+ // oops, we've gone too far:
+ // revert with a halfstep
+ r = r / 2;
+ dt = old_dt;
+ }
+ else {
+ // progress:
+ t += r;
+ }
+ }
+
+ return dt < epsilon;
+ };
+
+
+ /**
+ * Check if a point is on a cubic bezier curve segment with a thickness.
+ *
+ * @param {number} x The X coordinate of the point to check.
+ * @param {number} y The Y coordinate of the point to check.
+ * @param {number} x1 The X coordinate of the curve start point.
+ * @param {number} y1 The Y coordinate of the curve start point.
+ * @param {number} x2 The X coordinate of the curve end point.
+ * @param {number} y2 The Y coordinate of the curve end point.
+ * @param {number} cpx1 The X coordinate of the 1st curve control point.
+ * @param {number} cpy1 The Y coordinate of the 1st curve control point.
+ * @param {number} cpx2 The X coordinate of the 2nd curve control point.
+ * @param {number} cpy2 The Y coordinate of the 2nd curve control point.
+ * @param {number} epsilon The precision (consider the line thickness).
+ * @return {boolean} True if (x,y) is on the curve segment,
+ * false otherwise.
+ */
+ sigma.utils.isPointOnBezierCurve =
+ function(x, y, x1, y1, x2, y2, cpx1, cpy1, cpx2, cpy2, epsilon) {
+ // Fails if the point is too far from the extremities of the segment,
+ // preventing for more costly computation:
+ var dP1CP1 = sigma.utils.getDistance(x1, y1, cpx1, cpy1);
+ if (Math.abs(x - x1) > dP1CP1 || Math.abs(y - y1) > dP1CP1) {
+ return false;
+ }
+
+ var dP1 = sigma.utils.getDistance(x, y, x1, y1),
+ dP2 = sigma.utils.getDistance(x, y, x2, y2),
+ t = 0.5,
+ r = (dP1 < dP2) ? -0.01 : 0.01,
+ rThreshold = 0.001,
+ i = 100,
+ pt = sigma.utils.getPointOnBezierCurve(
+ t, x1, y1, x2, y2, cpx1, cpy1, cpx2, cpy2),
+ dt = sigma.utils.getDistance(x, y, pt.x, pt.y),
+ old_dt;
+
+ // This algorithm minimizes the distance from the point to the curve. It
+ // find the optimal t value where t=0 is the start point and t=1 is the end
+ // point of the curve, starting from t=0.5.
+ // It terminates because it runs a maximum of i interations.
+ while (i-- > 0 &&
+ t >= 0 && t <= 1 &&
+ (dt > epsilon) &&
+ (r > rThreshold || r < -rThreshold)) {
+ old_dt = dt;
+ pt = sigma.utils.getPointOnBezierCurve(
+ t, x1, y1, x2, y2, cpx1, cpy1, cpx2, cpy2);
+ dt = sigma.utils.getDistance(x, y, pt.x, pt.y);
+
+ if (dt > old_dt) {
+ // not the right direction:
+ // halfstep in the opposite direction
+ r = -r / 2;
+ t += r;
+ }
+ else if (t + r < 0 || t + r > 1) {
+ // oops, we've gone too far:
+ // revert with a halfstep
+ r = r / 2;
+ dt = old_dt;
+ }
+ else {
+ // progress:
+ t += r;
+ }
+ }
+
+ return dt < epsilon;
+ };
+
+
+ /**
+ * ************
+ * EVENTS UTILS:
+ * ************
+ */
+ /**
+ * Here are some useful functions to unify extraction of the information we
+ * need with mouse events and touch events, from different browsers:
+ */
+
+ /**
+ * Extract the local X position from a mouse or touch event.
+ *
+ * @param {event} e A mouse or touch event.
+ * @return {number} The local X value of the mouse.
+ */
+ sigma.utils.getX = function(e) {
+ return (
+ (e.offsetX !== undefined && e.offsetX) ||
+ (e.layerX !== undefined && e.layerX) ||
+ (e.clientX !== undefined && e.clientX)
+ );
+ };
+
+ /**
+ * Extract the local Y position from a mouse or touch event.
+ *
+ * @param {event} e A mouse or touch event.
+ * @return {number} The local Y value of the mouse.
+ */
+ sigma.utils.getY = function(e) {
+ return (
+ (e.offsetY !== undefined && e.offsetY) ||
+ (e.layerY !== undefined && e.layerY) ||
+ (e.clientY !== undefined && e.clientY)
+ );
+ };
+
+ /**
+ * The pixel ratio of the screen. Taking zoom into account
+ *
+ * @return {number} Pixel ratio of the screen
+ */
+ sigma.utils.getPixelRatio = function() {
+ var ratio = 1;
+ if (window.screen.deviceXDPI !== undefined &&
+ window.screen.logicalXDPI !== undefined &&
+ window.screen.deviceXDPI > window.screen.logicalXDPI) {
+ ratio = window.screen.systemXDPI / window.screen.logicalXDPI;
+ }
+ else if (window.devicePixelRatio !== undefined) {
+ ratio = window.devicePixelRatio;
+ }
+ return ratio;
+ };
+
+ /**
+ * Extract the width from a mouse or touch event.
+ *
+ * @param {event} e A mouse or touch event.
+ * @return {number} The width of the event's target.
+ */
+ sigma.utils.getWidth = function(e) {
+ var w = (!e.target.ownerSVGElement) ?
+ e.target.width :
+ e.target.ownerSVGElement.width;
+
+ return (
+ (typeof w === 'number' && w) ||
+ (w !== undefined && w.baseVal !== undefined && w.baseVal.value)
+ );
+ };
+
+ /**
+ * Extract the center from a mouse or touch event.
+ *
+ * @param {event} e A mouse or touch event.
+ * @return {object} The center of the event's target.
+ */
+ sigma.utils.getCenter = function(e) {
+ var ratio = e.target.namespaceURI.indexOf('svg') !== -1 ? 1 :
+ sigma.utils.getPixelRatio();
+ return {
+ x: sigma.utils.getWidth(e) / (2 * ratio),
+ y: sigma.utils.getHeight(e) / (2 * ratio),
+ };
+ };
+
+ /**
+ * Convert mouse coords to sigma coords
+ *
+ * @param {event} e A mouse or touch event.
+ * @param {number?} x The x coord to convert
+ * @param {number?} x The y coord to convert
+ *
+ * @return {object} The standardized event
+ */
+ sigma.utils.mouseCoords = function(e, x, y) {
+ x = x || sigma.utils.getX(e);
+ y = y || sigma.utils.getY(e);
+ return {
+ x: x - sigma.utils.getCenter(e).x,
+ y: y - sigma.utils.getCenter(e).y,
+ clientX: e.clientX,
+ clientY: e.clientY,
+ ctrlKey: e.ctrlKey,
+ metaKey: e.metaKey,
+ altKey: e.altKey,
+ shiftKey: e.shiftKey
+ };
+ };
+
+ /**
+ * Extract the height from a mouse or touch event.
+ *
+ * @param {event} e A mouse or touch event.
+ * @return {number} The height of the event's target.
+ */
+ sigma.utils.getHeight = function(e) {
+ var h = (!e.target.ownerSVGElement) ?
+ e.target.height :
+ e.target.ownerSVGElement.height;
+
+ return (
+ (typeof h === 'number' && h) ||
+ (h !== undefined && h.baseVal !== undefined && h.baseVal.value)
+ );
+ };
+
+ /**
+ * Extract the wheel delta from a mouse or touch event.
+ *
+ * @param {event} e A mouse or touch event.
+ * @return {number} The wheel delta of the mouse.
+ */
+ sigma.utils.getDelta = function(e) {
+ return (
+ (e.wheelDelta !== undefined && e.wheelDelta) ||
+ (e.detail !== undefined && -e.detail)
+ );
+ };
+
+ /**
+ * Returns the offset of a DOM element.
+ *
+ * @param {DOMElement} dom The element to retrieve the position.
+ * @return {object} The offset of the DOM element (top, left).
+ */
+ sigma.utils.getOffset = function(dom) {
+ var left = 0,
+ top = 0;
+
+ while (dom) {
+ top = top + parseInt(dom.offsetTop);
+ left = left + parseInt(dom.offsetLeft);
+ dom = dom.offsetParent;
+ }
+
+ return {
+ top: top,
+ left: left
+ };
+ };
+
+ /**
+ * Simulates a "double click" event.
+ *
+ * @param {HTMLElement} target The event target.
+ * @param {string} type The event type.
+ * @param {function} callback The callback to execute.
+ */
+ sigma.utils.doubleClick = function(target, type, callback) {
+ var clicks = 0,
+ self = this,
+ handlers;
+
+ target._doubleClickHandler = target._doubleClickHandler || {};
+ target._doubleClickHandler[type] = target._doubleClickHandler[type] || [];
+ handlers = target._doubleClickHandler[type];
+
+ handlers.push(function(e) {
+ clicks++;
+
+ if (clicks === 2) {
+ clicks = 0;
+ return callback(e);
+ } else if (clicks === 1) {
+ setTimeout(function() {
+ clicks = 0;
+ }, sigma.settings.doubleClickTimeout);
+ }
+ });
+
+ target.addEventListener(type, handlers[handlers.length - 1], false);
+ };
+
+ /**
+ * Unbind simulated "double click" events.
+ *
+ * @param {HTMLElement} target The event target.
+ * @param {string} type The event type.
+ */
+ sigma.utils.unbindDoubleClick = function(target, type) {
+ var handler,
+ handlers = (target._doubleClickHandler || {})[type] || [];
+
+ while ((handler = handlers.pop())) {
+ target.removeEventListener(type, handler);
+ }
+
+ delete (target._doubleClickHandler || {})[type];
+ };
+
+
+
+
+ /**
+ * Here are just some of the most basic easing functions, used for the
+ * animated camera "goTo" calls.
+ *
+ * If you need some more easings functions, don't hesitate to add them to
+ * sigma.utils.easings. But I will not add some more here or merge PRs
+ * containing, because I do not want sigma sources full of overkill and never
+ * used stuff...
+ */
+ sigma.utils.easings = sigma.utils.easings || {};
+ sigma.utils.easings.linearNone = function(k) {
+ return k;
+ };
+ sigma.utils.easings.quadraticIn = function(k) {
+ return k * k;
+ };
+ sigma.utils.easings.quadraticOut = function(k) {
+ return k * (2 - k);
+ };
+ sigma.utils.easings.quadraticInOut = function(k) {
+ if ((k *= 2) < 1)
+ return 0.5 * k * k;
+ return - 0.5 * (--k * (k - 2) - 1);
+ };
+ sigma.utils.easings.cubicIn = function(k) {
+ return k * k * k;
+ };
+ sigma.utils.easings.cubicOut = function(k) {
+ return --k * k * k + 1;
+ };
+ sigma.utils.easings.cubicInOut = function(k) {
+ if ((k *= 2) < 1)
+ return 0.5 * k * k * k;
+ return 0.5 * ((k -= 2) * k * k + 2);
+ };
+
+
+
+
+ /**
+ * ************
+ * WEBGL UTILS:
+ * ************
+ */
+ /**
+ * Loads a WebGL shader and returns it.
+ *
+ * @param {WebGLContext} gl The WebGLContext to use.
+ * @param {string} shaderSource The shader source.
+ * @param {number} shaderType The type of shader.
+ * @param {function(string): void} error Callback for errors.
+ * @return {WebGLShader} The created shader.
+ */
+ sigma.utils.loadShader = function(gl, shaderSource, shaderType, error) {
+ var compiled,
+ shader = gl.createShader(shaderType);
+
+ // Load the shader source
+ gl.shaderSource(shader, shaderSource);
+
+ // Compile the shader
+ gl.compileShader(shader);
+
+ // Check the compile status
+ compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
+
+ // If something went wrong:
+ if (!compiled) {
+ if (error) {
+ error(
+ 'Error compiling shader "' + shader + '":' +
+ gl.getShaderInfoLog(shader)
+ );
+ }
+
+ gl.deleteShader(shader);
+ return null;
+ }
+
+ return shader;
+ };
+
+ /**
+ * Creates a program, attaches shaders, binds attrib locations, links the
+ * program and calls useProgram.
+ *
+ * @param {Array.<WebGLShader>} shaders The shaders to attach.
+ * @param {Array.<string>} attribs The attribs names.
+ * @param {Array.<number>} locations The locations for the attribs.
+ * @param {function(string): void} error Callback for errors.
+ * @return {WebGLProgram} The created program.
+ */
+ sigma.utils.loadProgram = function(gl, shaders, attribs, loc, error) {
+ var i,
+ linked,
+ program = gl.createProgram();
+
+ for (i = 0; i < shaders.length; ++i)
+ gl.attachShader(program, shaders[i]);
+
+ if (attribs)
+ for (i = 0; i < attribs.length; ++i)
+ gl.bindAttribLocation(
+ program,
+ locations ? locations[i] : i,
+ opt_attribs[i]
+ );
+
+ gl.linkProgram(program);
+
+ // Check the link status
+ linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+ if (!linked) {
+ if (error)
+ error('Error in program linking: ' + gl.getProgramInfoLog(program));
+
+ gl.deleteProgram(program);
+ return null;
+ }
+
+ return program;
+ };
+
+
+
+
+ /**
+ * *********
+ * MATRICES:
+ * *********
+ * The following utils are just here to help generating the transformation
+ * matrices for the WebGL renderers.
+ */
+ sigma.utils.pkg('sigma.utils.matrices');
+
+ /**
+ * The returns a 3x3 translation matrix.
+ *
+ * @param {number} dx The X translation.
+ * @param {number} dy The Y translation.
+ * @return {array} Returns the matrix.
+ */
+ sigma.utils.matrices.translation = function(dx, dy) {
+ return [
+ 1, 0, 0,
+ 0, 1, 0,
+ dx, dy, 1
+ ];
+ };
+
+ /**
+ * The returns a 3x3 or 2x2 rotation matrix.
+ *
+ * @param {number} angle The rotation angle.
+ * @param {boolean} m2 If true, the function will return a 2x2 matrix.
+ * @return {array} Returns the matrix.
+ */
+ sigma.utils.matrices.rotation = function(angle, m2) {
+ var cos = Math.cos(angle),
+ sin = Math.sin(angle);
+
+ return m2 ? [
+ cos, -sin,
+ sin, cos
+ ] : [
+ cos, -sin, 0,
+ sin, cos, 0,
+ 0, 0, 1
+ ];
+ };
+
+ /**
+ * The returns a 3x3 or 2x2 homothetic transformation matrix.
+ *
+ * @param {number} ratio The scaling ratio.
+ * @param {boolean} m2 If true, the function will return a 2x2 matrix.
+ * @return {array} Returns the matrix.
+ */
+ sigma.utils.matrices.scale = function(ratio, m2) {
+ return m2 ? [
+ ratio, 0,
+ 0, ratio
+ ] : [
+ ratio, 0, 0,
+ 0, ratio, 0,
+ 0, 0, 1
+ ];
+ };
+
+ /**
+ * The returns a 3x3 or 2x2 homothetic transformation matrix.
+ *
+ * @param {array} a The first matrix.
+ * @param {array} b The second matrix.
+ * @param {boolean} m2 If true, the function will assume both matrices are
+ * 2x2.
+ * @return {array} Returns the matrix.
+ */
+ sigma.utils.matrices.multiply = function(a, b, m2) {
+ var l = m2 ? 2 : 3,
+ a00 = a[0 * l + 0],
+ a01 = a[0 * l + 1],
+ a02 = a[0 * l + 2],
+ a10 = a[1 * l + 0],
+ a11 = a[1 * l + 1],
+ a12 = a[1 * l + 2],
+ a20 = a[2 * l + 0],
+ a21 = a[2 * l + 1],
+ a22 = a[2 * l + 2],
+ b00 = b[0 * l + 0],
+ b01 = b[0 * l + 1],
+ b02 = b[0 * l + 2],
+ b10 = b[1 * l + 0],
+ b11 = b[1 * l + 1],
+ b12 = b[1 * l + 2],
+ b20 = b[2 * l + 0],
+ b21 = b[2 * l + 1],
+ b22 = b[2 * l + 2];
+
+ return m2 ? [
+ a00 * b00 + a01 * b10,
+ a00 * b01 + a01 * b11,
+ a10 * b00 + a11 * b10,
+ a10 * b01 + a11 * b11
+ ] : [
+ a00 * b00 + a01 * b10 + a02 * b20,
+ a00 * b01 + a01 * b11 + a02 * b21,
+ a00 * b02 + a01 * b12 + a02 * b22,
+ a10 * b00 + a11 * b10 + a12 * b20,
+ a10 * b01 + a11 * b11 + a12 * b21,
+ a10 * b02 + a11 * b12 + a12 * b22,
+ a20 * b00 + a21 * b10 + a22 * b20,
+ a20 * b01 + a21 * b11 + a22 * b21,
+ a20 * b02 + a21 * b12 + a22 * b22
+ ];
+ };
+}).call(this);
+
+;(function(global) {
+ 'use strict';
+
+ /**
+ * http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+ * http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
+ * requestAnimationFrame polyfill by Erik Möller.
+ * fixes from Paul Irish and Tino Zijdel
+ * MIT license
+ */
+ var x,
+ lastTime = 0,
+ vendors = ['ms', 'moz', 'webkit', 'o'];
+
+ for (x = 0; x < vendors.length && !global.requestAnimationFrame; x++) {
+ global.requestAnimationFrame =
+ global[vendors[x] + 'RequestAnimationFrame'];
+ global.cancelAnimationFrame =
+ global[vendors[x] + 'CancelAnimationFrame'] ||
+ global[vendors[x] + 'CancelRequestAnimationFrame'];
+ }
+
+ if (!global.requestAnimationFrame)
+ global.requestAnimationFrame = function(callback, element) {
+ var currTime = new Date().getTime(),
+ timeToCall = Math.max(0, 16 - (currTime - lastTime)),
+ id = global.setTimeout(
+ function() {
+ callback(currTime + timeToCall);
+ },
+ timeToCall
+ );
+
+ lastTime = currTime + timeToCall;
+ return id;
+ };
+
+ if (!global.cancelAnimationFrame)
+ global.cancelAnimationFrame = function(id) {
+ clearTimeout(id);
+ };
+
+ /**
+ * Function.prototype.bind polyfill found on MDN.
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility
+ * Public domain
+ */
+ if (!Function.prototype.bind)
+ Function.prototype.bind = function(oThis) {
+ if (typeof this !== 'function')
+ // Closest thing possible to the ECMAScript 5 internal IsCallable
+ // function:
+ throw new TypeError(
+ 'Function.prototype.bind - what is trying to be bound is not callable'
+ );
+
+ var aArgs = Array.prototype.slice.call(arguments, 1),
+ fToBind = this,
+ fNOP,
+ fBound;
+
+ fNOP = function() {};
+ fBound = function() {
+ return fToBind.apply(
+ this instanceof fNOP && oThis ?
+ this :
+ oThis,
+ aArgs.concat(Array.prototype.slice.call(arguments))
+ );
+ };
+
+ fNOP.prototype = this.prototype;
+ fBound.prototype = new fNOP();
+
+ return fBound;
+ };
+})(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Packages initialization:
+ sigma.utils.pkg('sigma.settings');
+
+ var settings = {
+ /**
+ * GRAPH SETTINGS:
+ * ***************
+ */
+ // {boolean} Indicates if the data have to be cloned in methods to add
+ // nodes or edges.
+ clone: true,
+ // {boolean} Indicates if nodes "id" values and edges "id", "source" and
+ // "target" values must be set as immutable.
+ immutable: true,
+ // {boolean} Indicates if sigma can log its errors and warnings.
+ verbose: false,
+
+
+ /**
+ * RENDERERS SETTINGS:
+ * *******************
+ */
+ // {string}
+ classPrefix: 'sigma',
+ // {string}
+ defaultNodeType: 'def',
+ // {string}
+ defaultEdgeType: 'def',
+ // {string}
+ defaultLabelColor: '#000',
+ // {string}
+ defaultEdgeColor: '#000',
+ // {string}
+ defaultNodeColor: '#000',
+ // {string}
+ defaultLabelSize: 14,
+ // {string} Indicates how to choose the edges color. Available values:
+ // "source", "target", "default"
+ edgeColor: 'source',
+ // {number} Defines the minimal edge's arrow display size.
+ minArrowSize: 0,
+ // {string}
+ font: 'arial',
+ // {string} Example: 'bold'
+ fontStyle: '',
+ // {string} Indicates how to choose the labels color. Available values:
+ // "node", "default"
+ labelColor: 'default',
+ // {string} Indicates how to choose the labels size. Available values:
+ // "fixed", "proportional"
+ labelSize: 'fixed',
+ // {string} The ratio between the font size of the label and the node size.
+ labelSizeRatio: 1,
+ // {number} The minimum size a node must have to see its label displayed.
+ labelThreshold: 8,
+ // {number} The oversampling factor used in WebGL renderer.
+ webglOversamplingRatio: 2,
+ // {number} The size of the border of hovered nodes.
+ borderSize: 0,
+ // {number} The default hovered node border's color.
+ defaultNodeBorderColor: '#000',
+ // {number} The hovered node's label font. If not specified, will heritate
+ // the "font" value.
+ hoverFont: '',
+ // {boolean} If true, then only one node can be hovered at a time.
+ singleHover: true,
+ // {string} Example: 'bold'
+ hoverFontStyle: '',
+ // {string} Indicates how to choose the hovered nodes shadow color.
+ // Available values: "node", "default"
+ labelHoverShadow: 'default',
+ // {string}
+ labelHoverShadowColor: '#000',
+ // {string} Indicates how to choose the hovered nodes color.
+ // Available values: "node", "default"
+ nodeHoverColor: 'node',
+ // {string}
+ defaultNodeHoverColor: '#000',
+ // {string} Indicates how to choose the hovered nodes background color.
+ // Available values: "node", "default"
+ labelHoverBGColor: 'default',
+ // {string}
+ defaultHoverLabelBGColor: '#fff',
+ // {string} Indicates how to choose the hovered labels color.
+ // Available values: "node", "default"
+ labelHoverColor: 'default',
+ // {string}
+ defaultLabelHoverColor: '#000',
+ // {string} Indicates how to choose the edges hover color. Available values:
+ // "edge", "default"
+ edgeHoverColor: 'edge',
+ // {number} The size multiplicator of hovered edges.
+ edgeHoverSizeRatio: 1,
+ // {string}
+ defaultEdgeHoverColor: '#000',
+ // {boolean} Indicates if the edge extremities must be hovered when the
+ // edge is hovered.
+ edgeHoverExtremities: false,
+ // {booleans} The different drawing modes:
+ // false: Layered not displayed.
+ // true: Layered displayed.
+ drawEdges: true,
+ drawNodes: true,
+ drawLabels: true,
+ drawEdgeLabels: false,
+ // {boolean} Indicates if the edges must be drawn in several frames or in
+ // one frame, as the nodes and labels are drawn.
+ batchEdgesDrawing: false,
+ // {boolean} Indicates if the edges must be hidden during dragging and
+ // animations.
+ hideEdgesOnMove: false,
+ // {numbers} The different batch sizes, when elements are displayed in
+ // several frames.
+ canvasEdgesBatchSize: 500,
+ webglEdgesBatchSize: 1000,
+
+
+
+
+ /**
+ * RESCALE SETTINGS:
+ * *****************
+ */
+ // {string} Indicates of to scale the graph relatively to its container.
+ // Available values: "inside", "outside"
+ scalingMode: 'inside',
+ // {number} The margin to keep around the graph.
+ sideMargin: 0,
+ // {number} Determine the size of the smallest and the biggest node / edges
+ // on the screen. This mapping makes easier to display the graph,
+ // avoiding too big nodes that take half of the screen, or too
+ // small ones that are not readable. If the two parameters are
+ // equals, then the minimal display size will be 0. And if they
+ // are both equal to 0, then there is no mapping, and the radius
+ // of the nodes will be their size.
+ minEdgeSize: 0.5,
+ maxEdgeSize: 1,
+ minNodeSize: 1,
+ maxNodeSize: 8,
+
+
+
+
+ /**
+ * CAPTORS SETTINGS:
+ * *****************
+ */
+ // {boolean}
+ touchEnabled: true,
+ // {boolean}
+ mouseEnabled: true,
+ // {boolean}
+ mouseWheelEnabled: true,
+ // {boolean}
+ doubleClickEnabled: true,
+ // {boolean} Defines whether the custom events such as "clickNode" can be
+ // used.
+ eventsEnabled: true,
+ // {number} Defines by how much multiplicating the zooming level when the
+ // user zooms with the mouse-wheel.
+ zoomingRatio: 1.7,
+ // {number} Defines by how much multiplicating the zooming level when the
+ // user zooms by double clicking.
+ doubleClickZoomingRatio: 2.2,
+ // {number} The minimum zooming level.
+ zoomMin: 0.0625,
+ // {number} The maximum zooming level.
+ zoomMax: 2,
+ // {number} The duration of animations following a mouse scrolling.
+ mouseZoomDuration: 200,
+ // {number} The duration of animations following a mouse double click.
+ doubleClickZoomDuration: 200,
+ // {number} The duration of animations following a mouse dropping.
+ mouseInertiaDuration: 200,
+ // {number} The inertia power (mouse captor).
+ mouseInertiaRatio: 3,
+ // {number} The duration of animations following a touch dropping.
+ touchInertiaDuration: 200,
+ // {number} The inertia power (touch captor).
+ touchInertiaRatio: 3,
+ // {number} The maximum time between two clicks to make it a double click.
+ doubleClickTimeout: 300,
+ // {number} The maximum time between two taps to make it a double tap.
+ doubleTapTimeout: 300,
+ // {number} The maximum time of dragging to trigger intertia.
+ dragTimeout: 200,
+
+
+
+
+ /**
+ * GLOBAL SETTINGS:
+ * ****************
+ */
+ // {boolean} Determines whether the instance has to refresh itself
+ // automatically when a "resize" event is dispatched from the
+ // window object.
+ autoResize: true,
+ // {boolean} Determines whether the "rescale" middleware has to be called
+ // automatically for each camera on refresh.
+ autoRescale: true,
+ // {boolean} If set to false, the camera method "goTo" will basically do
+ // nothing.
+ enableCamera: true,
+ // {boolean} If set to false, the nodes cannot be hovered.
+ enableHovering: true,
+ // {boolean} If set to true, the edges can be hovered.
+ enableEdgeHovering: false,
+ // {number} The size of the area around the edges to activate hovering.
+ edgeHoverPrecision: 5,
+ // {boolean} If set to true, the rescale middleware will ignore node sizes
+ // to determine the graphs boundings.
+ rescaleIgnoreSize: false,
+ // {boolean} Determines if the core has to try to catch errors on
+ // rendering.
+ skipErrors: false,
+
+
+
+
+ /**
+ * CAMERA SETTINGS:
+ * ****************
+ */
+ // {number} The power degrees applied to the nodes/edges size relatively to
+ // the zooming level. Basically:
+ // > onScreenR = Math.pow(zoom, nodesPowRatio) * R
+ // > onScreenT = Math.pow(zoom, edgesPowRatio) * T
+ nodesPowRatio: 0.5,
+ edgesPowRatio: 0.5,
+
+
+
+
+ /**
+ * ANIMATIONS SETTINGS:
+ * ********************
+ */
+ // {number} The default animation time.
+ animationsTime: 200
+ };
+
+ // Export the previously designed settings:
+ sigma.settings = sigma.utils.extend(sigma.settings || {}, settings);
+}).call(this);
+
+;(function() {
+ 'use strict';
+
+ /**
+ * Dispatcher constructor.
+ *
+ * @return {dispatcher} The new dispatcher instance.
+ */
+ var dispatcher = function() {
+ Object.defineProperty(this, '_handlers', {
+ value: {}
+ });
+ };
+
+
+
+
+ /**
+ * Will execute the handler everytime that the indicated event (or the
+ * indicated events) will be triggered.
+ *
+ * @param {string} events The name of the event (or the events
+ * separated by spaces).
+ * @param {function(Object)} handler The handler to bind.
+ * @return {dispatcher} Returns the instance itself.
+ */
+ dispatcher.prototype.bind = function(events, handler) {
+ var i,
+ l,
+ event,
+ eArray;
+
+ if (
+ arguments.length === 1 &&
+ typeof arguments[0] === 'object'
+ )
+ for (events in arguments[0])
+ this.bind(events, arguments[0][events]);
+ else if (
+ arguments.length === 2 &&
+ typeof arguments[1] === 'function'
+ ) {
+ eArray = typeof events === 'string' ? events.split(' ') : events;
+
+ for (i = 0, l = eArray.length; i !== l; i += 1) {
+ event = eArray[i];
+
+ // Check that event is not '':
+ if (!event)
+ continue;
+
+ if (!this._handlers[event])
+ this._handlers[event] = [];
+
+ // Using an object instead of directly the handler will make possible
+ // later to add flags
+ this._handlers[event].push({
+ handler: handler
+ });
+ }
+ } else
+ throw 'bind: Wrong arguments.';
+
+ return this;
+ };
+
+ /**
+ * Removes the handler from a specified event (or specified events).
+ *
+ * @param {?string} events The name of the event (or the events
+ * separated by spaces). If undefined,
+ * then all handlers are removed.
+ * @param {?function(object)} handler The handler to unbind. If undefined,
+ * each handler bound to the event or the
+ * events will be removed.
+ * @return {dispatcher} Returns the instance itself.
+ */
+ dispatcher.prototype.unbind = function(events, handler) {
+ var i,
+ n,
+ j,
+ m,
+ k,
+ a,
+ event,
+ eArray = typeof events === 'string' ? events.split(' ') : events;
+
+ if (!arguments.length) {
+ for (k in this._handlers)
+ delete this._handlers[k];
+ return this;
+ }
+
+ if (handler) {
+ for (i = 0, n = eArray.length; i !== n; i += 1) {
+ event = eArray[i];
+ if (this._handlers[event]) {
+ a = [];
+ for (j = 0, m = this._handlers[event].length; j !== m; j += 1)
+ if (this._handlers[event][j].handler !== handler)
+ a.push(this._handlers[event][j]);
+
+ this._handlers[event] = a;
+ }
+
+ if (this._handlers[event] && this._handlers[event].length === 0)
+ delete this._handlers[event];
+ }
+ } else
+ for (i = 0, n = eArray.length; i !== n; i += 1)
+ delete this._handlers[eArray[i]];
+
+ return this;
+ };
+
+ /**
+ * Executes each handler bound to the event
+ *
+ * @param {string} events The name of the event (or the events separated
+ * by spaces).
+ * @param {?object} data The content of the event (optional).
+ * @return {dispatcher} Returns the instance itself.
+ */
+ dispatcher.prototype.dispatchEvent = function(events, data) {
+ var i,
+ n,
+ j,
+ m,
+ a,
+ event,
+ eventName,
+ self = this,
+ eArray = typeof events === 'string' ? events.split(' ') : events;
+
+ data = data === undefined ? {} : data;
+
+ for (i = 0, n = eArray.length; i !== n; i += 1) {
+ eventName = eArray[i];
+
+ if (this._handlers[eventName]) {
+ event = self.getEvent(eventName, data);
+ a = [];
+
+ for (j = 0, m = this._handlers[eventName].length; j !== m; j += 1) {
+ this._handlers[eventName][j].handler(event);
+ if (!this._handlers[eventName][j].one)
+ a.push(this._handlers[eventName][j]);
+ }
+
+ this._handlers[eventName] = a;
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Return an event object.
+ *
+ * @param {string} events The name of the event.
+ * @param {?object} data The content of the event (optional).
+ * @return {object} Returns the instance itself.
+ */
+ dispatcher.prototype.getEvent = function(event, data) {
+ return {
+ type: event,
+ data: data || {},
+ target: this
+ };
+ };
+
+ /**
+ * A useful function to deal with inheritance. It will make the target
+ * inherit the prototype of the class dispatcher as well as its constructor.
+ *
+ * @param {object} target The target.
+ */
+ dispatcher.extend = function(target, args) {
+ var k;
+
+ for (k in dispatcher.prototype)
+ if (dispatcher.prototype.hasOwnProperty(k))
+ target[k] = dispatcher.prototype[k];
+
+ dispatcher.apply(target, args);
+ };
+
+
+
+
+ /**
+ * EXPORT:
+ * *******
+ */
+ if (typeof this.sigma !== 'undefined') {
+ this.sigma.classes = this.sigma.classes || {};
+ this.sigma.classes.dispatcher = dispatcher;
+ } else if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = dispatcher;
+ exports.dispatcher = dispatcher;
+ } else
+ this.dispatcher = dispatcher;
+}).call(this);
+
+;(function() {
+ 'use strict';
+
+ /**
+ * This utils aims to facilitate the manipulation of each instance setting.
+ * Using a function instead of an object brings two main advantages: First,
+ * it will be easier in the future to catch settings updates through a
+ * function than an object. Second, giving it a full object will "merge" it
+ * to the settings object properly, keeping us to have to always add a loop.
+ *
+ * @return {configurable} The "settings" function.
+ */
+ var configurable = function() {
+ var i,
+ l,
+ data = {},
+ datas = Array.prototype.slice.call(arguments, 0);
+
+ /**
+ * The method to use to set or get any property of this instance.
+ *
+ * @param {string|object} a1 If it is a string and if a2 is undefined,
+ * then it will return the corresponding
+ * property. If it is a string and if a2 is
+ * set, then it will set a2 as the property
+ * corresponding to a1, and return this. If
+ * it is an object, then each pair string +
+ * object(or any other type) will be set as a
+ * property.
+ * @param {*?} a2 The new property corresponding to a1 if a1
+ * is a string.
+ * @return {*|configurable} Returns itself or the corresponding
+ * property.
+ *
+ * Polymorphism:
+ * *************
+ * Here are some basic use examples:
+ *
+ * > settings = new configurable();
+ * > settings('mySetting', 42);
+ * > settings('mySetting'); // Logs: 42
+ * > settings('mySetting', 123);
+ * > settings('mySetting'); // Logs: 123
+ * > settings({mySetting: 456});
+ * > settings('mySetting'); // Logs: 456
+ *
+ * Also, it is possible to use the function as a fallback:
+ * > settings({mySetting: 'abc'}, 'mySetting'); // Logs: 'abc'
+ * > settings({hisSetting: 'abc'}, 'mySetting'); // Logs: 456
+ */
+ var settings = function(a1, a2) {
+ var o,
+ i,
+ l,
+ k;
+
+ if (arguments.length === 1 && typeof a1 === 'string') {
+ if (data[a1] !== undefined)
+ return data[a1];
+ for (i = 0, l = datas.length; i < l; i++)
+ if (datas[i][a1] !== undefined)
+ return datas[i][a1];
+ return undefined;
+ } else if (typeof a1 === 'object' && typeof a2 === 'string') {
+ return (a1 || {})[a2] !== undefined ? a1[a2] : settings(a2);
+ } else {
+ o = (typeof a1 === 'object' && a2 === undefined) ? a1 : {};
+
+ if (typeof a1 === 'string')
+ o[a1] = a2;
+
+ for (i = 0, k = Object.keys(o), l = k.length; i < l; i++)
+ data[k[i]] = o[k[i]];
+
+ return this;
+ }
+ };
+
+ /**
+ * This method returns a new configurable function, with new objects
+ *
+ * @param {object*} Any number of objects to search in.
+ * @return {function} Returns the function. Check its documentation to know
+ * more about how it works.
+ */
+ settings.embedObjects = function() {
+ var args = datas.concat(
+ data
+ ).concat(
+ Array.prototype.splice.call(arguments, 0)
+ );
+
+ return configurable.apply({}, args);
+ };
+
+ // Initialize
+ for (i = 0, l = arguments.length; i < l; i++)
+ settings(arguments[i]);
+
+ return settings;
+ };
+
+ /**
+ * EXPORT:
+ * *******
+ */
+ if (typeof this.sigma !== 'undefined') {
+ this.sigma.classes = this.sigma.classes || {};
+ this.sigma.classes.configurable = configurable;
+ } else if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = configurable;
+ exports.configurable = configurable;
+ } else
+ this.configurable = configurable;
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ var _methods = Object.create(null),
+ _indexes = Object.create(null),
+ _initBindings = Object.create(null),
+ _methodBindings = Object.create(null),
+ _methodBeforeBindings = Object.create(null),
+ _defaultSettings = {
+ immutable: true,
+ clone: true
+ },
+ _defaultSettingsFunction = function(key) {
+ return _defaultSettings[key];
+ };
+
+ /**
+ * The graph constructor. It initializes the data and the indexes, and binds
+ * the custom indexes and methods to its own scope.
+ *
+ * Recognized parameters:
+ * **********************
+ * Here is the exhaustive list of every accepted parameters in the settings
+ * object:
+ *
+ * {boolean} clone Indicates if the data have to be cloned in methods
+ * to add nodes or edges.
+ * {boolean} immutable Indicates if nodes "id" values and edges "id",
+ * "source" and "target" values must be set as
+ * immutable.
+ *
+ * @param {?configurable} settings Eventually a settings function.
+ * @return {graph} The new graph instance.
+ */
+ var graph = function(settings) {
+ var k,
+ fn,
+ data;
+
+ /**
+ * DATA:
+ * *****
+ * Every data that is callable from graph methods are stored in this "data"
+ * object. This object will be served as context for all these methods,
+ * and it is possible to add other type of data in it.
+ */
+ data = {
+ /**
+ * SETTINGS FUNCTION:
+ * ******************
+ */
+ settings: settings || _defaultSettingsFunction,
+
+ /**
+ * MAIN DATA:
+ * **********
+ */
+ nodesArray: [],
+ edgesArray: [],
+
+ /**
+ * GLOBAL INDEXES:
+ * ***************
+ * These indexes just index data by ids.
+ */
+ nodesIndex: Object.create(null),
+ edgesIndex: Object.create(null),
+
+ /**
+ * LOCAL INDEXES:
+ * **************
+ * These indexes refer from node to nodes. Each key is an id, and each
+ * value is the array of the ids of related nodes.
+ */
+ inNeighborsIndex: Object.create(null),
+ outNeighborsIndex: Object.create(null),
+ allNeighborsIndex: Object.create(null),
+
+ inNeighborsCount: Object.create(null),
+ outNeighborsCount: Object.create(null),
+ allNeighborsCount: Object.create(null)
+ };
+
+ // Execute bindings:
+ for (k in _initBindings)
+ _initBindings[k].call(data);
+
+ // Add methods to both the scope and the data objects:
+ for (k in _methods) {
+ fn = __bindGraphMethod(k, data, _methods[k]);
+ this[k] = fn;
+ data[k] = fn;
+ }
+ };
+
+
+
+
+ /**
+ * A custom tool to bind methods such that function that are bound to it will
+ * be executed anytime the method is called.
+ *
+ * @param {string} methodName The name of the method to bind.
+ * @param {object} scope The scope where the method must be executed.
+ * @param {function} fn The method itself.
+ * @return {function} The new method.
+ */
+ function __bindGraphMethod(methodName, scope, fn) {
+ var result = function() {
+ var k,
+ res;
+
+ // Execute "before" bound functions:
+ for (k in _methodBeforeBindings[methodName])
+ _methodBeforeBindings[methodName][k].apply(scope, arguments);
+
+ // Apply the method:
+ res = fn.apply(scope, arguments);
+
+ // Execute bound functions:
+ for (k in _methodBindings[methodName])
+ _methodBindings[methodName][k].apply(scope, arguments);
+
+ // Return res:
+ return res;
+ };
+
+ return result;
+ }
+
+ /**
+ * This custom tool function removes every pair key/value from an hash. The
+ * goal is to avoid creating a new object while some other references are
+ * still hanging in some scopes...
+ *
+ * @param {object} obj The object to empty.
+ * @return {object} The empty object.
+ */
+ function __emptyObject(obj) {
+ var k;
+
+ for (k in obj)
+ if (!('hasOwnProperty' in obj) || obj.hasOwnProperty(k))
+ delete obj[k];
+
+ return obj;
+ }
+
+
+
+
+ /**
+ * This global method adds a method that will be bound to the futurly created
+ * graph instances.
+ *
+ * Since these methods will be bound to their scope when the instances are
+ * created, it does not use the prototype. Because of that, methods have to
+ * be added before instances are created to make them available.
+ *
+ * Here is an example:
+ *
+ * > graph.addMethod('getNodesCount', function() {
+ * > return this.nodesArray.length;
+ * > });
+ * >
+ * > var myGraph = new graph();
+ * > console.log(myGraph.getNodesCount()); // outputs 0
+ *
+ * @param {string} methodName The name of the method.
+ * @param {function} fn The method itself.
+ * @return {object} The global graph constructor.
+ */
+ graph.addMethod = function(methodName, fn) {
+ if (
+ typeof methodName !== 'string' ||
+ typeof fn !== 'function' ||
+ arguments.length !== 2
+ )
+ throw 'addMethod: Wrong arguments.';
+
+ if (_methods[methodName] || graph[methodName])
+ throw 'The method "' + methodName + '" already exists.';
+
+ _methods[methodName] = fn;
+ _methodBindings[methodName] = Object.create(null);
+ _methodBeforeBindings[methodName] = Object.create(null);
+
+ return this;
+ };
+
+ /**
+ * This global method returns true if the method has already been added, and
+ * false else.
+ *
+ * Here are some examples:
+ *
+ * > graph.hasMethod('addNode'); // returns true
+ * > graph.hasMethod('hasMethod'); // returns true
+ * > graph.hasMethod('unexistingMethod'); // returns false
+ *
+ * @param {string} methodName The name of the method.
+ * @return {boolean} The result.
+ */
+ graph.hasMethod = function(methodName) {
+ return !!(_methods[methodName] || graph[methodName]);
+ };
+
+ /**
+ * This global methods attaches a function to a method. Anytime the specified
+ * method is called, the attached function is called right after, with the
+ * same arguments and in the same scope. The attached function is called
+ * right before if the last argument is true, unless the method is the graph
+ * constructor.
+ *
+ * To attach a function to the graph constructor, use 'constructor' as the
+ * method name (first argument).
+ *
+ * The main idea is to have a clean way to keep custom indexes up to date,
+ * for instance:
+ *
+ * > var timesAddNodeCalled = 0;
+ * > graph.attach('addNode', 'timesAddNodeCalledInc', function() {
+ * > timesAddNodeCalled++;
+ * > });
+ * >
+ * > var myGraph = new graph();
+ * > console.log(timesAddNodeCalled); // outputs 0
+ * >
+ * > myGraph.addNode({ id: '1' }).addNode({ id: '2' });
+ * > console.log(timesAddNodeCalled); // outputs 2
+ *
+ * The idea for calling a function before is to provide pre-processors, for
+ * instance:
+ *
+ * > var colorPalette = { Person: '#C3CBE1', Place: '#9BDEBD' };
+ * > graph.attach('addNode', 'applyNodeColorPalette', function(n) {
+ * > n.color = colorPalette[n.category];
+ * > }, true);
+ * >
+ * > var myGraph = new graph();
+ * > myGraph.addNode({ id: 'n0', category: 'Person' });
+ * > console.log(myGraph.nodes('n0').color); // outputs '#C3CBE1'
+ *
+ * @param {string} methodName The name of the related method or
+ * "constructor".
+ * @param {string} key The key to identify the function to attach.
+ * @param {function} fn The function to bind.
+ * @param {boolean} before If true the function is called right before.
+ * @return {object} The global graph constructor.
+ */
+ graph.attach = function(methodName, key, fn, before) {
+ if (
+ typeof methodName !== 'string' ||
+ typeof key !== 'string' ||
+ typeof fn !== 'function' ||
+ arguments.length < 3 ||
+ arguments.length > 4
+ )
+ throw 'attach: Wrong arguments.';
+
+ var bindings;
+
+ if (methodName === 'constructor')
+ bindings = _initBindings;
+ else {
+ if (before) {
+ if (!_methodBeforeBindings[methodName])
+ throw 'The method "' + methodName + '" does not exist.';
+
+ bindings = _methodBeforeBindings[methodName];
+ }
+ else {
+ if (!_methodBindings[methodName])
+ throw 'The method "' + methodName + '" does not exist.';
+
+ bindings = _methodBindings[methodName];
+ }
+ }
+
+ if (bindings[key])
+ throw 'A function "' + key + '" is already attached ' +
+ 'to the method "' + methodName + '".';
+
+ bindings[key] = fn;
+
+ return this;
+ };
+
+ /**
+ * Alias of attach(methodName, key, fn, true).
+ */
+ graph.attachBefore = function(methodName, key, fn) {
+ return this.attach(methodName, key, fn, true);
+ };
+
+ /**
+ * This methods is just an helper to deal with custom indexes. It takes as
+ * arguments the name of the index and an object containing all the different
+ * functions to bind to the methods.
+ *
+ * Here is a basic example, that creates an index to keep the number of nodes
+ * in the current graph. It also adds a method to provide a getter on that
+ * new index:
+ *
+ * > sigma.classes.graph.addIndex('nodesCount', {
+ * > constructor: function() {
+ * > this.nodesCount = 0;
+ * > },
+ * > addNode: function() {
+ * > this.nodesCount++;
+ * > },
+ * > dropNode: function() {
+ * > this.nodesCount--;
+ * > }
+ * > });
+ * >
+ * > sigma.classes.graph.addMethod('getNodesCount', function() {
+ * > return this.nodesCount;
+ * > });
+ * >
+ * > var myGraph = new sigma.classes.graph();
+ * > console.log(myGraph.getNodesCount()); // outputs 0
+ * >
+ * > myGraph.addNode({ id: '1' }).addNode({ id: '2' });
+ * > console.log(myGraph.getNodesCount()); // outputs 2
+ *
+ * @param {string} name The name of the index.
+ * @param {object} bindings The object containing the functions to bind.
+ * @return {object} The global graph constructor.
+ */
+ graph.addIndex = function(name, bindings) {
+ if (
+ typeof name !== 'string' ||
+ Object(bindings) !== bindings ||
+ arguments.length !== 2
+ )
+ throw 'addIndex: Wrong arguments.';
+
+ if (_indexes[name])
+ throw 'The index "' + name + '" already exists.';
+
+ var k;
+
+ // Store the bindings:
+ _indexes[name] = bindings;
+
+ // Attach the bindings:
+ for (k in bindings)
+ if (typeof bindings[k] !== 'function')
+ throw 'The bindings must be functions.';
+ else
+ graph.attach(k, name, bindings[k]);
+
+ return this;
+ };
+
+
+
+
+ /**
+ * This method adds a node to the graph. The node must be an object, with a
+ * string under the key "id". Except for this, it is possible to add any
+ * other attribute, that will be preserved all along the manipulations.
+ *
+ * If the graph option "clone" has a truthy value, the node will be cloned
+ * when added to the graph. Also, if the graph option "immutable" has a
+ * truthy value, its id will be defined as immutable.
+ *
+ * @param {object} node The node to add.
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('addNode', function(node) {
+ // Check that the node is an object and has an id:
+ if (Object(node) !== node || arguments.length !== 1)
+ throw 'addNode: Wrong arguments.';
+
+ if (typeof node.id !== 'string' && typeof node.id !== 'number')
+ throw 'The node must have a string or number id.';
+
+ if (this.nodesIndex[node.id])
+ throw 'The node "' + node.id + '" already exists.';
+
+ var k,
+ id = node.id,
+ validNode = Object.create(null);
+
+ // Check the "clone" option:
+ if (this.settings('clone')) {
+ for (k in node)
+ if (k !== 'id')
+ validNode[k] = node[k];
+ } else
+ validNode = node;
+
+ // Check the "immutable" option:
+ if (this.settings('immutable'))
+ Object.defineProperty(validNode, 'id', {
+ value: id,
+ enumerable: true
+ });
+ else
+ validNode.id = id;
+
+ // Add empty containers for edges indexes:
+ this.inNeighborsIndex[id] = Object.create(null);
+ this.outNeighborsIndex[id] = Object.create(null);
+ this.allNeighborsIndex[id] = Object.create(null);
+
+ this.inNeighborsCount[id] = 0;
+ this.outNeighborsCount[id] = 0;
+ this.allNeighborsCount[id] = 0;
+
+ // Add the node to indexes:
+ this.nodesArray.push(validNode);
+ this.nodesIndex[validNode.id] = validNode;
+
+ // Return the current instance:
+ return this;
+ });
+
+ /**
+ * This method adds an edge to the graph. The edge must be an object, with a
+ * string under the key "id", and strings under the keys "source" and
+ * "target" that design existing nodes. Except for this, it is possible to
+ * add any other attribute, that will be preserved all along the
+ * manipulations.
+ *
+ * If the graph option "clone" has a truthy value, the edge will be cloned
+ * when added to the graph. Also, if the graph option "immutable" has a
+ * truthy value, its id, source and target will be defined as immutable.
+ *
+ * @param {object} edge The edge to add.
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('addEdge', function(edge) {
+ // Check that the edge is an object and has an id:
+ if (Object(edge) !== edge || arguments.length !== 1)
+ throw 'addEdge: Wrong arguments.';
+
+ if (typeof edge.id !== 'string' && typeof edge.id !== 'number')
+ throw 'The edge must have a string or number id.';
+
+ if ((typeof edge.source !== 'string' && typeof edge.source !== 'number') ||
+ !this.nodesIndex[edge.source])
+ throw 'The edge source must have an existing node id.';
+
+ if ((typeof edge.target !== 'string' && typeof edge.target !== 'number') ||
+ !this.nodesIndex[edge.target])
+ throw 'The edge target must have an existing node id.';
+
+ if (this.edgesIndex[edge.id])
+ throw 'The edge "' + edge.id + '" already exists.';
+
+ var k,
+ validEdge = Object.create(null);
+
+ // Check the "clone" option:
+ if (this.settings('clone')) {
+ for (k in edge)
+ if (k !== 'id' && k !== 'source' && k !== 'target')
+ validEdge[k] = edge[k];
+ } else
+ validEdge = edge;
+
+ // Check the "immutable" option:
+ if (this.settings('immutable')) {
+ Object.defineProperty(validEdge, 'id', {
+ value: edge.id,
+ enumerable: true
+ });
+
+ Object.defineProperty(validEdge, 'source', {
+ value: edge.source,
+ enumerable: true
+ });
+
+ Object.defineProperty(validEdge, 'target', {
+ value: edge.target,
+ enumerable: true
+ });
+ } else {
+ validEdge.id = edge.id;
+ validEdge.source = edge.source;
+ validEdge.target = edge.target;
+ }
+
+ // Add the edge to indexes:
+ this.edgesArray.push(validEdge);
+ this.edgesIndex[validEdge.id] = validEdge;
+
+ if (!this.inNeighborsIndex[validEdge.target][validEdge.source])
+ this.inNeighborsIndex[validEdge.target][validEdge.source] =
+ Object.create(null);
+ this.inNeighborsIndex[validEdge.target][validEdge.source][validEdge.id] =
+ validEdge;
+
+ if (!this.outNeighborsIndex[validEdge.source][validEdge.target])
+ this.outNeighborsIndex[validEdge.source][validEdge.target] =
+ Object.create(null);
+ this.outNeighborsIndex[validEdge.source][validEdge.target][validEdge.id] =
+ validEdge;
+
+ if (!this.allNeighborsIndex[validEdge.source][validEdge.target])
+ this.allNeighborsIndex[validEdge.source][validEdge.target] =
+ Object.create(null);
+ this.allNeighborsIndex[validEdge.source][validEdge.target][validEdge.id] =
+ validEdge;
+
+ if (validEdge.target !== validEdge.source) {
+ if (!this.allNeighborsIndex[validEdge.target][validEdge.source])
+ this.allNeighborsIndex[validEdge.target][validEdge.source] =
+ Object.create(null);
+ this.allNeighborsIndex[validEdge.target][validEdge.source][validEdge.id] =
+ validEdge;
+ }
+
+ // Keep counts up to date:
+ this.inNeighborsCount[validEdge.target]++;
+ this.outNeighborsCount[validEdge.source]++;
+ this.allNeighborsCount[validEdge.target]++;
+ this.allNeighborsCount[validEdge.source]++;
+
+ return this;
+ });
+
+ /**
+ * This method drops a node from the graph. It also removes each edge that is
+ * bound to it, through the dropEdge method. An error is thrown if the node
+ * does not exist.
+ *
+ * @param {string} id The node id.
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('dropNode', function(id) {
+ // Check that the arguments are valid:
+ if ((typeof id !== 'string' && typeof id !== 'number') ||
+ arguments.length !== 1)
+ throw 'dropNode: Wrong arguments.';
+
+ if (!this.nodesIndex[id])
+ throw 'The node "' + id + '" does not exist.';
+
+ var i, k, l;
+
+ // Remove the node from indexes:
+ delete this.nodesIndex[id];
+ for (i = 0, l = this.nodesArray.length; i < l; i++)
+ if (this.nodesArray[i].id === id) {
+ this.nodesArray.splice(i, 1);
+ break;
+ }
+
+ // Remove related edges:
+ for (i = this.edgesArray.length - 1; i >= 0; i--)
+ if (this.edgesArray[i].source === id || this.edgesArray[i].target === id)
+ this.dropEdge(this.edgesArray[i].id);
+
+ // Remove related edge indexes:
+ delete this.inNeighborsIndex[id];
+ delete this.outNeighborsIndex[id];
+ delete this.allNeighborsIndex[id];
+
+ delete this.inNeighborsCount[id];
+ delete this.outNeighborsCount[id];
+ delete this.allNeighborsCount[id];
+
+ for (k in this.nodesIndex) {
+ delete this.inNeighborsIndex[k][id];
+ delete this.outNeighborsIndex[k][id];
+ delete this.allNeighborsIndex[k][id];
+ }
+
+ return this;
+ });
+
+ /**
+ * This method drops an edge from the graph. An error is thrown if the edge
+ * does not exist.
+ *
+ * @param {string} id The edge id.
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('dropEdge', function(id) {
+ // Check that the arguments are valid:
+ if ((typeof id !== 'string' && typeof id !== 'number') ||
+ arguments.length !== 1)
+ throw 'dropEdge: Wrong arguments.';
+
+ if (!this.edgesIndex[id])
+ throw 'The edge "' + id + '" does not exist.';
+
+ var i, l, edge;
+
+ // Remove the edge from indexes:
+ edge = this.edgesIndex[id];
+ delete this.edgesIndex[id];
+ for (i = 0, l = this.edgesArray.length; i < l; i++)
+ if (this.edgesArray[i].id === id) {
+ this.edgesArray.splice(i, 1);
+ break;
+ }
+
+ delete this.inNeighborsIndex[edge.target][edge.source][edge.id];
+ if (!Object.keys(this.inNeighborsIndex[edge.target][edge.source]).length)
+ delete this.inNeighborsIndex[edge.target][edge.source];
+
+ delete this.outNeighborsIndex[edge.source][edge.target][edge.id];
+ if (!Object.keys(this.outNeighborsIndex[edge.source][edge.target]).length)
+ delete this.outNeighborsIndex[edge.source][edge.target];
+
+ delete this.allNeighborsIndex[edge.source][edge.target][edge.id];
+ if (!Object.keys(this.allNeighborsIndex[edge.source][edge.target]).length)
+ delete this.allNeighborsIndex[edge.source][edge.target];
+
+ if (edge.target !== edge.source) {
+ delete this.allNeighborsIndex[edge.target][edge.source][edge.id];
+ if (!Object.keys(this.allNeighborsIndex[edge.target][edge.source]).length)
+ delete this.allNeighborsIndex[edge.target][edge.source];
+ }
+
+ this.inNeighborsCount[edge.target]--;
+ this.outNeighborsCount[edge.source]--;
+ this.allNeighborsCount[edge.source]--;
+ this.allNeighborsCount[edge.target]--;
+
+ return this;
+ });
+
+ /**
+ * This method destroys the current instance. It basically empties each index
+ * and methods attached to the graph.
+ */
+ graph.addMethod('kill', function() {
+ // Delete arrays:
+ this.nodesArray.length = 0;
+ this.edgesArray.length = 0;
+ delete this.nodesArray;
+ delete this.edgesArray;
+
+ // Delete indexes:
+ delete this.nodesIndex;
+ delete this.edgesIndex;
+ delete this.inNeighborsIndex;
+ delete this.outNeighborsIndex;
+ delete this.allNeighborsIndex;
+ delete this.inNeighborsCount;
+ delete this.outNeighborsCount;
+ delete this.allNeighborsCount;
+ });
+
+ /**
+ * This method empties the nodes and edges arrays, as well as the different
+ * indexes.
+ *
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('clear', function() {
+ this.nodesArray.length = 0;
+ this.edgesArray.length = 0;
+
+ // Due to GC issues, I prefer not to create new object. These objects are
+ // only available from the methods and attached functions, but still, it is
+ // better to prevent ghost references to unrelevant data...
+ __emptyObject(this.nodesIndex);
+ __emptyObject(this.edgesIndex);
+ __emptyObject(this.nodesIndex);
+ __emptyObject(this.inNeighborsIndex);
+ __emptyObject(this.outNeighborsIndex);
+ __emptyObject(this.allNeighborsIndex);
+ __emptyObject(this.inNeighborsCount);
+ __emptyObject(this.outNeighborsCount);
+ __emptyObject(this.allNeighborsCount);
+
+ return this;
+ });
+
+ /**
+ * This method reads an object and adds the nodes and edges, through the
+ * proper methods "addNode" and "addEdge".
+ *
+ * Here is an example:
+ *
+ * > var myGraph = new graph();
+ * > myGraph.read({
+ * > nodes: [
+ * > { id: 'n0' },
+ * > { id: 'n1' }
+ * > ],
+ * > edges: [
+ * > {
+ * > id: 'e0',
+ * > source: 'n0',
+ * > target: 'n1'
+ * > }
+ * > ]
+ * > });
+ * >
+ * > console.log(
+ * > myGraph.nodes().length,
+ * > myGraph.edges().length
+ * > ); // outputs 2 1
+ *
+ * @param {object} g The graph object.
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('read', function(g) {
+ var i,
+ a,
+ l;
+
+ a = g.nodes || [];
+ for (i = 0, l = a.length; i < l; i++)
+ this.addNode(a[i]);
+
+ a = g.edges || [];
+ for (i = 0, l = a.length; i < l; i++)
+ this.addEdge(a[i]);
+
+ return this;
+ });
+
+ /**
+ * This methods returns one or several nodes, depending on how it is called.
+ *
+ * To get the array of nodes, call "nodes" without argument. To get a
+ * specific node, call it with the id of the node. The get multiple node,
+ * call it with an array of ids, and it will return the array of nodes, in
+ * the same order.
+ *
+ * @param {?(string|array)} v Eventually one id, an array of ids.
+ * @return {object|array} The related node or array of nodes.
+ */
+ graph.addMethod('nodes', function(v) {
+ // Clone the array of nodes and return it:
+ if (!arguments.length)
+ return this.nodesArray.slice(0);
+
+ // Return the related node:
+ if (arguments.length === 1 &&
+ (typeof v === 'string' || typeof v === 'number'))
+ return this.nodesIndex[v];
+
+ // Return an array of the related node:
+ if (
+ arguments.length === 1 &&
+ Object.prototype.toString.call(v) === '[object Array]'
+ ) {
+ var i,
+ l,
+ a = [];
+
+ for (i = 0, l = v.length; i < l; i++)
+ if (typeof v[i] === 'string' || typeof v[i] === 'number')
+ a.push(this.nodesIndex[v[i]]);
+ else
+ throw 'nodes: Wrong arguments.';
+
+ return a;
+ }
+
+ throw 'nodes: Wrong arguments.';
+ });
+
+ /**
+ * This methods returns the degree of one or several nodes, depending on how
+ * it is called. It is also possible to get incoming or outcoming degrees
+ * instead by specifying 'in' or 'out' as a second argument.
+ *
+ * @param {string|array} v One id, an array of ids.
+ * @param {?string} which Which degree is required. Values are 'in',
+ * 'out', and by default the normal degree.
+ * @return {number|array} The related degree or array of degrees.
+ */
+ graph.addMethod('degree', function(v, which) {
+ // Check which degree is required:
+ which = {
+ 'in': this.inNeighborsCount,
+ 'out': this.outNeighborsCount
+ }[which || ''] || this.allNeighborsCount;
+
+ // Return the related node:
+ if (typeof v === 'string' || typeof v === 'number')
+ return which[v];
+
+ // Return an array of the related node:
+ if (Object.prototype.toString.call(v) === '[object Array]') {
+ var i,
+ l,
+ a = [];
+
+ for (i = 0, l = v.length; i < l; i++)
+ if (typeof v[i] === 'string' || typeof v[i] === 'number')
+ a.push(which[v[i]]);
+ else
+ throw 'degree: Wrong arguments.';
+
+ return a;
+ }
+
+ throw 'degree: Wrong arguments.';
+ });
+
+ /**
+ * This methods returns one or several edges, depending on how it is called.
+ *
+ * To get the array of edges, call "edges" without argument. To get a
+ * specific edge, call it with the id of the edge. The get multiple edge,
+ * call it with an array of ids, and it will return the array of edges, in
+ * the same order.
+ *
+ * @param {?(string|array)} v Eventually one id, an array of ids.
+ * @return {object|array} The related edge or array of edges.
+ */
+ graph.addMethod('edges', function(v) {
+ // Clone the array of edges and return it:
+ if (!arguments.length)
+ return this.edgesArray.slice(0);
+
+ // Return the related edge:
+ if (arguments.length === 1 &&
+ (typeof v === 'string' || typeof v === 'number'))
+ return this.edgesIndex[v];
+
+ // Return an array of the related edge:
+ if (
+ arguments.length === 1 &&
+ Object.prototype.toString.call(v) === '[object Array]'
+ ) {
+ var i,
+ l,
+ a = [];
+
+ for (i = 0, l = v.length; i < l; i++)
+ if (typeof v[i] === 'string' || typeof v[i] === 'number')
+ a.push(this.edgesIndex[v[i]]);
+ else
+ throw 'edges: Wrong arguments.';
+
+ return a;
+ }
+
+ throw 'edges: Wrong arguments.';
+ });
+
+
+ /**
+ * EXPORT:
+ * *******
+ */
+ if (typeof sigma !== 'undefined') {
+ sigma.classes = sigma.classes || Object.create(null);
+ sigma.classes.graph = graph;
+ } else if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = graph;
+ exports.graph = graph;
+ } else
+ this.graph = graph;
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ sigma.utils.pkg('sigma.classes');
+
+ /**
+ * The camera constructor. It just initializes its attributes and methods.
+ *
+ * @param {string} id The id.
+ * @param {sigma.classes.graph} graph The graph.
+ * @param {configurable} settings The settings function.
+ * @param {?object} options Eventually some overriding options.
+ * @return {camera} Returns the fresh new camera instance.
+ */
+ sigma.classes.camera = function(id, graph, settings, options) {
+ sigma.classes.dispatcher.extend(this);
+
+ Object.defineProperty(this, 'graph', {
+ value: graph
+ });
+ Object.defineProperty(this, 'id', {
+ value: id
+ });
+ Object.defineProperty(this, 'readPrefix', {
+ value: 'read_cam' + id + ':'
+ });
+ Object.defineProperty(this, 'prefix', {
+ value: 'cam' + id + ':'
+ });
+
+ this.x = 0;
+ this.y = 0;
+ this.ratio = 1;
+ this.angle = 0;
+ this.isAnimated = false;
+ this.settings = (typeof options === 'object' && options) ?
+ settings.embedObject(options) :
+ settings;
+ };
+
+ /**
+ * Updates the camera position.
+ *
+ * @param {object} coordinates The new coordinates object.
+ * @return {camera} Returns the camera.
+ */
+ sigma.classes.camera.prototype.goTo = function(coordinates) {
+ if (!this.settings('enableCamera'))
+ return this;
+
+ var i,
+ l,
+ c = coordinates || {},
+ keys = ['x', 'y', 'ratio', 'angle'];
+
+ for (i = 0, l = keys.length; i < l; i++)
+ if (c[keys[i]] !== undefined) {
+ if (typeof c[keys[i]] === 'number' && !isNaN(c[keys[i]]))
+ this[keys[i]] = c[keys[i]];
+ else
+ throw 'Value for "' + keys[i] + '" is not a number.';
+ }
+
+ this.dispatchEvent('coordinatesUpdated');
+ return this;
+ };
+
+ /**
+ * This method takes a graph and computes for each node and edges its
+ * coordinates relatively to the center of the camera. Basically, it will
+ * compute the coordinates that will be used by the graphic renderers.
+ *
+ * Since it should be possible to use different cameras and different
+ * renderers, it is possible to specify a prefix to put before the new
+ * coordinates (to get something like "node.camera1_x")
+ *
+ * @param {?string} read The prefix of the coordinates to read.
+ * @param {?string} write The prefix of the coordinates to write.
+ * @param {?object} options Eventually an object of options. Those can be:
+ * - A restricted nodes array.
+ * - A restricted edges array.
+ * - A width.
+ * - A height.
+ * @return {camera} Returns the camera.
+ */
+ sigma.classes.camera.prototype.applyView = function(read, write, options) {
+ options = options || {};
+ write = write !== undefined ? write : this.prefix;
+ read = read !== undefined ? read : this.readPrefix;
+
+ var nodes = options.nodes || this.graph.nodes(),
+ edges = options.edges || this.graph.edges();
+
+ var i,
+ l,
+ node,
+ cos = Math.cos(this.angle),
+ sin = Math.sin(this.angle),
+ nodeRatio = Math.pow(this.ratio, this.settings('nodesPowRatio')),
+ edgeRatio = Math.pow(this.ratio, this.settings('edgesPowRatio')),
+ xOffset = (options.width || 0) / 2,
+ yOffset = (options.height || 0) / 2;
+
+ for (i = 0, l = nodes.length; i < l; i++) {
+ node = nodes[i];
+ node[write + 'x'] =
+ (
+ ((node[read + 'x'] || 0) - this.x) * cos +
+ ((node[read + 'y'] || 0) - this.y) * sin
+ ) / this.ratio + xOffset;
+ node[write + 'y'] =
+ (
+ ((node[read + 'y'] || 0) - this.y) * cos -
+ ((node[read + 'x'] || 0) - this.x) * sin
+ ) / this.ratio + yOffset;
+ node[write + 'size'] =
+ (node[read + 'size'] || 0) /
+ nodeRatio;
+ }
+
+ for (i = 0, l = edges.length; i < l; i++) {
+ edges[i][write + 'size'] =
+ (edges[i][read + 'size'] || 0) /
+ edgeRatio;
+ }
+
+ return this;
+ };
+
+ /**
+ * This function converts the coordinates of a point from the frame of the
+ * camera to the frame of the graph.
+ *
+ * @param {number} x The X coordinate of the point in the frame of the
+ * camera.
+ * @param {number} y The Y coordinate of the point in the frame of the
+ * camera.
+ * @return {object} The point coordinates in the frame of the graph.
+ */
+ sigma.classes.camera.prototype.graphPosition = function(x, y, vector) {
+ var X = 0,
+ Y = 0,
+ cos = Math.cos(this.angle),
+ sin = Math.sin(this.angle);
+
+ // Revert the origin differential vector:
+ if (!vector) {
+ X = - (this.x * cos + this.y * sin) / this.ratio;
+ Y = - (this.y * cos - this.x * sin) / this.ratio;
+ }
+
+ return {
+ x: (x * cos + y * sin) / this.ratio + X,
+ y: (y * cos - x * sin) / this.ratio + Y
+ };
+ };
+
+ /**
+ * This function converts the coordinates of a point from the frame of the
+ * graph to the frame of the camera.
+ *
+ * @param {number} x The X coordinate of the point in the frame of the
+ * graph.
+ * @param {number} y The Y coordinate of the point in the frame of the
+ * graph.
+ * @return {object} The point coordinates in the frame of the camera.
+ */
+ sigma.classes.camera.prototype.cameraPosition = function(x, y, vector) {
+ var X = 0,
+ Y = 0,
+ cos = Math.cos(this.angle),
+ sin = Math.sin(this.angle);
+
+ // Revert the origin differential vector:
+ if (!vector) {
+ X = - (this.x * cos + this.y * sin) / this.ratio;
+ Y = - (this.y * cos - this.x * sin) / this.ratio;
+ }
+
+ return {
+ x: ((x - X) * cos - (y - Y) * sin) * this.ratio,
+ y: ((y - Y) * cos + (x - X) * sin) * this.ratio
+ };
+ };
+
+ /**
+ * This method returns the transformation matrix of the camera. This is
+ * especially useful to apply the camera view directly in shaders, in case of
+ * WebGL rendering.
+ *
+ * @return {array} The transformation matrix.
+ */
+ sigma.classes.camera.prototype.getMatrix = function() {
+ var scale = sigma.utils.matrices.scale(1 / this.ratio),
+ rotation = sigma.utils.matrices.rotation(this.angle),
+ translation = sigma.utils.matrices.translation(-this.x, -this.y),
+ matrix = sigma.utils.matrices.multiply(
+ translation,
+ sigma.utils.matrices.multiply(
+ rotation,
+ scale
+ )
+ );
+
+ return matrix;
+ };
+
+ /**
+ * Taking a width and a height as parameters, this method returns the
+ * coordinates of the rectangle representing the camera on screen, in the
+ * graph's referentiel.
+ *
+ * To keep displaying labels of nodes going out of the screen, the method
+ * keeps a margin around the screen in the returned rectangle.
+ *
+ * @param {number} width The width of the screen.
+ * @param {number} height The height of the screen.
+ * @return {object} The rectangle as x1, y1, x2 and y2, representing
+ * two opposite points.
+ */
+ sigma.classes.camera.prototype.getRectangle = function(width, height) {
+ var widthVect = this.cameraPosition(width, 0, true),
+ heightVect = this.cameraPosition(0, height, true),
+ centerVect = this.cameraPosition(width / 2, height / 2, true),
+ marginX = this.cameraPosition(width / 4, 0, true).x,
+ marginY = this.cameraPosition(0, height / 4, true).y;
+
+ return {
+ x1: this.x - centerVect.x - marginX,
+ y1: this.y - centerVect.y - marginY,
+ x2: this.x - centerVect.x + marginX + widthVect.x,
+ y2: this.y - centerVect.y - marginY + widthVect.y,
+ height: Math.sqrt(
+ Math.pow(heightVect.x, 2) +
+ Math.pow(heightVect.y + 2 * marginY, 2)
+ )
+ };
+ };
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ /**
+ * Sigma Quadtree Module
+ * =====================
+ *
+ * Author: Guillaume Plique (Yomguithereal)
+ * Version: 0.2
+ */
+
+
+
+ /**
+ * Quad Geometric Operations
+ * -------------------------
+ *
+ * A useful batch of geometric operations used by the quadtree.
+ */
+
+ var _geom = {
+
+ /**
+ * Transforms a graph node with x, y and size into an
+ * axis-aligned square.
+ *
+ * @param {object} A graph node with at least a point (x, y) and a size.
+ * @return {object} A square: two points (x1, y1), (x2, y2) and height.
+ */
+ pointToSquare: function(n) {
+ return {
+ x1: n.x - n.size,
+ y1: n.y - n.size,
+ x2: n.x + n.size,
+ y2: n.y - n.size,
+ height: n.size * 2
+ };
+ },
+
+ /**
+ * Checks whether a rectangle is axis-aligned.
+ *
+ * @param {object} A rectangle defined by two points
+ * (x1, y1) and (x2, y2).
+ * @return {boolean} True if the rectangle is axis-aligned.
+ */
+ isAxisAligned: function(r) {
+ return r.x1 === r.x2 || r.y1 === r.y2;
+ },
+
+ /**
+ * Compute top points of an axis-aligned rectangle. This is useful in
+ * cases when the rectangle has been rotated (left, right or bottom up) and
+ * later operations need to know the top points.
+ *
+ * @param {object} An axis-aligned rectangle defined by two points
+ * (x1, y1), (x2, y2) and height.
+ * @return {object} A rectangle: two points (x1, y1), (x2, y2) and height.
+ */
+ axisAlignedTopPoints: function(r) {
+
+ // Basic
+ if (r.y1 === r.y2 && r.x1 < r.x2)
+ return r;
+
+ // Rotated to right
+ if (r.x1 === r.x2 && r.y2 > r.y1)
+ return {
+ x1: r.x1 - r.height, y1: r.y1,
+ x2: r.x1, y2: r.y1,
+ height: r.height
+ };
+
+ // Rotated to left
+ if (r.x1 === r.x2 && r.y2 < r.y1)
+ return {
+ x1: r.x1, y1: r.y2,
+ x2: r.x2 + r.height, y2: r.y2,
+ height: r.height
+ };
+
+ // Bottom's up
+ return {
+ x1: r.x2, y1: r.y1 - r.height,
+ x2: r.x1, y2: r.y1 - r.height,
+ height: r.height
+ };
+ },
+
+ /**
+ * Get coordinates of a rectangle's lower left corner from its top points.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @return {object} Coordinates of the corner (x, y).
+ */
+ lowerLeftCoor: function(r) {
+ var width = (
+ Math.sqrt(
+ Math.pow(r.x2 - r.x1, 2) +
+ Math.pow(r.y2 - r.y1, 2)
+ )
+ );
+
+ return {
+ x: r.x1 - (r.y2 - r.y1) * r.height / width,
+ y: r.y1 + (r.x2 - r.x1) * r.height / width
+ };
+ },
+
+ /**
+ * Get coordinates of a rectangle's lower right corner from its top points
+ * and its lower left corner.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @param {object} A corner's coordinates (x, y).
+ * @return {object} Coordinates of the corner (x, y).
+ */
+ lowerRightCoor: function(r, llc) {
+ return {
+ x: llc.x - r.x1 + r.x2,
+ y: llc.y - r.y1 + r.y2
+ };
+ },
+
+ /**
+ * Get the coordinates of all the corners of a rectangle from its top point.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @return {array} An array of the four corners' coordinates (x, y).
+ */
+ rectangleCorners: function(r) {
+ var llc = this.lowerLeftCoor(r),
+ lrc = this.lowerRightCoor(r, llc);
+
+ return [
+ {x: r.x1, y: r.y1},
+ {x: r.x2, y: r.y2},
+ {x: llc.x, y: llc.y},
+ {x: lrc.x, y: lrc.y}
+ ];
+ },
+
+ /**
+ * Split a square defined by its boundaries into four.
+ *
+ * @param {object} Boundaries of the square (x, y, width, height).
+ * @return {array} An array containing the four new squares, themselves
+ * defined by an array of their four corners (x, y).
+ */
+ splitSquare: function(b) {
+ return [
+ [
+ {x: b.x, y: b.y},
+ {x: b.x + b.width / 2, y: b.y},
+ {x: b.x, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2}
+ ],
+ [
+ {x: b.x + b.width / 2, y: b.y},
+ {x: b.x + b.width, y: b.y},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x + b.width, y: b.y + b.height / 2}
+ ],
+ [
+ {x: b.x, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x, y: b.y + b.height},
+ {x: b.x + b.width / 2, y: b.y + b.height}
+ ],
+ [
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x + b.width, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height},
+ {x: b.x + b.width, y: b.y + b.height}
+ ]
+ ];
+ },
+
+ /**
+ * Compute the four axis between corners of rectangle A and corners of
+ * rectangle B. This is needed later to check an eventual collision.
+ *
+ * @param {array} An array of rectangle A's four corners (x, y).
+ * @param {array} An array of rectangle B's four corners (x, y).
+ * @return {array} An array of four axis defined by their coordinates (x,y).
+ */
+ axis: function(c1, c2) {
+ return [
+ {x: c1[1].x - c1[0].x, y: c1[1].y - c1[0].y},
+ {x: c1[1].x - c1[3].x, y: c1[1].y - c1[3].y},
+ {x: c2[0].x - c2[2].x, y: c2[0].y - c2[2].y},
+ {x: c2[0].x - c2[1].x, y: c2[0].y - c2[1].y}
+ ];
+ },
+
+ /**
+ * Project a rectangle's corner on an axis.
+ *
+ * @param {object} Coordinates of a corner (x, y).
+ * @param {object} Coordinates of an axis (x, y).
+ * @return {object} The projection defined by coordinates (x, y).
+ */
+ projection: function(c, a) {
+ var l = (
+ (c.x * a.x + c.y * a.y) /
+ (Math.pow(a.x, 2) + Math.pow(a.y, 2))
+ );
+
+ return {
+ x: l * a.x,
+ y: l * a.y
+ };
+ },
+
+ /**
+ * Check whether two rectangles collide on one particular axis.
+ *
+ * @param {object} An axis' coordinates (x, y).
+ * @param {array} Rectangle A's corners.
+ * @param {array} Rectangle B's corners.
+ * @return {boolean} True if the rectangles collide on the axis.
+ */
+ axisCollision: function(a, c1, c2) {
+ var sc1 = [],
+ sc2 = [];
+
+ for (var ci = 0; ci < 4; ci++) {
+ var p1 = this.projection(c1[ci], a),
+ p2 = this.projection(c2[ci], a);
+
+ sc1.push(p1.x * a.x + p1.y * a.y);
+ sc2.push(p2.x * a.x + p2.y * a.y);
+ }
+
+ var maxc1 = Math.max.apply(Math, sc1),
+ maxc2 = Math.max.apply(Math, sc2),
+ minc1 = Math.min.apply(Math, sc1),
+ minc2 = Math.min.apply(Math, sc2);
+
+ return (minc2 <= maxc1 && maxc2 >= minc1);
+ },
+
+ /**
+ * Check whether two rectangles collide on each one of their four axis. If
+ * all axis collide, then the two rectangles do collide on the plane.
+ *
+ * @param {array} Rectangle A's corners.
+ * @param {array} Rectangle B's corners.
+ * @return {boolean} True if the rectangles collide.
+ */
+ collision: function(c1, c2) {
+ var axis = this.axis(c1, c2),
+ col = true;
+
+ for (var i = 0; i < 4; i++)
+ col = col && this.axisCollision(axis[i], c1, c2);
+
+ return col;
+ }
+ };
+
+
+ /**
+ * Quad Functions
+ * ------------
+ *
+ * The Quadtree functions themselves.
+ * For each of those functions, we consider that in a splitted quad, the
+ * index of each node is the following:
+ * 0: top left
+ * 1: top right
+ * 2: bottom left
+ * 3: bottom right
+ *
+ * Moreover, the hereafter quad's philosophy is to consider that if an element
+ * collides with more than one nodes, this element belongs to each of the
+ * nodes it collides with where other would let it lie on a higher node.
+ */
+
+ /**
+ * Get the index of the node containing the point in the quad
+ *
+ * @param {object} point A point defined by coordinates (x, y).
+ * @param {object} quadBounds Boundaries of the quad (x, y, width, heigth).
+ * @return {integer} The index of the node containing the point.
+ */
+ function _quadIndex(point, quadBounds) {
+ var xmp = quadBounds.x + quadBounds.width / 2,
+ ymp = quadBounds.y + quadBounds.height / 2,
+ top = (point.y < ymp),
+ left = (point.x < xmp);
+
+ if (top) {
+ if (left)
+ return 0;
+ else
+ return 1;
+ }
+ else {
+ if (left)
+ return 2;
+ else
+ return 3;
+ }
+ }
+
+ /**
+ * Get a list of indexes of nodes containing an axis-aligned rectangle
+ *
+ * @param {object} rectangle A rectangle defined by two points (x1, y1),
+ * (x2, y2) and height.
+ * @param {array} quadCorners An array of the quad nodes' corners.
+ * @return {array} An array of indexes containing one to
+ * four integers.
+ */
+ function _quadIndexes(rectangle, quadCorners) {
+ var indexes = [];
+
+ // Iterating through quads
+ for (var i = 0; i < 4; i++)
+ if ((rectangle.x2 >= quadCorners[i][0].x) &&
+ (rectangle.x1 <= quadCorners[i][1].x) &&
+ (rectangle.y1 + rectangle.height >= quadCorners[i][0].y) &&
+ (rectangle.y1 <= quadCorners[i][2].y))
+ indexes.push(i);
+
+ return indexes;
+ }
+
+ /**
+ * Get a list of indexes of nodes containing a non-axis-aligned rectangle
+ *
+ * @param {array} corners An array containing each corner of the
+ * rectangle defined by its coordinates (x, y).
+ * @param {array} quadCorners An array of the quad nodes' corners.
+ * @return {array} An array of indexes containing one to
+ * four integers.
+ */
+ function _quadCollision(corners, quadCorners) {
+ var indexes = [];
+
+ // Iterating through quads
+ for (var i = 0; i < 4; i++)
+ if (_geom.collision(corners, quadCorners[i]))
+ indexes.push(i);
+
+ return indexes;
+ }
+
+ /**
+ * Subdivide a quad by creating a node at a precise index. The function does
+ * not generate all four nodes not to potentially create unused nodes.
+ *
+ * @param {integer} index The index of the node to create.
+ * @param {object} quad The quad object to subdivide.
+ * @return {object} A new quad representing the node created.
+ */
+ function _quadSubdivide(index, quad) {
+ var next = quad.level + 1,
+ subw = Math.round(quad.bounds.width / 2),
+ subh = Math.round(quad.bounds.height / 2),
+ qx = Math.round(quad.bounds.x),
+ qy = Math.round(quad.bounds.y),
+ x,
+ y;
+
+ switch (index) {
+ case 0:
+ x = qx;
+ y = qy;
+ break;
+ case 1:
+ x = qx + subw;
+ y = qy;
+ break;
+ case 2:
+ x = qx;
+ y = qy + subh;
+ break;
+ case 3:
+ x = qx + subw;
+ y = qy + subh;
+ break;
+ }
+
+ return _quadTree(
+ {x: x, y: y, width: subw, height: subh},
+ next,
+ quad.maxElements,
+ quad.maxLevel
+ );
+ }
+
+ /**
+ * Recursively insert an element into the quadtree. Only points
+ * with size, i.e. axis-aligned squares, may be inserted with this
+ * method.
+ *
+ * @param {object} el The element to insert in the quadtree.
+ * @param {object} sizedPoint A sized point defined by two top points
+ * (x1, y1), (x2, y2) and height.
+ * @param {object} quad The quad in which to insert the element.
+ * @return {undefined} The function does not return anything.
+ */
+ function _quadInsert(el, sizedPoint, quad) {
+ if (quad.level < quad.maxLevel) {
+
+ // Searching appropriate quads
+ var indexes = _quadIndexes(sizedPoint, quad.corners);
+
+ // Iterating
+ for (var i = 0, l = indexes.length; i < l; i++) {
+
+ // Subdividing if necessary
+ if (quad.nodes[indexes[i]] === undefined)
+ quad.nodes[indexes[i]] = _quadSubdivide(indexes[i], quad);
+
+ // Recursion
+ _quadInsert(el, sizedPoint, quad.nodes[indexes[i]]);
+ }
+ }
+ else {
+
+ // Pushing the element in a leaf node
+ quad.elements.push(el);
+ }
+ }
+
+ /**
+ * Recursively retrieve every elements held by the node containing the
+ * searched point.
+ *
+ * @param {object} point The searched point (x, y).
+ * @param {object} quad The searched quad.
+ * @return {array} An array of elements contained in the relevant
+ * node.
+ */
+ function _quadRetrievePoint(point, quad) {
+ if (quad.level < quad.maxLevel) {
+ var index = _quadIndex(point, quad.bounds);
+
+ // If node does not exist we return an empty list
+ if (quad.nodes[index] !== undefined) {
+ return _quadRetrievePoint(point, quad.nodes[index]);
+ }
+ else {
+ return [];
+ }
+ }
+ else {
+ return quad.elements;
+ }
+ }
+
+ /**
+ * Recursively retrieve every elements contained within an rectangular area
+ * that may or may not be axis-aligned.
+ *
+ * @param {object|array} rectData The searched area defined either by
+ * an array of four corners (x, y) in
+ * the case of a non-axis-aligned
+ * rectangle or an object with two top
+ * points (x1, y1), (x2, y2) and height.
+ * @param {object} quad The searched quad.
+ * @param {function} collisionFunc The collision function used to search
+ * for node indexes.
+ * @param {array?} els The retrieved elements.
+ * @return {array} An array of elements contained in the
+ * area.
+ */
+ function _quadRetrieveArea(rectData, quad, collisionFunc, els) {
+ els = els || {};
+
+ if (quad.level < quad.maxLevel) {
+ var indexes = collisionFunc(rectData, quad.corners);
+
+ for (var i = 0, l = indexes.length; i < l; i++)
+ if (quad.nodes[indexes[i]] !== undefined)
+ _quadRetrieveArea(
+ rectData,
+ quad.nodes[indexes[i]],
+ collisionFunc,
+ els
+ );
+ } else
+ for (var j = 0, m = quad.elements.length; j < m; j++)
+ if (els[quad.elements[j].id] === undefined)
+ els[quad.elements[j].id] = quad.elements[j];
+
+ return els;
+ }
+
+ /**
+ * Creates the quadtree object itself.
+ *
+ * @param {object} bounds The boundaries of the quad defined by an
+ * origin (x, y), width and heigth.
+ * @param {integer} level The level of the quad in the tree.
+ * @param {integer} maxElements The max number of element in a leaf node.
+ * @param {integer} maxLevel The max recursion level of the tree.
+ * @return {object} The quadtree object.
+ */
+ function _quadTree(bounds, level, maxElements, maxLevel) {
+ return {
+ level: level || 0,
+ bounds: bounds,
+ corners: _geom.splitSquare(bounds),
+ maxElements: maxElements || 20,
+ maxLevel: maxLevel || 4,
+ elements: [],
+ nodes: []
+ };
+ }
+
+
+ /**
+ * Sigma Quad Constructor
+ * ----------------------
+ *
+ * The quad API as exposed to sigma.
+ */
+
+ /**
+ * The quad core that will become the sigma interface with the quadtree.
+ *
+ * property {object} _tree Property holding the quadtree object.
+ * property {object} _geom Exposition of the _geom namespace for testing.
+ * property {object} _cache Cache for the area method.
+ */
+ var quad = function() {
+ this._geom = _geom;
+ this._tree = null;
+ this._cache = {
+ query: false,
+ result: false
+ };
+ };
+
+ /**
+ * Index a graph by inserting its nodes into the quadtree.
+ *
+ * @param {array} nodes An array of nodes to index.
+ * @param {object} params An object of parameters with at least the quad
+ * bounds.
+ * @return {object} The quadtree object.
+ *
+ * Parameters:
+ * ----------
+ * bounds: {object} boundaries of the quad defined by its origin (x, y)
+ * width and heigth.
+ * prefix: {string?} a prefix for node geometric attributes.
+ * maxElements: {integer?} the max number of elements in a leaf node.
+ * maxLevel: {integer?} the max recursion level of the tree.
+ */
+ quad.prototype.index = function(nodes, params) {
+
+ // Enforcing presence of boundaries
+ if (!params.bounds)
+ throw 'sigma.classes.quad.index: bounds information not given.';
+
+ // Prefix
+ var prefix = params.prefix || '';
+
+ // Building the tree
+ this._tree = _quadTree(
+ params.bounds,
+ 0,
+ params.maxElements,
+ params.maxLevel
+ );
+
+ // Inserting graph nodes into the tree
+ for (var i = 0, l = nodes.length; i < l; i++) {
+
+ // Inserting node
+ _quadInsert(
+ nodes[i],
+ _geom.pointToSquare({
+ x: nodes[i][prefix + 'x'],
+ y: nodes[i][prefix + 'y'],
+ size: nodes[i][prefix + 'size']
+ }),
+ this._tree
+ );
+ }
+
+ // Reset cache:
+ this._cache = {
+ query: false,
+ result: false
+ };
+
+ // remove?
+ return this._tree;
+ };
+
+ /**
+ * Retrieve every graph nodes held by the quadtree node containing the
+ * searched point.
+ *
+ * @param {number} x of the point.
+ * @param {number} y of the point.
+ * @return {array} An array of nodes retrieved.
+ */
+ quad.prototype.point = function(x, y) {
+ return this._tree ?
+ _quadRetrievePoint({x: x, y: y}, this._tree) || [] :
+ [];
+ };
+
+ /**
+ * Retrieve every graph nodes within a rectangular area. The methods keep the
+ * last area queried in cache for optimization reason and will act differently
+ * for the same reason if the area is axis-aligned or not.
+ *
+ * @param {object} A rectangle defined by two top points (x1, y1), (x2, y2)
+ * and height.
+ * @return {array} An array of nodes retrieved.
+ */
+ quad.prototype.area = function(rect) {
+ var serialized = JSON.stringify(rect),
+ collisionFunc,
+ rectData;
+
+ // Returning cache?
+ if (this._cache.query === serialized)
+ return this._cache.result;
+
+ // Axis aligned ?
+ if (_geom.isAxisAligned(rect)) {
+ collisionFunc = _quadIndexes;
+ rectData = _geom.axisAlignedTopPoints(rect);
+ }
+ else {
+ collisionFunc = _quadCollision;
+ rectData = _geom.rectangleCorners(rect);
+ }
+
+ // Retrieving nodes
+ var nodes = this._tree ?
+ _quadRetrieveArea(
+ rectData,
+ this._tree,
+ collisionFunc
+ ) :
+ [];
+
+ // Object to array
+ var nodesArray = [];
+ for (var i in nodes)
+ nodesArray.push(nodes[i]);
+
+ // Caching
+ this._cache.query = serialized;
+ this._cache.result = nodesArray;
+
+ return nodesArray;
+ };
+
+
+ /**
+ * EXPORT:
+ * *******
+ */
+ if (typeof this.sigma !== 'undefined') {
+ this.sigma.classes = this.sigma.classes || {};
+ this.sigma.classes.quad = quad;
+ } else if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = quad;
+ exports.quad = quad;
+ } else
+ this.quad = quad;
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ /**
+ * Sigma Quadtree Module for edges
+ * ===============================
+ *
+ * Author: Sébastien Heymann,
+ * from the quad of Guillaume Plique (Yomguithereal)
+ * Version: 0.2
+ */
+
+
+
+ /**
+ * Quad Geometric Operations
+ * -------------------------
+ *
+ * A useful batch of geometric operations used by the quadtree.
+ */
+
+ var _geom = {
+
+ /**
+ * Transforms a graph node with x, y and size into an
+ * axis-aligned square.
+ *
+ * @param {object} A graph node with at least a point (x, y) and a size.
+ * @return {object} A square: two points (x1, y1), (x2, y2) and height.
+ */
+ pointToSquare: function(n) {
+ return {
+ x1: n.x - n.size,
+ y1: n.y - n.size,
+ x2: n.x + n.size,
+ y2: n.y - n.size,
+ height: n.size * 2
+ };
+ },
+
+ /**
+ * Transforms a graph edge with x1, y1, x2, y2 and size into an
+ * axis-aligned square.
+ *
+ * @param {object} A graph edge with at least two points
+ * (x1, y1), (x2, y2) and a size.
+ * @return {object} A square: two points (x1, y1), (x2, y2) and height.
+ */
+ lineToSquare: function(e) {
+ if (e.y1 < e.y2) {
+ // (e.x1, e.y1) on top
+ if (e.x1 < e.x2) {
+ // (e.x1, e.y1) on left
+ return {
+ x1: e.x1 - e.size,
+ y1: e.y1 - e.size,
+ x2: e.x2 + e.size,
+ y2: e.y1 - e.size,
+ height: e.y2 - e.y1 + e.size * 2
+ };
+ }
+ // (e.x1, e.y1) on right
+ return {
+ x1: e.x2 - e.size,
+ y1: e.y1 - e.size,
+ x2: e.x1 + e.size,
+ y2: e.y1 - e.size,
+ height: e.y2 - e.y1 + e.size * 2
+ };
+ }
+
+ // (e.x2, e.y2) on top
+ if (e.x1 < e.x2) {
+ // (e.x1, e.y1) on left
+ return {
+ x1: e.x1 - e.size,
+ y1: e.y2 - e.size,
+ x2: e.x2 + e.size,
+ y2: e.y2 - e.size,
+ height: e.y1 - e.y2 + e.size * 2
+ };
+ }
+ // (e.x2, e.y2) on right
+ return {
+ x1: e.x2 - e.size,
+ y1: e.y2 - e.size,
+ x2: e.x1 + e.size,
+ y2: e.y2 - e.size,
+ height: e.y1 - e.y2 + e.size * 2
+ };
+ },
+
+ /**
+ * Transforms a graph edge of type 'curve' with x1, y1, x2, y2,
+ * control point and size into an axis-aligned square.
+ *
+ * @param {object} e A graph edge with at least two points
+ * (x1, y1), (x2, y2) and a size.
+ * @param {object} cp A control point (x,y).
+ * @return {object} A square: two points (x1, y1), (x2, y2) and height.
+ */
+ quadraticCurveToSquare: function(e, cp) {
+ var pt = sigma.utils.getPointOnQuadraticCurve(
+ 0.5,
+ e.x1,
+ e.y1,
+ e.x2,
+ e.y2,
+ cp.x,
+ cp.y
+ );
+
+ // Bounding box of the two points and the point at the middle of the
+ // curve:
+ var minX = Math.min(e.x1, e.x2, pt.x),
+ maxX = Math.max(e.x1, e.x2, pt.x),
+ minY = Math.min(e.y1, e.y2, pt.y),
+ maxY = Math.max(e.y1, e.y2, pt.y);
+
+ return {
+ x1: minX - e.size,
+ y1: minY - e.size,
+ x2: maxX + e.size,
+ y2: minY - e.size,
+ height: maxY - minY + e.size * 2
+ };
+ },
+
+ /**
+ * Transforms a graph self loop into an axis-aligned square.
+ *
+ * @param {object} n A graph node with a point (x, y) and a size.
+ * @return {object} A square: two points (x1, y1), (x2, y2) and height.
+ */
+ selfLoopToSquare: function(n) {
+ // Fitting to the curve is too costly, we compute a larger bounding box
+ // using the control points:
+ var cp = sigma.utils.getSelfLoopControlPoints(n.x, n.y, n.size);
+
+ // Bounding box of the point and the two control points:
+ var minX = Math.min(n.x, cp.x1, cp.x2),
+ maxX = Math.max(n.x, cp.x1, cp.x2),
+ minY = Math.min(n.y, cp.y1, cp.y2),
+ maxY = Math.max(n.y, cp.y1, cp.y2);
+
+ return {
+ x1: minX - n.size,
+ y1: minY - n.size,
+ x2: maxX + n.size,
+ y2: minY - n.size,
+ height: maxY - minY + n.size * 2
+ };
+ },
+
+ /**
+ * Checks whether a rectangle is axis-aligned.
+ *
+ * @param {object} A rectangle defined by two points
+ * (x1, y1) and (x2, y2).
+ * @return {boolean} True if the rectangle is axis-aligned.
+ */
+ isAxisAligned: function(r) {
+ return r.x1 === r.x2 || r.y1 === r.y2;
+ },
+
+ /**
+ * Compute top points of an axis-aligned rectangle. This is useful in
+ * cases when the rectangle has been rotated (left, right or bottom up) and
+ * later operations need to know the top points.
+ *
+ * @param {object} An axis-aligned rectangle defined by two points
+ * (x1, y1), (x2, y2) and height.
+ * @return {object} A rectangle: two points (x1, y1), (x2, y2) and height.
+ */
+ axisAlignedTopPoints: function(r) {
+
+ // Basic
+ if (r.y1 === r.y2 && r.x1 < r.x2)
+ return r;
+
+ // Rotated to right
+ if (r.x1 === r.x2 && r.y2 > r.y1)
+ return {
+ x1: r.x1 - r.height, y1: r.y1,
+ x2: r.x1, y2: r.y1,
+ height: r.height
+ };
+
+ // Rotated to left
+ if (r.x1 === r.x2 && r.y2 < r.y1)
+ return {
+ x1: r.x1, y1: r.y2,
+ x2: r.x2 + r.height, y2: r.y2,
+ height: r.height
+ };
+
+ // Bottom's up
+ return {
+ x1: r.x2, y1: r.y1 - r.height,
+ x2: r.x1, y2: r.y1 - r.height,
+ height: r.height
+ };
+ },
+
+ /**
+ * Get coordinates of a rectangle's lower left corner from its top points.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @return {object} Coordinates of the corner (x, y).
+ */
+ lowerLeftCoor: function(r) {
+ var width = (
+ Math.sqrt(
+ Math.pow(r.x2 - r.x1, 2) +
+ Math.pow(r.y2 - r.y1, 2)
+ )
+ );
+
+ return {
+ x: r.x1 - (r.y2 - r.y1) * r.height / width,
+ y: r.y1 + (r.x2 - r.x1) * r.height / width
+ };
+ },
+
+ /**
+ * Get coordinates of a rectangle's lower right corner from its top points
+ * and its lower left corner.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @param {object} A corner's coordinates (x, y).
+ * @return {object} Coordinates of the corner (x, y).
+ */
+ lowerRightCoor: function(r, llc) {
+ return {
+ x: llc.x - r.x1 + r.x2,
+ y: llc.y - r.y1 + r.y2
+ };
+ },
+
+ /**
+ * Get the coordinates of all the corners of a rectangle from its top point.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @return {array} An array of the four corners' coordinates (x, y).
+ */
+ rectangleCorners: function(r) {
+ var llc = this.lowerLeftCoor(r),
+ lrc = this.lowerRightCoor(r, llc);
+
+ return [
+ {x: r.x1, y: r.y1},
+ {x: r.x2, y: r.y2},
+ {x: llc.x, y: llc.y},
+ {x: lrc.x, y: lrc.y}
+ ];
+ },
+
+ /**
+ * Split a square defined by its boundaries into four.
+ *
+ * @param {object} Boundaries of the square (x, y, width, height).
+ * @return {array} An array containing the four new squares, themselves
+ * defined by an array of their four corners (x, y).
+ */
+ splitSquare: function(b) {
+ return [
+ [
+ {x: b.x, y: b.y},
+ {x: b.x + b.width / 2, y: b.y},
+ {x: b.x, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2}
+ ],
+ [
+ {x: b.x + b.width / 2, y: b.y},
+ {x: b.x + b.width, y: b.y},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x + b.width, y: b.y + b.height / 2}
+ ],
+ [
+ {x: b.x, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x, y: b.y + b.height},
+ {x: b.x + b.width / 2, y: b.y + b.height}
+ ],
+ [
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x + b.width, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height},
+ {x: b.x + b.width, y: b.y + b.height}
+ ]
+ ];
+ },
+
+ /**
+ * Compute the four axis between corners of rectangle A and corners of
+ * rectangle B. This is needed later to check an eventual collision.
+ *
+ * @param {array} An array of rectangle A's four corners (x, y).
+ * @param {array} An array of rectangle B's four corners (x, y).
+ * @return {array} An array of four axis defined by their coordinates (x,y).
+ */
+ axis: function(c1, c2) {
+ return [
+ {x: c1[1].x - c1[0].x, y: c1[1].y - c1[0].y},
+ {x: c1[1].x - c1[3].x, y: c1[1].y - c1[3].y},
+ {x: c2[0].x - c2[2].x, y: c2[0].y - c2[2].y},
+ {x: c2[0].x - c2[1].x, y: c2[0].y - c2[1].y}
+ ];
+ },
+
+ /**
+ * Project a rectangle's corner on an axis.
+ *
+ * @param {object} Coordinates of a corner (x, y).
+ * @param {object} Coordinates of an axis (x, y).
+ * @return {object} The projection defined by coordinates (x, y).
+ */
+ projection: function(c, a) {
+ var l = (
+ (c.x * a.x + c.y * a.y) /
+ (Math.pow(a.x, 2) + Math.pow(a.y, 2))
+ );
+
+ return {
+ x: l * a.x,
+ y: l * a.y
+ };
+ },
+
+ /**
+ * Check whether two rectangles collide on one particular axis.
+ *
+ * @param {object} An axis' coordinates (x, y).
+ * @param {array} Rectangle A's corners.
+ * @param {array} Rectangle B's corners.
+ * @return {boolean} True if the rectangles collide on the axis.
+ */
+ axisCollision: function(a, c1, c2) {
+ var sc1 = [],
+ sc2 = [];
+
+ for (var ci = 0; ci < 4; ci++) {
+ var p1 = this.projection(c1[ci], a),
+ p2 = this.projection(c2[ci], a);
+
+ sc1.push(p1.x * a.x + p1.y * a.y);
+ sc2.push(p2.x * a.x + p2.y * a.y);
+ }
+
+ var maxc1 = Math.max.apply(Math, sc1),
+ maxc2 = Math.max.apply(Math, sc2),
+ minc1 = Math.min.apply(Math, sc1),
+ minc2 = Math.min.apply(Math, sc2);
+
+ return (minc2 <= maxc1 && maxc2 >= minc1);
+ },
+
+ /**
+ * Check whether two rectangles collide on each one of their four axis. If
+ * all axis collide, then the two rectangles do collide on the plane.
+ *
+ * @param {array} Rectangle A's corners.
+ * @param {array} Rectangle B's corners.
+ * @return {boolean} True if the rectangles collide.
+ */
+ collision: function(c1, c2) {
+ var axis = this.axis(c1, c2),
+ col = true;
+
+ for (var i = 0; i < 4; i++)
+ col = col && this.axisCollision(axis[i], c1, c2);
+
+ return col;
+ }
+ };
+
+
+ /**
+ * Quad Functions
+ * ------------
+ *
+ * The Quadtree functions themselves.
+ * For each of those functions, we consider that in a splitted quad, the
+ * index of each node is the following:
+ * 0: top left
+ * 1: top right
+ * 2: bottom left
+ * 3: bottom right
+ *
+ * Moreover, the hereafter quad's philosophy is to consider that if an element
+ * collides with more than one nodes, this element belongs to each of the
+ * nodes it collides with where other would let it lie on a higher node.
+ */
+
+ /**
+ * Get the index of the node containing the point in the quad
+ *
+ * @param {object} point A point defined by coordinates (x, y).
+ * @param {object} quadBounds Boundaries of the quad (x, y, width, heigth).
+ * @return {integer} The index of the node containing the point.
+ */
+ function _quadIndex(point, quadBounds) {
+ var xmp = quadBounds.x + quadBounds.width / 2,
+ ymp = quadBounds.y + quadBounds.height / 2,
+ top = (point.y < ymp),
+ left = (point.x < xmp);
+
+ if (top) {
+ if (left)
+ return 0;
+ else
+ return 1;
+ }
+ else {
+ if (left)
+ return 2;
+ else
+ return 3;
+ }
+ }
+
+ /**
+ * Get a list of indexes of nodes containing an axis-aligned rectangle
+ *
+ * @param {object} rectangle A rectangle defined by two points (x1, y1),
+ * (x2, y2) and height.
+ * @param {array} quadCorners An array of the quad nodes' corners.
+ * @return {array} An array of indexes containing one to
+ * four integers.
+ */
+ function _quadIndexes(rectangle, quadCorners) {
+ var indexes = [];
+
+ // Iterating through quads
+ for (var i = 0; i < 4; i++)
+ if ((rectangle.x2 >= quadCorners[i][0].x) &&
+ (rectangle.x1 <= quadCorners[i][1].x) &&
+ (rectangle.y1 + rectangle.height >= quadCorners[i][0].y) &&
+ (rectangle.y1 <= quadCorners[i][2].y))
+ indexes.push(i);
+
+ return indexes;
+ }
+
+ /**
+ * Get a list of indexes of nodes containing a non-axis-aligned rectangle
+ *
+ * @param {array} corners An array containing each corner of the
+ * rectangle defined by its coordinates (x, y).
+ * @param {array} quadCorners An array of the quad nodes' corners.
+ * @return {array} An array of indexes containing one to
+ * four integers.
+ */
+ function _quadCollision(corners, quadCorners) {
+ var indexes = [];
+
+ // Iterating through quads
+ for (var i = 0; i < 4; i++)
+ if (_geom.collision(corners, quadCorners[i]))
+ indexes.push(i);
+
+ return indexes;
+ }
+
+ /**
+ * Subdivide a quad by creating a node at a precise index. The function does
+ * not generate all four nodes not to potentially create unused nodes.
+ *
+ * @param {integer} index The index of the node to create.
+ * @param {object} quad The quad object to subdivide.
+ * @return {object} A new quad representing the node created.
+ */
+ function _quadSubdivide(index, quad) {
+ var next = quad.level + 1,
+ subw = Math.round(quad.bounds.width / 2),
+ subh = Math.round(quad.bounds.height / 2),
+ qx = Math.round(quad.bounds.x),
+ qy = Math.round(quad.bounds.y),
+ x,
+ y;
+
+ switch (index) {
+ case 0:
+ x = qx;
+ y = qy;
+ break;
+ case 1:
+ x = qx + subw;
+ y = qy;
+ break;
+ case 2:
+ x = qx;
+ y = qy + subh;
+ break;
+ case 3:
+ x = qx + subw;
+ y = qy + subh;
+ break;
+ }
+
+ return _quadTree(
+ {x: x, y: y, width: subw, height: subh},
+ next,
+ quad.maxElements,
+ quad.maxLevel
+ );
+ }
+
+ /**
+ * Recursively insert an element into the quadtree. Only points
+ * with size, i.e. axis-aligned squares, may be inserted with this
+ * method.
+ *
+ * @param {object} el The element to insert in the quadtree.
+ * @param {object} sizedPoint A sized point defined by two top points
+ * (x1, y1), (x2, y2) and height.
+ * @param {object} quad The quad in which to insert the element.
+ * @return {undefined} The function does not return anything.
+ */
+ function _quadInsert(el, sizedPoint, quad) {
+ if (quad.level < quad.maxLevel) {
+
+ // Searching appropriate quads
+ var indexes = _quadIndexes(sizedPoint, quad.corners);
+
+ // Iterating
+ for (var i = 0, l = indexes.length; i < l; i++) {
+
+ // Subdividing if necessary
+ if (quad.nodes[indexes[i]] === undefined)
+ quad.nodes[indexes[i]] = _quadSubdivide(indexes[i], quad);
+
+ // Recursion
+ _quadInsert(el, sizedPoint, quad.nodes[indexes[i]]);
+ }
+ }
+ else {
+
+ // Pushing the element in a leaf node
+ quad.elements.push(el);
+ }
+ }
+
+ /**
+ * Recursively retrieve every elements held by the node containing the
+ * searched point.
+ *
+ * @param {object} point The searched point (x, y).
+ * @param {object} quad The searched quad.
+ * @return {array} An array of elements contained in the relevant
+ * node.
+ */
+ function _quadRetrievePoint(point, quad) {
+ if (quad.level < quad.maxLevel) {
+ var index = _quadIndex(point, quad.bounds);
+
+ // If node does not exist we return an empty list
+ if (quad.nodes[index] !== undefined) {
+ return _quadRetrievePoint(point, quad.nodes[index]);
+ }
+ else {
+ return [];
+ }
+ }
+ else {
+ return quad.elements;
+ }
+ }
+
+ /**
+ * Recursively retrieve every elements contained within an rectangular area
+ * that may or may not be axis-aligned.
+ *
+ * @param {object|array} rectData The searched area defined either by
+ * an array of four corners (x, y) in
+ * the case of a non-axis-aligned
+ * rectangle or an object with two top
+ * points (x1, y1), (x2, y2) and height.
+ * @param {object} quad The searched quad.
+ * @param {function} collisionFunc The collision function used to search
+ * for node indexes.
+ * @param {array?} els The retrieved elements.
+ * @return {array} An array of elements contained in the
+ * area.
+ */
+ function _quadRetrieveArea(rectData, quad, collisionFunc, els) {
+ els = els || {};
+
+ if (quad.level < quad.maxLevel) {
+ var indexes = collisionFunc(rectData, quad.corners);
+
+ for (var i = 0, l = indexes.length; i < l; i++)
+ if (quad.nodes[indexes[i]] !== undefined)
+ _quadRetrieveArea(
+ rectData,
+ quad.nodes[indexes[i]],
+ collisionFunc,
+ els
+ );
+ } else
+ for (var j = 0, m = quad.elements.length; j < m; j++)
+ if (els[quad.elements[j].id] === undefined)
+ els[quad.elements[j].id] = quad.elements[j];
+
+ return els;
+ }
+
+ /**
+ * Creates the quadtree object itself.
+ *
+ * @param {object} bounds The boundaries of the quad defined by an
+ * origin (x, y), width and heigth.
+ * @param {integer} level The level of the quad in the tree.
+ * @param {integer} maxElements The max number of element in a leaf node.
+ * @param {integer} maxLevel The max recursion level of the tree.
+ * @return {object} The quadtree object.
+ */
+ function _quadTree(bounds, level, maxElements, maxLevel) {
+ return {
+ level: level || 0,
+ bounds: bounds,
+ corners: _geom.splitSquare(bounds),
+ maxElements: maxElements || 40,
+ maxLevel: maxLevel || 8,
+ elements: [],
+ nodes: []
+ };
+ }
+
+
+ /**
+ * Sigma Quad Constructor
+ * ----------------------
+ *
+ * The edgequad API as exposed to sigma.
+ */
+
+ /**
+ * The edgequad core that will become the sigma interface with the quadtree.
+ *
+ * property {object} _tree Property holding the quadtree object.
+ * property {object} _geom Exposition of the _geom namespace for testing.
+ * property {object} _cache Cache for the area method.
+ * property {boolean} _enabled Can index and retreive elements.
+ */
+ var edgequad = function() {
+ this._geom = _geom;
+ this._tree = null;
+ this._cache = {
+ query: false,
+ result: false
+ };
+ this._enabled = true;
+ };
+
+ /**
+ * Index a graph by inserting its edges into the quadtree.
+ *
+ * @param {object} graph A graph instance.
+ * @param {object} params An object of parameters with at least the quad
+ * bounds.
+ * @return {object} The quadtree object.
+ *
+ * Parameters:
+ * ----------
+ * bounds: {object} boundaries of the quad defined by its origin (x, y)
+ * width and heigth.
+ * prefix: {string?} a prefix for edge geometric attributes.
+ * maxElements: {integer?} the max number of elements in a leaf node.
+ * maxLevel: {integer?} the max recursion level of the tree.
+ */
+ edgequad.prototype.index = function(graph, params) {
+ if (!this._enabled)
+ return this._tree;
+
+ // Enforcing presence of boundaries
+ if (!params.bounds)
+ throw 'sigma.classes.edgequad.index: bounds information not given.';
+
+ // Prefix
+ var prefix = params.prefix || '',
+ cp,
+ source,
+ target,
+ n,
+ e;
+
+ // Building the tree
+ this._tree = _quadTree(
+ params.bounds,
+ 0,
+ params.maxElements,
+ params.maxLevel
+ );
+
+ var edges = graph.edges();
+
+ // Inserting graph edges into the tree
+ for (var i = 0, l = edges.length; i < l; i++) {
+ source = graph.nodes(edges[i].source);
+ target = graph.nodes(edges[i].target);
+ e = {
+ x1: source[prefix + 'x'],
+ y1: source[prefix + 'y'],
+ x2: target[prefix + 'x'],
+ y2: target[prefix + 'y'],
+ size: edges[i][prefix + 'size'] || 0
+ };
+
+ // Inserting edge
+ if (edges[i].type === 'curve' || edges[i].type === 'curvedArrow') {
+ if (source.id === target.id) {
+ n = {
+ x: source[prefix + 'x'],
+ y: source[prefix + 'y'],
+ size: source[prefix + 'size'] || 0
+ };
+ _quadInsert(
+ edges[i],
+ _geom.selfLoopToSquare(n),
+ this._tree);
+ }
+ else {
+ cp = sigma.utils.getQuadraticControlPoint(e.x1, e.y1, e.x2, e.y2);
+ _quadInsert(
+ edges[i],
+ _geom.quadraticCurveToSquare(e, cp),
+ this._tree);
+ }
+ }
+ else {
+ _quadInsert(
+ edges[i],
+ _geom.lineToSquare(e),
+ this._tree);
+ }
+ }
+
+ // Reset cache:
+ this._cache = {
+ query: false,
+ result: false
+ };
+
+ // remove?
+ return this._tree;
+ };
+
+ /**
+ * Retrieve every graph edges held by the quadtree node containing the
+ * searched point.
+ *
+ * @param {number} x of the point.
+ * @param {number} y of the point.
+ * @return {array} An array of edges retrieved.
+ */
+ edgequad.prototype.point = function(x, y) {
+ if (!this._enabled)
+ return [];
+
+ return this._tree ?
+ _quadRetrievePoint({x: x, y: y}, this._tree) || [] :
+ [];
+ };
+
+ /**
+ * Retrieve every graph edges within a rectangular area. The methods keep the
+ * last area queried in cache for optimization reason and will act differently
+ * for the same reason if the area is axis-aligned or not.
+ *
+ * @param {object} A rectangle defined by two top points (x1, y1), (x2, y2)
+ * and height.
+ * @return {array} An array of edges retrieved.
+ */
+ edgequad.prototype.area = function(rect) {
+ if (!this._enabled)
+ return [];
+
+ var serialized = JSON.stringify(rect),
+ collisionFunc,
+ rectData;
+
+ // Returning cache?
+ if (this._cache.query === serialized)
+ return this._cache.result;
+
+ // Axis aligned ?
+ if (_geom.isAxisAligned(rect)) {
+ collisionFunc = _quadIndexes;
+ rectData = _geom.axisAlignedTopPoints(rect);
+ }
+ else {
+ collisionFunc = _quadCollision;
+ rectData = _geom.rectangleCorners(rect);
+ }
+
+ // Retrieving edges
+ var edges = this._tree ?
+ _quadRetrieveArea(
+ rectData,
+ this._tree,
+ collisionFunc
+ ) :
+ [];
+
+ // Object to array
+ var edgesArray = [];
+ for (var i in edges)
+ edgesArray.push(edges[i]);
+
+ // Caching
+ this._cache.query = serialized;
+ this._cache.result = edgesArray;
+
+ return edgesArray;
+ };
+
+
+ /**
+ * EXPORT:
+ * *******
+ */
+ if (typeof this.sigma !== 'undefined') {
+ this.sigma.classes = this.sigma.classes || {};
+ this.sigma.classes.edgequad = edgequad;
+ } else if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = edgequad;
+ exports.edgequad = edgequad;
+ } else
+ this.edgequad = edgequad;
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.captors');
+
+ /**
+ * The user inputs default captor. It deals with mouse events, keyboards
+ * events and touch events.
+ *
+ * @param {DOMElement} target The DOM element where the listeners will be
+ * bound.
+ * @param {camera} camera The camera related to the target.
+ * @param {configurable} settings The settings function.
+ * @return {sigma.captor} The fresh new captor instance.
+ */
+ sigma.captors.mouse = function(target, camera, settings) {
+ var _self = this,
+ _target = target,
+ _camera = camera,
+ _settings = settings,
+
+ // CAMERA MANAGEMENT:
+ // ******************
+ // The camera position when the user starts dragging:
+ _startCameraX,
+ _startCameraY,
+ _startCameraAngle,
+
+ // The latest stage position:
+ _lastCameraX,
+ _lastCameraY,
+ _lastCameraAngle,
+ _lastCameraRatio,
+
+ // MOUSE MANAGEMENT:
+ // *****************
+ // The mouse position when the user starts dragging:
+ _startMouseX,
+ _startMouseY,
+
+ _isMouseDown,
+ _isMoving,
+ _hasDragged,
+ _downStartTime,
+ _movingTimeoutId;
+
+ sigma.classes.dispatcher.extend(this);
+
+ sigma.utils.doubleClick(_target, 'click', _doubleClickHandler);
+ _target.addEventListener('DOMMouseScroll', _wheelHandler, false);
+ _target.addEventListener('mousewheel', _wheelHandler, false);
+ _target.addEventListener('mousemove', _moveHandler, false);
+ _target.addEventListener('mousedown', _downHandler, false);
+ _target.addEventListener('click', _clickHandler, false);
+ _target.addEventListener('mouseout', _outHandler, false);
+ document.addEventListener('mouseup', _upHandler, false);
+
+
+
+
+ /**
+ * This method unbinds every handlers that makes the captor work.
+ */
+ this.kill = function() {
+ sigma.utils.unbindDoubleClick(_target, 'click');
+ _target.removeEventListener('DOMMouseScroll', _wheelHandler);
+ _target.removeEventListener('mousewheel', _wheelHandler);
+ _target.removeEventListener('mousemove', _moveHandler);
+ _target.removeEventListener('mousedown', _downHandler);
+ _target.removeEventListener('click', _clickHandler);
+ _target.removeEventListener('mouseout', _outHandler);
+ document.removeEventListener('mouseup', _upHandler);
+ };
+
+
+
+
+ // MOUSE EVENTS:
+ // *************
+
+ /**
+ * The handler listening to the 'move' mouse event. It will effectively
+ * drag the graph.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _moveHandler(e) {
+ var x,
+ y,
+ pos;
+
+ // Dispatch event:
+ if (_settings('mouseEnabled')) {
+ _self.dispatchEvent('mousemove',
+ sigma.utils.mouseCoords(e));
+
+ if (_isMouseDown) {
+ _isMoving = true;
+ _hasDragged = true;
+
+ if (_movingTimeoutId)
+ clearTimeout(_movingTimeoutId);
+
+ _movingTimeoutId = setTimeout(function() {
+ _isMoving = false;
+ }, _settings('dragTimeout'));
+
+ sigma.misc.animation.killAll(_camera);
+
+ _camera.isMoving = true;
+ pos = _camera.cameraPosition(
+ sigma.utils.getX(e) - _startMouseX,
+ sigma.utils.getY(e) - _startMouseY,
+ true
+ );
+
+ x = _startCameraX - pos.x;
+ y = _startCameraY - pos.y;
+
+ if (x !== _camera.x || y !== _camera.y) {
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+
+ _camera.goTo({
+ x: x,
+ y: y
+ });
+ }
+
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+
+ e.stopPropagation();
+ return false;
+ }
+ }
+ }
+
+ /**
+ * The handler listening to the 'up' mouse event. It will stop dragging the
+ * graph.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _upHandler(e) {
+ if (_settings('mouseEnabled') && _isMouseDown) {
+ _isMouseDown = false;
+ if (_movingTimeoutId)
+ clearTimeout(_movingTimeoutId);
+
+ _camera.isMoving = false;
+
+ var x = sigma.utils.getX(e),
+ y = sigma.utils.getY(e);
+
+ if (_isMoving) {
+ sigma.misc.animation.killAll(_camera);
+ sigma.misc.animation.camera(
+ _camera,
+ {
+ x: _camera.x +
+ _settings('mouseInertiaRatio') * (_camera.x - _lastCameraX),
+ y: _camera.y +
+ _settings('mouseInertiaRatio') * (_camera.y - _lastCameraY)
+ },
+ {
+ easing: 'quadraticOut',
+ duration: _settings('mouseInertiaDuration')
+ }
+ );
+ } else if (
+ _startMouseX !== x ||
+ _startMouseY !== y
+ )
+ _camera.goTo({
+ x: _camera.x,
+ y: _camera.y
+ });
+
+ _self.dispatchEvent('mouseup',
+ sigma.utils.mouseCoords(e));
+
+ // Update _isMoving flag:
+ _isMoving = false;
+ }
+ }
+
+ /**
+ * The handler listening to the 'down' mouse event. It will start observing
+ * the mouse position for dragging the graph.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _downHandler(e) {
+ if (_settings('mouseEnabled')) {
+ _startCameraX = _camera.x;
+ _startCameraY = _camera.y;
+
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+
+ _startMouseX = sigma.utils.getX(e);
+ _startMouseY = sigma.utils.getY(e);
+
+ _hasDragged = false;
+ _downStartTime = (new Date()).getTime();
+
+ switch (e.which) {
+ case 2:
+ // Middle mouse button pressed
+ // Do nothing.
+ break;
+ case 3:
+ // Right mouse button pressed
+ _self.dispatchEvent('rightclick',
+ sigma.utils.mouseCoords(e, _startMouseX, _startMouseY));
+ break;
+ // case 1:
+ default:
+ // Left mouse button pressed
+ _isMouseDown = true;
+
+ _self.dispatchEvent('mousedown',
+ sigma.utils.mouseCoords(e, _startMouseX, _startMouseY));
+ }
+ }
+ }
+
+ /**
+ * The handler listening to the 'out' mouse event. It will just redispatch
+ * the event.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _outHandler(e) {
+ if (_settings('mouseEnabled'))
+ _self.dispatchEvent('mouseout');
+ }
+
+ /**
+ * The handler listening to the 'click' mouse event. It will redispatch the
+ * click event, but with normalized X and Y coordinates.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _clickHandler(e) {
+ if (_settings('mouseEnabled')) {
+ var event = sigma.utils.mouseCoords(e);
+ event.isDragging =
+ (((new Date()).getTime() - _downStartTime) > 100) && _hasDragged;
+ _self.dispatchEvent('click', event);
+ }
+
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+
+ e.stopPropagation();
+ return false;
+ }
+
+ /**
+ * The handler listening to the double click custom event. It will
+ * basically zoom into the graph.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _doubleClickHandler(e) {
+ var pos,
+ ratio,
+ animation;
+
+ if (_settings('mouseEnabled')) {
+ ratio = 1 / _settings('doubleClickZoomingRatio');
+
+ _self.dispatchEvent('doubleclick',
+ sigma.utils.mouseCoords(e, _startMouseX, _startMouseY));
+
+ if (_settings('doubleClickEnabled')) {
+ pos = _camera.cameraPosition(
+ sigma.utils.getX(e) - sigma.utils.getCenter(e).x,
+ sigma.utils.getY(e) - sigma.utils.getCenter(e).y,
+ true
+ );
+
+ animation = {
+ duration: _settings('doubleClickZoomDuration')
+ };
+
+ sigma.utils.zoomTo(_camera, pos.x, pos.y, ratio, animation);
+ }
+
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+
+ e.stopPropagation();
+ return false;
+ }
+ }
+
+ /**
+ * The handler listening to the 'wheel' mouse event. It will basically zoom
+ * in or not into the graph.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _wheelHandler(e) {
+ var pos,
+ ratio,
+ animation;
+
+ if (_settings('mouseEnabled') && _settings('mouseWheelEnabled')) {
+ ratio = sigma.utils.getDelta(e) > 0 ?
+ 1 / _settings('zoomingRatio') :
+ _settings('zoomingRatio');
+
+ pos = _camera.cameraPosition(
+ sigma.utils.getX(e) - sigma.utils.getCenter(e).x,
+ sigma.utils.getY(e) - sigma.utils.getCenter(e).y,
+ true
+ );
+
+ animation = {
+ duration: _settings('mouseZoomDuration')
+ };
+
+ sigma.utils.zoomTo(_camera, pos.x, pos.y, ratio, animation);
+
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+
+ e.stopPropagation();
+ return false;
+ }
+ }
+ };
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.captors');
+
+ /**
+ * The user inputs default captor. It deals with mouse events, keyboards
+ * events and touch events.
+ *
+ * @param {DOMElement} target The DOM element where the listeners will be
+ * bound.
+ * @param {camera} camera The camera related to the target.
+ * @param {configurable} settings The settings function.
+ * @return {sigma.captor} The fresh new captor instance.
+ */
+ sigma.captors.touch = function(target, camera, settings) {
+ var _self = this,
+ _target = target,
+ _camera = camera,
+ _settings = settings,
+
+ // CAMERA MANAGEMENT:
+ // ******************
+ // The camera position when the user starts dragging:
+ _startCameraX,
+ _startCameraY,
+ _startCameraAngle,
+ _startCameraRatio,
+
+ // The latest stage position:
+ _lastCameraX,
+ _lastCameraY,
+ _lastCameraAngle,
+ _lastCameraRatio,
+
+ // TOUCH MANAGEMENT:
+ // *****************
+ // Touches that are down:
+ _downTouches = [],
+
+ _startTouchX0,
+ _startTouchY0,
+ _startTouchX1,
+ _startTouchY1,
+ _startTouchAngle,
+ _startTouchDistance,
+
+ _touchMode,
+
+ _isMoving,
+ _doubleTap,
+ _movingTimeoutId;
+
+ sigma.classes.dispatcher.extend(this);
+
+ sigma.utils.doubleClick(_target, 'touchstart', _doubleTapHandler);
+ _target.addEventListener('touchstart', _handleStart, false);
+ _target.addEventListener('touchend', _handleLeave, false);
+ _target.addEventListener('touchcancel', _handleLeave, false);
+ _target.addEventListener('touchleave', _handleLeave, false);
+ _target.addEventListener('touchmove', _handleMove, false);
+
+ function position(e) {
+ var offset = sigma.utils.getOffset(_target);
+
+ return {
+ x: e.pageX - offset.left,
+ y: e.pageY - offset.top
+ };
+ }
+
+ /**
+ * This method unbinds every handlers that makes the captor work.
+ */
+ this.kill = function() {
+ sigma.utils.unbindDoubleClick(_target, 'touchstart');
+ _target.addEventListener('touchstart', _handleStart);
+ _target.addEventListener('touchend', _handleLeave);
+ _target.addEventListener('touchcancel', _handleLeave);
+ _target.addEventListener('touchleave', _handleLeave);
+ _target.addEventListener('touchmove', _handleMove);
+ };
+
+ // TOUCH EVENTS:
+ // *************
+ /**
+ * The handler listening to the 'touchstart' event. It will set the touch
+ * mode ("_touchMode") and start observing the user touch moves.
+ *
+ * @param {event} e A touch event.
+ */
+ function _handleStart(e) {
+ if (_settings('touchEnabled')) {
+ var x0,
+ x1,
+ y0,
+ y1,
+ pos0,
+ pos1;
+
+ _downTouches = e.touches;
+
+ switch (_downTouches.length) {
+ case 1:
+ _camera.isMoving = true;
+ _touchMode = 1;
+
+ _startCameraX = _camera.x;
+ _startCameraY = _camera.y;
+
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+
+ pos0 = position(_downTouches[0]);
+ _startTouchX0 = pos0.x;
+ _startTouchY0 = pos0.y;
+
+ break;
+ case 2:
+ _camera.isMoving = true;
+ _touchMode = 2;
+
+ pos0 = position(_downTouches[0]);
+ pos1 = position(_downTouches[1]);
+ x0 = pos0.x;
+ y0 = pos0.y;
+ x1 = pos1.x;
+ y1 = pos1.y;
+
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+
+ _startCameraAngle = _camera.angle;
+ _startCameraRatio = _camera.ratio;
+
+ _startCameraX = _camera.x;
+ _startCameraY = _camera.y;
+
+ _startTouchX0 = x0;
+ _startTouchY0 = y0;
+ _startTouchX1 = x1;
+ _startTouchY1 = y1;
+
+ _startTouchAngle = Math.atan2(
+ _startTouchY1 - _startTouchY0,
+ _startTouchX1 - _startTouchX0
+ );
+ _startTouchDistance = Math.sqrt(
+ (_startTouchY1 - _startTouchY0) *
+ (_startTouchY1 - _startTouchY0) +
+ (_startTouchX1 - _startTouchX0) *
+ (_startTouchX1 - _startTouchX0)
+ );
+
+ e.preventDefault();
+ return false;
+ }
+ }
+ }
+
+ /**
+ * The handler listening to the 'touchend', 'touchcancel' and 'touchleave'
+ * event. It will update the touch mode if there are still at least one
+ * finger, and stop dragging else.
+ *
+ * @param {event} e A touch event.
+ */
+ function _handleLeave(e) {
+ if (_settings('touchEnabled')) {
+ _downTouches = e.touches;
+ var inertiaRatio = _settings('touchInertiaRatio');
+
+ if (_movingTimeoutId) {
+ _isMoving = false;
+ clearTimeout(_movingTimeoutId);
+ }
+
+ switch (_touchMode) {
+ case 2:
+ if (e.touches.length === 1) {
+ _handleStart(e);
+
+ e.preventDefault();
+ break;
+ }
+ /* falls through */
+ case 1:
+ _camera.isMoving = false;
+ _self.dispatchEvent('stopDrag');
+
+ if (_isMoving) {
+ _doubleTap = false;
+ sigma.misc.animation.camera(
+ _camera,
+ {
+ x: _camera.x +
+ inertiaRatio * (_camera.x - _lastCameraX),
+ y: _camera.y +
+ inertiaRatio * (_camera.y - _lastCameraY)
+ },
+ {
+ easing: 'quadraticOut',
+ duration: _settings('touchInertiaDuration')
+ }
+ );
+ }
+
+ _isMoving = false;
+ _touchMode = 0;
+ break;
+ }
+ }
+ }
+
+ /**
+ * The handler listening to the 'touchmove' event. It will effectively drag
+ * the graph, and eventually zooms and turn it if the user is using two
+ * fingers.
+ *
+ * @param {event} e A touch event.
+ */
+ function _handleMove(e) {
+ if (!_doubleTap && _settings('touchEnabled')) {
+ var x0,
+ x1,
+ y0,
+ y1,
+ cos,
+ sin,
+ end,
+ pos0,
+ pos1,
+ diff,
+ start,
+ dAngle,
+ dRatio,
+ newStageX,
+ newStageY,
+ newStageRatio,
+ newStageAngle;
+
+ _downTouches = e.touches;
+ _isMoving = true;
+
+ if (_movingTimeoutId)
+ clearTimeout(_movingTimeoutId);
+
+ _movingTimeoutId = setTimeout(function() {
+ _isMoving = false;
+ }, _settings('dragTimeout'));
+
+ switch (_touchMode) {
+ case 1:
+ pos0 = position(_downTouches[0]);
+ x0 = pos0.x;
+ y0 = pos0.y;
+
+ diff = _camera.cameraPosition(
+ x0 - _startTouchX0,
+ y0 - _startTouchY0,
+ true
+ );
+
+ newStageX = _startCameraX - diff.x;
+ newStageY = _startCameraY - diff.y;
+
+ if (newStageX !== _camera.x || newStageY !== _camera.y) {
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+
+ _camera.goTo({
+ x: newStageX,
+ y: newStageY
+ });
+
+ _self.dispatchEvent('mousemove',
+ sigma.utils.mouseCoords(e, pos0.x, pos0.y));
+
+ _self.dispatchEvent('drag');
+ }
+ break;
+ case 2:
+ pos0 = position(_downTouches[0]);
+ pos1 = position(_downTouches[1]);
+ x0 = pos0.x;
+ y0 = pos0.y;
+ x1 = pos1.x;
+ y1 = pos1.y;
+
+ start = _camera.cameraPosition(
+ (_startTouchX0 + _startTouchX1) / 2 -
+ sigma.utils.getCenter(e).x,
+ (_startTouchY0 + _startTouchY1) / 2 -
+ sigma.utils.getCenter(e).y,
+ true
+ );
+ end = _camera.cameraPosition(
+ (x0 + x1) / 2 - sigma.utils.getCenter(e).x,
+ (y0 + y1) / 2 - sigma.utils.getCenter(e).y,
+ true
+ );
+
+ dAngle = Math.atan2(y1 - y0, x1 - x0) - _startTouchAngle;
+ dRatio = Math.sqrt(
+ (y1 - y0) * (y1 - y0) + (x1 - x0) * (x1 - x0)
+ ) / _startTouchDistance;
+
+ // Translation:
+ x0 = start.x;
+ y0 = start.y;
+
+ // Homothetic transformation:
+ newStageRatio = _startCameraRatio / dRatio;
+ x0 = x0 * dRatio;
+ y0 = y0 * dRatio;
+
+ // Rotation:
+ newStageAngle = _startCameraAngle - dAngle;
+ cos = Math.cos(-dAngle);
+ sin = Math.sin(-dAngle);
+ x1 = x0 * cos + y0 * sin;
+ y1 = y0 * cos - x0 * sin;
+ x0 = x1;
+ y0 = y1;
+
+ // Finalize:
+ newStageX = x0 - end.x + _startCameraX;
+ newStageY = y0 - end.y + _startCameraY;
+
+ if (
+ newStageRatio !== _camera.ratio ||
+ newStageAngle !== _camera.angle ||
+ newStageX !== _camera.x ||
+ newStageY !== _camera.y
+ ) {
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+ _lastCameraAngle = _camera.angle;
+ _lastCameraRatio = _camera.ratio;
+
+ _camera.goTo({
+ x: newStageX,
+ y: newStageY,
+ angle: newStageAngle,
+ ratio: newStageRatio
+ });
+
+ _self.dispatchEvent('drag');
+ }
+
+ break;
+ }
+
+ e.preventDefault();
+ return false;
+ }
+ }
+
+ /**
+ * The handler listening to the double tap custom event. It will
+ * basically zoom into the graph.
+ *
+ * @param {event} e A touch event.
+ */
+ function _doubleTapHandler(e) {
+ var pos,
+ ratio,
+ animation;
+
+ if (e.touches && e.touches.length === 1 && _settings('touchEnabled')) {
+ _doubleTap = true;
+
+ ratio = 1 / _settings('doubleClickZoomingRatio');
+
+ pos = position(e.touches[0]);
+ _self.dispatchEvent('doubleclick',
+ sigma.utils.mouseCoords(e, pos.x, pos.y));
+
+ if (_settings('doubleClickEnabled')) {
+ pos = _camera.cameraPosition(
+ pos.x - sigma.utils.getCenter(e).x,
+ pos.y - sigma.utils.getCenter(e).y,
+ true
+ );
+
+ animation = {
+ duration: _settings('doubleClickZoomDuration'),
+ onComplete: function() {
+ _doubleTap = false;
+ }
+ };
+
+ sigma.utils.zoomTo(_camera, pos.x, pos.y, ratio, animation);
+ }
+
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+
+ e.stopPropagation();
+ return false;
+ }
+ }
+ };
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ if (typeof conrad === 'undefined')
+ throw 'conrad is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.renderers');
+
+ /**
+ * This function is the constructor of the canvas sigma's renderer.
+ *
+ * @param {sigma.classes.graph} graph The graph to render.
+ * @param {sigma.classes.camera} camera The camera.
+ * @param {configurable} settings The sigma instance settings
+ * function.
+ * @param {object} object The options object.
+ * @return {sigma.renderers.canvas} The renderer instance.
+ */
+ sigma.renderers.canvas = function(graph, camera, settings, options) {
+ if (typeof options !== 'object')
+ throw 'sigma.renderers.canvas: Wrong arguments.';
+
+ if (!(options.container instanceof HTMLElement))
+ throw 'Container not found.';
+
+ var k,
+ i,
+ l,
+ a,
+ fn,
+ self = this;
+
+ sigma.classes.dispatcher.extend(this);
+
+ // Initialize main attributes:
+ Object.defineProperty(this, 'conradId', {
+ value: sigma.utils.id()
+ });
+ this.graph = graph;
+ this.camera = camera;
+ this.contexts = {};
+ this.domElements = {};
+ this.options = options;
+ this.container = this.options.container;
+ this.settings = (
+ typeof options.settings === 'object' &&
+ options.settings
+ ) ?
+ settings.embedObjects(options.settings) :
+ settings;
+
+ // Node indexes:
+ this.nodesOnScreen = [];
+ this.edgesOnScreen = [];
+
+ // Conrad related attributes:
+ this.jobs = {};
+
+ // Find the prefix:
+ this.options.prefix = 'renderer' + this.conradId + ':';
+
+ // Initialize the DOM elements:
+ if (
+ !this.settings('batchEdgesDrawing')
+ ) {
+ this.initDOM('canvas', 'scene');
+ this.contexts.edges = this.contexts.scene;
+ this.contexts.nodes = this.contexts.scene;
+ this.contexts.labels = this.contexts.scene;
+ } else {
+ this.initDOM('canvas', 'edges');
+ this.initDOM('canvas', 'scene');
+ this.contexts.nodes = this.contexts.scene;
+ this.contexts.labels = this.contexts.scene;
+ }
+
+ this.initDOM('canvas', 'mouse');
+ this.contexts.hover = this.contexts.mouse;
+
+ // Initialize captors:
+ this.captors = [];
+ a = this.options.captors || [sigma.captors.mouse, sigma.captors.touch];
+ for (i = 0, l = a.length; i < l; i++) {
+ fn = typeof a[i] === 'function' ? a[i] : sigma.captors[a[i]];
+ this.captors.push(
+ new fn(
+ this.domElements.mouse,
+ this.camera,
+ this.settings
+ )
+ );
+ }
+
+ // Deal with sigma events:
+ sigma.misc.bindEvents.call(this, this.options.prefix);
+ sigma.misc.drawHovers.call(this, this.options.prefix);
+
+ this.resize(false);
+ };
+
+
+
+
+ /**
+ * This method renders the graph on the canvases.
+ *
+ * @param {?object} options Eventually an object of options.
+ * @return {sigma.renderers.canvas} Returns the instance itself.
+ */
+ sigma.renderers.canvas.prototype.render = function(options) {
+ options = options || {};
+
+ var a,
+ i,
+ k,
+ l,
+ o,
+ id,
+ end,
+ job,
+ start,
+ edges,
+ renderers,
+ rendererType,
+ batchSize,
+ tempGCO,
+ index = {},
+ graph = this.graph,
+ nodes = this.graph.nodes,
+ prefix = this.options.prefix || '',
+ drawEdges = this.settings(options, 'drawEdges'),
+ drawNodes = this.settings(options, 'drawNodes'),
+ drawLabels = this.settings(options, 'drawLabels'),
+ drawEdgeLabels = this.settings(options, 'drawEdgeLabels'),
+ embedSettings = this.settings.embedObjects(options, {
+ prefix: this.options.prefix
+ });
+
+ // Call the resize function:
+ this.resize(false);
+
+ // Check the 'hideEdgesOnMove' setting:
+ if (this.settings(options, 'hideEdgesOnMove'))
+ if (this.camera.isAnimated || this.camera.isMoving)
+ drawEdges = false;
+
+ // Apply the camera's view:
+ this.camera.applyView(
+ undefined,
+ this.options.prefix,
+ {
+ width: this.width,
+ height: this.height
+ }
+ );
+
+ // Clear canvases:
+ this.clear();
+
+ // Kill running jobs:
+ for (k in this.jobs)
+ if (conrad.hasJob(k))
+ conrad.killJob(k);
+
+ // Find which nodes are on screen:
+ this.edgesOnScreen = [];
+ this.nodesOnScreen = this.camera.quadtree.area(
+ this.camera.getRectangle(this.width, this.height)
+ );
+
+ for (a = this.nodesOnScreen, i = 0, l = a.length; i < l; i++)
+ index[a[i].id] = a[i];
+
+ // Draw edges:
+ // - If settings('batchEdgesDrawing') is true, the edges are displayed per
+ // batches. If not, they are drawn in one frame.
+ if (drawEdges) {
+ // First, let's identify which edges to draw. To do this, we just keep
+ // every edges that have at least one extremity displayed according to
+ // the quadtree and the "hidden" attribute. We also do not keep hidden
+ // edges.
+ for (a = graph.edges(), i = 0, l = a.length; i < l; i++) {
+ o = a[i];
+ if (
+ (index[o.source] || index[o.target]) &&
+ (!o.hidden && !nodes(o.source).hidden && !nodes(o.target).hidden)
+ )
+ this.edgesOnScreen.push(o);
+ }
+
+ // If the "batchEdgesDrawing" settings is true, edges are batched:
+ if (this.settings(options, 'batchEdgesDrawing')) {
+ id = 'edges_' + this.conradId;
+ batchSize = embedSettings('canvasEdgesBatchSize');
+
+ edges = this.edgesOnScreen;
+ l = edges.length;
+
+ start = 0;
+ end = Math.min(edges.length, start + batchSize);
+
+ job = function() {
+ tempGCO = this.contexts.edges.globalCompositeOperation;
+ this.contexts.edges.globalCompositeOperation = 'destination-over';
+
+ renderers = sigma.canvas.edges;
+ for (i = start; i < end; i++) {
+ o = edges[i];
+ (renderers[
+ o.type || this.settings(options, 'defaultEdgeType')
+ ] || renderers.def)(
+ o,
+ graph.nodes(o.source),
+ graph.nodes(o.target),
+ this.contexts.edges,
+ embedSettings
+ );
+ }
+
+ // Draw edge labels:
+ if (drawEdgeLabels) {
+ renderers = sigma.canvas.edges.labels;
+ for (i = start; i < end; i++) {
+ o = edges[i];
+ if (!o.hidden)
+ (renderers[
+ o.type || this.settings(options, 'defaultEdgeType')
+ ] || renderers.def)(
+ o,
+ graph.nodes(o.source),
+ graph.nodes(o.target),
+ this.contexts.labels,
+ embedSettings
+ );
+ }
+ }
+
+ // Restore original globalCompositeOperation:
+ this.contexts.edges.globalCompositeOperation = tempGCO;
+
+ // Catch job's end:
+ if (end === edges.length) {
+ delete this.jobs[id];
+ return false;
+ }
+
+ start = end + 1;
+ end = Math.min(edges.length, start + batchSize);
+ return true;
+ };
+
+ this.jobs[id] = job;
+ conrad.addJob(id, job.bind(this));
+
+ // If not, they are drawn in one frame:
+ } else {
+ renderers = sigma.canvas.edges;
+ for (a = this.edgesOnScreen, i = 0, l = a.length; i < l; i++) {
+ o = a[i];
+ (renderers[
+ o.type || this.settings(options, 'defaultEdgeType')
+ ] || renderers.def)(
+ o,
+ graph.nodes(o.source),
+ graph.nodes(o.target),
+ this.contexts.edges,
+ embedSettings
+ );
+ }
+
+ // Draw edge labels:
+ // - No batching
+ if (drawEdgeLabels) {
+ renderers = sigma.canvas.edges.labels;
+ for (a = this.edgesOnScreen, i = 0, l = a.length; i < l; i++)
+ if (!a[i].hidden)
+ (renderers[
+ a[i].type || this.settings(options, 'defaultEdgeType')
+ ] || renderers.def)(
+ a[i],
+ graph.nodes(a[i].source),
+ graph.nodes(a[i].target),
+ this.contexts.labels,
+ embedSettings
+ );
+ }
+ }
+ }
+
+ // Draw nodes:
+ // - No batching
+ if (drawNodes) {
+ renderers = sigma.canvas.nodes;
+ for (a = this.nodesOnScreen, i = 0, l = a.length; i < l; i++)
+ if (!a[i].hidden)
+ (renderers[
+ a[i].type || this.settings(options, 'defaultNodeType')
+ ] || renderers.def)(
+ a[i],
+ this.contexts.nodes,
+ embedSettings
+ );
+ }
+
+ // Draw labels:
+ // - No batching
+ if (drawLabels) {
+ renderers = sigma.canvas.labels;
+ for (a = this.nodesOnScreen, i = 0, l = a.length; i < l; i++)
+ if (!a[i].hidden)
+ (renderers[
+ a[i].type || this.settings(options, 'defaultNodeType')
+ ] || renderers.def)(
+ a[i],
+ this.contexts.labels,
+ embedSettings
+ );
+ }
+
+ this.dispatchEvent('render');
+
+ return this;
+ };
+
+ /**
+ * This method creates a DOM element of the specified type, switches its
+ * position to "absolute", references it to the domElements attribute, and
+ * finally appends it to the container.
+ *
+ * @param {string} tag The label tag.
+ * @param {string} id The id of the element (to store it in "domElements").
+ */
+ sigma.renderers.canvas.prototype.initDOM = function(tag, id) {
+ var dom = document.createElement(tag);
+
+ dom.style.position = 'absolute';
+ dom.setAttribute('class', 'sigma-' + id);
+
+ this.domElements[id] = dom;
+ this.container.appendChild(dom);
+
+ if (tag.toLowerCase() === 'canvas')
+ this.contexts[id] = dom.getContext('2d');
+ };
+
+ /**
+ * This method resizes each DOM elements in the container and stores the new
+ * dimensions. Then, it renders the graph.
+ *
+ * @param {?number} width The new width of the container.
+ * @param {?number} height The new height of the container.
+ * @return {sigma.renderers.canvas} Returns the instance itself.
+ */
+ sigma.renderers.canvas.prototype.resize = function(w, h) {
+ var k,
+ oldWidth = this.width,
+ oldHeight = this.height,
+ pixelRatio = sigma.utils.getPixelRatio();
+
+ if (w !== undefined && h !== undefined) {
+ this.width = w;
+ this.height = h;
+ } else {
+ this.width = this.container.offsetWidth;
+ this.height = this.container.offsetHeight;
+
+ w = this.width;
+ h = this.height;
+ }
+
+ if (oldWidth !== this.width || oldHeight !== this.height) {
+ for (k in this.domElements) {
+ this.domElements[k].style.width = w + 'px';
+ this.domElements[k].style.height = h + 'px';
+
+ if (this.domElements[k].tagName.toLowerCase() === 'canvas') {
+ this.domElements[k].setAttribute('width', (w * pixelRatio) + 'px');
+ this.domElements[k].setAttribute('height', (h * pixelRatio) + 'px');
+
+ if (pixelRatio !== 1)
+ this.contexts[k].scale(pixelRatio, pixelRatio);
+ }
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * This method clears each canvas.
+ *
+ * @return {sigma.renderers.canvas} Returns the instance itself.
+ */
+ sigma.renderers.canvas.prototype.clear = function() {
+ for (var k in this.contexts) {
+ this.contexts[k].clearRect(0, 0, this.width, this.height);
+ }
+
+ return this;
+ };
+
+ /**
+ * This method kills contexts and other attributes.
+ */
+ sigma.renderers.canvas.prototype.kill = function() {
+ var k,
+ captor;
+
+ // Kill captors:
+ while ((captor = this.captors.pop()))
+ captor.kill();
+ delete this.captors;
+
+ // Kill contexts:
+ for (k in this.domElements) {
+ this.domElements[k].parentNode.removeChild(this.domElements[k]);
+ delete this.domElements[k];
+ delete this.contexts[k];
+ }
+ delete this.domElements;
+ delete this.contexts;
+ };
+
+
+
+
+ /**
+ * The labels, nodes and edges renderers are stored in the three following
+ * objects. When an element is drawn, its type will be checked and if a
+ * renderer with the same name exists, it will be used. If not found, the
+ * default renderer will be used instead.
+ *
+ * They are stored in different files, in the "./canvas" folder.
+ */
+ sigma.utils.pkg('sigma.canvas.nodes');
+ sigma.utils.pkg('sigma.canvas.edges');
+ sigma.utils.pkg('sigma.canvas.labels');
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.renderers');
+
+ /**
+ * This function is the constructor of the canvas sigma's renderer.
+ *
+ * @param {sigma.classes.graph} graph The graph to render.
+ * @param {sigma.classes.camera} camera The camera.
+ * @param {configurable} settings The sigma instance settings
+ * function.
+ * @param {object} object The options object.
+ * @return {sigma.renderers.canvas} The renderer instance.
+ */
+ sigma.renderers.webgl = function(graph, camera, settings, options) {
+ if (typeof options !== 'object')
+ throw 'sigma.renderers.webgl: Wrong arguments.';
+
+ if (!(options.container instanceof HTMLElement))
+ throw 'Container not found.';
+
+ var k,
+ i,
+ l,
+ a,
+ fn,
+ _self = this;
+
+ sigma.classes.dispatcher.extend(this);
+
+ // Conrad related attributes:
+ this.jobs = {};
+
+ Object.defineProperty(this, 'conradId', {
+ value: sigma.utils.id()
+ });
+
+ // Initialize main attributes:
+ this.graph = graph;
+ this.camera = camera;
+ this.contexts = {};
+ this.domElements = {};
+ this.options = options;
+ this.container = this.options.container;
+ this.settings = (
+ typeof options.settings === 'object' &&
+ options.settings
+ ) ?
+ settings.embedObjects(options.settings) :
+ settings;
+
+ // Find the prefix:
+ this.options.prefix = this.camera.readPrefix;
+
+ // Initialize programs hash
+ Object.defineProperty(this, 'nodePrograms', {
+ value: {}
+ });
+ Object.defineProperty(this, 'edgePrograms', {
+ value: {}
+ });
+ Object.defineProperty(this, 'nodeFloatArrays', {
+ value: {}
+ });
+ Object.defineProperty(this, 'edgeFloatArrays', {
+ value: {}
+ });
+ Object.defineProperty(this, 'edgeIndicesArrays', {
+ value: {}
+ });
+
+ // Initialize the DOM elements:
+ if (this.settings(options, 'batchEdgesDrawing')) {
+ this.initDOM('canvas', 'edges', true);
+ this.initDOM('canvas', 'nodes', true);
+ } else {
+ this.initDOM('canvas', 'scene', true);
+ this.contexts.nodes = this.contexts.scene;
+ this.contexts.edges = this.contexts.scene;
+ }
+
+ this.initDOM('canvas', 'labels');
+ this.initDOM('canvas', 'mouse');
+ this.contexts.hover = this.contexts.mouse;
+
+ // Initialize captors:
+ this.captors = [];
+ a = this.options.captors || [sigma.captors.mouse, sigma.captors.touch];
+ for (i = 0, l = a.length; i < l; i++) {
+ fn = typeof a[i] === 'function' ? a[i] : sigma.captors[a[i]];
+ this.captors.push(
+ new fn(
+ this.domElements.mouse,
+ this.camera,
+ this.settings
+ )
+ );
+ }
+
+ // Deal with sigma events:
+ sigma.misc.bindEvents.call(this, this.camera.prefix);
+ sigma.misc.drawHovers.call(this, this.camera.prefix);
+
+ this.resize();
+ };
+
+
+
+
+ /**
+ * This method will generate the nodes and edges float arrays. This step is
+ * separated from the "render" method, because to keep WebGL efficient, since
+ * all the camera and middlewares are modelised as matrices and they do not
+ * require the float arrays to be regenerated.
+ *
+ * Basically, when the user moves the camera or applies some specific linear
+ * transformations, this process step will be skipped, and the "render"
+ * method will efficiently refresh the rendering.
+ *
+ * And when the user modifies the graph colors or positions (applying a new
+ * layout or filtering the colors, for instance), this "process" step will be
+ * required to regenerate the float arrays.
+ *
+ * @return {sigma.renderers.webgl} Returns the instance itself.
+ */
+ sigma.renderers.webgl.prototype.process = function() {
+ var a,
+ i,
+ l,
+ k,
+ type,
+ renderer,
+ graph = this.graph,
+ options = sigma.utils.extend(options, this.options),
+ defaultEdgeType = this.settings(options, 'defaultEdgeType'),
+ defaultNodeType = this.settings(options, 'defaultNodeType');
+
+ // Empty float arrays:
+ for (k in this.nodeFloatArrays)
+ delete this.nodeFloatArrays[k];
+
+ for (k in this.edgeFloatArrays)
+ delete this.edgeFloatArrays[k];
+
+ for (k in this.edgeIndicesArrays)
+ delete this.edgeIndicesArrays[k];
+
+ // Sort edges and nodes per types:
+ for (a = graph.edges(), i = 0, l = a.length; i < l; i++) {
+ type = a[i].type || defaultEdgeType;
+ k = (type && sigma.webgl.edges[type]) ? type : 'def';
+
+ if (!this.edgeFloatArrays[k])
+ this.edgeFloatArrays[k] = {
+ edges: []
+ };
+
+ this.edgeFloatArrays[k].edges.push(a[i]);
+ }
+
+ for (a = graph.nodes(), i = 0, l = a.length; i < l; i++) {
+ type = a[i].type || defaultNodeType;
+ k = (type && sigma.webgl.nodes[type]) ? type : 'def';
+
+ if (!this.nodeFloatArrays[k])
+ this.nodeFloatArrays[k] = {
+ nodes: []
+ };
+
+ this.nodeFloatArrays[k].nodes.push(a[i]);
+ }
+
+ // Push edges:
+ for (k in this.edgeFloatArrays) {
+ renderer = sigma.webgl.edges[k];
+ a = this.edgeFloatArrays[k].edges;
+
+ // Creating the necessary arrays
+ this.edgeFloatArrays[k].array = new Float32Array(
+ a.length * renderer.POINTS * renderer.ATTRIBUTES
+ );
+
+ for (i = 0, l = a.length; i < l; i++) {
+
+ // Just check that the edge and both its extremities are visible:
+ if (
+ !a[i].hidden &&
+ !graph.nodes(a[i].source).hidden &&
+ !graph.nodes(a[i].target).hidden
+ )
+ renderer.addEdge(
+ a[i],
+ graph.nodes(a[i].source),
+ graph.nodes(a[i].target),
+ this.edgeFloatArrays[k].array,
+ i * renderer.POINTS * renderer.ATTRIBUTES,
+ options.prefix,
+ this.settings
+ );
+ }
+
+ if (typeof renderer.computeIndices === 'function')
+ this.edgeIndicesArrays[k] = renderer.computeIndices(
+ this.edgeFloatArrays[k].array
+ );
+ }
+
+ // Push nodes:
+ for (k in this.nodeFloatArrays) {
+ renderer = sigma.webgl.nodes[k];
+ a = this.nodeFloatArrays[k].nodes;
+
+ // Creating the necessary arrays
+ this.nodeFloatArrays[k].array = new Float32Array(
+ a.length * renderer.POINTS * renderer.ATTRIBUTES
+ );
+
+ for (i = 0, l = a.length; i < l; i++) {
+ if (!this.nodeFloatArrays[k].array)
+ this.nodeFloatArrays[k].array = new Float32Array(
+ a.length * renderer.POINTS * renderer.ATTRIBUTES
+ );
+
+ // Just check that the edge and both its extremities are visible:
+ if (
+ !a[i].hidden
+ )
+ renderer.addNode(
+ a[i],
+ this.nodeFloatArrays[k].array,
+ i * renderer.POINTS * renderer.ATTRIBUTES,
+ options.prefix,
+ this.settings
+ );
+ }
+ }
+
+ return this;
+ };
+
+
+
+
+ /**
+ * This method renders the graph. It basically calls each program (and
+ * generate them if they do not exist yet) to render nodes and edges, batched
+ * per renderer.
+ *
+ * As in the canvas renderer, it is possible to display edges, nodes and / or
+ * labels in batches, to make the whole thing way more scalable.
+ *
+ * @param {?object} params Eventually an object of options.
+ * @return {sigma.renderers.webgl} Returns the instance itself.
+ */
+ sigma.renderers.webgl.prototype.render = function(params) {
+ var a,
+ i,
+ l,
+ k,
+ o,
+ program,
+ renderer,
+ self = this,
+ graph = this.graph,
+ nodesGl = this.contexts.nodes,
+ edgesGl = this.contexts.edges,
+ matrix = this.camera.getMatrix(),
+ options = sigma.utils.extend(params, this.options),
+ drawLabels = this.settings(options, 'drawLabels'),
+ drawEdges = this.settings(options, 'drawEdges'),
+ drawNodes = this.settings(options, 'drawNodes');
+
+ // Call the resize function:
+ this.resize(false);
+
+ // Check the 'hideEdgesOnMove' setting:
+ if (this.settings(options, 'hideEdgesOnMove'))
+ if (this.camera.isAnimated || this.camera.isMoving)
+ drawEdges = false;
+
+ // Clear canvases:
+ this.clear();
+
+ // Translate matrix to [width/2, height/2]:
+ matrix = sigma.utils.matrices.multiply(
+ matrix,
+ sigma.utils.matrices.translation(this.width / 2, this.height / 2)
+ );
+
+ // Kill running jobs:
+ for (k in this.jobs)
+ if (conrad.hasJob(k))
+ conrad.killJob(k);
+
+ if (drawEdges) {
+ if (this.settings(options, 'batchEdgesDrawing'))
+ (function() {
+ var a,
+ k,
+ i,
+ id,
+ job,
+ arr,
+ end,
+ start,
+ indices,
+ renderer,
+ batchSize,
+ currentProgram;
+
+ id = 'edges_' + this.conradId;
+ batchSize = this.settings(options, 'webglEdgesBatchSize');
+ a = Object.keys(this.edgeFloatArrays);
+
+ if (!a.length)
+ return;
+ i = 0;
+ renderer = sigma.webgl.edges[a[i]];
+ arr = this.edgeFloatArrays[a[i]].array;
+ indices = this.edgeIndicesArrays[a[i]];
+ start = 0;
+ end = Math.min(
+ start + batchSize * renderer.POINTS,
+ arr.length / renderer.ATTRIBUTES
+ );
+
+ job = function() {
+ // Check program:
+ if (!this.edgePrograms[a[i]])
+ this.edgePrograms[a[i]] = renderer.initProgram(edgesGl);
+
+ if (start < end) {
+ edgesGl.useProgram(this.edgePrograms[a[i]]);
+ renderer.render(
+ edgesGl,
+ this.edgePrograms[a[i]],
+ arr,
+ {
+ settings: this.settings,
+ matrix: matrix,
+ width: this.width,
+ height: this.height,
+ ratio: this.camera.ratio,
+ scalingRatio: this.settings(
+ options,
+ 'webglOversamplingRatio'
+ ),
+ start: start,
+ count: end - start,
+ indicesData: indices
+ }
+ );
+ }
+
+ // Catch job's end:
+ if (
+ end >= arr.length / renderer.ATTRIBUTES &&
+ i === a.length - 1
+ ) {
+ delete this.jobs[id];
+ return false;
+ }
+
+ if (end >= arr.length / renderer.ATTRIBUTES) {
+ i++;
+ arr = this.edgeFloatArrays[a[i]].array;
+ renderer = sigma.webgl.edges[a[i]];
+ start = 0;
+ end = Math.min(
+ start + batchSize * renderer.POINTS,
+ arr.length / renderer.ATTRIBUTES
+ );
+ } else {
+ start = end;
+ end = Math.min(
+ start + batchSize * renderer.POINTS,
+ arr.length / renderer.ATTRIBUTES
+ );
+ }
+
+ return true;
+ };
+
+ this.jobs[id] = job;
+ conrad.addJob(id, job.bind(this));
+ }).call(this);
+ else {
+ for (k in this.edgeFloatArrays) {
+ renderer = sigma.webgl.edges[k];
+
+ // Check program:
+ if (!this.edgePrograms[k])
+ this.edgePrograms[k] = renderer.initProgram(edgesGl);
+
+ // Render
+ if (this.edgeFloatArrays[k]) {
+ edgesGl.useProgram(this.edgePrograms[k]);
+ renderer.render(
+ edgesGl,
+ this.edgePrograms[k],
+ this.edgeFloatArrays[k].array,
+ {
+ settings: this.settings,
+ matrix: matrix,
+ width: this.width,
+ height: this.height,
+ ratio: this.camera.ratio,
+ scalingRatio: this.settings(options, 'webglOversamplingRatio'),
+ indicesData: this.edgeIndicesArrays[k]
+ }
+ );
+ }
+ }
+ }
+ }
+
+ if (drawNodes) {
+ // Enable blending:
+ nodesGl.blendFunc(nodesGl.SRC_ALPHA, nodesGl.ONE_MINUS_SRC_ALPHA);
+ nodesGl.enable(nodesGl.BLEND);
+
+ for (k in this.nodeFloatArrays) {
+ renderer = sigma.webgl.nodes[k];
+
+ // Check program:
+ if (!this.nodePrograms[k])
+ this.nodePrograms[k] = renderer.initProgram(nodesGl);
+
+ // Render
+ if (this.nodeFloatArrays[k]) {
+ nodesGl.useProgram(this.nodePrograms[k]);
+ renderer.render(
+ nodesGl,
+ this.nodePrograms[k],
+ this.nodeFloatArrays[k].array,
+ {
+ settings: this.settings,
+ matrix: matrix,
+ width: this.width,
+ height: this.height,
+ ratio: this.camera.ratio,
+ scalingRatio: this.settings(options, 'webglOversamplingRatio')
+ }
+ );
+ }
+ }
+ }
+
+ if (drawLabels) {
+ a = this.camera.quadtree.area(
+ this.camera.getRectangle(this.width, this.height)
+ );
+
+ // Apply camera view to these nodes:
+ this.camera.applyView(
+ undefined,
+ undefined,
+ {
+ nodes: a,
+ edges: [],
+ width: this.width,
+ height: this.height
+ }
+ );
+
+ o = function(key) {
+ return self.settings({
+ prefix: self.camera.prefix
+ }, key);
+ };
+
+ for (i = 0, l = a.length; i < l; i++)
+ if (!a[i].hidden)
+ (
+ sigma.canvas.labels[
+ a[i].type ||
+ this.settings(options, 'defaultNodeType')
+ ] || sigma.canvas.labels.def
+ )(a[i], this.contexts.labels, o);
+ }
+
+ this.dispatchEvent('render');
+
+ return this;
+ };
+
+
+
+
+ /**
+ * This method creates a DOM element of the specified type, switches its
+ * position to "absolute", references it to the domElements attribute, and
+ * finally appends it to the container.
+ *
+ * @param {string} tag The label tag.
+ * @param {string} id The id of the element (to store it in
+ * "domElements").
+ * @param {?boolean} webgl Will init the WebGL context if true.
+ */
+ sigma.renderers.webgl.prototype.initDOM = function(tag, id, webgl) {
+ var gl,
+ dom = document.createElement(tag),
+ self = this;
+
+ dom.style.position = 'absolute';
+ dom.setAttribute('class', 'sigma-' + id);
+
+ this.domElements[id] = dom;
+ this.container.appendChild(dom);
+
+ if (tag.toLowerCase() === 'canvas') {
+ this.contexts[id] = dom.getContext(webgl ? 'experimental-webgl' : '2d', {
+ preserveDrawingBuffer: true
+ });
+
+ // Adding webgl context loss listeners
+ if (webgl) {
+ dom.addEventListener('webglcontextlost', function(e) {
+ e.preventDefault();
+ }, false);
+
+ dom.addEventListener('webglcontextrestored', function(e) {
+ self.render();
+ }, false);
+ }
+ }
+ };
+
+ /**
+ * This method resizes each DOM elements in the container and stores the new
+ * dimensions. Then, it renders the graph.
+ *
+ * @param {?number} width The new width of the container.
+ * @param {?number} height The new height of the container.
+ * @return {sigma.renderers.webgl} Returns the instance itself.
+ */
+ sigma.renderers.webgl.prototype.resize = function(w, h) {
+ var k,
+ oldWidth = this.width,
+ oldHeight = this.height,
+ pixelRatio = sigma.utils.getPixelRatio();
+
+ if (w !== undefined && h !== undefined) {
+ this.width = w;
+ this.height = h;
+ } else {
+ this.width = this.container.offsetWidth;
+ this.height = this.container.offsetHeight;
+
+ w = this.width;
+ h = this.height;
+ }
+
+ if (oldWidth !== this.width || oldHeight !== this.height) {
+ for (k in this.domElements) {
+ this.domElements[k].style.width = w + 'px';
+ this.domElements[k].style.height = h + 'px';
+
+ if (this.domElements[k].tagName.toLowerCase() === 'canvas') {
+ // If simple 2D canvas:
+ if (this.contexts[k] && this.contexts[k].scale) {
+ this.domElements[k].setAttribute('width', (w * pixelRatio) + 'px');
+ this.domElements[k].setAttribute('height', (h * pixelRatio) + 'px');
+
+ if (pixelRatio !== 1)
+ this.contexts[k].scale(pixelRatio, pixelRatio);
+ } else {
+ this.domElements[k].setAttribute(
+ 'width',
+ (w * this.settings('webglOversamplingRatio')) + 'px'
+ );
+ this.domElements[k].setAttribute(
+ 'height',
+ (h * this.settings('webglOversamplingRatio')) + 'px'
+ );
+ }
+ }
+ }
+ }
+
+ // Scale:
+ for (k in this.contexts)
+ if (this.contexts[k] && this.contexts[k].viewport)
+ this.contexts[k].viewport(
+ 0,
+ 0,
+ this.width * this.settings('webglOversamplingRatio'),
+ this.height * this.settings('webglOversamplingRatio')
+ );
+
+ return this;
+ };
+
+ /**
+ * This method clears each canvas.
+ *
+ * @return {sigma.renderers.webgl} Returns the instance itself.
+ */
+ sigma.renderers.webgl.prototype.clear = function() {
+ this.contexts.labels.clearRect(0, 0, this.width, this.height);
+ this.contexts.nodes.clear(this.contexts.nodes.COLOR_BUFFER_BIT);
+ this.contexts.edges.clear(this.contexts.edges.COLOR_BUFFER_BIT);
+
+ return this;
+ };
+
+ /**
+ * This method kills contexts and other attributes.
+ */
+ sigma.renderers.webgl.prototype.kill = function() {
+ var k,
+ captor;
+
+ // Kill captors:
+ while ((captor = this.captors.pop()))
+ captor.kill();
+ delete this.captors;
+
+ // Kill contexts:
+ for (k in this.domElements) {
+ this.domElements[k].parentNode.removeChild(this.domElements[k]);
+ delete this.domElements[k];
+ delete this.contexts[k];
+ }
+ delete this.domElements;
+ delete this.contexts;
+ };
+
+
+
+
+ /**
+ * The object "sigma.webgl.nodes" contains the different WebGL node
+ * renderers. The default one draw nodes as discs. Here are the attributes
+ * any node renderer must have:
+ *
+ * {number} POINTS The number of points required to draw a node.
+ * {number} ATTRIBUTES The number of attributes needed to draw one point.
+ * {function} addNode A function that adds a node to the data stack that
+ * will be given to the buffer. Here is the arguments:
+ * > {object} node
+ * > {number} index The node index in the
+ * nodes array.
+ * > {Float32Array} data The stack.
+ * > {object} options Some options.
+ * {function} render The function that will effectively render the nodes
+ * into the buffer.
+ * > {WebGLRenderingContext} gl
+ * > {WebGLProgram} program
+ * > {Float32Array} data The stack to give to the
+ * buffer.
+ * > {object} params An object containing some
+ * options, like width,
+ * height, the camera ratio.
+ * {function} initProgram The function that will initiate the program, with
+ * the relevant shaders and parameters. It must return
+ * the newly created program.
+ *
+ * Check sigma.webgl.nodes.def or sigma.webgl.nodes.fast to see how it
+ * works more precisely.
+ */
+ sigma.utils.pkg('sigma.webgl.nodes');
+
+
+
+
+ /**
+ * The object "sigma.webgl.edges" contains the different WebGL edge
+ * renderers. The default one draw edges as direct lines. Here are the
+ * attributes any edge renderer must have:
+ *
+ * {number} POINTS The number of points required to draw an edge.
+ * {number} ATTRIBUTES The number of attributes needed to draw one point.
+ * {function} addEdge A function that adds an edge to the data stack that
+ * will be given to the buffer. Here is the arguments:
+ * > {object} edge
+ * > {object} source
+ * > {object} target
+ * > {Float32Array} data The stack.
+ * > {object} options Some options.
+ * {function} render The function that will effectively render the edges
+ * into the buffer.
+ * > {WebGLRenderingContext} gl
+ * > {WebGLProgram} program
+ * > {Float32Array} data The stack to give to the
+ * buffer.
+ * > {object} params An object containing some
+ * options, like width,
+ * height, the camera ratio.
+ * {function} initProgram The function that will initiate the program, with
+ * the relevant shaders and parameters. It must return
+ * the newly created program.
+ *
+ * Check sigma.webgl.edges.def or sigma.webgl.edges.fast to see how it
+ * works more precisely.
+ */
+ sigma.utils.pkg('sigma.webgl.edges');
+
+
+
+
+ /**
+ * The object "sigma.canvas.labels" contains the different
+ * label renderers for the WebGL renderer. Since displaying texts in WebGL is
+ * definitely painful and since there a way less labels to display than nodes
+ * or edges, the default renderer simply renders them in a canvas.
+ *
+ * A labels renderer is a simple function, taking as arguments the related
+ * node, the renderer and a settings function.
+ */
+ sigma.utils.pkg('sigma.canvas.labels');
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ if (typeof conrad === 'undefined')
+ throw 'conrad is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.renderers');
+
+ /**
+ * This function is the constructor of the svg sigma's renderer.
+ *
+ * @param {sigma.classes.graph} graph The graph to render.
+ * @param {sigma.classes.camera} camera The camera.
+ * @param {configurable} settings The sigma instance settings
+ * function.
+ * @param {object} object The options object.
+ * @return {sigma.renderers.svg} The renderer instance.
+ */
+ sigma.renderers.svg = function(graph, camera, settings, options) {
+ if (typeof options !== 'object')
+ throw 'sigma.renderers.svg: Wrong arguments.';
+
+ if (!(options.container instanceof HTMLElement))
+ throw 'Container not found.';
+
+ var i,
+ l,
+ a,
+ fn,
+ self = this;
+
+ sigma.classes.dispatcher.extend(this);
+
+ // Initialize main attributes:
+ this.graph = graph;
+ this.camera = camera;
+ this.domElements = {
+ graph: null,
+ groups: {},
+ nodes: {},
+ edges: {},
+ labels: {},
+ hovers: {}
+ };
+ this.measurementCanvas = null;
+ this.options = options;
+ this.container = this.options.container;
+ this.settings = (
+ typeof options.settings === 'object' &&
+ options.settings
+ ) ?
+ settings.embedObjects(options.settings) :
+ settings;
+
+ // Is the renderer meant to be freestyle?
+ this.settings('freeStyle', !!this.options.freeStyle);
+
+ // SVG xmlns
+ this.settings('xmlns', 'http://www.w3.org/2000/svg');
+
+ // Indexes:
+ this.nodesOnScreen = [];
+ this.edgesOnScreen = [];
+
+ // Find the prefix:
+ this.options.prefix = 'renderer' + sigma.utils.id() + ':';
+
+ // Initialize the DOM elements
+ this.initDOM('svg');
+
+ // Initialize captors:
+ this.captors = [];
+ a = this.options.captors || [sigma.captors.mouse, sigma.captors.touch];
+ for (i = 0, l = a.length; i < l; i++) {
+ fn = typeof a[i] === 'function' ? a[i] : sigma.captors[a[i]];
+ this.captors.push(
+ new fn(
+ this.domElements.graph,
+ this.camera,
+ this.settings
+ )
+ );
+ }
+
+ // Bind resize:
+ window.addEventListener('resize', function() {
+ self.resize();
+ });
+
+ // Deal with sigma events:
+ // TODO: keep an option to override the DOM events?
+ sigma.misc.bindDOMEvents.call(this, this.domElements.graph);
+ this.bindHovers(this.options.prefix);
+
+ // Resize
+ this.resize(false);
+ };
+
+ /**
+ * This method renders the graph on the svg scene.
+ *
+ * @param {?object} options Eventually an object of options.
+ * @return {sigma.renderers.svg} Returns the instance itself.
+ */
+ sigma.renderers.svg.prototype.render = function(options) {
+ options = options || {};
+
+ var a,
+ i,
+ k,
+ e,
+ l,
+ o,
+ source,
+ target,
+ start,
+ edges,
+ renderers,
+ subrenderers,
+ index = {},
+ graph = this.graph,
+ nodes = this.graph.nodes,
+ prefix = this.options.prefix || '',
+ drawEdges = this.settings(options, 'drawEdges'),
+ drawNodes = this.settings(options, 'drawNodes'),
+ drawLabels = this.settings(options, 'drawLabels'),
+ embedSettings = this.settings.embedObjects(options, {
+ prefix: this.options.prefix,
+ forceLabels: this.options.forceLabels
+ });
+
+ // Check the 'hideEdgesOnMove' setting:
+ if (this.settings(options, 'hideEdgesOnMove'))
+ if (this.camera.isAnimated || this.camera.isMoving)
+ drawEdges = false;
+
+ // Apply the camera's view:
+ this.camera.applyView(
+ undefined,
+ this.options.prefix,
+ {
+ width: this.width,
+ height: this.height
+ }
+ );
+
+ // Hiding everything
+ // TODO: find a more sensible way to perform this operation
+ this.hideDOMElements(this.domElements.nodes);
+ this.hideDOMElements(this.domElements.edges);
+ this.hideDOMElements(this.domElements.labels);
+
+ // Find which nodes are on screen
+ this.edgesOnScreen = [];
+ this.nodesOnScreen = this.camera.quadtree.area(
+ this.camera.getRectangle(this.width, this.height)
+ );
+
+ // Node index
+ for (a = this.nodesOnScreen, i = 0, l = a.length; i < l; i++)
+ index[a[i].id] = a[i];
+
+ // Find which edges are on screen
+ for (a = graph.edges(), i = 0, l = a.length; i < l; i++) {
+ o = a[i];
+ if (
+ (index[o.source] || index[o.target]) &&
+ (!o.hidden && !nodes(o.source).hidden && !nodes(o.target).hidden)
+ )
+ this.edgesOnScreen.push(o);
+ }
+
+ // Display nodes
+ //---------------
+ renderers = sigma.svg.nodes;
+ subrenderers = sigma.svg.labels;
+
+ //-- First we create the nodes which are not already created
+ if (drawNodes)
+ for (a = this.nodesOnScreen, i = 0, l = a.length; i < l; i++) {
+ if (!a[i].hidden && !this.domElements.nodes[a[i].id]) {
+
+ // Node
+ e = (renderers[a[i].type] || renderers.def).create(
+ a[i],
+ embedSettings
+ );
+
+ this.domElements.nodes[a[i].id] = e;
+ this.domElements.groups.nodes.appendChild(e);
+
+ // Label
+ e = (subrenderers[a[i].type] || subrenderers.def).create(
+ a[i],
+ embedSettings
+ );
+
+ this.domElements.labels[a[i].id] = e;
+ this.domElements.groups.labels.appendChild(e);
+ }
+ }
+
+ //-- Second we update the nodes
+ if (drawNodes)
+ for (a = this.nodesOnScreen, i = 0, l = a.length; i < l; i++) {
+
+ if (a[i].hidden)
+ continue;
+
+ // Node
+ (renderers[a[i].type] || renderers.def).update(
+ a[i],
+ this.domElements.nodes[a[i].id],
+ embedSettings
+ );
+
+ // Label
+ (subrenderers[a[i].type] || subrenderers.def).update(
+ a[i],
+ this.domElements.labels[a[i].id],
+ embedSettings
+ );
+ }
+
+ // Display edges
+ //---------------
+ renderers = sigma.svg.edges;
+
+ //-- First we create the edges which are not already created
+ if (drawEdges)
+ for (a = this.edgesOnScreen, i = 0, l = a.length; i < l; i++) {
+ if (!this.domElements.edges[a[i].id]) {
+ source = nodes(a[i].source);
+ target = nodes(a[i].target);
+
+ e = (renderers[a[i].type] || renderers.def).create(
+ a[i],
+ source,
+ target,
+ embedSettings
+ );
+
+ this.domElements.edges[a[i].id] = e;
+ this.domElements.groups.edges.appendChild(e);
+ }
+ }
+
+ //-- Second we update the edges
+ if (drawEdges)
+ for (a = this.edgesOnScreen, i = 0, l = a.length; i < l; i++) {
+ source = nodes(a[i].source);
+ target = nodes(a[i].target);
+
+ (renderers[a[i].type] || renderers.def).update(
+ a[i],
+ this.domElements.edges[a[i].id],
+ source,
+ target,
+ embedSettings
+ );
+ }
+
+ this.dispatchEvent('render');
+
+ return this;
+ };
+
+ /**
+ * This method creates a DOM element of the specified type, switches its
+ * position to "absolute", references it to the domElements attribute, and
+ * finally appends it to the container.
+ *
+ * @param {string} tag The label tag.
+ * @param {string} id The id of the element (to store it in "domElements").
+ */
+ sigma.renderers.svg.prototype.initDOM = function(tag) {
+ var dom = document.createElementNS(this.settings('xmlns'), tag),
+ c = this.settings('classPrefix'),
+ g,
+ l,
+ i;
+
+ dom.style.position = 'absolute';
+ dom.setAttribute('class', c + '-svg');
+
+ // Setting SVG namespace
+ dom.setAttribute('xmlns', this.settings('xmlns'));
+ dom.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
+ dom.setAttribute('version', '1.1');
+
+ // Creating the measurement canvas
+ var canvas = document.createElement('canvas');
+ canvas.setAttribute('class', c + '-measurement-canvas');
+
+ // Appending elements
+ this.domElements.graph = this.container.appendChild(dom);
+
+ // Creating groups
+ var groups = ['edges', 'nodes', 'labels', 'hovers'];
+ for (i = 0, l = groups.length; i < l; i++) {
+ g = document.createElementNS(this.settings('xmlns'), 'g');
+
+ g.setAttributeNS(null, 'id', c + '-group-' + groups[i]);
+ g.setAttributeNS(null, 'class', c + '-group');
+
+ this.domElements.groups[groups[i]] =
+ this.domElements.graph.appendChild(g);
+ }
+
+ // Appending measurement canvas
+ this.container.appendChild(canvas);
+ this.measurementCanvas = canvas.getContext('2d');
+ };
+
+ /**
+ * This method hides a batch of SVG DOM elements.
+ *
+ * @param {array} elements An array of elements to hide.
+ * @param {object} renderer The renderer to use.
+ * @return {sigma.renderers.svg} Returns the instance itself.
+ */
+ sigma.renderers.svg.prototype.hideDOMElements = function(elements) {
+ var o,
+ i;
+
+ for (i in elements) {
+ o = elements[i];
+ sigma.svg.utils.hide(o);
+ }
+
+ return this;
+ };
+
+ /**
+ * This method binds the hover events to the renderer.
+ *
+ * @param {string} prefix The renderer prefix.
+ */
+ // TODO: add option about whether to display hovers or not
+ sigma.renderers.svg.prototype.bindHovers = function(prefix) {
+ var renderers = sigma.svg.hovers,
+ self = this,
+ hoveredNode;
+
+ function overNode(e) {
+ var node = e.data.node,
+ embedSettings = self.settings.embedObjects({
+ prefix: prefix
+ });
+
+ if (!embedSettings('enableHovering'))
+ return;
+
+ var hover = (renderers[node.type] || renderers.def).create(
+ node,
+ self.domElements.nodes[node.id],
+ self.measurementCanvas,
+ embedSettings
+ );
+
+ self.domElements.hovers[node.id] = hover;
+
+ // Inserting the hover in the dom
+ self.domElements.groups.hovers.appendChild(hover);
+ hoveredNode = node;
+ }
+
+ function outNode(e) {
+ var node = e.data.node,
+ embedSettings = self.settings.embedObjects({
+ prefix: prefix
+ });
+
+ if (!embedSettings('enableHovering'))
+ return;
+
+ // Deleting element
+ self.domElements.groups.hovers.removeChild(
+ self.domElements.hovers[node.id]
+ );
+ hoveredNode = null;
+ delete self.domElements.hovers[node.id];
+
+ // Reinstate
+ self.domElements.groups.nodes.appendChild(
+ self.domElements.nodes[node.id]
+ );
+ }
+
+ // OPTIMIZE: perform a real update rather than a deletion
+ function update() {
+ if (!hoveredNode)
+ return;
+
+ var embedSettings = self.settings.embedObjects({
+ prefix: prefix
+ });
+
+ // Deleting element before update
+ self.domElements.groups.hovers.removeChild(
+ self.domElements.hovers[hoveredNode.id]
+ );
+ delete self.domElements.hovers[hoveredNode.id];
+
+ var hover = (renderers[hoveredNode.type] || renderers.def).create(
+ hoveredNode,
+ self.domElements.nodes[hoveredNode.id],
+ self.measurementCanvas,
+ embedSettings
+ );
+
+ self.domElements.hovers[hoveredNode.id] = hover;
+
+ // Inserting the hover in the dom
+ self.domElements.groups.hovers.appendChild(hover);
+ }
+
+ // Binding events
+ this.bind('overNode', overNode);
+ this.bind('outNode', outNode);
+
+ // Update on render
+ this.bind('render', update);
+ };
+
+ /**
+ * This method resizes each DOM elements in the container and stores the new
+ * dimensions. Then, it renders the graph.
+ *
+ * @param {?number} width The new width of the container.
+ * @param {?number} height The new height of the container.
+ * @return {sigma.renderers.svg} Returns the instance itself.
+ */
+ sigma.renderers.svg.prototype.resize = function(w, h) {
+ var oldWidth = this.width,
+ oldHeight = this.height,
+ pixelRatio = 1;
+
+ if (w !== undefined && h !== undefined) {
+ this.width = w;
+ this.height = h;
+ } else {
+ this.width = this.container.offsetWidth;
+ this.height = this.container.offsetHeight;
+
+ w = this.width;
+ h = this.height;
+ }
+
+ if (oldWidth !== this.width || oldHeight !== this.height) {
+ this.domElements.graph.style.width = w + 'px';
+ this.domElements.graph.style.height = h + 'px';
+
+ if (this.domElements.graph.tagName.toLowerCase() === 'svg') {
+ this.domElements.graph.setAttribute('width', (w * pixelRatio));
+ this.domElements.graph.setAttribute('height', (h * pixelRatio));
+ }
+ }
+
+ return this;
+ };
+
+
+ /**
+ * The labels, nodes and edges renderers are stored in the three following
+ * objects. When an element is drawn, its type will be checked and if a
+ * renderer with the same name exists, it will be used. If not found, the
+ * default renderer will be used instead.
+ *
+ * They are stored in different files, in the "./svg" folder.
+ */
+ sigma.utils.pkg('sigma.svg.nodes');
+ sigma.utils.pkg('sigma.svg.edges');
+ sigma.utils.pkg('sigma.svg.labels');
+}).call(this);
+
+;(function(global) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.renderers');
+
+ // Check if WebGL is enabled:
+ var canvas,
+ webgl = !!global.WebGLRenderingContext;
+ if (webgl) {
+ canvas = document.createElement('canvas');
+ try {
+ webgl = !!(
+ canvas.getContext('webgl') ||
+ canvas.getContext('experimental-webgl')
+ );
+ } catch (e) {
+ webgl = false;
+ }
+ }
+
+ // Copy the good renderer:
+ sigma.renderers.def = webgl ?
+ sigma.renderers.webgl :
+ sigma.renderers.canvas;
+})(this);
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.webgl.nodes');
+
+ /**
+ * This node renderer will display nodes as discs, shaped in triangles with
+ * the gl.TRIANGLES display mode. So, to be more precise, to draw one node,
+ * it will store three times the center of node, with the color and the size,
+ * and an angle indicating which "corner" of the triangle to draw.
+ *
+ * The fragment shader does not deal with anti-aliasing, so make sure that
+ * you deal with it somewhere else in the code (by default, the WebGL
+ * renderer will oversample the rendering through the webglOversamplingRatio
+ * value).
+ */
+ sigma.webgl.nodes.def = {
+ POINTS: 3,
+ ATTRIBUTES: 5,
+ addNode: function(node, data, i, prefix, settings) {
+ var color = sigma.utils.floatColor(
+ node.color || settings('defaultNodeColor')
+ );
+
+ data[i++] = node[prefix + 'x'];
+ data[i++] = node[prefix + 'y'];
+ data[i++] = node[prefix + 'size'];
+ data[i++] = color;
+ data[i++] = 0;
+
+ data[i++] = node[prefix + 'x'];
+ data[i++] = node[prefix + 'y'];
+ data[i++] = node[prefix + 'size'];
+ data[i++] = color;
+ data[i++] = 2 * Math.PI / 3;
+
+ data[i++] = node[prefix + 'x'];
+ data[i++] = node[prefix + 'y'];
+ data[i++] = node[prefix + 'size'];
+ data[i++] = color;
+ data[i++] = 4 * Math.PI / 3;
+ },
+ render: function(gl, program, data, params) {
+ var buffer;
+
+ // Define attributes:
+ var positionLocation =
+ gl.getAttribLocation(program, 'a_position'),
+ sizeLocation =
+ gl.getAttribLocation(program, 'a_size'),
+ colorLocation =
+ gl.getAttribLocation(program, 'a_color'),
+ angleLocation =
+ gl.getAttribLocation(program, 'a_angle'),
+ resolutionLocation =
+ gl.getUniformLocation(program, 'u_resolution'),
+ matrixLocation =
+ gl.getUniformLocation(program, 'u_matrix'),
+ ratioLocation =
+ gl.getUniformLocation(program, 'u_ratio'),
+ scaleLocation =
+ gl.getUniformLocation(program, 'u_scale');
+
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
+
+ gl.uniform2f(resolutionLocation, params.width, params.height);
+ gl.uniform1f(
+ ratioLocation,
+ 1 / Math.pow(params.ratio, params.settings('nodesPowRatio'))
+ );
+ gl.uniform1f(scaleLocation, params.scalingRatio);
+ gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
+
+ gl.enableVertexAttribArray(positionLocation);
+ gl.enableVertexAttribArray(sizeLocation);
+ gl.enableVertexAttribArray(colorLocation);
+ gl.enableVertexAttribArray(angleLocation);
+
+ gl.vertexAttribPointer(
+ positionLocation,
+ 2,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 0
+ );
+ gl.vertexAttribPointer(
+ sizeLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 8
+ );
+ gl.vertexAttribPointer(
+ colorLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 12
+ );
+ gl.vertexAttribPointer(
+ angleLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 16
+ );
+
+ gl.drawArrays(
+ gl.TRIANGLES,
+ params.start || 0,
+ params.count || (data.length / this.ATTRIBUTES)
+ );
+ },
+ initProgram: function(gl) {
+ var vertexShader,
+ fragmentShader,
+ program;
+
+ vertexShader = sigma.utils.loadShader(
+ gl,
+ [
+ 'attribute vec2 a_position;',
+ 'attribute float a_size;',
+ 'attribute float a_color;',
+ 'attribute float a_angle;',
+
+ 'uniform vec2 u_resolution;',
+ 'uniform float u_ratio;',
+ 'uniform float u_scale;',
+ 'uniform mat3 u_matrix;',
+
+ 'varying vec4 color;',
+ 'varying vec2 center;',
+ 'varying float radius;',
+
+ 'void main() {',
+ // Multiply the point size twice:
+ 'radius = a_size * u_ratio;',
+
+ // Scale from [[-1 1] [-1 1]] to the container:
+ 'vec2 position = (u_matrix * vec3(a_position, 1)).xy;',
+ // 'center = (position / u_resolution * 2.0 - 1.0) * vec2(1, -1);',
+ 'center = position * u_scale;',
+ 'center = vec2(center.x, u_scale * u_resolution.y - center.y);',
+
+ 'position = position +',
+ '2.0 * radius * vec2(cos(a_angle), sin(a_angle));',
+ 'position = (position / u_resolution * 2.0 - 1.0) * vec2(1, -1);',
+
+ 'radius = radius * u_scale;',
+
+ 'gl_Position = vec4(position, 0, 1);',
+
+ // Extract the color:
+ 'float c = a_color;',
+ 'color.b = mod(c, 256.0); c = floor(c / 256.0);',
+ 'color.g = mod(c, 256.0); c = floor(c / 256.0);',
+ 'color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;',
+ 'color.a = 1.0;',
+ '}'
+ ].join('\n'),
+ gl.VERTEX_SHADER
+ );
+
+ fragmentShader = sigma.utils.loadShader(
+ gl,
+ [
+ 'precision mediump float;',
+
+ 'varying vec4 color;',
+ 'varying vec2 center;',
+ 'varying float radius;',
+
+ 'void main(void) {',
+ 'vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);',
+
+ 'vec2 m = gl_FragCoord.xy - center;',
+ 'float diff = radius - sqrt(m.x * m.x + m.y * m.y);',
+
+ // Here is how we draw a disc instead of a square:
+ 'if (diff > 0.0)',
+ 'gl_FragColor = color;',
+ 'else',
+ 'gl_FragColor = color0;',
+ '}'
+ ].join('\n'),
+ gl.FRAGMENT_SHADER
+ );
+
+ program = sigma.utils.loadProgram(gl, [vertexShader, fragmentShader]);
+
+ return program;
+ }
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.webgl.nodes');
+
+ /**
+ * This node renderer will display nodes in the fastest way: Nodes are basic
+ * squares, drawn through the gl.POINTS drawing method. The size of the nodes
+ * are represented with the "gl_PointSize" value in the vertex shader.
+ *
+ * It is the fastest node renderer here since the buffer just takes one line
+ * to draw each node (with attributes "x", "y", "size" and "color").
+ *
+ * Nevertheless, this method has some problems, especially due to some issues
+ * with the gl.POINTS:
+ * - First, if the center of a node is outside the scene, the point will not
+ * be drawn, even if it should be partly on screen.
+ * - I tried applying a fragment shader similar to the one in the default
+ * node renderer to display them as discs, but it did not work fine on
+ * some computers settings, filling the discs with weird gradients not
+ * depending on the actual color.
+ */
+ sigma.webgl.nodes.fast = {
+ POINTS: 1,
+ ATTRIBUTES: 4,
+ addNode: function(node, data, i, prefix, settings) {
+ data[i++] = node[prefix + 'x'];
+ data[i++] = node[prefix + 'y'];
+ data[i++] = node[prefix + 'size'];
+ data[i++] = sigma.utils.floatColor(
+ node.color || settings('defaultNodeColor')
+ );
+ },
+ render: function(gl, program, data, params) {
+ var buffer;
+
+ // Define attributes:
+ var positionLocation =
+ gl.getAttribLocation(program, 'a_position'),
+ sizeLocation =
+ gl.getAttribLocation(program, 'a_size'),
+ colorLocation =
+ gl.getAttribLocation(program, 'a_color'),
+ resolutionLocation =
+ gl.getUniformLocation(program, 'u_resolution'),
+ matrixLocation =
+ gl.getUniformLocation(program, 'u_matrix'),
+ ratioLocation =
+ gl.getUniformLocation(program, 'u_ratio'),
+ scaleLocation =
+ gl.getUniformLocation(program, 'u_scale');
+
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
+
+ gl.uniform2f(resolutionLocation, params.width, params.height);
+ gl.uniform1f(
+ ratioLocation,
+ 1 / Math.pow(params.ratio, params.settings('nodesPowRatio'))
+ );
+ gl.uniform1f(scaleLocation, params.scalingRatio);
+ gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
+
+ gl.enableVertexAttribArray(positionLocation);
+ gl.enableVertexAttribArray(sizeLocation);
+ gl.enableVertexAttribArray(colorLocation);
+
+ gl.vertexAttribPointer(
+ positionLocation,
+ 2,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 0
+ );
+ gl.vertexAttribPointer(
+ sizeLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 8
+ );
+ gl.vertexAttribPointer(
+ colorLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 12
+ );
+
+ gl.drawArrays(
+ gl.POINTS,
+ params.start || 0,
+ params.count || (data.length / this.ATTRIBUTES)
+ );
+ },
+ initProgram: function(gl) {
+ var vertexShader,
+ fragmentShader,
+ program;
+
+ vertexShader = sigma.utils.loadShader(
+ gl,
+ [
+ 'attribute vec2 a_position;',
+ 'attribute float a_size;',
+ 'attribute float a_color;',
+
+ 'uniform vec2 u_resolution;',
+ 'uniform float u_ratio;',
+ 'uniform float u_scale;',
+ 'uniform mat3 u_matrix;',
+
+ 'varying vec4 color;',
+
+ 'void main() {',
+ // Scale from [[-1 1] [-1 1]] to the container:
+ 'gl_Position = vec4(',
+ '((u_matrix * vec3(a_position, 1)).xy /',
+ 'u_resolution * 2.0 - 1.0) * vec2(1, -1),',
+ '0,',
+ '1',
+ ');',
+
+ // Multiply the point size twice:
+ // - x SCALING_RATIO to correct the canvas scaling
+ // - x 2 to correct the formulae
+ 'gl_PointSize = a_size * u_ratio * u_scale * 2.0;',
+
+ // Extract the color:
+ 'float c = a_color;',
+ 'color.b = mod(c, 256.0); c = floor(c / 256.0);',
+ 'color.g = mod(c, 256.0); c = floor(c / 256.0);',
+ 'color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;',
+ 'color.a = 1.0;',
+ '}'
+ ].join('\n'),
+ gl.VERTEX_SHADER
+ );
+
+ fragmentShader = sigma.utils.loadShader(
+ gl,
+ [
+ 'precision mediump float;',
+
+ 'varying vec4 color;',
+
+ 'void main(void) {',
+ 'float border = 0.01;',
+ 'float radius = 0.5;',
+
+ 'vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);',
+ 'vec2 m = gl_PointCoord - vec2(0.5, 0.5);',
+ 'float dist = radius - sqrt(m.x * m.x + m.y * m.y);',
+
+ 'float t = 0.0;',
+ 'if (dist > border)',
+ 't = 1.0;',
+ 'else if (dist > 0.0)',
+ 't = dist / border;',
+
+ 'gl_FragColor = mix(color0, color, t);',
+ '}'
+ ].join('\n'),
+ gl.FRAGMENT_SHADER
+ );
+
+ program = sigma.utils.loadProgram(gl, [vertexShader, fragmentShader]);
+
+ return program;
+ }
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.webgl.edges');
+
+ /**
+ * This edge renderer will display edges as lines going from the source node
+ * to the target node. To deal with edge thicknesses, the lines are made of
+ * two triangles forming rectangles, with the gl.TRIANGLES drawing mode.
+ *
+ * It is expensive, since drawing a single edge requires 6 points, each
+ * having 7 attributes (source position, target position, thickness, color
+ * and a flag indicating which vertice of the rectangle it is).
+ */
+ sigma.webgl.edges.def = {
+ POINTS: 6,
+ ATTRIBUTES: 7,
+ addEdge: function(edge, source, target, data, i, prefix, settings) {
+ var w = (edge[prefix + 'size'] || 1) / 2,
+ x1 = source[prefix + 'x'],
+ y1 = source[prefix + 'y'],
+ x2 = target[prefix + 'x'],
+ y2 = target[prefix + 'y'],
+ color = edge.color;
+
+ if (!color)
+ switch (settings('edgeColor')) {
+ case 'source':
+ color = source.color || settings('defaultNodeColor');
+ break;
+ case 'target':
+ color = target.color || settings('defaultNodeColor');
+ break;
+ default:
+ color = settings('defaultEdgeColor');
+ break;
+ }
+
+ // Normalize color:
+ color = sigma.utils.floatColor(color);
+
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = w;
+ data[i++] = 0.0;
+ data[i++] = color;
+
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = w;
+ data[i++] = 1.0;
+ data[i++] = color;
+
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = w;
+ data[i++] = 0.0;
+ data[i++] = color;
+
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = w;
+ data[i++] = 0.0;
+ data[i++] = color;
+
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = w;
+ data[i++] = 1.0;
+ data[i++] = color;
+
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = w;
+ data[i++] = 0.0;
+ data[i++] = color;
+ },
+ render: function(gl, program, data, params) {
+ var buffer;
+
+ // Define attributes:
+ var colorLocation =
+ gl.getAttribLocation(program, 'a_color'),
+ positionLocation1 =
+ gl.getAttribLocation(program, 'a_position1'),
+ positionLocation2 =
+ gl.getAttribLocation(program, 'a_position2'),
+ thicknessLocation =
+ gl.getAttribLocation(program, 'a_thickness'),
+ minusLocation =
+ gl.getAttribLocation(program, 'a_minus'),
+ resolutionLocation =
+ gl.getUniformLocation(program, 'u_resolution'),
+ matrixLocation =
+ gl.getUniformLocation(program, 'u_matrix'),
+ matrixHalfPiLocation =
+ gl.getUniformLocation(program, 'u_matrixHalfPi'),
+ matrixHalfPiMinusLocation =
+ gl.getUniformLocation(program, 'u_matrixHalfPiMinus'),
+ ratioLocation =
+ gl.getUniformLocation(program, 'u_ratio'),
+ scaleLocation =
+ gl.getUniformLocation(program, 'u_scale');
+
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
+
+ gl.uniform2f(resolutionLocation, params.width, params.height);
+ gl.uniform1f(
+ ratioLocation,
+ params.ratio / Math.pow(params.ratio, params.settings('edgesPowRatio'))
+ );
+ gl.uniform1f(scaleLocation, params.scalingRatio);
+ gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
+ gl.uniformMatrix2fv(
+ matrixHalfPiLocation,
+ false,
+ sigma.utils.matrices.rotation(Math.PI / 2, true)
+ );
+ gl.uniformMatrix2fv(
+ matrixHalfPiMinusLocation,
+ false,
+ sigma.utils.matrices.rotation(-Math.PI / 2, true)
+ );
+
+ gl.enableVertexAttribArray(colorLocation);
+ gl.enableVertexAttribArray(positionLocation1);
+ gl.enableVertexAttribArray(positionLocation2);
+ gl.enableVertexAttribArray(thicknessLocation);
+ gl.enableVertexAttribArray(minusLocation);
+
+ gl.vertexAttribPointer(positionLocation1,
+ 2,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 0
+ );
+ gl.vertexAttribPointer(positionLocation2,
+ 2,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 8
+ );
+ gl.vertexAttribPointer(thicknessLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 16
+ );
+ gl.vertexAttribPointer(minusLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 20
+ );
+ gl.vertexAttribPointer(colorLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 24
+ );
+
+ gl.drawArrays(
+ gl.TRIANGLES,
+ params.start || 0,
+ params.count || (data.length / this.ATTRIBUTES)
+ );
+ },
+ initProgram: function(gl) {
+ var vertexShader,
+ fragmentShader,
+ program;
+
+ vertexShader = sigma.utils.loadShader(
+ gl,
+ [
+ 'attribute vec2 a_position1;',
+ 'attribute vec2 a_position2;',
+ 'attribute float a_thickness;',
+ 'attribute float a_minus;',
+ 'attribute float a_color;',
+
+ 'uniform vec2 u_resolution;',
+ 'uniform float u_ratio;',
+ 'uniform float u_scale;',
+ 'uniform mat3 u_matrix;',
+ 'uniform mat2 u_matrixHalfPi;',
+ 'uniform mat2 u_matrixHalfPiMinus;',
+
+ 'varying vec4 color;',
+
+ 'void main() {',
+ // Find the good point:
+ 'vec2 position = a_thickness * u_ratio *',
+ 'normalize(a_position2 - a_position1);',
+
+ 'mat2 matrix = a_minus * u_matrixHalfPiMinus +',
+ '(1.0 - a_minus) * u_matrixHalfPi;',
+
+ 'position = matrix * position + a_position1;',
+
+ // Scale from [[-1 1] [-1 1]] to the container:
+ 'gl_Position = vec4(',
+ '((u_matrix * vec3(position, 1)).xy /',
+ 'u_resolution * 2.0 - 1.0) * vec2(1, -1),',
+ '0,',
+ '1',
+ ');',
+
+ // Extract the color:
+ 'float c = a_color;',
+ 'color.b = mod(c, 256.0); c = floor(c / 256.0);',
+ 'color.g = mod(c, 256.0); c = floor(c / 256.0);',
+ 'color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;',
+ 'color.a = 1.0;',
+ '}'
+ ].join('\n'),
+ gl.VERTEX_SHADER
+ );
+
+ fragmentShader = sigma.utils.loadShader(
+ gl,
+ [
+ 'precision mediump float;',
+
+ 'varying vec4 color;',
+
+ 'void main(void) {',
+ 'gl_FragColor = color;',
+ '}'
+ ].join('\n'),
+ gl.FRAGMENT_SHADER
+ );
+
+ program = sigma.utils.loadProgram(gl, [vertexShader, fragmentShader]);
+
+ return program;
+ }
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.webgl.edges');
+
+ /**
+ * This edge renderer will display edges as lines with the gl.LINES display
+ * mode. Since this mode does not support well thickness, edges are all drawn
+ * with the same thickness (3px), independantly of the edge attributes or the
+ * zooming ratio.
+ */
+ sigma.webgl.edges.fast = {
+ POINTS: 2,
+ ATTRIBUTES: 3,
+ addEdge: function(edge, source, target, data, i, prefix, settings) {
+ var w = (edge[prefix + 'size'] || 1) / 2,
+ x1 = source[prefix + 'x'],
+ y1 = source[prefix + 'y'],
+ x2 = target[prefix + 'x'],
+ y2 = target[prefix + 'y'],
+ color = edge.color;
+
+ if (!color)
+ switch (settings('edgeColor')) {
+ case 'source':
+ color = source.color || settings('defaultNodeColor');
+ break;
+ case 'target':
+ color = target.color || settings('defaultNodeColor');
+ break;
+ default:
+ color = settings('defaultEdgeColor');
+ break;
+ }
+
+ // Normalize color:
+ color = sigma.utils.floatColor(color);
+
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = color;
+
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = color;
+ },
+ render: function(gl, program, data, params) {
+ var buffer;
+
+ // Define attributes:
+ var colorLocation =
+ gl.getAttribLocation(program, 'a_color'),
+ positionLocation =
+ gl.getAttribLocation(program, 'a_position'),
+ resolutionLocation =
+ gl.getUniformLocation(program, 'u_resolution'),
+ matrixLocation =
+ gl.getUniformLocation(program, 'u_matrix');
+
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
+
+ gl.uniform2f(resolutionLocation, params.width, params.height);
+ gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
+
+ gl.enableVertexAttribArray(positionLocation);
+ gl.enableVertexAttribArray(colorLocation);
+
+ gl.vertexAttribPointer(positionLocation,
+ 2,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 0
+ );
+ gl.vertexAttribPointer(colorLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 8
+ );
+
+ gl.lineWidth(3);
+ gl.drawArrays(
+ gl.LINES,
+ params.start || 0,
+ params.count || (data.length / this.ATTRIBUTES)
+ );
+ },
+ initProgram: function(gl) {
+ var vertexShader,
+ fragmentShader,
+ program;
+
+ vertexShader = sigma.utils.loadShader(
+ gl,
+ [
+ 'attribute vec2 a_position;',
+ 'attribute float a_color;',
+
+ 'uniform vec2 u_resolution;',
+ 'uniform mat3 u_matrix;',
+
+ 'varying vec4 color;',
+
+ 'void main() {',
+ // Scale from [[-1 1] [-1 1]] to the container:
+ 'gl_Position = vec4(',
+ '((u_matrix * vec3(a_position, 1)).xy /',
+ 'u_resolution * 2.0 - 1.0) * vec2(1, -1),',
+ '0,',
+ '1',
+ ');',
+
+ // Extract the color:
+ 'float c = a_color;',
+ 'color.b = mod(c, 256.0); c = floor(c / 256.0);',
+ 'color.g = mod(c, 256.0); c = floor(c / 256.0);',
+ 'color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;',
+ 'color.a = 1.0;',
+ '}'
+ ].join('\n'),
+ gl.VERTEX_SHADER
+ );
+
+ fragmentShader = sigma.utils.loadShader(
+ gl,
+ [
+ 'precision mediump float;',
+
+ 'varying vec4 color;',
+
+ 'void main(void) {',
+ 'gl_FragColor = color;',
+ '}'
+ ].join('\n'),
+ gl.FRAGMENT_SHADER
+ );
+
+ program = sigma.utils.loadProgram(gl, [vertexShader, fragmentShader]);
+
+ return program;
+ }
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.webgl.edges');
+
+ /**
+ * This edge renderer will display edges as arrows going from the source node
+ * to the target node. To deal with edge thicknesses, the lines are made of
+ * three triangles: two forming rectangles, with the gl.TRIANGLES drawing
+ * mode.
+ *
+ * It is expensive, since drawing a single edge requires 9 points, each
+ * having a lot of attributes.
+ */
+ sigma.webgl.edges.arrow = {
+ POINTS: 9,
+ ATTRIBUTES: 11,
+ addEdge: function(edge, source, target, data, i, prefix, settings) {
+ var w = (edge[prefix + 'size'] || 1) / 2,
+ x1 = source[prefix + 'x'],
+ y1 = source[prefix + 'y'],
+ x2 = target[prefix + 'x'],
+ y2 = target[prefix + 'y'],
+ targetSize = target[prefix + 'size'],
+ color = edge.color;
+
+ if (!color)
+ switch (settings('edgeColor')) {
+ case 'source':
+ color = source.color || settings('defaultNodeColor');
+ break;
+ case 'target':
+ color = target.color || settings('defaultNodeColor');
+ break;
+ default:
+ color = settings('defaultEdgeColor');
+ break;
+ }
+
+ // Normalize color:
+ color = sigma.utils.floatColor(color);
+
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = w;
+ data[i++] = targetSize;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = color;
+
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = w;
+ data[i++] = targetSize;
+ data[i++] = 1.0;
+ data[i++] = 1.0;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = color;
+
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = w;
+ data[i++] = targetSize;
+ data[i++] = 1.0;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = color;
+
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = w;
+ data[i++] = targetSize;
+ data[i++] = 1.0;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = color;
+
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = w;
+ data[i++] = targetSize;
+ data[i++] = 0.0;
+ data[i++] = 1.0;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = color;
+
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = w;
+ data[i++] = targetSize;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = 0.0;
+ data[i++] = color;
+
+ // Arrow head:
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = w;
+ data[i++] = targetSize;
+ data[i++] = 1.0;
+ data[i++] = 0.0;
+ data[i++] = 1.0;
+ data[i++] = -1.0;
+ data[i++] = color;
+
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = w;
+ data[i++] = targetSize;
+ data[i++] = 1.0;
+ data[i++] = 0.0;
+ data[i++] = 1.0;
+ data[i++] = 0.0;
+ data[i++] = color;
+
+ data[i++] = x2;
+ data[i++] = y2;
+ data[i++] = x1;
+ data[i++] = y1;
+ data[i++] = w;
+ data[i++] = targetSize;
+ data[i++] = 1.0;
+ data[i++] = 0.0;
+ data[i++] = 1.0;
+ data[i++] = 1.0;
+ data[i++] = color;
+ },
+ render: function(gl, program, data, params) {
+ var buffer;
+
+ // Define attributes:
+ var positionLocation1 =
+ gl.getAttribLocation(program, 'a_pos1'),
+ positionLocation2 =
+ gl.getAttribLocation(program, 'a_pos2'),
+ thicknessLocation =
+ gl.getAttribLocation(program, 'a_thickness'),
+ targetSizeLocation =
+ gl.getAttribLocation(program, 'a_tSize'),
+ delayLocation =
+ gl.getAttribLocation(program, 'a_delay'),
+ minusLocation =
+ gl.getAttribLocation(program, 'a_minus'),
+ headLocation =
+ gl.getAttribLocation(program, 'a_head'),
+ headPositionLocation =
+ gl.getAttribLocation(program, 'a_headPosition'),
+ colorLocation =
+ gl.getAttribLocation(program, 'a_color'),
+ resolutionLocation =
+ gl.getUniformLocation(program, 'u_resolution'),
+ matrixLocation =
+ gl.getUniformLocation(program, 'u_matrix'),
+ matrixHalfPiLocation =
+ gl.getUniformLocation(program, 'u_matrixHalfPi'),
+ matrixHalfPiMinusLocation =
+ gl.getUniformLocation(program, 'u_matrixHalfPiMinus'),
+ ratioLocation =
+ gl.getUniformLocation(program, 'u_ratio'),
+ nodeRatioLocation =
+ gl.getUniformLocation(program, 'u_nodeRatio'),
+ arrowHeadLocation =
+ gl.getUniformLocation(program, 'u_arrowHead'),
+ scaleLocation =
+ gl.getUniformLocation(program, 'u_scale');
+
+ buffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
+
+ gl.uniform2f(resolutionLocation, params.width, params.height);
+ gl.uniform1f(
+ ratioLocation,
+ params.ratio / Math.pow(params.ratio, params.settings('edgesPowRatio'))
+ );
+ gl.uniform1f(
+ nodeRatioLocation,
+ Math.pow(params.ratio, params.settings('nodesPowRatio')) /
+ params.ratio
+ );
+ gl.uniform1f(arrowHeadLocation, 5.0);
+ gl.uniform1f(scaleLocation, params.scalingRatio);
+ gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
+ gl.uniformMatrix2fv(
+ matrixHalfPiLocation,
+ false,
+ sigma.utils.matrices.rotation(Math.PI / 2, true)
+ );
+ gl.uniformMatrix2fv(
+ matrixHalfPiMinusLocation,
+ false,
+ sigma.utils.matrices.rotation(-Math.PI / 2, true)
+ );
+
+ gl.enableVertexAttribArray(positionLocation1);
+ gl.enableVertexAttribArray(positionLocation2);
+ gl.enableVertexAttribArray(thicknessLocation);
+ gl.enableVertexAttribArray(targetSizeLocation);
+ gl.enableVertexAttribArray(delayLocation);
+ gl.enableVertexAttribArray(minusLocation);
+ gl.enableVertexAttribArray(headLocation);
+ gl.enableVertexAttribArray(headPositionLocation);
+ gl.enableVertexAttribArray(colorLocation);
+
+ gl.vertexAttribPointer(positionLocation1,
+ 2,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 0
+ );
+ gl.vertexAttribPointer(positionLocation2,
+ 2,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 8
+ );
+ gl.vertexAttribPointer(thicknessLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 16
+ );
+ gl.vertexAttribPointer(targetSizeLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 20
+ );
+ gl.vertexAttribPointer(delayLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 24
+ );
+ gl.vertexAttribPointer(minusLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 28
+ );
+ gl.vertexAttribPointer(headLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 32
+ );
+ gl.vertexAttribPointer(headPositionLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 36
+ );
+ gl.vertexAttribPointer(colorLocation,
+ 1,
+ gl.FLOAT,
+ false,
+ this.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT,
+ 40
+ );
+
+ gl.drawArrays(
+ gl.TRIANGLES,
+ params.start || 0,
+ params.count || (data.length / this.ATTRIBUTES)
+ );
+ },
+ initProgram: function(gl) {
+ var vertexShader,
+ fragmentShader,
+ program;
+
+ vertexShader = sigma.utils.loadShader(
+ gl,
+ [
+ 'attribute vec2 a_pos1;',
+ 'attribute vec2 a_pos2;',
+ 'attribute float a_thickness;',
+ 'attribute float a_tSize;',
+ 'attribute float a_delay;',
+ 'attribute float a_minus;',
+ 'attribute float a_head;',
+ 'attribute float a_headPosition;',
+ 'attribute float a_color;',
+
+ 'uniform vec2 u_resolution;',
+ 'uniform float u_ratio;',
+ 'uniform float u_nodeRatio;',
+ 'uniform float u_arrowHead;',
+ 'uniform float u_scale;',
+ 'uniform mat3 u_matrix;',
+ 'uniform mat2 u_matrixHalfPi;',
+ 'uniform mat2 u_matrixHalfPiMinus;',
+
+ 'varying vec4 color;',
+
+ 'void main() {',
+ // Find the good point:
+ 'vec2 pos = normalize(a_pos2 - a_pos1);',
+
+ 'mat2 matrix = (1.0 - a_head) *',
+ '(',
+ 'a_minus * u_matrixHalfPiMinus +',
+ '(1.0 - a_minus) * u_matrixHalfPi',
+ ') + a_head * (',
+ 'a_headPosition * u_matrixHalfPiMinus * 0.6 +',
+ '(a_headPosition * a_headPosition - 1.0) * mat2(1.0)',
+ ');',
+
+ 'pos = a_pos1 + (',
+ // Deal with body:
+ '(1.0 - a_head) * a_thickness * u_ratio * matrix * pos +',
+ // Deal with head:
+ 'a_head * u_arrowHead * a_thickness * u_ratio * matrix * pos +',
+ // Deal with delay:
+ 'a_delay * pos * (',
+ 'a_tSize / u_nodeRatio +',
+ 'u_arrowHead * a_thickness * u_ratio',
+ ')',
+ ');',
+
+ // Scale from [[-1 1] [-1 1]] to the container:
+ 'gl_Position = vec4(',
+ '((u_matrix * vec3(pos, 1)).xy /',
+ 'u_resolution * 2.0 - 1.0) * vec2(1, -1),',
+ '0,',
+ '1',
+ ');',
+
+ // Extract the color:
+ 'float c = a_color;',
+ 'color.b = mod(c, 256.0); c = floor(c / 256.0);',
+ 'color.g = mod(c, 256.0); c = floor(c / 256.0);',
+ 'color.r = mod(c, 256.0); c = floor(c / 256.0); color /= 255.0;',
+ 'color.a = 1.0;',
+ '}'
+ ].join('\n'),
+ gl.VERTEX_SHADER
+ );
+
+ fragmentShader = sigma.utils.loadShader(
+ gl,
+ [
+ 'precision mediump float;',
+
+ 'varying vec4 color;',
+
+ 'void main(void) {',
+ 'gl_FragColor = color;',
+ '}'
+ ].join('\n'),
+ gl.FRAGMENT_SHADER
+ );
+
+ program = sigma.utils.loadProgram(gl, [vertexShader, fragmentShader]);
+
+ return program;
+ }
+ };
+})();
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.canvas.labels');
+
+ /**
+ * This label renderer will just display the label on the right of the node.
+ *
+ * @param {object} node The node object.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.labels.def = function(node, context, settings) {
+ var fontSize,
+ prefix = settings('prefix') || '',
+ size = node[prefix + 'size'];
+
+ if (size < settings('labelThreshold'))
+ return;
+
+ if (!node.label || typeof node.label !== 'string')
+ return;
+
+ fontSize = (settings('labelSize') === 'fixed') ?
+ settings('defaultLabelSize') :
+ settings('labelSizeRatio') * size;
+
+ context.font = (settings('fontStyle') ? settings('fontStyle') + ' ' : '') +
+ fontSize + 'px ' + settings('font');
+ context.fillStyle = (settings('labelColor') === 'node') ?
+ (node.color || settings('defaultNodeColor')) :
+ settings('defaultLabelColor');
+
+ context.fillText(
+ node.label,
+ Math.round(node[prefix + 'x'] + size + 3),
+ Math.round(node[prefix + 'y'] + fontSize / 3)
+ );
+ };
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.canvas.hovers');
+
+ /**
+ * This hover renderer will basically display the label with a background.
+ *
+ * @param {object} node The node object.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.hovers.def = function(node, context, settings) {
+ var x,
+ y,
+ w,
+ h,
+ e,
+ fontStyle = settings('hoverFontStyle') || settings('fontStyle'),
+ prefix = settings('prefix') || '',
+ size = node[prefix + 'size'],
+ fontSize = (settings('labelSize') === 'fixed') ?
+ settings('defaultLabelSize') :
+ settings('labelSizeRatio') * size;
+
+ // Label background:
+ context.font = (fontStyle ? fontStyle + ' ' : '') +
+ fontSize + 'px ' + (settings('hoverFont') || settings('font'));
+
+ context.beginPath();
+ context.fillStyle = settings('labelHoverBGColor') === 'node' ?
+ (node.color || settings('defaultNodeColor')) :
+ settings('defaultHoverLabelBGColor');
+
+ if (node.label && settings('labelHoverShadow')) {
+ context.shadowOffsetX = 0;
+ context.shadowOffsetY = 0;
+ context.shadowBlur = 8;
+ context.shadowColor = settings('labelHoverShadowColor');
+ }
+
+ if (node.label && typeof node.label === 'string') {
+ x = Math.round(node[prefix + 'x'] - fontSize / 2 - 2);
+ y = Math.round(node[prefix + 'y'] - fontSize / 2 - 2);
+ w = Math.round(
+ context.measureText(node.label).width + fontSize / 2 + size + 7
+ );
+ h = Math.round(fontSize + 4);
+ e = Math.round(fontSize / 2 + 2);
+
+ context.moveTo(x, y + e);
+ context.arcTo(x, y, x + e, y, e);
+ context.lineTo(x + w, y);
+ context.lineTo(x + w, y + h);
+ context.lineTo(x + e, y + h);
+ context.arcTo(x, y + h, x, y + h - e, e);
+ context.lineTo(x, y + e);
+
+ context.closePath();
+ context.fill();
+
+ context.shadowOffsetX = 0;
+ context.shadowOffsetY = 0;
+ context.shadowBlur = 0;
+ }
+
+ // Node border:
+ if (settings('borderSize') > 0) {
+ context.beginPath();
+ context.fillStyle = settings('nodeBorderColor') === 'node' ?
+ (node.color || settings('defaultNodeColor')) :
+ settings('defaultNodeBorderColor');
+ context.arc(
+ node[prefix + 'x'],
+ node[prefix + 'y'],
+ size + settings('borderSize'),
+ 0,
+ Math.PI * 2,
+ true
+ );
+ context.closePath();
+ context.fill();
+ }
+
+ // Node:
+ var nodeRenderer = sigma.canvas.nodes[node.type] || sigma.canvas.nodes.def;
+ nodeRenderer(node, context, settings);
+
+ // Display the label:
+ if (node.label && typeof node.label === 'string') {
+ context.fillStyle = (settings('labelHoverColor') === 'node') ?
+ (node.color || settings('defaultNodeColor')) :
+ settings('defaultLabelHoverColor');
+
+ context.fillText(
+ node.label,
+ Math.round(node[prefix + 'x'] + size + 3),
+ Math.round(node[prefix + 'y'] + fontSize / 3)
+ );
+ }
+ };
+}).call(this);
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.canvas.nodes');
+
+ /**
+ * The default node renderer. It renders the node as a simple disc.
+ *
+ * @param {object} node The node object.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.nodes.def = function(node, context, settings) {
+ var prefix = settings('prefix') || '';
+
+ context.fillStyle = node.color || settings('defaultNodeColor');
+ context.beginPath();
+ context.arc(
+ node[prefix + 'x'],
+ node[prefix + 'y'],
+ node[prefix + 'size'],
+ 0,
+ Math.PI * 2,
+ true
+ );
+
+ context.closePath();
+ context.fill();
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.canvas.edges');
+
+ /**
+ * The default edge renderer. It renders the edge as a simple line.
+ *
+ * @param {object} edge The edge object.
+ * @param {object} source node The edge source node.
+ * @param {object} target node The edge target node.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.edges.def = function(edge, source, target, context, settings) {
+ var color = edge.color,
+ prefix = settings('prefix') || '',
+ size = edge[prefix + 'size'] || 1,
+ edgeColor = settings('edgeColor'),
+ defaultNodeColor = settings('defaultNodeColor'),
+ defaultEdgeColor = settings('defaultEdgeColor');
+
+ if (!color)
+ switch (edgeColor) {
+ case 'source':
+ color = source.color || defaultNodeColor;
+ break;
+ case 'target':
+ color = target.color || defaultNodeColor;
+ break;
+ default:
+ color = defaultEdgeColor;
+ break;
+ }
+
+ context.strokeStyle = color;
+ context.lineWidth = size;
+ context.beginPath();
+ context.moveTo(
+ source[prefix + 'x'],
+ source[prefix + 'y']
+ );
+ context.lineTo(
+ target[prefix + 'x'],
+ target[prefix + 'y']
+ );
+ context.stroke();
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.canvas.edges');
+
+ /**
+ * This edge renderer will display edges as curves.
+ *
+ * @param {object} edge The edge object.
+ * @param {object} source node The edge source node.
+ * @param {object} target node The edge target node.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.edges.curve = function(edge, source, target, context, settings) {
+ var color = edge.color,
+ prefix = settings('prefix') || '',
+ size = edge[prefix + 'size'] || 1,
+ edgeColor = settings('edgeColor'),
+ defaultNodeColor = settings('defaultNodeColor'),
+ defaultEdgeColor = settings('defaultEdgeColor'),
+ cp = {},
+ sSize = source[prefix + 'size'],
+ sX = source[prefix + 'x'],
+ sY = source[prefix + 'y'],
+ tX = target[prefix + 'x'],
+ tY = target[prefix + 'y'];
+
+ cp = (source.id === target.id) ?
+ sigma.utils.getSelfLoopControlPoints(sX, sY, sSize) :
+ sigma.utils.getQuadraticControlPoint(sX, sY, tX, tY);
+
+ if (!color)
+ switch (edgeColor) {
+ case 'source':
+ color = source.color || defaultNodeColor;
+ break;
+ case 'target':
+ color = target.color || defaultNodeColor;
+ break;
+ default:
+ color = defaultEdgeColor;
+ break;
+ }
+
+ context.strokeStyle = color;
+ context.lineWidth = size;
+ context.beginPath();
+ context.moveTo(sX, sY);
+ if (source.id === target.id) {
+ context.bezierCurveTo(cp.x1, cp.y1, cp.x2, cp.y2, tX, tY);
+ } else {
+ context.quadraticCurveTo(cp.x, cp.y, tX, tY);
+ }
+ context.stroke();
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.canvas.edges');
+
+ /**
+ * This edge renderer will display edges as arrows going from the source node
+ *
+ * @param {object} edge The edge object.
+ * @param {object} source node The edge source node.
+ * @param {object} target node The edge target node.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.edges.arrow = function(edge, source, target, context, settings) {
+ var color = edge.color,
+ prefix = settings('prefix') || '',
+ edgeColor = settings('edgeColor'),
+ defaultNodeColor = settings('defaultNodeColor'),
+ defaultEdgeColor = settings('defaultEdgeColor'),
+ size = edge[prefix + 'size'] || 1,
+ tSize = target[prefix + 'size'],
+ sX = source[prefix + 'x'],
+ sY = source[prefix + 'y'],
+ tX = target[prefix + 'x'],
+ tY = target[prefix + 'y'],
+ aSize = Math.max(size * 2.5, settings('minArrowSize')),
+ d = Math.sqrt(Math.pow(tX - sX, 2) + Math.pow(tY - sY, 2)),
+ aX = sX + (tX - sX) * (d - aSize - tSize) / d,
+ aY = sY + (tY - sY) * (d - aSize - tSize) / d,
+ vX = (tX - sX) * aSize / d,
+ vY = (tY - sY) * aSize / d;
+
+ if (!color)
+ switch (edgeColor) {
+ case 'source':
+ color = source.color || defaultNodeColor;
+ break;
+ case 'target':
+ color = target.color || defaultNodeColor;
+ break;
+ default:
+ color = defaultEdgeColor;
+ break;
+ }
+
+ context.strokeStyle = color;
+ context.lineWidth = size;
+ context.beginPath();
+ context.moveTo(sX, sY);
+ context.lineTo(
+ aX,
+ aY
+ );
+ context.stroke();
+
+ context.fillStyle = color;
+ context.beginPath();
+ context.moveTo(aX + vX, aY + vY);
+ context.lineTo(aX + vY * 0.6, aY - vX * 0.6);
+ context.lineTo(aX - vY * 0.6, aY + vX * 0.6);
+ context.lineTo(aX + vX, aY + vY);
+ context.closePath();
+ context.fill();
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.canvas.edges');
+
+ /**
+ * This edge renderer will display edges as curves with arrow heading.
+ *
+ * @param {object} edge The edge object.
+ * @param {object} source node The edge source node.
+ * @param {object} target node The edge target node.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.edges.curvedArrow =
+ function(edge, source, target, context, settings) {
+ var color = edge.color,
+ prefix = settings('prefix') || '',
+ edgeColor = settings('edgeColor'),
+ defaultNodeColor = settings('defaultNodeColor'),
+ defaultEdgeColor = settings('defaultEdgeColor'),
+ cp = {},
+ size = edge[prefix + 'size'] || 1,
+ tSize = target[prefix + 'size'],
+ sX = source[prefix + 'x'],
+ sY = source[prefix + 'y'],
+ tX = target[prefix + 'x'],
+ tY = target[prefix + 'y'],
+ aSize = Math.max(size * 2.5, settings('minArrowSize')),
+ d,
+ aX,
+ aY,
+ vX,
+ vY;
+
+ cp = (source.id === target.id) ?
+ sigma.utils.getSelfLoopControlPoints(sX, sY, tSize) :
+ sigma.utils.getQuadraticControlPoint(sX, sY, tX, tY);
+
+ if (source.id === target.id) {
+ d = Math.sqrt(Math.pow(tX - cp.x1, 2) + Math.pow(tY - cp.y1, 2));
+ aX = cp.x1 + (tX - cp.x1) * (d - aSize - tSize) / d;
+ aY = cp.y1 + (tY - cp.y1) * (d - aSize - tSize) / d;
+ vX = (tX - cp.x1) * aSize / d;
+ vY = (tY - cp.y1) * aSize / d;
+ }
+ else {
+ d = Math.sqrt(Math.pow(tX - cp.x, 2) + Math.pow(tY - cp.y, 2));
+ aX = cp.x + (tX - cp.x) * (d - aSize - tSize) / d;
+ aY = cp.y + (tY - cp.y) * (d - aSize - tSize) / d;
+ vX = (tX - cp.x) * aSize / d;
+ vY = (tY - cp.y) * aSize / d;
+ }
+
+ if (!color)
+ switch (edgeColor) {
+ case 'source':
+ color = source.color || defaultNodeColor;
+ break;
+ case 'target':
+ color = target.color || defaultNodeColor;
+ break;
+ default:
+ color = defaultEdgeColor;
+ break;
+ }
+
+ context.strokeStyle = color;
+ context.lineWidth = size;
+ context.beginPath();
+ context.moveTo(sX, sY);
+ if (source.id === target.id) {
+ context.bezierCurveTo(cp.x2, cp.y2, cp.x1, cp.y1, aX, aY);
+ } else {
+ context.quadraticCurveTo(cp.x, cp.y, aX, aY);
+ }
+ context.stroke();
+
+ context.fillStyle = color;
+ context.beginPath();
+ context.moveTo(aX + vX, aY + vY);
+ context.lineTo(aX + vY * 0.6, aY - vX * 0.6);
+ context.lineTo(aX - vY * 0.6, aY + vX * 0.6);
+ context.lineTo(aX + vX, aY + vY);
+ context.closePath();
+ context.fill();
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.canvas.edgehovers');
+
+ /**
+ * This hover renderer will display the edge with a different color or size.
+ *
+ * @param {object} edge The edge object.
+ * @param {object} source node The edge source node.
+ * @param {object} target node The edge target node.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.edgehovers.def =
+ function(edge, source, target, context, settings) {
+ var color = edge.color,
+ prefix = settings('prefix') || '',
+ size = edge[prefix + 'size'] || 1,
+ edgeColor = settings('edgeColor'),
+ defaultNodeColor = settings('defaultNodeColor'),
+ defaultEdgeColor = settings('defaultEdgeColor');
+
+ if (!color)
+ switch (edgeColor) {
+ case 'source':
+ color = source.color || defaultNodeColor;
+ break;
+ case 'target':
+ color = target.color || defaultNodeColor;
+ break;
+ default:
+ color = defaultEdgeColor;
+ break;
+ }
+
+ if (settings('edgeHoverColor') === 'edge') {
+ color = edge.hover_color || color;
+ } else {
+ color = edge.hover_color || settings('defaultEdgeHoverColor') || color;
+ }
+ size *= settings('edgeHoverSizeRatio');
+
+ context.strokeStyle = color;
+ context.lineWidth = size;
+ context.beginPath();
+ context.moveTo(
+ source[prefix + 'x'],
+ source[prefix + 'y']
+ );
+ context.lineTo(
+ target[prefix + 'x'],
+ target[prefix + 'y']
+ );
+ context.stroke();
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.canvas.edgehovers');
+
+ /**
+ * This hover renderer will display the edge with a different color or size.
+ *
+ * @param {object} edge The edge object.
+ * @param {object} source node The edge source node.
+ * @param {object} target node The edge target node.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.edgehovers.curve =
+ function(edge, source, target, context, settings) {
+ var color = edge.color,
+ prefix = settings('prefix') || '',
+ size = settings('edgeHoverSizeRatio') * (edge[prefix + 'size'] || 1),
+ edgeColor = settings('edgeColor'),
+ defaultNodeColor = settings('defaultNodeColor'),
+ defaultEdgeColor = settings('defaultEdgeColor'),
+ cp = {},
+ sSize = source[prefix + 'size'],
+ sX = source[prefix + 'x'],
+ sY = source[prefix + 'y'],
+ tX = target[prefix + 'x'],
+ tY = target[prefix + 'y'];
+
+ cp = (source.id === target.id) ?
+ sigma.utils.getSelfLoopControlPoints(sX, sY, sSize) :
+ sigma.utils.getQuadraticControlPoint(sX, sY, tX, tY);
+
+ if (!color)
+ switch (edgeColor) {
+ case 'source':
+ color = source.color || defaultNodeColor;
+ break;
+ case 'target':
+ color = target.color || defaultNodeColor;
+ break;
+ default:
+ color = defaultEdgeColor;
+ break;
+ }
+
+ if (settings('edgeHoverColor') === 'edge') {
+ color = edge.hover_color || color;
+ } else {
+ color = edge.hover_color || settings('defaultEdgeHoverColor') || color;
+ }
+
+ context.strokeStyle = color;
+ context.lineWidth = size;
+ context.beginPath();
+ context.moveTo(sX, sY);
+ if (source.id === target.id) {
+ context.bezierCurveTo(cp.x1, cp.y1, cp.x2, cp.y2, tX, tY);
+ } else {
+ context.quadraticCurveTo(cp.x, cp.y, tX, tY);
+ }
+ context.stroke();
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.canvas.edgehovers');
+
+ /**
+ * This hover renderer will display the edge with a different color or size.
+ *
+ * @param {object} edge The edge object.
+ * @param {object} source node The edge source node.
+ * @param {object} target node The edge target node.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.edgehovers.arrow =
+ function(edge, source, target, context, settings) {
+ var color = edge.color,
+ prefix = settings('prefix') || '',
+ edgeColor = settings('edgeColor'),
+ defaultNodeColor = settings('defaultNodeColor'),
+ defaultEdgeColor = settings('defaultEdgeColor'),
+ size = edge[prefix + 'size'] || 1,
+ tSize = target[prefix + 'size'],
+ sX = source[prefix + 'x'],
+ sY = source[prefix + 'y'],
+ tX = target[prefix + 'x'],
+ tY = target[prefix + 'y'];
+
+ size = (edge.hover) ?
+ settings('edgeHoverSizeRatio') * size : size;
+ var aSize = size * 2.5,
+ d = Math.sqrt(Math.pow(tX - sX, 2) + Math.pow(tY - sY, 2)),
+ aX = sX + (tX - sX) * (d - aSize - tSize) / d,
+ aY = sY + (tY - sY) * (d - aSize - tSize) / d,
+ vX = (tX - sX) * aSize / d,
+ vY = (tY - sY) * aSize / d;
+
+ if (!color)
+ switch (edgeColor) {
+ case 'source':
+ color = source.color || defaultNodeColor;
+ break;
+ case 'target':
+ color = target.color || defaultNodeColor;
+ break;
+ default:
+ color = defaultEdgeColor;
+ break;
+ }
+
+ if (settings('edgeHoverColor') === 'edge') {
+ color = edge.hover_color || color;
+ } else {
+ color = edge.hover_color || settings('defaultEdgeHoverColor') || color;
+ }
+
+ context.strokeStyle = color;
+ context.lineWidth = size;
+ context.beginPath();
+ context.moveTo(sX, sY);
+ context.lineTo(
+ aX,
+ aY
+ );
+ context.stroke();
+
+ context.fillStyle = color;
+ context.beginPath();
+ context.moveTo(aX + vX, aY + vY);
+ context.lineTo(aX + vY * 0.6, aY - vX * 0.6);
+ context.lineTo(aX - vY * 0.6, aY + vX * 0.6);
+ context.lineTo(aX + vX, aY + vY);
+ context.closePath();
+ context.fill();
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.canvas.edgehovers');
+
+ /**
+ * This hover renderer will display the edge with a different color or size.
+ *
+ * @param {object} edge The edge object.
+ * @param {object} source node The edge source node.
+ * @param {object} target node The edge target node.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.edgehovers.curvedArrow =
+ function(edge, source, target, context, settings) {
+ var color = edge.color,
+ prefix = settings('prefix') || '',
+ edgeColor = settings('edgeColor'),
+ defaultNodeColor = settings('defaultNodeColor'),
+ defaultEdgeColor = settings('defaultEdgeColor'),
+ cp = {},
+ size = settings('edgeHoverSizeRatio') * (edge[prefix + 'size'] || 1),
+ tSize = target[prefix + 'size'],
+ sX = source[prefix + 'x'],
+ sY = source[prefix + 'y'],
+ tX = target[prefix + 'x'],
+ tY = target[prefix + 'y'],
+ d,
+ aSize,
+ aX,
+ aY,
+ vX,
+ vY;
+
+ cp = (source.id === target.id) ?
+ sigma.utils.getSelfLoopControlPoints(sX, sY, tSize) :
+ sigma.utils.getQuadraticControlPoint(sX, sY, tX, tY);
+
+ if (source.id === target.id) {
+ d = Math.sqrt(Math.pow(tX - cp.x1, 2) + Math.pow(tY - cp.y1, 2));
+ aSize = size * 2.5;
+ aX = cp.x1 + (tX - cp.x1) * (d - aSize - tSize) / d;
+ aY = cp.y1 + (tY - cp.y1) * (d - aSize - tSize) / d;
+ vX = (tX - cp.x1) * aSize / d;
+ vY = (tY - cp.y1) * aSize / d;
+ }
+ else {
+ d = Math.sqrt(Math.pow(tX - cp.x, 2) + Math.pow(tY - cp.y, 2));
+ aSize = size * 2.5;
+ aX = cp.x + (tX - cp.x) * (d - aSize - tSize) / d;
+ aY = cp.y + (tY - cp.y) * (d - aSize - tSize) / d;
+ vX = (tX - cp.x) * aSize / d;
+ vY = (tY - cp.y) * aSize / d;
+ }
+
+ if (!color)
+ switch (edgeColor) {
+ case 'source':
+ color = source.color || defaultNodeColor;
+ break;
+ case 'target':
+ color = target.color || defaultNodeColor;
+ break;
+ default:
+ color = defaultEdgeColor;
+ break;
+ }
+
+ if (settings('edgeHoverColor') === 'edge') {
+ color = edge.hover_color || color;
+ } else {
+ color = edge.hover_color || settings('defaultEdgeHoverColor') || color;
+ }
+
+ context.strokeStyle = color;
+ context.lineWidth = size;
+ context.beginPath();
+ context.moveTo(sX, sY);
+ if (source.id === target.id) {
+ context.bezierCurveTo(cp.x2, cp.y2, cp.x1, cp.y1, aX, aY);
+ } else {
+ context.quadraticCurveTo(cp.x, cp.y, aX, aY);
+ }
+ context.stroke();
+
+ context.fillStyle = color;
+ context.beginPath();
+ context.moveTo(aX + vX, aY + vY);
+ context.lineTo(aX + vY * 0.6, aY - vX * 0.6);
+ context.lineTo(aX - vY * 0.6, aY + vX * 0.6);
+ context.lineTo(aX + vX, aY + vY);
+ context.closePath();
+ context.fill();
+ };
+})();
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.canvas.extremities');
+
+ /**
+ * The default renderer for hovered edge extremities. It renders the edge
+ * extremities as hovered.
+ *
+ * @param {object} edge The edge object.
+ * @param {object} source node The edge source node.
+ * @param {object} target node The edge target node.
+ * @param {CanvasRenderingContext2D} context The canvas context.
+ * @param {configurable} settings The settings function.
+ */
+ sigma.canvas.extremities.def =
+ function(edge, source, target, context, settings) {
+ // Source Node:
+ (
+ sigma.canvas.hovers[source.type] ||
+ sigma.canvas.hovers.def
+ ) (
+ source, context, settings
+ );
+
+ // Target Node:
+ (
+ sigma.canvas.hovers[target.type] ||
+ sigma.canvas.hovers.def
+ ) (
+ target, context, settings
+ );
+ };
+}).call(this);
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.svg.utils');
+
+ /**
+ * Some useful functions used by sigma's SVG renderer.
+ */
+ sigma.svg.utils = {
+
+ /**
+ * SVG Element show.
+ *
+ * @param {DOMElement} element The DOM element to show.
+ */
+ show: function(element) {
+ element.style.display = '';
+ return this;
+ },
+
+ /**
+ * SVG Element hide.
+ *
+ * @param {DOMElement} element The DOM element to hide.
+ */
+ hide: function(element) {
+ element.style.display = 'none';
+ return this;
+ }
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.svg.nodes');
+
+ /**
+ * The default node renderer. It renders the node as a simple disc.
+ */
+ sigma.svg.nodes.def = {
+
+ /**
+ * SVG Element creation.
+ *
+ * @param {object} node The node object.
+ * @param {configurable} settings The settings function.
+ */
+ create: function(node, settings) {
+ var prefix = settings('prefix') || '',
+ circle = document.createElementNS(settings('xmlns'), 'circle');
+
+ // Defining the node's circle
+ circle.setAttributeNS(null, 'data-node-id', node.id);
+ circle.setAttributeNS(null, 'class', settings('classPrefix') + '-node');
+ circle.setAttributeNS(
+ null, 'fill', node.color || settings('defaultNodeColor'));
+
+ // Returning the DOM Element
+ return circle;
+ },
+
+ /**
+ * SVG Element update.
+ *
+ * @param {object} node The node object.
+ * @param {DOMElement} circle The node DOM element.
+ * @param {configurable} settings The settings function.
+ */
+ update: function(node, circle, settings) {
+ var prefix = settings('prefix') || '';
+
+ // Applying changes
+ // TODO: optimize - check if necessary
+ circle.setAttributeNS(null, 'cx', node[prefix + 'x']);
+ circle.setAttributeNS(null, 'cy', node[prefix + 'y']);
+ circle.setAttributeNS(null, 'r', node[prefix + 'size']);
+
+ // Updating only if not freestyle
+ if (!settings('freeStyle'))
+ circle.setAttributeNS(
+ null, 'fill', node.color || settings('defaultNodeColor'));
+
+ // Showing
+ circle.style.display = '';
+
+ return this;
+ }
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.svg.edges');
+
+ /**
+ * The default edge renderer. It renders the node as a simple line.
+ */
+ sigma.svg.edges.def = {
+
+ /**
+ * SVG Element creation.
+ *
+ * @param {object} edge The edge object.
+ * @param {object} source The source node object.
+ * @param {object} target The target node object.
+ * @param {configurable} settings The settings function.
+ */
+ create: function(edge, source, target, settings) {
+ var color = edge.color,
+ prefix = settings('prefix') || '',
+ edgeColor = settings('edgeColor'),
+ defaultNodeColor = settings('defaultNodeColor'),
+ defaultEdgeColor = settings('defaultEdgeColor');
+
+ if (!color)
+ switch (edgeColor) {
+ case 'source':
+ color = source.color || defaultNodeColor;
+ break;
+ case 'target':
+ color = target.color || defaultNodeColor;
+ break;
+ default:
+ color = defaultEdgeColor;
+ break;
+ }
+
+ var line = document.createElementNS(settings('xmlns'), 'line');
+
+ // Attributes
+ line.setAttributeNS(null, 'data-edge-id', edge.id);
+ line.setAttributeNS(null, 'class', settings('classPrefix') + '-edge');
+ line.setAttributeNS(null, 'stroke', color);
+
+ return line;
+ },
+
+ /**
+ * SVG Element update.
+ *
+ * @param {object} edge The edge object.
+ * @param {DOMElement} line The line DOM Element.
+ * @param {object} source The source node object.
+ * @param {object} target The target node object.
+ * @param {configurable} settings The settings function.
+ */
+ update: function(edge, line, source, target, settings) {
+ var prefix = settings('prefix') || '';
+
+ line.setAttributeNS(null, 'stroke-width', edge[prefix + 'size'] || 1);
+ line.setAttributeNS(null, 'x1', source[prefix + 'x']);
+ line.setAttributeNS(null, 'y1', source[prefix + 'y']);
+ line.setAttributeNS(null, 'x2', target[prefix + 'x']);
+ line.setAttributeNS(null, 'y2', target[prefix + 'y']);
+
+ // Showing
+ line.style.display = '';
+
+ return this;
+ }
+ };
+})();
+
+;(function() {
+ 'use strict';
+
+ sigma.utils.pkg('sigma.svg.edges');
+
+ /**
+ * The curve edge renderer. It renders the node as a bezier curve.
+ */
+ sigma.svg.edges.curve = {
+
+ /**
+ * SVG Element creation.
+ *
+ * @param {object} edge The edge object.
+ * @param {object} source The source node object.
+ * @param {object} target The target node object.
+ * @param {configurable} settings The settings function.
+ */
+ create: function(edge, source, target, settings) {
+ var color = edge.color,
+ prefix = settings('prefix') || '',
+ edgeColor = settings('edgeColor'),
+ defaultNodeColor = settings('defaultNodeColor'),
+ defaultEdgeColor = settings('defaultEdgeColor');
+
+ if (!color)
+ switch (edgeColor) {
+ case 'source':
+ color = source.color || defaultNodeColor;
+ break;
+ case 'target':
+ color = target.color || defaultNodeColor;
+ break;
+ default:
+ color = defaultEdgeColor;
+ break;
+ }
+
+ var path = document.createElementNS(settings('xmlns'), 'path');
+
+ // Attributes
+ path.setAttributeNS(null, 'data-edge-id', edge.id);
+ path.setAttributeNS(null, 'class', settings('classPrefix') + '-edge');
+ path.setAttributeNS(null, 'stroke', color);
+
+ return path;
+ },
+
+ /**
+ * SVG Element update.
+ *
+ * @param {object} edge The edge object.
+ * @param {DOMElement} line The line DOM Element.
+ * @param {object} source The source node object.
+ * @param {object} target The target node object.
+ * @param {configurable} settings The settings function.
+ */
+ update: function(edge, path, source, target, settings) {
+ var prefix = settings('prefix') || '';
+
+ path.setAttributeNS(null, 'stroke-width', edge[prefix + 'size'] || 1);
+
+ // Control point
+ var cx = (source[prefix + 'x'] + target[prefix + 'x']) / 2 +
+ (target[prefix + 'y'] - source[prefix + 'y']) / 4,
+ cy = (source[prefix + 'y'] + target[prefix + 'y']) / 2 +
+ (source[prefix + 'x'] - target[prefix + 'x']) / 4;
+
+ // Path
+ var p = 'M' + source[prefix + 'x'] + ',' + source[prefix + 'y'] + ' ' +
+ 'Q' + cx + ',' + cy + ' ' +
+ target[prefix + 'x'] + ',' + target[prefix + 'y'];
+
+ // Updating attributes
+ path.setAttributeNS(null, 'd', p);
+ path.setAttributeNS(null, 'fill', 'none');
+
+ // Showing
+ path.style.display = '';
+
+ return this;
+ }
+ };
+})();
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.svg.labels');
+
+ /**
+ * The default label renderer. It renders the label as a simple text.
+ */
+ sigma.svg.labels.def = {
+
+ /**
+ * SVG Element creation.
+ *
+ * @param {object} node The node object.
+ * @param {configurable} settings The settings function.
+ */
+ create: function(node, settings) {
+ var prefix = settings('prefix') || '',
+ size = node[prefix + 'size'],
+ text = document.createElementNS(settings('xmlns'), 'text');
+
+ var fontSize = (settings('labelSize') === 'fixed') ?
+ settings('defaultLabelSize') :
+ settings('labelSizeRatio') * size;
+
+ var fontColor = (settings('labelColor') === 'node') ?
+ (node.color || settings('defaultNodeColor')) :
+ settings('defaultLabelColor');
+
+ text.setAttributeNS(null, 'data-label-target', node.id);
+ text.setAttributeNS(null, 'class', settings('classPrefix') + '-label');
+ text.setAttributeNS(null, 'font-size', fontSize);
+ text.setAttributeNS(null, 'font-family', settings('font'));
+ text.setAttributeNS(null, 'fill', fontColor);
+
+ text.innerHTML = node.label;
+ text.textContent = node.label;
+
+ return text;
+ },
+
+ /**
+ * SVG Element update.
+ *
+ * @param {object} node The node object.
+ * @param {DOMElement} text The label DOM element.
+ * @param {configurable} settings The settings function.
+ */
+ update: function(node, text, settings) {
+ var prefix = settings('prefix') || '',
+ size = node[prefix + 'size'];
+
+ var fontSize = (settings('labelSize') === 'fixed') ?
+ settings('defaultLabelSize') :
+ settings('labelSizeRatio') * size;
+
+ // Case when we don't want to display the label
+ if (!settings('forceLabels') && size < settings('labelThreshold'))
+ return;
+
+ if (typeof node.label !== 'string')
+ return;
+
+ // Updating
+ text.setAttributeNS(null, 'x',
+ Math.round(node[prefix + 'x'] + size + 3));
+ text.setAttributeNS(null, 'y',
+ Math.round(node[prefix + 'y'] + fontSize / 3));
+
+ // Showing
+ text.style.display = '';
+
+ return this;
+ }
+ };
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.svg.hovers');
+
+ /**
+ * The default hover renderer.
+ */
+ sigma.svg.hovers.def = {
+
+ /**
+ * SVG Element creation.
+ *
+ * @param {object} node The node object.
+ * @param {CanvasElement} measurementCanvas A fake canvas handled by
+ * the svg to perform some measurements and
+ * passed by the renderer.
+ * @param {DOMElement} nodeCircle The node DOM Element.
+ * @param {configurable} settings The settings function.
+ */
+ create: function(node, nodeCircle, measurementCanvas, settings) {
+
+ // Defining visual properties
+ var x,
+ y,
+ w,
+ h,
+ e,
+ d,
+ fontStyle = settings('hoverFontStyle') || settings('fontStyle'),
+ prefix = settings('prefix') || '',
+ size = node[prefix + 'size'],
+ fontSize = (settings('labelSize') === 'fixed') ?
+ settings('defaultLabelSize') :
+ settings('labelSizeRatio') * size,
+ fontColor = (settings('labelHoverColor') === 'node') ?
+ (node.color || settings('defaultNodeColor')) :
+ settings('defaultLabelHoverColor');
+
+ // Creating elements
+ var group = document.createElementNS(settings('xmlns'), 'g'),
+ rectangle = document.createElementNS(settings('xmlns'), 'rect'),
+ circle = document.createElementNS(settings('xmlns'), 'circle'),
+ text = document.createElementNS(settings('xmlns'), 'text');
+
+ // Defining properties
+ group.setAttributeNS(null, 'class', settings('classPrefix') + '-hover');
+ group.setAttributeNS(null, 'data-node-id', node.id);
+
+ if (typeof node.label === 'string') {
+
+ // Text
+ text.innerHTML = node.label;
+ text.textContent = node.label;
+ text.setAttributeNS(
+ null,
+ 'class',
+ settings('classPrefix') + '-hover-label');
+ text.setAttributeNS(null, 'font-size', fontSize);
+ text.setAttributeNS(null, 'font-family', settings('font'));
+ text.setAttributeNS(null, 'fill', fontColor);
+ text.setAttributeNS(null, 'x',
+ Math.round(node[prefix + 'x'] + size + 3));
+ text.setAttributeNS(null, 'y',
+ Math.round(node[prefix + 'y'] + fontSize / 3));
+
+ // Measures
+ // OPTIMIZE: Find a better way than a measurement canvas
+ x = Math.round(node[prefix + 'x'] - fontSize / 2 - 2);
+ y = Math.round(node[prefix + 'y'] - fontSize / 2 - 2);
+ w = Math.round(
+ measurementCanvas.measureText(node.label).width +
+ fontSize / 2 + size + 9
+ );
+ h = Math.round(fontSize + 4);
+ e = Math.round(fontSize / 2 + 2);
+
+ // Circle
+ circle.setAttributeNS(
+ null,
+ 'class',
+ settings('classPrefix') + '-hover-area');
+ circle.setAttributeNS(null, 'fill', '#fff');
+ circle.setAttributeNS(null, 'cx', node[prefix + 'x']);
+ circle.setAttributeNS(null, 'cy', node[prefix + 'y']);
+ circle.setAttributeNS(null, 'r', e);
+
+ // Rectangle
+ rectangle.setAttributeNS(
+ null,
+ 'class',
+ settings('classPrefix') + '-hover-area');
+ rectangle.setAttributeNS(null, 'fill', '#fff');
+ rectangle.setAttributeNS(null, 'x', node[prefix + 'x'] + e / 4);
+ rectangle.setAttributeNS(null, 'y', node[prefix + 'y'] - e);
+ rectangle.setAttributeNS(null, 'width', w);
+ rectangle.setAttributeNS(null, 'height', h);
+ }
+
+ // Appending childs
+ group.appendChild(circle);
+ group.appendChild(rectangle);
+ group.appendChild(text);
+ group.appendChild(nodeCircle);
+
+ return group;
+ }
+ };
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.middlewares');
+ sigma.utils.pkg('sigma.utils');
+
+ /**
+ * This middleware will rescale the graph such that it takes an optimal space
+ * on the renderer.
+ *
+ * As each middleware, this function is executed in the scope of the sigma
+ * instance.
+ *
+ * @param {?string} readPrefix The read prefix.
+ * @param {?string} writePrefix The write prefix.
+ * @param {object} options The parameters.
+ */
+ sigma.middlewares.rescale = function(readPrefix, writePrefix, options) {
+ var i,
+ l,
+ a,
+ b,
+ c,
+ d,
+ scale,
+ margin,
+ n = this.graph.nodes(),
+ e = this.graph.edges(),
+ settings = this.settings.embedObjects(options || {}),
+ bounds = settings('bounds') || sigma.utils.getBoundaries(
+ this.graph,
+ readPrefix,
+ true
+ ),
+ minX = bounds.minX,
+ minY = bounds.minY,
+ maxX = bounds.maxX,
+ maxY = bounds.maxY,
+ sizeMax = bounds.sizeMax,
+ weightMax = bounds.weightMax,
+ w = settings('width') || 1,
+ h = settings('height') || 1,
+ rescaleSettings = settings('autoRescale'),
+ validSettings = {
+ nodePosition: 1,
+ nodeSize: 1,
+ edgeSize: 1
+ };
+
+ /**
+ * What elements should we rescale?
+ */
+ if (!(rescaleSettings instanceof Array))
+ rescaleSettings = ['nodePosition', 'nodeSize', 'edgeSize'];
+
+ for (i = 0, l = rescaleSettings.length; i < l; i++)
+ if (!validSettings[rescaleSettings[i]])
+ throw new Error(
+ 'The rescale setting "' + rescaleSettings[i] + '" is not recognized.'
+ );
+
+ var np = ~rescaleSettings.indexOf('nodePosition'),
+ ns = ~rescaleSettings.indexOf('nodeSize'),
+ es = ~rescaleSettings.indexOf('edgeSize');
+
+ /**
+ * First, we compute the scaling ratio, without considering the sizes
+ * of the nodes : Each node will have its center in the canvas, but might
+ * be partially out of it.
+ */
+ scale = settings('scalingMode') === 'outside' ?
+ Math.max(
+ w / Math.max(maxX - minX, 1),
+ h / Math.max(maxY - minY, 1)
+ ) :
+ Math.min(
+ w / Math.max(maxX - minX, 1),
+ h / Math.max(maxY - minY, 1)
+ );
+
+ /**
+ * Then, we correct that scaling ratio considering a margin, which is
+ * basically the size of the biggest node.
+ * This has to be done as a correction since to compare the size of the
+ * biggest node to the X and Y values, we have to first get an
+ * approximation of the scaling ratio.
+ **/
+ margin =
+ (
+ settings('rescaleIgnoreSize') ?
+ 0 :
+ (settings('maxNodeSize') || sizeMax) / scale
+ ) +
+ (settings('sideMargin') || 0);
+ maxX += margin;
+ minX -= margin;
+ maxY += margin;
+ minY -= margin;
+
+ // Fix the scaling with the new extrema:
+ scale = settings('scalingMode') === 'outside' ?
+ Math.max(
+ w / Math.max(maxX - minX, 1),
+ h / Math.max(maxY - minY, 1)
+ ) :
+ Math.min(
+ w / Math.max(maxX - minX, 1),
+ h / Math.max(maxY - minY, 1)
+ );
+
+ // Size homothetic parameters:
+ if (!settings('maxNodeSize') && !settings('minNodeSize')) {
+ a = 1;
+ b = 0;
+ } else if (settings('maxNodeSize') === settings('minNodeSize')) {
+ a = 0;
+ b = +settings('maxNodeSize');
+ } else {
+ a = (settings('maxNodeSize') - settings('minNodeSize')) / sizeMax;
+ b = +settings('minNodeSize');
+ }
+
+ if (!settings('maxEdgeSize') && !settings('minEdgeSize')) {
+ c = 1;
+ d = 0;
+ } else if (settings('maxEdgeSize') === settings('minEdgeSize')) {
+ c = 0;
+ d = +settings('minEdgeSize');
+ } else {
+ c = (settings('maxEdgeSize') - settings('minEdgeSize')) / weightMax;
+ d = +settings('minEdgeSize');
+ }
+
+ // Rescale the nodes and edges:
+ for (i = 0, l = e.length; i < l; i++)
+ e[i][writePrefix + 'size'] =
+ e[i][readPrefix + 'size'] * (es ? c : 1) + (es ? d : 0);
+
+ for (i = 0, l = n.length; i < l; i++) {
+ n[i][writePrefix + 'size'] =
+ n[i][readPrefix + 'size'] * (ns ? a : 1) + (ns ? b : 0);
+ n[i][writePrefix + 'x'] =
+ (n[i][readPrefix + 'x'] - (maxX + minX) / 2) * (np ? scale : 1);
+ n[i][writePrefix + 'y'] =
+ (n[i][readPrefix + 'y'] - (maxY + minY) / 2) * (np ? scale : 1);
+ }
+ };
+
+ sigma.utils.getBoundaries = function(graph, prefix, doEdges) {
+ var i,
+ l,
+ e = graph.edges(),
+ n = graph.nodes(),
+ weightMax = -Infinity,
+ sizeMax = -Infinity,
+ minX = Infinity,
+ minY = Infinity,
+ maxX = -Infinity,
+ maxY = -Infinity;
+
+ if (doEdges)
+ for (i = 0, l = e.length; i < l; i++)
+ weightMax = Math.max(e[i][prefix + 'size'], weightMax);
+
+ for (i = 0, l = n.length; i < l; i++) {
+ sizeMax = Math.max(n[i][prefix + 'size'], sizeMax);
+ maxX = Math.max(n[i][prefix + 'x'], maxX);
+ minX = Math.min(n[i][prefix + 'x'], minX);
+ maxY = Math.max(n[i][prefix + 'y'], maxY);
+ minY = Math.min(n[i][prefix + 'y'], minY);
+ }
+
+ weightMax = weightMax || 1;
+ sizeMax = sizeMax || 1;
+
+ return {
+ weightMax: weightMax,
+ sizeMax: sizeMax,
+ minX: minX,
+ minY: minY,
+ maxX: maxX,
+ maxY: maxY
+ };
+ };
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.middlewares');
+
+ /**
+ * This middleware will just copy the graphic properties.
+ *
+ * @param {?string} readPrefix The read prefix.
+ * @param {?string} writePrefix The write prefix.
+ */
+ sigma.middlewares.copy = function(readPrefix, writePrefix) {
+ var i,
+ l,
+ a;
+
+ if (writePrefix + '' === readPrefix + '')
+ return;
+
+ a = this.graph.nodes();
+ for (i = 0, l = a.length; i < l; i++) {
+ a[i][writePrefix + 'x'] = a[i][readPrefix + 'x'];
+ a[i][writePrefix + 'y'] = a[i][readPrefix + 'y'];
+ a[i][writePrefix + 'size'] = a[i][readPrefix + 'size'];
+ }
+
+ a = this.graph.edges();
+ for (i = 0, l = a.length; i < l; i++)
+ a[i][writePrefix + 'size'] = a[i][readPrefix + 'size'];
+ };
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.misc.animation.running');
+
+ /**
+ * Generates a unique ID for the animation.
+ *
+ * @return {string} Returns the new ID.
+ */
+ var _getID = (function() {
+ var id = 0;
+ return function() {
+ return '' + (++id);
+ };
+ })();
+
+ /**
+ * This function animates a camera. It has to be called with the camera to
+ * animate, the values of the coordinates to reach and eventually some
+ * options. It returns a number id, that you can use to kill the animation,
+ * with the method sigma.misc.animation.kill(id).
+ *
+ * The available options are:
+ *
+ * {?number} duration The duration of the animation.
+ * {?function} onNewFrame A callback to execute when the animation
+ * enter a new frame.
+ * {?function} onComplete A callback to execute when the animation
+ * is completed or killed.
+ * {?(string|function)} easing The name of a function from the package
+ * sigma.utils.easings, or a custom easing
+ * function.
+ *
+ * @param {camera} camera The camera to animate.
+ * @param {object} target The coordinates to reach.
+ * @param {?object} options Eventually an object to specify some options to
+ * the function. The available options are
+ * presented in the description of the function.
+ * @return {number} The animation id, to make it easy to kill
+ * through the method "sigma.misc.animation.kill".
+ */
+ sigma.misc.animation.camera = function(camera, val, options) {
+ if (
+ !(camera instanceof sigma.classes.camera) ||
+ typeof val !== 'object' ||
+ !val
+ )
+ throw 'animation.camera: Wrong arguments.';
+
+ if (
+ typeof val.x !== 'number' &&
+ typeof val.y !== 'number' &&
+ typeof val.ratio !== 'number' &&
+ typeof val.angle !== 'number'
+ )
+ throw 'There must be at least one valid coordinate in the given val.';
+
+ var fn,
+ id,
+ anim,
+ easing,
+ duration,
+ initialVal,
+ o = options || {},
+ start = sigma.utils.dateNow();
+
+ // Store initial values:
+ initialVal = {
+ x: camera.x,
+ y: camera.y,
+ ratio: camera.ratio,
+ angle: camera.angle
+ };
+
+ duration = o.duration;
+ easing = typeof o.easing !== 'function' ?
+ sigma.utils.easings[o.easing || 'quadraticInOut'] :
+ o.easing;
+
+ fn = function() {
+ var coef,
+ t = o.duration ? (sigma.utils.dateNow() - start) / o.duration : 1;
+
+ // If the animation is over:
+ if (t >= 1) {
+ camera.isAnimated = false;
+ camera.goTo({
+ x: val.x !== undefined ? val.x : initialVal.x,
+ y: val.y !== undefined ? val.y : initialVal.y,
+ ratio: val.ratio !== undefined ? val.ratio : initialVal.ratio,
+ angle: val.angle !== undefined ? val.angle : initialVal.angle
+ });
+
+ cancelAnimationFrame(id);
+ delete sigma.misc.animation.running[id];
+
+ // Check callbacks:
+ if (typeof o.onComplete === 'function')
+ o.onComplete();
+
+ // Else, let's keep going:
+ } else {
+ coef = easing(t);
+ camera.isAnimated = true;
+ camera.goTo({
+ x: val.x !== undefined ?
+ initialVal.x + (val.x - initialVal.x) * coef :
+ initialVal.x,
+ y: val.y !== undefined ?
+ initialVal.y + (val.y - initialVal.y) * coef :
+ initialVal.y,
+ ratio: val.ratio !== undefined ?
+ initialVal.ratio + (val.ratio - initialVal.ratio) * coef :
+ initialVal.ratio,
+ angle: val.angle !== undefined ?
+ initialVal.angle + (val.angle - initialVal.angle) * coef :
+ initialVal.angle
+ });
+
+ // Check callbacks:
+ if (typeof o.onNewFrame === 'function')
+ o.onNewFrame();
+
+ anim.frameId = requestAnimationFrame(fn);
+ }
+ };
+
+ id = _getID();
+ anim = {
+ frameId: requestAnimationFrame(fn),
+ target: camera,
+ type: 'camera',
+ options: o,
+ fn: fn
+ };
+ sigma.misc.animation.running[id] = anim;
+
+ return id;
+ };
+
+ /**
+ * Kills a running animation. It triggers the eventual onComplete callback.
+ *
+ * @param {number} id The id of the animation to kill.
+ * @return {object} Returns the sigma.misc.animation package.
+ */
+ sigma.misc.animation.kill = function(id) {
+ if (arguments.length !== 1 || typeof id !== 'number')
+ throw 'animation.kill: Wrong arguments.';
+
+ var o = sigma.misc.animation.running[id];
+
+ if (o) {
+ cancelAnimationFrame(id);
+ delete sigma.misc.animation.running[o.frameId];
+
+ if (o.type === 'camera')
+ o.target.isAnimated = false;
+
+ // Check callbacks:
+ if (typeof (o.options || {}).onComplete === 'function')
+ o.options.onComplete();
+ }
+
+ return this;
+ };
+
+ /**
+ * Kills every running animations, or only the one with the specified type,
+ * if a string parameter is given.
+ *
+ * @param {?(string|object)} filter A string to filter the animations to kill
+ * on their type (example: "camera"), or an
+ * object to filter on their target.
+ * @return {number} Returns the number of animations killed
+ * that way.
+ */
+ sigma.misc.animation.killAll = function(filter) {
+ var o,
+ id,
+ count = 0,
+ type = typeof filter === 'string' ? filter : null,
+ target = typeof filter === 'object' ? filter : null,
+ running = sigma.misc.animation.running;
+
+ for (id in running)
+ if (
+ (!type || running[id].type === type) &&
+ (!target || running[id].target === target)
+ ) {
+ o = sigma.misc.animation.running[id];
+ cancelAnimationFrame(o.frameId);
+ delete sigma.misc.animation.running[id];
+
+ if (o.type === 'camera')
+ o.target.isAnimated = false;
+
+ // Increment counter:
+ count++;
+
+ // Check callbacks:
+ if (typeof (o.options || {}).onComplete === 'function')
+ o.options.onComplete();
+ }
+
+ return count;
+ };
+
+ /**
+ * Returns "true" if any animation that is currently still running matches
+ * the filter given to the function.
+ *
+ * @param {string|object} filter A string to filter the animations to kill
+ * on their type (example: "camera"), or an
+ * object to filter on their target.
+ * @return {boolean} Returns true if any running animation
+ * matches.
+ */
+ sigma.misc.animation.has = function(filter) {
+ var id,
+ type = typeof filter === 'string' ? filter : null,
+ target = typeof filter === 'object' ? filter : null,
+ running = sigma.misc.animation.running;
+
+ for (id in running)
+ if (
+ (!type || running[id].type === type) &&
+ (!target || running[id].target === target)
+ )
+ return true;
+
+ return false;
+ };
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.misc');
+
+ /**
+ * This helper will bind any no-DOM renderer (for instance canvas or WebGL)
+ * to its captors, to properly dispatch the good events to the sigma instance
+ * to manage clicking, hovering etc...
+ *
+ * It has to be called in the scope of the related renderer.
+ */
+ sigma.misc.bindEvents = function(prefix) {
+ var i,
+ l,
+ mX,
+ mY,
+ captor,
+ self = this;
+
+ function getNodes(e) {
+ if (e) {
+ mX = 'x' in e.data ? e.data.x : mX;
+ mY = 'y' in e.data ? e.data.y : mY;
+ }
+
+ var i,
+ j,
+ l,
+ n,
+ x,
+ y,
+ s,
+ inserted,
+ selected = [],
+ modifiedX = mX + self.width / 2,
+ modifiedY = mY + self.height / 2,
+ point = self.camera.cameraPosition(
+ mX,
+ mY
+ ),
+ nodes = self.camera.quadtree.point(
+ point.x,
+ point.y
+ );
+
+ if (nodes.length)
+ for (i = 0, l = nodes.length; i < l; i++) {
+ n = nodes[i];
+ x = n[prefix + 'x'];
+ y = n[prefix + 'y'];
+ s = n[prefix + 'size'];
+
+ if (
+ !n.hidden &&
+ modifiedX > x - s &&
+ modifiedX < x + s &&
+ modifiedY > y - s &&
+ modifiedY < y + s &&
+ Math.sqrt(
+ Math.pow(modifiedX - x, 2) +
+ Math.pow(modifiedY - y, 2)
+ ) < s
+ ) {
+ // Insert the node:
+ inserted = false;
+
+ for (j = 0; j < selected.length; j++)
+ if (n.size > selected[j].size) {
+ selected.splice(j, 0, n);
+ inserted = true;
+ break;
+ }
+
+ if (!inserted)
+ selected.push(n);
+ }
+ }
+
+ return selected;
+ }
+
+
+ function getEdges(e) {
+ if (!self.settings('enableEdgeHovering')) {
+ // No event if the setting is off:
+ return [];
+ }
+
+ var isCanvas = (
+ sigma.renderers.canvas && self instanceof sigma.renderers.canvas);
+
+ if (!isCanvas) {
+ // A quick hardcoded rule to prevent people from using this feature
+ // with the WebGL renderer (which is not good enough at the moment):
+ throw new Error(
+ 'The edge events feature is not compatible with the WebGL renderer'
+ );
+ }
+
+ if (e) {
+ mX = 'x' in e.data ? e.data.x : mX;
+ mY = 'y' in e.data ? e.data.y : mY;
+ }
+
+ var i,
+ j,
+ l,
+ a,
+ edge,
+ s,
+ maxEpsilon = self.settings('edgeHoverPrecision'),
+ source,
+ target,
+ cp,
+ nodeIndex = {},
+ inserted,
+ selected = [],
+ modifiedX = mX + self.width / 2,
+ modifiedY = mY + self.height / 2,
+ point = self.camera.cameraPosition(
+ mX,
+ mY
+ ),
+ edges = [];
+
+ if (isCanvas) {
+ var nodesOnScreen = self.camera.quadtree.area(
+ self.camera.getRectangle(self.width, self.height)
+ );
+ for (a = nodesOnScreen, i = 0, l = a.length; i < l; i++)
+ nodeIndex[a[i].id] = a[i];
+ }
+
+ if (self.camera.edgequadtree !== undefined) {
+ edges = self.camera.edgequadtree.point(
+ point.x,
+ point.y
+ );
+ }
+
+ function insertEdge(selected, edge) {
+ inserted = false;
+
+ for (j = 0; j < selected.length; j++)
+ if (edge.size > selected[j].size) {
+ selected.splice(j, 0, edge);
+ inserted = true;
+ break;
+ }
+
+ if (!inserted)
+ selected.push(edge);
+ }
+
+ if (edges.length)
+ for (i = 0, l = edges.length; i < l; i++) {
+ edge = edges[i];
+ source = self.graph.nodes(edge.source);
+ target = self.graph.nodes(edge.target);
+ // (HACK) we can't get edge[prefix + 'size'] on WebGL renderer:
+ s = edge[prefix + 'size'] ||
+ edge['read_' + prefix + 'size'];
+
+ // First, let's identify which edges are drawn. To do this, we keep
+ // every edges that have at least one extremity displayed according to
+ // the quadtree and the "hidden" attribute. We also do not keep hidden
+ // edges.
+ // Then, let's check if the mouse is on the edge (we suppose that it
+ // is a line segment).
+
+ if (
+ !edge.hidden &&
+ !source.hidden && !target.hidden &&
+ (!isCanvas ||
+ (nodeIndex[edge.source] || nodeIndex[edge.target])) &&
+ sigma.utils.getDistance(
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ modifiedX,
+ modifiedY) > source[prefix + 'size'] &&
+ sigma.utils.getDistance(
+ target[prefix + 'x'],
+ target[prefix + 'y'],
+ modifiedX,
+ modifiedY) > target[prefix + 'size']
+ ) {
+ if (edge.type == 'curve' || edge.type == 'curvedArrow') {
+ if (source.id === target.id) {
+ cp = sigma.utils.getSelfLoopControlPoints(
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ source[prefix + 'size']
+ );
+ if (
+ sigma.utils.isPointOnBezierCurve(
+ modifiedX,
+ modifiedY,
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ target[prefix + 'x'],
+ target[prefix + 'y'],
+ cp.x1,
+ cp.y1,
+ cp.x2,
+ cp.y2,
+ Math.max(s, maxEpsilon)
+ )) {
+ insertEdge(selected, edge);
+ }
+ }
+ else {
+ cp = sigma.utils.getQuadraticControlPoint(
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ target[prefix + 'x'],
+ target[prefix + 'y']);
+ if (
+ sigma.utils.isPointOnQuadraticCurve(
+ modifiedX,
+ modifiedY,
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ target[prefix + 'x'],
+ target[prefix + 'y'],
+ cp.x,
+ cp.y,
+ Math.max(s, maxEpsilon)
+ )) {
+ insertEdge(selected, edge);
+ }
+ }
+ } else if (
+ sigma.utils.isPointOnSegment(
+ modifiedX,
+ modifiedY,
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ target[prefix + 'x'],
+ target[prefix + 'y'],
+ Math.max(s, maxEpsilon)
+ )) {
+ insertEdge(selected, edge);
+ }
+ }
+ }
+
+ return selected;
+ }
+
+
+ function bindCaptor(captor) {
+ var nodes,
+ edges,
+ overNodes = {},
+ overEdges = {};
+
+ function onClick(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ self.dispatchEvent('click', e.data);
+
+ nodes = getNodes(e);
+ edges = getEdges(e);
+
+ if (nodes.length) {
+ self.dispatchEvent('clickNode', {
+ node: nodes[0],
+ captor: e.data
+ });
+ self.dispatchEvent('clickNodes', {
+ node: nodes,
+ captor: e.data
+ });
+ } else if (edges.length) {
+ self.dispatchEvent('clickEdge', {
+ edge: edges[0],
+ captor: e.data
+ });
+ self.dispatchEvent('clickEdges', {
+ edge: edges,
+ captor: e.data
+ });
+ } else
+ self.dispatchEvent('clickStage', {captor: e.data});
+ }
+
+ function onDoubleClick(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ self.dispatchEvent('doubleClick', e.data);
+
+ nodes = getNodes(e);
+ edges = getEdges(e);
+
+ if (nodes.length) {
+ self.dispatchEvent('doubleClickNode', {
+ node: nodes[0],
+ captor: e.data
+ });
+ self.dispatchEvent('doubleClickNodes', {
+ node: nodes,
+ captor: e.data
+ });
+ } else if (edges.length) {
+ self.dispatchEvent('doubleClickEdge', {
+ edge: edges[0],
+ captor: e.data
+ });
+ self.dispatchEvent('doubleClickEdges', {
+ edge: edges,
+ captor: e.data
+ });
+ } else
+ self.dispatchEvent('doubleClickStage', {captor: e.data});
+ }
+
+ function onRightClick(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ self.dispatchEvent('rightClick', e.data);
+
+ nodes = getNodes(e);
+ edges = getEdges(e);
+
+ if (nodes.length) {
+ self.dispatchEvent('rightClickNode', {
+ node: nodes[0],
+ captor: e.data
+ });
+ self.dispatchEvent('rightClickNodes', {
+ node: nodes,
+ captor: e.data
+ });
+ } else if (edges.length) {
+ self.dispatchEvent('rightClickEdge', {
+ edge: edges[0],
+ captor: e.data
+ });
+ self.dispatchEvent('rightClickEdges', {
+ edge: edges,
+ captor: e.data
+ });
+ } else
+ self.dispatchEvent('rightClickStage', {captor: e.data});
+ }
+
+ function onOut(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ var k,
+ i,
+ l,
+ le,
+ outNodes = [],
+ outEdges = [];
+
+ for (k in overNodes)
+ outNodes.push(overNodes[k]);
+
+ overNodes = {};
+ // Dispatch both single and multi events:
+ for (i = 0, l = outNodes.length; i < l; i++)
+ self.dispatchEvent('outNode', {
+ node: outNodes[i],
+ captor: e.data
+ });
+ if (outNodes.length)
+ self.dispatchEvent('outNodes', {
+ nodes: outNodes,
+ captor: e.data
+ });
+
+ overEdges = {};
+ // Dispatch both single and multi events:
+ for (i = 0, le = outEdges.length; i < le; i++)
+ self.dispatchEvent('outEdge', {
+ edge: outEdges[i],
+ captor: e.data
+ });
+ if (outEdges.length)
+ self.dispatchEvent('outEdges', {
+ edges: outEdges,
+ captor: e.data
+ });
+ }
+
+ function onMove(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ nodes = getNodes(e);
+ edges = getEdges(e);
+
+ var i,
+ k,
+ node,
+ edge,
+ newOutNodes = [],
+ newOverNodes = [],
+ currentOverNodes = {},
+ l = nodes.length,
+ newOutEdges = [],
+ newOverEdges = [],
+ currentOverEdges = {},
+ le = edges.length;
+
+ // Check newly overred nodes:
+ for (i = 0; i < l; i++) {
+ node = nodes[i];
+ currentOverNodes[node.id] = node;
+ if (!overNodes[node.id]) {
+ newOverNodes.push(node);
+ overNodes[node.id] = node;
+ }
+ }
+
+ // Check no more overred nodes:
+ for (k in overNodes)
+ if (!currentOverNodes[k]) {
+ newOutNodes.push(overNodes[k]);
+ delete overNodes[k];
+ }
+
+ // Dispatch both single and multi events:
+ for (i = 0, l = newOverNodes.length; i < l; i++)
+ self.dispatchEvent('overNode', {
+ node: newOverNodes[i],
+ captor: e.data
+ });
+ for (i = 0, l = newOutNodes.length; i < l; i++)
+ self.dispatchEvent('outNode', {
+ node: newOutNodes[i],
+ captor: e.data
+ });
+ if (newOverNodes.length)
+ self.dispatchEvent('overNodes', {
+ nodes: newOverNodes,
+ captor: e.data
+ });
+ if (newOutNodes.length)
+ self.dispatchEvent('outNodes', {
+ nodes: newOutNodes,
+ captor: e.data
+ });
+
+ // Check newly overred edges:
+ for (i = 0; i < le; i++) {
+ edge = edges[i];
+ currentOverEdges[edge.id] = edge;
+ if (!overEdges[edge.id]) {
+ newOverEdges.push(edge);
+ overEdges[edge.id] = edge;
+ }
+ }
+
+ // Check no more overred edges:
+ for (k in overEdges)
+ if (!currentOverEdges[k]) {
+ newOutEdges.push(overEdges[k]);
+ delete overEdges[k];
+ }
+
+ // Dispatch both single and multi events:
+ for (i = 0, le = newOverEdges.length; i < le; i++)
+ self.dispatchEvent('overEdge', {
+ edge: newOverEdges[i],
+ captor: e.data
+ });
+ for (i = 0, le = newOutEdges.length; i < le; i++)
+ self.dispatchEvent('outEdge', {
+ edge: newOutEdges[i],
+ captor: e.data
+ });
+ if (newOverEdges.length)
+ self.dispatchEvent('overEdges', {
+ edges: newOverEdges,
+ captor: e.data
+ });
+ if (newOutEdges.length)
+ self.dispatchEvent('outEdges', {
+ edges: newOutEdges,
+ captor: e.data
+ });
+ }
+
+ // Bind events:
+ captor.bind('click', onClick);
+ captor.bind('mousedown', onMove);
+ captor.bind('mouseup', onMove);
+ captor.bind('mousemove', onMove);
+ captor.bind('mouseout', onOut);
+ captor.bind('doubleclick', onDoubleClick);
+ captor.bind('rightclick', onRightClick);
+ self.bind('render', onMove);
+ }
+
+ for (i = 0, l = this.captors.length; i < l; i++)
+ bindCaptor(this.captors[i]);
+ };
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.misc');
+
+ /**
+ * This helper will bind any DOM renderer (for instance svg)
+ * to its captors, to properly dispatch the good events to the sigma instance
+ * to manage clicking, hovering etc...
+ *
+ * It has to be called in the scope of the related renderer.
+ */
+ sigma.misc.bindDOMEvents = function(container) {
+ var self = this,
+ graph = this.graph;
+
+ // DOMElement abstraction
+ function Element(domElement) {
+
+ // Helpers
+ this.attr = function(attrName) {
+ return domElement.getAttributeNS(null, attrName);
+ };
+
+ // Properties
+ this.tag = domElement.tagName;
+ this.class = this.attr('class');
+ this.id = this.attr('id');
+
+ // Methods
+ this.isNode = function() {
+ return !!~this.class.indexOf(self.settings('classPrefix') + '-node');
+ };
+
+ this.isEdge = function() {
+ return !!~this.class.indexOf(self.settings('classPrefix') + '-edge');
+ };
+
+ this.isHover = function() {
+ return !!~this.class.indexOf(self.settings('classPrefix') + '-hover');
+ };
+ }
+
+ // Click
+ function click(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ // Generic event
+ self.dispatchEvent('click', e);
+
+ // Are we on a node?
+ var element = new Element(e.target);
+
+ if (element.isNode())
+ self.dispatchEvent('clickNode', {
+ node: graph.nodes(element.attr('data-node-id'))
+ });
+ else
+ self.dispatchEvent('clickStage');
+
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ // Double click
+ function doubleClick(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ // Generic event
+ self.dispatchEvent('doubleClick', e);
+
+ // Are we on a node?
+ var element = new Element(e.target);
+
+ if (element.isNode())
+ self.dispatchEvent('doubleClickNode', {
+ node: graph.nodes(element.attr('data-node-id'))
+ });
+ else
+ self.dispatchEvent('doubleClickStage');
+
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ // On over
+ function onOver(e) {
+ var target = e.toElement || e.target;
+
+ if (!self.settings('eventsEnabled') || !target)
+ return;
+
+ var el = new Element(target);
+
+ if (el.isNode()) {
+ self.dispatchEvent('overNode', {
+ node: graph.nodes(el.attr('data-node-id'))
+ });
+ }
+ else if (el.isEdge()) {
+ var edge = graph.edges(el.attr('data-edge-id'));
+ self.dispatchEvent('overEdge', {
+ edge: edge,
+ source: graph.nodes(edge.source),
+ target: graph.nodes(edge.target)
+ });
+ }
+ }
+
+ // On out
+ function onOut(e) {
+ var target = e.fromElement || e.originalTarget;
+
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ var el = new Element(target);
+
+ if (el.isNode()) {
+ self.dispatchEvent('outNode', {
+ node: graph.nodes(el.attr('data-node-id'))
+ });
+ }
+ else if (el.isEdge()) {
+ var edge = graph.edges(el.attr('data-edge-id'));
+ self.dispatchEvent('outEdge', {
+ edge: edge,
+ source: graph.nodes(edge.source),
+ target: graph.nodes(edge.target)
+ });
+ }
+ }
+
+ // Registering Events:
+
+ // Click
+ container.addEventListener('click', click, false);
+ sigma.utils.doubleClick(container, 'click', doubleClick);
+
+ // Touch counterparts
+ container.addEventListener('touchstart', click, false);
+ sigma.utils.doubleClick(container, 'touchstart', doubleClick);
+
+ // Mouseover
+ container.addEventListener('mouseover', onOver, true);
+
+ // Mouseout
+ container.addEventListener('mouseout', onOut, true);
+ };
+}).call(this);
+
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.misc');
+
+ /**
+ * This method listens to "overNode", "outNode", "overEdge" and "outEdge"
+ * events from a renderer and renders the nodes differently on the top layer.
+ * The goal is to make any node label readable with the mouse, and to
+ * highlight hovered nodes and edges.
+ *
+ * It has to be called in the scope of the related renderer.
+ */
+ sigma.misc.drawHovers = function(prefix) {
+ var self = this,
+ hoveredNodes = {},
+ hoveredEdges = {};
+
+ this.bind('overNode', function(event) {
+ var node = event.data.node;
+ if (!node.hidden) {
+ hoveredNodes[node.id] = node;
+ draw();
+ }
+ });
+
+ this.bind('outNode', function(event) {
+ delete hoveredNodes[event.data.node.id];
+ draw();
+ });
+
+ this.bind('overEdge', function(event) {
+ var edge = event.data.edge;
+ if (!edge.hidden) {
+ hoveredEdges[edge.id] = edge;
+ draw();
+ }
+ });
+
+ this.bind('outEdge', function(event) {
+ delete hoveredEdges[event.data.edge.id];
+ draw();
+ });
+
+ this.bind('render', function(event) {
+ draw();
+ });
+
+ function draw() {
+
+ var k,
+ source,
+ target,
+ hoveredNode,
+ hoveredEdge,
+ c = self.contexts.hover.canvas,
+ defaultNodeType = self.settings('defaultNodeType'),
+ defaultEdgeType = self.settings('defaultEdgeType'),
+ nodeRenderers = sigma.canvas.hovers,
+ edgeRenderers = sigma.canvas.edgehovers,
+ extremitiesRenderers = sigma.canvas.extremities,
+ embedSettings = self.settings.embedObjects({
+ prefix: prefix
+ });
+
+ // Clear self.contexts.hover:
+ self.contexts.hover.clearRect(0, 0, c.width, c.height);
+
+ // Node render: single hover
+ if (
+ embedSettings('enableHovering') &&
+ embedSettings('singleHover') &&
+ Object.keys(hoveredNodes).length
+ ) {
+ hoveredNode = hoveredNodes[Object.keys(hoveredNodes)[0]];
+ (
+ nodeRenderers[hoveredNode.type] ||
+ nodeRenderers[defaultNodeType] ||
+ nodeRenderers.def
+ )(
+ hoveredNode,
+ self.contexts.hover,
+ embedSettings
+ );
+ }
+
+ // Node render: multiple hover
+ if (
+ embedSettings('enableHovering') &&
+ !embedSettings('singleHover')
+ )
+ for (k in hoveredNodes)
+ (
+ nodeRenderers[hoveredNodes[k].type] ||
+ nodeRenderers[defaultNodeType] ||
+ nodeRenderers.def
+ )(
+ hoveredNodes[k],
+ self.contexts.hover,
+ embedSettings
+ );
+
+ // Edge render: single hover
+ if (
+ embedSettings('enableEdgeHovering') &&
+ embedSettings('singleHover') &&
+ Object.keys(hoveredEdges).length
+ ) {
+ hoveredEdge = hoveredEdges[Object.keys(hoveredEdges)[0]];
+ source = self.graph.nodes(hoveredEdge.source);
+ target = self.graph.nodes(hoveredEdge.target);
+
+ if (! hoveredEdge.hidden) {
+ (
+ edgeRenderers[hoveredEdge.type] ||
+ edgeRenderers[defaultEdgeType] ||
+ edgeRenderers.def
+ ) (
+ hoveredEdge,
+ source,
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+
+ if (embedSettings('edgeHoverExtremities')) {
+ (
+ extremitiesRenderers[hoveredEdge.type] ||
+ extremitiesRenderers.def
+ )(
+ hoveredEdge,
+ source,
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+
+ } else {
+ // Avoid edges rendered over nodes:
+ (
+ sigma.canvas.nodes[source.type] ||
+ sigma.canvas.nodes.def
+ ) (
+ source,
+ self.contexts.hover,
+ embedSettings
+ );
+ (
+ sigma.canvas.nodes[target.type] ||
+ sigma.canvas.nodes.def
+ ) (
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+ }
+ }
+ }
+
+ // Edge render: multiple hover
+ if (
+ embedSettings('enableEdgeHovering') &&
+ !embedSettings('singleHover')
+ ) {
+ for (k in hoveredEdges) {
+ hoveredEdge = hoveredEdges[k];
+ source = self.graph.nodes(hoveredEdge.source);
+ target = self.graph.nodes(hoveredEdge.target);
+
+ if (!hoveredEdge.hidden) {
+ (
+ edgeRenderers[hoveredEdge.type] ||
+ edgeRenderers[defaultEdgeType] ||
+ edgeRenderers.def
+ ) (
+ hoveredEdge,
+ source,
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+
+ if (embedSettings('edgeHoverExtremities')) {
+ (
+ extremitiesRenderers[hoveredEdge.type] ||
+ extremitiesRenderers.def
+ )(
+ hoveredEdge,
+ source,
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+ } else {
+ // Avoid edges rendered over nodes:
+ (
+ sigma.canvas.nodes[source.type] ||
+ sigma.canvas.nodes.def
+ ) (
+ source,
+ self.contexts.hover,
+ embedSettings
+ );
+ (
+ sigma.canvas.nodes[target.type] ||
+ sigma.canvas.nodes.def
+ ) (
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+ }
+ }
+ }
+ }
+ }
+ };
+}).call(this);
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/underlay.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/underlay.js
new file mode 100644
index 00000000..05fc3daf
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/underlay.js
@@ -0,0 +1,120 @@
+/* Copyright 2016, Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+function loadUnderlayData(){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.l3vpnservice/openoapi/sdnol3vpn/v1/l3vpns";
+ $
+ .ajax({
+ type : "GET",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ alert("loading underlay data");
+ //TODO: Update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on getting underlay data : " + xhr.responseText);
+ }
+ });
+}
+function deleteUnderlayData(objectId){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.l3vpnservice/openoapi/sdnol3vpn/v1/l3vpns/"+objectId;
+ $
+ .ajax({
+ type : "DELETE",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ alert("deleting underlay data");
+ //TODO: Update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on deleting underlay data : " + xhr.responseText);
+ }
+ });
+}
+function loadOverlayData(){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.overlayvpnservice/openoapi/sdnooverlayvpn/v1/site2dc-vpn";
+ $
+ .ajax({
+ type : "GET",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ alert("loading Overlay data...");
+ //TODO: Update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on getting Overlayvpn data : " + xhr.responseText);
+ }
+ });
+}
+function refressTpDataTable(overlayTable,TpTable){
+ alert("refesssing Tp data table");
+}
+$(function(){
+ $.fn.serializeObject = function() {
+ var o = {};
+ var a = this.serializeArray();
+ $.each(a, function() {
+ if (o[this.name] !== undefined) {
+ if (!o[this.name].push) {
+ o[this.name] = [ o[this.name] ];
+ }
+ o[this.name].push(this.value || '');
+ } else {
+ o[this.name] = this.value || '';
+ }
+ });
+ return o;
+ };
+ $('#createUnderlay').click(function(){
+ var formData = JSON.stringify($("#underlayForm").serializeObject());
+ alert(formData);
+ var jsonobj = JSON.parse(formData);
+ var requestUrl = "http://localhost:8080/org.openo.sdno.l3vpnservice/openoapi/sdnol3vpn/v1/l3vpns";
+ $
+ .ajax({
+ type : "POST",
+ url : requestUrl,
+ contentType : "application/json",
+ dataType : "json",
+ data : formData,
+ success : function(jsonobj) {
+ alert("Details saved successfully!!!");
+ //var data = [jsonobj.name,jsonobj.hostName,jsonobj.productName,jsonobj.vendor,jsonobj.description];
+ //TODO: update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ });
+ $('.underlayNameLink').click(function(){
+ alert("coming here");
+ var data = $(this).parent().parent().parent().find('td:last').find('div:last').html();
+ alert(data);
+ var jsonObj = JSON.parse(data);
+ for(var i = 0; i < jsonObj.length; i++) {
+ var obj = jsonObj[i];
+ var rowData = [obj.tpName,obj.peName,obj.vlanId,obj.siteCidr,obj.ip];
+ $('#underlayTpDataTable').DataTable();
+ $('#underlayTpDataTable').dataTable().fnAddData(rowData);
+ }
+
+ });
+
+}) \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/vpn.js b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/vpn.js
new file mode 100644
index 00000000..eaa53e63
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/js/vpn.js
@@ -0,0 +1,307 @@
+/* Copyright 2016, Huawei Technologies Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+function deleteSite(objectId){
+ alert(objectId);
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/sites"+objectId;
+ $
+ .ajax({
+ type : "DELETE",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ alert("Details deleted successfully!!!");
+ //TODO: Update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on deleting site: " + xhr.responseText);
+ }
+ });
+}
+function deleteLink(objectId){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/topological-links"+objectId;
+ $
+ .ajax({
+ type : "DELETE",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ alert("Details deleted successfully!!!");
+ //TODO: Update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on deleting link : " + xhr.responseText);
+ }
+ });
+}
+
+function deleteNe(objectId){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/sdnobrs/v1/managed-elements"+objectId;
+ $
+ .ajax({
+ type : "DELETE",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ alert("Details deleted successfully!!!");
+ //TODO: Update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on deleting ne : " + xhr.responseText);
+ }
+ });
+}
+
+function deletePort(objectId){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/logical-termination-points"+objectId;
+ $
+ .ajax({
+ type : "DELETE",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ alert("Details deleted successfully!!!");
+ //TODO: Update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on deleting port : " + xhr.responseText);
+ }
+ });
+}
+function loadSiteData(){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/sites";
+ $
+ .ajax({
+ type : "GET",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ alert("loading Site data");
+ //TODO: Update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on getting site data : " + xhr.responseText);
+ }
+ });
+}
+function loadLinkData(){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/topological-links";
+ $
+ .ajax({
+ type : "GET",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ alert("loading Link data");
+ //TODO: Update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on getting link data : " + xhr.responseText);
+ }
+ });
+}
+function loadNeData(){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/sdnobrs/v1/managed-elements";
+ $
+ .ajax({
+ type : "GET",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ alert("loading NE data");
+ //TODO: Update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on getting ne data : " + xhr.responseText);
+ }
+ });
+}
+function loadPortData(){
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/logical-termination-points";
+ $
+ .ajax({
+ type : "GET",
+ url : requestUrl,
+ contentType : "application/json",
+ success : function(jsonobj) {
+ alert("loading port data");
+ //TODO: Update the table
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on getting port data : " + xhr.responseText);
+ }
+ });
+}
+$(function(){
+ $('.creat-btn').click(function(){
+ $('#vmAppDialog').addClass('in').css({'display':'block'});
+
+ });
+ $('.close,.button-previous').click(function(){
+ $('#vmAppDialog').removeClass('in').css('display','none');
+ });
+ $('.detail-top ul li').click(function(){
+ $(this).addClass('current').siblings().removeClass('current');
+ });
+ $('.para').click(function(){
+ if($('#serviceTemplateName').val() == ''){
+ alert('Please choose the service templet!');
+ $('#flavorTab').css('display','none');
+ }else{
+ $('#flavorTab').css('display','block');
+ }
+ $('#basicTab').css('display','block');
+ });
+ $('.basic').click(function(){
+ $('#flavorTab').css('display','none');
+ });
+
+ $('.table tbody tr').click(function(){
+ $(this).addClass('openoTable_row_selected').siblings().removeClass('openoTable_row_selected');
+ });
+ $('.table tr:odd').addClass('active');
+ $('#false').click(function(){
+ $('#vmAppDialog').addClass('in').css({'display':'block'});
+ });
+ $('.close,.button-previous').click(function(){
+ $('#vmAppDialog').removeClass('in').css('display','none');
+ });
+ $('#filterTpLogicalType').click(function(){
+ $('#filterTpLogicalType_select_popupcontainer').toggleClass('openo-hide');
+ $('#filterTpLogicalType').toggleClass('openo-focus');
+ var oLeft = $('#open_base_tpL_td6').offset().left;
+ var oTop = $('#open_base_tpL_td6').offset().top;
+ var oHeight = $('#open_base_tpL_td6').height();
+ $('#filterTpLogicalType_select_popupcontainer').css({'left':oLeft,'top':oTop + oHeight + 10});
+ });
+ $('div.openo-select-popup-container>div.openo-select-item>label').click(function(){
+ var Lvalue = $(this).html();
+ $('#filterTpLogicalType_select_input').attr('value',Lvalue);
+ $('#filterTpLogicalType_select_popupcontainer').addClass('openo-hide');
+ $('#filterTpLogicalType').removeClass('openo-focus');
+ });
+ $.fn.serializeObject = function() {
+ var o = {};
+ var a = this.serializeArray();
+ $.each(a, function() {
+ if (o[this.name] !== undefined) {
+ if (!o[this.name].push) {
+ o[this.name] = [ o[this.name] ];
+ }
+ o[this.name].push(this.value || '');
+ } else {
+ o[this.name] = this.value || '';
+ }
+ });
+ return o;
+ };
+ $('#createSite').click(function(){
+ var formData = JSON.stringify($("#vmAppForm").serializeObject());
+ alert(formData);
+ var jsonobj = JSON.parse(formData);
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/sites";
+ $
+ .ajax({
+ type : "POST",
+ url : requestUrl,
+ contentType : "application/json",
+ dataType : "json",
+ data : formData,
+ success : function(jsonobj) {
+ alert("Details saved successfully!!!");
+ var data = [jsonobj.name,jsonobj.hostName,jsonobj.productName,jsonobj.vendor,jsonobj.description];
+ $('#example').dataTable().fnAddData(data);
+ $('.modal').modal('hide');
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ });
+
+ $('#createNe').click(function(){
+ var formData = JSON.stringify($("#neForm").serializeObject());
+ alert(formData);
+ var jsonobj = JSON.parse(formData);
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/sdnobrs/v1/managed-elements";
+ $
+ .ajax({
+ type : "POST",
+ url : requestUrl,
+ contentType : "application/json",
+ dataType : "json",
+ data : formData,
+ success : function(jsonobj) {
+ alert("Details saved successfully!!!");
+ var data = [jsonobj.name,jsonobj.hostName,jsonobj.productName,jsonobj.vendor,jsonobj.description];
+ $('#example').dataTable().fnAddData(data);
+ $('.modal').modal('hide');
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ });
+
+ $('#createPort').click(function(){
+ var formData = JSON.stringify($("#portForm").serializeObject());
+ alert(formData);
+ var jsonobj = JSON.parse(formData);
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/logical-termination-points";
+ $
+ .ajax({
+ type : "POST",
+ url : requestUrl,
+ contentType : "application/json",
+ dataType : "json",
+ data : formData,
+ success : function(jsonobj) {
+ alert("Details saved successfully!!!");
+ var data = [jsonobj.name,jsonobj.hostName,jsonobj.productName,jsonobj.vendor,jsonobj.description];
+ $('#example').dataTable().fnAddData(data);
+ $('.modal').modal('hide');
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ });
+
+ $('#createLink').click(function(){
+ var formData = JSON.stringify($("#linkForm").serializeObject());
+ alert(formData);
+ var jsonobj = JSON.parse(formData);
+ var requestUrl = "http://localhost:8080/org.openo.sdno.brs/openoapi/sdnobrs/v1/topological-links";
+ $
+ .ajax({
+ type : "POST",
+ url : requestUrl,
+ contentType : "application/json",
+ dataType : "json",
+ data : formData,
+ success : function(jsonobj) {
+ alert("Details saved successfully!!!");
+ var data = [jsonobj.name,jsonobj.hostName,jsonobj.productName,jsonobj.vendor,jsonobj.description];
+ $('#example').dataTable().fnAddData(data);
+ $('.modal').modal('hide');
+ },
+ error : function(xhr, ajaxOptions, thrownError) {
+ alert("Error on page : " + xhr.responseText);
+ }
+ });
+ });
+
+ }) \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/overlayvpn.html b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/overlayvpn.html
new file mode 100644
index 00000000..1a7355cd
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/overlayvpn.html
@@ -0,0 +1,153 @@
+<!--
+
+ Copyright 2016, Huawei Technologies Co., Ltd.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+ <head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+ <link href="css/bootstrap.min.css" rel="stylesheet" />
+ <link href="css/VMMain.css" rel="stylesheet" />
+ <link href="css/bootstrap-table.min.css" rel="stylesheet" />
+ <script type="text/javascript" src="js/jquery-1.11.2.min.js"></script>
+ <script type="text/javascript" src="js/bootstrap.min.js"></script>
+ <script type="text/javascript" src="js/brs.js"></script>
+ <script type="text/javascript" src="js/underlay.js"></script>
+ <script type="text/javascript" src="js/bootstrap-table.min.js"></script>
+ <style type="text/css">
+ </style>
+ <script type="text/javascript">
+ $(document).ready(function() {
+ var jsondata = [];
+ jsondata = loadOverlayData();
+
+ $('#sai').bootstrapTable({
+ //Assigning data to table
+ data: jsondata
+ });
+
+ });
+ function operateFormatter(value, row, index) {
+ return [
+ '<img class="siteDeleteImg" src="images/delete.png" href="javascript:void(0)" style="cursor: pointer" name="title" title="Delete" />'
+ ].join('');
+
+ }
+ window.operateEvents = {
+ 'click .siteDeleteImg': function (e, value, row, index) {
+ // TO DO ajex call for delete
+ console.log(value, row, index);
+ }
+ };
+ </script>
+</head>
+<body id="open_base_vpn_cotentBody" class="cotentBody ng-scope">
+ <div class="container-fluid ms-controller">
+
+ <h3> Overlay VPN </h3>
+ <div class="row-fluid" data-name="table_zone">
+ <div id='ict_virtualApplication_table_div'>
+ <div>
+ <div class="top">
+ <table id="sai" data-pagination="true" data-page-size="5" data-pagination-first-text="First" data-pagination-pre-text="Previous" data-pagination-next-text="Next" data-pagination-last-text="Last">
+ <thead id="soverlayTable_thead" class="openo-table-thead">
+ <tr class="active">
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayName" data-sortable="true">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayName_sorticon" class="openo-table-th-sorticon overflow_elip openoTable_sortable leftHeaderAlign openo-table-disable-element">Name
+ </span>
+ </div>
+ </th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayDesc" data-sortable="true">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayDesc_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element "> Description
+ </span></div></th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayThincCPE" data-sortable="true">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayThincCPE_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Thin CPE
+ </span></div></th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayPortVlanID" data-sortable="true">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayPortVlanID_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Port:Vlan ID
+ </span></div></th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayDCName" data-sortable="true">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayDCName_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">DC Name
+ </span></div></th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayVPC" data-sortable="true">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayVPC_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">VPC
+ </span>
+ </div>
+ </th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayVPCCIDR" data-sortable="true">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="overlayVPCCIDR_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">VPC CIDR
+ </span>
+ </div>
+ </th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="overlayOperation" align="center" data-formatter = "operateFormatter" data-events="operateEvents">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="portAction_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Action</span>
+ </div>
+ </th>
+ </tr></thead>
+ <!-- <tbody>
+ <tr style="display: none;">
+ <td colspan="7" style="text-align: center;">NULL</td>
+ </tr>
+ <tr class="odd openo-table-tr openo-table-disable-element" data-rowid="0" data-tableid="overlayTable">
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="overlayName" data-tableid="overlayTable">
+ <div class="openo-table-disable-element overflow_elip leftDataAlign">
+ <a class="openo-table-disable-element hyperLinkRow" href="javascript:void(0)" id="overlayTable_0_overlayName_link">overlay1</a></div></td>
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="overlayDesc" data-tableid="overlayTable"><div class="overflow_elip leftDataAlign openo-table-custom-el openo-table-disable-element" id="overlayTable_0_overlayDesc_custom_el">overlay 101</div>
+ </td>
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="overlayThincCPE" data-tableid="overlayTable"><div class="overflow_elip leftDataAlign openo-table-custom-el openo-table-disable-element" id="overlayTable_0_overlayThincCPE_custom_el">chaxuanyue</div>
+ </td>
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="overlayPortVlanID" data-tableid="overlayTable"><div class="overflow_elip leftDataAlign openo-table-custom-el openo-table-disable-element" id="overlayTable_0_overlayPortVlanID_custom_el">Bangalore</div>
+ </td>
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="overlayDCName" data-tableid="overlayTable"><div class="overflow_elip leftDataAlign openo-table-custom-el openo-table-disable-element" id="overlayTable_0_overlayDCName_custom_el">Bangalore</div>
+ </td>
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="overlayVPC" data-tableid="overlayTable"><div class="overflow_elip leftDataAlign openo-table-custom-el openo-table-disable-element" id="overlayTable_0_overlayVPC_custom_el">Bangalore</div>
+ </td>
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="overlayVPCCIDR" data-tableid="overlayTable"><div class="overflow_elip leftDataAlign openo-table-custom-el openo-table-disable-element" id="overlayTable_0_overlayVPCCIDR_custom_el">Bangalore</div>
+ </td>
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="overlayOperation" data-tableid="overlayTable">
+ <div class="openo-table-disable-element overflow_elip leftDataAlign openo-table-custom-el" id="overlayTable_0_overlayOperation_custom_el">
+ <div>
+ <img src="images/delete.png" href="javascript:void(0)" onclick="deleteoverlay('this')" opertype="overlayDelete" style="cursor: pointer" title="Delete" id="bac4ff3c-d693-4f54-86cd-25af1ea22f59" rowid="0/">
+ </div>
+ </div>
+ </td>
+ </tr>
+ </tbody> -->
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+
+
+
+
+</body>
+</html> \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/overlayvpn_topo.html b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/overlayvpn_topo.html
new file mode 100644
index 00000000..ddd8eaaa
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/overlayvpn_topo.html
@@ -0,0 +1,42 @@
+<!--
+
+ Copyright 2016, Huawei Technologies Co., Ltd.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<style type="text/css">
+ #container {
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ position: absolute;
+ }
+</style>
+</head>
+<body>
+<div id="container"></div>
+<script src="js/topo/sigma/sigma.min.js"></script>
+<script src="js/topo/sigma/jquery-3.1.0.min.js"></script>
+<script src="js/topo/sigma/plugins/sigma.renderers.customShapes.min.js"></script>
+<script src="js/topo/sigma/plugins/sigma.renderers.edgeLabels.min.js"></script>
+<script src="js/topo/Node.js"></script>
+<script src="js/topo/Edge.js"></script>
+<script src="js/topo/Topology.js"></script>
+</body>
+</html> \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/sdnovpn.html b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/sdnovpn.html
new file mode 100644
index 00000000..75d41cc7
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/sdnovpn.html
@@ -0,0 +1,117 @@
+<!--
+
+ Copyright 2016, Huawei Technologies Co., Ltd.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title></title>
+ <link href="css/bootstrap.min.css" rel="stylesheet" />
+ <link href="css/RMain.css" rel="stylesheet" />
+ <script type="text/javascript" src="js/jquery-1.11.2.min.js"></script>
+ <script type="text/javascript" src="js/bootstrap.min.js"></script>
+</head>
+<script type="text/javascript">
+ $(function(){
+ $('.openo_accordion_ui-icon-expand,.header').click(function(){
+ $('#accordionmenuid_ul_0_0_brAppTopMenuID_UL').slideToggle(500);
+ $('.openo_accordion_ui-icon-expand').toggleClass('current')
+ });
+ $('.openoAccordian_showHideArrow_hide').click(function(){
+ // $('#open_base_openo').css('margin-left','-200px');
+ // $('#open_base_openo').css('display','none');
+ // $('.bar').css('display','block');
+ if($('#accordionmenuid').width() >= 200){
+ $('#accordionmenuid').width('18px');
+ $('.openo_accordion_ui-icon-expand,.header,#accordionmenuid_ul_0_0_brAppTopMenuID_UL li a').css('display','none');
+ $('#accordionmenuid_arrow').attr('classname','openoAccordian_showHideArrow_show');
+ $('#iframeContainer').css('width','1284px');
+ }else if($('#accordionmenuid').width() == 18){
+ $('#accordionmenuid').width('220px');
+ $('.openo_accordion_ui-icon-expand,.header,#accordionmenuid_ul_0_0_brAppTopMenuID_UL li a').css('display','block');
+ $('#accordionmenuid_arrow').attr('classname','openoAccordian_showHideArrow_hide');
+ $('#iframeContainer').css('width','1063px');
+ }
+
+ });
+ $('.bar span').click(function(){
+ $('#open_base_openo').css('display','block');
+ $('.bar').css('display','none');
+ $('#iframeContainer').css('width','1063px');
+ });
+ $('#accordionmenuid_ul_0_0_brAppTopMenuID_UL li').click(function(){
+ $(this).addClass('openo_accordion_selected').siblings().removeClass('openo_accordion_selected');
+ });
+ $('#accordionmenuid_ul_0_0_brAppTopMenuID_UL_1_0_brAppSiteMenuID').click(function(){
+ $('#accordionContent').attr('src','overlayvpn.html');
+ });
+ $('#accordionmenuid_ul_0_0_brAppTopMenuID_UL_1_1_brAppMeMenuID').click(function(){
+ $('#accordionContent').attr('src','underlayvpn.html');
+ });
+ })
+</script>
+<body>
+ <div id="febDiv" style="overflow: hidden;">
+ <div id="open_base_feb">
+ <!--use for store menu come from feb service, maybe just a temple plan-->
+ <div id="app">
+ <div id="iemp_layout_container" ng-controller="resourceCtrl" class="iemp_layout_container ng-scope">
+
+ <table id="open_base_table" class="three-cols-layout">
+ <tbody id="open_base_tbody">
+ <tr id="open_base_tr">
+ <td class="bar">
+ <span></span>
+ </td>
+ <td id="open_base_openo" class="three-cols-column three-cols-left">
+ <div id="accordionmenuid" allow-resize="true" dataset="dataArr" height="resHeight" listeners="callBacklisteners" resize-callback="resizehandler" current-select="currentselect" click="clickHandler" class="ng-isolate-scope accordion_parent openo_accordion_main_menu" style="height: 870px;">
+ <div class="openo-accordion-resizable-handle" style="cursor: auto;"></div>
+ <ul id="accordionmenuid_ul" class="openoAccordian_accordionmenu">
+ <li id="accordionmenuid_ul_0_0_brAppTopMenuID" nodeid="brAppTopMenuID">
+ <span class="openo_accordion_ui-icon-expand" style="padding-left: 20px; height: 60px;cursor: pointer;"></span>
+ <span class="openoAccordian_showHideArrow_hide" id="accordionmenuid_arrow" style="cursor: pointer;"></span>
+ <a title="brApp" class="header opened" style="padding-left: 10px; cursor: pointer;">VPN Manager</a>
+ <ul id="accordionmenuid_ul_0_0_brAppTopMenuID_UL">
+ <li id="accordionmenuid_ul_0_0_brAppTopMenuID_UL_1_0_brAppSiteMenuID" nodeid="brAppSiteMenuID" class="" style="display: list-item;">
+ <a title="点击访问站点" class="" style="padding-left: 62px;">Overlay VPN</a>
+ </li>
+ <li id="accordionmenuid_ul_0_0_brAppTopMenuID_UL_1_1_brAppMeMenuID" nodeid="brAppMeMenuID" style="display: list-item;">
+ <a title="点击访问网元" style="padding-left: 62px;">Underlay VPN</a>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+
+ </td>
+ <td id="open_base_iframe" class="three-cols-column three-cols-center" style="padding: 0px;">
+
+ <div id="iframeContainer" class="frame-class" style="height: 870px;">
+ <iframe id="accordionContent" src="" height="870px"></iframe>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ </div>
+ </div>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/underlayvpn.html b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/underlayvpn.html
new file mode 100644
index 00000000..bd4535cb
--- /dev/null
+++ b/openo-portal/portal-lifecyclemgr/src/main/webapp/lifecyclemgr/underlayvpn.html
@@ -0,0 +1,225 @@
+<!--
+
+ Copyright 2016, Huawei Technologies Co., Ltd.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+ <head lang="en">
+ <meta charset="UTF-8">
+ <title></title>
+ <link href="css/bootstrap.min.css" rel="stylesheet" />
+ <link href="css/jquery.dataTables.min.css" rel="stylesheet" />
+ <link href="css/VMMain.css" rel="stylesheet" />
+ <link href="css/bootstrap-table.min.css" rel="stylesheet" />
+ <script type="text/javascript" src="js/jquery-1.11.2.min.js"></script>
+ <script type="text/javascript" src="js/bootstrap.min.js"></script>
+ <script type="text/javascript" src="js/brs.js"></script>
+ <script type="text/javascript" src="js/underlay.js"></script>
+ <script type="text/javascript" src="js/bootstrap-table.min.js"></script>
+ <style type="text/css">
+ hr {
+ ##-moz-border-bottom-colors: none;
+ -moz-border-image: none;
+ -moz-border-left-colors: none;
+ -moz-border-right-colors: none;
+ -moz-border-top-colors: none;
+ ##border-color: #EEEEEE -moz-use-text-color #FFFFFF;
+ border-style: solid none;
+ border-width: 1px 0;
+ margin: 50px 0;
+}
+ </style>
+ <script type="text/javascript">
+ $(document).ready(function() {
+
+
+var jsondata =loadUnderlayData();
+ $('#tbl_overlay').bootstrapTable({
+ //Assigning data to table
+ data: jsondata
+ });
+ $('#underlayTpDataTable').bootstrapTable({
+ //Assigning data to table
+ data: {}
+ });
+ });
+ function operateFormatter(value, row, index) {
+ return [
+ '<img class="siteDeleteImg" src="images/delete.png" href="javascript:void(0)" style="cursor: pointer" name="title" title="Delete" />'
+ ].join('');
+
+ }
+ window.operateEvents = {
+ 'click .siteDeleteImg': function (e, value, row, index) {
+ // TO DO ajex call for delete
+ console.log(value, row, index);
+ }
+ };
+
+
+ function nameFormatter(value, row) {
+ jsonForTP = row.json.data;
+ var name=JSON.stringify(row.json.data);
+ var temp = "<a class='underlayNameLink' onclick='getMethod(this)' name='"+ name + "' data-events='operateEventsU'>" + value + "</a>";
+ return temp;
+ }
+ function getMethod(obj){
+ //Update the lower table here
+
+ $('#underlayTpDataTable').bootstrapTable(
+ //Assigning data to table
+ "append", JSON.parse(obj.name)
+ );
+ }
+ </script>
+</head>
+<body id="open_base_vpn_cotentBody" class="cotentBody ng-scope">
+ <div class="container-fluid ms-controller">
+ <h3>Underlay VPN</h3>
+ <div class="row-fluid" data-name="table_zone">
+ <div id='ict_virtualApplication_table_div'>
+ <div>
+ <div class="top">
+ <table id="tbl_overlay" data-pagination="true" data-page-size="5" data-pagination-first-text="First" data-pagination-pre-text="Previous" data-pagination-next-text="Next" data-pagination-last-text="Last">
+ <thead id="sunderlayTable_thead" class="openo-table-thead">
+ <tr class="active">
+
+
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-formatter="nameFormatter" data-field="underlayName" data-sortable="true">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="underlayName_sorticon" class="openo-table-th-sorticon overflow_elip openoTable_sortable leftHeaderAlign openo-table-disable-element ">Name
+ </span>
+ </div>
+ </th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="underlayTenantName" data-sortable="true">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="underlayTenantName_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">State
+ </span>
+ </div>
+ </th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="underlayType" data-sortable="true">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="underlayType_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element " >Description
+ </span></div></th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="underlayDescription" align="center" data-formatter = "operateFormatter" data-events="operateEvents">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="underlayDescription_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Action
+ </span>
+ </div>
+ </th>
+ <!-- <th style="display: none;" class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="underlayTenantName">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="underlayObjId_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">ID
+ </span>
+ </div>
+ </th>
+ <th style="display: none;" class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="underlayTenantName">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="underlayObjData_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Data
+ </span>
+ </div>
+ </th> -->
+ </tr>
+ </thead>
+ <!-- <tbody>
+ <tr style="display: none;">
+ <td colspan="7" style="text-align: center;">NULL</td>
+ </tr>
+ <tr class="odd openo-table-tr openo-table-disable-element" data-rowid="0" data-tableid="underlayTable">
+
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="underlayName" data-tableid="underlayTable">
+ <div class="openo-table-disable-element overflow_elip leftDataAlign">
+ <a class="underlayNameLink" href="javascript:void(0)" id="underlayTable_0_underlayName_link">underlay1</a>
+ </div>
+ </td>
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="underlayType" data-tableid="underlayTable">
+ <div class="overflow_elip leftDataAlign openo-table-custom-el openo-table-disable-element" id="underlayTable_0_underlayType_custom_el">underlay 101</div>
+ </td>
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="underlayTenantName" data-tableid="underlayTable">
+ <div class="overflow_elip leftDataAlign openo-table-custom-el openo-table-disable-element" id="underlayTable_0_underlayTenantName_custom_el">chaxuanyue</div>
+ </td>
+ <td class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="underlayOperation" data-tableid="underlayTable">
+ <div class="openo-table-disable-element overflow_elip leftDataAlign openo-table-custom-el" id="underlayTable_0_underlayOperation_custom_el">
+ <div>
+ <img src="images/delete.png" href="javascript:void(0)" onclick="deleteUnderlayData('this')" opertype="underlayDelete" style="cursor: pointer" title="Delete" id="bac4ff3c-d693-4f54-86cd-25af1ea22f59" rowid="0/">
+ </div>
+ </div>
+ </td>
+ <td style="display: none;" class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="underlayType" data-tableid="underlayTable">
+ <div class="overflow_elip leftDataAlign openo-table-custom-el openo-table-disable-element" id="underlayTable_0_underlayType_custom_el">ID12345</div>
+ </td>
+ <td style="display: none;" class="openo-table-disable-element openo-table-td overflow_elip leftDataAlign tableHeaderTDTopBorderColor" data-colid="underlayType" data-tableid="underlayTable">
+ <div class="overflow_elip leftDataAlign openo-table-custom-el openo-table-disable-element" id="underlayTable_0_underlayType_custom_el">[{"tpName":"tp345","peName":"pe123","vlanId":"12344","siteCidr":"tettd","ip":"1.1.1.1"},{"tpName":"tp345","peName":"8xzxze123","vlanId":"234","siteCidr":"tettd","ip":"10.10.1.10"}]</div>
+ </td>
+ </tr>
+ </tbody> -->
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ <hr>
+ <h3>TP Details</h3>
+ <div class="row-fluid" data-name="table_zone">
+ <div id='ict_virtualApplication_table_div'>
+ <div>
+ <div class="top">
+ <table id="underlayTpDataTable" data-pagination="true" data-page-size="5" data-pagination-first-text="First" data-pagination-pre-text="Previous" data-pagination-next-text="Next" data-pagination-last-text="Last">
+ <thead id="underlayTable_thead" class="openo-table-thead">
+ <tr class="active">
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="underlayName">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="underlayName_sorticon" class="openo-table-th-sorticon overflow_elip openoTable_sortable leftHeaderAlign openo-table-disable-element ">TP Name
+ </span>
+ </div>
+ </th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="underlayType">
+ <div class="openo-table-th-border"></div>
+ <div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="underlayType_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">PE Name
+ </span></div></th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="underlayTenantName">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="underlayTenantName_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">VLAN ID
+ </span></div></th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="underlayTenantunderlayName" >
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="underlayTenantunderlayName_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">Site CIDR
+ </span></div></th>
+ <th class="openo-table-state-default openo-table-th openo-table-disable-element leftHeaderAlign" data-field="underlayTenantunderlayIP">
+ <div class="openo-table-th-border"></div><div class="DataTables_sort_wrapper openo-ellipsis ">
+ <span id="underlayTenantunderlayName_sorticon" class="openo-table-th-sorticon overflow_elip leftHeaderAlign openo-table-disable-element ">IP
+ </span></div></th>
+ </tr></thead>
+ <!-- <tbody>
+ </tbody> -->
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="filterTpLogicalType_select_popupcontainer" class="openo openo-select-popup-container openo-hide" style="width: 155px; max-height: 130px; left: 628px; top: 104px; z-index: 1761;"><div class="openo-select-item openo-ellipsis " id="filterTpLogicalType_openo-select-id_0"><label class="openo-ellipsis openo-select-blank-item" style="width: 100%; display: block; height: 20px;"></label></div><div class="openo-select-item openo-ellipsis " id="filterTpLogicalType_openo-select-id_1"><label class="openo-ellipsis " style="width: 100%; display: block; height: 20px;">ETH</label></div><div class="openo-select-item openo-ellipsis " id="filterTpLogicalType_openo-select-id_2"><label class="openo-ellipsis " style="width: 100%; display: block; height: 20px;" title="POS">POS</label></div><div class="openo-select-item openo-ellipsis " id="filterTpLogicalType_openo-select-id_3"><label class="openo-ellipsis " style="width: 100%; display: block; height: 20px;">Trunk</label></div><div class="openo-select-item openo-ellipsis " id="filterTpLogicalType_openo-select-id_4"><label class="openo-ellipsis " style="width: 100%; display: block; height: 20px;">Loopback</label></div></div>
+</body>
+</html> \ No newline at end of file