From db2e5afc3ade00ac958876b24b851bc9a63ddf49 Mon Sep 17 00:00:00 2001 From: dpmcmlxxvi Date: Fri, 24 Jun 2016 11:30:42 -0400 Subject: [PATCH] Use strict mode --- dist/olexp.css | 488 +- dist/olexp.js | 13166 ++++++++++++++++++++-------------------- dist/olexp.min.js | 4 +- dist/olexp.sa.min.css | 8 +- dist/olexp.sa.min.js | 1996 +++--- src/js/control.js | 3512 +++++------ src/js/event.js | 274 +- src/js/explorer.js | 1970 +++--- src/js/item.js | 1055 ++-- src/js/manager.js | 2326 +++---- src/js/measure.js | 1312 ++-- src/js/menu.js | 826 +-- src/js/ol.js | 203 +- src/js/selection.js | 229 +- src/js/util.js | 1439 ++--- 15 files changed, 14414 insertions(+), 14394 deletions(-) diff --git a/dist/olexp.css b/dist/olexp.css index a092239..153525a 100644 --- a/dist/olexp.css +++ b/dist/olexp.css @@ -1,244 +1,244 @@ -/* olexp 0.1.2 (c) Daniel Pulido */ - -/* - * olexp explorer styling - */ - -.olexp-explorer-content, -.olexp-explorer-map -{ - height: 100%; - width: 100%; -} - -.olexp-control-layer-manager-down -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAUVBMVEX///+9vQC9vQCWlpbm5ubb26fExCW+vgDIyCbS01HBwQ3U1VzX2Gbw8KC/vwbExBLAwAbAwAfj43bk5HrBwQjBwQfj43XAwAji4nTZ2VX///9Z+37dAAAAA3RSTlMA1kayq0LiAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAHNJREFUKM/F0ckOgCAMRVHA4SlSFRWH//9RKZogrNwY77InTSAV4t+KrAhl0gdQfARVjSupUqibVvuxbhuZAjoDIoLpkIG5wbyFHhg8DMCYbdiJuHkJGzHArTzfwPDIP9XtNFswPK8j/cQePJfpMVWQ8PMTKmUIMs6ZAJ8AAAAYdEVYdEF1dGhvcgBSb2JlcnQgU3pjemVwYW5la19WsQgAAABSdEVYdENvcHlyaWdodABDQyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzMuMC9eg1q8AAAAGHRFWHRDcmVhdGlvbiBUaW1lADIwMDgtMTItMTJYLju/AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjQyOjQ0LTA0OjAwt/PTXAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNi0wNDowMO1wzfYAAAAndEVYdERlc2NyaXB0aW9uAGh0dHA6Ly9yb2JlcnQuc3pjemVwYW5lay5wbJBZSGAAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); -} - -.olexp-control-layer-control-add-vector -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA+VBMVEX///9HZntLaH1La4BKaHxLaH1LaH1KZ3tFZHhLaH1AWHA9Wm46WmtEYndKZ3w8Wm08WW4+W2w8Wm5AYHBajFpZjFnA3vJJZns8Wm6WlpaUlJVJYnN9hYtWa3pue4Tm5ua1vsNUbn/i4+S6wsdRbH3i4uNwhZOVo63l5eVedoaqtbzR1NdJZXfT1tmrtbxddYWToqtziJVSbH66wcZUbX64wMabqbFtgpFWb4DY2txLZnnIzdBie4xNan5qgZFeeIped4qrt79dd4nF0cV4n3hajFpynXOBqIKFq4bO2s/M2M2IrImKrovs7e3N2c7P2tC8y7y5ybn///9EpCZXAAAAFnRSTlMAieVi5t3c9K7gIOwfw+98ri3qEMk8P+Ru4wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAADpSURBVCjPbdLrTsIwAIbhwhBEBVHHoCp+gKIoKKjgCVGRjU3pFO7/ZuwBKHZ7f7RpnzRplxFCEkmLxJZyNvTCSluLgU+ZTQ1Zp1Qul5y0XGxt76wgl9cnCNktLPf39g/0aUoPj46pqnJCqQagWqtDdHrWwD/A+YXYb15ewYBW+5qPN52mCejeAvW7e2igChq9Ph4eEQVUn55fBnGA1+EbYuHd+YiH0ecIGLuezC5qkLkTP/j6DvyJbYA3ZSwMGZt6JjAFLAI/oew3AjM1zyWsJW7EmUf0NxOtg2oBNt+az8RDjD+maC8f+AeaIjk7ipjOKAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNVQxMToyNTozNC0wNDowMNic0/sAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MjctMDQ6MDCHrcbcAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg=='); -} - -.olexp-control-graticule -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABZVBMVEW01e9bhb+DqdR6otB+pNLI5vqJr9iFq9VHdLR8o9HE4/jA3/ZslMhIdbWSt93H5flmkMWoyei+3fROerhUgLt0m8xoksaCqNSDqtXF4/hPe7irzOqGrNZahb5hi8KfwuRdh8DG5PmszetymstNebdnkMV0nMxLd7ZVgbxYg72myOeAptOOs9u42PGnyeiavuGNstqFq9aLsNlul8ldiMCx0e1RfLm21vC72/NTfrrH5vp9pNGZveF1nM1zmstQfbmGq9bB4PZ3ns6Xu+CDqNRIdbS62vN5oM9Sfbp4n86gwuRUf7u62fLD4ve52fKRtdxjjcSMsdqaveG11fDC4fdpkseQtNx6odCbv+KBp9RrlMdtlsmhw+XF5Pmpy+lkjsSHrNeHrddokcaQtdxkjcSqy+pJdbWHrNauz+yszutLeLZeiMBljsSDqdVeicFMeLdZhL6Msdmz1O9VgLuWut/G5fn///9aqb94AAAAAWJLR0R2MWPJQQAAAAlwSFlzAAAN1wAADdcBQiibeAAAAXRJREFUKM9l0Pk3AlEUB/BXfBmFGpMiRkUNaUGLtrFUKFtpsaRV2ZdK8v97M4j45Z773ueee8+9hCiUA4PA0DDAAMNDwOCISqkgBOrRsXENtKwMrBaY4HSTahBAb9ArprhpGaaNM7MKfg6gYDJbML9g1dkExiDYFpeU8xaziYLKvkzd4XS5V5jVFfeag76W7SoQj5dm8Pkht4LfJz29HpD1AE2CofAXhENBGgPrQRKRKsQNfAE2RCkqN8nWdhSIxXsQj9EQ3dkle4nk/sHhUQ+OdMcH+8mEk+6RSp+MeTNZNsfkc2w2Y7WeplMIE6nq7PyiINh4xsrbhMKlR/qCDMUSeq1QKvagbIz+gqix/A2VKn4BqpVvqF31wVVNhnrDdX3TBzfXcDXqpJRI3t7dq39A/fD4FEqUaCvT80uTa7U/z95ucc32q0aeEWnQOrqbdHY2lwcakc/hfAd9M9DhZUi94Q/gLSVBN/YPYl0K74L4D0QB7x8Kmj3ZLAlwHgAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0xMC0yMoA45boAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjVUMTE6NTE6MTEtMDQ6MDDoUU7YAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI2LTA0OjAwIdrNaAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAPdEVYdFRpdGxlAGdyYXRpY3VsZZJv4HwAAAAASUVORK5CYII='); -} - -.olexp-control-export-map -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAwFBMVEX///+ZmZmcnJyampqYmJiZmZmbm5u3t7eqqqqampqXl5eYmJiZmZk8W246W22ZmZmVlZWcnJyAgICbm5vT09Pg4ODm5ubf39+WlpbR0dHX19fZ2dm3wMVXcYE8Wm5RbX5pgZBthZRxiJZ0i5lwh5XY2911i5mClqLU2Nrb3d6PoKuvr6+ioqK/v7/j5OSpqam7u7ulpaVke4rW2Nqzs7PIyMjHx8esrKzL0NNQany3t7fJycnOzs7R1ddKZHT///8tFxR7AAAAFHRSTlMAI7TffAqt/veV+/no1kbmWfgCvQR3K/YAAAABYktHRACIBR1IAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAqklEQVQoz9XRWQ6CMBCA4borWkXFEReGRSiCO66oeP9jWWIEa+oB/J+afpmkzRDyq0KxVK7IoFrT6g0ZKAMYNmWgA4Au1sphpI0nkKX/PUwNfEXbIhimZTszx7ZMKgK6HniM+czFL2DA5swPQiYBXhiEHBbLlTiRHtYcNttdDgjpm6J9hKRzOJ7On3DBmN8jUbvX2z2HBBLEmE+RntpXst098B0V99ym2c+fRzQtIQC3ZTAAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjVUMTE6NTI6MDMtMDQ6MDBYU+RsAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI5LTA0OjAw15K9gQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII='); -} - -.olexp-control-measure-length -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYBAMAAAASWSDLAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAGFBMVEX///9VV1NSU1HT18+Rk488Wm5QUFD////r4EM9AAAABXRSTlMA/f79/vIq1voAAAABYktHRACIBR1IAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAQklEQVQY02NgoBiwwhgBGJxQKMDkICsjAzAKKgpBkQADo3GyGRRhcJxNjJNNQCSIAwTJIALGcUbmGMM4gnAggNsBAKVhFsLRWT/tAAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDA4LTEyLTEyWC47vwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNVQxMTo1MToxMS0wNDowMOhRTtgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzYtMDQ6MDDtcM32AAAAJ3RFWHREZXNjcmlwdGlvbgBodHRwOi8vcm9iZXJ0LnN6Y3plcGFuZWsucGyQWUhgAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg=='); -} - -.olexp-control-edit-settings -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAB/lBMVEX////IpgvFogLEogDDnwDIpgvHnwDGowjJpw7GowbGowTIpgfGowPkzmHNrRrGpAjHpgnGogTNqwzixiDGowLNrRvEoQPEoQLNqwnixhvIpQPNqgbGowDNqgXGogDSshDGowLSsQ3EoQHHpAHHowDDnwC/nwDSsQrFoQDGowHSsQzRrwbIpgjHpQfHpQXSsQnQrwXEoQDGogDGogLNqwfJpwHGowLNqgfIpgHGoQDIpgTGowDixRXMqQPWtwLFogDGowHixBDLqAPGogHGogHHpAHy44r88qrz5Y7+9a/676P34jr365r+9KT25nT34Tn75jn75TX88qj47Jz98pn87nj86lb13zn54zn75jf75TP75C/33yj98Y787Wz76Ev75z775jr75Tb75TL75C733yf974P862L03jn03Tb75TH75Cz54Cbz3kjy2Sf75Cv74yf13B/74yb74yL64R3v1RXozQ/kyQvfwwb750H02hz54Bz02xbv1hHq0QvlzAbiyQT750D75jv03TDx1hfy2RTt1A/ozwnjygTx4HDx31jx2j313zfw1xPr0g3mzQjfxQTdwgPcwQP13i/y2CLozQ7gxgT54S374yP74h/s0hLiyAT33yv75Cr13BjhxwT33yn74yj74yT74iD33Rvv1RTz2hjkyQjy2Bb///9QqXrkAAAARnRSTlMAtfseVd8g6feKivfp/POH34fz/Onz/Pzz/PfzivOH8/Pz/N+1gAjz+/Pz87Xf3/Pz/N+H8/OK8/OK9/f88/zp6fzz3+n3Dl9naQAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAAGOSURBVCjPY2AgCBiZgIARTZCZhYGB1c3d3Y2VgYGFGSHOxs7BycDq4enpwcrAxc3DhhDn9eLjB0sICAp5C4tAZZjZeT09vUTFfDx9/cQl/AMCJUUgprFweHl6egYFe4aEhoVHREZFx0ixQLRw8oFkPGPj4hMSk5JTUqVlYJbwiwZ5+qalZ2QGBGZl58jKQd3PysoqFhwSmiuvoKCYl19QqKSsrKwClGBy8/DwARojr6qmpqpeVFxSWlZeoQGScAcZU5mpoMbAoKZZVV1TW1ffAJEAuqaxqRki0dLa1t7RAZHo7OruAbpGC2SUdm9f/4SJEyeBJHR09fSUJmdlT9HX1DSYWlc/zdDIyEgF4jBjk+n5BTNmtswCGTPbVA7mDTPzOXOBrpkHNKYDCOZbWELEWawWLFy0eMlSoGs6ps0GyVhDgoRZxGbGzGW2hss7OiYYms7v6LCzh0YJm4PjCic554kdHRON5Czm29kjIsTF1ZLBCCzBYGmNEIdErdGkhoZJRqhRCwYqGkCgQjjRAAC4W228IT8VJAAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0wNC0wM3cLCUkAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjVUMTE6NTI6MDMtMDQ6MDBYU+RsAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjM1LTA0OjAw3JjXawAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAOdEVYdFRpdGxlAHNldHRpbmdzRrN3QwAAAABJRU5ErkJggg=='); -} - -.olexp-control-measure-area -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYBAMAAAASWSDLAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAG1BMVEX///9VV1NSU1HT18+Rk488Wm6CoLRQUFD///+VUipIAAAABXRSTlMA/f79/vIq1voAAAABYktHRACIBR1IAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAWklEQVQY02NgQAGsoaEBCE5aGgonFAIgHAhIJcgBakBwAkAkJicUZCuUA3dHKAMewCioKARFAgyMxsXmUITBcTYxLjYBkSAOEBSDCBjHGZljDOMIwoEAbgcAAFUrLNBnsGw7AAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDA4LTEyLTEyWC47vwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNVQxMTo1MToxMS0wNDowMOhRTtgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzUtMDQ6MDDcmNdrAAAAJ3RFWHREZXNjcmlwdGlvbgBodHRwOi8vcm9iZXJ0LnN6Y3plcGFuZWsucGyQWUhgAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg=='); -} - -.olexp-control-layer-control-add-tile -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAARVBMVEX///9ajFpZjFk8Wm6CoLSWlpbm5ubF0cV4n3hajFpumm6AqIGEqoXO2s/M2M2GrIeKrovs7e3N2c7P2tC8y7y5ybn///8H9fLcAAAAA3RSTlMAyTzPIdReAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAHRJREFUKM+t0ksOgCAMQEGqoqIoxc/9r2pbwCiYuOFtmnQ2EFDqr5bqKJ71QUtpyTNBz1WENtbrtK4Pd98wjEaCJoNxmu2y2nmCDIxD9B7RmRwwABaweWkv4AjzFHjEJyKmlH491xNCEYBW58EXyf5KA+mCF5KaCagHkknTAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI1VDExOjI1OjM0LTA0OjAw2JzT+wAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNS0wNDowMNyY12sAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); -} - -.olexp-control-toolbar-hide -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABWVBMVEX///8AAAArK0ArNTUwNzcuMzgtNTUwNDQoNjY3Nzc6QkJHTU5UWVpna212eXqBhIaPkpKcnp+Tl5hxdHZhZmdXXV5NU1VITU9ATU0AAABCRklaX2DDxcXl5eW9v79rb3FOUlQ/RkbHx8esr6/j4+OXmpro6Ojm5ubl5eXm5ubm5ubp6enp6enm5ubLy8tVWlxVampNUlRWW1tjZ2h5fX6oqqplamtTV1gxMTFTWVp+goPIyci0trWDiIjX19eChIaNkJBcYGEgQEAnOztITU1ydXeipKRlaWu2uLjY2tqQk5V3enuIjIy+wb5fZGUzMzNeYmPHyMePkpJxdXVucnJ4fX58f4B1eXpzdnaFiInHycetr69ZXV8uLi5VVVVXWlx3enq/wcGoqqpnbGxOVFRMTlFgZWZucnJ2ent1eXlnbG1YXF5ARUXu7uzd3dzh4uDt7evp6uj////Z6plGAAAAbXRSTlMAAQwYJTI/OxMObZakqammpJ2arbKonHgUAm2njICQtaRFMpaBnSFwbWhlOS8KitUMbaDOwp/qmRXB3v3yrYW97scIDWrX672ChK/X5P3MD8H85ca+rr/Lz+P88KoLA43V+u/GWFu0wcvNuaA0nka8DgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAAC0SURBVCjPY2CgOmBkYmZhZWPnQBXl5OLm4eXjFxAUEhYRFROXgApLSknLyCIBOXkFRbCEkrIsGlBRVQNJqMtiAg2QhCYWCS2QhDYWCR2QhC6GWXr6BkA3GRoZm6CKm5qZA9VbWFpZ29giCdvZOzg6gZ3r7OLq5u4BEfX08vbx9fOH+dwiIDAoOCQ0LDwiMio3OiYWESZx8QmJuXn5BbmFSckpqMEVl5qWnpGZlZ1D/fihCwAAE8IpsYDcOLEAAAAYdEVYdEF1dGhvcgBSb2JlcnQgU3pjemVwYW5la19WsQgAAABSdEVYdENvcHlyaWdodABDQyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzMuMC9eg1q8AAAAGHRFWHRDcmVhdGlvbiBUaW1lADIwMDgtMTItMTJYLju/AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDE2OjIzOjQ0LTA0OjAwDFw9bAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzoyNi0wNDowMCHazWgAAAAndEVYdERlc2NyaXB0aW9uAGh0dHA6Ly9yb2JlcnQuc3pjemVwYW5lay5wbJBZSGAAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); -} - -.olexp-control-layer-manager-navigation -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYBAMAAAASWSDLAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAMFBMVEX///9BX3JBX3JCX3I8Wm7I5vqmxdhEY3dAXnNph5tlhJhFYnfm5uZXcIGst77///+b4/bXAAAABHRSTlMA6P3oG6ESOAAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAABMSURBVBjTY2DADURcoMARyHENhYIQIMetxCN1ClDCC8xp8U5dAuR4hqArU4EZ4ATk+JyBgiMgzhXfM0+AEn5HMGQGXJkJzNXOeMIGALCya915oHCyAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDE3OjUwOjI1LTA0OjAwc95IWgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNC0wNDowMHrv3N8AAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); -} - -.olexp-control-layer-manager-up -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAb1BMVEX///+9vQC9vQCWlpbm5ubb26fExCW+vgDIyCbS01HT1FjQ0UvDwxTPz0XU1VzX2GbS01DCwg3a2lrBwQzR0UvR0k/j43jw8KDl5X3Q0UzCwgzk5Hnl5XzR0k3k5Hrk5Hu/vwbDww/AwAa/vwX///86q3s0AAAAA3RSTlMA1kayq0LiAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAH5JREFUKM/F0dsOgjAMgOGVCQUE5pxQ5Xx4/3d0i4nQ3hP+myX9brpUqWvToh1urBNAnwRxgr8g4pCkWX4vyjxLgQNW5mGf7mUqFGBq19DbfYyEuu2IqHeDBDtSaLICZsTFzxfENcBe2NRDeJQ+nobB8TrwB+DHjAA3P938z78plwn5biz3jQAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAwOC0xMi0xMlguO78AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjI6NDI6NDQtMDQ6MDC389NcAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI4LTA0OjAwceW2NQAAACd0RVh0RGVzY3JpcHRpb24AaHR0cDovL3JvYmVydC5zemN6ZXBhbmVrLnBskFlIYAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII='); -} - -.olexp-control-layer-manager-details -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAyVBMVEX///87Wm47Wm08Wm6ElqJfeIhPa308WW5AQIDCyc56j51ed4icqrR2i5k8Wm6grrdddoc8Wm67w8hfeIhOanw8Wm6qtbw8WW6yu8GUo6x6jZqVo62Wlpbu7uzO09WElqFheohGYHLs7OqYpq9ieoprgpGTpK29xcluhJKClqLY293m5uZTbX5+kp+yvMLb3d5OaXtpgY+OoKqisLivusBNaXpcd4bAx8xQanxVcIDHzNCtt720vcNqeYNIYnNFYHKUoqvj5OT////5SfIOAAAAHHRSTlMAyZgu7+nhfAT57uPz7d706uX46ujm9uL38u7z87N4ewAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAACtSURBVCjPzdHZDoIwEEBRCipYta4VBQQUt1rcHfcF/v+nJJAA5d3E+3rSTKeVpD/NKpTBSOgHYAlgO+4YyUoRJt50Nl+UyhVVE8FbMrbiVYxrqgC2v2Zss61j3CBKHpzdnh2OpybGrbacBxfgfOG80+1RivJwBYDbnfdplF44AfBIAIkzUhBn2H4ETz6IILlV2uv9CUIeDimJ98jSVGKYpmmQeHPhdxQZ6clbfQFNzCgU6GJ0sAAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0xMC0yMoA45boAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjI6MzE6MTctMDQ6MDAM92klAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI3LTA0OjAwh63G3AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAQdEVYdFRpdGxlAGxheWVyIGluZm8RUEZfAAAAAElFTkSuQmCC'); -} - -.olexp-control-layer-menu -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAY1BMVEX///88W246W20+XXCWlpbm5ua3wMVXcYE8Wm5RbX5pgZBthZRxiJZ0i5lwh5V1i5k/XXDCyc6RoKrf4eKJm6e2vsTl5eV6jZrf4eFacoPe4OF1iZZDYHOwusDc3t/N0dT////L7exBAAAABHRSTlMA1kbW8wSwegAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAABtSURBVCjPxdHHDoAgEEVR2igKNuzY/v8vjYjRIXFpvMt3Mqsh5N9E0A2A+gDERxDF8owyDHGSKp1plSYUg8wLXxnAtVfmBeoXaCAEX9s5uPN7P7iLR24e2wHsRNB3qJyXFTqwG8fPZLQ0RxNnO72DCnTXfN++AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI1VDExOjIyOjU1LTA0OjAwWljKsQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNy0wNDowMEsHxkIAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); -} - - -.olexp-item-image -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABO1BMVEUAAAA8Wm47WW2cnJxqiJy8vLyEorbBwcGCoLSWlpY8Wm48Wm5DYXV7ma2EorZqiJw7WW08Wm48Wm48Wm48Wm47WW07WW2YmJigoKCioqJ4jp1qiJygoKCEoraHorWCoLSCoLSUlJShoaGxtLaCkpx/ormVlZWioqK3traCgoK2trW1tbWWlpabm5uysrK2tra1tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpY8Wm5DYXV7ma2EorZqiJw7WW1CYHR8mq6Fo7dph5xohppWdIhUcoZceo7V1dXd3d3e3d2jtsOCobV9m69BX3M4Vmrn5+ehtMF5mKx2lKg6WGxYdYjm5ubo5+d7j5w/XXI9W284V2t1iZd0iJY0U2g4Vmt2iZeeqrN3i5ieq7P///+3Ru7wAAAAPnRSTlMAAAAAAAAAAAAAQGRiYmJiYmMiplmmWWyqpuBZpln97FA0pekuB5ul5xjn55uR5uHj6NEWwGlzdFMXAmNlQRdviEwAAAABYktHRGjLbPQiAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAwElEQVQY02NgAAJGLm4eXj5+AUEhRgYwYBS2s3dwdHK2E4EKMIk6u7i6OTk7izExMDCLS0hKSrl7eHp5OzlJszAwsMr4+Pr5BwQGBXs5OsqyMTCwS/qGhISGhbtERMrJK3AwMCgq+UZFx8S6xMUnKKuoAgXU1IECiUnJ8UkpGpqcDBCBkNTEtLTEdC24QFRINBCEaCMEIAC3QAiED9Wio6unb6ANAoZGxiABE1MzcwtLTRAwtgIJWFtb29hyMsABAOfZLuUNID9SAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjQyOjEzLTA0OjAwOrTjtgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNy0wNDowMEsHxkIAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); -} - -.olexp-item-group -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAZlBMVEX///8gSocgSocgSocgSocgSocgSocgSocgSoeIioV+hIUpUIfu7uzh5OYsVI2FiIUjTIfs7eshS4dAZJfn6OgmT4onUIvY3eEwV4/J0NozWZA7X5SdrsRAY5aTpb8uVY6YqsL///+1ixGOAAAACXRSTlMAUufoasVTONg7C2lAAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAGBJREFUGNNdzkcSgDAIQFHsoth79/6nNH2Cf8FMHosAoArCKAa/JM1y74miopTTAhFVtRjo9ohNi2iBZF1PDIZxMoAa5qXmsG47h+O8ONzPy0GmD/NBf2oOc4cj/PJ2qg+0UQc1SZnCjgAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0wMy0xMR3JYZ0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjM6MDA6MzgtMDQ6MDATLMoLAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjQzLTA0OjAwtY3rSAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAARdEVYdFRpdGxlAGdyb3VwIGxheWVyMZzWCQAAAABJRU5ErkJggg=='); -} - -.olexp-item-heatmap -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAACZFBMVEW+2fW+2fa92fK01dWm0KmYy4Vwt0NgsCJqtEB6unCTw76iye++2fSz1dGgzpaRyWuKxlKMx093vCVwtw5ttQ1crwVnszS82O2o0a+QyGWLxlCgzli82WfT4HDj2FrnzE3bz0WKuB1XqwOBvIW51+aNx1iczVfH3Wvq4X/yzozstYnfi2rLdVzKn0qRqSRSngaDvY282O+gzpiNx1O312Tq5n3z0orqrJPilJHXeHm9Wl6zZ1K+pj9wmhRSlCSPvbyp0rSOx1m62GXz54LvwI7jmJHeg4TVcHG8XF20a1DBoESSpiZOjQZjllyYvN+21t2UynOk0Fru6n7xxo3ilZPbeXrRZme8YVm5fky8qD6QpSRRjgdWkDZ9oKyZvOOr0rvE3Gr55Ifmo5PdgoPSaGfAcFbAl0azrjZ1nBdKjANSjix2nJuJqcuewumhz5yOx1HR4HD11YrgjonTbGzEfFPGrUKlrS5ekw1KixFdk0t3nZ2DosOVuNyjyfGl0KaMx1LH3Wz10oLZdnHBaVrFpkSysjRfkxBVkDVwmoiAoLmQsdWhx+6x1c2KxV2izUfw2VrPeF2/jEq+tTpwmhhbkkh7nqqDocOCocKOsNOgxe2x0u17vGJwtxDW1j/QrkjHskCNpCJUkCZ5nqaCocOCocGMrtCfxOukyvOIv55crw2qxCvPv0CprzBXkA5nl2+Mrc+ew+qjyfKcxtpmsjJuqQ+mri9nlhBSjil6nqeLrM6ew+mjyfCGv5daphVTkgdIigZmlmeDo8ONrtCdwumgyOd+u35epylkoUqHrbuWud+gxez///+BqYbEAAAAAWJLR0TLhLMGcAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAQdJREFUGNNjYAABRiZmFlY2dg5OLm4wl4eXj19AUEhYRFSMC8QXl5CUkpaRlZNXUFRSBvJV+FTV1DU0tbR1dPX0DRgYDI2MTUzNzC0sraxtbO3sGRgcHJ2cXVzd3D08vbx9fP0Y/AMCg4JDQsPCIyKjomNi4xjiVRMSk5JTUtPSMzKzsnNyGfLyCwqLiktKy8orKquqa2oZ6uobGpuaW1rb2js6q7u6axl6evv6J0ycNHnK1GnTZ8ysrWWYNXvO3HnzFyxctHjJ0mW1QIHlK1auWr1m7bolS9Zv2AgS2Lhp85at27bvWLxzVy0IMNTu3rN33/4DBw8d3ggV2Hjk6LHjJ06eqoUAADN6Yn18G+yHAAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDEyLTA0LTI1nbbUYwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo0MjoxMy0wNDowMDq047YAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzItMDQ6MDAZP+nlAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAAl0RVh0VGl0bGUAZGVtUqgAxgAAAABJRU5ErkJggg=='); -} - -.olexp-item-overlay -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABnlBMVEUAAABiYmJhYWOHh0G4uDOcnJy8vLzBwcGHh4iXl5eWlpZgYGCIiIicnJx5eXpQUFJ5eUWQkD6VlTx8fE69vbyVlW6Ojj2UlD2Tkz2CgkKQkD7V1Szg4Cm4uDvf3ynd3Sre3iqqqjiYmJigoKCioqKhoaOXl2SgoKCGhmGQkD+UlD2cnJ15eXuUlJShoaG2traDg4OVlZWioqK1tbWCgoKWlpabm5uysrK2tra2tra2trW2tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpbb29W7u7a3t6nFxUDV1S7g4Cq4uDy8vLe5uavGxkHV1dXd3d3d3d7ExLW6upC9vZCiooOkpKOxsavn5+fh4eLZ2drW1tjY2NjAwMC+vr7n5ubh4eHR0dHNzc3c3Nzo6Ojh4uLN0dTp6OjZ2dnQ0NDk5OTZ292NnaezvcPIztHT09PW1tbe3d3X2tuFmKSouMCUpK7l5eXj4+Pm5ubV2dqaq7Tf5umXprDX2tx8k6KRqLePoKvf4eKZqLKKnamwusH///912DDDAAAASXRSTlMAAAAAAAAAAAAAAEfj7sUTRoKAqPvrjIKDcoP8/v7+/v7YbKqmptSm84+D5xg0pecYm6XnGJuR5uHj5+fo0RbAaXN0UxcCY2VBXXRV9wAAAAFiS0dEiRxhJswAAAAJcEhZcwAADdcAAA3XAUIom3gAAADNSURBVBjTY2CAAEZuHl4+fiYoj1lAUEhYxFNUTFxCEizAIiUtI+vl7SMnr6DIwKqkrKKq5uvnHxAYBBZgUw8OCQ0Lj4iMitbQ1AJqYVcJiYmJjYtPSEzS1uEA6tfVC0mOSUlNS03P0DfgBAoYGoVkZmXnpOam5hmbcEEE8gsKi9KLS+ACpWXlFZUxVdU1cIHauvqG5JoahEBjU3NLDLJAa1t7B1AgBiJgamZuYWllbWxsbGNrBxKwd3B0cnYxAQE7V5CAm5ubuwcXAxwAAHTkNv/yoA4lAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjQyOjEzLTA0OjAwOrTjtgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozMi0wNDowMBk/6eUAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); -} - -.olexp-item-tile -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABelBMVEUAAAAePUpAXnE9XG49W3BRboNCYHOcnJxJZ3q8vLxMan7BwcGAiI2Xl5eWlpYAGyE/XXFJZ3pOa39FYnZEYnY3VWcnRlZHZXhuiZuCmql4k6Vceo5gfpJObIE6WG1BX3NvipxujKBNa38kQlOYmJigoKCioqKhoKBqfouTq7tffZE7V2qgoKBbeo1BX3KUlJShoaGVlZWioqJlgZNQbYE5V22VnaJvd3y3traDg4K1tbWCgoKWlpabm5uysrK2tra1tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpaascB7lqiEorVvjaFujKCMpbZpiJyEorZ3lalsiZ6AnrLV1dXe3t7R09R+kp9+mKlvi51lgpZykKNqiJxceo5ti5/d3d3n5+fg4eK+xcq0vcO1vsS2v8V6j51mhJhde47m5ubp6Ojp6ejq6emQoq1wjqJsip6OoKxohppujKGHmaVXdYmwucChrbbk5OX////lQAoeAAAATnRSTlMAAAAAAAAAAAAAAAAAAAABL2eNdUUIA1TO+f785oAROtz1dQNsqqam0f7QFqbmNTSlm6X4gxHoGucY5xibkebh4+jRFsBpc3RTFwJjZUFlaURvAAAAAWJLR0R9prEQyQAAAAlwSFlzAAAN1wAADdcBQiibeAAAAMJJREFUGNNjYAABRn4BQSFhEVEmBghgFhOXkJSSlpGVY4EIsMor+PkHBAYpKimzMbCrqKqpa2gGh4SGhUdoaXMwcOpERkXHxMbFJyQmJevqcTFwq6WkpqVnZGZl5+SCBfQNUvLy8gsKCouKS8BaDI2AAkCQWlpWDjYULlBRaWxiCrQWLlBVbWbOw4AQyKtJtbDkRRbIy7Oy5oMIpEL4qRABG1s7ewcrEHB0cgYJuLi6uXt4WoOAsxdIwNvb28eXjwEOAGCvOxqF81rtAAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDEyLTA0LTMw9McRrQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo0MjoxMy0wNDowMDq047YAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MjctMDQ6MDCHrcbcAAAAQXRFWHREZXNjcmlwdGlvbgBHZW5lcmljIGljb24gZm9yIE9HQyBXZWIgc2VydmljZSAtIE9XUwogKFdNUyxXRlMsV0NTKYljsRwAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAG3RFWHRUaXRsZQBsYXllciBPR0MgV2ViIHNlcnZpY2Vl1KvyAAAAAElFTkSuQmCC'); -} - -.olexp-item-vector -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABYlBMVEVohppLaX4AAABLa4Bph5tGZHlLaH0rSWE5V2xAXnOdnJyXlpa8vLyWlpbBwcFUcodriJ1KaH1NcIVNcodKan9KaH1La4BXdoplgpZGZHgxTmRriJ1mhJg6WGxRb4N2lKgAMVo4VWo7WW03Vmo7WW1KaH1Ucog7WW1ObIFbeY5Kan+ZmJiYm5xmd4N/iI+jo6KhoaGioqJreoV0goubmpqVlJSgoKCysrKEhIS1tbWCgoKUlJShoaGVlZWioqKWlpabm5uysrK2tra1tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpbW1ta9xMiJmaPT1dbe3d3f3t7FycyGlqHQ09Xd3d3k5OWcqbKuuL/o5+fl5eWeqrOtt73n5+fo6OfQ1NaLm6bS1tjJztLa3N3m5uaut76Ypa+RoKq3v8XX2tt2jp54j6DY29zn5+bf4OGaq7f////ACgSZAAAAUXRSTlMAAAAAAAAAAAAAAAAAAAB6zjICAh1ADmHXRQ+5zpCz1wJZbgUdsmggSHcea7jYraamprnYlw+m5xjnGDSlm6Wbkebh4+jRFsBpc3RTFwJjZUGgI6O7AAAAAWJLR0R1qGqY+wAAAAlwSFlzAAAN1wAADdcBQiibeAAAAMFJREFUGNNjYOAXEGRkYmJiFhIUFBYRFWNgEZeQZAUKsElJy8jKyYsysCsoKilzMDFxqqiqqWtoajFwaevo6ukbGBoYGZuYcjMxMfCYBQYFh4SGhUdEmlvwAgX4DKOiY2Lj4hMSkyytQALWNlHJKalp6akZUAFbu6jMpKzsnNykTCSBvPyCwiIkgczikpLiTGSBzGIgH0UADOACSRA+1BZ7B0cnZ0sQcHF1Awm4e3h6eftYgYCbL0jAz8/PPwDIgAEAQjY2sOYkNQMAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjI6NDI6MTMtMDQ6MDA6tOO2AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI0LTA0OjAwtkXcQQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII='); -} - - - -/* - * OpenLayersExplorer measurement tool styles - */ - -.olexp-measure -{ - background: #000000; - background: rgba(0, 0, 0, 0.5); - border-radius: 4px; - color: white; - opacity: 0.7; - padding: 4px 8px; - position: relative; - white-space: nowrap; -} - -.olexp-measure-active -{ - font-weight: bold; - opacity: 1; -} - -.olexp-measure-static -{ - background-color: #ffcc33; - border: 1px solid white; - color: black; -} - -.olexp-measure-active:before, -.olexp-measure-static:before -{ - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-top: 6px solid #000000; - border-top: 6px solid rgba(0, 0, 0, 0.5); - bottom: -6px; - content: ""; - left: 50%; - margin-left: -7px; - position: absolute; -} - -.olexp-measure-static:before -{ - border-top-color: #ffcc33; -} - -.olexp-measure-hidden -{ - display: none; -} - -.olexp-menu-remove -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA/FBMVEUAAACcnJyWlpa8vLzBwcGVlpbSZGSYmJigoKCioqKhoaGioqKampqTk5OgoKCxsbGEhIS1tbWCgoKUlJShoaGVlZWioqK0tbWBgoLJgoLQa2vUamrTaWnTZmbWcHCWlpabm5uysrK2tra1tbXJgYGWlpaWlpaSkpKSkpKQkJCBgYF6hobOZWXSY2OWlpaWlpaWlpbSZGTSZGTSZGTSZGTV1dXd3d3n5+fm5ubm5+fj0tLcoaHaf3/diYndjIzdi4vbhobalpbekpLhnJzgm5vXeHjbmprkxMTq5eXp5OTo2trZiYnYhITZkpLYjIzUcHDSYmLSYWHSZGT///9J6V6JAAAANXRSTlMAAAAAAAAAbKqmpqeXEKbnGOcYNKWbpecY96+nnFPim5Hm4eP3wGlzdFMXFqT0Y2VBU+L0mxGrfJUAAAABYktHRFN6Zx0GAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAlUlEQVQY02NgIB0wsnNwcoEBNw8vE1CAmc/UDAr4BUACLJxm5hZgYC4oBBIQFjGzgAKIgKgYTgFLcQlWZAEra0kpaRlZuICltY2tnb2DHELA0cnZ2dnFFSQAttbSzd3D08PLm0FeQVFJWVBQUFzFx9fX18+fQVVNXUNTS0hIWycgEAh0GfT09PQNgPazGRoFBQUZmwAAfGshdfRsxLUAAAAYdEVYdEF1dGhvcgBSb2JlcnQgU3pjemVwYW5la19WsQgAAABSdEVYdENvcHlyaWdodABDQyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzMuMC9eg1q8AAAAGHRFWHRDcmVhdGlvbiBUaW1lADIwMDgtMTItMTJYLju/AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjUyOjE4LTA0OjAw+T1ojAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNC0wNDowMHrv3N8AAAAndEVYdERlc2NyaXB0aW9uAGh0dHA6Ly9yb2JlcnQuc3pjemVwYW5lay5wbJBZSGAAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); -} - -.olexp-menu-zoom -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAB2lBMVEUAAAB8e3tJSUkaGhpVVVVLS0tWVlacnJy8vLzBwcF+fn5RUVFISEiUlJSWlpaXl5dKSkpSUlJQUFBTU1NPT09AQEBCQkJYWFh+fn6trq67u7upqqqHh4djY2NHR0c3NzdcXFycnJzf4OD09vb2+Pjt7u7c3NywsLBvb2+YmJigoKCioqKJiYmVlZXg4eHz9fXq6+vg4eHd3d3d3d3l5eUlJSWgoKDc3Nzk5OTc3Nzd3d3k5OShoaFUVFSUlJShoaHn5+epqalRUVGVlZWioqLi4uKbm5tUVFTl5eXS0tJ6enrf39/c3NyamppZWVnAwMCSkpJdXV1BQUGWlpaenp6Pj49gYGAxMTGTk5R+fnyxsbGBgYF+fHewoG6jjEWHhYKxsbK1tbW1tbWioqKOjo6ijUx3dnGQkZOFhYWCgoKbm5txcG5xZ0pqZ12RkpOXl5fV1dXZ2dmoqKjKysrz9PTx8vLm5ubk5OTe3t7d3d2mpqbe39/2+Pjt7e3a2tqjo6Pr7Ozy8/Pq6url5eW0tLS8vLzn5+fm5+fi4uKXl5dpaWnExMSrq6tEREMZGRnX19fg4ODb29uwr66xpHuGdkNDQ0K0p3zoxValklaqqqnpxVd7dF7CpEX///8MWklrAAAAcHRSTlMAAAAAAAAAAAAAAAAAAAAAFTdJPyIDBkKVw9nGo2ERA1i+4u/s3c/IhWyqpqvZ8fj69u/q0AKm+tHO+s3APzSlzMlKm6XNuDfRzpP607xC+7lZBZul70IDoqvnGOLl7+Pn5+jRFv62VBcYAm+/hWRBY/kEXQAAAAFiS0dEnQa78rEAAAAJcEhZcwAADdcAAA3XAUIom3gAAADySURBVBjTY2AAA0YBQSFhEVEmCI+BSUxcQlJKWkZWjpkFxGeVV1BUUlZRVVPXkGNjYNfU0tbR1dM3MDQyNlGXNWXgMCsoLCouKS0rLze3sJQRYeDUrqisqq6pLSsrs7KwtrFlsLOvrKsvq2kACzg4OjE4u1RWFBU2NoEFXN3cQQLNLa1t7SABD08vAZBAR2dXd1tbWZu3j68fF1Cgrqe3r6u1f8JE/4DAIG6G4JBJk6dM7Wwpqq8KDQvnYWCIiJw2fcbMjuaKusqoaF6gu2NiZ8XFJyQCQVJyCh9QYPac1LT0jEwQSMkCCWTn5Obl8zPAAQBxnUmB66PzwgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo1MjoxOC0wNDowMPk9aIwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MjUtMDQ6MDAQMtf1AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg=='); -} - -.olexp-menu-properties -{ - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABPlBMVEUAAACcnJyWlpa8vLzBwcGVlpnEoACYmJigoKCioqKhoaGioqKampqTk5OgoKCxsbGEhIS1tbWCgoKUlJShoaGVlZWioqK0tbmBgoW6rXW5mxXEnwDDngDDnwDOsCzRtTjVvU7HpQ3OsS6Wlpabm5uysrK2tra1tbW6rXGWlpaWlpaSkpKSkpKQkJCBgYFveam5mhHUu0fEoACWlpaWlpaWlpbDnwDMribEoADEoADV1dXd3d3n5+fm5ubm5+nn6Ovl5eHf2Lnb0Jzf2LfMsTXMriTNsCvazpbMribVu0rVvEvbx2jv6MHv6cXazZXPsS/WvU/ezHby7tL4+Ozh0YXLqx7n6OzMrSPZw1/s47b5+e/i0obQtDbIpxPKqRfp4Kvj1I3cyGvHpg/EoADr4rLaxmbGowrEnwDKqhz///9c6MQYAAAAOnRSTlMAAAAAAAAAbKqmpqeXEKbnGOcYNKWbpecY72NTTSL8/PW2/puR5uHj78Bpc3RTFxNi+/VjZUEpxPejjuW4JwAAAAFiS0dEabxrxLQAAAAJcEhZcwAADdcAAA3XAUIom3gAAACnSURBVBjTY2AgHTCyc3BygQE3Dy8TUICZz8oaCvgFQAIsnNY2tmBgIygEEhAWsbaFAoiAqBhUwM5eXIIVScDB0UlSSlpGFiZg5+zi6iYnr6AIE7B39/D08vbxVYIL+PkHBAYFh4SCBEDWhrmHR0RGRcfEMiirqKqpCwqKa8TFJyQmJSczaGpp6+jqCekbGKakpqUnGzEYGxubmDIxsJmZZyQnJ1tYAgAz9Sdtd6GLUgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo1MjoxOC0wNDowMPk9aIwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzEtMDQ6MDAo1/N4AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg=='); -} - - - -/* - * olexp ol styling - */ - -.olexp-ol-toolbar-show -{ - left : 2.75em; - top : 0.5em; -} - - -/* - * OpenLayers override - */ - -.ol-mouse-position -{ - background: #95b9e6; - background: rgba(0,60,136,.5); - bottom: 8px; - color: #eee; - font-size: 10px; - left: auto; - margin: 1px; - padding: 2px; - position: absolute; - right: 0.5em; - text-align: center; - top: auto; - } - -.ol-overviewmap -{ - bottom: 2.25em; -} - -.ol-rotate -{ - top: 5.0em; -} - -.ol-zoom-extent -{ - left: auto; - right: 0.5em; - top: 2.75em; -} - -.ol-zoomslider -{ - width: 28px; -} - - -/* - * w2ui override - */ - -.w2ui-toolbar table.w2ui-button .w2ui-tb-image -{ - height: 24px; - width: 24px; -} +/* olexp 0.1.2 (c) Daniel Pulido */ + +/* + * olexp explorer styling + */ + +.olexp-explorer-content, +.olexp-explorer-map +{ + height: 100%; + width: 100%; +} + +.olexp-control-layer-manager-down +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAUVBMVEX///+9vQC9vQCWlpbm5ubb26fExCW+vgDIyCbS01HBwQ3U1VzX2Gbw8KC/vwbExBLAwAbAwAfj43bk5HrBwQjBwQfj43XAwAji4nTZ2VX///9Z+37dAAAAA3RSTlMA1kayq0LiAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAHNJREFUKM/F0ckOgCAMRVHA4SlSFRWH//9RKZogrNwY77InTSAV4t+KrAhl0gdQfARVjSupUqibVvuxbhuZAjoDIoLpkIG5wbyFHhg8DMCYbdiJuHkJGzHArTzfwPDIP9XtNFswPK8j/cQePJfpMVWQ8PMTKmUIMs6ZAJ8AAAAYdEVYdEF1dGhvcgBSb2JlcnQgU3pjemVwYW5la19WsQgAAABSdEVYdENvcHlyaWdodABDQyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzMuMC9eg1q8AAAAGHRFWHRDcmVhdGlvbiBUaW1lADIwMDgtMTItMTJYLju/AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjQyOjQ0LTA0OjAwt/PTXAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNi0wNDowMO1wzfYAAAAndEVYdERlc2NyaXB0aW9uAGh0dHA6Ly9yb2JlcnQuc3pjemVwYW5lay5wbJBZSGAAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); +} + +.olexp-control-layer-control-add-vector +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA+VBMVEX///9HZntLaH1La4BKaHxLaH1LaH1KZ3tFZHhLaH1AWHA9Wm46WmtEYndKZ3w8Wm08WW4+W2w8Wm5AYHBajFpZjFnA3vJJZns8Wm6WlpaUlJVJYnN9hYtWa3pue4Tm5ua1vsNUbn/i4+S6wsdRbH3i4uNwhZOVo63l5eVedoaqtbzR1NdJZXfT1tmrtbxddYWToqtziJVSbH66wcZUbX64wMabqbFtgpFWb4DY2txLZnnIzdBie4xNan5qgZFeeIped4qrt79dd4nF0cV4n3hajFpynXOBqIKFq4bO2s/M2M2IrImKrovs7e3N2c7P2tC8y7y5ybn///9EpCZXAAAAFnRSTlMAieVi5t3c9K7gIOwfw+98ri3qEMk8P+Ru4wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAADpSURBVCjPbdLrTsIwAIbhwhBEBVHHoCp+gKIoKKjgCVGRjU3pFO7/ZuwBKHZ7f7RpnzRplxFCEkmLxJZyNvTCSluLgU+ZTQ1Zp1Qul5y0XGxt76wgl9cnCNktLPf39g/0aUoPj46pqnJCqQagWqtDdHrWwD/A+YXYb15ewYBW+5qPN52mCejeAvW7e2igChq9Ph4eEQVUn55fBnGA1+EbYuHd+YiH0ecIGLuezC5qkLkTP/j6DvyJbYA3ZSwMGZt6JjAFLAI/oew3AjM1zyWsJW7EmUf0NxOtg2oBNt+az8RDjD+maC8f+AeaIjk7ipjOKAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNVQxMToyNTozNC0wNDowMNic0/sAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MjctMDQ6MDCHrcbcAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg=='); +} + +.olexp-control-graticule +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABZVBMVEW01e9bhb+DqdR6otB+pNLI5vqJr9iFq9VHdLR8o9HE4/jA3/ZslMhIdbWSt93H5flmkMWoyei+3fROerhUgLt0m8xoksaCqNSDqtXF4/hPe7irzOqGrNZahb5hi8KfwuRdh8DG5PmszetymstNebdnkMV0nMxLd7ZVgbxYg72myOeAptOOs9u42PGnyeiavuGNstqFq9aLsNlul8ldiMCx0e1RfLm21vC72/NTfrrH5vp9pNGZveF1nM1zmstQfbmGq9bB4PZ3ns6Xu+CDqNRIdbS62vN5oM9Sfbp4n86gwuRUf7u62fLD4ve52fKRtdxjjcSMsdqaveG11fDC4fdpkseQtNx6odCbv+KBp9RrlMdtlsmhw+XF5Pmpy+lkjsSHrNeHrddokcaQtdxkjcSqy+pJdbWHrNauz+yszutLeLZeiMBljsSDqdVeicFMeLdZhL6Msdmz1O9VgLuWut/G5fn///9aqb94AAAAAWJLR0R2MWPJQQAAAAlwSFlzAAAN1wAADdcBQiibeAAAAXRJREFUKM9l0Pk3AlEUB/BXfBmFGpMiRkUNaUGLtrFUKFtpsaRV2ZdK8v97M4j45Z773ueee8+9hCiUA4PA0DDAAMNDwOCISqkgBOrRsXENtKwMrBaY4HSTahBAb9ArprhpGaaNM7MKfg6gYDJbML9g1dkExiDYFpeU8xaziYLKvkzd4XS5V5jVFfeag76W7SoQj5dm8Pkht4LfJz29HpD1AE2CofAXhENBGgPrQRKRKsQNfAE2RCkqN8nWdhSIxXsQj9EQ3dkle4nk/sHhUQ+OdMcH+8mEk+6RSp+MeTNZNsfkc2w2Y7WeplMIE6nq7PyiINh4xsrbhMKlR/qCDMUSeq1QKvagbIz+gqix/A2VKn4BqpVvqF31wVVNhnrDdX3TBzfXcDXqpJRI3t7dq39A/fD4FEqUaCvT80uTa7U/z95ucc32q0aeEWnQOrqbdHY2lwcakc/hfAd9M9DhZUi94Q/gLSVBN/YPYl0K74L4D0QB7x8Kmj3ZLAlwHgAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0xMC0yMoA45boAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjVUMTE6NTE6MTEtMDQ6MDDoUU7YAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI2LTA0OjAwIdrNaAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAPdEVYdFRpdGxlAGdyYXRpY3VsZZJv4HwAAAAASUVORK5CYII='); +} + +.olexp-control-export-map +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAwFBMVEX///+ZmZmcnJyampqYmJiZmZmbm5u3t7eqqqqampqXl5eYmJiZmZk8W246W22ZmZmVlZWcnJyAgICbm5vT09Pg4ODm5ubf39+WlpbR0dHX19fZ2dm3wMVXcYE8Wm5RbX5pgZBthZRxiJZ0i5lwh5XY2911i5mClqLU2Nrb3d6PoKuvr6+ioqK/v7/j5OSpqam7u7ulpaVke4rW2Nqzs7PIyMjHx8esrKzL0NNQany3t7fJycnOzs7R1ddKZHT///8tFxR7AAAAFHRSTlMAI7TffAqt/veV+/no1kbmWfgCvQR3K/YAAAABYktHRACIBR1IAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAqklEQVQoz9XRWQ6CMBCA4borWkXFEReGRSiCO66oeP9jWWIEa+oB/J+afpmkzRDyq0KxVK7IoFrT6g0ZKAMYNmWgA4Au1sphpI0nkKX/PUwNfEXbIhimZTszx7ZMKgK6HniM+czFL2DA5swPQiYBXhiEHBbLlTiRHtYcNttdDgjpm6J9hKRzOJ7On3DBmN8jUbvX2z2HBBLEmE+RntpXst098B0V99ym2c+fRzQtIQC3ZTAAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjVUMTE6NTI6MDMtMDQ6MDBYU+RsAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI5LTA0OjAw15K9gQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII='); +} + +.olexp-control-measure-length +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYBAMAAAASWSDLAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAGFBMVEX///9VV1NSU1HT18+Rk488Wm5QUFD////r4EM9AAAABXRSTlMA/f79/vIq1voAAAABYktHRACIBR1IAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAQklEQVQY02NgoBiwwhgBGJxQKMDkICsjAzAKKgpBkQADo3GyGRRhcJxNjJNNQCSIAwTJIALGcUbmGMM4gnAggNsBAKVhFsLRWT/tAAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDA4LTEyLTEyWC47vwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNVQxMTo1MToxMS0wNDowMOhRTtgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzYtMDQ6MDDtcM32AAAAJ3RFWHREZXNjcmlwdGlvbgBodHRwOi8vcm9iZXJ0LnN6Y3plcGFuZWsucGyQWUhgAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg=='); +} + +.olexp-control-edit-settings +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAB/lBMVEX////IpgvFogLEogDDnwDIpgvHnwDGowjJpw7GowbGowTIpgfGowPkzmHNrRrGpAjHpgnGogTNqwzixiDGowLNrRvEoQPEoQLNqwnixhvIpQPNqgbGowDNqgXGogDSshDGowLSsQ3EoQHHpAHHowDDnwC/nwDSsQrFoQDGowHSsQzRrwbIpgjHpQfHpQXSsQnQrwXEoQDGogDGogLNqwfJpwHGowLNqgfIpgHGoQDIpgTGowDixRXMqQPWtwLFogDGowHixBDLqAPGogHGogHHpAHy44r88qrz5Y7+9a/676P34jr365r+9KT25nT34Tn75jn75TX88qj47Jz98pn87nj86lb13zn54zn75jf75TP75C/33yj98Y787Wz76Ev75z775jr75Tb75TL75C733yf974P862L03jn03Tb75TH75Cz54Cbz3kjy2Sf75Cv74yf13B/74yb74yL64R3v1RXozQ/kyQvfwwb750H02hz54Bz02xbv1hHq0QvlzAbiyQT750D75jv03TDx1hfy2RTt1A/ozwnjygTx4HDx31jx2j313zfw1xPr0g3mzQjfxQTdwgPcwQP13i/y2CLozQ7gxgT54S374yP74h/s0hLiyAT33yv75Cr13BjhxwT33yn74yj74yT74iD33Rvv1RTz2hjkyQjy2Bb///9QqXrkAAAARnRSTlMAtfseVd8g6feKivfp/POH34fz/Onz/Pzz/PfzivOH8/Pz/N+1gAjz+/Pz87Xf3/Pz/N+H8/OK8/OK9/f88/zp6fzz3+n3Dl9naQAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAAGOSURBVCjPY2AgCBiZgIARTZCZhYGB1c3d3Y2VgYGFGSHOxs7BycDq4enpwcrAxc3DhhDn9eLjB0sICAp5C4tAZZjZeT09vUTFfDx9/cQl/AMCJUUgprFweHl6egYFe4aEhoVHREZFx0ixQLRw8oFkPGPj4hMSk5JTUqVlYJbwiwZ5+qalZ2QGBGZl58jKQd3PysoqFhwSmiuvoKCYl19QqKSsrKwClGBy8/DwARojr6qmpqpeVFxSWlZeoQGScAcZU5mpoMbAoKZZVV1TW1ffAJEAuqaxqRki0dLa1t7RAZHo7OruAbpGC2SUdm9f/4SJEyeBJHR09fSUJmdlT9HX1DSYWlc/zdDIyEgF4jBjk+n5BTNmtswCGTPbVA7mDTPzOXOBrpkHNKYDCOZbWELEWawWLFy0eMlSoGs6ps0GyVhDgoRZxGbGzGW2hss7OiYYms7v6LCzh0YJm4PjCic554kdHRON5Czm29kjIsTF1ZLBCCzBYGmNEIdErdGkhoZJRqhRCwYqGkCgQjjRAAC4W228IT8VJAAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0wNC0wM3cLCUkAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjVUMTE6NTI6MDMtMDQ6MDBYU+RsAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjM1LTA0OjAw3JjXawAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAOdEVYdFRpdGxlAHNldHRpbmdzRrN3QwAAAABJRU5ErkJggg=='); +} + +.olexp-control-measure-area +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYBAMAAAASWSDLAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAG1BMVEX///9VV1NSU1HT18+Rk488Wm6CoLRQUFD///+VUipIAAAABXRSTlMA/f79/vIq1voAAAABYktHRACIBR1IAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAWklEQVQY02NgQAGsoaEBCE5aGgonFAIgHAhIJcgBakBwAkAkJicUZCuUA3dHKAMewCioKARFAgyMxsXmUITBcTYxLjYBkSAOEBSDCBjHGZljDOMIwoEAbgcAAFUrLNBnsGw7AAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDA4LTEyLTEyWC47vwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNVQxMTo1MToxMS0wNDowMOhRTtgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzUtMDQ6MDDcmNdrAAAAJ3RFWHREZXNjcmlwdGlvbgBodHRwOi8vcm9iZXJ0LnN6Y3plcGFuZWsucGyQWUhgAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg=='); +} + +.olexp-control-layer-control-add-tile +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAARVBMVEX///9ajFpZjFk8Wm6CoLSWlpbm5ubF0cV4n3hajFpumm6AqIGEqoXO2s/M2M2GrIeKrovs7e3N2c7P2tC8y7y5ybn///8H9fLcAAAAA3RSTlMAyTzPIdReAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAHRJREFUKM+t0ksOgCAMQEGqoqIoxc/9r2pbwCiYuOFtmnQ2EFDqr5bqKJ71QUtpyTNBz1WENtbrtK4Pd98wjEaCJoNxmu2y2nmCDIxD9B7RmRwwABaweWkv4AjzFHjEJyKmlH491xNCEYBW58EXyf5KA+mCF5KaCagHkknTAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI1VDExOjI1OjM0LTA0OjAw2JzT+wAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNS0wNDowMNyY12sAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); +} + +.olexp-control-toolbar-hide +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABWVBMVEX///8AAAArK0ArNTUwNzcuMzgtNTUwNDQoNjY3Nzc6QkJHTU5UWVpna212eXqBhIaPkpKcnp+Tl5hxdHZhZmdXXV5NU1VITU9ATU0AAABCRklaX2DDxcXl5eW9v79rb3FOUlQ/RkbHx8esr6/j4+OXmpro6Ojm5ubl5eXm5ubm5ubp6enp6enm5ubLy8tVWlxVampNUlRWW1tjZ2h5fX6oqqplamtTV1gxMTFTWVp+goPIyci0trWDiIjX19eChIaNkJBcYGEgQEAnOztITU1ydXeipKRlaWu2uLjY2tqQk5V3enuIjIy+wb5fZGUzMzNeYmPHyMePkpJxdXVucnJ4fX58f4B1eXpzdnaFiInHycetr69ZXV8uLi5VVVVXWlx3enq/wcGoqqpnbGxOVFRMTlFgZWZucnJ2ent1eXlnbG1YXF5ARUXu7uzd3dzh4uDt7evp6uj////Z6plGAAAAbXRSTlMAAQwYJTI/OxMObZakqammpJ2arbKonHgUAm2njICQtaRFMpaBnSFwbWhlOS8KitUMbaDOwp/qmRXB3v3yrYW97scIDWrX672ChK/X5P3MD8H85ca+rr/Lz+P88KoLA43V+u/GWFu0wcvNuaA0nka8DgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAAC0SURBVCjPY2CgOmBkYmZhZWPnQBXl5OLm4eXjFxAUEhYRFROXgApLSknLyCIBOXkFRbCEkrIsGlBRVQNJqMtiAg2QhCYWCS2QhDYWCR2QhC6GWXr6BkA3GRoZm6CKm5qZA9VbWFpZ29giCdvZOzg6gZ3r7OLq5u4BEfX08vbx9fOH+dwiIDAoOCQ0LDwiMio3OiYWESZx8QmJuXn5BbmFSckpqMEVl5qWnpGZlZ1D/fihCwAAE8IpsYDcOLEAAAAYdEVYdEF1dGhvcgBSb2JlcnQgU3pjemVwYW5la19WsQgAAABSdEVYdENvcHlyaWdodABDQyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzMuMC9eg1q8AAAAGHRFWHRDcmVhdGlvbiBUaW1lADIwMDgtMTItMTJYLju/AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDE2OjIzOjQ0LTA0OjAwDFw9bAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzoyNi0wNDowMCHazWgAAAAndEVYdERlc2NyaXB0aW9uAGh0dHA6Ly9yb2JlcnQuc3pjemVwYW5lay5wbJBZSGAAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); +} + +.olexp-control-layer-manager-navigation +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYBAMAAAASWSDLAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAMFBMVEX///9BX3JBX3JCX3I8Wm7I5vqmxdhEY3dAXnNph5tlhJhFYnfm5uZXcIGst77///+b4/bXAAAABHRSTlMA6P3oG6ESOAAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAABMSURBVBjTY2DADURcoMARyHENhYIQIMetxCN1ClDCC8xp8U5dAuR4hqArU4EZ4ATk+JyBgiMgzhXfM0+AEn5HMGQGXJkJzNXOeMIGALCya915oHCyAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDE3OjUwOjI1LTA0OjAwc95IWgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNC0wNDowMHrv3N8AAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); +} + +.olexp-control-layer-manager-up +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAb1BMVEX///+9vQC9vQCWlpbm5ubb26fExCW+vgDIyCbS01HT1FjQ0UvDwxTPz0XU1VzX2GbS01DCwg3a2lrBwQzR0UvR0k/j43jw8KDl5X3Q0UzCwgzk5Hnl5XzR0k3k5Hrk5Hu/vwbDww/AwAa/vwX///86q3s0AAAAA3RSTlMA1kayq0LiAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAH5JREFUKM/F0dsOgjAMgOGVCQUE5pxQ5Xx4/3d0i4nQ3hP+myX9brpUqWvToh1urBNAnwRxgr8g4pCkWX4vyjxLgQNW5mGf7mUqFGBq19DbfYyEuu2IqHeDBDtSaLICZsTFzxfENcBe2NRDeJQ+nobB8TrwB+DHjAA3P938z78plwn5biz3jQAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAwOC0xMi0xMlguO78AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjI6NDI6NDQtMDQ6MDC389NcAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI4LTA0OjAwceW2NQAAACd0RVh0RGVzY3JpcHRpb24AaHR0cDovL3JvYmVydC5zemN6ZXBhbmVrLnBskFlIYAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII='); +} + +.olexp-control-layer-manager-details +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAyVBMVEX///87Wm47Wm08Wm6ElqJfeIhPa308WW5AQIDCyc56j51ed4icqrR2i5k8Wm6grrdddoc8Wm67w8hfeIhOanw8Wm6qtbw8WW6yu8GUo6x6jZqVo62Wlpbu7uzO09WElqFheohGYHLs7OqYpq9ieoprgpGTpK29xcluhJKClqLY293m5uZTbX5+kp+yvMLb3d5OaXtpgY+OoKqisLivusBNaXpcd4bAx8xQanxVcIDHzNCtt720vcNqeYNIYnNFYHKUoqvj5OT////5SfIOAAAAHHRSTlMAyZgu7+nhfAT57uPz7d706uX46ujm9uL38u7z87N4ewAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAACtSURBVCjPzdHZDoIwEEBRCipYta4VBQQUt1rcHfcF/v+nJJAA5d3E+3rSTKeVpD/NKpTBSOgHYAlgO+4YyUoRJt50Nl+UyhVVE8FbMrbiVYxrqgC2v2Zss61j3CBKHpzdnh2OpybGrbacBxfgfOG80+1RivJwBYDbnfdplF44AfBIAIkzUhBn2H4ETz6IILlV2uv9CUIeDimJ98jSVGKYpmmQeHPhdxQZ6clbfQFNzCgU6GJ0sAAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0xMC0yMoA45boAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjI6MzE6MTctMDQ6MDAM92klAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI3LTA0OjAwh63G3AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAQdEVYdFRpdGxlAGxheWVyIGluZm8RUEZfAAAAAElFTkSuQmCC'); +} + +.olexp-control-layer-menu +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAY1BMVEX///88W246W20+XXCWlpbm5ua3wMVXcYE8Wm5RbX5pgZBthZRxiJZ0i5lwh5V1i5k/XXDCyc6RoKrf4eKJm6e2vsTl5eV6jZrf4eFacoPe4OF1iZZDYHOwusDc3t/N0dT////L7exBAAAABHRSTlMA1kbW8wSwegAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAABtSURBVCjPxdHHDoAgEEVR2igKNuzY/v8vjYjRIXFpvMt3Mqsh5N9E0A2A+gDERxDF8owyDHGSKp1plSYUg8wLXxnAtVfmBeoXaCAEX9s5uPN7P7iLR24e2wHsRNB3qJyXFTqwG8fPZLQ0RxNnO72DCnTXfN++AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI1VDExOjIyOjU1LTA0OjAwWljKsQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNy0wNDowMEsHxkIAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); +} + + +.olexp-item-image +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABO1BMVEUAAAA8Wm47WW2cnJxqiJy8vLyEorbBwcGCoLSWlpY8Wm48Wm5DYXV7ma2EorZqiJw7WW08Wm48Wm48Wm48Wm47WW07WW2YmJigoKCioqJ4jp1qiJygoKCEoraHorWCoLSCoLSUlJShoaGxtLaCkpx/ormVlZWioqK3traCgoK2trW1tbWWlpabm5uysrK2tra1tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpY8Wm5DYXV7ma2EorZqiJw7WW1CYHR8mq6Fo7dph5xohppWdIhUcoZceo7V1dXd3d3e3d2jtsOCobV9m69BX3M4Vmrn5+ehtMF5mKx2lKg6WGxYdYjm5ubo5+d7j5w/XXI9W284V2t1iZd0iJY0U2g4Vmt2iZeeqrN3i5ieq7P///+3Ru7wAAAAPnRSTlMAAAAAAAAAAAAAQGRiYmJiYmMiplmmWWyqpuBZpln97FA0pekuB5ul5xjn55uR5uHj6NEWwGlzdFMXAmNlQRdviEwAAAABYktHRGjLbPQiAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAwElEQVQY02NgAAJGLm4eXj5+AUEhRgYwYBS2s3dwdHK2E4EKMIk6u7i6OTk7izExMDCLS0hKSrl7eHp5OzlJszAwsMr4+Pr5BwQGBXs5OsqyMTCwS/qGhISGhbtERMrJK3AwMCgq+UZFx8S6xMUnKKuoAgXU1IECiUnJ8UkpGpqcDBCBkNTEtLTEdC24QFRINBCEaCMEIAC3QAiED9Wio6unb6ANAoZGxiABE1MzcwtLTRAwtgIJWFtb29hyMsABAOfZLuUNID9SAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjQyOjEzLTA0OjAwOrTjtgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNy0wNDowMEsHxkIAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); +} + +.olexp-item-group +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAZlBMVEX///8gSocgSocgSocgSocgSocgSocgSocgSoeIioV+hIUpUIfu7uzh5OYsVI2FiIUjTIfs7eshS4dAZJfn6OgmT4onUIvY3eEwV4/J0NozWZA7X5SdrsRAY5aTpb8uVY6YqsL///+1ixGOAAAACXRSTlMAUufoasVTONg7C2lAAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAGBJREFUGNNdzkcSgDAIQFHsoth79/6nNH2Cf8FMHosAoArCKAa/JM1y74miopTTAhFVtRjo9ohNi2iBZF1PDIZxMoAa5qXmsG47h+O8ONzPy0GmD/NBf2oOc4cj/PJ2qg+0UQc1SZnCjgAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0wMy0xMR3JYZ0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjM6MDA6MzgtMDQ6MDATLMoLAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjQzLTA0OjAwtY3rSAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAARdEVYdFRpdGxlAGdyb3VwIGxheWVyMZzWCQAAAABJRU5ErkJggg=='); +} + +.olexp-item-heatmap +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAACZFBMVEW+2fW+2fa92fK01dWm0KmYy4Vwt0NgsCJqtEB6unCTw76iye++2fSz1dGgzpaRyWuKxlKMx093vCVwtw5ttQ1crwVnszS82O2o0a+QyGWLxlCgzli82WfT4HDj2FrnzE3bz0WKuB1XqwOBvIW51+aNx1iczVfH3Wvq4X/yzozstYnfi2rLdVzKn0qRqSRSngaDvY282O+gzpiNx1O312Tq5n3z0orqrJPilJHXeHm9Wl6zZ1K+pj9wmhRSlCSPvbyp0rSOx1m62GXz54LvwI7jmJHeg4TVcHG8XF20a1DBoESSpiZOjQZjllyYvN+21t2UynOk0Fru6n7xxo3ilZPbeXrRZme8YVm5fky8qD6QpSRRjgdWkDZ9oKyZvOOr0rvE3Gr55Ifmo5PdgoPSaGfAcFbAl0azrjZ1nBdKjANSjix2nJuJqcuewumhz5yOx1HR4HD11YrgjonTbGzEfFPGrUKlrS5ekw1KixFdk0t3nZ2DosOVuNyjyfGl0KaMx1LH3Wz10oLZdnHBaVrFpkSysjRfkxBVkDVwmoiAoLmQsdWhx+6x1c2KxV2izUfw2VrPeF2/jEq+tTpwmhhbkkh7nqqDocOCocKOsNOgxe2x0u17vGJwtxDW1j/QrkjHskCNpCJUkCZ5nqaCocOCocGMrtCfxOukyvOIv55crw2qxCvPv0CprzBXkA5nl2+Mrc+ew+qjyfKcxtpmsjJuqQ+mri9nlhBSjil6nqeLrM6ew+mjyfCGv5daphVTkgdIigZmlmeDo8ONrtCdwumgyOd+u35epylkoUqHrbuWud+gxez///+BqYbEAAAAAWJLR0TLhLMGcAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAQdJREFUGNNjYAABRiZmFlY2dg5OLm4wl4eXj19AUEhYRFSMC8QXl5CUkpaRlZNXUFRSBvJV+FTV1DU0tbR1dPX0DRgYDI2MTUzNzC0sraxtbO3sGRgcHJ2cXVzd3D08vbx9fP0Y/AMCg4JDQsPCIyKjomNi4xjiVRMSk5JTUtPSMzKzsnNyGfLyCwqLiktKy8orKquqa2oZ6uobGpuaW1rb2js6q7u6axl6evv6J0ycNHnK1GnTZ8ysrWWYNXvO3HnzFyxctHjJ0mW1QIHlK1auWr1m7bolS9Zv2AgS2Lhp85at27bvWLxzVy0IMNTu3rN33/4DBw8d3ggV2Hjk6LHjJ06eqoUAADN6Yn18G+yHAAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDEyLTA0LTI1nbbUYwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo0MjoxMy0wNDowMDq047YAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzItMDQ6MDAZP+nlAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAAl0RVh0VGl0bGUAZGVtUqgAxgAAAABJRU5ErkJggg=='); +} + +.olexp-item-overlay +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABnlBMVEUAAABiYmJhYWOHh0G4uDOcnJy8vLzBwcGHh4iXl5eWlpZgYGCIiIicnJx5eXpQUFJ5eUWQkD6VlTx8fE69vbyVlW6Ojj2UlD2Tkz2CgkKQkD7V1Szg4Cm4uDvf3ynd3Sre3iqqqjiYmJigoKCioqKhoaOXl2SgoKCGhmGQkD+UlD2cnJ15eXuUlJShoaG2traDg4OVlZWioqK1tbWCgoKWlpabm5uysrK2tra2tra2trW2tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpbb29W7u7a3t6nFxUDV1S7g4Cq4uDy8vLe5uavGxkHV1dXd3d3d3d7ExLW6upC9vZCiooOkpKOxsavn5+fh4eLZ2drW1tjY2NjAwMC+vr7n5ubh4eHR0dHNzc3c3Nzo6Ojh4uLN0dTp6OjZ2dnQ0NDk5OTZ292NnaezvcPIztHT09PW1tbe3d3X2tuFmKSouMCUpK7l5eXj4+Pm5ubV2dqaq7Tf5umXprDX2tx8k6KRqLePoKvf4eKZqLKKnamwusH///912DDDAAAASXRSTlMAAAAAAAAAAAAAAEfj7sUTRoKAqPvrjIKDcoP8/v7+/v7YbKqmptSm84+D5xg0pecYm6XnGJuR5uHj5+fo0RbAaXN0UxcCY2VBXXRV9wAAAAFiS0dEiRxhJswAAAAJcEhZcwAADdcAAA3XAUIom3gAAADNSURBVBjTY2CAAEZuHl4+fiYoj1lAUEhYxFNUTFxCEizAIiUtI+vl7SMnr6DIwKqkrKKq5uvnHxAYBBZgUw8OCQ0Lj4iMitbQ1AJqYVcJiYmJjYtPSEzS1uEA6tfVC0mOSUlNS03P0DfgBAoYGoVkZmXnpOam5hmbcEEE8gsKi9KLS+ACpWXlFZUxVdU1cIHauvqG5JoahEBjU3NLDLJAa1t7B1AgBiJgamZuYWllbWxsbGNrBxKwd3B0cnYxAQE7V5CAm5ubuwcXAxwAAHTkNv/yoA4lAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjQyOjEzLTA0OjAwOrTjtgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozMi0wNDowMBk/6eUAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); +} + +.olexp-item-tile +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABelBMVEUAAAAePUpAXnE9XG49W3BRboNCYHOcnJxJZ3q8vLxMan7BwcGAiI2Xl5eWlpYAGyE/XXFJZ3pOa39FYnZEYnY3VWcnRlZHZXhuiZuCmql4k6Vceo5gfpJObIE6WG1BX3NvipxujKBNa38kQlOYmJigoKCioqKhoKBqfouTq7tffZE7V2qgoKBbeo1BX3KUlJShoaGVlZWioqJlgZNQbYE5V22VnaJvd3y3traDg4K1tbWCgoKWlpabm5uysrK2tra1tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpaascB7lqiEorVvjaFujKCMpbZpiJyEorZ3lalsiZ6AnrLV1dXe3t7R09R+kp9+mKlvi51lgpZykKNqiJxceo5ti5/d3d3n5+fg4eK+xcq0vcO1vsS2v8V6j51mhJhde47m5ubp6Ojp6ejq6emQoq1wjqJsip6OoKxohppujKGHmaVXdYmwucChrbbk5OX////lQAoeAAAATnRSTlMAAAAAAAAAAAAAAAAAAAABL2eNdUUIA1TO+f785oAROtz1dQNsqqam0f7QFqbmNTSlm6X4gxHoGucY5xibkebh4+jRFsBpc3RTFwJjZUFlaURvAAAAAWJLR0R9prEQyQAAAAlwSFlzAAAN1wAADdcBQiibeAAAAMJJREFUGNNjYAABRn4BQSFhEVEmBghgFhOXkJSSlpGVY4EIsMor+PkHBAYpKimzMbCrqKqpa2gGh4SGhUdoaXMwcOpERkXHxMbFJyQmJevqcTFwq6WkpqVnZGZl5+SCBfQNUvLy8gsKCouKS8BaDI2AAkCQWlpWDjYULlBRaWxiCrQWLlBVbWbOw4AQyKtJtbDkRRbIy7Oy5oMIpEL4qRABG1s7ewcrEHB0cgYJuLi6uXt4WoOAsxdIwNvb28eXjwEOAGCvOxqF81rtAAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDEyLTA0LTMw9McRrQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo0MjoxMy0wNDowMDq047YAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MjctMDQ6MDCHrcbcAAAAQXRFWHREZXNjcmlwdGlvbgBHZW5lcmljIGljb24gZm9yIE9HQyBXZWIgc2VydmljZSAtIE9XUwogKFdNUyxXRlMsV0NTKYljsRwAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAG3RFWHRUaXRsZQBsYXllciBPR0MgV2ViIHNlcnZpY2Vl1KvyAAAAAElFTkSuQmCC'); +} + +.olexp-item-vector +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABYlBMVEVohppLaX4AAABLa4Bph5tGZHlLaH0rSWE5V2xAXnOdnJyXlpa8vLyWlpbBwcFUcodriJ1KaH1NcIVNcodKan9KaH1La4BXdoplgpZGZHgxTmRriJ1mhJg6WGxRb4N2lKgAMVo4VWo7WW03Vmo7WW1KaH1Ucog7WW1ObIFbeY5Kan+ZmJiYm5xmd4N/iI+jo6KhoaGioqJreoV0goubmpqVlJSgoKCysrKEhIS1tbWCgoKUlJShoaGVlZWioqKWlpabm5uysrK2tra1tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpbW1ta9xMiJmaPT1dbe3d3f3t7FycyGlqHQ09Xd3d3k5OWcqbKuuL/o5+fl5eWeqrOtt73n5+fo6OfQ1NaLm6bS1tjJztLa3N3m5uaut76Ypa+RoKq3v8XX2tt2jp54j6DY29zn5+bf4OGaq7f////ACgSZAAAAUXRSTlMAAAAAAAAAAAAAAAAAAAB6zjICAh1ADmHXRQ+5zpCz1wJZbgUdsmggSHcea7jYraamprnYlw+m5xjnGDSlm6Wbkebh4+jRFsBpc3RTFwJjZUGgI6O7AAAAAWJLR0R1qGqY+wAAAAlwSFlzAAAN1wAADdcBQiibeAAAAMFJREFUGNNjYOAXEGRkYmJiFhIUFBYRFWNgEZeQZAUKsElJy8jKyYsysCsoKilzMDFxqqiqqWtoajFwaevo6ukbGBoYGZuYcjMxMfCYBQYFh4SGhUdEmlvwAgX4DKOiY2Lj4hMSkyytQALWNlHJKalp6akZUAFbu6jMpKzsnNykTCSBvPyCwiIkgczikpLiTGSBzGIgH0UADOACSRA+1BZ7B0cnZ0sQcHF1Awm4e3h6eftYgYCbL0jAz8/PPwDIgAEAQjY2sOYkNQMAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjI6NDI6MTMtMDQ6MDA6tOO2AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI0LTA0OjAwtkXcQQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII='); +} + + + +/* + * OpenLayersExplorer measurement tool styles + */ + +.olexp-measure +{ + background: #000000; + background: rgba(0, 0, 0, 0.5); + border-radius: 4px; + color: white; + opacity: 0.7; + padding: 4px 8px; + position: relative; + white-space: nowrap; +} + +.olexp-measure-active +{ + font-weight: bold; + opacity: 1; +} + +.olexp-measure-static +{ + background-color: #ffcc33; + border: 1px solid white; + color: black; +} + +.olexp-measure-active:before, +.olexp-measure-static:before +{ + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid #000000; + border-top: 6px solid rgba(0, 0, 0, 0.5); + bottom: -6px; + content: ""; + left: 50%; + margin-left: -7px; + position: absolute; +} + +.olexp-measure-static:before +{ + border-top-color: #ffcc33; +} + +.olexp-measure-hidden +{ + display: none; +} + +.olexp-menu-remove +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA/FBMVEUAAACcnJyWlpa8vLzBwcGVlpbSZGSYmJigoKCioqKhoaGioqKampqTk5OgoKCxsbGEhIS1tbWCgoKUlJShoaGVlZWioqK0tbWBgoLJgoLQa2vUamrTaWnTZmbWcHCWlpabm5uysrK2tra1tbXJgYGWlpaWlpaSkpKSkpKQkJCBgYF6hobOZWXSY2OWlpaWlpaWlpbSZGTSZGTSZGTSZGTV1dXd3d3n5+fm5ubm5+fj0tLcoaHaf3/diYndjIzdi4vbhobalpbekpLhnJzgm5vXeHjbmprkxMTq5eXp5OTo2trZiYnYhITZkpLYjIzUcHDSYmLSYWHSZGT///9J6V6JAAAANXRSTlMAAAAAAAAAbKqmpqeXEKbnGOcYNKWbpecY96+nnFPim5Hm4eP3wGlzdFMXFqT0Y2VBU+L0mxGrfJUAAAABYktHRFN6Zx0GAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAlUlEQVQY02NgIB0wsnNwcoEBNw8vE1CAmc/UDAr4BUACLJxm5hZgYC4oBBIQFjGzgAKIgKgYTgFLcQlWZAEra0kpaRlZuICltY2tnb2DHELA0cnZ2dnFFSQAttbSzd3D08PLm0FeQVFJWVBQUFzFx9fX18+fQVVNXUNTS0hIWycgEAh0GfT09PQNgPazGRoFBQUZmwAAfGshdfRsxLUAAAAYdEVYdEF1dGhvcgBSb2JlcnQgU3pjemVwYW5la19WsQgAAABSdEVYdENvcHlyaWdodABDQyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzMuMC9eg1q8AAAAGHRFWHRDcmVhdGlvbiBUaW1lADIwMDgtMTItMTJYLju/AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjUyOjE4LTA0OjAw+T1ojAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNC0wNDowMHrv3N8AAAAndEVYdERlc2NyaXB0aW9uAGh0dHA6Ly9yb2JlcnQuc3pjemVwYW5lay5wbJBZSGAAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC'); +} + +.olexp-menu-zoom +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAB2lBMVEUAAAB8e3tJSUkaGhpVVVVLS0tWVlacnJy8vLzBwcF+fn5RUVFISEiUlJSWlpaXl5dKSkpSUlJQUFBTU1NPT09AQEBCQkJYWFh+fn6trq67u7upqqqHh4djY2NHR0c3NzdcXFycnJzf4OD09vb2+Pjt7u7c3NywsLBvb2+YmJigoKCioqKJiYmVlZXg4eHz9fXq6+vg4eHd3d3d3d3l5eUlJSWgoKDc3Nzk5OTc3Nzd3d3k5OShoaFUVFSUlJShoaHn5+epqalRUVGVlZWioqLi4uKbm5tUVFTl5eXS0tJ6enrf39/c3NyamppZWVnAwMCSkpJdXV1BQUGWlpaenp6Pj49gYGAxMTGTk5R+fnyxsbGBgYF+fHewoG6jjEWHhYKxsbK1tbW1tbWioqKOjo6ijUx3dnGQkZOFhYWCgoKbm5txcG5xZ0pqZ12RkpOXl5fV1dXZ2dmoqKjKysrz9PTx8vLm5ubk5OTe3t7d3d2mpqbe39/2+Pjt7e3a2tqjo6Pr7Ozy8/Pq6url5eW0tLS8vLzn5+fm5+fi4uKXl5dpaWnExMSrq6tEREMZGRnX19fg4ODb29uwr66xpHuGdkNDQ0K0p3zoxValklaqqqnpxVd7dF7CpEX///8MWklrAAAAcHRSTlMAAAAAAAAAAAAAAAAAAAAAFTdJPyIDBkKVw9nGo2ERA1i+4u/s3c/IhWyqpqvZ8fj69u/q0AKm+tHO+s3APzSlzMlKm6XNuDfRzpP607xC+7lZBZul70IDoqvnGOLl7+Pn5+jRFv62VBcYAm+/hWRBY/kEXQAAAAFiS0dEnQa78rEAAAAJcEhZcwAADdcAAA3XAUIom3gAAADySURBVBjTY2AAA0YBQSFhEVEmCI+BSUxcQlJKWkZWjpkFxGeVV1BUUlZRVVPXkGNjYNfU0tbR1dM3MDQyNlGXNWXgMCsoLCouKS0rLze3sJQRYeDUrqisqq6pLSsrs7KwtrFlsLOvrKsvq2kACzg4OjE4u1RWFBU2NoEFXN3cQQLNLa1t7SABD08vAZBAR2dXd1tbWZu3j68fF1Cgrqe3r6u1f8JE/4DAIG6G4JBJk6dM7Wwpqq8KDQvnYWCIiJw2fcbMjuaKusqoaF6gu2NiZ8XFJyQCQVJyCh9QYPac1LT0jEwQSMkCCWTn5Obl8zPAAQBxnUmB66PzwgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo1MjoxOC0wNDowMPk9aIwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MjUtMDQ6MDAQMtf1AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg=='); +} + +.olexp-menu-properties +{ + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABPlBMVEUAAACcnJyWlpa8vLzBwcGVlpnEoACYmJigoKCioqKhoaGioqKampqTk5OgoKCxsbGEhIS1tbWCgoKUlJShoaGVlZWioqK0tbmBgoW6rXW5mxXEnwDDngDDnwDOsCzRtTjVvU7HpQ3OsS6Wlpabm5uysrK2tra1tbW6rXGWlpaWlpaSkpKSkpKQkJCBgYFveam5mhHUu0fEoACWlpaWlpaWlpbDnwDMribEoADEoADV1dXd3d3n5+fm5ubm5+nn6Ovl5eHf2Lnb0Jzf2LfMsTXMriTNsCvazpbMribVu0rVvEvbx2jv6MHv6cXazZXPsS/WvU/ezHby7tL4+Ozh0YXLqx7n6OzMrSPZw1/s47b5+e/i0obQtDbIpxPKqRfp4Kvj1I3cyGvHpg/EoADr4rLaxmbGowrEnwDKqhz///9c6MQYAAAAOnRSTlMAAAAAAAAAbKqmpqeXEKbnGOcYNKWbpecY72NTTSL8/PW2/puR5uHj78Bpc3RTFxNi+/VjZUEpxPejjuW4JwAAAAFiS0dEabxrxLQAAAAJcEhZcwAADdcAAA3XAUIom3gAAACnSURBVBjTY2AgHTCyc3BygQE3Dy8TUICZz8oaCvgFQAIsnNY2tmBgIygEEhAWsbaFAoiAqBhUwM5eXIIVScDB0UlSSlpGFiZg5+zi6iYnr6AIE7B39/D08vbxVYIL+PkHBAYFh4SCBEDWhrmHR0RGRcfEMiirqKqpCwqKa8TFJyQmJSczaGpp6+jqCekbGKakpqUnGzEYGxubmDIxsJmZZyQnJ1tYAgAz9Sdtd6GLUgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo1MjoxOC0wNDowMPk9aIwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzEtMDQ6MDAo1/N4AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg=='); +} + + + +/* + * olexp ol styling + */ + +.olexp-ol-toolbar-show +{ + left : 2.75em; + top : 0.5em; +} + + +/* + * OpenLayers override + */ + +.ol-mouse-position +{ + background: #95b9e6; + background: rgba(0,60,136,.5); + bottom: 8px; + color: #eee; + font-size: 10px; + left: auto; + margin: 1px; + padding: 2px; + position: absolute; + right: 0.5em; + text-align: center; + top: auto; + } + +.ol-overviewmap +{ + bottom: 2.25em; +} + +.ol-rotate +{ + top: 5.0em; +} + +.ol-zoom-extent +{ + left: auto; + right: 0.5em; + top: 2.75em; +} + +.ol-zoomslider +{ + width: 28px; +} + + +/* + * w2ui override + */ + +.w2ui-toolbar table.w2ui-button .w2ui-tb-image +{ + height: 24px; + width: 24px; +} diff --git a/dist/olexp.js b/dist/olexp.js index 368eeb6..582b221 100644 --- a/dist/olexp.js +++ b/dist/olexp.js @@ -1,6578 +1,6588 @@ -/* olexp 0.1.2 (c) Daniel Pulido */ - -/* global ol, w2ui */ - -/** - * @namespace olexp - */ -var olexp = olexp || {}; - -//================================================== -// Documentation definitions -//-------------------------------------------------- - -/** - * jQuery - * @external jQuery - * @see {@link https://api.jquery.com} - */ - -/** - * jQuery plugin namespace - * @memberof external:jQuery - * @namespace fn - */ - -/** - * ol3 main namespace - * @external ol - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.html} - */ - -/** - * ol3 Collection - * @class Collection - * @memberof external:ol - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.Collection.html} - */ - -/** - * ol3 format namespace - * @memberof external:ol - * @namespace format - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.format.html} - */ - -/** - * ol3 Feature - * @class Feature - * @memberof external:ol - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.Feature.html} - */ - -/** - * ol3 format feature - * @class Feature - * @memberof external:ol.format - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.format.Feature.html} - */ - -/** - * ol3 graticule - * @class Graticule - * @memberof external:ol - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.Graticule.html} - */ - -/** - * ol3 interaction namespace - * @memberof external:ol - * @namespace interaction - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.interaction.html} - */ - -/** - * ol3 selection interaction - * @class Select - * @memberof external:ol.interaction - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.interaction.Select.html} - */ - -/** - * ol3 layer namespace - * @memberof external:ol - * @namespace layer - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.layer.html} - */ - -/** - * ol3 layer base class - * @class Layer - * @memberof external:ol.layer - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.layer.Layer.html} - */ - -/** - * ol3 map - * @class Map - * @memberof external:ol - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.Map.html} - */ - -/** - * ol3 overlay - * @class Overlay - * @memberof external:ol - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.Overlay.html} - */ - -/** - * ol3 style namespace - * @memberof external:ol - * @namespace style - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.style.html} - */ - -/** - * ol3 Style - * @class Style - * @memberof external:ol.style - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.style.Style.html} - */ - -/** - * ol3 view - * @class View - * @memberof external:ol - * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.View.html} - */ - -/** - * w2ui form - * @function w2form - * @memberof external:jQuery.fn - * @see {@link http://w2ui.com/web/docs/form} - */ - -/** - * w2ui form properties - * @memberof external:jQuery.fn.w2form - * @name properties - * @type object - * @see {@link http://w2ui.com/web/docs/form/properties} - */ - -/** - * w2ui grid - * @function w2grid - * @memberof external:jQuery.fn - * @see {@link http://w2ui.com/web/docs/grid} - */ - -/** - * w2ui layout - * @function w2layout - * @memberof external:jQuery.fn - * @see {@link http://w2ui.com/web/docs/layout} - */ - -/** - * w2ui layout panels - * @memberof external:jQuery.fn.w2layout - * @name panels - * @type object - * @see {@link http://w2ui.com/web/docs/w2layout.panels} - */ - -/** - * w2ui popup - * @function w2popup - * @memberof external:jQuery.fn - * @see {@link http://w2ui.com/web/docs/popup} - */ - -/** - * w2ui popup properties - * @memberof external:jQuery.fn.w2popup - * @name properties - * @type object - * @see {@link http://w2ui.com/web/docs/w2popup.defaults} - */ - -/** - * w2ui sidebar - * @function w2sidebar - * @memberof external:jQuery.fn - * @see {@link http://w2ui.com/web/docs/sidebar} - */ - -/** - * w2ui sidebar nodes - * @memberof external:jQuery.fn.w2sidebar - * @name nodes - * @type object - * @see {@link http://w2ui.com/web/docs/w2sidebar.nodes} - */ - -/** - * w2ui toolbar - * @function w2toolbar - * @memberof external:jQuery.fn - * @see {@link http://w2ui.com/web/docs/toolbar} - */ - -/** - * w2ui toolbar properties - * @memberof external:jQuery.fn.w2toolbar - * @name properties - * @type object - * @see {@link http://w2ui.com/web/docs/w2toolbar.items} - */ - -/** - * w2ui common name - * @external w2ui.common.name - * @ignore - * @see {@link http://w2ui.com/web/docs/common.name} - */ - -/** - * @description Advanced settings for customizing various controls and menus - * look and feel. - * @typedef {object} ExplorerSettings - * @memberOf olexp - * - * @property {object} [control] olexp.control settings - * - * @property {object} [control.EditSettings] Edit Settings control settings - * @property {external:jQuery.fn.w2form.properties} [control.EditSettings.form] - * w2form properties - * @property {string} [control.EditSettings.hint='Edit Controls'] Control button - * hover hint text - * @property {external:jQuery.fn.w2popup.properties} [control.EditSettings.popup] - * w2popup properties - * @property {number} [control.EditSettings.span=6] Span size of control fields - * - * @property {object} [control.ExportMap] Export Map control settings - * @property {string} [control.ExportMap.filename='map.png'] Default filename of - * saved map - * @property {string} [control.ExportMap.hint='Export map'] Control button hover - * hint text - * - * @property {object} [control.Graticule] Graticule control settings - * @property {boolean} [control.Graticule.enable=false] Enable grid line display - * @property {external:jQuery.fn.w2form.properties} [control.Graticule.form] - * w2form properties - * @property {string} [control.Graticule.hint='Edit Controls'] Control button - * hover hint text - * @property {object} [control.Graticule.options] ol.style.Stroke options - * @property {external:jQuery.fn.w2popup.properties} [control.Graticule.popup] - * w2popup properties - * @property {number} [control.Graticule.span=6] Span size of control fields - * - * @property {object} [control.LayerControlTile] Layer Control Tile control - * settings - * @property {external:jQuery.fn.w2form.properties} [control.LayerControlTile.form] - * w2form properties - * @property {string} [control.LayerControlTile.hint='Edit Controls'] Control - * button hover hint text - * @property {external:jQuery.fn.w2popup.properties} [control.LayerControlTile.popup] - * w2popup properties - * @property {number} [control.LayerControlTile.span=6] Span size of control - * fields - * - * @property {object} [control.LayerControlVector] Layer Control Vector control - * settings - * @property {external:jQuery.fn.w2form.properties} [control.LayerControlVector.form] - * w2form properties - * @property {string} [control.LayerControlVector.hint='Edit Controls'] Control - * button hover hint text - * @property {external:jQuery.fn.w2popup.properties} [control.LayerControlVector.popup] - * w2popup properties - * @property {number} [control.LayerControlVector.span=6] Span size of control - * fields - * - * @property {object} [control.LayerManager] Layer Manager control settings - * @property {string} [control.LayerManager.hintDetailsHide='Hide details'] Hide - * details control button hover hint text - * @property {string} [control.LayerManager.hintDetailsShow='Show details'] Show - * details control button hover hint text - * @property {string} [control.LayerManager.hintMoveDown='Move item down'] Move - * item down control button hover hint text - * @property {string} [control.LayerManager.hintMoveUp='Move item up'] Move item - * up control button hover hint text - * @property {string} [control.LayerManager.hintOutlineHide='Hide outline'] Hide - * outline control button hover hint text - * @property {string} [control.LayerManager.hintOutlineShow='Show outline'] Show - * outline control button hover hint text - * - * @property {object} [control.LayerMenu] Layer Menu control settings - * @property {string} [control.LayerMenu.arrow=true] Display arrow for drop down - * menu - * @property {string} [control.LayerMenu.hint='Item Properties'] Control button - * hover hint text - * @property {string} [control.LayerMenu.text=''] Button text - * - * @property {object} [control.Measurement] Measurement control settings - * @property {string} [control.Measurement.hintArea='Measure area'] Area - * measurement control button hover hint text - * @property {string} [control.Measurement.hintLength='Measure length'] Length - * measurement control button hover hint text - * - * @property {object} [control.ToolbarHide] Toolbar Hide control settings - * @property {string} [control.ToolbarHide.hint='Hide toolbar'] Hide toolbar - * control button hover hint text - * - * @property {object} [measure] olexp.measure settings - * - * @property {object} [measure.Tool] Properties menu settings - * @property {string} [measure.Tool.continueLineMsg='Click to continue drawing the line'] - * Message displayed to continue drawing line - * @property {string} [measure.Tool.continuePolygonMsg='Click to continue drawing the polygon'] - * Message displayed to continue drawing polygon - * @property {Array} [measure.Tool.helpTooltipOffset=[20, 0]] Pixel offset of - * help tooltip - * @property {string} [measure.Tool.helpTooltipPositioning='center-left'] - * Position of help tooltip - * @property {external:ol.style.Style} [measure.Tool.measuredStyle] Style of a - * measurement vector after completed. - * @property {external:ol.style.Style} [measure.Tool.measuredStyle] Style of a - * measurement vector during drawing. - * @property {Array} [measure.Tool.measureTooltipOffset=[0, -20]] Pixel offset - * of measuring tooltip - * @property {string} [measure.Tool.measureTooltipPositioning='bottom-center'] - * Position of measuring tooltip - * @property {string} [measure.Tool.messageStart='Click to start drawing. Double click to stop.'] - * Message to display to start drawing. - * - * @property {object} [menu] olexp.menu settings - * - * @property {object} [menu.Properties] Properties menu settings - * @property {number} [menu.Properties.field=35] Field size - * @property {external:jQuery.fn.w2form.properties} [menu.Properties.form] - * w2form properties - * @property {external:jQuery.fn.w2popup.properties} [menu.Properties.popup] - * w2popup properties - * @property {number} [menu.Properties.span=4] Span size of control fields - * @property {string} [menu.Properties.text='Properties'] Context menu text - * - * @property {object} [menu.Remove] Remove menu settings - * @property {string} [menu.Remove.text='Remove'] Context menu text - * - * @property {object} [menu.Zoom] Zoom menu settings - * @property {string} [menu.Zoom.text='Zoom'] Context menu text - * - * @property {object} [ol] olexp.ol settings - * - * @property {object} [ol.ToolbarShow] ol3 map control settings - * @property {string} [ol.ToolbarShow.html='T'] HTML to display in control - * @property {string} [ol.ToolbarShow.title='Show toolbar'] Control hover hint - * - * @property {object} [util] olexp.util settings - * - * @property {function} [util.Cluster] Function that returns ol.style.Style for - * a given cluster size. - * @property {external:ol.style.Style} [util.Point] Point style - * @property {external:ol.style.Style} [util.LineString] LineString style - * @property {external:ol.style.Style} [util.Polygon] Polygon style - * @property {external:ol.style.Style} [util.MultiPoint] MultiPoint style - * @property {external:ol.style.Style} [util.MultiLineString] MultiLineString - * style - * @property {external:ol.style.Style} [util.MultiPolygon] MultiPolygon style - */ - -//================================================== -// OpenLayers Explorer -//-------------------------------------------------- -/** - * olexp main module - */ -(function(olexp) { - - /** - * Main OpenLayers Explorer object that provides a layout manager to an - * Open Layers 3 map. - * @param {string} id DOM id of the element containing the Explorer. - * @param {olexp.ExplorerOptions} [options] Explorer options - * @throws {Error} id must be defined and exist - */ - var Explorer = function(id, options) - { - - // ================================================== - // Parse arguments - // -------------------------------------------------- - - if (typeof id === 'undefined') - { - throw new Error('olexp.Explorer: id not defined'); - } - else if ($('#'+id).length === 0) - { - throw new Error('olexp.Explorer: id not found'); - } - - // ================================================== - // Default options - // -------------------------------------------------- - - // Prefix is used to create DOM ids and w2ui names. This ensures they - // are unique and can have multiple instances on the same page - var prefix = 'olexp-' + id; - - /** - * @description Explorer constructor options to override default - * behavior. - * @typedef {object} ExplorerOptions - * @memberOf olexp - * - * @property {object} [controls] Enables built-in toolbar controls - * @property {boolean} [controls.editsettings=true] Enable settings - * editor control - * @property {boolean} [controls.exportmap=true] Enable map exporting - * control - * @property {boolean} [controls.graticule=true] Enable graticule - * control - * @property {boolean} [controls.layercontrol=true] Enable Layer Control - * control - * @property {boolean} [controls.layermanager=true] Enable Layer Manager - * control - * @property {boolean} [controls.layermenu=true] Enable Layer Menu - * control - * @property {boolean} [controls.measure=true] Enable measurement - * control - * @property {boolean} [controls.toolbarhide=true] Enable toolbar hide - * control - * - * @property {external:jQuery.fn.w2layout.panels} [details] Options for - * details panel. Below are only those different from w2ui - * defaults. - * @property {boolean} [details.hidden=true] Visibility - * @property {boolean} [details.resizable=true] Resizability - * @property {string} [details.size='25%'] Size - * @property {string} [details.type='preview'] Type of panel - * - * @property {external:jQuery.fn.w2sidebar.nodes} [layers] Options for - * layers node. Below are only those different from w2ui defaults. - * @property {boolean} [layers.expanded=true] Indicate if initially - * expanded - * @property {boolean} [layers.group=true] Indicate if a group - * @property {string} [layers.img='icon-folder'] CSS selector of node - * image - * @property {string} [layers.text='Layers'] Node text - * - * @property {external:jQuery.fn.w2layout.panels} [map] Options for map - * panel. Below are only those different from w2ui defaults. - * @property {string} [map.type='main'] Type of panel - * - * @property {external:jQuery.fn.w2layout.panels} [navigation] Options - * for navigation panel. Below are only those different from - * w2ui defaults. - * @property {boolean} [navigation.resizable=true] Resizability - * @property {string} [navigation.size='15%'] Size - * @property {string} [navigation.type='left'] Type of panel - * - * @property {object} [olcontrols] Enables OpenLayers map controls - * @property {boolean} [olcontrols.fullscreen=true] Enable full screen - * @property {boolean} [olcontrols.mouseposition=true] Enable mouse position - * @property {boolean} [olcontrols.overviewmap=true] Enable overview map - * @property {boolean} [olcontrols.rotate=true] Enable rotation - * @property {boolean} [olcontrols.scaleline=true] Enable scale line - * @property {boolean} [olcontrols.zoom=true] Enable zoom - * @property {boolean} [olcontrols.zoomslider=true] Enable zoom slider - * @property {boolean} [olcontrols.zoomtoextent=true] Enable zoom to extent - * - * @property {object} [olinteractions] Enables OpenLayers map interactions - * @property {boolean} [olinteractions.draganddrop=true] Enable drag and drop - * - * @property {external:ol.Map} [olmap] Options for ol3 map. - * Below are only those different from ol3 defaults. - * @property {array} [olmap.controls=[]] Controls initially added to the - * map. - * @property {external:ol.View | undefined} [olmap.view=new ol.View({center: [0,0], zoom: 4})] - * The map's initial view. - * - * @property {external:jQuery.fn.w2layout.panels} [outline] Options for - * outline panel. Below are only those different from w2ui - * defaults. - * @property {string} [outline.type='main'] Type of panel - * - * @property {external:jQuery.fn.w2sidebar.nodes} [overlays] Options for - * overlays node. Below are only those different from w2ui - * defaults. - * @property {boolean} [overlays.expanded=true] Indicate if initially - * expanded - * @property {boolean} [overlays.group=true] Indicate if a group - * @property {string} [overlays.img='icon-folder'] CSS selector of node - * image - * @property {string} [overlays.text='Overlays'] Node text - * - * @property {olexp.ExplorerSettings} [settings] Advanced settings for - * customizing various controls and menus look and feel. - * - * @property {external:jQuery.fn.w2layout.panels} [toolbar] Options for - * toolbar panel. Below are only those different from w2ui - * defaults. - * @property {string} [toolbar.size='40'] Size - * @property {string} [toolbar.style='padding: 5px;'] Additional CSS - * style - * @property {string} [toolbar.type='top'] Type of panel - */ - this.options = { - controls : { - editsettings : true, - exportmap : true, - graticule : true, - layercontrol : true, - layermanager : true, - layermenu : true, - measure : true, - toolbarhide : true - }, - details : { - hidden : true, - resizable : true, - size : '25%', - type : 'preview' - }, - layers : { - expanded : true, - group : true, - img : 'icon-folder', - text : 'Layers' - }, - map : { - type : 'main' - }, - navigation : { - resizable : true, - size : '15%', - type : 'left' - }, - olcontrols : { - fullscreen : true, - mouseposition : true, - overviewmap : true, - rotate : true, - scaleline : true, - zoom : true, - zoomslider : true, - zoomtoextent : true - }, - olinteractions : { - draganddrop : true - }, - olmap : { - controls : [], - view : new ol.View({center: [0,0], zoom: 3}) - }, - outline : { - type : 'main' - }, - overlays : { - expanded : true, - group : true, - img : 'icon-folder', - text : 'Overlays' - }, - settings: {}, - toolbar : { - size : '40', - style : 'padding: 5px;', - type : 'top' - }, - }; - - // Override default options with user options - $.extend(true, this.options, options); - - /** - * @description Explorer options the user can not override (DOM ids and - * w2ui names) - * @memberOf olexp - * - * @property {object} [explorer] Explorer properties - * @property {string} [explorer.cls='olexp-explorer-content'] Explorer - * div class - * @property {string} [explorer.id='olexp-' + id + - * '-explorer-id-content'] Explorer div id - * @property {external:w2ui.common.name} [explorer.details='olexp-' + id - * + '-explorer-name-details'] w2ui name of details panel - * @property {external:w2ui.common.name} [explorer.layout='olexp-' + id - * + '-explorer-name-layout'] w2ui name of main layout - * @property {external:w2ui.common.name} [explorer.navigation='olexp-' - * + id + '-explorer-name-navigation'] w2ui name of navigation - * panel - * @property {external:w2ui.common.name} [explorer.outline='olexp-' + id - * + '-explorer-name-outline'] w2ui name of outline panel - * @property {external:w2ui.common.name} [explorer.toolbar='olexp-' + id - * + '-explorer-name-toolbar'] w2ui name of toolbar - * - * @property {external:jQuery.fn.w2sidebar.nodes} [layers] Options for - * layers node - * @property {string} [layers.id='olexp-' + id + '-explorer-id-layers'] - * Unique ID of node - * - * @property {external:jQuery.fn.w2layout.panels} [map] Options for map - * panel - * @property {string} [map.content='
'] - * Panel content. Should be div containing ol.Map and - * referenced by olmap.target. - * - * @property {external:ol.Map} [olmap] Options for ol3 map - * @property {Element|string|undefined} [olmap.target=options.map.id] - * The container for the map, either the element itself or the - * id of the element. - * - * @property {external:jQuery.fn.w2sidebar.nodes} [overlays] Options for - * overlays node - * @property {string} [overlays.id='olexp-' + id + - * '-explorer-id-overlays'] Unique ID of node - */ - $.extend(true, this.options, { - explorer : { - cls : 'olexp-explorer-content', - id : prefix + '-explorer-id-content', - details : prefix + '-explorer-name-details', - layout : prefix + '-explorer-name-layout', - navigation : prefix + '-explorer-name-navigation', - outline : prefix + '-explorer-name-outline', - toolbar : prefix + '-explorer-name-toolbar' - }, - layers : { - id : prefix + '-explorer-id-layers', - }, - map : { - content : ('
'), - }, - olmap : { - target : prefix + '-explorer-id-map', - }, - overlays : { - id : prefix + '-explorer-id-overlays', - }, - settings : { - prefix : prefix - } - }); - - // ================================================== - // Store current object - // -------------------------------------------------- - var me = this; - - // ================================================== - // Create main layout content div - // -------------------------------------------------- - - var div = $('
', {'id': this.options.explorer.id, - 'class': this.options.explorer.cls}); - $('#'+id).append(div); - - // ================================================== - // Main Layout - // -------------------------------------------------- - - this.layout = $('#'+this.options.explorer.id).w2layout({ - name : this.options.explorer.layout, - panels : [ - this.options.navigation, - this.options.map, - this.options.toolbar - ] - }); - - // ================================================== - // Main Toolbar - // -------------------------------------------------- - - this.toolbar = $('').w2toolbar({ - name: this.options.explorer.toolbar - }); - - // ================================================== - // Navigation pane Layout - // -------------------------------------------------- - - this.navigation = $('').w2layout({ - name : this.options.explorer.navigation, - onResize : function() { - if (me.hasOwnProperty('map')) - { - me.map.updateSize(); - } - if (me.hasOwnProperty('details')) - { - me.details.resize(); - } - }, - panels : [ - this.options.outline, - this.options.details - ] - }); - - // ================================================== - // Outline sidebar - // -------------------------------------------------- - - this.outline = $('').w2sidebar({ - name : this.options.explorer.outline, - nodes : [ - this.options.layers, - this.options.overlays - ], - onClick : function (event) { - var id = event.target; - var records = me.manager.getDetails(id); - me.details.clear(); - me.details.add(records); - me.manager.onItemSelected(id); - }, - onDblClick : function (event) { - var id = event.target; - me.manager.toggleNode(id); - me.manager.onItemSelected(id); - }, - onRender : function(event) { - event.onComplete = function() - { - var id = me.outline.selected; - me.manager.onItemSelected(id); - }; - } - }); - - // ================================================== - // Details table - // -------------------------------------------------- - - this.details = $('').w2grid({ - columns : [ - { - field : 'property', - caption : 'Property', - size : '100%', - sortable : true - }, - { - field : 'value', - caption : 'Value', - size : '100%', - sortable : true - } - ], - name : this.options.explorer.details, - }); - - // ================================================== - // Add Content - // -------------------------------------------------- - - this.navigation.content(this.options.outline.type, this.outline); - this.navigation.content(this.options.details.type, this.details); - this.layout.content(this.options.navigation.type, this.navigation); - - // ================================================== - // Define map - // -------------------------------------------------- - - this.map = new ol.Map(this.options.olmap); - - // ================================================== - // Layer manager - // -------------------------------------------------- - - this.manager = new olexp.manager.Manager(this.map, - this.outline, - this.details, - this.options.layers.id, - this.options.overlays.id); - - // ================================================== - // Create menu items and callbacks in outline - // -------------------------------------------------- - - var zoom = olexp.menu.Zoom(this.manager, this.options.settings); - var properties = olexp.menu.Properties(this.manager, this.options.settings); - var remove = olexp.menu.Remove(this.manager, this.options.settings); - - this.menu = {items: [], callbacks: {}}; - - this.menu.items.push(zoom.menu); - this.menu.items.push(properties.menu); - this.menu.items.push(remove.menu); - - this.menu.callbacks[zoom.menu.id] = zoom.click; - this.menu.callbacks[properties.menu.id] = properties.click; - this.menu.callbacks[remove.menu.id] = remove.click; - - // Add menu items and callbacks to outline - this.outline.menu = this.menu.items; - this.outline.onMenuClick = function (event) - { - var id = event.menuItem.id; - if (id in me.menu.callbacks) - { - me.menu.callbacks[id](event); - } - }; - - // ================================================== - // Define map interactions - // -------------------------------------------------- - - this.util = new olexp.util.Util(this.options.settings); - - // Add map interactions - var interactions = this.util.getInteractions(this.map); - for (var iname in this.options.olinteractions) - { - var interaction = interactions[iname]; - if (this.options.olinteractions[iname]) this.map.addInteraction(interaction); - } - - // Add map controls - var controls = this.util.getControls(); - for (var cname in this.options.olcontrols) - { - var control = controls[cname]; - this.map.addControl(control); - control.setMap((this.options.olcontrols[cname] ? this.map : null)); - } - - // ================================================== - // Feature selector - // -------------------------------------------------- - - this.selector = new olexp.selection.Feature(this.map, this.details); - this.selector.setEnable(true); - - // ================================================== - // All layout and map components are defined so we - // can define the main Explorer API. - // -------------------------------------------------- - - /** - * @description The objects exposed by the Explorer API - * @typedef {object} ExplorerAPI - * @memberOf olexp - * @property {external:jQuery.fn.w2grid} details Layer details panels. - * Display the details of the later that is currently selected - * in the outline sidebar. - * @property {external:jQuery.fn.w2layout} layout Explorer layout - * object. Contains the map, toolbar, and navigation panels. - * Can maintain up to 3 additional panels that are stretchable - * and resizable. - * @property {olexp.manager.ManagerAPI} manager Explorer item manager - * @property {external:ol.Map} map ol3 map object used to add layers, - * overlays, controls, etc. - * @property {external:jQuery.fn.w2layout} navigation Layer manager - * navigation panel. The panel that contains the outline - * sidebar and detail grid. - * @property {olexp.ExplorerOptions} options Explorer options object - * that contains the options argument passed to the explorer - * constructor. - * @property {external:jQuery.fn.w2sidebar} outline Layer manager - * outline panel that allows the user to manage the ordering - * and properties of the map layers. - * @property {external:jQuery.fn.w2toolbar} toolbar Explorer toolbar - * that contains map and layers controls. - */ - this.api = { - details : this.details, - layout : this.layout, - manager : this.manager, - map : this.map, - navigation : this.navigation, - options : this.options, - outline : this.outline, - toolbar : this.toolbar - }; - - // ================================================== - // Add built-in controls to toolbar - // -------------------------------------------------- - - if (this.options.controls.toolbarhide) - { - this.toolbar.add(olexp.control.ToolbarHide(this.api, - {hidden : this.options.toolbar.hidden, - settings : this.options.settings})); - this.toolbar.add({id: 'break-toolbar-hide', type: 'break'}); - } - - if (this.options.controls.layermanager) - { - this.toolbar.add(olexp.control.LayerManager(this.api, - this.manager, - {details: {checked: !this.options.details.hidden}, - navigation: {checked: !this.options.navigation.hidden}, - settings : this.options.settings})); - this.toolbar.add({id: 'break-layer-manager', type: 'break'}); - } - - if (this.options.controls.layermenu) - { - this.toolbar.add(olexp.control.LayerMenu(this.api, - this.manager, - this.menu, - {settings : this.options.settings})); - this.toolbar.add({id: 'break-item-menu', type: 'break'}); - } - - if (this.options.controls.layercontrol) - { - this.toolbar.add(olexp.control.LayerControl(this.api, - {settings : this.options.settings})); - this.toolbar.add({id: 'break-layer-control', type: 'break'}); - } - - if (this.options.controls.graticule) - { - this.toolbar.add(olexp.control.Graticule(this.api, - {settings : this.options.settings})); - this.toolbar.add({id: 'break-graticule', type: 'break'}); - } - - if (this.options.controls.measure) - { - this.toolbar.add(olexp.control.Measure(this.api, - {settings : this.options.settings})); - this.toolbar.add({id: 'break-measure', type: 'break'}); - } - - if (this.options.controls.exportmap) - { - this.toolbar.add(olexp.control.ExportMap(this.api, - {settings : this.options.settings})); - this.toolbar.add({id: 'break-export-map', type: 'break'}); - } - - if (this.options.controls.editsettings) - { - this.toolbar.add(olexp.control.EditSettings(this.api, - {settings : this.options.settings})); - this.toolbar.add({id: 'break-edit-settings', type: 'break'}); - } - - this.layout.set(this.options.toolbar.type, {content: '', - show : {toolbar : true}, - toolbar: this.toolbar}); - - }; - - /** - * Destroy all w2ui and openlayer resources. The explorer is no longer - * valid after calling this method. - * @memberOf olexp - * @param {olexp.ExplorerAPI} explorer Explorer API object - * @public - */ - olexp.destroy = function(explorer) - { - - if (explorer.map !== undefined) explorer.map.setTarget(null); - if (explorer.details !== undefined) explorer.details.destroy(); - if (explorer.outline !== undefined) explorer.outline.destroy(); - if (explorer.navigation !== undefined) explorer.navigation.destroy(); - if (explorer.toolbar !== undefined) explorer.toolbar.destroy(); - if (explorer.layout !== undefined) explorer.layout.destroy(); - - }; - - // ================================================== - // Explorer API - // -------------------------------------------------- - - /** - * Constructor to create an Explorer. - * @class Explorer - * @memberOf olexp - * @param {string} id DOM id of the element div containing the Explorer. - * @param {olexp.ExplorerOptions} [options] Explorer options - * @public - * @returns {olexp.ExplorerAPI} Explorer API - * @throws {Error} DOM id must be defined and exist - */ - olexp.Explorer = function(id, options) - { - var explorer = new Explorer(id, options); - return explorer.api; - }; - -}(olexp || {})); - - -/** - * @namespace olexp.event - */ -olexp.event = olexp.event || {}; - -//================================================== -// Event Handler -//-------------------------------------------------- -(function(olexp) { - - /** - * Handles listening for registered events - * @param {object} listeners Initial listeners - * @private - */ - var Event = function(listeners) - { - - // ================================================== - // Collection of event listeners that are keyed by - // the event name and valued by an array of callback - // functions (e.g., {'name': [function1, function2]}) - // -------------------------------------------------- - this.listeners = $.extend({}, listeners); - - }; - - /** - * Add listener to event type - * @memberOf Event.prototype - * @param {string} type The event type. - * @param {function} listener The listener function. - * @param {object} opt_this The object to use as this in listener. - * @private - * @warning If event type is not already registered then listener is not. - */ - Event.prototype.on = function(type, listener, opt_this) - { - - if (!(type in this.listeners)) return; - - var callback = listener; - if (typeof opt_this !== 'undefined') callback = listener.bind(opt_this); - this.listeners[type].push(callback); - - }; - - /** - * Register event to which to listen - * @memberOf Event.prototype - * @param {string} type The event type. - * @private - * @warning If event type is already registered then nothing is done. - */ - Event.prototype.register = function(type) - { - - if (type in this.listeners) return; - this.listeners[type] = []; - - }; - - /** - * Trigger event and call listeners - * @memberOf Event.prototype - * @param {string} type The event type. - * @private - */ - Event.prototype.trigger = function() - { - var args = Array.prototype.slice.call(arguments); - var type = args.shift(); - if (!(type in this.listeners)) return; - - // Call listeners with remaining arguments - for (var i = 0; i < this.listeners[type].length; i++) - { - this.listeners[type][i].apply(this, args); - } - }; - - /** - * Unregister event to which to listen - * @memberOf Event.prototype - * @param {string} type The event type. - * @private - * @returns Listeners registered with given type - * @warning If event type is already registered then nothing is done. - */ - Event.prototype.unregister = function(type) - { - - if (!(type in this.listeners)) return; - var listeners = this.listeners[type]; - delete this.listeners[type]; - return listeners; - - }; - - /** - * Remove listener from event type - * @memberOf Event.prototype - * @param {string} type The event type. - * @param {function} listener The listener function. - * @param {object} opt_this The object to use as this in listener. - * @private - */ - Event.prototype.off = function(type, listener, opt_this) - { - - if (!(type in this.listeners)) return; - - var callback = listener; - if (typeof opt_this !== 'undefined') callback = listener.bind(opt_this); - var index = this.listeners[type].indexOf(callback); - if (index > -1) this.listeners[type].splice(index, 1); - - }; - - /** - * Event handler - * @memberOf olexp.event - * @param {object} listeners Initial listeners - * @public - */ - olexp.event.Event = function(listeners) { - - var handler = new Event(listeners); - return handler; - - }; - - return olexp; - -}(olexp || {})); - - -/** - * @namespace olexp.control - */ -olexp.control = olexp.control || {}; - -//================================================== -// Edit Settings Control -//-------------------------------------------------- -(function(olexp) { - - /** - * Control to edit settings - * @param {ol.Map} map Source map - * @param {olexp.ExplorerSettings} settings olexp settings - * @private - */ - var EditSettings = function(map, settings) - { - - //================================================== - // Override Edit Settings Control default settings - // with user provided values. - //-------------------------------------------------- - var olexpSettings = $.extend(true, {control : { - EditSettings : { - form : { - header : '', - style : 'border: 0px; background-color: transparent;' - }, - hint : 'Edit Controls', - popup : { - height : 380, - style : 'width: 100%; height: 100%;', - title : 'Edit Controls', - width : 225 - }, - span : 6 - }}}, settings); - - /** - * Edit Settings control settings - * @field - * @private - * @type {Object} - */ - this.settings = olexpSettings.control.EditSettings; - - /** - * Button element id - * @field - * @private - * @type {string} - */ - this.button = settings.prefix + '-control-edit-settings-button'; - - /** - * Control icon - * @field - * @private - * @type {string} - */ - this.icon = 'olexp-control-edit-settings'; - - /** - * Control element id - * @field - * @private - * @type {string} - */ - this.id = settings.prefix + '-control-edit-settings-form'; - - /** - * Map on which to edit controls - * @field - * @private - * @type {ol.Map} - */ - this.map = map; - - /** - * Control w2ui name - * @field - * @private - * @type {string} - */ - this.name = settings.prefix + '-control-edit-settings-form'; - - }; - - /** - * Display settings editor - * @private - */ - EditSettings.prototype.display = function() - { - var me = this; - - // ================================================== - // Form fields - // -------------------------------------------------- - var fields = [ - { - html : { - caption : 'Full Screen', - span : this.settings.span - }, - name : 'fullscreen', - type : 'checkbox' - }, - { - html : { - caption : 'Mouse Position', - span : this.settings.span - }, - name : 'mouseposition', - type : 'checkbox' - }, - { - html : { - caption : 'Overview Map', - span : this.settings.span - }, - name : 'overviewmap', - type : 'checkbox' - }, - { - html : { - caption : 'Rotate', - span : this.settings.span - }, - name : 'rotate', - type: 'checkbox' - }, - { - html : { - caption : 'Scale Line', - span : this.settings.span - }, - name : 'scaleline', - type : 'checkbox' - }, - { - html : { - caption : 'Zoom', - span : this.settings.span - }, - name : 'zoom', - type : 'checkbox' - }, - { - html : { - caption : 'Zoom Slider', - span : this.settings.span - }, - name : 'zoomslider', - type : 'checkbox' - }, - { - html : { - caption : 'Zoom To Extent', - span : this.settings.span - }, - name : 'zoomtoextent', - type : 'checkbox' - } - ]; - - // ================================================== - // Extract controls to be edited - // -------------------------------------------------- - var record = { - fullscreen : this.isControlActive('fullscreen'), - mouseposition : this.isControlActive('mouseposition'), - overviewmap : this.isControlActive('overviewmap'), - rotate : this.isControlActive('rotate'), - scaleline : this.isControlActive('scaleline'), - zoom : this.isControlActive('zoom'), - zoomslider : this.isControlActive('zoomslider'), - zoomtoextent : this.isControlActive('zoomtoextent') - }; - - // ================================================== - // Function to process form changes - // -------------------------------------------------- - var onChanges = function(changes) - { - for (var name in changes) - { - var enable = changes[name]; - me.setControl(name, enable); - } - }; - - // ================================================== - // Process popup form - // -------------------------------------------------- - - var formOptions = $.extend(this.settings.form, { - fields : fields, - name : this.name, - record : record - }); - - var popupOptions = this.settings.popup; - - olexp.util.popup(this.id, onChanges, formOptions, popupOptions); - - }; - - /** - * Get control with given name - * @param {string} name Name of control to check if active - * @private - * @returns {ol.control.Control} Current control with given name or null if none - */ - EditSettings.prototype.getControl = function(name) - { - var controls = this.map.getControls().getArray(); - for (var i = 0; i < controls.length; i++) - { - var control = controls[i]; - if (name === 'fullscreen' && control instanceof ol.control.FullScreen) return control; - if (name === 'mouseposition' && control instanceof ol.control.MousePosition) return control; - if (name === 'overviewmap' && control instanceof ol.control.OverviewMap) return control; - if (name === 'rotate' && control instanceof ol.control.Rotate) return control; - if (name === 'scaleline' && control instanceof ol.control.ScaleLine) return control; - if (name === 'zoom' && control instanceof ol.control.Zoom) return control; - if (name === 'zoomslider' && control instanceof ol.control.ZoomSlider) return control; - if (name === 'zoomtoextent' && control instanceof ol.control.ZoomToExtent) return control; - } - return null; - }; - - /** - * Check if control is active - * @param {string} name Name of control to check if active - * @private - * @returns {boolean} True if control is active otherwise false - */ - EditSettings.prototype.isControlActive = function(name) - { - var control = this.getControl(name); - if (control !== null && control.getMap() !== null) return true; - return false; - }; - - /** - * Set control with given name - * @param {string} name Name of control to check if active - * @param {boolean} enable True if control is to be enabled otherwise false - * @private - */ - EditSettings.prototype.setControl = function(name, enable) - { - var control = this.getControl(name); - if (control === null) return; - var map = (enable ? this.map : null); - control.setMap(map); - }; - - /** - * Control to edit settings to enable/disable ol3 controls displayed on map. - * @memberOf olexp.control - * @param {olexp.Explorer} explorer Source explorer - * @param {object} options Control options - * @param {olexp.ExplorerSettings} options.settings Explorer settings - * @public - * @returns {external:jQuery.fn.w2toolbar.properties} EditSettings toolbar - * control - */ - olexp.control.EditSettings = function(explorer, options) { - - var control = new EditSettings(explorer.map, options.settings); - - return { - hint : control.settings.hint, - id : control.button, - img : control.icon, - onClick : function (event) { - control.display(); - }, - type : 'button' - }; - - }; - - return olexp; - -}(olexp || {})); - -// ================================================== -// Export Map Control -// -------------------------------------------------- -(function(olexp) { - - /** - * Control to export map to image - * @param {ol.Map} map Map on which to render measurements - * @param {olexp.ExplorerSettings} settings olexp settings - * @private - */ - var ExportMap = function(map, settings) - { - - //================================================== - // Override Export Map Control option defaults - // with user provided values. - //-------------------------------------------------- - var olexpSettings = $.extend(true, {control : { - ExportMap : { - filename : 'map.png', - hint : 'Export map' - }}}, settings); - - /** - * Export Map control settings - * @field - * @private - * @type {Object} - */ - this.settings = olexpSettings.control.ExportMap; - - /** - * Anchor element id - * @field - * @private - * @type {string} - */ - this.anchor = settings.prefix + '-control-export-map-anchor'; - - /** - * Button element id - * @field - * @private - * @type {string} - */ - this.button = settings.prefix + '-control-export-map-button'; - - /** - * Filename of map to download - * @field - * @private - * @type {string} - */ - this.filename = this.settings.filename; - - /** - * Icon selectors - * @field - * @private - * @type {string} - */ - this.icon = 'olexp-control-export-map'; - - /** - * Map on which to render measurements - * @field - * @private - * @type {ol.Map} - */ - this.map = map; - - }; - - /** - * Export current map to image. Activates anchor link download. - * @private - */ - ExportMap.prototype.toImage = function() - { - // ================================================== - // Create a temporary anchor, click it, then remove it - // -------------------------------------------------- - var id = this.anchor; - var filename = this.filename; - - // Create callback when anchor is clicked - var callback = function(e) - { - this.map.once('postcompose', function(event) - { - anchor.href = event.context.canvas.toDataURL('image/png'); - }); - this.map.renderSync(); - }; - - // Create anchor - $('body').append(''); - var anchor = document.getElementById(id); - anchor.addEventListener('click', callback.bind(this), false); - - // Click then remove - $('#' + id)[0].click(); - $('#' + id).remove(); - }; - - /** - * Export map to image - * @memberOf olexp.control - * @param {olexp.Explorer} explorer Source explorer - * @param {object} options Control options - * @param {olexp.ExplorerSettings} options.settings Explorer settings - * @public - * @returns {external:jQuery.fn.w2toolbar.properties} ExportMap toolbar - * control - */ - olexp.control.ExportMap = function(explorer, options) { - - var control = new ExportMap(explorer.map, options.settings); - - return { - hint : control.settings.hint, - id : control.button, - img : control.icon, - onClick : function (event) { - control.toImage(); - }, - type : 'button' - }; - - }; - - return olexp; - -}(olexp || {})); - -//================================================== -// Graticule Controls -//-------------------------------------------------- -(function(olexp) { - - /** - * Control to display graticule - * @param {ol.Map} map Source map - * @param {olexp.ExplorerSettings} settings olexp settings - * @private - */ - var Graticule = function(map, settings) - { - - //================================================== - // Override Graticule Control option defaults - // with user provided values. - //-------------------------------------------------- - var olexpSettings = $.extend(true, {control : { - Graticule : { - enable : false, - form : { - header : '', - style : 'border: 0px; background-color: transparent;' - }, - hint : 'Edit Grid Lines', - options : { - color : '000000', - lineDash : [0.5, 4], - width : 2 - }, - popup : { - height : 225, - style : 'border: 0px; background-color: transparent;', - title : 'Edit Grid Lines', - width : 300 - }, - span : 3 - }}}, settings); - - /** - * Tile control settings - * @field - * @private - * @type {Object} - */ - this.settings = olexpSettings.control.Graticule; - - /** - * Button element id - * @field - * @private - * @type {string} - */ - this.button = settings.prefix + '-control-graticule-button'; - - /** - * Control icon - * @field - * @private - * @type {string} - */ - this.icon = 'olexp-control-graticule'; - - /** - * Form element id - * @field - * @private - * @type {string} - */ - this.id = settings.prefix + '-control-graticule'; - - /** - * Parent explorer - * @field - * @private - * @type {ol.Map} - */ - this.map = map; - - /** - * Form w2ui name - * @field - * @private - * @type {string} - */ - this.name = settings.prefix + '-control-graticule-form'; - - /** - * Utility tool - * @field - * @private - * @type {olexp.util.Util} - */ - this.util = new olexp.util.Util(olexpSettings); - - /** - * Graticule tool - * @field - * @private - * @type {ol.Graticule} - */ - this.graticule = this.util.getGraticule((this.settings.enable ? this.map : null), - $.extend({}, this.settings.options)); - - }; - - /** - * Display graticule form - * @private - */ - Graticule.prototype.display = function() - { - - var me = this; - - // ================================================== - // Form fields - // -------------------------------------------------- - var fields = [ - { - html : { - caption : 'Enable', - span : this.settings.span - }, - name : 'enable', - required : true, - type : 'checkbox' - }, - { - html : { - caption : 'Color', - span : this.settings.span - }, - name : 'color', - options : { - silent: false - }, - required : true, - type : 'color', - }, - { - html : { - caption : 'Width', - span : this.settings.span - }, - name : 'width', - options : { - arrows : true, - max : 4, - min : 0.25, - placeholder : '0.25 - 4', - silent : false, - step : 0.25 - }, - required : true, - type : 'float', - } - ]; - - // ================================================== - // Define allowable tile types - // -------------------------------------------------- - var record = this.graticule.olexp_record; - - // ================================================== - // Function to process form changes - // -------------------------------------------------- - var onChanges = function(changes) - { - for (var name in changes) - { - record[name] = changes[name]; - } - var options = $.extend({}, record); - delete options.enable; - me.graticule.setMap(null); - me.graticule = me.util.getGraticule((record.enable ? me.map : null), options); - }; - - // ================================================== - // Process popup form - // -------------------------------------------------- - - var formOptions = $.extend(this.settings.form, { - fields : fields, - name : this.name, - record : record - }); - - var popupOptions = this.settings.popup; - - olexp.util.popup(this.id, onChanges, formOptions, popupOptions); - - }; - - /** - * Control to edit grid lines. - * @memberOf olexp.control - * @param {olexp.Explorer} explorer Source Explorer - * @param {object} options Control options - * @param {olexp.ExplorerSettings} options.settings Explorer settings - * @public - * @returns {external:jQuery.fn.w2toolbar.properties} Graticule toolbar - * control - */ - olexp.control.Graticule = function(explorer, options) { - - if (typeof options === "undefined") options = {}; - if (typeof options.settings === "undefined") options.settings = {}; - - var control = new Graticule(explorer.map, options.settings); - - return { - hint : control.settings.hint, - id : control.button, - img : control.icon, - onClick : function (event) { - control.display(); - }, - type : 'button' - }; - - }; - - return olexp; - -}(olexp || {})); - -//================================================== -// Layer Controls -//-------------------------------------------------- -(function(olexp) { - - /** - * Control to add layers - * @param {ol.Map} map - * @param {olexp.ExplorerSettings} settings olexp settings - * @private - */ - var LayerControl = function(map, settings) - { - - //================================================== - // Override Layer Control Tile option defaults - // with user provided values. - //-------------------------------------------------- - var olexpSettings = $.extend(true, {control : { - LayerControlTile : { - form : { - header : '', - style : 'border: 0px; background-color: transparent;' - }, - hint : 'Add Tile Layer', - popup : { - height : 165, - style : 'border: 0px; background-color: transparent;', - title : 'Add Tile Layer', - width : 290 - }, - span : 3 - }, - LayerControlVector : { - form : { - header : ('File Types: ' + $.map(olexp.util.FileTypes, - function(o) { return ' ' + o.name; })), - style : 'border: 0px; background-color: transparent;' - }, - hint : 'Add Vector Layer', - popup : { - height : 195, - style : 'border: 0px; background-color: transparent;', - title : 'Add Vector Layer', - width : 350 - }, - span : 4 - }}}, settings); - - /** - * Tile control settings - * @field - * @private - * @type {Object} - */ - this.settingsTile = olexpSettings.control.LayerControlTile; - - /** - * Vector control settings - * @field - * @private - * @type {Object} - */ - this.settingsVector = olexpSettings.control.LayerControlVector; - - /** - * Control icons - * @field - * @private - * @type {string} - */ - this.icons = { - tile : 'olexp-control-layer-control-add-tile', - vector : 'olexp-control-layer-control-add-vector' - }; - - /** - * Button element ids - * @field - * @private - * @type {string} - */ - this.buttons = { - tile : settings.prefix + '-control-layer-control-add-tile-button', - vector : settings.prefix + '-control-layer-control-add-vector-button' - }; - - /** - * Controls element ids - * @field - * @private - * @type {string} - */ - this.ids = { - tile : settings.prefix + '-control-layer-control-add-tile', - vector : settings.prefix + '-control-layer-control-add-vector' - }; - - /** - * Parent map - * @field - * @private - * @type {ol.Map} - */ - this.map = map; - - /** - * w2ui form names - * @field - * @private - * @type {object} - */ - this.names = { - tile : settings.prefix + '-control-tile-form', - vector : settings.prefix + '-control-vector-form' - }; - - /** - * Utility tool - * @field - * @private - * @type {olexp.util.Util} - */ - this.util = new olexp.util.Util(this.map); - - }; - - /** - * Display add tile form - * @private - */ - LayerControl.prototype.tile = function() - { - var me = this; - - // ================================================== - // Define allowable tile types - // -------------------------------------------------- - var tileTypes = this.util.getTileTypes(); - var items = $.map(tileTypes, function(val) { return val.name; }); - - // ================================================== - // Form fields - // -------------------------------------------------- - var fields = [ - { - field : 'tile_source', - html : { - caption : 'Source', - span : this.settingsTile.span - }, - options : { - items: items - }, - required : true, - type : 'list' - } - ]; - - // ================================================== - // Form record - // -------------------------------------------------- - var record = {}; - record[fields[0].field] = null; - - // ================================================== - // Function to process form changes - // -------------------------------------------------- - var onChanges = function(changes) - { - for (var fieldName in changes) - { - if (fieldName === fields[0].field) - { - // Search for selected tile in list - var typeName = changes[fieldName].id; - for (var key in tileTypes) - { - if (typeName !== tileTypes[key].name) continue; - var tileType = tileTypes[key]; - var tileClass = tileType['class']; - var tile = new ol.layer.Tile({ - source: new tileClass(tileType.settings) - }); - tile.set('name', typeName); - me.map.addLayer(tile); - } - } - } - }; - - // ================================================== - // Process popup form - // -------------------------------------------------- - - var formOptions = $.extend(this.settingsTile.form, { - fields : fields, - name : this.names.tile, - record : record - }); - - var popupOptions = this.settingsTile.popup; - - olexp.util.popup(this.ids.tile, onChanges, formOptions, popupOptions); - - }; - - /** - * Display add vector form - * @private - */ - LayerControl.prototype.vector = function() - { - var me = this; - - // ================================================== - // Form fields - // -------------------------------------------------- - var fields = [ - { - field : 'vector_source', - html : { - caption : 'Source', - span : this.settingsVector.span - }, - options : { - placeholder : 'Click to add file', - silent : false - }, - required : true, - type : 'file' - } - ]; - - // ================================================== - // Form record - // -------------------------------------------------- - var record = {}; - record[fields[0].field] = null; - - // ================================================== - // Function to process form changes - // -------------------------------------------------- - var onChanges = function(changes) - { - for (var fieldName in changes) - { - if (fieldName === fields[0].field) - { - // Search for selected tile in list - for (var change in changes[fieldName]) - { - - // Check that file contents are valid - var content = changes[fieldName][change].content; - if (typeof content === 'undefined' || content === null) continue; - - // Extract filename and contents - var filename = changes[fieldName][change].name; - var name = filename.replace(/\.[^/.]+$/, ""); - - // Get file reader - var reader = olexp.util.getReader(filename); - if (reader === null) - { - w2alert('Unable to open file ' + filename, 'Error'); - return; - } - - // Convert file contents from base64 to text - // Read features and convert to map coordinates - var text = atob(content); - var projection = me.map.getView().getProjection(); - var options = {'featureProjection' : projection}; - var features = reader.readFeatures(text, options); - - // Add features to map - me.util.addLayerVector(me.map, name, features); - } - } - } - }; - - // ================================================== - // Process popup form - // -------------------------------------------------- - - var formOptions = $.extend(this.settingsVector.form, { - fields : fields, - name : this.names.vector, - record : record - }); - - var popupOptions = this.settingsVector.popup; - - olexp.util.popup(this.ids.vector, onChanges, formOptions, popupOptions); - - }; - - /** - * Control to add layers - * @memberOf olexp.control - * @param {olexp.Explorer} explorer Source Explorer - * @param {object} options Control options - * @param {boolean} options.tile Enable tile control - * @param {boolean} options.vector Enable vector control - * @param {olexp.ExplorerSettings} options.settings Explorer settings - * @public - * @returns {array} Array of w2toolbar properties - */ - olexp.control.LayerControl = function(explorer, options) { - - if (typeof options === "undefined") options = {}; - if (typeof options.tile === "undefined") options.tile = true; - if (typeof options.vector === "undefined") options.vector = true; - if (typeof options.settings === "undefined") options.settings = {}; - - var tool = new LayerControl(explorer.map, options.settings); - - // Add controls for those selected - var controls = []; - if (options.tile) - { - controls.push({ - hint : tool.settingsTile.hint, - id : tool.buttons.tile, - img : tool.icons.tile, - onClick : function (event) { - tool.tile(); - }, - type : 'button' - }); - } - if (options.vector) - { - controls.push({ - hint : tool.settingsVector.hint, - id : tool.buttons.vector, - img : tool.icons.vector, - onClick : function (event) { - tool.vector(); - }, - type : 'button' - }); - } - - return controls; - - }; - - return olexp; - -}(olexp || {})); - -//================================================== -// Layer Manager Controls -//-------------------------------------------------- -olexp = (function(olexp) { - - /** - * Control to manage layers - * @param {olexp.Explorer} explorer Explorer - * @param {olexp.manager.Manager} manager Explorer manager - * @param {olexp.ExplorerSettings} settings olexp settings - * @private - */ - var LayerManager = function(explorer, manager, settings) - { - - //================================================== - // Override Layer Manager option defaults - // with user provided values. - //-------------------------------------------------- - var olexpSettings = $.extend(true, {control : { - LayerManager : { - hintDetailsHide : 'Hide details', - hintDetailsShow : 'Show details', - hintMoveDown : 'Move item down', - hintMoveUp : 'Move item up', - hintOutlineHide : 'Hide outline', - hintOutlineShow : 'Show outline' - }}}, settings); - - /** - * Button element ids - * @field - * @private - * @type {string} - */ - this.buttons = { - details : settings.prefix + '-control-layer-manager-button-details', - down : settings.prefix + '-control-layer-manager-button-down', - navigation : settings.prefix + '-control-layer-manager-button-navigation', - up : settings.prefix + '-control-layer-manager-button-up' - }; - - /** - * Explorer - * @field - * @private - * @type {olexp.Explorer} - */ - this.explorer = explorer; - - /** - * Control icon - * @field - * @private - * @type {string} - */ - this.icons = { - details : 'olexp-control-layer-manager-details', - down : 'olexp-control-layer-manager-down', - navigation : 'olexp-control-layer-manager-navigation', - up : 'olexp-control-layer-manager-up' - }; - - /** - * Explorer manager - * @field - * @private - * @type {olexp.manager.Manager} - */ - this.manager = manager; - - /** - * Layer Manager control settings - * @field - * @private - * @type {string} - */ - this.settings = olexpSettings.control.LayerManager; - - // ================================================== - // Add layer callback events - // -------------------------------------------------- - this.manager.on('remove:item', this.onItemRemoved, this); - this.manager.on('select:item', this.onItemSelected, this); - - }; - - /** - * Show details - * @private - */ - LayerManager.prototype.details = function() - { - this.explorer.navigation.toggle(this.explorer.options.details.type); - // Set control tooltip based on navigation panel visibility - var details = this.explorer.navigation.get(this.explorer.options.details.type); - var item = this.explorer.toolbar.get(this.buttons.details); - item.hint = this.hintDetails(details.hidden); - this.explorer.toolbar.refresh(); - }; - - /** - * Move layer down - * @private - */ - LayerManager.prototype.down = function() - { - this.manager.moveDown(); - }; - - /** - * Set details control hint text - * @param {boolean} hidden True if details is hidden otherwise false - * @private - */ - LayerManager.prototype.hintDetails = function(hidden) - { - return (hidden ? this.settings.hintDetailsShow : this.settings.hintDetailsHide); - }; - - /** - * Set navigation control hint text - * @param {boolean} hidden True if navigation is hidden otherwise false - * @private - */ - LayerManager.prototype.hintNavigation = function(hidden) - { - return (hidden ? this.settings.hintOutlineShow : this.settings.hintOutlineHide); - }; - - /** - * Show navigation - * @private - */ - LayerManager.prototype.navigation = function() - { - this.explorer.layout.toggle(this.explorer.options.navigation.type); - // Set control tooltip based on navigation panel visibility - var navigation = this.explorer.layout.get(this.explorer.options.navigation.type); - var item = this.explorer.toolbar.get(this.buttons.navigation); - item.hint = this.hintNavigation(navigation.hidden); - this.explorer.toolbar.refresh(); - }; - - /** - * Callback when layer removed - * @param {olexp.item.Item} item OpenLayers Explorer Item - * @private - */ - LayerManager.prototype.onItemRemoved = function(item) - { - - if (this.manager.isSelected(item.id)) - { - this.explorer.toolbar.disable(this.buttons.up); - this.explorer.toolbar.disable(this.buttons.down); - } - - }; - - /** - * Callback when node is selected either by click or double click - * @param {string} id Layer ID - * @private - */ - LayerManager.prototype.onItemSelected = function(id) - { - if (typeof id === 'undefined') return; - var item = this.manager.getById(id); - if (item === null) return; - var node = this.manager.getNode(item.id); - if (node.disabled) - { - this.explorer.toolbar.disable(this.buttons.up); - this.explorer.toolbar.disable(this.buttons.down); - } - else - { - this.explorer.toolbar.enable(this.buttons.up); - this.explorer.toolbar.enable(this.buttons.down); - } - }; - - /** - * Move layer up - * @private - */ - LayerManager.prototype.up = function() - { - this.manager.moveUp(); - }; - - /** - * Control to manage layers - * @memberOf olexp.control - * @param {olexp.Explorer} explorer Explorer - * @param {olexp.manager.Manager} manager Explorer manager - * @param {object} options Control options - * @param {object} options.details Enable details panel options - * @param {boolean} options.details.enabled Enable details control - * @param {boolean} options.details.checked Indicate checked state - * @param {boolean} options.down Enable down control - * @param {object} options.navigation Enable navigation options - * @param {boolean} options.navigation.enabled Enable navigation control - * @param {boolean} options.navigation.checked Indicate checked state - * @param {olexp.ExplorerSettings} options.settings Explorer settings - * @param {boolean} options.up Enable up control - * @public - * @returns {array} Array of external:jQuery.fn.w2toolbar.properties - */ - olexp.control.LayerManager = function(explorer, manager, options) { - - if (typeof options === "undefined") options = {}; - - if (typeof options.details === "undefined") options.details = {}; - if (typeof options.details.enabled === "undefined") options.details.enabled = true; - if (typeof options.details.checked === "undefined") options.details.checked = true; - if (typeof options.down === "undefined") options.down = true; - if (typeof options.navigation === "undefined") options.navigation = {}; - if (typeof options.navigation.enabled === "undefined") options.navigation.enabled = true; - if (typeof options.navigation.checked === "undefined") options.navigation.checked = true; - if (typeof options.up === "undefined") options.up = true; - - var tool = new LayerManager(explorer, manager, options.settings); - - // Add controls for those selected - var controls = []; - if (options.navigation.enabled) - { - // Determine control tooltip based on navigation panel visibility - controls.push({ - checked : options.navigation.checked, - hint : tool.hintNavigation(!options.navigation.checked), - id : tool.buttons.navigation, - img : tool.icons.navigation, - onClick : function (event) { - tool.navigation(); - }, - type : 'check' - }); - } - if (options.details.enabled) - { - // Determine control tooltip based on details panel visibility - controls.push({ - checked : options.details.checked, - hint : tool.hintDetails(!options.details.checked), - id : tool.buttons.details, - img : tool.icons.details, - onClick : function (event) { - tool.details(); - }, - type : 'check' - }); - } - if (options.up) - { - controls.push({ - disabled : true, - hint : tool.settings.hintMoveUp, - id : tool.buttons.up, - img : tool.icons.up, - onClick : function (event) { - tool.up(); - }, - type : 'button' - }); - } - if (options.down) - { - controls.push({ - disabled : true, - hint : tool.settings.hintMoveDown, - id : tool.buttons.down, - img : tool.icons.down, - onClick : function (event) { - tool.down(); - }, - type : 'button' - }); - } - - return controls; - - }; - - return olexp; - -}(olexp || {})); - -//================================================== -// Layer Menu Control -//-------------------------------------------------- -(function(olexp) { - - /** - * Control to display layer menu properties - * @param {olexp.Explorer} explorer Explorer - * @param {olexp.manager.Manager} manager Explorer manager - * @param {object} menu Item Menus {items : list of menu item, - * callbacks : list of menu item callbacks} - * @param {olexp.ExplorerSettings} settings olexp.ExplorerSettings - * @private - */ - var LayerMenu = function(explorer, manager, menu, settings) - { - - //================================================== - // Override Layer Menu Control option defaults - // with user provided values. - //-------------------------------------------------- - var olexpSettings = $.extend(true, {control : { - LayerMenu : { - arrow : true, - hint : 'Item Options', - text : '' - }}}, settings); - - /** - * Button element id - * @field - * @private - * @type {string} - */ - this.button = settings.prefix + '-control-layer-menu'; - - /** - * Explorer - * @field - * @private - * @type {olexp.Explorer} - */ - this.explorer = explorer; - - /** - * Control icon - * @field - * @private - * @type {string} - */ - this.icon = 'olexp-control-layer-menu'; - - /** - * Explorer manager - * @field - * @private - * @type {olexp.manager.Manager} - */ - this.manager = manager; - - /** - * Menu items and callbacks - * @field - * @private - * @type {Object} - */ - this.menu = menu; - - /** - * Layer Menu control settings - * @field - * @private - * @type {Object} - */ - this.settings = olexpSettings.control.LayerMenu; - - // ================================================== - // Add layer callback events - // -------------------------------------------------- - this.manager.on('remove:item', this.onItemRemoved, this); - this.manager.on('select:item', this.onItemSelected, this); - - }; - - /** - * Callback when layer removed - * @param {olexp.item.Item} item OpenLayers Explorer Item - * @private - */ - LayerMenu.prototype.onItemRemoved = function(item) - { - - if (this.manager.isSelected(item.id)) - { - this.explorer.toolbar.disable(this.button); - } - - }; - - /** - * Callback when node is selected either by click or double click - * @param {string} id Layer ID - * @private - */ - LayerMenu.prototype.onItemSelected = function(id) - { - if (typeof id === 'undefined') return; - var item = this.manager.getById(id); - if (item === null) return; - var node = this.manager.getNode(item.id); - if (node.disabled) - { - this.explorer.toolbar.disable(this.button); - } - else - { - this.explorer.toolbar.enable(this.button); - } - }; - - /** - * Display layer properties menu control - * @memberOf olexp.control - * @param {olexp.Explorer} explorer Source explorer - * @param {olexp.manager.Manager} manager Explorer manager - * @param {object} menu Item Menu items and callbacks - * @param {Array} menu.items List of menu items - * @param {Array} menu.callbacks List of menu item callbacks - * @param {object} options Control options - * @param {olexp.ExplorerSettings} options.settings Explorer settings - * @public - * @returns {external:jQuery.fn.w2toolbar.properties} LayerMenu toolbar - * control - */ - olexp.control.LayerMenu = function(explorer, manager, menu, options) { - - var control = new LayerMenu(explorer, manager, menu, options.settings); - - explorer.toolbar.on('click', function(event) { - - // Check if any item is selected - if (explorer.outline.selected === null) return; - - // Check if layer menu item was selected - var id = control.button + ':'; - if (event.target.indexOf(id) < 0) return; - var menuid = event.target.replace(id, ""); - - // Create dummy menu event - if (menuid in menu.callbacks) - { - menu.callbacks[menuid]({target : explorer.outline.selected}); - } - - }); - - return { - arrow : control.settings.arrow, - disabled : true, - hint : control.settings.hint, - id : control.button, - img : control.icon, - items : control.menu.items, - text : control.settings.text, - type : 'menu' - }; - - }; - - return olexp; - -}(olexp || {})); - -//================================================== -// Measurement Controls -//-------------------------------------------------- -(function(olexp) { - - /** - * Control to calculate measurements - * @param {olexp.Explorer} explorer Explorer - * @param {olexp.ExplorerSettings} settings olexp settings - * @private - */ - var Measurement = function(explorer, settings) - { - - //================================================== - // Override Measurement option defaults - // with user provided values. - //-------------------------------------------------- - var olexpSettings = $.extend(true, {control : { - Measurement : { - hintArea : 'Measure area', - hintLength : 'Measure length' - }}}, settings); - - /** - * Parent explorer - * @field - * @private - * @type {olexp.Explorer} - */ - this.explorer = explorer; - - /** - * Control icon - * @field - * @private - * @type {string} - */ - this.icons = { - area : 'olexp-control-measure-area', - length : 'olexp-control-measure-length' - }; - - /** - * Button element id - * @field - * @private - * @type {string} - */ - this.ids = { - area : settings.prefix + '-control-measure-area-button', - length : settings.prefix + '-control-measure-length-button' - }; - - /** - * Measurement control settings - * @field - * @private - * @type {Object} - */ - this.settings = olexpSettings.control.Measurement; - - /** - * Measurement tool - * @field - * @private - * @type {olexp.measure.Tool} - */ - this.tool = new olexp.measure.Tool(explorer.map, - olexp.measure.Type.LINE, - settings); - - }; - - /** - * Start area measurement - * @memberOf Measurement.prototype - * @private - */ - Measurement.prototype.area = function() - { - var enable = !this.explorer.toolbar.get(this.ids.area).checked; - this.measure(olexp.measure.Type.AREA, enable); - }; - - /** - * Start length measurement - * @memberOf Measurement.prototype - * @private - */ - Measurement.prototype.length = function() - { - var enable = !this.explorer.toolbar.get(this.ids.length).checked; - this.measure(olexp.measure.Type.LINE, enable); - }; - - /** - * Run measurement tool - * @memberOf Measurement.prototype - * @param {olexp.measure.Type} type Measurement type to start. - * @param {boolean} enable True if measurement is started otherwise false - * @private - */ - Measurement.prototype.measure = function(type, enable) - { - this.tool.setEnable(false); - if (enable) - { - this.tool.setType(type); - this.tool.setEnable(true); - } - }; - - /** - * Control to export map to image - * @memberOf olexp.control - * @param {olexp.Explorer} explorer Explorer - * @param {object} options Control options - * @param {boolean} options.area Enable area measurement control - * @param {boolean} options.length Enable length measurement control - * @param {olexp.ExplorerSettings} options.settings Explorer settings - * @public - * @returns {array} Array of w2toolbar properties - */ - olexp.control.Measure = function(explorer, options) { - - if (typeof options === "undefined") options = {}; - if (typeof options.area === "undefined") options.area = true; - if (typeof options.length === "undefined") options.length = true; - if (typeof options.settings === "undefined") options.settings = {}; - - var tool = new Measurement(explorer, options.settings); - - // Add controls for those selected - var controls = []; - if (options.area) - { - controls.push({ - hint : tool.settings.hintArea, - id : tool.ids.area, - img : tool.icons.area, - onClick : function (event) { - if (options.length) - { - explorer.toolbar.uncheck(tool.ids.length); - } - tool.area(); - }, - type : 'check' - }); - } - if (options.length) - { - controls.push({ - hint : tool.settings.hintLength, - id : tool.ids.length, - img : tool.icons.length, - onClick : function (event) { - if (options.area) - { - explorer.toolbar.uncheck(tool.ids.area); - } - tool.length(); - }, - type : 'check' - }); - } - - return controls; - - }; - - return olexp; - -}(olexp || {})); - -//================================================== -// Toolbar Hide Control -//-------------------------------------------------- -(function(olexp) { - - /** - * Control to hide toolbar - * @param {olexp.Explorer} explorer Source explorer - * @param {object} options Control options {hidden : True if toolbar is - * initially hidden, - * settings : olexp.ExplorerSettings} - * @private - */ - var ToolbarHide = function(explorer, options) - { - - //================================================== - // Override Toolbar Hide option defaults - // with user provided values. - //-------------------------------------------------- - var olexpSettings = $.extend(true, {control : { - ToolbarHide : { - hint : 'Hide toolbar' - }}}, options.settings); - - /** - * Button element id - * @field - * @private - * @type {string} - */ - this.button = options.settings.prefix + '-control-toolbar-hide-button'; - - /** - * Source explorer - * @field - * @private - * @type {olexp.Explorer} - */ - this.explorer = explorer; - - /** - * Control icon - * @field - * @private - * @type {string} - */ - this.icon = 'olexp-control-toolbar-hide'; - - /** - * ToolbarHide control settings - * @field - * @private - * @param {Object} settings - */ - this.settings = olexpSettings.control.ToolbarHide; - - /** - * ol.control to show toolbar when hidden - * @field - * @private - * @type {olexp.ol.ToolbarShow} - */ - this.show = olexp.ol.ToolbarShow(this.explorer, options); - - }; - - /** - * Toolbar visibility - * @private - */ - ToolbarHide.prototype.hide = function() - { - this.explorer.layout.hide(this.explorer.options.toolbar.type); - this.show.setMap(this.explorer.map); - }; - - /** - * Control to set toolbar visibility - * @memberOf olexp.control - * @param {olexp.Explorer} explorer Source Explorer - * @param {object} options Control options - * @param {boolean} options.hidden True if toolbar is initially hidden - * @param {olexp.ExplorerSettings} options.settings Explorer settings - * @public - * @returns {external:jQuery.fn.w2toolbar.properties} ToolbarHide toolbar - * control - */ - olexp.control.ToolbarHide = function(explorer, options) - { - - var control = new ToolbarHide(explorer, options); - - return { - hint : control.settings.hint, - id : control.button, - img : control.icon, - onClick : function (event) { - control.hide(); - }, - type : 'button' - }; - }; - - return olexp; - -}(olexp || {})); - - -/** - * @namespace olexp.item - */ -olexp.item = olexp.item || {}; - -//================================================== -// Explorer managed item -//-------------------------------------------------- -(function(olexp) { - - /** - * Item icons - * @enum {string} - * @memberOf olexp.item - * @public - * @readonly - */ - olexp.item.icons = { - /** - * Group icon css selector - * @type string - */ - group : 'olexp-item-group', - /** - * Heat Map icon css selector - * @type string - */ - heatmap : 'olexp-item-heatmap', - /** - * Image icon css selector - * @type string - */ - image : 'olexp-item-image', - /** - * Overlay icon css selector - * @type string - */ - overlay : 'olexp-item-overlay', - /** - * Tile Map icon css selector - * @type string - */ - tile : 'olexp-item-tile', - /** - * Vector icon css selector - * @type string - */ - vector : 'olexp-item-vector' - }; - - /** - * Item managed - * @param {string} id Item ID - * @param {string} name Item name - * @param {ol.layer.Layer|ol.Overlay} layer ol3 layer/overlay object - * @private - */ - Item = function(id, name, layer) - { - - /** - * Item id - * @field - * @private - * @type {string} - */ - this.id = id; - - /** - * ol3 layer/overlay object - * @field - * @private - * @type {ol.layer.Layer|ol.Overlay} - */ - this.layer = layer; - - /** - * Indicates if item is currently being moved in manager - * @field - * @private - * @type {string} - */ - this.moving = false; - - /** - * Item name - * @field - * @private - * @type {string} - */ - this.name = name; - - /** - * Item type - * @field - * @private - * @readonly - * @type {olexp.item.Type} - */ - this.type = Item.getType(this.layer); - - /** - * Item icon - * @field - * @private - * @readonly - * @type {string} - */ - this.icon = Item.getIcon(this.type); - - }; - - /** - * Get item details - * @memberOf Item.prototype - * @private - * @returns {object} Object of item properties - */ - Item.prototype.getDetails = function() - { - var properties = {}; - - // ================================================== - // Generic properties - // -------------------------------------------------- - properties.Name = this.name; - - var layerProperties = this.layer.getProperties(); - if (layerProperties.hasOwnProperty(olexp.measure.properties.area)) - { - properties.Area = layerProperties[olexp.measure.properties.area]; - } - else if (layerProperties.hasOwnProperty(olexp.measure.properties.length)) - { - properties.Length = layerProperties[olexp.measure.properties.length]; - } - - // ================================================== - // Group properties - // -------------------------------------------------- - if (this.type === olexp.item.Type.GROUP) - { - var layers = this.layer.getLayers(); - properties['Layer Count'] = layers.getLength(); - } - - // ================================================== - // Vector properties - // -------------------------------------------------- - if (this.type === olexp.item.Type.VECTOR) - { - var source = this.layer.getSource(); - var features = source.getFeatures(); - properties['Feature Count'] = features.length; - } - - // ================================================== - // Convert properties to records - // -------------------------------------------------- - var records = olexp.util.toRecords(properties); - - return records; - }; - - /** - * Get item extent - * @memberOf Item.prototype - * @private - * @returns {ol.Extent|null} Item extent or null if undefined - */ - Item.prototype.getExtent = function() - { - - if (this.type === olexp.item.Type.OVERLAY) - { - return null; - } - else if (this.type === olexp.item.Type.GROUP) - { - var extent = null; - var layers = this.layer.getLayers(); - layers.forEach(function(layer, index, array) - { - var layerExtent = Item.getLayerExtent(layer); - if ((extent === null) && - (layerExtent !== null)) - { - extent = layerExtent; - } - else if ((extent !== null) && - (layerExtent !== null)) - { - extent = ol.extent.extend(extent, layerExtent); - } - }, this); - return extent; - } - - return Item.getLayerExtent(this.layer); - - }; - - /** - * Get item icon based on type - * @memberOf Item - * @param {olexp.item.Type} type Item type - * @private - * @returns {string} CSS selector of icon - */ - Item.getIcon = function(type) - { - if (type === olexp.item.Type.GROUP) - { - return olexp.item.icons.group; - } - else if (type === olexp.item.Type.HEATMAP) - { - return olexp.item.icons.heatmap; - } - else if (type === olexp.item.Type.IMAGE) - { - return olexp.item.icons.image; - } - else if (type === olexp.item.Type.OVERLAY) - { - return olexp.item.icons.overlay; - } - else if (type === olexp.item.Type.TILE) - { - return olexp.item.icons.tile; - } - else if (type === olexp.item.Type.VECTOR) - { - return olexp.item.icons.vector; - } - return 'icon-page'; - }; - - /** - * Get layer extent - * @memberOf Item.prototype - * @param {ol.layer.Layer} layer Source layer - * @private - * @returns {ol.Extent|null} Layer extent or null if undefined - */ - Item.getLayerExtent = function(layer) - { - - // ================================================== - // Check if layer has extent defined - // -------------------------------------------------- - var extent = layer.getExtent(); - if (typeof extent === 'undefined') - { - // ================================================== - // Check if source has extent defined - // -------------------------------------------------- - var source = layer.getSource(); - if (source !== null && - (source instanceof ol.source.Cluster || - source instanceof ol.source.VectorTile || - source instanceof ol.source.Vector)) - { - extent = source.getExtent(); - } - } - if (typeof extent === 'undefined') return null; - return extent; - - }; - - /** - * List of editable properties of layer/overlay - * @memberOf Item.prototype - * @private - * @returns {object} Item properties names - */ - Item.prototype.getPropertyTypes = function() - { - if (this.layer instanceof ol.layer.Layer) - { - return olexp.item.LayerProperties; - } - else if (this.layer instanceof ol.Overlay) - { - return olexp.item.OverlayProperties; - } - return {}; - }; - - /** - * Update item editable properties - * @memberOf Item.prototype - * @private - * @returns {object} Item properties - */ - Item.prototype.getProperties = function() - { - var properties = {name: this.name}; - var types = this.getPropertyTypes(); - for (var key in types) - { - properties[key] = this.layer.get(key); - } - return properties; - }; - - /** - * Get item type for given layer - * @memberOf Item - * @param {ol.layer.Layer|ol.Overlay} layer Source layer - * @private - * @returns {olexp.item.Type} Type of item - */ - Item.getType = function(layer) - { - if (layer instanceof ol.layer.Group) - { - return olexp.item.Type.GROUP; - } - else if (layer instanceof ol.layer.Heatmap) - { - return olexp.item.Type.HEATMAP; - } - else if (layer instanceof ol.layer.Image) - { - return olexp.item.Type.IMAGE; - } - else if (layer instanceof ol.layer.Tile) - { - return olexp.item.Type.TILE; - } - else if (layer instanceof ol.layer.Vector) - { - return olexp.item.Type.VECTOR; - } - else if (layer instanceof ol.Overlay) - { - return olexp.item.Type.OVERLAY; - } - return null; - }; - - /** - * Update item editable properties - * @memberOf Item.prototype - * @param {Object} properties Item properties to update - * @private - */ - Item.prototype.setProperties = function(properties) - { - if (properties.hasOwnProperty('name')) this.name = properties.name; - var types = this.getPropertyTypes(); - for (var key in types) - { - if (properties.hasOwnProperty(key)) this.layer.set(key, properties[key]); - } - }; - - /** - * Get/set item property - * @memberOf Item.prototype - * @param {string} name Property name - * @param {object} value Property value - * @private - */ - Item.prototype.property = function(name, value) - { - if (typeof this[name] === 'undefined') return; - if (typeof value !== 'undefined') this[name] = value; - return this[name]; - }; - - /** - * Get item extent - * @memberOf Item.prototype - * @param {ol.Map} map ol3 map to zoom - * @private - */ - Item.prototype.zoomTo = function(map) - { - - var view = map.getView(); - - if (this.type === olexp.item.Type.OVERLAY) - { - - // ================================================== - // Check if overlay has position defined - // -------------------------------------------------- - var position = this.layer.getPosition(); - if (typeof position !== 'undefined') - { - view.setCenter(position); - return; - } - - w2alert('Overlay has no position defined to which to zoom.', 'Warning'); - - } - else - { - - // ================================================== - // Check if layer has extent defined - // -------------------------------------------------- - var extent = this.getExtent(); - if (extent !== null) - { - view.fit(extent, map.getSize()); - return; - } - - w2alert('Layer has no extent defined to which to zoom.', 'Warning'); - - } - - }; - - /** - * Item managed - * @memberOf olexp.item - * @param {string} id Item ID - * @param {string} name Item name - * @param {external:ol.layer.Layer|external:ol.Overlay} layer ol3 layer or - * overlay object - * @public - */ - olexp.item.Item = function(id, name, layer) - { - var item = new Item(id, name, layer); - return { - getDetails : item.getDetails.bind(item), - getProperties : item.getProperties.bind(item), - getPropertyTypes : item.getPropertyTypes.bind(item), - icon : item.icon, - id : item.id, - layer : item.layer, - moving : function(moving) { - return item.property('moving', moving); - }, - name : function(name) { - return item.property('name', name); - }, - setProperties : item.setProperties.bind(item), - type : item.type, - zoomTo : item.zoomTo.bind(item) - }; - }; - - /** - * Enumeration of Overlay properties - * @enum {string} - * @memberOf olexp.item - * @public - * @readonly - */ - olexp.item.OverlayProperties = - { - }; - - /** - * Enumeration of Layer properties - * @enum {string} - * @memberOf olexp.item - * @public - * @readonly - */ - olexp.item.LayerProperties = - { - /** - * Opacity property - * @type object - */ - opacity : { - /** - * Opacity title - * @type string - */ - title : 'Opacity' - } - }; - - /** - * Enumeration of types of allowable managed items - * @enum {string} - * @memberOf olexp.item - * @public - * @readonly - */ - olexp.item.Type = { - /** - * Group managed item - * @type number - */ - GROUP : 0, - /** - * Heat Map managed item - * @type number - */ - HEATMAP : 1, - /** - * Image managed item - * @type number - */ - IMAGE : 2, - /** - * Overlay managed item - * @type number - */ - OVERLAY : 3, - /** - * Tile managed item - * @type number - */ - TILE : 4, - /** - * Vector managed item - * @type number - */ - VECTOR : 5 - }; - - return olexp; - -}(olexp || {})); - - -/** - * @namespace olexp.manager - */ -olexp.manager = olexp.manager || {}; - -//================================================== -// Manager -//-------------------------------------------------- -(function(olexp) { - - /** - * Item manager that synchronizes adding and removing items from the map - * sidebar and the corresponding layers on the ol3 map - * @class - * @memberOf olexp.manager - * @param {external:ol.Map} map Managed map - * @param {external:jQuery.fn.w2sidebar} outline Managed outline sidebar - * @param {external:jQuery.fn.w2grid} details Details grid - * @param {string} layersId w2ui name of layers node - * @param {string} overlaysId w2ui name of overlays node - * @private - */ - var ManagerAPI = function(map, outline, details, layersId, overlaysId) - { - - /** - * Event listeners - * @ignore - * @type {olexp.event.Event} - */ - this.event = new olexp.event.Event({'select:item' : []}); - - /** - * Layer Manager - * @ignore - * @type {olexp.manager.NodeManager} - */ - this.managerLayers = new olexp.manager.NodeManager(layersId, - map.getLayers(), - outline, - details); - - /** - * Layers node id prefix - * @ignore - * @type {string} - */ - this.layersId = layersId; - - /** - * Overlay Manager - * @ignore - * @type {olexp.manager.NodeManager} - */ - this.managerOverlays = new olexp.manager.NodeManager(overlaysId, - map.getOverlays(), - outline, - details); - - /** - * Managed map - * @ignore - * @type {ol.Map} - */ - this.map = map; - this.map.on('change:layergroup', this.onLayerGroupChanged, this); - - /** - * Managed outline sidebar - * @ignore - * @type {external:jQuery.fn.w2sidebar} - */ - this.outline = outline; - - /** - * Overlays node id prefix - * @ignore - * @type {string} - */ - this.overlaysId = overlaysId; - - }; - - /** - * Check if id is a Layer node - * @ignore - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id Item ID - * @private - * @returns True if id a Layer node otherwise false - */ - ManagerAPI.prototype.isIdLayerNode = function(id) - { - if (typeof id !== 'string') return false; - return id.indexOf(this.layersId) === 0; - }; - - /** - * Check if id is a Overlay node - * @ignore - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id Item ID - * @private - * @returns True if id is a Overlay node otherwise false - */ - ManagerAPI.prototype.isIdOverlayNode = function(id) - { - if (typeof id !== 'string') return false; - return id.indexOf(this.overlaysId) === 0; - }; - - /** - * Check if item is selected - * @function isSelected - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id Item ID - * @public - * @returns True if item is selected otherwise false - */ - ManagerAPI.prototype.isSelected = function(id) - { - return id === this.outline.selected; - }; - - /** - * Get item based on id - * @function getById - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id Item ID - * @public - * @returns {null|olexp.item.Item} Managed item or null if not found - */ - ManagerAPI.prototype.getById = function(id) - { - - // Check if this is a layer node - if (this.isIdLayerNode(id)) - { - return this.managerLayers.getById(id); - } - // Check if this is a overlay node - else if (this.isIdOverlayNode(id)) - { - return this.managerOverlays.getById(id); - } - - return null; - - }; - - /** - * Get layer details - * @function getDetails - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id Layer ID - * @public - * @returns {array} Item details - */ - ManagerAPI.prototype.getDetails = function(id) - { - - // Check if this is a layer node - if (this.isIdLayerNode(id)) - { - var itemLayer = this.managerLayers.getById(id); - if (itemLayer !== null) return itemLayer.getDetails(); - } - // Check if this is a overlay node - else if (this.isIdOverlayNode(id)) - { - var itemOverlay = this.managerOverlays.getById(id); - if (itemOverlay !== null) return itemOverlay.getDetails(); - } - - return []; - - }; - - /** - * Get node for item - * @function getNode - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id Item ID - * @public - * @returns {external:jQuery.fn.w2sidebar.nodes} w2ui sidebar node - */ - ManagerAPI.prototype.getNode = function(id) - { - return this.outline.get(id); - }; - - /** - * Move item down in map list - * @function moveDown - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id Item ID - * @public - * @returns {boolean} True if moved otherwise false - */ - ManagerAPI.prototype.moveDown = function(id) - { - - // If no id provided use selected - if (typeof id === 'undefined') id = this.outline.selected; - - // Check if this is a layer node - if (this.isIdLayerNode(id)) - { - return this.managerLayers.moveDown(id); - } - // Check if this is a overlay node - else if (this.isIdOverlayNode(id)) - { - return this.managerOverlays.moveDown(id); - } - - return false; - - }; - - /** - * Move item up in map list - * @function moveUp - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id Item ID - * @public - * @returns {boolean} True if moved otherwise false - */ - ManagerAPI.prototype.moveUp = function(id) - { - - // If no id provided use selected - if (typeof id === 'undefined') id = this.outline.selected; - - // Check if this is a layer node - if (this.isIdLayerNode(id)) - { - return this.managerLayers.moveUp(id); - } - // Check if this is a overlay node - else if (this.isIdOverlayNode(id)) - { - return this.managerOverlays.moveUp(id); - } - - return false; - - }; - - /** - * Remove listener - * @function off - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} type The event type. - * @param {function} listener The listener function. - * @param {object} opt_this The object to use as this in listener. - * @public - */ - ManagerAPI.prototype.off = function(type, listener, opt_this) - { - this.event.off(type, listener, opt_this); - this.managerLayers.off(type, listener, opt_this); - this.managerOverlays.off(type, listener, opt_this); - }; - - /** - * Add listener - * @function on - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} type The event type. - * @param {function} listener The listener function. - * @param {object} opt_this The object to use as this in listener. - * @public - */ - ManagerAPI.prototype.on = function(type, listener, opt_this) - { - this.event.on(type, listener, opt_this); - this.managerLayers.on(type, listener, opt_this); - this.managerOverlays.on(type, listener, opt_this); - }; - - /** - * Callback when node is selected either by click or double click - * @function onItemSelected - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id Layer ID - * @public - */ - ManagerAPI.prototype.onItemSelected = function(id) - { - this.event.trigger('select:item', id); - }; - - /** - * Callback when map layer group is changed - * @function onLayerGroupChanged - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {external:ol.ObjectEvent} event The change event. - * @private - */ - ManagerAPI.prototype.onLayerGroupChanged = function(event) - { - - this.managerLayers.setLayers(event.target.getLayers()); - - }; - - /** - * Remove item from map - * @function removeFromMap - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {olexp.item.Item} item Item to remove from map - * @public - * @returns {null|external:ol.layer.Layer|external:ol.Overlay} Layer removed - * from map or null if not found - */ - ManagerAPI.prototype.removeFromMap = function(item) - { - - // If no id provided use selected - if (!(item.hasOwnProperty('id'))) return null; - - // Check if this is a layer node - if (this.isIdLayerNode(item.id)) - { - return this.managerLayers.removeFromMap(item); - } - // Check if this is a overlay node - else if (this.isIdOverlayNode(item.id)) - { - return this.managerOverlays.removeFromMap(item); - } - - return null; - - }; - - /** - * Toggle node enable and corresponding layer visibility - * @function toggleNode - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id Item ID of node to toggle - * @public - */ - ManagerAPI.prototype.toggleNode = function(id) - { - - if (typeof id !== 'string') return; - - // ================================================== - // Toggle sidebar node enabled state - // -------------------------------------------------- - var node = this.outline.get(id); - var enable = node.disabled; - if (enable) - { - this.outline.enable(id); - } - else - { - this.outline.disable(id); - } - - // ================================================== - // Toggle map layer visibility - // -------------------------------------------------- - - // Check if this is a layer node - if (this.isIdLayerNode(id)) - { - var itemLayer = this.managerLayers.getById(id); - if (itemLayer !== null) itemLayer.layer.setVisible(enable); - } - // Check if this is a overlay node - else if (this.isIdOverlayNode(id)) - { - var itemOverlay = this.managerOverlays.getById(id); - if (itemOverlay !== null) - { - // Overlays don't have visibility so we hide DOM element - var properties = itemOverlay.layer.getProperties(); - if (properties.hasOwnProperty('element')) - { - var dom = $(properties.element); - if (enable) - { - dom.show(); - } - else - { - dom.hide(); - } - } - } - } - - }; - - /** - * Update item editable properties - * @function updateItem - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id ID of item to edit - * @param {object} properties Item properties to update - * @public - */ - ManagerAPI.prototype.updateItem = function(id, properties) - { - var item = this.getById(id); - if (item !== null) - { - item.setProperties(properties); - - // Update node - var node = this.outline.get(id); - node.text = item.name(); - - this.outline.refresh(); - } - }; - - /** - * Zoom to given item on map - * @function zoomTo - * @memberOf olexp.manager.ManagerAPI.prototype - * @param {string} id ID of item on which to zoom - * @public - */ - ManagerAPI.prototype.zoomTo = function(id) - { - var item = this.getById(id); - item.zoomTo(this.map); - }; - - /** - * Item manager that synchronizes adding and removing items from the map - * sidebar and the corresponding layers on the ol3 map - * @function - * @memberOf olexp.manager - * @param {external:ol.Map} map Managed map - * @param {external:jQuery.fn.w2sidebar} outline Managed outline sidebar - * @param {external:jQuery.fn.w2grid} details Details grid - * @param {string} layers w2ui name of layers node - * @param {string} overlays w2ui name of overlays node - * @public - * @returns {olexp.manager.ManagerAPI} - */ - olexp.manager.Manager = function(map, outline, details, layers, overlays) - { - var manager = new ManagerAPI(map, outline, details, layers, overlays); - return { - getById : manager.getById.bind(manager), - getDetails : manager.getDetails.bind(manager), - getNode : manager.getNode.bind(manager), - isSelected : manager.isSelected.bind(manager), - moveDown : manager.moveDown.bind(manager), - moveUp : manager.moveUp.bind(manager), - off : manager.off.bind(manager), - on : manager.on.bind(manager), - onItemSelected : manager.onItemSelected.bind(manager), - removeFromMap : manager.removeFromMap.bind(manager), - toggleNode : manager.toggleNode.bind(manager), - updateItem : manager.updateItem.bind(manager), - zoomTo : manager.zoomTo.bind(manager) - }; - }; - - return olexp; - -}(olexp || {})); - -//================================================== -// Node Manager -//-------------------------------------------------- -(function(olexp) { - - /** - * Node manager that synchronizes adding and removing items - * @param {string} id Node id - * @param {external:ol.Collection} layers Managed map layers - * @param {external:jQuery.fn.w2sidebar} outline Managed outline sidebar - * @param {external:jQuery.fn.w2grid} details Details grid - * @private - */ - var NodeManager = function(id, layers, outline, details) - { - - /** - * Total count of items added - * @type {number} - */ - this.count = 0; - - /** - * Details grid - * @type {external:jQuery.fn.w2grid} - */ - this.details = details; - - /** - * Event listeners - * @type {olexp.event.Event} - */ - this.event = new olexp.event.Event({'remove:item' : []}); - - /** - * Node id - * @type {string} - */ - this.id = id; - - /** - * List of managed items - * @type {number} - */ - this.items = []; - - /** - * Managed map layers - * @type {ol.Collection} - */ - this.layers = layers; - this.layers.on('change:length', this.onLayerChanged, this); - - /** - * Node managers - * @type {object} - * @example {item.id: NodeManager} - */ - this.managers = {}; - - /** - * Managed outline sidebar - * @type {external:jQuery.fn.w2sidebar} - */ - this.outline = outline; - - }; - - /** - * Add layer to node manager - * @memberOf NodeManager.prototype - * @param {ol.layer.Layer|ol.Overlay} layer ol3 layer/overlay to add - * @private - * @returns {olexp.item.Item} Managed item for added layer - */ - NodeManager.prototype.addLayer = function(layer) - { - - // ================================================== - // Create managed item - // -------------------------------------------------- - - // Create item id, name, and properties - this.count += 1; - var id = this.id + '-' + this.count; - var name = 'Item ' + this.count; - var properties = layer.getProperties(); - if (properties.hasOwnProperty('name')) name = properties.name; - - // Store managed item - var item = new olexp.item.Item(id, name, layer); - this.items.push(item); - - // ================================================== - // Create w2ui node for item - // -------------------------------------------------- - var node = { - id : item.id, - img : item.icon, - text : item.name() - }; - - // ================================================== - // Add item to outline - // -------------------------------------------------- - - // Always prepend new node to top - var nodes = this.outline.get(this.id).nodes; - if (nodes.length === 0) - { - this.outline.add(this.id, [node]); - } - else - { - this.outline.insert(this.id, nodes[0].id, [node]); - } - - // ================================================== - // Check layer is group and create a sub-manager and add its - // layers - // -------------------------------------------------- - if (item.type === olexp.item.Type.GROUP) - { - - var layers = layer.getLayers(); - var manager = new NodeManager(item.id, - layers, - this.outline, - this.details); - - layers.forEach(function(childLayer) - { - manager.addLayer(childLayer); - }, this); - this.managers[item.id] = manager; - this.outline.expand(item.id); - - } - - return item; - - }; - - /** - * Get item based on id - * @memberOf NodeManager.prototype - * @param {string} id Item ID - * @param {boolean} recursive True for recursive search otherwise false - * @private - * @returns {null|olexp.item.Item} Managed item or null if not found - */ - NodeManager.prototype.getById = function(id, recursive) - { - - if (typeof recursive === 'undefined') recursive = true; - - var numItems = this.getSize(); - for (var i = 0; i < numItems; i++) - { - if (this.items[i].id === id) return this.items[i]; - if (this.items[i].type === olexp.item.Type.GROUP && recursive) - { - var item = this.managers[this.items[i].id].getById(id); - if (item === null) continue; - if (item.id === id) return item; - } - } - return null; - - }; - - /** - * Get item based on layer reference - * @memberOf NodeManager.prototype - * @param {ol.layer.Layer|ol.Overlay} layer ol3 layer/overlay - * @param {boolean} recursive True for recursive search otherwise false - * @private - * @returns {null|olexp.item.Item} Managed item or null if not found - */ - NodeManager.prototype.getByLayer = function(layer, recursive) - { - - if (typeof recursive === 'undefined') recursive = true; - - var numItems = this.getSize(); - for (var i = 0; i < numItems; i++) - { - if (this.items[i].layer === layer) return this.items[i]; - if (this.items[i].type === olexp.item.Type.GROUP && recursive) - { - var item = this.managers[this.items[i].id].getByLayer(layer); - if (item === null) continue; - if (item.layer === layer) return item; - } - } - return null; - }; - - /** - * Get size of manager list - * @memberOf NodeManager.prototype - * @private - * @returns {number} Size - */ - NodeManager.prototype.getSize = function() - { - return this.items.length; - }; - - /** - * Check if item is selected - * @memberOf NodeManager.prototype - * @param {string} id Item ID - * @private - * @returns {boolean} True if item is selected otherwise false - */ - NodeManager.prototype.isSelected = function(id) - { - return id === this.outline.selected; - }; - - - /** - * Check if layer should be hidden and not added to manager - * @memberOf NodeManager.prototype - * @param {ol.layer.Layer|ol.Overlay} layer Item ID - * @private - * @returns {boolean} True if item is hidden otherwise false - */ - NodeManager.prototype.isHidden = function(layer) - { - if (layer instanceof olexp.measure.Overlay) return true; - return false; - }; - - /** - * Move item down in map list - * @memberOf NodeManager.prototype - * @param {string} id Item ID - * @private - * @returns {null|boolean} True if moved, false is not moved, null if not - * found. - */ - NodeManager.prototype.moveDown = function(id) - { - - var item = this.getById(id, false); - - if (item !== null) - { - // Item found in this node - var movedItem = this.moveLayerUp(this.layers, item.layer); - if (movedItem) movedItem = this.moveItemDown(id); - return movedItem; - } - - // Check if item in child managers - var numItems = this.getSize(); - for (var i = 0; i < numItems; i++) - { - if (this.items[i].type === olexp.item.Type.GROUP) - { - var movedChild = this.managers[this.items[i].id].moveDown(id); - if (movedChild !== null) return movedChild; - } - } - - return null; - - }; - - /** - * Move item down - * @memberOf NodeManager.prototype - * @param {string} id Item ID - * @private - * @returns {boolean} True if moved otherwise false - */ - NodeManager.prototype.moveItemDown = function(id) - { - // Get node to move - var node = this.outline.get(id); - if (node === null) return false; - - // Get index in list - var nodes = this.outline.find(node.parent.id, - { - parent : node.parent - }); - var index = this.outline.get(node.parent.id, id, true); - if (index >= (nodes.length - 1)) return false; - - // Get node to swap - var nextId = nodes[index + 1].id; - var nextNode = nodes[index + 1]; - - // Check that nodes are in same parent node - if (node.parent !== nextNode.parent) return false; - - // Swap nodes - this.outline.remove(nextId); - this.outline.insert(node.parent, id, nextNode); - this.outline.select(id); - - return true; - }; - - /** - * Move item up - * @memberOf NodeManager.prototype - * @param {string} id Item ID - * @private - * @returns {boolean} True if moved otherwise false - */ - NodeManager.prototype.moveItemUp = function(id) - { - // Get node to move - var node = this.outline.get(id); - if (node === null) return false; - - // Get index in list - var nodes = this.outline.find(node.parent.id, - { - parent : node.parent - }); - var index = this.outline.get(node.parent.id, id, true); - if (index <= 0) return false; - - // Get node to swap - var prevId = nodes[index - 1].id; - var prevNode = nodes[index - 1]; - - // Check that nodes are in same parent node - if (node.parent !== prevNode.parent) return false; - - // Swap nodes - this.outline.remove(id); - this.outline.insert(node.parent, prevId, node); - this.outline.select(id); - - return true; - }; - - /** - * Move layer down - * @memberOf NodeManager.prototype - * @param {ol.Collection} layers Source layer list - * @param {ol.layer.Layer|ol.Overlay} layer Layer to move - * @private - * @returns {boolean} True if moved otherwise false - */ - NodeManager.prototype.moveLayerDown = function(layers, layer) - { - var index = olexp.util.indexOf(layers, layer); - var numLayers = this.layers.getLength(); - if (index < numLayers - 1) - { - var item = this.getByLayer(layer, false); - - // Set item to moving so it's not removed by the manager - item.moving(true); - layers.removeAt(index); - layers.insertAt(index + 1, layer); - item.moving(false); - - return true; - } - return false; - }; - - /** - * Move layer up - * @memberOf NodeManager.prototype - * @param {ol.Collection} layers Source layer list - * @param {ol.layer.Layer|ol.Overlay} layer Layer to move - * @private - * @returns {boolean} True if moved otherwise false - */ - NodeManager.prototype.moveLayerUp = function(layers, layer) - { - var index = olexp.util.indexOf(layers, layer); - if (index > 0) - { - var item = this.getByLayer(layer, false); - - // Set item to moving so it's not removed by the manager - item.moving(true); - layers.removeAt(index); - layers.insertAt(index - 1, layer); - item.moving(false); - - return true; - } - return false; - }; - - /** - * Move item up in map list - * @memberOf NodeManager.prototype - * @param {string} id Item ID - * @private - * @returns {null|boolean} True if moved, false if not moved, null if not - * found - */ - NodeManager.prototype.moveUp = function(id) - { - - var item = this.getById(id, false); - - if (item !== null) - { - // Item found in this node - var movedItem = this.moveLayerDown(this.layers, item.layer); - if (movedItem) movedItem = this.moveItemUp(id); - return movedItem; - } - - // Check if item in child managers - var numItems = this.getSize(); - for (var i = 0; i < numItems; i++) - { - if (this.items[i].type === olexp.item.Type.GROUP) - { - var movedChild = this.managers[this.items[i].id].moveUp(id); - if (movedChild !== null) return movedChild; - } - } - - return null; - - }; - - /** - * Remove listener - * @memberOf NodeManager.prototype - * @param {string} type The event type. - * @param {function} listener The listener function. - * @param {object} opt_this The object to use as this in listener. - * @private - */ - NodeManager.prototype.off = function(type, listener, opt_this) - { - this.event.off(type, listener, opt_this); - - // Remove listener from child managers - var numItems = this.getSize(); - for (var i = 0; i < numItems; i++) - { - if (this.items[i].type === olexp.item.Type.GROUP) - { - this.managers[this.items[i].id].off(type, listener, opt_this); - } - } - - }; - - /** - * Callback when layer changed - * @memberOf NodeManager.prototype - * @param {string} type The event type. - * @param {function} listener The listener function. - * @param {object} opt_this The object to use as this in listener. - * @private - */ - NodeManager.prototype.on = function(type, listener, opt_this) - { - this.event.on(type, listener, opt_this); - - // Register listener with child managers - var numItems = this.getSize(); - for (var i = 0; i < numItems; i++) - { - if (this.items[i].type === olexp.item.Type.GROUP) - { - this.managers[this.items[i].id].on(type, listener, opt_this); - } - } - - }; - - /** - * Callback when layer removed - * @memberOf NodeManager.prototype - * @param {olexp.item.Item} item OpenLayers Explorer Item - * @private - */ - NodeManager.prototype.onItemRemoved = function(item) - { - // Trigger item remove event - this.event.trigger('remove:item', item); - - // Remove item - if (this.isSelected(item.id)) - { - this.details.clear(); - } - this.remove(item); - }; - - /** - * Callback when layer changed - * @memberOf NodeManager.prototype - * @param {ol.ObjectEvent} event ol3 Layer change event - * @private - */ - NodeManager.prototype.onLayerChanged = function(event) - { - - // ================================================== - // Extract layers from change event - // -------------------------------------------------- - var changes = event.target; - - // ================================================== - // If layer is in map but not in manager then add - // -------------------------------------------------- - var numLayers = changes.getLength(); - for (var i = 0; i < numLayers; i++) - { - var layer = changes.item(i); - if (this.isHidden(layer)) continue; - var itemMap = this.getByLayer(layer); - if (itemMap === null) - { - this.addLayer(layer); - } - } - - // ================================================== - // If layer is in manager but not in map then remove - // -------------------------------------------------- - - var items = this.toList(); - var numItems = items.length; - for (var j = 0; j < numItems; j++) - { - var itemManager = items[j]; - - // Check if item is just being moved by user - if (itemManager.moving()) continue; - - var index = olexp.util.indexOf(this.layers, itemManager.layer); - if (index === -1) - { - this.onItemRemoved(itemManager); - } - } - - }; - - /** - * Remove layer from manager - * @memberOf NodeManager.prototype - * @param {olexp.item.Item} item Managed item to remove - * @private - * @returns {boolean} True if removed otherwise false - */ - NodeManager.prototype.remove = function(item) - { - - // ================================================== - // Remove layer from manager - // -------------------------------------------------- - var index = this.items.indexOf(item); - if (index !== -1) - { - this.items.splice(index, 1); - this.outline.remove(item.id); - return true; - } - - // ================================================== - // Check if item in child managers and remove - // -------------------------------------------------- - var numItems = this.getSize(); - for (var i = 0; i < numItems; i++) - { - if (this.items[i].type === olexp.item.Type.GROUP) - { - var removed = this.managers[this.items[i].id].remove(id); - if (removed) return true; - } - } - - return false; - - }; - - /** - * Remove item from map - * @memberOf NodeManager.prototype - * @private - * @param {null|ol.layer.Layer|ol.Overlay} Layer removed from map or null - * if not found - */ - NodeManager.prototype.removeFromMap = function(item) - { - var layerMap = this.layers.remove(item.layer); - if (typeof layerMap !== 'undefined') return layerMap; - - // ================================================== - // Check if item in child managers and remove - // -------------------------------------------------- - var numItems = this.getSize(); - for (var i = 0; i < numItems; i++) - { - if (this.items[i].type === olexp.item.Type.GROUP) - { - var layerChild = this.managers[this.items[i].id].removeFromMap(item); - if (layerChild !== null) return layerChild; - } - } - - return null; - - }; - - /** - * Set layers that are being managed - * @function setLayers - * @memberOf NodeManager.prototype - * @param {external:ol.Collection} layers New layer collection to monitor. - * @private - */ - NodeManager.prototype.setLayers = function(layers) - { - - // Remove old layers - this.layers.un('change:length', this.onLayerChanged, this); - while (this.items.length > 0) - { - this.onItemRemoved(this.items[this.items.length-1]); - } - - // Add new layers - this.layers = layers; - this.layers.on('change:length', this.onLayerChanged, this); - for (var j = 0; j < this.layers.getLength(); j++) - { - this.addLayer(this.layers.item(j)); - } - - }; - - /** - * Get items as list - * @memberOf NodeManager.prototype - * @private - * @returns {array} List of items - */ - NodeManager.prototype.toList = function() - { - - var items = []; - var numItems = this.getSize(); - for (var i = 0; i < numItems; i++) - { - items.push(this.items[i]); - } - return items; - - }; - - /** - * Node manager that synchronizes adding and removing items - * @function - * @memberOf olexp.manager - * @param {string} id Node id - * @param {external:ol.Map} map Managed map - * @param {external:jQuery.fn.w2sidebar} outline Managed outline sidebar - * @param {external:jQuery.fn.w2grid} details Details grid - * @public - */ - olexp.manager.NodeManager = function(id, map, outline, details) - { - var manager = new NodeManager(id, map, outline, details); - return { - getById : manager.getById.bind(manager), - getByLayer : manager.getByLayer.bind(manager), - moveDown : manager.moveDown.bind(manager), - moveUp : manager.moveUp.bind(manager), - off : manager.off.bind(manager), - on : manager.on.bind(manager), - removeFromMap : manager.removeFromMap.bind(manager), - setLayers : manager.setLayers.bind(manager) - }; - }; - - return olexp; - -}(olexp || {})); - - -/** - * @namespace olexp.measure - */ -olexp.measure = olexp.measure || {}; - -//================================================== -// Measuring Tool -//-------------------------------------------------- -(function(olexp) { - - /** - * Enumeration of item measurements types. Object key where measurement is stored. - * @enum {string} - * @memberOf olexp.measure - * @public - * @readonly - */ - olexp.measure.properties = { - /** - * Area measurement property name - * @type string - */ - area: 'olexp-measure-property-area', - /** - * Length measurement property name - * @type string - */ - length: 'olexp-measure-property-length' - }; - - /** - * Measure tool Overlay hidden from map - * @param {object} options ol.Overlay options - * @private - */ - var Overlay = function (options) - { - ol.Overlay.call(this, options); - }; - Overlay.prototype = Object.create(ol.Overlay.prototype); - - /** - * Measuring Tool - * @param {ol.Map} map Map on which to render measurements - * @param {olexp.measure.Type} type Measuring tool type. - * (Default = olexp.measure.Type.LINE) - * @param {Object} settings olexp settings - * @private - */ - var Tool = function(map, type, settings) - { - - //================================================== - // Override Measure Tool option defaults - // with user provided values. - //-------------------------------------------------- - var olexpSettings = $.extend(true, {measure : { - Tool : { - continueLineMsg : 'Click to continue drawing the line', - continuePolygonMsg : 'Click to continue drawing the polygon', - helpTooltipOffset : [20, 0], - helpTooltipPositioning : 'center-left', - measuredStyle : new ol.style.Style({ - fill: new ol.style.Fill({ - color: 'rgba(255, 255, 255, 0.2)' - }), - stroke: new ol.style.Stroke({ - color: '#ffcc33', - width: 2 - }), - image: new ol.style.Circle({ - radius: 7, - fill: new ol.style.Fill({ - color: '#ffcc33' - }) - }) - }), - measuringStyle : new ol.style.Style({ - fill: new ol.style.Fill({ - color: 'rgba(255, 255, 255, 0.2)' - }), - stroke: new ol.style.Stroke({ - color: 'rgba(0, 0, 0, 0.5)', - lineDash: [10, 10], - width: 2 - }), - image: new ol.style.Circle({ - radius: 5, - stroke: new ol.style.Stroke({ - color: 'rgba(0, 0, 0, 0.7)' - }), - fill: new ol.style.Fill({ - color: 'rgba(255, 255, 255, 0.2)' - }) - }) - }), - measureTooltipOffset : [0, -20], - measureTooltipPositioning : 'bottom-center', - messageStart : 'Click to start drawing. Double click to stop.' - }}}, settings); - - /** - * Measurement control settings - * @field - * @private - * @type {Object} - */ - this.settings = olexpSettings.measure.Tool; - - /** - * Message to show when the user is drawing a line. - * @type {string} - */ - this.continueLineMsg = this.settings.continueLineMsg; - - /** - * Message to show when the user is drawing a polygon. - * @type {string} - */ - this.continuePolygonMsg = this.settings.continuePolygonMsg; - - /** - * Keeps track of number of measurements taken - * @type {Number} - */ - this.count = 0; - - /** - * Draw interaction - * @type {ol.interaction.Draw} - */ - this.draw = null; - - /** - * Drawing is active - * @type {boolean} - */ - this.drawing = false; - - /** - * Do geodesic measurement - * @type {boolean} - */ - this.geodesic = false; - - /** - * Overlay to show the help messages. - * @type {ol.Overlay} - */ - this.helpTooltip = null; - - /** - * The help tooltip element. - * @type {Element} - */ - this.helpTooltipElement = null; - - /** - * Map on which to render measurements - * @type {ol.Map} - */ - this.map = map; - - /** - * Overlay to show the measurement. - * @type {ol.Overlay} - */ - this.measureTooltip = null; - - /** - * The measure tooltip element. - * @type {Element} - */ - this.measureTooltipElement = null; - - /** - * Callback when pointer moves - * @type {function} - */ - this.pointerMoveCallback = this.onPointerMove.bind(this); - - /** - * Currently drawn feature. - * @type {external:ol.Feature} - */ - this.sketch = null; - - /** - * Draw vector source. - * @type {ol.source.Vector} - */ - this.source = null; - - /** - * WGS84 ellipsoid on which to perform measurements - * @type {ol.Sphere} - */ - this.sphere = new ol.Sphere(6378137); - - /** - * Measurement tool type - * @type {olexp.measure.Type} - */ - this.type = type; - - /** - * Draw vector. - * @type {ol.layer.Vector} - */ - this.vector = null; - - }; - - /** - * Creates a new help tooltip - * @memberOf Tool.prototype - * @private - */ - Tool.prototype.createHelpTooltip = function () - { - - // ================================================== - // Remove existing help overlay element - // -------------------------------------------------- - if (this.helpTooltipElement) - { - this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement); - } - - // ================================================== - // Create new help tooltip - // -------------------------------------------------- - this.helpTooltipElement = document.createElement('div'); - this.helpTooltipElement.className = 'olexp-measure olexp-measure-hidden'; - this.helpTooltip = new olexp.measure.Overlay({ - element: this.helpTooltipElement, - offset: this.settings.helpTooltipOffset, - positioning: this.settings.helpTooltipPositioning - }); - - // ================================================== - // Add overlay to map - // -------------------------------------------------- - this.map.addOverlay(this.helpTooltip); - - }; - - /** - * Creates a new measure vector - * @memberOf Tool.prototype - * @private - */ - Tool.prototype.createMeasureVector = function () - { - - this.vector = new ol.layer.Vector({ - source: this.source, - style: this.settings.measuredStyle - }); - this.vector.set('name','Measurement #' + (this.count + 1)); - this.map.addLayer(this.vector); - - }; - - /** - * Creates a new measure tooltip - * @memberOf Tool.prototype - * @private - */ - Tool.prototype.createMeasureTooltip = function () - { - - // ================================================== - // Remove existing help overlay element - // -------------------------------------------------- - if (this.measureTooltipElement) - { - this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement); - } - - // ================================================== - // Create new measure tooltip - // -------------------------------------------------- - this.measureTooltipElement = document.createElement('div'); - this.measureTooltipElement.className = 'olexp-measure olexp-measure-active'; - this.measureTooltip = new olexp.measure.Overlay({ - element: this.measureTooltipElement, - offset: this.settings.measureTooltipOffset, - positioning: this.settings.measureTooltipPositioning - }); - this.measureTooltip.set('name','Measurement #' + (this.count+1)); - - // ================================================== - // Add overlay to map - // -------------------------------------------------- - this.map.addOverlay(this.measureTooltip); - - }; - - /** - * Format length output - * @memberOf Tool.prototype - * @param {ol.geom.Polygon} polygon - * @private - * @return {string} - */ - Tool.prototype.formatArea = function (polygon) - { - - var area = 0; - if (this.geodesic) - { - - var projection = this.map.getView().getProjection(); - var geometry = polygon.clone().transform(projection, 'EPSG:4326'); - var coordinates = geometry.getLinearRing(0).getCoordinates(); - area = Math.abs(this.sphere.geodesicArea(coordinates)); - - } - else - { - area = polygon.getArea(); - } - - var output = ''; - if (area > 10000) - { - output = (Math.round(area / 1000000 * 100) / 100) + ' km2'; - } - else - { - output = (Math.round(area * 100) / 100) + ' m2'; - } - - return output; - - }; - - /** - * Format length output - * @memberOf Tool.prototype - * @param {ol.geom.LineString} line - * @private - * @return {string} - */ - Tool.prototype.formatLength = function (line) - { - - var length = 0; - if (this.geodesic) - { - var projection = this.map.getView().getProjection(); - var coordinates = line.getCoordinates(); - var numCoordinates = coordinates.length; - for (var i = 0; i < numCoordinates - 1; ++i) { - var c1 = ol.proj.transform(coordinates[i], projection, 'EPSG:4326'); - var c2 = ol.proj.transform(coordinates[i + 1], projection, 'EPSG:4326'); - length += this.sphere.haversineDistance(c1, c2); - } - } - else - { - length = Math.round(line.getLength() * 100) / 100; - } - - var output; - if (length > 100) - { - output = (Math.round(length / 1000 * 100) / 100) + ' ' + 'km'; - } - else - { - output = (Math.round(length * 100) / 100) + ' ' + 'm'; - } - - return output; - - }; - - /** - * Handle pointer move. - * @memberOf Tool.prototype - * @param {ol.MapBrowserEvent} event - * @private - */ - Tool.prototype.onPointerMove = function (event) - { - - if (event.dragging) - { - return; - } - - var message = this.settings.messageStart; - - if (this.sketch) - { - var geometry = this.sketch.getGeometry(); - if (geometry instanceof ol.geom.Polygon) - { - message = this.continuePolygonMsg; - } - else if (geometry instanceof ol.geom.LineString) - { - message = this.continueLineMsg; - } - } - - this.helpTooltipElement.innerHTML = message; - this.helpTooltip.setPosition(event.coordinate); - - $(this.helpTooltipElement).removeClass('olexp-measure-hidden'); - - }; - - /** - * Enable/disable tool - * @memberOf Tool.prototype - * @param {boolean} enable True if measurement tool is enabled otherwise false - * @private - */ - Tool.prototype.setEnable = function (enable) - { - if (enable) - { - this.map.on('pointermove', this.pointerMoveCallback); - } - else - { - this.map.un('pointermove', this.pointerMoveCallback); - } - this.setInteraction(enable); - }; - - /** - * Add drawing interaction to map - * @memberOf Tool.prototype - * @param {boolean} enable True if drawing should be set otherwise false - * @private - */ - Tool.prototype.setInteraction = function (enable) - { - - if (typeof enable === 'undefined') enable = true; - - var me = this; - - // ================================================== - // Remove interactions and hidden overlays - // -------------------------------------------------- - if (this.draw) - { - this.map.removeInteraction(this.draw); - } - - if (enable) - { - $(this.helpTooltipElement).removeClass('olexp-measure-hidden'); - } - else - { - $(this.helpTooltipElement).addClass('olexp-measure-hidden'); - - // If measure tool is disabled while drawing then clean up vector - if (this.drawing) - { - // Remove drawing vector - this.map.removeLayer(this.vector); - this.vector = null; - - // Remove measure tooltip - this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement); - this.measureTooltipElement = null; - - this.drawing = false; - } - return; - } - - // ================================================== - // Define drawing interaction - // -------------------------------------------------- - this.source = new ol.source.Vector(); - this.draw = new ol.interaction.Draw({ - source: this.source, - type: this.type, - style: this.settings.measuringStyle - }); - - this.map.addInteraction(this.draw); - - // ================================================== - // Define tooltips - // -------------------------------------------------- - this.createMeasureTooltip(); - this.createHelpTooltip(); - - // ================================================== - // Define behavior when drawing starts and ends - // -------------------------------------------------- - var listener = null; - this.draw.on('drawstart', - function(event) - { - this.drawing = true; - - // ================================================== - // Create measurement vector - // -------------------------------------------------- - me.createMeasureVector(); - - // ================================================== - // Update measurement tooltip when on change - // -------------------------------------------------- - var tooltipCoord = event.coordinate; - me.sketch = event.feature; - listener = me.sketch.getGeometry().on('change', - function(event) - { - // ================================================== - // Compute new measurement - // -------------------------------------------------- - var output = ''; - var geometry = event.target; - if (geometry instanceof ol.geom.Polygon) - { - output = me.formatArea(geometry); - tooltipCoord = geometry.getInteriorPoint().getCoordinates(); - } - else if (geometry instanceof ol.geom.LineString) - { - output = me.formatLength(geometry); - tooltipCoord = geometry.getLastCoordinate(); - } - me.measureTooltipElement.innerHTML = output; - me.measureTooltip.setPosition(tooltipCoord); - }); - }, this); - - this.draw.on('drawend', - function(event) - { - this.drawing = false; - me.count += 1; - - // ================================================== - // Store final measurement as layer attribute - // -------------------------------------------------- - var geometry = me.sketch.getGeometry(); - var property = {}; - if (geometry instanceof ol.geom.Polygon) - { - property[olexp.measure.properties.area] = me.formatArea(geometry); - me.vector.setProperties(property); - } - else if (geometry instanceof ol.geom.LineString) - { - property[olexp.measure.properties.length] = me.formatLength(geometry); - me.vector.setProperties(property); - } - - // ================================================== - // Unset sketch - // -------------------------------------------------- - me.sketch = null; - - // ================================================== - // Unset tooltip so that a new one can be created - // -------------------------------------------------- - me.measureTooltipElement.parentNode.removeChild(me.measureTooltipElement); - me.measureTooltipElement = null; - me.createMeasureTooltip(); - - ol.Observable.unByKey(listener); - - me.setInteraction(true); - - }, this); - - }; - - /** - * Set measurement type - * @memberOf Tool.prototype - * @param {olexp.measure.Type} type Measuring tool type - * @private - */ - Tool.prototype.setType = function (type) - { - this.type = type; - }; - - /** - * Measurement tool - * @memberOf olexp.measure - * @param {external:ol.Map} map Source map - * @param {Object} options Measurement options - * @param {olexp.measure.Type} options.type Type of measurement to compute - * @param {olexp.ExplorerSettings} options.settings Explorer settings - * @public - */ - olexp.measure.Tool = function(map, options) { - - if (typeof options === 'undefined') options = {}; - if (typeof options.type === 'undefined') options.type = olexp.measure.Type.LINE; - if (typeof options.settings === "undefined") options.settings = {}; - - var tool = new Tool(map, options.type, options.settings); - - /** - * olexp.measure.Tool API - */ - return { - setEnable: function (enable) { - tool.setEnable(enable); - }, - setType: function (type) { - tool.setType(type); - } - }; - - }; - - /** - * Enumeration of allowable measurement types - * @enum {string} - * @memberOf olexp.measure - * @public - * @readonly - */ - olexp.measure.Type = { - /** - * Area measurement type - * @type string - */ - AREA : 'Polygon', - /** - * Line measurement type - * @type string - */ - LINE : 'LineString' - }; - - /** - * Measurement tool overlay - * @memberOf olexp.measure - * @param {object} options ol.Overlay options - * @public - */ - olexp.measure.Overlay = Overlay; - - return olexp; - -}(olexp || {})); - - -/** - * @namespace olexp.menu - */ -olexp.menu = olexp.menu || {}; - -//================================================== -// Properties menu item -//-------------------------------------------------- -(function(olexp) { - - /** - * Properties menu item - * @param {olexp.manager.Manager} manager Explorer manager - * @param {olexp.ExplorerSettings} settings olexp settings - * @private - */ - var Properties = function(manager, settings) - { - - var olexpSettings = $.extend(true, {menu : { - Properties : { - field : 35, - form : {}, - popup : { - height : 130, - style : 'width: 100%; height: 100%;', - title : 'Edit Layer', - width : 365 - }, - span : 4, - text : 'Properties' - }}}, settings); - - /** - * Menu item icon - * @field - * @private - * @type {string} - */ - this.icon = 'olexp-menu-properties'; - - /** - * Form DOM id - * @field - * @private - * @type {string} - */ - this.form = settings.prefix + '-menu-properties-form'; - - /** - * Menu DOM id - * @field - * @private - * @type {string} - */ - this.id = settings.prefix + '-menu-properties'; - - /** - * Explorer manager - * @field - * @private - * @type {olexp.manager.Manager} - */ - this.manager = manager; - - /** - * Menu w2ui name - * @field - * @private - * @type {string} - */ - this.name = 'layerform'; - - /** - * Properties menu settings - * @field - * @private - * @type {Object} - */ - this.settings = olexpSettings.menu.Properties; - - }; - - /** - * Callback when properties menu item is clicked - * @memberOf Properties.prototype - * @param {external:jQuery.fn.w2sidebar.onMenuClick} event Menu click event - * @private - */ - Properties.prototype.onClick = function(event) - { - - var me = this; - - // ================================================== - // Extract node item id - // -------------------------------------------------- - var id = event.target; - - // ================================================== - // Extract item to be edited - // -------------------------------------------------- - var item = this.manager.getById(id); - var record = item.getProperties(); - - // ================================================== - // Create form fields and adjust form height per field - // -------------------------------------------------- - var formHeight = this.settings.popup.height; - var fieldHeight = this.settings.field; - var fields = []; - - // Add item name field - formHeight += fieldHeight; - fields.push({ - field: 'name', - html: - { - caption : 'Name', - span : this.settings.span - }, - required: true, - type: 'text' - }); - - // Add numeric fields - var propertyTypes = item.getPropertyTypes(); - var numerics = $.map(propertyTypes, function(value) { - return value.title; - }); - for (var i = 0; i < numerics.length; i++) - { - formHeight += fieldHeight; - fields.push({ - field: numerics[i].toLowerCase(), - html: - { - caption : numerics[i], - span : this.settings.span - }, - required: true, - type: 'float' - }); - } - - // ================================================== - // Function to process form changes - // -------------------------------------------------- - var onChanges = function(changes) - { - me.manager.updateItem(id, changes); - }; - - // ================================================== - // Process popup form - // -------------------------------------------------- - - var formOptions = $.extend(this.settings.form, { - fields : fields, - name : this.name, - record : record - }); - - var popupOptions = $.extend($.extend({}, this.settings.popup), { - height : formHeight - }); - - olexp.util.popup(this.form, onChanges, formOptions, popupOptions); - - }; - - /** - * Properties menu item - * @memberOf olexp.menu - * @param {olexp.manager.Manager} manager Explorer manager - * @param {olexp.ExplorerSettings} settings olexp settings - * @public - */ - olexp.menu.Properties = function(manager, settings) { - - var control = new Properties(manager, settings); - - return { - menu: { - id : control.id, - img : control.icon, - text : control.settings.text - }, - click: function(event) { - control.onClick(event); - } - }; - - }; - - return olexp; - -}(olexp || {})); - -//================================================== -// Remove menu item -//-------------------------------------------------- -(function(olexp) { - - /** - * Remove menu item - * @param {olexp.manager.Manager} manager Explorer manager - * @param {olexp.ExplorerSettings} settings olexp settings - * @private - */ - var Remove = function(manager, settings) - { - - var olexpSettings = $.extend(true, {menu : { - Remove : { - text : 'Remove' - }}}, settings); - - /** - * Menu item icon - * @field - * @private - * @type {string} - */ - this.icon = 'olexp-menu-remove'; - - /** - * Menu DOM id - * @field - * @private - * @type {string} - */ - this.id = settings.prefix + '-menu-remove'; - - /** - * Explorer manager - * @field - * @private - * @type {olexp.manager.Manager} - */ - this.manager = manager; - - /** - * Remove menu settings - * @field - * @private - * @param {Object} settings - */ - this.settings = olexpSettings.menu.Remove; - - }; - - /** - * Callback when properties menu item is clicked - * @memberOf Remove.prototype - * @param {external:jQuery.fn.w2sidebar.onMenuClick} event Menu click event - * @private - */ - Remove.prototype.onClick = function(event) - { - - var me = this; - - // ================================================== - // Extract node item id - // -------------------------------------------------- - var id = event.target; - - // ================================================== - // Extract item to be removes - // -------------------------------------------------- - var item = this.manager.getById(id); - - // Confirm user wants to delete item - // Remove item from map and manager - w2confirm('Do you want to delete "' + item.name() + '"?') - .yes(function () { - me.manager.removeFromMap(item); - }); - - }; - - /** - * Remove menu item - * @memberOf olexp.menu - * @param {olexp.manager.Manager} manager Explorer manager - * @param {olexp.ExplorerSettings} settings olexp settings - * @public - */ - olexp.menu.Remove = function(manager, settings) { - - var control = new Remove(manager, settings); - - return { - menu: { - id : control.id, - img : control.icon, - text : control.settings.text - }, - click: function(event) { - control.onClick(event); - } - }; - - }; - - return olexp; - -}(olexp || {})); - -//================================================== -// Zoom menu item -//-------------------------------------------------- -(function(olexp) { - - /** - * Zoom menu item - * @param {olexp.manager.Manager} manager Explorer manager - * @param {olexp.ExplorerSettings} settings olexp settings - * @private - */ - var Zoom = function(manager, settings) - { - - var olexpSettings = $.extend(true, {menu : { - Zoom : { - text : 'Zoom' - }}}, settings); - - /** - * Menu item icon - * @field - * @private - * @type {string} - */ - this.icon = 'olexp-menu-zoom'; - - /** - * Menu DOM id - * @field - * @private - * @type {string} - */ - this.id = settings.prefix + '-menu-zoom'; - - /** - * Explorer - * @field - * @private - * @type {olexp.manager.Manager} - */ - this.manager = manager; - - /** - * Zoom menu settings - * @field - * @private - * @param {Object} settings - */ - this.settings = olexpSettings.menu.Zoom; - - }; - - /** - * Callback when properties menu item is zoomed in - * @memberOf Zoom.prototype - * @param {external:jQuery.fn.w2sidebar.onMenuClick} event Menu click event - * @private - */ - Zoom.prototype.onClick = function(event) - { - - // ================================================== - // Extract node item id - // -------------------------------------------------- - var id = event.target; - - // ================================================== - // Zoom to item layer - // -------------------------------------------------- - this.manager.zoomTo(id); - - }; - - /** - * Zoom menu item - * @memberOf olexp.menu - * @param {olexp.manager.Manager} manager Explorer manager - * @param {olexp.ExplorerSettings} settings olexp settings - * @public - */ - olexp.menu.Zoom = function(manager, settings) { - - var control = new Zoom(manager, settings); - - return { - menu: { - id : control.id, - img : control.icon, - text : control.settings.text - }, - click: function(event) { - control.onClick(event); - } - }; - - }; - - return olexp; - -}(olexp || {})); - - -/** - * @description olexp specific OpenLayers 3 classes - * @namespace olexp.ol - */ -olexp.ol = olexp.ol || {}; - -//================================================== -// Toolbar show Control -//-------------------------------------------------- -(function(olexp) { - - /** - * Control to show toolbar - * @param {olexp.Explorer} explorer Source explorer - * @param {olexp.ExplorerSettings} settings olexp settings - * @private - */ - var ToolbarShow = function(explorer, settings) - { - - //================================================== - // Override Toolbar Show option defaults - // with user provided values. - //-------------------------------------------------- - var olexpSettings = $.extend(true, {ol : { - ToolbarShow : { - html : 'T', - title : 'Show toolbar' - }}}, settings); - - /** - * ol ToolbarShow control settings - * @field - * @private - * @param {Object} settings - */ - this.settings = olexpSettings.ol.ToolbarShow; - - /** - * Source explorer - * @field - * @private - * @type {olexp.Explorer} - */ - this.explorer = explorer; - - // Define control button - var button = document.createElement('button'); - button.innerHTML = this.settings.html; - button.title = this.settings.title; - button.addEventListener('click', this.show.bind(this), false); - button.addEventListener('touchstart', this.show.bind(this), false); - - // Define control button wrapper div - var element = document.createElement('div'); - element.id = settings.prefix + '-ol-toolbar-show'; - element.className = 'olexp-ol-toolbar-show ol-unselectable ol-control'; - element.appendChild(button); - - ol.control.Control.call(this, {element: element}); - - }; - ol.inherits(ToolbarShow, ol.control.Control); - - - /** - * Show toolbar - * @private - */ - ToolbarShow.prototype.show = function() - { - this.explorer.layout.show(this.explorer.options.toolbar.type); - this.setMap(null); - }; - - /** - * Control to set toolbar visibility - * @memberOf olexp.ol - * @param {olexp.Explorer} explorer Source explorer - * @param {object} options Control options - * @param {boolean} options.hidden True if toolbar is initially hidden - * @param {olexp.ExplorerSettings} options.settings Explorer settings - * @public - * @returns {external:jQuery.fn.w2toolbar.properties} ToolbarShow toolbar - * control - */ - olexp.ol.ToolbarShow = function(explorer, options) - { - - var opts = $.extend({hidden: false}, options); - - var control = new ToolbarShow(explorer, opts.settings); - if (opts.hidden) control.setMap(explorer.map); - return control; - - }; - - return olexp; - -}(olexp || {})); - - -/** - * @namespace olexp.selection - */ -olexp.selection = olexp.selection || {}; - -//================================================== -// Selection Tool -//-------------------------------------------------- -(function(olexp) { - - /** - * Handles the selection of features on the map - * @param {ol.Map} map Managed map - * @param {external:jQuery.fn.w2grid} details Details grid - * @private - */ - var Feature = function(map, details) - { - - /** - * Details grid - * @type {external:jQuery.fn.w2grid} - */ - this.details = details; - - /** - * Selection interaction - * @type {external:ol.interaction.Select} - */ - this.interaction = new ol.interaction.Select(); - - /** - * Managed map - * @type {ol.Map} - */ - this.map = map; - - // ================================================== - // Add callback for feature selection - // -------------------------------------------------- - var me = this; - this.interaction.on('select', function(event) { - - if (event.selected.length === 1) - { - var feature = event.selected[0]; - var properties = olexp.util.toProperties(feature); - for (var name in properties) - { - if (typeof properties[name] !== 'boolean' && - typeof properties[name] !== 'number' && - typeof properties[name] !== 'string') - { - delete properties[name]; - } - } - var records = olexp.util.toRecords(properties); - me.details.clear(); - me.details.add(records); - } - - }); - - }; - - /** - * Enable feature selection - * @memberOf Feature.prototype - * @param {boolean} enable True if selection should be enabled otherwise false - */ - Feature.prototype.setEnable = function(enable) - { - if (enable) - { - this.map.addInteraction(this.interaction); - } - else - { - this.map.removeInteraction(this.interaction); - } - }; - - /** - * Selection tool - * @memberOf olexp.selection - * @param {external:ol.Map} map Managed map - * @param {external:jQuery.fn.w2grid} details Details grid - * @public - * @returns {olexp.selection.Feature} Feature selector - */ - olexp.selection.Feature = function(map, details) - { - - var selector = new Feature(map, details); - - /** - * @description The objects exposed by the olexp.selection.Feature API - * @typedef {object} Feature - * @memberOf olexp.selection - * @property {function} setEnable Enable/disable feature selection - */ - return { - setEnable: function (enable) - { - selector.setEnable(enable); - } - }; - - }; - - return olexp; - -}(olexp || {})); - - -/** - * @namespace olexp.util - */ -olexp.util = olexp.util || {}; - -//================================================== -// Utility tools -//-------------------------------------------------- -(function(olexp) { - - /** - * Utility tools - * @param {olexp.ExplorerSettings} settings olexp settings - * @private - */ - Util = function(settings) - { - - //================================================== - // Override Util option defaults - // with user provided values. - //-------------------------------------------------- - var olexpSettings = $.extend(true, {util : {Util : { - Cluster : function(size) - { - style = [new ol.style.Style({ - image : new ol.style.Circle({ - radius : 10, - stroke : new ol.style.Stroke({ - color : '#ffffff' - }), - fill : new ol.style.Fill({ - color : '#3399CC' - }) - }), - text : new ol.style.Text({ - text : size.toString(), - fill : new ol.style.Fill({ - color : '#ffffff' - }) - }) - })]; - return style; - }, - Point : [new ol.style.Style({ - image : new ol.style.Circle({ - fill : new ol.style.Fill({ - color : 'rgba(255,255,0,0.5)' - }), - radius : 5, - stroke : new ol.style.Stroke({color : '#ff0', - width : 1}) - }) - })], - LineString : [new ol.style.Style({ - stroke : new ol.style.Stroke({ - color : '#f00', - width : 3 - }) - })], - Polygon : [new ol.style.Style({ - fill : new ol.style.Fill({ - color : 'rgba(0,255,255,0.5)' - }), - stroke : new ol.style.Stroke({ - color : '#0ff', - width : 1 - }) - })], - MultiPoint : [new ol.style.Style({ - image : new ol.style.Circle({ - fill : new ol.style.Fill({ - color : 'rgba(255,0,255,0.5)' - }), - radius : 5, - stroke : new ol.style.Stroke({ - color : '#f0f', - width : 1 - }) - }) - })], - MultiLineString : [new ol.style.Style({ - stroke : new ol.style.Stroke({ - color : '#0f0', - width : 3 - }) - })], - MultiPolygon : [new ol.style.Style({ - fill : new ol.style.Fill({ - color : 'rgba(0,0,255,0.5)' - }), - stroke : new ol.style.Stroke({ - color : '#00f', - width : 1 - }) - })] - }}}, settings); - - /** - * Util settings - * @field - * @private - * @param {Object} settings - */ - this.settings = olexpSettings.util.Util; - - /** - * Default vector styles - * @field - * @private - * @param {Object} defaultStyle - */ - this.defaultStyle = - { - 'Point' : this.settings.Point, - 'LineString' : this.settings.LineString, - 'Polygon' : this.settings.Polygon, - 'MultiPoint' : this.settings.MultiPoint, - 'MultiLineString' : this.settings.MultiLineString, - 'MultiPolygon' : this.settings.MultiPolygon - }; - - /** - * Cache for cluster styles - * @field - * @private - * @param {Object} clusterStyleCache - */ - this.clusterStyleCache = {}; - - }; - - /** - * Add vector layer to map - * @memberOf Util.prototype - * @param {external:ol.Map} map Source ol3 map - * @param {string} name Name of new vector layer - * @param {array} features Array of features - * @param {boolean} cluster True if features should be clustered otherwise false - * @public - */ - Util.prototype.addLayerVector = function(map, - name, - features, - cluster) - { - - if (typeof cluster === 'undefined') cluster = true; - - var me = this; - - // Detect if clustering is on for non-points and disable clustering - for (var i = 0; i < features.length; i++) - { - var geometry = features[i].getGeometry(); - if (typeof geometry === 'undefined' || - geometry.getType() !== 'Point') - { - cluster = false; - break; - } - } - - // Build layer source - var source = new ol.source.Vector({ - features: features - }); - - if (cluster) - { - source = new ol.source.Cluster({ - source: source - }); - } - - // Build layer style - var style = function(feature, resolution) - { - var styleFunction = feature.getStyleFunction(); - if (styleFunction) - { - return styleFunction.call(feature, resolution); - } - else - { - return me.defaultStyle[feature.getGeometry().getType()]; - } - }; - - if (cluster) - { - style = function(feature, resolution) - { - return me.getClusterStyle(feature); - }; - } - - // Add layer to map - var layer = new ol.layer.Vector({ - source : source, - style : style - }); - layer.set('name', name); - map.getLayers().push(layer); - - }; - - /** - * Get feature style - * @memberOf Util.prototype - * @param {external:ol.Feature} feature Feature to style - * @public - * @returns {ol.Style} Cluster style - */ - Util.prototype.getClusterStyle = function(feature) - { - - var size = feature.get('features').length; - var style = this.clusterStyleCache[size]; - if (!style) - { - style = this.settings.Cluster(size); - this.clusterStyleCache[size] = style; - } - - return style; - - }; - - /** - * Create map controls - * @memberOf Util.prototype - * @public - * @returns {object} Object of ol.control objects by key name - */ - Util.prototype.getControls = function() - { - - var controls = { - fullscreen : new ol.control.FullScreen(), - mouseposition : new ol.control.MousePosition({ - coordinateFormat : ol.coordinate.createStringXY(6), - projection : 'EPSG:4326'}), - overviewmap : new ol.control.OverviewMap(), - rotate : new ol.control.Rotate(), - scaleline : new ol.control.ScaleLine(), - zoom : new ol.control.Zoom(), - zoomslider : new ol.control.ZoomSlider(), - zoomtoextent : new ol.control.ZoomToExtent() - }; - - return controls; - - }; - - /** - * Create drag and drop interaction - * @memberOf Util.prototype - * @param {ol.Map} map Source map - * @public - * @returns {ol.interaction.DragAndDrop} ol3 drag and drop interaction - */ - Util.prototype.getDragAndDrop = function(map) - { - - var me = this; - - var interaction = new ol.interaction.DragAndDrop({ - formatConstructors: $.map(olexp.util.FileTypes, function(o) { - return o.format; - }) - }); - - interaction.on('addfeatures', function(event) { - - // Get filename and remove any extensions - var filename = event.file.name.replace(/\.[^/.]+$/, ""); - - me.addLayerVector(map, filename, event.features); - - }); - - return interaction; - - }; - - /** - * Create a new graticule - * @memberOf Util.prototype - * @param {external:ol.Map} map Source map - * @param {object} options ol.Graticule constructor options - * @public - * @returns {external:ol.Graticule} New graticule based on settings - */ - Util.prototype.getGraticule = function(map, options) - { - - var opts = $.extend($.extend({}, options), - {color : '#' + options.color}); - var graticule = new ol.Graticule({ - map : map, - strokeStyle : new ol.style.Stroke(opts) - }); - graticule.olexp_record = $.extend({enable : (map===null ? false : true)}, - options); - - return graticule; - - }; - - /** - * Create map interactions - * @memberOf Util.prototype - * @param {external:ol.Map} map Source map - * @public - * @returns {object} Object of ol.interaction objects by key name - */ - Util.prototype.getInteractions = function(map) - { - - var interactions = { - draganddrop : this.getDragAndDrop(map) - }; - - return interactions; - - }; - - /** - * Get object of ol3 tile types - * @memberOf Util.prototype - * @public - * @returns {object} Object of ol.source objects - */ - Util.prototype.getTileTypes = function() - { - - // ================================================== - // Define tile types object - // -------------------------------------------------- - var tileTypes = {}; - - // ================================================== - // Define Bing tiles - // -------------------------------------------------- - - var bingKey = 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3'; - var bingMaxZoom = 19; - - tileTypes.bingAerial = - { - 'class' : ol.source.BingMaps, - name : 'Bing Maps (Aerial)', - settings : - { - imagerySet : 'Aerial', - key : bingKey, - maxZoom : bingMaxZoom - } - }; - - tileTypes.bingAerialLabels = - { - 'class' : ol.source.BingMaps, - name : 'Bing Maps (Aerial with Labels)', - settings : - { - imagerySet : 'AerialWithLabels', - key : bingKey, - maxZoom : bingMaxZoom - } - }; - - tileTypes.bingRoad = - { - 'class' : ol.source.BingMaps, - name : 'Bing Maps (Road)', - settings : - { - imagerySet : 'Road', - key : bingKey, - maxZoom : bingMaxZoom - } - }; - - // ================================================== - // Define MapQuest tiles - // -------------------------------------------------- - - tileTypes.mapQuestAerial = - { - 'class' : ol.source.MapQuest, - name : 'Map Quest (Aerial)', - settings : - { - layer : 'sat' - } - }; - - tileTypes.mapQuestAerialLabels = - { - 'class' : ol.source.MapQuest, - name : 'Map Quest (Labels)', - settings : - { - layer : 'hyb' - } - }; - - tileTypes.mapQuestRoad = - { - 'class' : ol.source.MapQuest, - name : 'Map Quest (Road)', - settings : - { - layer : 'osm' - } - }; - - // ================================================== - // Define OpenStreetMap tiles - // -------------------------------------------------- - - tileTypes.osm = - { - 'class' : ol.source.OSM, - name : 'OpenStreetMap', - settings : {} - }; - - // ================================================== - // Define Stamen tiles - // -------------------------------------------------- - - tileTypes.stamenTerrain = - { - 'class' : ol.source.Stamen, - name : 'Stamen (Terrain)', - settings : - { - layer: 'terrain' - } - }; - - tileTypes.stamenToner = - { - 'class' : ol.source.Stamen, - name : 'Stamen (Toner)', - settings : - { - layer: 'toner' - } - }; - - tileTypes.stamenWater = - { - 'class' : ol.source.Stamen, - name : 'Stamen (Water Color)', - settings : - { - layer : 'watercolor' - } - }; - - return tileTypes; - - }; - - /** - * Supported ol3 file types - * @memberOf olexp.util - * @public - * @readonly - * @returns {object} ol3 file types - */ - olexp.util.FileTypes = { - gpx : { - extensions: ['gpx'], - format : ol.format.GPX, - name : 'GPX' - }, - igc : { - extensions: ['igc'], - format : ol.format.IGC, - name : 'IGC' - }, - json : { - extensions: ['json', 'geojson'], - format : ol.format.GeoJSON, - name : 'GeoJSON' - }, - kml : { - extensions: ['kml'], - format : ol.format.KML, - name : 'KML' - } - }; - - /** - * Find feature reader based on filename extension - * @memberOf olexp.util - * @param {string} filename Filename to be read - * @public - * @returns {external:ol.format.Feature} File reader - */ - olexp.util.getReader = function(filename) - { - - var extension = filename.substring(filename.lastIndexOf(".")+1).toLowerCase(); - var types = Object.keys(olexp.util.FileTypes); - for (var i = 0; i < types.length; i++) - { - var type = olexp.util.FileTypes[types[i]]; - var extensions = type.extensions; - for (var j = 0; j < extensions.length; j++) - { - if (extension === extensions[j]) - { - return new type.format(); - } - } - } - return null; - - }; - - /** - * Returns the index of the layer within the collection. - * @function - * @memberOf olexp.util - * @param {external:ol.Collection} layers Map layers - * @param {external:ol.layer.Layer|external:ol.Overlay} layer Layer to find - * @public - * @returns {number} Index of layer - */ - olexp.util.indexOf = function(layers, layer) - { - var length = layers.getLength(); - for (var i = 0; i < length; i++) - { - if (layer === layers.item(i)) - { - return i; - } - } - return -1; - }; - - /** - * Create and process popup form - * @function - * @memberOf olexp.util - * @param {string} id DOM id - * @param {function} onChanges Function that processes w2ui form changes - * @param {external:jQuery.fn.w2form.properties} formOptions w2form - * properties - * @param {external:jQuery.fn.w2popup.properties} popupOptions w2popup - * properties - * @public - */ - olexp.util.popup = function(id, onChanges, formOptions, popupOptions) - { - - var name = formOptions.name; - var record = formOptions.record; - - // ================================================== - // Create form - // -------------------------------------------------- - if (w2ui.hasOwnProperty(name)) - { - w2ui[name].destroy(); - } - $().w2form($.extend(formOptions, { - actions : { - save : function () { - // Check for errors - var errors = this.validate(); - if (errors.length === 0) - { - // Close popup and update with changes - w2popup.close(); - var form = w2ui[name]; - var changes = form.getChanges(); - onChanges(changes); - } - }, - reset : function () { - // Reset properties to original item values - var form = w2ui[name]; - for (var rname in record) - { - form.record[rname] = record[rname]; - } - form.refresh(); - } - } - })); - - // ================================================== - // Display form in popup - // -------------------------------------------------- - w2popup.open($.extend(popupOptions, { - body : ('
'), - onOpen : function (event) { - event.onComplete = function () { - $('#w2ui-popup #' + id).w2render(name); - }; - }, - onToggle : function (event) { - var form = w2ui[name]; - $(form.box).hide(); - event.onComplete = function () { - $(form.box).show(); - form.resize(); - }; - } - })); - - }; - - /** - * Get properties from feature accounting for clustered features - * @memberOf olexp.util - * @param {external:ol.Feature} feature Source feature - * @public - * @returns {object} Feature properties - */ - olexp.util.toProperties = function(feature) - { - var properties = feature.getProperties(); - - // ================================================== - // Check if this is a cluster feature - // -------------------------------------------------- - if (properties.hasOwnProperty('features')) - { - var features = properties.features; - if (features instanceof Array) - { - if (features.length === 1) - { - // ================================================== - // If just one feature get its properties - // -------------------------------------------------- - if (features[0] instanceof ol.Feature) - { - properties = features[0].getProperties(); - } - } - else - { - // ================================================== - // If more than one feature get feature count - // -------------------------------------------------- - var count = 0; - for (var i = 0; i < features.length; i++) - { - if (features[i] instanceof ol.Feature) - { - count += 1; - properties['Cluster Size'] = count; - } - } - } - } - } - - return properties; - - }; - - /** - * Convert properties object to record for w2ui grid - * @memberOf olexp.util - * @param {object} properties Object properties to convert to grid record - * @public - * @returns {array} Properties in record format - */ - olexp.util.toRecords = function(properties) - { - var records = []; - var recid = 0; - - // ================================================== - // Push properties into record - // -------------------------------------------------- - for (var name in properties) - { - var value = properties[name]; - recid += 1; - records.push({recid: recid, property: name, value: value}); - } - - return records; - }; - - /** - * Utility functions - * @memberOf olexp.util - * @param {olexp.ExplorerSettings} settings olexp settings - * @public - */ - olexp.util.Util = function(settings) - { - var util = new Util(settings); - return { - addLayerVector : util.addLayerVector.bind(util), - getControls : util.getControls.bind(util), - getGraticule : util.getGraticule.bind(util), - getInteractions : util.getInteractions.bind(util), - getTileTypes : util.getTileTypes.bind(util) - }; - }; - - return olexp; - -}(olexp || {})); +/* olexp 0.1.2 (c) Daniel Pulido */ + +/* global ol, w2ui */ + +/** + * @namespace olexp + */ +var olexp = olexp || {}; + +//================================================== +// Documentation definitions +//-------------------------------------------------- + +/** + * jQuery + * @external jQuery + * @see {@link https://api.jquery.com} + */ + +/** + * jQuery plugin namespace + * @memberof external:jQuery + * @namespace fn + */ + +/** + * ol3 main namespace + * @external ol + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.html} + */ + +/** + * ol3 Collection + * @class Collection + * @memberof external:ol + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.Collection.html} + */ + +/** + * ol3 format namespace + * @memberof external:ol + * @namespace format + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.format.html} + */ + +/** + * ol3 Feature + * @class Feature + * @memberof external:ol + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.Feature.html} + */ + +/** + * ol3 format feature + * @class Feature + * @memberof external:ol.format + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.format.Feature.html} + */ + +/** + * ol3 graticule + * @class Graticule + * @memberof external:ol + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.Graticule.html} + */ + +/** + * ol3 interaction namespace + * @memberof external:ol + * @namespace interaction + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.interaction.html} + */ + +/** + * ol3 selection interaction + * @class Select + * @memberof external:ol.interaction + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.interaction.Select.html} + */ + +/** + * ol3 layer namespace + * @memberof external:ol + * @namespace layer + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.layer.html} + */ + +/** + * ol3 layer base class + * @class Layer + * @memberof external:ol.layer + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.layer.Layer.html} + */ + +/** + * ol3 map + * @class Map + * @memberof external:ol + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.Map.html} + */ + +/** + * ol3 overlay + * @class Overlay + * @memberof external:ol + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.Overlay.html} + */ + +/** + * ol3 style namespace + * @memberof external:ol + * @namespace style + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.style.html} + */ + +/** + * ol3 Style + * @class Style + * @memberof external:ol.style + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.style.Style.html} + */ + +/** + * ol3 view + * @class View + * @memberof external:ol + * @see {@link http://openlayers.org/en/v3.14.2/apidoc/ol.View.html} + */ + +/** + * w2ui form + * @function w2form + * @memberof external:jQuery.fn + * @see {@link http://w2ui.com/web/docs/form} + */ + +/** + * w2ui form properties + * @memberof external:jQuery.fn.w2form + * @name properties + * @type object + * @see {@link http://w2ui.com/web/docs/form/properties} + */ + +/** + * w2ui grid + * @function w2grid + * @memberof external:jQuery.fn + * @see {@link http://w2ui.com/web/docs/grid} + */ + +/** + * w2ui layout + * @function w2layout + * @memberof external:jQuery.fn + * @see {@link http://w2ui.com/web/docs/layout} + */ + +/** + * w2ui layout panels + * @memberof external:jQuery.fn.w2layout + * @name panels + * @type object + * @see {@link http://w2ui.com/web/docs/w2layout.panels} + */ + +/** + * w2ui popup + * @function w2popup + * @memberof external:jQuery.fn + * @see {@link http://w2ui.com/web/docs/popup} + */ + +/** + * w2ui popup properties + * @memberof external:jQuery.fn.w2popup + * @name properties + * @type object + * @see {@link http://w2ui.com/web/docs/w2popup.defaults} + */ + +/** + * w2ui sidebar + * @function w2sidebar + * @memberof external:jQuery.fn + * @see {@link http://w2ui.com/web/docs/sidebar} + */ + +/** + * w2ui sidebar nodes + * @memberof external:jQuery.fn.w2sidebar + * @name nodes + * @type object + * @see {@link http://w2ui.com/web/docs/w2sidebar.nodes} + */ + +/** + * w2ui toolbar + * @function w2toolbar + * @memberof external:jQuery.fn + * @see {@link http://w2ui.com/web/docs/toolbar} + */ + +/** + * w2ui toolbar properties + * @memberof external:jQuery.fn.w2toolbar + * @name properties + * @type object + * @see {@link http://w2ui.com/web/docs/w2toolbar.items} + */ + +/** + * w2ui common name + * @external w2ui.common.name + * @ignore + * @see {@link http://w2ui.com/web/docs/common.name} + */ + +/** + * @description Advanced settings for customizing various controls and menus + * look and feel. + * @typedef {object} ExplorerSettings + * @memberOf olexp + * + * @property {object} [control] olexp.control settings + * + * @property {object} [control.EditSettings] Edit Settings control settings + * @property {external:jQuery.fn.w2form.properties} [control.EditSettings.form] + * w2form properties + * @property {string} [control.EditSettings.hint='Edit Controls'] Control button + * hover hint text + * @property {external:jQuery.fn.w2popup.properties} [control.EditSettings.popup] + * w2popup properties + * @property {number} [control.EditSettings.span=6] Span size of control fields + * + * @property {object} [control.ExportMap] Export Map control settings + * @property {string} [control.ExportMap.filename='map.png'] Default filename of + * saved map + * @property {string} [control.ExportMap.hint='Export map'] Control button hover + * hint text + * + * @property {object} [control.Graticule] Graticule control settings + * @property {boolean} [control.Graticule.enable=false] Enable grid line display + * @property {external:jQuery.fn.w2form.properties} [control.Graticule.form] + * w2form properties + * @property {string} [control.Graticule.hint='Edit Controls'] Control button + * hover hint text + * @property {object} [control.Graticule.options] ol.style.Stroke options + * @property {external:jQuery.fn.w2popup.properties} [control.Graticule.popup] + * w2popup properties + * @property {number} [control.Graticule.span=6] Span size of control fields + * + * @property {object} [control.LayerControlTile] Layer Control Tile control + * settings + * @property {external:jQuery.fn.w2form.properties} [control.LayerControlTile.form] + * w2form properties + * @property {string} [control.LayerControlTile.hint='Edit Controls'] Control + * button hover hint text + * @property {external:jQuery.fn.w2popup.properties} [control.LayerControlTile.popup] + * w2popup properties + * @property {number} [control.LayerControlTile.span=6] Span size of control + * fields + * + * @property {object} [control.LayerControlVector] Layer Control Vector control + * settings + * @property {external:jQuery.fn.w2form.properties} [control.LayerControlVector.form] + * w2form properties + * @property {string} [control.LayerControlVector.hint='Edit Controls'] Control + * button hover hint text + * @property {external:jQuery.fn.w2popup.properties} [control.LayerControlVector.popup] + * w2popup properties + * @property {number} [control.LayerControlVector.span=6] Span size of control + * fields + * + * @property {object} [control.LayerManager] Layer Manager control settings + * @property {string} [control.LayerManager.hintDetailsHide='Hide details'] Hide + * details control button hover hint text + * @property {string} [control.LayerManager.hintDetailsShow='Show details'] Show + * details control button hover hint text + * @property {string} [control.LayerManager.hintMoveDown='Move item down'] Move + * item down control button hover hint text + * @property {string} [control.LayerManager.hintMoveUp='Move item up'] Move item + * up control button hover hint text + * @property {string} [control.LayerManager.hintOutlineHide='Hide outline'] Hide + * outline control button hover hint text + * @property {string} [control.LayerManager.hintOutlineShow='Show outline'] Show + * outline control button hover hint text + * + * @property {object} [control.LayerMenu] Layer Menu control settings + * @property {string} [control.LayerMenu.arrow=true] Display arrow for drop down + * menu + * @property {string} [control.LayerMenu.hint='Item Properties'] Control button + * hover hint text + * @property {string} [control.LayerMenu.text=''] Button text + * + * @property {object} [control.Measurement] Measurement control settings + * @property {string} [control.Measurement.hintArea='Measure area'] Area + * measurement control button hover hint text + * @property {string} [control.Measurement.hintLength='Measure length'] Length + * measurement control button hover hint text + * + * @property {object} [control.ToolbarHide] Toolbar Hide control settings + * @property {string} [control.ToolbarHide.hint='Hide toolbar'] Hide toolbar + * control button hover hint text + * + * @property {object} [measure] olexp.measure settings + * + * @property {object} [measure.Tool] Properties menu settings + * @property {string} [measure.Tool.continueLineMsg='Click to continue drawing the line'] + * Message displayed to continue drawing line + * @property {string} [measure.Tool.continuePolygonMsg='Click to continue drawing the polygon'] + * Message displayed to continue drawing polygon + * @property {Array} [measure.Tool.helpTooltipOffset=[20, 0]] Pixel offset of + * help tooltip + * @property {string} [measure.Tool.helpTooltipPositioning='center-left'] + * Position of help tooltip + * @property {external:ol.style.Style} [measure.Tool.measuredStyle] Style of a + * measurement vector after completed. + * @property {external:ol.style.Style} [measure.Tool.measuredStyle] Style of a + * measurement vector during drawing. + * @property {Array} [measure.Tool.measureTooltipOffset=[0, -20]] Pixel offset + * of measuring tooltip + * @property {string} [measure.Tool.measureTooltipPositioning='bottom-center'] + * Position of measuring tooltip + * @property {string} [measure.Tool.messageStart='Click to start drawing. Double click to stop.'] + * Message to display to start drawing. + * + * @property {object} [menu] olexp.menu settings + * + * @property {object} [menu.Properties] Properties menu settings + * @property {number} [menu.Properties.field=35] Field size + * @property {external:jQuery.fn.w2form.properties} [menu.Properties.form] + * w2form properties + * @property {external:jQuery.fn.w2popup.properties} [menu.Properties.popup] + * w2popup properties + * @property {number} [menu.Properties.span=4] Span size of control fields + * @property {string} [menu.Properties.text='Properties'] Context menu text + * + * @property {object} [menu.Remove] Remove menu settings + * @property {string} [menu.Remove.text='Remove'] Context menu text + * + * @property {object} [menu.Zoom] Zoom menu settings + * @property {string} [menu.Zoom.text='Zoom'] Context menu text + * + * @property {object} [ol] olexp.ol settings + * + * @property {object} [ol.ToolbarShow] ol3 map control settings + * @property {string} [ol.ToolbarShow.html='T'] HTML to display in control + * @property {string} [ol.ToolbarShow.title='Show toolbar'] Control hover hint + * + * @property {object} [util] olexp.util settings + * + * @property {function} [util.Cluster] Function that returns ol.style.Style for + * a given cluster size. + * @property {external:ol.style.Style} [util.Point] Point style + * @property {external:ol.style.Style} [util.LineString] LineString style + * @property {external:ol.style.Style} [util.Polygon] Polygon style + * @property {external:ol.style.Style} [util.MultiPoint] MultiPoint style + * @property {external:ol.style.Style} [util.MultiLineString] MultiLineString + * style + * @property {external:ol.style.Style} [util.MultiPolygon] MultiPolygon style + */ + +//================================================== +// OpenLayers Explorer +//-------------------------------------------------- +/** + * olexp main module + */ +(function(olexp) { + "use strict"; + + /** + * Main OpenLayers Explorer object that provides a layout manager to an + * Open Layers 3 map. + * @param {string} id DOM id of the element containing the Explorer. + * @param {olexp.ExplorerOptions} [options] Explorer options + * @throws {Error} id must be defined and exist + */ + var Explorer = function(id, options) + { + + // ================================================== + // Parse arguments + // -------------------------------------------------- + + if (typeof id === 'undefined') + { + throw new Error('olexp.Explorer: id not defined'); + } + else if ($('#'+id).length === 0) + { + throw new Error('olexp.Explorer: id not found'); + } + + // ================================================== + // Default options + // -------------------------------------------------- + + // Prefix is used to create DOM ids and w2ui names. This ensures they + // are unique and can have multiple instances on the same page + var prefix = 'olexp-' + id; + + /** + * @description Explorer constructor options to override default + * behavior. + * @typedef {object} ExplorerOptions + * @memberOf olexp + * + * @property {object} [controls] Enables built-in toolbar controls + * @property {boolean} [controls.editsettings=true] Enable settings + * editor control + * @property {boolean} [controls.exportmap=true] Enable map exporting + * control + * @property {boolean} [controls.graticule=true] Enable graticule + * control + * @property {boolean} [controls.layercontrol=true] Enable Layer Control + * control + * @property {boolean} [controls.layermanager=true] Enable Layer Manager + * control + * @property {boolean} [controls.layermenu=true] Enable Layer Menu + * control + * @property {boolean} [controls.measure=true] Enable measurement + * control + * @property {boolean} [controls.toolbarhide=true] Enable toolbar hide + * control + * + * @property {external:jQuery.fn.w2layout.panels} [details] Options for + * details panel. Below are only those different from w2ui + * defaults. + * @property {boolean} [details.hidden=true] Visibility + * @property {boolean} [details.resizable=true] Resizability + * @property {string} [details.size='25%'] Size + * @property {string} [details.type='preview'] Type of panel + * + * @property {external:jQuery.fn.w2sidebar.nodes} [layers] Options for + * layers node. Below are only those different from w2ui defaults. + * @property {boolean} [layers.expanded=true] Indicate if initially + * expanded + * @property {boolean} [layers.group=true] Indicate if a group + * @property {string} [layers.img='icon-folder'] CSS selector of node + * image + * @property {string} [layers.text='Layers'] Node text + * + * @property {external:jQuery.fn.w2layout.panels} [map] Options for map + * panel. Below are only those different from w2ui defaults. + * @property {string} [map.type='main'] Type of panel + * + * @property {external:jQuery.fn.w2layout.panels} [navigation] Options + * for navigation panel. Below are only those different from + * w2ui defaults. + * @property {boolean} [navigation.resizable=true] Resizability + * @property {string} [navigation.size='15%'] Size + * @property {string} [navigation.type='left'] Type of panel + * + * @property {object} [olcontrols] Enables OpenLayers map controls + * @property {boolean} [olcontrols.fullscreen=true] Enable full screen + * @property {boolean} [olcontrols.mouseposition=true] Enable mouse position + * @property {boolean} [olcontrols.overviewmap=true] Enable overview map + * @property {boolean} [olcontrols.rotate=true] Enable rotation + * @property {boolean} [olcontrols.scaleline=true] Enable scale line + * @property {boolean} [olcontrols.zoom=true] Enable zoom + * @property {boolean} [olcontrols.zoomslider=true] Enable zoom slider + * @property {boolean} [olcontrols.zoomtoextent=true] Enable zoom to extent + * + * @property {object} [olinteractions] Enables OpenLayers map interactions + * @property {boolean} [olinteractions.draganddrop=true] Enable drag and drop + * + * @property {external:ol.Map} [olmap] Options for ol3 map. + * Below are only those different from ol3 defaults. + * @property {array} [olmap.controls=[]] Controls initially added to the + * map. + * @property {external:ol.View | undefined} [olmap.view=new ol.View({center: [0,0], zoom: 4})] + * The map's initial view. + * + * @property {external:jQuery.fn.w2layout.panels} [outline] Options for + * outline panel. Below are only those different from w2ui + * defaults. + * @property {string} [outline.type='main'] Type of panel + * + * @property {external:jQuery.fn.w2sidebar.nodes} [overlays] Options for + * overlays node. Below are only those different from w2ui + * defaults. + * @property {boolean} [overlays.expanded=true] Indicate if initially + * expanded + * @property {boolean} [overlays.group=true] Indicate if a group + * @property {string} [overlays.img='icon-folder'] CSS selector of node + * image + * @property {string} [overlays.text='Overlays'] Node text + * + * @property {olexp.ExplorerSettings} [settings] Advanced settings for + * customizing various controls and menus look and feel. + * + * @property {external:jQuery.fn.w2layout.panels} [toolbar] Options for + * toolbar panel. Below are only those different from w2ui + * defaults. + * @property {string} [toolbar.size='40'] Size + * @property {string} [toolbar.style='padding: 5px;'] Additional CSS + * style + * @property {string} [toolbar.type='top'] Type of panel + */ + this.options = { + controls : { + editsettings : true, + exportmap : true, + graticule : true, + layercontrol : true, + layermanager : true, + layermenu : true, + measure : true, + toolbarhide : true + }, + details : { + hidden : true, + resizable : true, + size : '25%', + type : 'preview' + }, + layers : { + expanded : true, + group : true, + img : 'icon-folder', + text : 'Layers' + }, + map : { + type : 'main' + }, + navigation : { + resizable : true, + size : '15%', + type : 'left' + }, + olcontrols : { + fullscreen : true, + mouseposition : true, + overviewmap : true, + rotate : true, + scaleline : true, + zoom : true, + zoomslider : true, + zoomtoextent : true + }, + olinteractions : { + draganddrop : true + }, + olmap : { + controls : [], + view : new ol.View({center: [0,0], zoom: 3}) + }, + outline : { + type : 'main' + }, + overlays : { + expanded : true, + group : true, + img : 'icon-folder', + text : 'Overlays' + }, + settings: {}, + toolbar : { + size : '40', + style : 'padding: 5px;', + type : 'top' + }, + }; + + // Override default options with user options + $.extend(true, this.options, options); + + /** + * @description Explorer options the user can not override (DOM ids and + * w2ui names) + * @memberOf olexp + * + * @property {object} [explorer] Explorer properties + * @property {string} [explorer.cls='olexp-explorer-content'] Explorer + * div class + * @property {string} [explorer.id='olexp-' + id + + * '-explorer-id-content'] Explorer div id + * @property {external:w2ui.common.name} [explorer.details='olexp-' + id + * + '-explorer-name-details'] w2ui name of details panel + * @property {external:w2ui.common.name} [explorer.layout='olexp-' + id + * + '-explorer-name-layout'] w2ui name of main layout + * @property {external:w2ui.common.name} [explorer.navigation='olexp-' + * + id + '-explorer-name-navigation'] w2ui name of navigation + * panel + * @property {external:w2ui.common.name} [explorer.outline='olexp-' + id + * + '-explorer-name-outline'] w2ui name of outline panel + * @property {external:w2ui.common.name} [explorer.toolbar='olexp-' + id + * + '-explorer-name-toolbar'] w2ui name of toolbar + * + * @property {external:jQuery.fn.w2sidebar.nodes} [layers] Options for + * layers node + * @property {string} [layers.id='olexp-' + id + '-explorer-id-layers'] + * Unique ID of node + * + * @property {external:jQuery.fn.w2layout.panels} [map] Options for map + * panel + * @property {string} [map.content='
'] + * Panel content. Should be div containing ol.Map and + * referenced by olmap.target. + * + * @property {external:ol.Map} [olmap] Options for ol3 map + * @property {Element|string|undefined} [olmap.target=options.map.id] + * The container for the map, either the element itself or the + * id of the element. + * + * @property {external:jQuery.fn.w2sidebar.nodes} [overlays] Options for + * overlays node + * @property {string} [overlays.id='olexp-' + id + + * '-explorer-id-overlays'] Unique ID of node + */ + $.extend(true, this.options, { + explorer : { + cls : 'olexp-explorer-content', + id : prefix + '-explorer-id-content', + details : prefix + '-explorer-name-details', + layout : prefix + '-explorer-name-layout', + navigation : prefix + '-explorer-name-navigation', + outline : prefix + '-explorer-name-outline', + toolbar : prefix + '-explorer-name-toolbar' + }, + layers : { + id : prefix + '-explorer-id-layers', + }, + map : { + content : ('
'), + }, + olmap : { + target : prefix + '-explorer-id-map', + }, + overlays : { + id : prefix + '-explorer-id-overlays', + }, + settings : { + prefix : prefix + } + }); + + // ================================================== + // Store current object + // -------------------------------------------------- + var me = this; + + // ================================================== + // Create main layout content div + // -------------------------------------------------- + + var div = $('
', {'id': this.options.explorer.id, + 'class': this.options.explorer.cls}); + $('#'+id).append(div); + + // ================================================== + // Main Layout + // -------------------------------------------------- + + this.layout = $('#'+this.options.explorer.id).w2layout({ + name : this.options.explorer.layout, + panels : [ + this.options.navigation, + this.options.map, + this.options.toolbar + ] + }); + + // ================================================== + // Main Toolbar + // -------------------------------------------------- + + this.toolbar = $('').w2toolbar({ + name: this.options.explorer.toolbar + }); + + // ================================================== + // Navigation pane Layout + // -------------------------------------------------- + + this.navigation = $('').w2layout({ + name : this.options.explorer.navigation, + onResize : function() { + if (me.hasOwnProperty('map')) + { + me.map.updateSize(); + } + if (me.hasOwnProperty('details')) + { + me.details.resize(); + } + }, + panels : [ + this.options.outline, + this.options.details + ] + }); + + // ================================================== + // Outline sidebar + // -------------------------------------------------- + + this.outline = $('').w2sidebar({ + name : this.options.explorer.outline, + nodes : [ + this.options.layers, + this.options.overlays + ], + onClick : function (event) { + var id = event.target; + var records = me.manager.getDetails(id); + me.details.clear(); + me.details.add(records); + me.manager.onItemSelected(id); + }, + onDblClick : function (event) { + var id = event.target; + me.manager.toggleNode(id); + me.manager.onItemSelected(id); + }, + onRender : function(event) { + event.onComplete = function() + { + var id = me.outline.selected; + me.manager.onItemSelected(id); + }; + } + }); + + // ================================================== + // Details table + // -------------------------------------------------- + + this.details = $('').w2grid({ + columns : [ + { + field : 'property', + caption : 'Property', + size : '100%', + sortable : true + }, + { + field : 'value', + caption : 'Value', + size : '100%', + sortable : true + } + ], + name : this.options.explorer.details, + }); + + // ================================================== + // Add Content + // -------------------------------------------------- + + this.navigation.content(this.options.outline.type, this.outline); + this.navigation.content(this.options.details.type, this.details); + this.layout.content(this.options.navigation.type, this.navigation); + + // ================================================== + // Define map + // -------------------------------------------------- + + this.map = new ol.Map(this.options.olmap); + + // ================================================== + // Layer manager + // -------------------------------------------------- + + this.manager = new olexp.manager.Manager(this.map, + this.outline, + this.details, + this.options.layers.id, + this.options.overlays.id); + + // ================================================== + // Create menu items and callbacks in outline + // -------------------------------------------------- + + var zoom = olexp.menu.Zoom(this.manager, this.options.settings); + var properties = olexp.menu.Properties(this.manager, this.options.settings); + var remove = olexp.menu.Remove(this.manager, this.options.settings); + + this.menu = {items: [], callbacks: {}}; + + this.menu.items.push(zoom.menu); + this.menu.items.push(properties.menu); + this.menu.items.push(remove.menu); + + this.menu.callbacks[zoom.menu.id] = zoom.click; + this.menu.callbacks[properties.menu.id] = properties.click; + this.menu.callbacks[remove.menu.id] = remove.click; + + // Add menu items and callbacks to outline + this.outline.menu = this.menu.items; + this.outline.onMenuClick = function (event) + { + var id = event.menuItem.id; + if (id in me.menu.callbacks) + { + me.menu.callbacks[id](event); + } + }; + + // ================================================== + // Define map interactions + // -------------------------------------------------- + + this.util = new olexp.util.Util(this.options.settings); + + // Add map interactions + var interactions = this.util.getInteractions(this.map); + for (var iname in this.options.olinteractions) + { + var interaction = interactions[iname]; + if (this.options.olinteractions[iname]) this.map.addInteraction(interaction); + } + + // Add map controls + var controls = this.util.getControls(); + for (var cname in this.options.olcontrols) + { + var control = controls[cname]; + this.map.addControl(control); + control.setMap((this.options.olcontrols[cname] ? this.map : null)); + } + + // ================================================== + // Feature selector + // -------------------------------------------------- + + this.selector = new olexp.selection.Feature(this.map, this.details); + this.selector.setEnable(true); + + // ================================================== + // All layout and map components are defined so we + // can define the main Explorer API. + // -------------------------------------------------- + + /** + * @description The objects exposed by the Explorer API + * @typedef {object} ExplorerAPI + * @memberOf olexp + * @property {external:jQuery.fn.w2grid} details Layer details panels. + * Display the details of the later that is currently selected + * in the outline sidebar. + * @property {external:jQuery.fn.w2layout} layout Explorer layout + * object. Contains the map, toolbar, and navigation panels. + * Can maintain up to 3 additional panels that are stretchable + * and resizable. + * @property {olexp.manager.ManagerAPI} manager Explorer item manager + * @property {external:ol.Map} map ol3 map object used to add layers, + * overlays, controls, etc. + * @property {external:jQuery.fn.w2layout} navigation Layer manager + * navigation panel. The panel that contains the outline + * sidebar and detail grid. + * @property {olexp.ExplorerOptions} options Explorer options object + * that contains the options argument passed to the explorer + * constructor. + * @property {external:jQuery.fn.w2sidebar} outline Layer manager + * outline panel that allows the user to manage the ordering + * and properties of the map layers. + * @property {external:jQuery.fn.w2toolbar} toolbar Explorer toolbar + * that contains map and layers controls. + */ + this.api = { + details : this.details, + layout : this.layout, + manager : this.manager, + map : this.map, + navigation : this.navigation, + options : this.options, + outline : this.outline, + toolbar : this.toolbar + }; + + // ================================================== + // Add built-in controls to toolbar + // -------------------------------------------------- + + if (this.options.controls.toolbarhide) + { + this.toolbar.add(olexp.control.ToolbarHide(this.api, + {hidden : this.options.toolbar.hidden, + settings : this.options.settings})); + this.toolbar.add({id: 'break-toolbar-hide', type: 'break'}); + } + + if (this.options.controls.layermanager) + { + this.toolbar.add(olexp.control.LayerManager(this.api, + this.manager, + {details: {checked: !this.options.details.hidden}, + navigation: {checked: !this.options.navigation.hidden}, + settings : this.options.settings})); + this.toolbar.add({id: 'break-layer-manager', type: 'break'}); + } + + if (this.options.controls.layermenu) + { + this.toolbar.add(olexp.control.LayerMenu(this.api, + this.manager, + this.menu, + {settings : this.options.settings})); + this.toolbar.add({id: 'break-item-menu', type: 'break'}); + } + + if (this.options.controls.layercontrol) + { + this.toolbar.add(olexp.control.LayerControl(this.api, + {settings : this.options.settings})); + this.toolbar.add({id: 'break-layer-control', type: 'break'}); + } + + if (this.options.controls.graticule) + { + this.toolbar.add(olexp.control.Graticule(this.api, + {settings : this.options.settings})); + this.toolbar.add({id: 'break-graticule', type: 'break'}); + } + + if (this.options.controls.measure) + { + this.toolbar.add(olexp.control.Measure(this.api, + {settings : this.options.settings})); + this.toolbar.add({id: 'break-measure', type: 'break'}); + } + + if (this.options.controls.exportmap) + { + this.toolbar.add(olexp.control.ExportMap(this.api, + {settings : this.options.settings})); + this.toolbar.add({id: 'break-export-map', type: 'break'}); + } + + if (this.options.controls.editsettings) + { + this.toolbar.add(olexp.control.EditSettings(this.api, + {settings : this.options.settings})); + this.toolbar.add({id: 'break-edit-settings', type: 'break'}); + } + + this.layout.set(this.options.toolbar.type, {content: '', + show : {toolbar : true}, + toolbar: this.toolbar}); + + }; + + /** + * Destroy all w2ui and openlayer resources. The explorer is no longer + * valid after calling this method. + * @memberOf olexp + * @param {olexp.ExplorerAPI} explorer Explorer API object + * @public + */ + olexp.destroy = function(explorer) + { + + if (explorer.map !== undefined) explorer.map.setTarget(null); + if (explorer.details !== undefined) explorer.details.destroy(); + if (explorer.outline !== undefined) explorer.outline.destroy(); + if (explorer.navigation !== undefined) explorer.navigation.destroy(); + if (explorer.toolbar !== undefined) explorer.toolbar.destroy(); + if (explorer.layout !== undefined) explorer.layout.destroy(); + + }; + + // ================================================== + // Explorer API + // -------------------------------------------------- + + /** + * Constructor to create an Explorer. + * @class Explorer + * @memberOf olexp + * @param {string} id DOM id of the element div containing the Explorer. + * @param {olexp.ExplorerOptions} [options] Explorer options + * @public + * @returns {olexp.ExplorerAPI} Explorer API + * @throws {Error} DOM id must be defined and exist + */ + olexp.Explorer = function(id, options) { + var explorer = new Explorer(id, options); + return explorer.api; + }; + +}(olexp || {})); + + +/** + * @namespace olexp.event + */ +olexp.event = olexp.event || {}; + +//================================================== +// Event Handler +//-------------------------------------------------- +(function(olexp) { + + "use strict"; + + /** + * Handles listening for registered events + * @param {object} listeners Initial listeners + * @private + */ + var Event = function(listeners) + { + + // ================================================== + // Collection of event listeners that are keyed by + // the event name and valued by an array of callback + // functions (e.g., {'name': [function1, function2]}) + // -------------------------------------------------- + this.listeners = $.extend({}, listeners); + + }; + + /** + * Add listener to event type + * @memberOf Event.prototype + * @param {string} type The event type. + * @param {function} listener The listener function. + * @param {object} opt_this The object to use as this in listener. + * @private + * @warning If event type is not already registered then listener is not. + */ + Event.prototype.on = function(type, listener, opt_this) + { + + if (!(type in this.listeners)) return; + + var callback = listener; + if (typeof opt_this !== 'undefined') callback = listener.bind(opt_this); + this.listeners[type].push(callback); + + }; + + /** + * Register event to which to listen + * @memberOf Event.prototype + * @param {string} type The event type. + * @private + * @warning If event type is already registered then nothing is done. + */ + Event.prototype.register = function(type) + { + + if (type in this.listeners) return; + this.listeners[type] = []; + + }; + + /** + * Trigger event and call listeners + * @memberOf Event.prototype + * @param {string} type The event type. + * @private + */ + Event.prototype.trigger = function() + { + var args = Array.prototype.slice.call(arguments); + var type = args.shift(); + if (!(type in this.listeners)) return; + + // Call listeners with remaining arguments + for (var i = 0; i < this.listeners[type].length; i++) + { + this.listeners[type][i].apply(this, args); + } + }; + + /** + * Unregister event to which to listen + * @memberOf Event.prototype + * @param {string} type The event type. + * @private + * @returns Listeners registered with given type + * @warning If event type is already registered then nothing is done. + */ + Event.prototype.unregister = function(type) + { + + if (!(type in this.listeners)) return; + var listeners = this.listeners[type]; + delete this.listeners[type]; + return listeners; + + }; + + /** + * Remove listener from event type + * @memberOf Event.prototype + * @param {string} type The event type. + * @param {function} listener The listener function. + * @param {object} opt_this The object to use as this in listener. + * @private + */ + Event.prototype.off = function(type, listener, opt_this) + { + + if (!(type in this.listeners)) return; + + var callback = listener; + if (typeof opt_this !== 'undefined') callback = listener.bind(opt_this); + var index = this.listeners[type].indexOf(callback); + if (index > -1) this.listeners[type].splice(index, 1); + + }; + + /** + * Event handler + * @memberOf olexp.event + * @param {object} listeners Initial listeners + * @public + */ + olexp.event.Event = function(listeners) { + + var handler = new Event(listeners); + return handler; + + }; + + return olexp; + +}(olexp || {})); + + +/** + * @namespace olexp.control + */ +olexp.control = olexp.control || {}; + +//================================================== +// Edit Settings Control +//-------------------------------------------------- +(function(olexp) { + + "use strict"; + + /** + * Control to edit settings + * @param {ol.Map} map Source map + * @param {olexp.ExplorerSettings} settings olexp settings + * @private + */ + var EditSettings = function(map, settings) + { + + //================================================== + // Override Edit Settings Control default settings + // with user provided values. + //-------------------------------------------------- + var olexpSettings = $.extend(true, {control : { + EditSettings : { + form : { + header : '', + style : 'border: 0px; background-color: transparent;' + }, + hint : 'Edit Controls', + popup : { + height : 380, + style : 'width: 100%; height: 100%;', + title : 'Edit Controls', + width : 225 + }, + span : 6 + }}}, settings); + + /** + * Edit Settings control settings + * @field + * @private + * @type {Object} + */ + this.settings = olexpSettings.control.EditSettings; + + /** + * Button element id + * @field + * @private + * @type {string} + */ + this.button = settings.prefix + '-control-edit-settings-button'; + + /** + * Control icon + * @field + * @private + * @type {string} + */ + this.icon = 'olexp-control-edit-settings'; + + /** + * Control element id + * @field + * @private + * @type {string} + */ + this.id = settings.prefix + '-control-edit-settings-form'; + + /** + * Map on which to edit controls + * @field + * @private + * @type {ol.Map} + */ + this.map = map; + + /** + * Control w2ui name + * @field + * @private + * @type {string} + */ + this.name = settings.prefix + '-control-edit-settings-form'; + + }; + + /** + * Display settings editor + * @private + */ + EditSettings.prototype.display = function() + { + var me = this; + + // ================================================== + // Form fields + // -------------------------------------------------- + var fields = [ + { + html : { + caption : 'Full Screen', + span : this.settings.span + }, + name : 'fullscreen', + type : 'checkbox' + }, + { + html : { + caption : 'Mouse Position', + span : this.settings.span + }, + name : 'mouseposition', + type : 'checkbox' + }, + { + html : { + caption : 'Overview Map', + span : this.settings.span + }, + name : 'overviewmap', + type : 'checkbox' + }, + { + html : { + caption : 'Rotate', + span : this.settings.span + }, + name : 'rotate', + type: 'checkbox' + }, + { + html : { + caption : 'Scale Line', + span : this.settings.span + }, + name : 'scaleline', + type : 'checkbox' + }, + { + html : { + caption : 'Zoom', + span : this.settings.span + }, + name : 'zoom', + type : 'checkbox' + }, + { + html : { + caption : 'Zoom Slider', + span : this.settings.span + }, + name : 'zoomslider', + type : 'checkbox' + }, + { + html : { + caption : 'Zoom To Extent', + span : this.settings.span + }, + name : 'zoomtoextent', + type : 'checkbox' + } + ]; + + // ================================================== + // Extract controls to be edited + // -------------------------------------------------- + var record = { + fullscreen : this.isControlActive('fullscreen'), + mouseposition : this.isControlActive('mouseposition'), + overviewmap : this.isControlActive('overviewmap'), + rotate : this.isControlActive('rotate'), + scaleline : this.isControlActive('scaleline'), + zoom : this.isControlActive('zoom'), + zoomslider : this.isControlActive('zoomslider'), + zoomtoextent : this.isControlActive('zoomtoextent') + }; + + // ================================================== + // Function to process form changes + // -------------------------------------------------- + var onChanges = function(changes) + { + for (var name in changes) + { + var enable = changes[name]; + me.setControl(name, enable); + } + }; + + // ================================================== + // Process popup form + // -------------------------------------------------- + + var formOptions = $.extend(this.settings.form, { + fields : fields, + name : this.name, + record : record + }); + + var popupOptions = this.settings.popup; + + olexp.util.popup(this.id, onChanges, formOptions, popupOptions); + + }; + + /** + * Get control with given name + * @param {string} name Name of control to check if active + * @private + * @returns {ol.control.Control} Current control with given name or null if none + */ + EditSettings.prototype.getControl = function(name) + { + var controls = this.map.getControls().getArray(); + for (var i = 0; i < controls.length; i++) + { + var control = controls[i]; + if (name === 'fullscreen' && control instanceof ol.control.FullScreen) return control; + if (name === 'mouseposition' && control instanceof ol.control.MousePosition) return control; + if (name === 'overviewmap' && control instanceof ol.control.OverviewMap) return control; + if (name === 'rotate' && control instanceof ol.control.Rotate) return control; + if (name === 'scaleline' && control instanceof ol.control.ScaleLine) return control; + if (name === 'zoom' && control instanceof ol.control.Zoom) return control; + if (name === 'zoomslider' && control instanceof ol.control.ZoomSlider) return control; + if (name === 'zoomtoextent' && control instanceof ol.control.ZoomToExtent) return control; + } + return null; + }; + + /** + * Check if control is active + * @param {string} name Name of control to check if active + * @private + * @returns {boolean} True if control is active otherwise false + */ + EditSettings.prototype.isControlActive = function(name) + { + var control = this.getControl(name); + if (control !== null && control.getMap() !== null) return true; + return false; + }; + + /** + * Set control with given name + * @param {string} name Name of control to check if active + * @param {boolean} enable True if control is to be enabled otherwise false + * @private + */ + EditSettings.prototype.setControl = function(name, enable) + { + var control = this.getControl(name); + if (control === null) return; + var map = (enable ? this.map : null); + control.setMap(map); + }; + + /** + * Control to edit settings to enable/disable ol3 controls displayed on map. + * @memberOf olexp.control + * @param {olexp.Explorer} explorer Source explorer + * @param {object} options Control options + * @param {olexp.ExplorerSettings} options.settings Explorer settings + * @public + * @returns {external:jQuery.fn.w2toolbar.properties} EditSettings toolbar + * control + */ + olexp.control.EditSettings = function(explorer, options) { + + var control = new EditSettings(explorer.map, options.settings); + + return { + hint : control.settings.hint, + id : control.button, + img : control.icon, + onClick : function (event) { + control.display(); + }, + type : 'button' + }; + + }; + + return olexp; + +}(olexp || {})); + +// ================================================== +// Export Map Control +// -------------------------------------------------- +(function(olexp) { + + /** + * Control to export map to image + * @param {ol.Map} map Map on which to render measurements + * @param {olexp.ExplorerSettings} settings olexp settings + * @private + */ + var ExportMap = function(map, settings) + { + + //================================================== + // Override Export Map Control option defaults + // with user provided values. + //-------------------------------------------------- + var olexpSettings = $.extend(true, {control : { + ExportMap : { + filename : 'map.png', + hint : 'Export map' + }}}, settings); + + /** + * Export Map control settings + * @field + * @private + * @type {Object} + */ + this.settings = olexpSettings.control.ExportMap; + + /** + * Anchor element id + * @field + * @private + * @type {string} + */ + this.anchor = settings.prefix + '-control-export-map-anchor'; + + /** + * Button element id + * @field + * @private + * @type {string} + */ + this.button = settings.prefix + '-control-export-map-button'; + + /** + * Filename of map to download + * @field + * @private + * @type {string} + */ + this.filename = this.settings.filename; + + /** + * Icon selectors + * @field + * @private + * @type {string} + */ + this.icon = 'olexp-control-export-map'; + + /** + * Map on which to render measurements + * @field + * @private + * @type {ol.Map} + */ + this.map = map; + + }; + + /** + * Export current map to image. Activates anchor link download. + * @private + */ + ExportMap.prototype.toImage = function() + { + // ================================================== + // Create a temporary anchor, click it, then remove it + // -------------------------------------------------- + var id = this.anchor; + var filename = this.filename; + + // Create callback when anchor is clicked + var callback = function(e) + { + this.map.once('postcompose', function(event) + { + anchor.href = event.context.canvas.toDataURL('image/png'); + }); + this.map.renderSync(); + }; + + // Create anchor + $('body').append(''); + var anchor = document.getElementById(id); + anchor.addEventListener('click', callback.bind(this), false); + + // Click then remove + $('#' + id)[0].click(); + $('#' + id).remove(); + }; + + /** + * Export map to image + * @memberOf olexp.control + * @param {olexp.Explorer} explorer Source explorer + * @param {object} options Control options + * @param {olexp.ExplorerSettings} options.settings Explorer settings + * @public + * @returns {external:jQuery.fn.w2toolbar.properties} ExportMap toolbar + * control + */ + olexp.control.ExportMap = function(explorer, options) { + + var control = new ExportMap(explorer.map, options.settings); + + return { + hint : control.settings.hint, + id : control.button, + img : control.icon, + onClick : function (event) { + control.toImage(); + }, + type : 'button' + }; + + }; + + return olexp; + +}(olexp || {})); + +//================================================== +// Graticule Controls +//-------------------------------------------------- +(function(olexp) { + + /** + * Control to display graticule + * @param {ol.Map} map Source map + * @param {olexp.ExplorerSettings} settings olexp settings + * @private + */ + var Graticule = function(map, settings) + { + + //================================================== + // Override Graticule Control option defaults + // with user provided values. + //-------------------------------------------------- + var olexpSettings = $.extend(true, {control : { + Graticule : { + enable : false, + form : { + header : '', + style : 'border: 0px; background-color: transparent;' + }, + hint : 'Edit Grid Lines', + options : { + color : '000000', + lineDash : [0.5, 4], + width : 2 + }, + popup : { + height : 225, + style : 'border: 0px; background-color: transparent;', + title : 'Edit Grid Lines', + width : 300 + }, + span : 3 + }}}, settings); + + /** + * Tile control settings + * @field + * @private + * @type {Object} + */ + this.settings = olexpSettings.control.Graticule; + + /** + * Button element id + * @field + * @private + * @type {string} + */ + this.button = settings.prefix + '-control-graticule-button'; + + /** + * Control icon + * @field + * @private + * @type {string} + */ + this.icon = 'olexp-control-graticule'; + + /** + * Form element id + * @field + * @private + * @type {string} + */ + this.id = settings.prefix + '-control-graticule'; + + /** + * Parent explorer + * @field + * @private + * @type {ol.Map} + */ + this.map = map; + + /** + * Form w2ui name + * @field + * @private + * @type {string} + */ + this.name = settings.prefix + '-control-graticule-form'; + + /** + * Utility tool + * @field + * @private + * @type {olexp.util.Util} + */ + this.util = new olexp.util.Util(olexpSettings); + + /** + * Graticule tool + * @field + * @private + * @type {ol.Graticule} + */ + this.graticule = this.util.getGraticule((this.settings.enable ? this.map : null), + $.extend({}, this.settings.options)); + + }; + + /** + * Display graticule form + * @private + */ + Graticule.prototype.display = function() + { + + var me = this; + + // ================================================== + // Form fields + // -------------------------------------------------- + var fields = [ + { + html : { + caption : 'Enable', + span : this.settings.span + }, + name : 'enable', + required : true, + type : 'checkbox' + }, + { + html : { + caption : 'Color', + span : this.settings.span + }, + name : 'color', + options : { + silent: false + }, + required : true, + type : 'color', + }, + { + html : { + caption : 'Width', + span : this.settings.span + }, + name : 'width', + options : { + arrows : true, + max : 4, + min : 0.25, + placeholder : '0.25 - 4', + silent : false, + step : 0.25 + }, + required : true, + type : 'float', + } + ]; + + // ================================================== + // Define allowable tile types + // -------------------------------------------------- + var record = this.graticule.olexp_record; + + // ================================================== + // Function to process form changes + // -------------------------------------------------- + var onChanges = function(changes) + { + for (var name in changes) + { + record[name] = changes[name]; + } + var options = $.extend({}, record); + delete options.enable; + me.graticule.setMap(null); + me.graticule = me.util.getGraticule((record.enable ? me.map : null), options); + }; + + // ================================================== + // Process popup form + // -------------------------------------------------- + + var formOptions = $.extend(this.settings.form, { + fields : fields, + name : this.name, + record : record + }); + + var popupOptions = this.settings.popup; + + olexp.util.popup(this.id, onChanges, formOptions, popupOptions); + + }; + + /** + * Control to edit grid lines. + * @memberOf olexp.control + * @param {olexp.Explorer} explorer Source Explorer + * @param {object} options Control options + * @param {olexp.ExplorerSettings} options.settings Explorer settings + * @public + * @returns {external:jQuery.fn.w2toolbar.properties} Graticule toolbar + * control + */ + olexp.control.Graticule = function(explorer, options) { + + if (typeof options === "undefined") options = {}; + if (typeof options.settings === "undefined") options.settings = {}; + + var control = new Graticule(explorer.map, options.settings); + + return { + hint : control.settings.hint, + id : control.button, + img : control.icon, + onClick : function (event) { + control.display(); + }, + type : 'button' + }; + + }; + + return olexp; + +}(olexp || {})); + +//================================================== +// Layer Controls +//-------------------------------------------------- +(function(olexp) { + + /** + * Control to add layers + * @param {ol.Map} map + * @param {olexp.ExplorerSettings} settings olexp settings + * @private + */ + var LayerControl = function(map, settings) + { + + //================================================== + // Override Layer Control Tile option defaults + // with user provided values. + //-------------------------------------------------- + var olexpSettings = $.extend(true, {control : { + LayerControlTile : { + form : { + header : '', + style : 'border: 0px; background-color: transparent;' + }, + hint : 'Add Tile Layer', + popup : { + height : 165, + style : 'border: 0px; background-color: transparent;', + title : 'Add Tile Layer', + width : 290 + }, + span : 3 + }, + LayerControlVector : { + form : { + header : ('File Types: ' + $.map(olexp.util.FileTypes, + function(o) { return ' ' + o.name; })), + style : 'border: 0px; background-color: transparent;' + }, + hint : 'Add Vector Layer', + popup : { + height : 195, + style : 'border: 0px; background-color: transparent;', + title : 'Add Vector Layer', + width : 350 + }, + span : 4 + }}}, settings); + + /** + * Tile control settings + * @field + * @private + * @type {Object} + */ + this.settingsTile = olexpSettings.control.LayerControlTile; + + /** + * Vector control settings + * @field + * @private + * @type {Object} + */ + this.settingsVector = olexpSettings.control.LayerControlVector; + + /** + * Control icons + * @field + * @private + * @type {string} + */ + this.icons = { + tile : 'olexp-control-layer-control-add-tile', + vector : 'olexp-control-layer-control-add-vector' + }; + + /** + * Button element ids + * @field + * @private + * @type {string} + */ + this.buttons = { + tile : settings.prefix + '-control-layer-control-add-tile-button', + vector : settings.prefix + '-control-layer-control-add-vector-button' + }; + + /** + * Controls element ids + * @field + * @private + * @type {string} + */ + this.ids = { + tile : settings.prefix + '-control-layer-control-add-tile', + vector : settings.prefix + '-control-layer-control-add-vector' + }; + + /** + * Parent map + * @field + * @private + * @type {ol.Map} + */ + this.map = map; + + /** + * w2ui form names + * @field + * @private + * @type {object} + */ + this.names = { + tile : settings.prefix + '-control-tile-form', + vector : settings.prefix + '-control-vector-form' + }; + + /** + * Utility tool + * @field + * @private + * @type {olexp.util.Util} + */ + this.util = new olexp.util.Util(this.map); + + }; + + /** + * Display add tile form + * @private + */ + LayerControl.prototype.tile = function() + { + var me = this; + + // ================================================== + // Define allowable tile types + // -------------------------------------------------- + var tileTypes = this.util.getTileTypes(); + var items = $.map(tileTypes, function(val) { return val.name; }); + + // ================================================== + // Form fields + // -------------------------------------------------- + var fields = [ + { + field : 'tile_source', + html : { + caption : 'Source', + span : this.settingsTile.span + }, + options : { + items: items + }, + required : true, + type : 'list' + } + ]; + + // ================================================== + // Form record + // -------------------------------------------------- + var record = {}; + record[fields[0].field] = null; + + // ================================================== + // Function to process form changes + // -------------------------------------------------- + var onChanges = function(changes) + { + for (var fieldName in changes) + { + if (fieldName === fields[0].field) + { + // Search for selected tile in list + var typeName = changes[fieldName].id; + for (var key in tileTypes) + { + if (typeName !== tileTypes[key].name) continue; + var tileType = tileTypes[key]; + var tileClass = tileType['class']; + var tile = new ol.layer.Tile({ + source: new tileClass(tileType.settings) + }); + tile.set('name', typeName); + me.map.addLayer(tile); + } + } + } + }; + + // ================================================== + // Process popup form + // -------------------------------------------------- + + var formOptions = $.extend(this.settingsTile.form, { + fields : fields, + name : this.names.tile, + record : record + }); + + var popupOptions = this.settingsTile.popup; + + olexp.util.popup(this.ids.tile, onChanges, formOptions, popupOptions); + + }; + + /** + * Display add vector form + * @private + */ + LayerControl.prototype.vector = function() + { + var me = this; + + // ================================================== + // Form fields + // -------------------------------------------------- + var fields = [ + { + field : 'vector_source', + html : { + caption : 'Source', + span : this.settingsVector.span + }, + options : { + placeholder : 'Click to add file', + silent : false + }, + required : true, + type : 'file' + } + ]; + + // ================================================== + // Form record + // -------------------------------------------------- + var record = {}; + record[fields[0].field] = null; + + // ================================================== + // Function to process form changes + // -------------------------------------------------- + var onChanges = function(changes) + { + for (var fieldName in changes) + { + if (fieldName === fields[0].field) + { + // Search for selected tile in list + for (var change in changes[fieldName]) + { + + // Check that file contents are valid + var content = changes[fieldName][change].content; + if (typeof content === 'undefined' || content === null) continue; + + // Extract filename and contents + var filename = changes[fieldName][change].name; + var name = filename.replace(/\.[^/.]+$/, ""); + + // Get file reader + var reader = olexp.util.getReader(filename); + if (reader === null) + { + w2alert('Unable to open file ' + filename, 'Error'); + return; + } + + // Convert file contents from base64 to text + // Read features and convert to map coordinates + var text = atob(content); + var projection = me.map.getView().getProjection(); + var options = {'featureProjection' : projection}; + var features = reader.readFeatures(text, options); + + // Add features to map + me.util.addLayerVector(me.map, name, features); + } + } + } + }; + + // ================================================== + // Process popup form + // -------------------------------------------------- + + var formOptions = $.extend(this.settingsVector.form, { + fields : fields, + name : this.names.vector, + record : record + }); + + var popupOptions = this.settingsVector.popup; + + olexp.util.popup(this.ids.vector, onChanges, formOptions, popupOptions); + + }; + + /** + * Control to add layers + * @memberOf olexp.control + * @param {olexp.Explorer} explorer Source Explorer + * @param {object} options Control options + * @param {boolean} options.tile Enable tile control + * @param {boolean} options.vector Enable vector control + * @param {olexp.ExplorerSettings} options.settings Explorer settings + * @public + * @returns {array} Array of w2toolbar properties + */ + olexp.control.LayerControl = function(explorer, options) { + + if (typeof options === "undefined") options = {}; + if (typeof options.tile === "undefined") options.tile = true; + if (typeof options.vector === "undefined") options.vector = true; + if (typeof options.settings === "undefined") options.settings = {}; + + var tool = new LayerControl(explorer.map, options.settings); + + // Add controls for those selected + var controls = []; + if (options.tile) + { + controls.push({ + hint : tool.settingsTile.hint, + id : tool.buttons.tile, + img : tool.icons.tile, + onClick : function (event) { + tool.tile(); + }, + type : 'button' + }); + } + if (options.vector) + { + controls.push({ + hint : tool.settingsVector.hint, + id : tool.buttons.vector, + img : tool.icons.vector, + onClick : function (event) { + tool.vector(); + }, + type : 'button' + }); + } + + return controls; + + }; + + return olexp; + +}(olexp || {})); + +//================================================== +// Layer Manager Controls +//-------------------------------------------------- +olexp = (function(olexp) { + + /** + * Control to manage layers + * @param {olexp.Explorer} explorer Explorer + * @param {olexp.manager.Manager} manager Explorer manager + * @param {olexp.ExplorerSettings} settings olexp settings + * @private + */ + var LayerManager = function(explorer, manager, settings) + { + + //================================================== + // Override Layer Manager option defaults + // with user provided values. + //-------------------------------------------------- + var olexpSettings = $.extend(true, {control : { + LayerManager : { + hintDetailsHide : 'Hide details', + hintDetailsShow : 'Show details', + hintMoveDown : 'Move item down', + hintMoveUp : 'Move item up', + hintOutlineHide : 'Hide outline', + hintOutlineShow : 'Show outline' + }}}, settings); + + /** + * Button element ids + * @field + * @private + * @type {string} + */ + this.buttons = { + details : settings.prefix + '-control-layer-manager-button-details', + down : settings.prefix + '-control-layer-manager-button-down', + navigation : settings.prefix + '-control-layer-manager-button-navigation', + up : settings.prefix + '-control-layer-manager-button-up' + }; + + /** + * Explorer + * @field + * @private + * @type {olexp.Explorer} + */ + this.explorer = explorer; + + /** + * Control icon + * @field + * @private + * @type {string} + */ + this.icons = { + details : 'olexp-control-layer-manager-details', + down : 'olexp-control-layer-manager-down', + navigation : 'olexp-control-layer-manager-navigation', + up : 'olexp-control-layer-manager-up' + }; + + /** + * Explorer manager + * @field + * @private + * @type {olexp.manager.Manager} + */ + this.manager = manager; + + /** + * Layer Manager control settings + * @field + * @private + * @type {string} + */ + this.settings = olexpSettings.control.LayerManager; + + // ================================================== + // Add layer callback events + // -------------------------------------------------- + this.manager.on('remove:item', this.onItemRemoved, this); + this.manager.on('select:item', this.onItemSelected, this); + + }; + + /** + * Show details + * @private + */ + LayerManager.prototype.details = function() + { + this.explorer.navigation.toggle(this.explorer.options.details.type); + // Set control tooltip based on navigation panel visibility + var details = this.explorer.navigation.get(this.explorer.options.details.type); + var item = this.explorer.toolbar.get(this.buttons.details); + item.hint = this.hintDetails(details.hidden); + this.explorer.toolbar.refresh(); + }; + + /** + * Move layer down + * @private + */ + LayerManager.prototype.down = function() + { + this.manager.moveDown(); + }; + + /** + * Set details control hint text + * @param {boolean} hidden True if details is hidden otherwise false + * @private + */ + LayerManager.prototype.hintDetails = function(hidden) + { + return (hidden ? this.settings.hintDetailsShow : this.settings.hintDetailsHide); + }; + + /** + * Set navigation control hint text + * @param {boolean} hidden True if navigation is hidden otherwise false + * @private + */ + LayerManager.prototype.hintNavigation = function(hidden) + { + return (hidden ? this.settings.hintOutlineShow : this.settings.hintOutlineHide); + }; + + /** + * Show navigation + * @private + */ + LayerManager.prototype.navigation = function() + { + this.explorer.layout.toggle(this.explorer.options.navigation.type); + // Set control tooltip based on navigation panel visibility + var navigation = this.explorer.layout.get(this.explorer.options.navigation.type); + var item = this.explorer.toolbar.get(this.buttons.navigation); + item.hint = this.hintNavigation(navigation.hidden); + this.explorer.toolbar.refresh(); + }; + + /** + * Callback when layer removed + * @param {olexp.item.Item} item OpenLayers Explorer Item + * @private + */ + LayerManager.prototype.onItemRemoved = function(item) + { + + if (this.manager.isSelected(item.id)) + { + this.explorer.toolbar.disable(this.buttons.up); + this.explorer.toolbar.disable(this.buttons.down); + } + + }; + + /** + * Callback when node is selected either by click or double click + * @param {string} id Layer ID + * @private + */ + LayerManager.prototype.onItemSelected = function(id) + { + if (typeof id === 'undefined') return; + var item = this.manager.getById(id); + if (item === null) return; + var node = this.manager.getNode(item.id); + if (node.disabled) + { + this.explorer.toolbar.disable(this.buttons.up); + this.explorer.toolbar.disable(this.buttons.down); + } + else + { + this.explorer.toolbar.enable(this.buttons.up); + this.explorer.toolbar.enable(this.buttons.down); + } + }; + + /** + * Move layer up + * @private + */ + LayerManager.prototype.up = function() + { + this.manager.moveUp(); + }; + + /** + * Control to manage layers + * @memberOf olexp.control + * @param {olexp.Explorer} explorer Explorer + * @param {olexp.manager.Manager} manager Explorer manager + * @param {object} options Control options + * @param {object} options.details Enable details panel options + * @param {boolean} options.details.enabled Enable details control + * @param {boolean} options.details.checked Indicate checked state + * @param {boolean} options.down Enable down control + * @param {object} options.navigation Enable navigation options + * @param {boolean} options.navigation.enabled Enable navigation control + * @param {boolean} options.navigation.checked Indicate checked state + * @param {olexp.ExplorerSettings} options.settings Explorer settings + * @param {boolean} options.up Enable up control + * @public + * @returns {array} Array of external:jQuery.fn.w2toolbar.properties + */ + olexp.control.LayerManager = function(explorer, manager, options) { + + if (typeof options === "undefined") options = {}; + + if (typeof options.details === "undefined") options.details = {}; + if (typeof options.details.enabled === "undefined") options.details.enabled = true; + if (typeof options.details.checked === "undefined") options.details.checked = true; + if (typeof options.down === "undefined") options.down = true; + if (typeof options.navigation === "undefined") options.navigation = {}; + if (typeof options.navigation.enabled === "undefined") options.navigation.enabled = true; + if (typeof options.navigation.checked === "undefined") options.navigation.checked = true; + if (typeof options.up === "undefined") options.up = true; + + var tool = new LayerManager(explorer, manager, options.settings); + + // Add controls for those selected + var controls = []; + if (options.navigation.enabled) + { + // Determine control tooltip based on navigation panel visibility + controls.push({ + checked : options.navigation.checked, + hint : tool.hintNavigation(!options.navigation.checked), + id : tool.buttons.navigation, + img : tool.icons.navigation, + onClick : function (event) { + tool.navigation(); + }, + type : 'check' + }); + } + if (options.details.enabled) + { + // Determine control tooltip based on details panel visibility + controls.push({ + checked : options.details.checked, + hint : tool.hintDetails(!options.details.checked), + id : tool.buttons.details, + img : tool.icons.details, + onClick : function (event) { + tool.details(); + }, + type : 'check' + }); + } + if (options.up) + { + controls.push({ + disabled : true, + hint : tool.settings.hintMoveUp, + id : tool.buttons.up, + img : tool.icons.up, + onClick : function (event) { + tool.up(); + }, + type : 'button' + }); + } + if (options.down) + { + controls.push({ + disabled : true, + hint : tool.settings.hintMoveDown, + id : tool.buttons.down, + img : tool.icons.down, + onClick : function (event) { + tool.down(); + }, + type : 'button' + }); + } + + return controls; + + }; + + return olexp; + +}(olexp || {})); + +//================================================== +// Layer Menu Control +//-------------------------------------------------- +(function(olexp) { + + /** + * Control to display layer menu properties + * @param {olexp.Explorer} explorer Explorer + * @param {olexp.manager.Manager} manager Explorer manager + * @param {object} menu Item Menus {items : list of menu item, + * callbacks : list of menu item callbacks} + * @param {olexp.ExplorerSettings} settings olexp.ExplorerSettings + * @private + */ + var LayerMenu = function(explorer, manager, menu, settings) + { + + //================================================== + // Override Layer Menu Control option defaults + // with user provided values. + //-------------------------------------------------- + var olexpSettings = $.extend(true, {control : { + LayerMenu : { + arrow : true, + hint : 'Item Options', + text : '' + }}}, settings); + + /** + * Button element id + * @field + * @private + * @type {string} + */ + this.button = settings.prefix + '-control-layer-menu'; + + /** + * Explorer + * @field + * @private + * @type {olexp.Explorer} + */ + this.explorer = explorer; + + /** + * Control icon + * @field + * @private + * @type {string} + */ + this.icon = 'olexp-control-layer-menu'; + + /** + * Explorer manager + * @field + * @private + * @type {olexp.manager.Manager} + */ + this.manager = manager; + + /** + * Menu items and callbacks + * @field + * @private + * @type {Object} + */ + this.menu = menu; + + /** + * Layer Menu control settings + * @field + * @private + * @type {Object} + */ + this.settings = olexpSettings.control.LayerMenu; + + // ================================================== + // Add layer callback events + // -------------------------------------------------- + this.manager.on('remove:item', this.onItemRemoved, this); + this.manager.on('select:item', this.onItemSelected, this); + + }; + + /** + * Callback when layer removed + * @param {olexp.item.Item} item OpenLayers Explorer Item + * @private + */ + LayerMenu.prototype.onItemRemoved = function(item) + { + + if (this.manager.isSelected(item.id)) + { + this.explorer.toolbar.disable(this.button); + } + + }; + + /** + * Callback when node is selected either by click or double click + * @param {string} id Layer ID + * @private + */ + LayerMenu.prototype.onItemSelected = function(id) + { + if (typeof id === 'undefined') return; + var item = this.manager.getById(id); + if (item === null) return; + var node = this.manager.getNode(item.id); + if (node.disabled) + { + this.explorer.toolbar.disable(this.button); + } + else + { + this.explorer.toolbar.enable(this.button); + } + }; + + /** + * Display layer properties menu control + * @memberOf olexp.control + * @param {olexp.Explorer} explorer Source explorer + * @param {olexp.manager.Manager} manager Explorer manager + * @param {object} menu Item Menu items and callbacks + * @param {Array} menu.items List of menu items + * @param {Array} menu.callbacks List of menu item callbacks + * @param {object} options Control options + * @param {olexp.ExplorerSettings} options.settings Explorer settings + * @public + * @returns {external:jQuery.fn.w2toolbar.properties} LayerMenu toolbar + * control + */ + olexp.control.LayerMenu = function(explorer, manager, menu, options) { + + var control = new LayerMenu(explorer, manager, menu, options.settings); + + explorer.toolbar.on('click', function(event) { + + // Check if any item is selected + if (explorer.outline.selected === null) return; + + // Check if layer menu item was selected + var id = control.button + ':'; + if (event.target.indexOf(id) < 0) return; + var menuid = event.target.replace(id, ""); + + // Create dummy menu event + if (menuid in menu.callbacks) + { + menu.callbacks[menuid]({target : explorer.outline.selected}); + } + + }); + + return { + arrow : control.settings.arrow, + disabled : true, + hint : control.settings.hint, + id : control.button, + img : control.icon, + items : control.menu.items, + text : control.settings.text, + type : 'menu' + }; + + }; + + return olexp; + +}(olexp || {})); + +//================================================== +// Measurement Controls +//-------------------------------------------------- +(function(olexp) { + + /** + * Control to calculate measurements + * @param {olexp.Explorer} explorer Explorer + * @param {olexp.ExplorerSettings} settings olexp settings + * @private + */ + var Measurement = function(explorer, settings) + { + + //================================================== + // Override Measurement option defaults + // with user provided values. + //-------------------------------------------------- + var olexpSettings = $.extend(true, {control : { + Measurement : { + hintArea : 'Measure area', + hintLength : 'Measure length' + }}}, settings); + + /** + * Parent explorer + * @field + * @private + * @type {olexp.Explorer} + */ + this.explorer = explorer; + + /** + * Control icon + * @field + * @private + * @type {string} + */ + this.icons = { + area : 'olexp-control-measure-area', + length : 'olexp-control-measure-length' + }; + + /** + * Button element id + * @field + * @private + * @type {string} + */ + this.ids = { + area : settings.prefix + '-control-measure-area-button', + length : settings.prefix + '-control-measure-length-button' + }; + + /** + * Measurement control settings + * @field + * @private + * @type {Object} + */ + this.settings = olexpSettings.control.Measurement; + + /** + * Measurement tool + * @field + * @private + * @type {olexp.measure.Tool} + */ + this.tool = new olexp.measure.Tool(explorer.map, + {type: olexp.measure.Type.LINE, + settings: settings}); + + }; + + /** + * Start area measurement + * @memberOf Measurement.prototype + * @private + */ + Measurement.prototype.area = function() { + var enable = !this.explorer.toolbar.get(this.ids.area).checked; + this.measure(olexp.measure.Type.AREA, enable); + }; + + /** + * Start length measurement + * @memberOf Measurement.prototype + * @private + */ + Measurement.prototype.length = function() + { + var enable = !this.explorer.toolbar.get(this.ids.length).checked; + this.measure(olexp.measure.Type.LINE, enable); + }; + + /** + * Run measurement tool + * @memberOf Measurement.prototype + * @param {olexp.measure.Type} type Measurement type to start. + * @param {boolean} enable True if measurement is started otherwise false + * @private + */ + Measurement.prototype.measure = function(type, enable) + { + this.tool.setEnable(false); + if (enable) + { + this.tool.setType(type); + this.tool.setEnable(true); + } + }; + + /** + * Control to export map to image + * @memberOf olexp.control + * @param {olexp.Explorer} explorer Explorer + * @param {object} options Control options + * @param {boolean} options.area Enable area measurement control + * @param {boolean} options.length Enable length measurement control + * @param {olexp.ExplorerSettings} options.settings Explorer settings + * @public + * @returns {array} Array of w2toolbar properties + */ + olexp.control.Measure = function(explorer, options) { + + if (typeof options === "undefined") options = {}; + if (typeof options.area === "undefined") options.area = true; + if (typeof options.length === "undefined") options.length = true; + if (typeof options.settings === "undefined") options.settings = {}; + + var tool = new Measurement(explorer, options.settings); + + // Add controls for those selected + var controls = []; + if (options.area) + { + controls.push({ + hint : tool.settings.hintArea, + id : tool.ids.area, + img : tool.icons.area, + onClick : function (event) { + if (options.length) + { + explorer.toolbar.uncheck(tool.ids.length); + } + tool.area(); + }, + type : 'check' + }); + } + if (options.length) + { + controls.push({ + hint : tool.settings.hintLength, + id : tool.ids.length, + img : tool.icons.length, + onClick : function (event) { + if (options.area) + { + explorer.toolbar.uncheck(tool.ids.area); + } + tool.length(); + }, + type : 'check' + }); + } + + return controls; + + }; + + return olexp; + +}(olexp || {})); + +//================================================== +// Toolbar Hide Control +//-------------------------------------------------- +(function(olexp) { + + /** + * Control to hide toolbar + * @param {olexp.Explorer} explorer Source explorer + * @param {object} options Control options {hidden : True if toolbar is + * initially hidden, + * settings : olexp.ExplorerSettings} + * @private + */ + var ToolbarHide = function(explorer, options) + { + + //================================================== + // Override Toolbar Hide option defaults + // with user provided values. + //-------------------------------------------------- + var olexpSettings = $.extend(true, {control : { + ToolbarHide : { + hint : 'Hide toolbar' + }}}, options.settings); + + /** + * Button element id + * @field + * @private + * @type {string} + */ + this.button = options.settings.prefix + '-control-toolbar-hide-button'; + + /** + * Source explorer + * @field + * @private + * @type {olexp.Explorer} + */ + this.explorer = explorer; + + /** + * Control icon + * @field + * @private + * @type {string} + */ + this.icon = 'olexp-control-toolbar-hide'; + + /** + * ToolbarHide control settings + * @field + * @private + * @param {Object} settings + */ + this.settings = olexpSettings.control.ToolbarHide; + + /** + * ol.control to show toolbar when hidden + * @field + * @private + * @type {olexp.ol.ToolbarShow} + */ + this.show = olexp.ol.ToolbarShow(this.explorer, options); + + }; + + /** + * Toolbar visibility + * @private + */ + ToolbarHide.prototype.hide = function() + { + this.explorer.layout.hide(this.explorer.options.toolbar.type); + this.show.setMap(this.explorer.map); + }; + + /** + * Control to set toolbar visibility + * @memberOf olexp.control + * @param {olexp.Explorer} explorer Source Explorer + * @param {object} options Control options + * @param {boolean} options.hidden True if toolbar is initially hidden + * @param {olexp.ExplorerSettings} options.settings Explorer settings + * @public + * @returns {external:jQuery.fn.w2toolbar.properties} ToolbarHide toolbar + * control + */ + olexp.control.ToolbarHide = function(explorer, options) { + + var control = new ToolbarHide(explorer, options); + + return { + hint : control.settings.hint, + id : control.button, + img : control.icon, + onClick : function (event) { + control.hide(); + }, + type : 'button' + }; + }; + + return olexp; + +}(olexp || {})); + + +/** + * @namespace olexp.item + */ +olexp.item = olexp.item || {}; + +//================================================== +// Explorer managed item +//-------------------------------------------------- +(function(olexp) { + + "use strict"; + + /** + * Item icons + * @enum {string} + * @memberOf olexp.item + * @public + * @readonly + */ + olexp.item.icons = { + /** + * Group icon css selector + * @type string + */ + group : 'olexp-item-group', + /** + * Heat Map icon css selector + * @type string + */ + heatmap : 'olexp-item-heatmap', + /** + * Image icon css selector + * @type string + */ + image : 'olexp-item-image', + /** + * Overlay icon css selector + * @type string + */ + overlay : 'olexp-item-overlay', + /** + * Tile Map icon css selector + * @type string + */ + tile : 'olexp-item-tile', + /** + * Vector icon css selector + * @type string + */ + vector : 'olexp-item-vector' + }; + + /** + * Item managed + * @param {string} id Item ID + * @param {string} name Item name + * @param {ol.layer.Layer|ol.Overlay} layer ol3 layer/overlay object + * @private + */ + var Item = function(id, name, layer) + { + + /** + * Item id + * @field + * @private + * @type {string} + */ + this.id = id; + + /** + * ol3 layer/overlay object + * @field + * @private + * @type {ol.layer.Layer|ol.Overlay} + */ + this.layer = layer; + + /** + * Indicates if item is currently being moved in manager + * @field + * @private + * @type {string} + */ + this.moving = false; + + /** + * Item name + * @field + * @private + * @type {string} + */ + this.name = name; + + /** + * Item type + * @field + * @private + * @readonly + * @type {olexp.item.Type} + */ + this.type = Item.getType(this.layer); + + /** + * Item icon + * @field + * @private + * @readonly + * @type {string} + */ + this.icon = Item.getIcon(this.type); + + }; + + /** + * Get item details + * @memberOf Item.prototype + * @private + * @returns {object} Object of item properties + */ + Item.prototype.getDetails = function() + { + var properties = {}; + + // ================================================== + // Generic properties + // -------------------------------------------------- + properties.Name = this.name; + + var layerProperties = this.layer.getProperties(); + if (layerProperties.hasOwnProperty(olexp.measure.properties.area)) + { + properties.Area = layerProperties[olexp.measure.properties.area]; + } + else if (layerProperties.hasOwnProperty(olexp.measure.properties.length)) + { + properties.Length = layerProperties[olexp.measure.properties.length]; + } + + // ================================================== + // Group properties + // -------------------------------------------------- + if (this.type === olexp.item.Type.GROUP) + { + var layers = this.layer.getLayers(); + properties['Layer Count'] = layers.getLength(); + } + + // ================================================== + // Vector properties + // -------------------------------------------------- + if (this.type === olexp.item.Type.VECTOR) + { + var source = this.layer.getSource(); + var features = source.getFeatures(); + properties['Feature Count'] = features.length; + } + + // ================================================== + // Convert properties to records + // -------------------------------------------------- + var records = olexp.util.toRecords(properties); + + return records; + }; + + /** + * Get item extent + * @memberOf Item.prototype + * @private + * @returns {ol.Extent|null} Item extent or null if undefined + */ + Item.prototype.getExtent = function() + { + + if (this.type === olexp.item.Type.OVERLAY) + { + return null; + } + else if (this.type === olexp.item.Type.GROUP) + { + var extent = null; + var layers = this.layer.getLayers(); + layers.forEach(function(layer, index, array) + { + var layerExtent = Item.getLayerExtent(layer); + if ((extent === null) && + (layerExtent !== null)) + { + extent = layerExtent; + } + else if ((extent !== null) && + (layerExtent !== null)) + { + extent = ol.extent.extend(extent, layerExtent); + } + }, this); + return extent; + } + + return Item.getLayerExtent(this.layer); + + }; + + /** + * Get item icon based on type + * @memberOf Item + * @param {olexp.item.Type} type Item type + * @private + * @returns {string} CSS selector of icon + */ + Item.getIcon = function(type) + { + if (type === olexp.item.Type.GROUP) + { + return olexp.item.icons.group; + } + else if (type === olexp.item.Type.HEATMAP) + { + return olexp.item.icons.heatmap; + } + else if (type === olexp.item.Type.IMAGE) + { + return olexp.item.icons.image; + } + else if (type === olexp.item.Type.OVERLAY) + { + return olexp.item.icons.overlay; + } + else if (type === olexp.item.Type.TILE) + { + return olexp.item.icons.tile; + } + else if (type === olexp.item.Type.VECTOR) + { + return olexp.item.icons.vector; + } + return 'icon-page'; + }; + + /** + * Get layer extent + * @memberOf Item.prototype + * @param {ol.layer.Layer} layer Source layer + * @private + * @returns {ol.Extent|null} Layer extent or null if undefined + */ + Item.getLayerExtent = function(layer) + { + + // ================================================== + // Check if layer has extent defined + // -------------------------------------------------- + var extent = layer.getExtent(); + if (typeof extent === 'undefined') + { + // ================================================== + // Check if source has extent defined + // -------------------------------------------------- + var source = layer.getSource(); + if (source !== null && + (source instanceof ol.source.Cluster || + source instanceof ol.source.VectorTile || + source instanceof ol.source.Vector)) + { + extent = source.getExtent(); + } + } + if (typeof extent === 'undefined') return null; + return extent; + + }; + + /** + * List of editable properties of layer/overlay + * @memberOf Item.prototype + * @private + * @returns {object} Item properties names + */ + Item.prototype.getPropertyTypes = function() + { + if (this.layer instanceof ol.layer.Layer) + { + return olexp.item.LayerProperties; + } + else if (this.layer instanceof ol.Overlay) + { + return olexp.item.OverlayProperties; + } + return {}; + }; + + /** + * Update item editable properties + * @memberOf Item.prototype + * @private + * @returns {object} Item properties + */ + Item.prototype.getProperties = function() + { + var properties = {name: this.name}; + var types = this.getPropertyTypes(); + for (var key in types) + { + properties[key] = this.layer.get(key); + } + return properties; + }; + + /** + * Get item type for given layer + * @memberOf Item + * @param {ol.layer.Layer|ol.Overlay} layer Source layer + * @private + * @returns {olexp.item.Type} Type of item + */ + Item.getType = function(layer) + { + if (layer instanceof ol.layer.Group) + { + return olexp.item.Type.GROUP; + } + else if (layer instanceof ol.layer.Heatmap) + { + return olexp.item.Type.HEATMAP; + } + else if (layer instanceof ol.layer.Image) + { + return olexp.item.Type.IMAGE; + } + else if (layer instanceof ol.layer.Tile) + { + return olexp.item.Type.TILE; + } + else if (layer instanceof ol.layer.Vector) + { + return olexp.item.Type.VECTOR; + } + else if (layer instanceof ol.Overlay) + { + return olexp.item.Type.OVERLAY; + } + return null; + }; + + /** + * Update item editable properties + * @memberOf Item.prototype + * @param {Object} properties Item properties to update + * @private + */ + Item.prototype.setProperties = function(properties) + { + if (properties.hasOwnProperty('name')) this.name = properties.name; + var types = this.getPropertyTypes(); + for (var key in types) + { + if (properties.hasOwnProperty(key)) this.layer.set(key, properties[key]); + } + }; + + /** + * Get/set item property + * @memberOf Item.prototype + * @param {string} name Property name + * @param {object} value Property value + * @private + */ + Item.prototype.property = function(name, value) + { + if (typeof this[name] === 'undefined') return; + if (typeof value !== 'undefined') this[name] = value; + return this[name]; + }; + + /** + * Get item extent + * @memberOf Item.prototype + * @param {ol.Map} map ol3 map to zoom + * @private + */ + Item.prototype.zoomTo = function(map) + { + + var view = map.getView(); + + if (this.type === olexp.item.Type.OVERLAY) + { + + // ================================================== + // Check if overlay has position defined + // -------------------------------------------------- + var position = this.layer.getPosition(); + if (typeof position !== 'undefined') + { + view.setCenter(position); + return; + } + + w2alert('Overlay has no position defined to which to zoom.', 'Warning'); + + } + else + { + + // ================================================== + // Check if layer has extent defined + // -------------------------------------------------- + var extent = this.getExtent(); + if (extent !== null) + { + view.fit(extent, map.getSize()); + return; + } + + w2alert('Layer has no extent defined to which to zoom.', 'Warning'); + + } + + }; + + /** + * Item managed + * @memberOf olexp.item + * @param {string} id Item ID + * @param {string} name Item name + * @param {external:ol.layer.Layer|external:ol.Overlay} layer ol3 layer or + * overlay object + * @public + */ + olexp.item.Item = function(id, name, layer) { + var item = new Item(id, name, layer); + return { + getDetails : item.getDetails.bind(item), + getProperties : item.getProperties.bind(item), + getPropertyTypes : item.getPropertyTypes.bind(item), + icon : item.icon, + id : item.id, + layer : item.layer, + moving : function(moving) { + return item.property('moving', moving); + }, + name : function(name) { + return item.property('name', name); + }, + setProperties : item.setProperties.bind(item), + type : item.type, + zoomTo : item.zoomTo.bind(item) + }; + }; + + /** + * Enumeration of Overlay properties + * @enum {string} + * @memberOf olexp.item + * @public + * @readonly + */ + olexp.item.OverlayProperties = + { + }; + + /** + * Enumeration of Layer properties + * @enum {string} + * @memberOf olexp.item + * @public + * @readonly + */ + olexp.item.LayerProperties = + { + /** + * Opacity property + * @type object + */ + opacity : { + /** + * Opacity title + * @type string + */ + title : 'Opacity' + } + }; + + /** + * Enumeration of types of allowable managed items + * @enum {string} + * @memberOf olexp.item + * @public + * @readonly + */ + olexp.item.Type = { + /** + * Group managed item + * @type number + */ + GROUP : 0, + /** + * Heat Map managed item + * @type number + */ + HEATMAP : 1, + /** + * Image managed item + * @type number + */ + IMAGE : 2, + /** + * Overlay managed item + * @type number + */ + OVERLAY : 3, + /** + * Tile managed item + * @type number + */ + TILE : 4, + /** + * Vector managed item + * @type number + */ + VECTOR : 5 + }; + + return olexp; + +}(olexp || {})); + + +/** + * @namespace olexp.manager + */ +olexp.manager = olexp.manager || {}; + +//================================================== +// Manager +//-------------------------------------------------- +(function(olexp) { + + "use strict"; + + /** + * Item manager that synchronizes adding and removing items from the map + * sidebar and the corresponding layers on the ol3 map + * @class + * @memberOf olexp.manager + * @param {external:ol.Map} map Managed map + * @param {external:jQuery.fn.w2sidebar} outline Managed outline sidebar + * @param {external:jQuery.fn.w2grid} details Details grid + * @param {string} layersId w2ui name of layers node + * @param {string} overlaysId w2ui name of overlays node + * @private + */ + var ManagerAPI = function(map, outline, details, layersId, overlaysId) + { + + /** + * Event listeners + * @ignore + * @type {olexp.event.Event} + */ + this.event = new olexp.event.Event({'select:item' : []}); + + /** + * Layer Manager + * @ignore + * @type {olexp.manager.NodeManager} + */ + this.managerLayers = new olexp.manager.NodeManager(layersId, + map.getLayers(), + outline, + details); + + /** + * Layers node id prefix + * @ignore + * @type {string} + */ + this.layersId = layersId; + + /** + * Overlay Manager + * @ignore + * @type {olexp.manager.NodeManager} + */ + this.managerOverlays = new olexp.manager.NodeManager(overlaysId, + map.getOverlays(), + outline, + details); + + /** + * Managed map + * @ignore + * @type {ol.Map} + */ + this.map = map; + this.map.on('change:layergroup', this.onLayerGroupChanged, this); + + /** + * Managed outline sidebar + * @ignore + * @type {external:jQuery.fn.w2sidebar} + */ + this.outline = outline; + + /** + * Overlays node id prefix + * @ignore + * @type {string} + */ + this.overlaysId = overlaysId; + + }; + + /** + * Check if id is a Layer node + * @ignore + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id Item ID + * @private + * @returns True if id a Layer node otherwise false + */ + ManagerAPI.prototype.isIdLayerNode = function(id) + { + if (typeof id !== 'string') return false; + return id.indexOf(this.layersId) === 0; + }; + + /** + * Check if id is a Overlay node + * @ignore + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id Item ID + * @private + * @returns True if id is a Overlay node otherwise false + */ + ManagerAPI.prototype.isIdOverlayNode = function(id) + { + if (typeof id !== 'string') return false; + return id.indexOf(this.overlaysId) === 0; + }; + + /** + * Check if item is selected + * @function isSelected + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id Item ID + * @public + * @returns True if item is selected otherwise false + */ + ManagerAPI.prototype.isSelected = function(id) + { + return id === this.outline.selected; + }; + + /** + * Get item based on id + * @function getById + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id Item ID + * @public + * @returns {null|olexp.item.Item} Managed item or null if not found + */ + ManagerAPI.prototype.getById = function(id) + { + + // Check if this is a layer node + if (this.isIdLayerNode(id)) + { + return this.managerLayers.getById(id); + } + // Check if this is a overlay node + else if (this.isIdOverlayNode(id)) + { + return this.managerOverlays.getById(id); + } + + return null; + + }; + + /** + * Get layer details + * @function getDetails + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id Layer ID + * @public + * @returns {array} Item details + */ + ManagerAPI.prototype.getDetails = function(id) + { + + // Check if this is a layer node + if (this.isIdLayerNode(id)) + { + var itemLayer = this.managerLayers.getById(id); + if (itemLayer !== null) return itemLayer.getDetails(); + } + // Check if this is a overlay node + else if (this.isIdOverlayNode(id)) + { + var itemOverlay = this.managerOverlays.getById(id); + if (itemOverlay !== null) return itemOverlay.getDetails(); + } + + return []; + + }; + + /** + * Get node for item + * @function getNode + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id Item ID + * @public + * @returns {external:jQuery.fn.w2sidebar.nodes} w2ui sidebar node + */ + ManagerAPI.prototype.getNode = function(id) + { + return this.outline.get(id); + }; + + /** + * Move item down in map list + * @function moveDown + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id Item ID + * @public + * @returns {boolean} True if moved otherwise false + */ + ManagerAPI.prototype.moveDown = function(id) + { + + // If no id provided use selected + if (typeof id === 'undefined') id = this.outline.selected; + + // Check if this is a layer node + if (this.isIdLayerNode(id)) + { + return this.managerLayers.moveDown(id); + } + // Check if this is a overlay node + else if (this.isIdOverlayNode(id)) + { + return this.managerOverlays.moveDown(id); + } + + return false; + + }; + + /** + * Move item up in map list + * @function moveUp + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id Item ID + * @public + * @returns {boolean} True if moved otherwise false + */ + ManagerAPI.prototype.moveUp = function(id) + { + + // If no id provided use selected + if (typeof id === 'undefined') id = this.outline.selected; + + // Check if this is a layer node + if (this.isIdLayerNode(id)) + { + return this.managerLayers.moveUp(id); + } + // Check if this is a overlay node + else if (this.isIdOverlayNode(id)) + { + return this.managerOverlays.moveUp(id); + } + + return false; + + }; + + /** + * Remove listener + * @function off + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} type The event type. + * @param {function} listener The listener function. + * @param {object} opt_this The object to use as this in listener. + * @public + */ + ManagerAPI.prototype.off = function(type, listener, opt_this) + { + this.event.off(type, listener, opt_this); + this.managerLayers.off(type, listener, opt_this); + this.managerOverlays.off(type, listener, opt_this); + }; + + /** + * Add listener + * @function on + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} type The event type. + * @param {function} listener The listener function. + * @param {object} opt_this The object to use as this in listener. + * @public + */ + ManagerAPI.prototype.on = function(type, listener, opt_this) + { + this.event.on(type, listener, opt_this); + this.managerLayers.on(type, listener, opt_this); + this.managerOverlays.on(type, listener, opt_this); + }; + + /** + * Callback when node is selected either by click or double click + * @function onItemSelected + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id Layer ID + * @public + */ + ManagerAPI.prototype.onItemSelected = function(id) + { + this.event.trigger('select:item', id); + }; + + /** + * Callback when map layer group is changed + * @function onLayerGroupChanged + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {external:ol.ObjectEvent} event The change event. + * @private + */ + ManagerAPI.prototype.onLayerGroupChanged = function(event) + { + + this.managerLayers.setLayers(event.target.getLayers()); + + }; + + /** + * Remove item from map + * @function removeFromMap + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {olexp.item.Item} item Item to remove from map + * @public + * @returns {null|external:ol.layer.Layer|external:ol.Overlay} Layer removed + * from map or null if not found + */ + ManagerAPI.prototype.removeFromMap = function(item) + { + + // If no id provided use selected + if (!(item.hasOwnProperty('id'))) return null; + + // Check if this is a layer node + if (this.isIdLayerNode(item.id)) + { + return this.managerLayers.removeFromMap(item); + } + // Check if this is a overlay node + else if (this.isIdOverlayNode(item.id)) + { + return this.managerOverlays.removeFromMap(item); + } + + return null; + + }; + + /** + * Toggle node enable and corresponding layer visibility + * @function toggleNode + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id Item ID of node to toggle + * @public + */ + ManagerAPI.prototype.toggleNode = function(id) + { + + if (typeof id !== 'string') return; + + // ================================================== + // Toggle sidebar node enabled state + // -------------------------------------------------- + var node = this.outline.get(id); + var enable = node.disabled; + if (enable) + { + this.outline.enable(id); + } + else + { + this.outline.disable(id); + } + + // ================================================== + // Toggle map layer visibility + // -------------------------------------------------- + + // Check if this is a layer node + if (this.isIdLayerNode(id)) + { + var itemLayer = this.managerLayers.getById(id); + if (itemLayer !== null) itemLayer.layer.setVisible(enable); + } + // Check if this is a overlay node + else if (this.isIdOverlayNode(id)) + { + var itemOverlay = this.managerOverlays.getById(id); + if (itemOverlay !== null) + { + // Overlays don't have visibility so we hide DOM element + var properties = itemOverlay.layer.getProperties(); + if (properties.hasOwnProperty('element')) + { + var dom = $(properties.element); + if (enable) + { + dom.show(); + } + else + { + dom.hide(); + } + } + } + } + + }; + + /** + * Update item editable properties + * @function updateItem + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id ID of item to edit + * @param {object} properties Item properties to update + * @public + */ + ManagerAPI.prototype.updateItem = function(id, properties) + { + var item = this.getById(id); + if (item !== null) + { + item.setProperties(properties); + + // Update node + var node = this.outline.get(id); + node.text = item.name(); + + this.outline.refresh(); + } + }; + + /** + * Zoom to given item on map + * @function zoomTo + * @memberOf olexp.manager.ManagerAPI.prototype + * @param {string} id ID of item on which to zoom + * @public + */ + ManagerAPI.prototype.zoomTo = function(id) + { + var item = this.getById(id); + item.zoomTo(this.map); + }; + + /** + * Item manager that synchronizes adding and removing items from the map + * sidebar and the corresponding layers on the ol3 map + * @function + * @memberOf olexp.manager + * @param {external:ol.Map} map Managed map + * @param {external:jQuery.fn.w2sidebar} outline Managed outline sidebar + * @param {external:jQuery.fn.w2grid} details Details grid + * @param {string} layers w2ui name of layers node + * @param {string} overlays w2ui name of overlays node + * @public + * @returns {olexp.manager.ManagerAPI} + */ + olexp.manager.Manager = function(map, outline, details, layers, overlays) { + var manager = new ManagerAPI(map, outline, details, layers, overlays); + return { + getById : manager.getById.bind(manager), + getDetails : manager.getDetails.bind(manager), + getNode : manager.getNode.bind(manager), + isSelected : manager.isSelected.bind(manager), + moveDown : manager.moveDown.bind(manager), + moveUp : manager.moveUp.bind(manager), + off : manager.off.bind(manager), + on : manager.on.bind(manager), + onItemSelected : manager.onItemSelected.bind(manager), + removeFromMap : manager.removeFromMap.bind(manager), + toggleNode : manager.toggleNode.bind(manager), + updateItem : manager.updateItem.bind(manager), + zoomTo : manager.zoomTo.bind(manager) + }; + }; + + return olexp; + +}(olexp || {})); + +//================================================== +// Node Manager +//-------------------------------------------------- +(function(olexp) { + + /** + * Node manager that synchronizes adding and removing items + * @param {string} id Node id + * @param {external:ol.Collection} layers Managed map layers + * @param {external:jQuery.fn.w2sidebar} outline Managed outline sidebar + * @param {external:jQuery.fn.w2grid} details Details grid + * @private + */ + var NodeManager = function(id, layers, outline, details) + { + + /** + * Total count of items added + * @type {number} + */ + this.count = 0; + + /** + * Details grid + * @type {external:jQuery.fn.w2grid} + */ + this.details = details; + + /** + * Event listeners + * @type {olexp.event.Event} + */ + this.event = new olexp.event.Event({'remove:item' : []}); + + /** + * Node id + * @type {string} + */ + this.id = id; + + /** + * List of managed items + * @type {number} + */ + this.items = []; + + /** + * Managed map layers + * @type {ol.Collection} + */ + this.layers = layers; + this.layers.on('change:length', this.onLayerChanged, this); + + /** + * Node managers + * @type {object} + * @example {item.id: NodeManager} + */ + this.managers = {}; + + /** + * Managed outline sidebar + * @type {external:jQuery.fn.w2sidebar} + */ + this.outline = outline; + + }; + + /** + * Add layer to node manager + * @memberOf NodeManager.prototype + * @param {ol.layer.Layer|ol.Overlay} layer ol3 layer/overlay to add + * @private + * @returns {olexp.item.Item} Managed item for added layer + */ + NodeManager.prototype.addLayer = function(layer) + { + + // ================================================== + // Create managed item + // -------------------------------------------------- + + // Create item id, name, and properties + this.count += 1; + var id = this.id + '-' + this.count; + var name = 'Item ' + this.count; + var properties = layer.getProperties(); + if (properties.hasOwnProperty('name')) name = properties.name; + + // Store managed item + var item = new olexp.item.Item(id, name, layer); + this.items.push(item); + + // ================================================== + // Create w2ui node for item + // -------------------------------------------------- + var node = { + id : item.id, + img : item.icon, + text : item.name() + }; + + // ================================================== + // Add item to outline + // -------------------------------------------------- + + // Always prepend new node to top + var nodes = this.outline.get(this.id).nodes; + if (nodes.length === 0) + { + this.outline.add(this.id, [node]); + } + else + { + this.outline.insert(this.id, nodes[0].id, [node]); + } + + // ================================================== + // Check layer is group and create a sub-manager and add its + // layers + // -------------------------------------------------- + if (item.type === olexp.item.Type.GROUP) + { + + var layers = layer.getLayers(); + var manager = new NodeManager(item.id, + layers, + this.outline, + this.details); + + layers.forEach(function(childLayer) + { + manager.addLayer(childLayer); + }, this); + this.managers[item.id] = manager; + this.outline.expand(item.id); + + } + + return item; + + }; + + /** + * Get item based on id + * @memberOf NodeManager.prototype + * @param {string} id Item ID + * @param {boolean} recursive True for recursive search otherwise false + * @private + * @returns {null|olexp.item.Item} Managed item or null if not found + */ + NodeManager.prototype.getById = function(id, recursive) + { + + if (typeof recursive === 'undefined') recursive = true; + + var numItems = this.getSize(); + for (var i = 0; i < numItems; i++) + { + if (this.items[i].id === id) return this.items[i]; + if (this.items[i].type === olexp.item.Type.GROUP && recursive) + { + var item = this.managers[this.items[i].id].getById(id); + if (item === null) continue; + if (item.id === id) return item; + } + } + return null; + + }; + + /** + * Get item based on layer reference + * @memberOf NodeManager.prototype + * @param {ol.layer.Layer|ol.Overlay} layer ol3 layer/overlay + * @param {boolean} recursive True for recursive search otherwise false + * @private + * @returns {null|olexp.item.Item} Managed item or null if not found + */ + NodeManager.prototype.getByLayer = function(layer, recursive) + { + + if (typeof recursive === 'undefined') recursive = true; + + var numItems = this.getSize(); + for (var i = 0; i < numItems; i++) + { + if (this.items[i].layer === layer) return this.items[i]; + if (this.items[i].type === olexp.item.Type.GROUP && recursive) + { + var item = this.managers[this.items[i].id].getByLayer(layer); + if (item === null) continue; + if (item.layer === layer) return item; + } + } + return null; + }; + + /** + * Get size of manager list + * @memberOf NodeManager.prototype + * @private + * @returns {number} Size + */ + NodeManager.prototype.getSize = function() + { + return this.items.length; + }; + + /** + * Check if item is selected + * @memberOf NodeManager.prototype + * @param {string} id Item ID + * @private + * @returns {boolean} True if item is selected otherwise false + */ + NodeManager.prototype.isSelected = function(id) + { + return id === this.outline.selected; + }; + + + /** + * Check if layer should be hidden and not added to manager + * @memberOf NodeManager.prototype + * @param {ol.layer.Layer|ol.Overlay} layer Item ID + * @private + * @returns {boolean} True if item is hidden otherwise false + */ + NodeManager.prototype.isHidden = function(layer) + { + if (layer instanceof olexp.measure.Overlay) return true; + return false; + }; + + /** + * Move item down in map list + * @memberOf NodeManager.prototype + * @param {string} id Item ID + * @private + * @returns {null|boolean} True if moved, false is not moved, null if not + * found. + */ + NodeManager.prototype.moveDown = function(id) + { + + var item = this.getById(id, false); + + if (item !== null) + { + // Item found in this node + var movedItem = this.moveLayerUp(this.layers, item.layer); + if (movedItem) movedItem = this.moveItemDown(id); + return movedItem; + } + + // Check if item in child managers + var numItems = this.getSize(); + for (var i = 0; i < numItems; i++) + { + if (this.items[i].type === olexp.item.Type.GROUP) + { + var movedChild = this.managers[this.items[i].id].moveDown(id); + if (movedChild !== null) return movedChild; + } + } + + return null; + + }; + + /** + * Move item down + * @memberOf NodeManager.prototype + * @param {string} id Item ID + * @private + * @returns {boolean} True if moved otherwise false + */ + NodeManager.prototype.moveItemDown = function(id) + { + // Get node to move + var node = this.outline.get(id); + if (node === null) return false; + + // Get index in list + var nodes = this.outline.find(node.parent.id, + { + parent : node.parent + }); + var index = this.outline.get(node.parent.id, id, true); + if (index >= (nodes.length - 1)) return false; + + // Get node to swap + var nextId = nodes[index + 1].id; + var nextNode = nodes[index + 1]; + + // Check that nodes are in same parent node + if (node.parent !== nextNode.parent) return false; + + // Swap nodes + this.outline.remove(nextId); + this.outline.insert(node.parent, id, nextNode); + this.outline.select(id); + + return true; + }; + + /** + * Move item up + * @memberOf NodeManager.prototype + * @param {string} id Item ID + * @private + * @returns {boolean} True if moved otherwise false + */ + NodeManager.prototype.moveItemUp = function(id) + { + // Get node to move + var node = this.outline.get(id); + if (node === null) return false; + + // Get index in list + var nodes = this.outline.find(node.parent.id, + { + parent : node.parent + }); + var index = this.outline.get(node.parent.id, id, true); + if (index <= 0) return false; + + // Get node to swap + var prevId = nodes[index - 1].id; + var prevNode = nodes[index - 1]; + + // Check that nodes are in same parent node + if (node.parent !== prevNode.parent) return false; + + // Swap nodes + this.outline.remove(id); + this.outline.insert(node.parent, prevId, node); + this.outline.select(id); + + return true; + }; + + /** + * Move layer down + * @memberOf NodeManager.prototype + * @param {ol.Collection} layers Source layer list + * @param {ol.layer.Layer|ol.Overlay} layer Layer to move + * @private + * @returns {boolean} True if moved otherwise false + */ + NodeManager.prototype.moveLayerDown = function(layers, layer) + { + var index = olexp.util.indexOf(layers, layer); + var numLayers = this.layers.getLength(); + if (index < numLayers - 1) + { + var item = this.getByLayer(layer, false); + + // Set item to moving so it's not removed by the manager + item.moving(true); + layers.removeAt(index); + layers.insertAt(index + 1, layer); + item.moving(false); + + return true; + } + return false; + }; + + /** + * Move layer up + * @memberOf NodeManager.prototype + * @param {ol.Collection} layers Source layer list + * @param {ol.layer.Layer|ol.Overlay} layer Layer to move + * @private + * @returns {boolean} True if moved otherwise false + */ + NodeManager.prototype.moveLayerUp = function(layers, layer) + { + var index = olexp.util.indexOf(layers, layer); + if (index > 0) + { + var item = this.getByLayer(layer, false); + + // Set item to moving so it's not removed by the manager + item.moving(true); + layers.removeAt(index); + layers.insertAt(index - 1, layer); + item.moving(false); + + return true; + } + return false; + }; + + /** + * Move item up in map list + * @memberOf NodeManager.prototype + * @param {string} id Item ID + * @private + * @returns {null|boolean} True if moved, false if not moved, null if not + * found + */ + NodeManager.prototype.moveUp = function(id) + { + + var item = this.getById(id, false); + + if (item !== null) + { + // Item found in this node + var movedItem = this.moveLayerDown(this.layers, item.layer); + if (movedItem) movedItem = this.moveItemUp(id); + return movedItem; + } + + // Check if item in child managers + var numItems = this.getSize(); + for (var i = 0; i < numItems; i++) + { + if (this.items[i].type === olexp.item.Type.GROUP) + { + var movedChild = this.managers[this.items[i].id].moveUp(id); + if (movedChild !== null) return movedChild; + } + } + + return null; + + }; + + /** + * Remove listener + * @memberOf NodeManager.prototype + * @param {string} type The event type. + * @param {function} listener The listener function. + * @param {object} opt_this The object to use as this in listener. + * @private + */ + NodeManager.prototype.off = function(type, listener, opt_this) + { + this.event.off(type, listener, opt_this); + + // Remove listener from child managers + var numItems = this.getSize(); + for (var i = 0; i < numItems; i++) + { + if (this.items[i].type === olexp.item.Type.GROUP) + { + this.managers[this.items[i].id].off(type, listener, opt_this); + } + } + + }; + + /** + * Callback when layer changed + * @memberOf NodeManager.prototype + * @param {string} type The event type. + * @param {function} listener The listener function. + * @param {object} opt_this The object to use as this in listener. + * @private + */ + NodeManager.prototype.on = function(type, listener, opt_this) + { + this.event.on(type, listener, opt_this); + + // Register listener with child managers + var numItems = this.getSize(); + for (var i = 0; i < numItems; i++) + { + if (this.items[i].type === olexp.item.Type.GROUP) + { + this.managers[this.items[i].id].on(type, listener, opt_this); + } + } + + }; + + /** + * Callback when layer removed + * @memberOf NodeManager.prototype + * @param {olexp.item.Item} item OpenLayers Explorer Item + * @private + */ + NodeManager.prototype.onItemRemoved = function(item) + { + // Trigger item remove event + this.event.trigger('remove:item', item); + + // Remove item + if (this.isSelected(item.id)) + { + this.details.clear(); + } + this.remove(item); + }; + + /** + * Callback when layer changed + * @memberOf NodeManager.prototype + * @param {ol.ObjectEvent} event ol3 Layer change event + * @private + */ + NodeManager.prototype.onLayerChanged = function(event) + { + + // ================================================== + // Extract layers from change event + // -------------------------------------------------- + var changes = event.target; + + // ================================================== + // If layer is in map but not in manager then add + // -------------------------------------------------- + var numLayers = changes.getLength(); + for (var i = 0; i < numLayers; i++) + { + var layer = changes.item(i); + if (this.isHidden(layer)) continue; + var itemMap = this.getByLayer(layer); + if (itemMap === null) + { + this.addLayer(layer); + } + } + + // ================================================== + // If layer is in manager but not in map then remove + // -------------------------------------------------- + + var items = this.toList(); + var numItems = items.length; + for (var j = 0; j < numItems; j++) + { + var itemManager = items[j]; + + // Check if item is just being moved by user + if (itemManager.moving()) continue; + + var index = olexp.util.indexOf(this.layers, itemManager.layer); + if (index === -1) + { + this.onItemRemoved(itemManager); + } + } + + }; + + /** + * Remove layer from manager + * @memberOf NodeManager.prototype + * @param {olexp.item.Item} item Managed item to remove + * @private + * @returns {boolean} True if removed otherwise false + */ + NodeManager.prototype.remove = function(item) + { + + // ================================================== + // Remove layer from manager + // -------------------------------------------------- + var index = this.items.indexOf(item); + if (index !== -1) + { + this.items.splice(index, 1); + this.outline.remove(item.id); + return true; + } + + // ================================================== + // Check if item in child managers and remove + // -------------------------------------------------- + var numItems = this.getSize(); + for (var i = 0; i < numItems; i++) + { + if (this.items[i].type === olexp.item.Type.GROUP) + { + var removed = this.managers[this.items[i].id].remove(id); + if (removed) return true; + } + } + + return false; + + }; + + /** + * Remove item from map + * @memberOf NodeManager.prototype + * @private + * @param {null|ol.layer.Layer|ol.Overlay} Layer removed from map or null + * if not found + */ + NodeManager.prototype.removeFromMap = function(item) + { + var layerMap = this.layers.remove(item.layer); + if (typeof layerMap !== 'undefined') return layerMap; + + // ================================================== + // Check if item in child managers and remove + // -------------------------------------------------- + var numItems = this.getSize(); + for (var i = 0; i < numItems; i++) + { + if (this.items[i].type === olexp.item.Type.GROUP) + { + var layerChild = this.managers[this.items[i].id].removeFromMap(item); + if (layerChild !== null) return layerChild; + } + } + + return null; + + }; + + /** + * Set layers that are being managed + * @function setLayers + * @memberOf NodeManager.prototype + * @param {external:ol.Collection} layers New layer collection to monitor. + * @private + */ + NodeManager.prototype.setLayers = function(layers) + { + + // Remove old layers + this.layers.un('change:length', this.onLayerChanged, this); + while (this.items.length > 0) + { + this.onItemRemoved(this.items[this.items.length-1]); + } + + // Add new layers + this.layers = layers; + this.layers.on('change:length', this.onLayerChanged, this); + for (var j = 0; j < this.layers.getLength(); j++) + { + this.addLayer(this.layers.item(j)); + } + + }; + + /** + * Get items as list + * @memberOf NodeManager.prototype + * @private + * @returns {array} List of items + */ + NodeManager.prototype.toList = function() + { + + var items = []; + var numItems = this.getSize(); + for (var i = 0; i < numItems; i++) + { + items.push(this.items[i]); + } + return items; + + }; + + /** + * Node manager that synchronizes adding and removing items + * @function + * @memberOf olexp.manager + * @param {string} id Node id + * @param {external:ol.Map} map Managed map + * @param {external:jQuery.fn.w2sidebar} outline Managed outline sidebar + * @param {external:jQuery.fn.w2grid} details Details grid + * @public + */ + olexp.manager.NodeManager = function(id, map, outline, details) { + var manager = new NodeManager(id, map, outline, details); + return { + getById : manager.getById.bind(manager), + getByLayer : manager.getByLayer.bind(manager), + moveDown : manager.moveDown.bind(manager), + moveUp : manager.moveUp.bind(manager), + off : manager.off.bind(manager), + on : manager.on.bind(manager), + removeFromMap : manager.removeFromMap.bind(manager), + setLayers : manager.setLayers.bind(manager) + }; + }; + + return olexp; + +}(olexp || {})); + + +/** + * @namespace olexp.measure + */ +olexp.measure = olexp.measure || {}; + +//================================================== +// Measuring Tool +//-------------------------------------------------- +(function(olexp) { + + "use strict"; + + /** + * Enumeration of item measurements types. Object key where measurement is stored. + * @enum {string} + * @memberOf olexp.measure + * @public + * @readonly + */ + olexp.measure.properties = { + /** + * Area measurement property name + * @type string + */ + area: 'olexp-measure-property-area', + /** + * Length measurement property name + * @type string + */ + length: 'olexp-measure-property-length' + }; + + /** + * Measure tool Overlay hidden from map + * @param {object} options ol.Overlay options + * @private + */ + var Overlay = function (options) + { + ol.Overlay.call(this, options); + }; + Overlay.prototype = Object.create(ol.Overlay.prototype); + + /** + * Measuring Tool + * @param {ol.Map} map Map on which to render measurements + * @param {olexp.measure.Type} type Measuring tool type. + * (Default = olexp.measure.Type.LINE) + * @param {Object} settings olexp settings + * @private + */ + var Tool = function(map, type, settings) + { + + //================================================== + // Override Measure Tool option defaults + // with user provided values. + //-------------------------------------------------- + var olexpSettings = $.extend(true, {measure : { + Tool : { + continueLineMsg : 'Click to continue drawing the line', + continuePolygonMsg : 'Click to continue drawing the polygon', + helpTooltipOffset : [20, 0], + helpTooltipPositioning : 'center-left', + measuredStyle : new ol.style.Style({ + fill: new ol.style.Fill({ + color: 'rgba(255, 255, 255, 0.2)' + }), + stroke: new ol.style.Stroke({ + color: '#ffcc33', + width: 2 + }), + image: new ol.style.Circle({ + radius: 7, + fill: new ol.style.Fill({ + color: '#ffcc33' + }) + }) + }), + measuringStyle : new ol.style.Style({ + fill: new ol.style.Fill({ + color: 'rgba(255, 255, 255, 0.2)' + }), + stroke: new ol.style.Stroke({ + color: 'rgba(0, 0, 0, 0.5)', + lineDash: [10, 10], + width: 2 + }), + image: new ol.style.Circle({ + radius: 5, + stroke: new ol.style.Stroke({ + color: 'rgba(0, 0, 0, 0.7)' + }), + fill: new ol.style.Fill({ + color: 'rgba(255, 255, 255, 0.2)' + }) + }) + }), + measureTooltipOffset : [0, -20], + measureTooltipPositioning : 'bottom-center', + messageStart : 'Click to start drawing. Double click to stop.' + }}}, settings); + + /** + * Measurement control settings + * @field + * @private + * @type {Object} + */ + this.settings = olexpSettings.measure.Tool; + + /** + * Message to show when the user is drawing a line. + * @type {string} + */ + this.continueLineMsg = this.settings.continueLineMsg; + + /** + * Message to show when the user is drawing a polygon. + * @type {string} + */ + this.continuePolygonMsg = this.settings.continuePolygonMsg; + + /** + * Keeps track of number of measurements taken + * @type {Number} + */ + this.count = 0; + + /** + * Draw interaction + * @type {ol.interaction.Draw} + */ + this.draw = null; + + /** + * Drawing is active + * @type {boolean} + */ + this.drawing = false; + + /** + * Do geodesic measurement + * @type {boolean} + */ + this.geodesic = false; + + /** + * Overlay to show the help messages. + * @type {ol.Overlay} + */ + this.helpTooltip = null; + + /** + * The help tooltip element. + * @type {Element} + */ + this.helpTooltipElement = null; + + /** + * Map on which to render measurements + * @type {ol.Map} + */ + this.map = map; + + /** + * Overlay to show the measurement. + * @type {ol.Overlay} + */ + this.measureTooltip = null; + + /** + * The measure tooltip element. + * @type {Element} + */ + this.measureTooltipElement = null; + + /** + * Callback when pointer moves + * @type {function} + */ + this.pointerMoveCallback = this.onPointerMove.bind(this); + + /** + * Currently drawn feature. + * @type {external:ol.Feature} + */ + this.sketch = null; + + /** + * Draw vector source. + * @type {ol.source.Vector} + */ + this.source = null; + + /** + * WGS84 ellipsoid on which to perform measurements + * @type {ol.Sphere} + */ + this.sphere = new ol.Sphere(6378137); + + /** + * Measurement tool type + * @type {olexp.measure.Type} + */ + this.type = type; + + /** + * Draw vector. + * @type {ol.layer.Vector} + */ + this.vector = null; + + }; + + /** + * Creates a new help tooltip + * @memberOf Tool.prototype + * @private + */ + Tool.prototype.createHelpTooltip = function () + { + + // ================================================== + // Remove existing help overlay element + // -------------------------------------------------- + if (this.helpTooltipElement) + { + this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement); + } + + // ================================================== + // Create new help tooltip + // -------------------------------------------------- + this.helpTooltipElement = document.createElement('div'); + this.helpTooltipElement.className = 'olexp-measure olexp-measure-hidden'; + this.helpTooltip = new olexp.measure.Overlay({ + element: this.helpTooltipElement, + offset: this.settings.helpTooltipOffset, + positioning: this.settings.helpTooltipPositioning + }); + + // ================================================== + // Add overlay to map + // -------------------------------------------------- + this.map.addOverlay(this.helpTooltip); + + }; + + /** + * Creates a new measure vector + * @memberOf Tool.prototype + * @private + */ + Tool.prototype.createMeasureVector = function () + { + + this.vector = new ol.layer.Vector({ + source: this.source, + style: this.settings.measuredStyle + }); + this.vector.set('name','Measurement #' + (this.count + 1)); + this.map.addLayer(this.vector); + + }; + + /** + * Creates a new measure tooltip + * @memberOf Tool.prototype + * @private + */ + Tool.prototype.createMeasureTooltip = function () + { + + // ================================================== + // Remove existing help overlay element + // -------------------------------------------------- + if (this.measureTooltipElement) + { + this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement); + } + + // ================================================== + // Create new measure tooltip + // -------------------------------------------------- + this.measureTooltipElement = document.createElement('div'); + this.measureTooltipElement.className = 'olexp-measure olexp-measure-active'; + this.measureTooltip = new olexp.measure.Overlay({ + element: this.measureTooltipElement, + offset: this.settings.measureTooltipOffset, + positioning: this.settings.measureTooltipPositioning + }); + this.measureTooltip.set('name','Measurement #' + (this.count+1)); + + // ================================================== + // Add overlay to map + // -------------------------------------------------- + this.map.addOverlay(this.measureTooltip); + + }; + + /** + * Format length output + * @memberOf Tool.prototype + * @param {ol.geom.Polygon} polygon + * @private + * @return {string} + */ + Tool.prototype.formatArea = function (polygon) + { + + var area = 0; + if (this.geodesic) + { + + var projection = this.map.getView().getProjection(); + var geometry = polygon.clone().transform(projection, 'EPSG:4326'); + var coordinates = geometry.getLinearRing(0).getCoordinates(); + area = Math.abs(this.sphere.geodesicArea(coordinates)); + + } + else + { + area = polygon.getArea(); + } + + var output = ''; + if (area > 10000) + { + output = (Math.round(area / 1000000 * 100) / 100) + ' km2'; + } + else + { + output = (Math.round(area * 100) / 100) + ' m2'; + } + + return output; + + }; + + /** + * Format length output + * @memberOf Tool.prototype + * @param {ol.geom.LineString} line + * @private + * @return {string} + */ + Tool.prototype.formatLength = function (line) + { + + var length = 0; + if (this.geodesic) + { + var projection = this.map.getView().getProjection(); + var coordinates = line.getCoordinates(); + var numCoordinates = coordinates.length; + for (var i = 0; i < numCoordinates - 1; ++i) { + var c1 = ol.proj.transform(coordinates[i], projection, 'EPSG:4326'); + var c2 = ol.proj.transform(coordinates[i + 1], projection, 'EPSG:4326'); + length += this.sphere.haversineDistance(c1, c2); + } + } + else + { + length = Math.round(line.getLength() * 100) / 100; + } + + var output; + if (length > 100) + { + output = (Math.round(length / 1000 * 100) / 100) + ' ' + 'km'; + } + else + { + output = (Math.round(length * 100) / 100) + ' ' + 'm'; + } + + return output; + + }; + + /** + * Handle pointer move. + * @memberOf Tool.prototype + * @param {ol.MapBrowserEvent} event + * @private + */ + Tool.prototype.onPointerMove = function (event) + { + + if (event.dragging) + { + return; + } + + var message = this.settings.messageStart; + + if (this.sketch) + { + var geometry = this.sketch.getGeometry(); + if (geometry instanceof ol.geom.Polygon) + { + message = this.continuePolygonMsg; + } + else if (geometry instanceof ol.geom.LineString) + { + message = this.continueLineMsg; + } + } + + this.helpTooltipElement.innerHTML = message; + this.helpTooltip.setPosition(event.coordinate); + + $(this.helpTooltipElement).removeClass('olexp-measure-hidden'); + + }; + + /** + * Enable/disable tool + * @memberOf Tool.prototype + * @param {boolean} enable True if measurement tool is enabled otherwise false + * @private + */ + Tool.prototype.setEnable = function (enable) + { + if (enable) + { + this.map.on('pointermove', this.pointerMoveCallback); + } + else + { + this.map.un('pointermove', this.pointerMoveCallback); + } + this.setInteraction(enable); + }; + + /** + * Add drawing interaction to map + * @memberOf Tool.prototype + * @param {boolean} enable True if drawing should be set otherwise false + * @private + */ + Tool.prototype.setInteraction = function (enable) + { + + if (typeof enable === 'undefined') enable = true; + + var me = this; + + // ================================================== + // Remove interactions and hidden overlays + // -------------------------------------------------- + if (this.draw) + { + this.map.removeInteraction(this.draw); + } + + if (enable) + { + $(this.helpTooltipElement).removeClass('olexp-measure-hidden'); + } + else + { + $(this.helpTooltipElement).addClass('olexp-measure-hidden'); + + // If measure tool is disabled while drawing then clean up vector + if (this.drawing) + { + // Remove drawing vector + this.map.removeLayer(this.vector); + this.vector = null; + + // Remove measure tooltip + this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement); + this.measureTooltipElement = null; + + this.drawing = false; + } + return; + } + + // ================================================== + // Define drawing interaction + // -------------------------------------------------- + this.source = new ol.source.Vector(); + this.draw = new ol.interaction.Draw({ + source: this.source, + type: this.type, + style: this.settings.measuringStyle + }); + + this.map.addInteraction(this.draw); + + // ================================================== + // Define tooltips + // -------------------------------------------------- + this.createMeasureTooltip(); + this.createHelpTooltip(); + + // ================================================== + // Define behavior when drawing starts and ends + // -------------------------------------------------- + var listener = null; + this.draw.on('drawstart', + function(event) + { + this.drawing = true; + + // ================================================== + // Create measurement vector + // -------------------------------------------------- + me.createMeasureVector(); + + // ================================================== + // Update measurement tooltip when on change + // -------------------------------------------------- + var tooltipCoord = event.coordinate; + me.sketch = event.feature; + listener = me.sketch.getGeometry().on('change', + function(event) + { + // ================================================== + // Compute new measurement + // -------------------------------------------------- + var output = ''; + var geometry = event.target; + if (geometry instanceof ol.geom.Polygon) + { + output = me.formatArea(geometry); + tooltipCoord = geometry.getInteriorPoint().getCoordinates(); + } + else if (geometry instanceof ol.geom.LineString) + { + output = me.formatLength(geometry); + tooltipCoord = geometry.getLastCoordinate(); + } + me.measureTooltipElement.innerHTML = output; + me.measureTooltip.setPosition(tooltipCoord); + }); + }, this); + + this.draw.on('drawend', + function(event) + { + this.drawing = false; + me.count += 1; + + // ================================================== + // Store final measurement as layer attribute + // -------------------------------------------------- + var geometry = me.sketch.getGeometry(); + var property = {}; + if (geometry instanceof ol.geom.Polygon) + { + property[olexp.measure.properties.area] = me.formatArea(geometry); + me.vector.setProperties(property); + } + else if (geometry instanceof ol.geom.LineString) + { + property[olexp.measure.properties.length] = me.formatLength(geometry); + me.vector.setProperties(property); + } + + // ================================================== + // Unset sketch + // -------------------------------------------------- + me.sketch = null; + + // ================================================== + // Unset tooltip so that a new one can be created + // -------------------------------------------------- + me.measureTooltipElement.parentNode.removeChild(me.measureTooltipElement); + me.measureTooltipElement = null; + me.createMeasureTooltip(); + + ol.Observable.unByKey(listener); + + me.setInteraction(true); + + }, this); + + }; + + /** + * Set measurement type + * @memberOf Tool.prototype + * @param {olexp.measure.Type} type Measuring tool type + * @private + */ + Tool.prototype.setType = function (type) + { + this.type = type; + }; + + /** + * Measurement tool + * @memberOf olexp.measure + * @param {external:ol.Map} map Source map + * @param {Object} options Measurement options + * @param {olexp.measure.Type} options.type Type of measurement to compute + * @param {olexp.ExplorerSettings} options.settings Explorer settings + * @public + */ + olexp.measure.Tool = function(map, options) { + + if (typeof options === 'undefined') options = {}; + if (typeof options.type === 'undefined') options.type = olexp.measure.Type.LINE; + if (typeof options.settings === "undefined") options.settings = {}; + + var tool = new Tool(map, options.type, options.settings); + + /** + * olexp.measure.Tool API + */ + return { + setEnable: function (enable) { + tool.setEnable(enable); + }, + setType: function (type) { + tool.setType(type); + } + }; + + }; + + /** + * Enumeration of allowable measurement types + * @enum {string} + * @memberOf olexp.measure + * @public + * @readonly + */ + olexp.measure.Type = { + /** + * Area measurement type + * @type string + */ + AREA : 'Polygon', + /** + * Line measurement type + * @type string + */ + LINE : 'LineString' + }; + + /** + * Measurement tool overlay + * @memberOf olexp.measure + * @param {object} options ol.Overlay options + * @public + */ + olexp.measure.Overlay = Overlay; + + return olexp; + +}(olexp || {})); + + +/** + * @namespace olexp.menu + */ +olexp.menu = olexp.menu || {}; + +//================================================== +// Properties menu item +//-------------------------------------------------- +(function(olexp) { + + "use strict"; + + /** + * Properties menu item + * @param {olexp.manager.Manager} manager Explorer manager + * @param {olexp.ExplorerSettings} settings olexp settings + * @private + */ + var Properties = function(manager, settings) + { + + var olexpSettings = $.extend(true, {menu : { + Properties : { + field : 35, + form : {}, + popup : { + height : 130, + style : 'width: 100%; height: 100%;', + title : 'Edit Layer', + width : 365 + }, + span : 4, + text : 'Properties' + }}}, settings); + + /** + * Menu item icon + * @field + * @private + * @type {string} + */ + this.icon = 'olexp-menu-properties'; + + /** + * Form DOM id + * @field + * @private + * @type {string} + */ + this.form = settings.prefix + '-menu-properties-form'; + + /** + * Menu DOM id + * @field + * @private + * @type {string} + */ + this.id = settings.prefix + '-menu-properties'; + + /** + * Explorer manager + * @field + * @private + * @type {olexp.manager.Manager} + */ + this.manager = manager; + + /** + * Menu w2ui name + * @field + * @private + * @type {string} + */ + this.name = 'layerform'; + + /** + * Properties menu settings + * @field + * @private + * @type {Object} + */ + this.settings = olexpSettings.menu.Properties; + + }; + + /** + * Callback when properties menu item is clicked + * @memberOf Properties.prototype + * @param {external:jQuery.fn.w2sidebar.onMenuClick} event Menu click event + * @private + */ + Properties.prototype.onClick = function(event) + { + + var me = this; + + // ================================================== + // Extract node item id + // -------------------------------------------------- + var id = event.target; + + // ================================================== + // Extract item to be edited + // -------------------------------------------------- + var item = this.manager.getById(id); + var record = item.getProperties(); + + // ================================================== + // Create form fields and adjust form height per field + // -------------------------------------------------- + var formHeight = this.settings.popup.height; + var fieldHeight = this.settings.field; + var fields = []; + + // Add item name field + formHeight += fieldHeight; + fields.push({ + field: 'name', + html: + { + caption : 'Name', + span : this.settings.span + }, + required: true, + type: 'text' + }); + + // Add numeric fields + var propertyTypes = item.getPropertyTypes(); + var numerics = $.map(propertyTypes, function(value) { + return value.title; + }); + for (var i = 0; i < numerics.length; i++) + { + formHeight += fieldHeight; + fields.push({ + field: numerics[i].toLowerCase(), + html: + { + caption : numerics[i], + span : this.settings.span + }, + required: true, + type: 'float' + }); + } + + // ================================================== + // Function to process form changes + // -------------------------------------------------- + var onChanges = function(changes) + { + me.manager.updateItem(id, changes); + }; + + // ================================================== + // Process popup form + // -------------------------------------------------- + + var formOptions = $.extend(this.settings.form, { + fields : fields, + name : this.name, + record : record + }); + + var popupOptions = $.extend($.extend({}, this.settings.popup), { + height : formHeight + }); + + olexp.util.popup(this.form, onChanges, formOptions, popupOptions); + + }; + + /** + * Properties menu item + * @memberOf olexp.menu + * @param {olexp.manager.Manager} manager Explorer manager + * @param {olexp.ExplorerSettings} settings olexp settings + * @public + */ + olexp.menu.Properties = function(manager, settings) { + + var control = new Properties(manager, settings); + + return { + menu: { + id : control.id, + img : control.icon, + text : control.settings.text + }, + click: function(event) { + control.onClick(event); + } + }; + + }; + + return olexp; + +}(olexp || {})); + +//================================================== +// Remove menu item +//-------------------------------------------------- +(function(olexp) { + + /** + * Remove menu item + * @param {olexp.manager.Manager} manager Explorer manager + * @param {olexp.ExplorerSettings} settings olexp settings + * @private + */ + var Remove = function(manager, settings) + { + + var olexpSettings = $.extend(true, {menu : { + Remove : { + text : 'Remove' + }}}, settings); + + /** + * Menu item icon + * @field + * @private + * @type {string} + */ + this.icon = 'olexp-menu-remove'; + + /** + * Menu DOM id + * @field + * @private + * @type {string} + */ + this.id = settings.prefix + '-menu-remove'; + + /** + * Explorer manager + * @field + * @private + * @type {olexp.manager.Manager} + */ + this.manager = manager; + + /** + * Remove menu settings + * @field + * @private + * @param {Object} settings + */ + this.settings = olexpSettings.menu.Remove; + + }; + + /** + * Callback when properties menu item is clicked + * @memberOf Remove.prototype + * @param {external:jQuery.fn.w2sidebar.onMenuClick} event Menu click event + * @private + */ + Remove.prototype.onClick = function(event) + { + + var me = this; + + // ================================================== + // Extract node item id + // -------------------------------------------------- + var id = event.target; + + // ================================================== + // Extract item to be removes + // -------------------------------------------------- + var item = this.manager.getById(id); + + // Confirm user wants to delete item + // Remove item from map and manager + w2confirm('Do you want to delete "' + item.name() + '"?') + .yes(function () { + me.manager.removeFromMap(item); + }); + + }; + + /** + * Remove menu item + * @memberOf olexp.menu + * @param {olexp.manager.Manager} manager Explorer manager + * @param {olexp.ExplorerSettings} settings olexp settings + * @public + */ + olexp.menu.Remove = function(manager, settings) { + + var control = new Remove(manager, settings); + + return { + menu: { + id : control.id, + img : control.icon, + text : control.settings.text + }, + click: function(event) { + control.onClick(event); + } + }; + + }; + + return olexp; + +}(olexp || {})); + +//================================================== +// Zoom menu item +//-------------------------------------------------- +(function(olexp) { + + /** + * Zoom menu item + * @param {olexp.manager.Manager} manager Explorer manager + * @param {olexp.ExplorerSettings} settings olexp settings + * @private + */ + var Zoom = function(manager, settings) + { + + var olexpSettings = $.extend(true, {menu : { + Zoom : { + text : 'Zoom' + }}}, settings); + + /** + * Menu item icon + * @field + * @private + * @type {string} + */ + this.icon = 'olexp-menu-zoom'; + + /** + * Menu DOM id + * @field + * @private + * @type {string} + */ + this.id = settings.prefix + '-menu-zoom'; + + /** + * Explorer + * @field + * @private + * @type {olexp.manager.Manager} + */ + this.manager = manager; + + /** + * Zoom menu settings + * @field + * @private + * @param {Object} settings + */ + this.settings = olexpSettings.menu.Zoom; + + }; + + /** + * Callback when properties menu item is zoomed in + * @memberOf Zoom.prototype + * @param {external:jQuery.fn.w2sidebar.onMenuClick} event Menu click event + * @private + */ + Zoom.prototype.onClick = function(event) + { + + // ================================================== + // Extract node item id + // -------------------------------------------------- + var id = event.target; + + // ================================================== + // Zoom to item layer + // -------------------------------------------------- + this.manager.zoomTo(id); + + }; + + /** + * Zoom menu item + * @memberOf olexp.menu + * @param {olexp.manager.Manager} manager Explorer manager + * @param {olexp.ExplorerSettings} settings olexp settings + * @public + */ + olexp.menu.Zoom = function(manager, settings) { + + var control = new Zoom(manager, settings); + + return { + menu: { + id : control.id, + img : control.icon, + text : control.settings.text + }, + click: function(event) { + control.onClick(event); + } + }; + + }; + + return olexp; + +}(olexp || {})); + + +/** + * @description olexp specific OpenLayers 3 classes + * @namespace olexp.ol + */ +olexp.ol = olexp.ol || {}; + +//================================================== +// Toolbar show Control +//-------------------------------------------------- +(function(olexp) { + + "use strict"; + + /** + * Control to show toolbar + * @param {olexp.Explorer} explorer Source explorer + * @param {olexp.ExplorerSettings} settings olexp settings + * @private + */ + var ToolbarShow = function(explorer, settings) + { + + //================================================== + // Override Toolbar Show option defaults + // with user provided values. + //-------------------------------------------------- + var olexpSettings = $.extend(true, {ol : { + ToolbarShow : { + html : 'T', + title : 'Show toolbar' + }}}, settings); + + /** + * ol ToolbarShow control settings + * @field + * @private + * @param {Object} settings + */ + this.settings = olexpSettings.ol.ToolbarShow; + + /** + * Source explorer + * @field + * @private + * @type {olexp.Explorer} + */ + this.explorer = explorer; + + // Define control button + var button = document.createElement('button'); + button.innerHTML = this.settings.html; + button.title = this.settings.title; + button.addEventListener('click', this.show.bind(this), false); + button.addEventListener('touchstart', this.show.bind(this), false); + + // Define control button wrapper div + var element = document.createElement('div'); + element.id = settings.prefix + '-ol-toolbar-show'; + element.className = 'olexp-ol-toolbar-show ol-unselectable ol-control'; + element.appendChild(button); + + ol.control.Control.call(this, {element: element}); + + }; + ol.inherits(ToolbarShow, ol.control.Control); + + + /** + * Show toolbar + * @private + */ + ToolbarShow.prototype.show = function() + { + this.explorer.layout.show(this.explorer.options.toolbar.type); + this.setMap(null); + }; + + /** + * Control to set toolbar visibility + * @memberOf olexp.ol + * @param {olexp.Explorer} explorer Source explorer + * @param {object} options Control options + * @param {boolean} options.hidden True if toolbar is initially hidden + * @param {olexp.ExplorerSettings} options.settings Explorer settings + * @public + * @returns {external:jQuery.fn.w2toolbar.properties} ToolbarShow toolbar + * control + */ + olexp.ol.ToolbarShow = function(explorer, options) { + + var opts = $.extend({hidden: false}, options); + + var control = new ToolbarShow(explorer, opts.settings); + if (opts.hidden) control.setMap(explorer.map); + return control; + + }; + + return olexp; + +}(olexp || {})); + + +/** + * @namespace olexp.selection + */ +olexp.selection = olexp.selection || {}; + +//================================================== +// Selection Tool +//-------------------------------------------------- +(function(olexp) { + + "use strict"; + + /** + * Handles the selection of features on the map + * @param {ol.Map} map Managed map + * @param {external:jQuery.fn.w2grid} details Details grid + * @private + */ + var Feature = function(map, details) + { + + /** + * Details grid + * @type {external:jQuery.fn.w2grid} + */ + this.details = details; + + /** + * Selection interaction + * @type {external:ol.interaction.Select} + */ + this.interaction = new ol.interaction.Select(); + + /** + * Managed map + * @type {ol.Map} + */ + this.map = map; + + // ================================================== + // Add callback for feature selection + // -------------------------------------------------- + var me = this; + this.interaction.on('select', function(event) { + + if (event.selected.length === 1) + { + var feature = event.selected[0]; + var properties = olexp.util.toProperties(feature); + for (var name in properties) + { + if (typeof properties[name] !== 'boolean' && + typeof properties[name] !== 'number' && + typeof properties[name] !== 'string') + { + delete properties[name]; + } + } + var records = olexp.util.toRecords(properties); + me.details.clear(); + me.details.add(records); + } + + }); + + }; + + /** + * Enable feature selection + * @memberOf Feature.prototype + * @param {boolean} enable True if selection should be enabled otherwise false + */ + Feature.prototype.setEnable = function(enable) + { + if (enable) + { + this.map.addInteraction(this.interaction); + } + else + { + this.map.removeInteraction(this.interaction); + } + }; + + /** + * Selection tool + * @memberOf olexp.selection + * @param {external:ol.Map} map Managed map + * @param {external:jQuery.fn.w2grid} details Details grid + * @public + * @returns {olexp.selection.Feature} Feature selector + */ + olexp.selection.Feature = function(map, details) { + + var selector = new Feature(map, details); + + /** + * @description The objects exposed by the olexp.selection.Feature API + * @typedef {object} Feature + * @memberOf olexp.selection + * @property {function} setEnable Enable/disable feature selection + */ + return { + setEnable: function (enable) + { + selector.setEnable(enable); + } + }; + + }; + + return olexp; + +}(olexp || {})); + + +/** + * @namespace olexp.util + */ +olexp.util = olexp.util || {}; + +//================================================== +// Utility tools +//-------------------------------------------------- +(function(olexp) { + + "use strict"; + + /** + * Utility tools + * @param {olexp.ExplorerSettings} settings olexp settings + * @private + */ + var Util = function(settings) + { + + //================================================== + // Override Util option defaults + // with user provided values. + //-------------------------------------------------- + var olexpSettings = $.extend(true, {util : {Util : { + Cluster : function(size) + { + var style = [new ol.style.Style({ + image : new ol.style.Circle({ + radius : 10, + stroke : new ol.style.Stroke({ + color : '#ffffff' + }), + fill : new ol.style.Fill({ + color : '#3399CC' + }) + }), + text : new ol.style.Text({ + text : size.toString(), + fill : new ol.style.Fill({ + color : '#ffffff' + }) + }) + })]; + return style; + }, + Point : [new ol.style.Style({ + image : new ol.style.Circle({ + fill : new ol.style.Fill({ + color : 'rgba(255,255,0,0.5)' + }), + radius : 5, + stroke : new ol.style.Stroke({color : '#ff0', + width : 1}) + }) + })], + LineString : [new ol.style.Style({ + stroke : new ol.style.Stroke({ + color : '#f00', + width : 3 + }) + })], + Polygon : [new ol.style.Style({ + fill : new ol.style.Fill({ + color : 'rgba(0,255,255,0.5)' + }), + stroke : new ol.style.Stroke({ + color : '#0ff', + width : 1 + }) + })], + MultiPoint : [new ol.style.Style({ + image : new ol.style.Circle({ + fill : new ol.style.Fill({ + color : 'rgba(255,0,255,0.5)' + }), + radius : 5, + stroke : new ol.style.Stroke({ + color : '#f0f', + width : 1 + }) + }) + })], + MultiLineString : [new ol.style.Style({ + stroke : new ol.style.Stroke({ + color : '#0f0', + width : 3 + }) + })], + MultiPolygon : [new ol.style.Style({ + fill : new ol.style.Fill({ + color : 'rgba(0,0,255,0.5)' + }), + stroke : new ol.style.Stroke({ + color : '#00f', + width : 1 + }) + })] + }}}, settings); + + /** + * Util settings + * @field + * @private + * @param {Object} settings + */ + this.settings = olexpSettings.util.Util; + + /** + * Default vector styles + * @field + * @private + * @param {Object} defaultStyle + */ + this.defaultStyle = + { + 'Point' : this.settings.Point, + 'LineString' : this.settings.LineString, + 'Polygon' : this.settings.Polygon, + 'MultiPoint' : this.settings.MultiPoint, + 'MultiLineString' : this.settings.MultiLineString, + 'MultiPolygon' : this.settings.MultiPolygon + }; + + /** + * Cache for cluster styles + * @field + * @private + * @param {Object} clusterStyleCache + */ + this.clusterStyleCache = {}; + + }; + + /** + * Add vector layer to map + * @memberOf Util.prototype + * @param {external:ol.Map} map Source ol3 map + * @param {string} name Name of new vector layer + * @param {array} features Array of features + * @param {boolean} cluster True if features should be clustered otherwise false + * @public + */ + Util.prototype.addLayerVector = function(map, + name, + features, + cluster) + { + + if (typeof cluster === 'undefined') cluster = true; + + var me = this; + + // Detect if clustering is on for non-points and disable clustering + for (var i = 0; i < features.length; i++) + { + var geometry = features[i].getGeometry(); + if (typeof geometry === 'undefined' || + geometry.getType() !== 'Point') + { + cluster = false; + break; + } + } + + // Build layer source + var source = new ol.source.Vector({ + features: features + }); + + if (cluster) + { + source = new ol.source.Cluster({ + source: source + }); + } + + // Build layer style + var style = function(feature, resolution) + { + var styleFunction = feature.getStyleFunction(); + if (styleFunction) + { + return styleFunction.call(feature, resolution); + } + else + { + return me.defaultStyle[feature.getGeometry().getType()]; + } + }; + + if (cluster) + { + style = function(feature, resolution) + { + return me.getClusterStyle(feature); + }; + } + + // Add layer to map + var layer = new ol.layer.Vector({ + source : source, + style : style + }); + layer.set('name', name); + map.getLayers().push(layer); + + }; + + /** + * Get feature style + * @memberOf Util.prototype + * @param {external:ol.Feature} feature Feature to style + * @public + * @returns {ol.Style} Cluster style + */ + Util.prototype.getClusterStyle = function(feature) + { + + var size = feature.get('features').length; + var style = this.clusterStyleCache[size]; + if (!style) + { + style = this.settings.Cluster(size); + this.clusterStyleCache[size] = style; + } + + return style; + + }; + + /** + * Create map controls + * @memberOf Util.prototype + * @public + * @returns {object} Object of ol.control objects by key name + */ + Util.prototype.getControls = function() + { + + var controls = { + fullscreen : new ol.control.FullScreen(), + mouseposition : new ol.control.MousePosition({ + coordinateFormat : ol.coordinate.createStringXY(6), + projection : 'EPSG:4326'}), + overviewmap : new ol.control.OverviewMap(), + rotate : new ol.control.Rotate(), + scaleline : new ol.control.ScaleLine(), + zoom : new ol.control.Zoom(), + zoomslider : new ol.control.ZoomSlider(), + zoomtoextent : new ol.control.ZoomToExtent() + }; + + return controls; + + }; + + /** + * Create drag and drop interaction + * @memberOf Util.prototype + * @param {ol.Map} map Source map + * @public + * @returns {ol.interaction.DragAndDrop} ol3 drag and drop interaction + */ + Util.prototype.getDragAndDrop = function(map) + { + + var me = this; + + var interaction = new ol.interaction.DragAndDrop({ + formatConstructors: $.map(olexp.util.FileTypes, function(o) { + return o.format; + }) + }); + + interaction.on('addfeatures', function(event) { + + // Get filename and remove any extensions + var filename = event.file.name.replace(/\.[^/.]+$/, ""); + + me.addLayerVector(map, filename, event.features); + + }); + + return interaction; + + }; + + /** + * Create a new graticule + * @memberOf Util.prototype + * @param {external:ol.Map} map Source map + * @param {object} options ol.Graticule constructor options + * @public + * @returns {external:ol.Graticule} New graticule based on settings + */ + Util.prototype.getGraticule = function(map, options) + { + + var opts = $.extend($.extend({}, options), + {color : '#' + options.color}); + var graticule = new ol.Graticule({ + map : map, + strokeStyle : new ol.style.Stroke(opts) + }); + graticule.olexp_record = $.extend({enable : (map===null ? false : true)}, + options); + + return graticule; + + }; + + /** + * Create map interactions + * @memberOf Util.prototype + * @param {external:ol.Map} map Source map + * @public + * @returns {object} Object of ol.interaction objects by key name + */ + Util.prototype.getInteractions = function(map) + { + + var interactions = { + draganddrop : this.getDragAndDrop(map) + }; + + return interactions; + + }; + + /** + * Get object of ol3 tile types + * @memberOf Util.prototype + * @public + * @returns {object} Object of ol.source objects + */ + Util.prototype.getTileTypes = function() + { + + // ================================================== + // Define tile types object + // -------------------------------------------------- + var tileTypes = {}; + + // ================================================== + // Define Bing tiles + // -------------------------------------------------- + + var bingKey = 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3'; + var bingMaxZoom = 19; + + tileTypes.bingAerial = + { + 'class' : ol.source.BingMaps, + name : 'Bing Maps (Aerial)', + settings : + { + imagerySet : 'Aerial', + key : bingKey, + maxZoom : bingMaxZoom + } + }; + + tileTypes.bingAerialLabels = + { + 'class' : ol.source.BingMaps, + name : 'Bing Maps (Aerial with Labels)', + settings : + { + imagerySet : 'AerialWithLabels', + key : bingKey, + maxZoom : bingMaxZoom + } + }; + + tileTypes.bingRoad = + { + 'class' : ol.source.BingMaps, + name : 'Bing Maps (Road)', + settings : + { + imagerySet : 'Road', + key : bingKey, + maxZoom : bingMaxZoom + } + }; + + // ================================================== + // Define MapQuest tiles + // -------------------------------------------------- + + tileTypes.mapQuestAerial = + { + 'class' : ol.source.MapQuest, + name : 'Map Quest (Aerial)', + settings : + { + layer : 'sat' + } + }; + + tileTypes.mapQuestAerialLabels = + { + 'class' : ol.source.MapQuest, + name : 'Map Quest (Labels)', + settings : + { + layer : 'hyb' + } + }; + + tileTypes.mapQuestRoad = + { + 'class' : ol.source.MapQuest, + name : 'Map Quest (Road)', + settings : + { + layer : 'osm' + } + }; + + // ================================================== + // Define OpenStreetMap tiles + // -------------------------------------------------- + + tileTypes.osm = + { + 'class' : ol.source.OSM, + name : 'OpenStreetMap', + settings : {} + }; + + // ================================================== + // Define Stamen tiles + // -------------------------------------------------- + + tileTypes.stamenTerrain = + { + 'class' : ol.source.Stamen, + name : 'Stamen (Terrain)', + settings : + { + layer: 'terrain' + } + }; + + tileTypes.stamenToner = + { + 'class' : ol.source.Stamen, + name : 'Stamen (Toner)', + settings : + { + layer: 'toner' + } + }; + + tileTypes.stamenWater = + { + 'class' : ol.source.Stamen, + name : 'Stamen (Water Color)', + settings : + { + layer : 'watercolor' + } + }; + + return tileTypes; + + }; + + /** + * Supported ol3 file types + * @memberOf olexp.util + * @public + * @readonly + * @returns {object} ol3 file types + */ + olexp.util.FileTypes = { + gpx : { + extensions: ['gpx'], + format : ol.format.GPX, + name : 'GPX' + }, + igc : { + extensions: ['igc'], + format : ol.format.IGC, + name : 'IGC' + }, + json : { + extensions: ['json', 'geojson'], + format : ol.format.GeoJSON, + name : 'GeoJSON' + }, + kml : { + extensions: ['kml'], + format : ol.format.KML, + name : 'KML' + } + }; + + /** + * Find feature reader based on filename extension + * @memberOf olexp.util + * @param {string} filename Filename to be read + * @public + * @returns {external:ol.format.Feature} File reader + */ + olexp.util.getReader = function(filename) + { + + var extension = filename.substring(filename.lastIndexOf(".")+1).toLowerCase(); + var types = Object.keys(olexp.util.FileTypes); + for (var i = 0; i < types.length; i++) + { + var type = olexp.util.FileTypes[types[i]]; + var extensions = type.extensions; + for (var j = 0; j < extensions.length; j++) + { + if (extension === extensions[j]) + { + return new type.format(); + } + } + } + return null; + + }; + + /** + * Returns the index of the layer within the collection. + * @function + * @memberOf olexp.util + * @param {external:ol.Collection} layers Map layers + * @param {external:ol.layer.Layer|external:ol.Overlay} layer Layer to find + * @public + * @returns {number} Index of layer + */ + olexp.util.indexOf = function(layers, layer) + { + var length = layers.getLength(); + for (var i = 0; i < length; i++) + { + if (layer === layers.item(i)) + { + return i; + } + } + return -1; + }; + + /** + * Create and process popup form + * @function + * @memberOf olexp.util + * @param {string} id DOM id + * @param {function} onChanges Function that processes w2ui form changes + * @param {external:jQuery.fn.w2form.properties} formOptions w2form + * properties + * @param {external:jQuery.fn.w2popup.properties} popupOptions w2popup + * properties + * @public + */ + olexp.util.popup = function(id, onChanges, formOptions, popupOptions) + { + + var name = formOptions.name; + var record = formOptions.record; + + // ================================================== + // Create form + // -------------------------------------------------- + if (w2ui.hasOwnProperty(name)) + { + w2ui[name].destroy(); + } + $().w2form($.extend(formOptions, { + actions : { + save : function () { + // Check for errors + var errors = this.validate(); + if (errors.length === 0) + { + // Close popup and update with changes + w2popup.close(); + var form = w2ui[name]; + var changes = form.getChanges(); + onChanges(changes); + } + }, + reset : function () { + // Reset properties to original item values + var form = w2ui[name]; + for (var rname in record) + { + form.record[rname] = record[rname]; + } + form.refresh(); + } + } + })); + + // ================================================== + // Display form in popup + // -------------------------------------------------- + w2popup.open($.extend(popupOptions, { + body : ('
'), + onOpen : function (event) { + event.onComplete = function () { + $('#w2ui-popup #' + id).w2render(name); + }; + }, + onToggle : function (event) { + var form = w2ui[name]; + $(form.box).hide(); + event.onComplete = function () { + $(form.box).show(); + form.resize(); + }; + } + })); + + }; + + /** + * Get properties from feature accounting for clustered features + * @memberOf olexp.util + * @param {external:ol.Feature} feature Source feature + * @public + * @returns {object} Feature properties + */ + olexp.util.toProperties = function(feature) + { + var properties = feature.getProperties(); + + // ================================================== + // Check if this is a cluster feature + // -------------------------------------------------- + if (properties.hasOwnProperty('features')) + { + var features = properties.features; + if (features instanceof Array) + { + if (features.length === 1) + { + // ================================================== + // If just one feature get its properties + // -------------------------------------------------- + if (features[0] instanceof ol.Feature) + { + properties = features[0].getProperties(); + } + } + else + { + // ================================================== + // If more than one feature get feature count + // -------------------------------------------------- + var count = 0; + for (var i = 0; i < features.length; i++) + { + if (features[i] instanceof ol.Feature) + { + count += 1; + properties['Cluster Size'] = count; + } + } + } + } + } + + return properties; + + }; + + /** + * Convert properties object to record for w2ui grid + * @memberOf olexp.util + * @param {object} properties Object properties to convert to grid record + * @public + * @returns {array} Properties in record format + */ + olexp.util.toRecords = function(properties) + { + var records = []; + var recid = 0; + + // ================================================== + // Push properties into record + // -------------------------------------------------- + for (var name in properties) + { + var value = properties[name]; + recid += 1; + records.push({recid: recid, property: name, value: value}); + } + + return records; + }; + + /** + * Utility functions + * @memberOf olexp.util + * @param {olexp.ExplorerSettings} settings olexp settings + * @public + */ + olexp.util.Util = function(settings) { + var util = new Util(settings); + return { + addLayerVector : util.addLayerVector.bind(util), + getControls : util.getControls.bind(util), + getGraticule : util.getGraticule.bind(util), + getInteractions : util.getInteractions.bind(util), + getTileTypes : util.getTileTypes.bind(util) + }; + }; + + return olexp; + +}(olexp || {})); diff --git a/dist/olexp.min.js b/dist/olexp.min.js index 2af0ec3..9c47e9e 100644 --- a/dist/olexp.min.js +++ b/dist/olexp.min.js @@ -1,3 +1,3 @@ /* olexp 0.1.2 (c) Daniel Pulido */ -var olexp=olexp||{};!function(a){var b=function(b,c){if("undefined"==typeof b)throw new Error("olexp.Explorer: id not defined");if(0===$("#"+b).length)throw new Error("olexp.Explorer: id not found");var d="olexp-"+b;this.options={controls:{editsettings:!0,exportmap:!0,graticule:!0,layercontrol:!0,layermanager:!0,layermenu:!0,measure:!0,toolbarhide:!0},details:{hidden:!0,resizable:!0,size:"25%",type:"preview"},layers:{expanded:!0,group:!0,img:"icon-folder",text:"Layers"},map:{type:"main"},navigation:{resizable:!0,size:"15%",type:"left"},olcontrols:{fullscreen:!0,mouseposition:!0,overviewmap:!0,rotate:!0,scaleline:!0,zoom:!0,zoomslider:!0,zoomtoextent:!0},olinteractions:{draganddrop:!0},olmap:{controls:[],view:new ol.View({center:[0,0],zoom:3})},outline:{type:"main"},overlays:{expanded:!0,group:!0,img:"icon-folder",text:"Overlays"},settings:{},toolbar:{size:"40",style:"padding: 5px;",type:"top"}},$.extend(!0,this.options,c),$.extend(!0,this.options,{explorer:{cls:"olexp-explorer-content",id:d+"-explorer-id-content",details:d+"-explorer-name-details",layout:d+"-explorer-name-layout",navigation:d+"-explorer-name-navigation",outline:d+"-explorer-name-outline",toolbar:d+"-explorer-name-toolbar"},layers:{id:d+"-explorer-id-layers"},map:{content:'
'},olmap:{target:d+"-explorer-id-map"},overlays:{id:d+"-explorer-id-overlays"},settings:{prefix:d}});var e=this,f=$("
",{id:this.options.explorer.id,"class":this.options.explorer.cls});$("#"+b).append(f),this.layout=$("#"+this.options.explorer.id).w2layout({name:this.options.explorer.layout,panels:[this.options.navigation,this.options.map,this.options.toolbar]}),this.toolbar=$("").w2toolbar({name:this.options.explorer.toolbar}),this.navigation=$("").w2layout({name:this.options.explorer.navigation,onResize:function(){e.hasOwnProperty("map")&&e.map.updateSize(),e.hasOwnProperty("details")&&e.details.resize()},panels:[this.options.outline,this.options.details]}),this.outline=$("").w2sidebar({name:this.options.explorer.outline,nodes:[this.options.layers,this.options.overlays],onClick:function(a){var b=a.target,c=e.manager.getDetails(b);e.details.clear(),e.details.add(c),e.manager.onItemSelected(b)},onDblClick:function(a){var b=a.target;e.manager.toggleNode(b),e.manager.onItemSelected(b)},onRender:function(a){a.onComplete=function(){var a=e.outline.selected;e.manager.onItemSelected(a)}}}),this.details=$("").w2grid({columns:[{field:"property",caption:"Property",size:"100%",sortable:!0},{field:"value",caption:"Value",size:"100%",sortable:!0}],name:this.options.explorer.details}),this.navigation.content(this.options.outline.type,this.outline),this.navigation.content(this.options.details.type,this.details),this.layout.content(this.options.navigation.type,this.navigation),this.map=new ol.Map(this.options.olmap),this.manager=new a.manager.Manager(this.map,this.outline,this.details,this.options.layers.id,this.options.overlays.id);var g=a.menu.Zoom(this.manager,this.options.settings),h=a.menu.Properties(this.manager,this.options.settings),i=a.menu.Remove(this.manager,this.options.settings);this.menu={items:[],callbacks:{}},this.menu.items.push(g.menu),this.menu.items.push(h.menu),this.menu.items.push(i.menu),this.menu.callbacks[g.menu.id]=g.click,this.menu.callbacks[h.menu.id]=h.click,this.menu.callbacks[i.menu.id]=i.click,this.outline.menu=this.menu.items,this.outline.onMenuClick=function(a){var b=a.menuItem.id;b in e.menu.callbacks&&e.menu.callbacks[b](a)},this.util=new a.util.Util(this.options.settings);var j=this.util.getInteractions(this.map);for(var k in this.options.olinteractions){var l=j[k];this.options.olinteractions[k]&&this.map.addInteraction(l)}var m=this.util.getControls();for(var n in this.options.olcontrols){var o=m[n];this.map.addControl(o),o.setMap(this.options.olcontrols[n]?this.map:null)}this.selector=new a.selection.Feature(this.map,this.details),this.selector.setEnable(!0),this.api={details:this.details,layout:this.layout,manager:this.manager,map:this.map,navigation:this.navigation,options:this.options,outline:this.outline,toolbar:this.toolbar},this.options.controls.toolbarhide&&(this.toolbar.add(a.control.ToolbarHide(this.api,{hidden:this.options.toolbar.hidden,settings:this.options.settings})),this.toolbar.add({id:"break-toolbar-hide",type:"break"})),this.options.controls.layermanager&&(this.toolbar.add(a.control.LayerManager(this.api,this.manager,{details:{checked:!this.options.details.hidden},navigation:{checked:!this.options.navigation.hidden},settings:this.options.settings})),this.toolbar.add({id:"break-layer-manager",type:"break"})),this.options.controls.layermenu&&(this.toolbar.add(a.control.LayerMenu(this.api,this.manager,this.menu,{settings:this.options.settings})),this.toolbar.add({id:"break-item-menu",type:"break"})),this.options.controls.layercontrol&&(this.toolbar.add(a.control.LayerControl(this.api,{settings:this.options.settings})),this.toolbar.add({id:"break-layer-control",type:"break"})),this.options.controls.graticule&&(this.toolbar.add(a.control.Graticule(this.api,{settings:this.options.settings})),this.toolbar.add({id:"break-graticule",type:"break"})),this.options.controls.measure&&(this.toolbar.add(a.control.Measure(this.api,{settings:this.options.settings})),this.toolbar.add({id:"break-measure",type:"break"})),this.options.controls.exportmap&&(this.toolbar.add(a.control.ExportMap(this.api,{settings:this.options.settings})),this.toolbar.add({id:"break-export-map",type:"break"})),this.options.controls.editsettings&&(this.toolbar.add(a.control.EditSettings(this.api,{settings:this.options.settings})),this.toolbar.add({id:"break-edit-settings",type:"break"})),this.layout.set(this.options.toolbar.type,{content:"",show:{toolbar:!0},toolbar:this.toolbar})};a.destroy=function(a){void 0!==a.map&&a.map.setTarget(null),void 0!==a.details&&a.details.destroy(),void 0!==a.outline&&a.outline.destroy(),void 0!==a.navigation&&a.navigation.destroy(),void 0!==a.toolbar&&a.toolbar.destroy(),void 0!==a.layout&&a.layout.destroy()},a.Explorer=function(a,c){var d=new b(a,c);return d.api}}(olexp||{}),olexp.event=olexp.event||{},function(a){var b=function(a){this.listeners=$.extend({},a)};return b.prototype.on=function(a,b,c){if(a in this.listeners){var d=b;"undefined"!=typeof c&&(d=b.bind(c)),this.listeners[a].push(d)}},b.prototype.register=function(a){a in this.listeners||(this.listeners[a]=[])},b.prototype.trigger=function(){var a=Array.prototype.slice.call(arguments),b=a.shift();if(b in this.listeners)for(var c=0;c-1&&this.listeners[a].splice(e,1)}},a.event.Event=function(a){var c=new b(a);return c},a}(olexp||{}),olexp.control=olexp.control||{},function(a){var b=function(a,b){var c=$.extend(!0,{control:{EditSettings:{form:{header:"",style:"border: 0px; background-color: transparent;"},hint:"Edit Controls",popup:{height:380,style:"width: 100%; height: 100%;",title:"Edit Controls",width:225},span:6}}},b);this.settings=c.control.EditSettings,this.button=b.prefix+"-control-edit-settings-button",this.icon="olexp-control-edit-settings",this.id=b.prefix+"-control-edit-settings-form",this.map=a,this.name=b.prefix+"-control-edit-settings-form"};return b.prototype.display=function(){var b=this,c=[{html:{caption:"Full Screen",span:this.settings.span},name:"fullscreen",type:"checkbox"},{html:{caption:"Mouse Position",span:this.settings.span},name:"mouseposition",type:"checkbox"},{html:{caption:"Overview Map",span:this.settings.span},name:"overviewmap",type:"checkbox"},{html:{caption:"Rotate",span:this.settings.span},name:"rotate",type:"checkbox"},{html:{caption:"Scale Line",span:this.settings.span},name:"scaleline",type:"checkbox"},{html:{caption:"Zoom",span:this.settings.span},name:"zoom",type:"checkbox"},{html:{caption:"Zoom Slider",span:this.settings.span},name:"zoomslider",type:"checkbox"},{html:{caption:"Zoom To Extent",span:this.settings.span},name:"zoomtoextent",type:"checkbox"}],d={fullscreen:this.isControlActive("fullscreen"),mouseposition:this.isControlActive("mouseposition"),overviewmap:this.isControlActive("overviewmap"),rotate:this.isControlActive("rotate"),scaleline:this.isControlActive("scaleline"),zoom:this.isControlActive("zoom"),zoomslider:this.isControlActive("zoomslider"),zoomtoextent:this.isControlActive("zoomtoextent")},e=function(a){for(var c in a){var d=a[c];b.setControl(c,d)}},f=$.extend(this.settings.form,{fields:c,name:this.name,record:d}),g=this.settings.popup;a.util.popup(this.id,e,f,g)},b.prototype.getControl=function(a){for(var b=this.map.getControls().getArray(),c=0;c');var d=document.getElementById(a);d.addEventListener("click",c.bind(this),!1),$("#"+a)[0].click(),$("#"+a).remove()},a.control.ExportMap=function(a,c){var d=new b(a.map,c.settings);return{hint:d.settings.hint,id:d.button,img:d.icon,onClick:function(a){d.toImage()},type:"button"}},a}(olexp||{}),function(a){var b=function(b,c){var d=$.extend(!0,{control:{Graticule:{enable:!1,form:{header:"",style:"border: 0px; background-color: transparent;"},hint:"Edit Grid Lines",options:{color:"000000",lineDash:[.5,4],width:2},popup:{height:225,style:"border: 0px; background-color: transparent;",title:"Edit Grid Lines",width:300},span:3}}},c);this.settings=d.control.Graticule,this.button=c.prefix+"-control-graticule-button",this.icon="olexp-control-graticule",this.id=c.prefix+"-control-graticule",this.map=b,this.name=c.prefix+"-control-graticule-form",this.util=new a.util.Util(d),this.graticule=this.util.getGraticule(this.settings.enable?this.map:null,$.extend({},this.settings.options))};return b.prototype.display=function(){var b=this,c=[{html:{caption:"Enable",span:this.settings.span},name:"enable",required:!0,type:"checkbox"},{html:{caption:"Color",span:this.settings.span},name:"color",options:{silent:!1},required:!0,type:"color"},{html:{caption:"Width",span:this.settings.span},name:"width",options:{arrows:!0,max:4,min:.25,placeholder:"0.25 - 4",silent:!1,step:.25},required:!0,type:"float"}],d=this.graticule.olexp_record,e=function(a){for(var c in a)d[c]=a[c];var e=$.extend({},d);delete e.enable,b.graticule.setMap(null),b.graticule=b.util.getGraticule(d.enable?b.map:null,e)},f=$.extend(this.settings.form,{fields:c,name:this.name,record:d}),g=this.settings.popup;a.util.popup(this.id,e,f,g)},a.control.Graticule=function(a,c){"undefined"==typeof c&&(c={}),"undefined"==typeof c.settings&&(c.settings={});var d=new b(a.map,c.settings);return{hint:d.settings.hint,id:d.button,img:d.icon,onClick:function(a){d.display()},type:"button"}},a}(olexp||{}),function(a){var b=function(b,c){var d=$.extend(!0,{control:{LayerControlTile:{form:{header:"",style:"border: 0px; background-color: transparent;"},hint:"Add Tile Layer",popup:{height:165,style:"border: 0px; background-color: transparent;",title:"Add Tile Layer",width:290},span:3},LayerControlVector:{form:{header:"File Types: "+$.map(a.util.FileTypes,function(a){return" "+a.name}),style:"border: 0px; background-color: transparent;"},hint:"Add Vector Layer",popup:{height:195,style:"border: 0px; background-color: transparent;",title:"Add Vector Layer",width:350},span:4}}},c);this.settingsTile=d.control.LayerControlTile,this.settingsVector=d.control.LayerControlVector,this.icons={tile:"olexp-control-layer-control-add-tile",vector:"olexp-control-layer-control-add-vector"},this.buttons={tile:c.prefix+"-control-layer-control-add-tile-button",vector:c.prefix+"-control-layer-control-add-vector-button"},this.ids={tile:c.prefix+"-control-layer-control-add-tile",vector:c.prefix+"-control-layer-control-add-vector"},this.map=b,this.names={tile:c.prefix+"-control-tile-form",vector:c.prefix+"-control-vector-form"},this.util=new a.util.Util(this.map)};return b.prototype.tile=function(){var b=this,c=this.util.getTileTypes(),d=$.map(c,function(a){return a.name}),e=[{field:"tile_source",html:{caption:"Source",span:this.settingsTile.span},options:{items:d},required:!0,type:"list"}],f={};f[e[0].field]=null;var g=function(a){for(var d in a)if(d===e[0].field){var f=a[d].id;for(var g in c)if(f===c[g].name){var h=c[g],i=h["class"],j=new ol.layer.Tile({source:new i(h.settings)});j.set("name",f),b.map.addLayer(j)}}},h=$.extend(this.settingsTile.form,{fields:e,name:this.names.tile,record:f}),i=this.settingsTile.popup;a.util.popup(this.ids.tile,g,h,i)},b.prototype.vector=function(){var b=this,c=[{field:"vector_source",html:{caption:"Source",span:this.settingsVector.span},options:{placeholder:"Click to add file",silent:!1},required:!0,type:"file"}],d={};d[c[0].field]=null;var e=function(d){for(var e in d)if(e===c[0].field)for(var f in d[e]){var g=d[e][f].content;if("undefined"!=typeof g&&null!==g){var h=d[e][f].name,i=h.replace(/\.[^\/.]+$/,""),j=a.util.getReader(h);if(null===j)return void w2alert("Unable to open file "+h,"Error");var k=atob(g),l=b.map.getView().getProjection(),m={featureProjection:l},n=j.readFeatures(k,m);b.util.addLayerVector(b.map,i,n)}}},f=$.extend(this.settingsVector.form,{fields:c,name:this.names.vector,record:d}),g=this.settingsVector.popup;a.util.popup(this.ids.vector,e,f,g)},a.control.LayerControl=function(a,c){"undefined"==typeof c&&(c={}),"undefined"==typeof c.tile&&(c.tile=!0),"undefined"==typeof c.vector&&(c.vector=!0),"undefined"==typeof c.settings&&(c.settings={});var d=new b(a.map,c.settings),e=[];return c.tile&&e.push({hint:d.settingsTile.hint,id:d.buttons.tile,img:d.icons.tile,onClick:function(a){d.tile()},type:"button"}),c.vector&&e.push({hint:d.settingsVector.hint,id:d.buttons.vector,img:d.icons.vector,onClick:function(a){d.vector()},type:"button"}),e},a}(olexp||{}),olexp=function(a){var b=function(a,b,c){var d=$.extend(!0,{control:{LayerManager:{hintDetailsHide:"Hide details",hintDetailsShow:"Show details",hintMoveDown:"Move item down",hintMoveUp:"Move item up",hintOutlineHide:"Hide outline",hintOutlineShow:"Show outline"}}},c);this.buttons={details:c.prefix+"-control-layer-manager-button-details",down:c.prefix+"-control-layer-manager-button-down",navigation:c.prefix+"-control-layer-manager-button-navigation",up:c.prefix+"-control-layer-manager-button-up"},this.explorer=a,this.icons={details:"olexp-control-layer-manager-details",down:"olexp-control-layer-manager-down",navigation:"olexp-control-layer-manager-navigation",up:"olexp-control-layer-manager-up"},this.manager=b,this.settings=d.control.LayerManager,this.manager.on("remove:item",this.onItemRemoved,this),this.manager.on("select:item",this.onItemSelected,this)};return b.prototype.details=function(){this.explorer.navigation.toggle(this.explorer.options.details.type);var a=this.explorer.navigation.get(this.explorer.options.details.type),b=this.explorer.toolbar.get(this.buttons.details);b.hint=this.hintDetails(a.hidden),this.explorer.toolbar.refresh()},b.prototype.down=function(){this.manager.moveDown()},b.prototype.hintDetails=function(a){return a?this.settings.hintDetailsShow:this.settings.hintDetailsHide},b.prototype.hintNavigation=function(a){return a?this.settings.hintOutlineShow:this.settings.hintOutlineHide},b.prototype.navigation=function(){this.explorer.layout.toggle(this.explorer.options.navigation.type);var a=this.explorer.layout.get(this.explorer.options.navigation.type),b=this.explorer.toolbar.get(this.buttons.navigation);b.hint=this.hintNavigation(a.hidden),this.explorer.toolbar.refresh()},b.prototype.onItemRemoved=function(a){this.manager.isSelected(a.id)&&(this.explorer.toolbar.disable(this.buttons.up),this.explorer.toolbar.disable(this.buttons.down))},b.prototype.onItemSelected=function(a){if("undefined"!=typeof a){var b=this.manager.getById(a);if(null!==b){var c=this.manager.getNode(b.id);c.disabled?(this.explorer.toolbar.disable(this.buttons.up),this.explorer.toolbar.disable(this.buttons.down)):(this.explorer.toolbar.enable(this.buttons.up),this.explorer.toolbar.enable(this.buttons.down))}}},b.prototype.up=function(){this.manager.moveUp()},a.control.LayerManager=function(a,c,d){"undefined"==typeof d&&(d={}),"undefined"==typeof d.details&&(d.details={}),"undefined"==typeof d.details.enabled&&(d.details.enabled=!0),"undefined"==typeof d.details.checked&&(d.details.checked=!0),"undefined"==typeof d.down&&(d.down=!0),"undefined"==typeof d.navigation&&(d.navigation={}),"undefined"==typeof d.navigation.enabled&&(d.navigation.enabled=!0),"undefined"==typeof d.navigation.checked&&(d.navigation.checked=!0),"undefined"==typeof d.up&&(d.up=!0);var e=new b(a,c,d.settings),f=[];return d.navigation.enabled&&f.push({checked:d.navigation.checked,hint:e.hintNavigation(!d.navigation.checked),id:e.buttons.navigation,img:e.icons.navigation,onClick:function(a){e.navigation()},type:"check"}),d.details.enabled&&f.push({checked:d.details.checked,hint:e.hintDetails(!d.details.checked),id:e.buttons.details,img:e.icons.details,onClick:function(a){e.details()},type:"check"}),d.up&&f.push({disabled:!0,hint:e.settings.hintMoveUp,id:e.buttons.up,img:e.icons.up,onClick:function(a){e.up()},type:"button"}),d.down&&f.push({disabled:!0,hint:e.settings.hintMoveDown,id:e.buttons.down,img:e.icons.down,onClick:function(a){e.down()},type:"button"}),f},a}(olexp||{}),function(a){var b=function(a,b,c,d){var e=$.extend(!0,{control:{LayerMenu:{arrow:!0,hint:"Item Options",text:""}}},d);this.button=d.prefix+"-control-layer-menu",this.explorer=a,this.icon="olexp-control-layer-menu",this.manager=b,this.menu=c,this.settings=e.control.LayerMenu,this.manager.on("remove:item",this.onItemRemoved,this),this.manager.on("select:item",this.onItemSelected,this)};return b.prototype.onItemRemoved=function(a){this.manager.isSelected(a.id)&&this.explorer.toolbar.disable(this.button)},b.prototype.onItemSelected=function(a){if("undefined"!=typeof a){var b=this.manager.getById(a);if(null!==b){var c=this.manager.getNode(b.id);c.disabled?this.explorer.toolbar.disable(this.button):this.explorer.toolbar.enable(this.button)}}},a.control.LayerMenu=function(a,c,d,e){var f=new b(a,c,d,e.settings);return a.toolbar.on("click",function(b){if(null!==a.outline.selected){var c=f.button+":";if(!(b.target.indexOf(c)<0)){var e=b.target.replace(c,"");e in d.callbacks&&d.callbacks[e]({target:a.outline.selected})}}}),{arrow:f.settings.arrow,disabled:!0,hint:f.settings.hint,id:f.button,img:f.icon,items:f.menu.items,text:f.settings.text,type:"menu"}},a}(olexp||{}),function(a){var b=function(b,c){var d=$.extend(!0,{control:{Measurement:{hintArea:"Measure area",hintLength:"Measure length"}}},c);this.explorer=b,this.icons={area:"olexp-control-measure-area",length:"olexp-control-measure-length"},this.ids={area:c.prefix+"-control-measure-area-button",length:c.prefix+"-control-measure-length-button"},this.settings=d.control.Measurement,this.tool=new a.measure.Tool(b.map,a.measure.Type.LINE,c)};return b.prototype.area=function(){var b=!this.explorer.toolbar.get(this.ids.area).checked;this.measure(a.measure.Type.AREA,b)},b.prototype.length=function(){var b=!this.explorer.toolbar.get(this.ids.length).checked;this.measure(a.measure.Type.LINE,b)},b.prototype.measure=function(a,b){this.tool.setEnable(!1),b&&(this.tool.setType(a),this.tool.setEnable(!0))},a.control.Measure=function(a,c){"undefined"==typeof c&&(c={}),"undefined"==typeof c.area&&(c.area=!0),"undefined"==typeof c.length&&(c.length=!0),"undefined"==typeof c.settings&&(c.settings={});var d=new b(a,c.settings),e=[];return c.area&&e.push({hint:d.settings.hintArea,id:d.ids.area,img:d.icons.area,onClick:function(b){c.length&&a.toolbar.uncheck(d.ids.length),d.area()},type:"check"}),c.length&&e.push({hint:d.settings.hintLength,id:d.ids.length,img:d.icons.length,onClick:function(b){c.area&&a.toolbar.uncheck(d.ids.area),d.length()},type:"check"}),e},a}(olexp||{}),function(a){var b=function(b,c){var d=$.extend(!0,{control:{ToolbarHide:{hint:"Hide toolbar"}}},c.settings);this.button=c.settings.prefix+"-control-toolbar-hide-button",this.explorer=b,this.icon="olexp-control-toolbar-hide",this.settings=d.control.ToolbarHide,this.show=a.ol.ToolbarShow(this.explorer,c)};return b.prototype.hide=function(){this.explorer.layout.hide(this.explorer.options.toolbar.type),this.show.setMap(this.explorer.map)},a.control.ToolbarHide=function(a,c){var d=new b(a,c);return{hint:d.settings.hint,id:d.button,img:d.icon,onClick:function(a){d.hide()},type:"button"}},a}(olexp||{}),olexp.item=olexp.item||{},function(a){return a.item.icons={group:"olexp-item-group",heatmap:"olexp-item-heatmap",image:"olexp-item-image",overlay:"olexp-item-overlay",tile:"olexp-item-tile",vector:"olexp-item-vector"},Item=function(a,b,c){this.id=a,this.layer=c,this.moving=!1,this.name=b,this.type=Item.getType(this.layer),this.icon=Item.getIcon(this.type)},Item.prototype.getDetails=function(){var b={};b.Name=this.name;var c=this.layer.getProperties();if(c.hasOwnProperty(a.measure.properties.area)?b.Area=c[a.measure.properties.area]:c.hasOwnProperty(a.measure.properties.length)&&(b.Length=c[a.measure.properties.length]),this.type===a.item.Type.GROUP){var d=this.layer.getLayers();b["Layer Count"]=d.getLength()}if(this.type===a.item.Type.VECTOR){var e=this.layer.getSource(),f=e.getFeatures();b["Feature Count"]=f.length}var g=a.util.toRecords(b);return g},Item.prototype.getExtent=function(){if(this.type===a.item.Type.OVERLAY)return null;if(this.type===a.item.Type.GROUP){var b=null,c=this.layer.getLayers();return c.forEach(function(a,c,d){var e=Item.getLayerExtent(a);null===b&&null!==e?b=e:null!==b&&null!==e&&(b=ol.extent.extend(b,e))},this),b}return Item.getLayerExtent(this.layer)},Item.getIcon=function(b){return b===a.item.Type.GROUP?a.item.icons.group:b===a.item.Type.HEATMAP?a.item.icons.heatmap:b===a.item.Type.IMAGE?a.item.icons.image:b===a.item.Type.OVERLAY?a.item.icons.overlay:b===a.item.Type.TILE?a.item.icons.tile:b===a.item.Type.VECTOR?a.item.icons.vector:"icon-page"},Item.getLayerExtent=function(a){var b=a.getExtent();if("undefined"==typeof b){var c=a.getSource();null!==c&&(c instanceof ol.source.Cluster||c instanceof ol.source.VectorTile||c instanceof ol.source.Vector)&&(b=c.getExtent())}return"undefined"==typeof b?null:b},Item.prototype.getPropertyTypes=function(){return this.layer instanceof ol.layer.Layer?a.item.LayerProperties:this.layer instanceof ol.Overlay?a.item.OverlayProperties:{}},Item.prototype.getProperties=function(){var a={name:this.name},b=this.getPropertyTypes();for(var c in b)a[c]=this.layer.get(c);return a},Item.getType=function(b){return b instanceof ol.layer.Group?a.item.Type.GROUP:b instanceof ol.layer.Heatmap?a.item.Type.HEATMAP:b instanceof ol.layer.Image?a.item.Type.IMAGE:b instanceof ol.layer.Tile?a.item.Type.TILE:b instanceof ol.layer.Vector?a.item.Type.VECTOR:b instanceof ol.Overlay?a.item.Type.OVERLAY:null},Item.prototype.setProperties=function(a){a.hasOwnProperty("name")&&(this.name=a.name);var b=this.getPropertyTypes();for(var c in b)a.hasOwnProperty(c)&&this.layer.set(c,a[c])},Item.prototype.property=function(a,b){return"undefined"!=typeof this[a]?("undefined"!=typeof b&&(this[a]=b),this[a]):void 0},Item.prototype.zoomTo=function(b){var c=b.getView();if(this.type===a.item.Type.OVERLAY){var d=this.layer.getPosition();if("undefined"!=typeof d)return void c.setCenter(d);w2alert("Overlay has no position defined to which to zoom.","Warning")}else{var e=this.getExtent();if(null!==e)return void c.fit(e,b.getSize());w2alert("Layer has no extent defined to which to zoom.","Warning")}},a.item.Item=function(a,b,c){var d=new Item(a,b,c);return{getDetails:d.getDetails.bind(d),getProperties:d.getProperties.bind(d),getPropertyTypes:d.getPropertyTypes.bind(d),icon:d.icon,id:d.id,layer:d.layer,moving:function(a){return d.property("moving",a)},name:function(a){return d.property("name",a)},setProperties:d.setProperties.bind(d),type:d.type,zoomTo:d.zoomTo.bind(d)}},a.item.OverlayProperties={},a.item.LayerProperties={opacity:{title:"Opacity"}},a.item.Type={GROUP:0,HEATMAP:1,IMAGE:2,OVERLAY:3,TILE:4,VECTOR:5},a}(olexp||{}),olexp.manager=olexp.manager||{},function(a){var b=function(b,c,d,e,f){this.event=new a.event.Event({"select:item":[]}),this.managerLayers=new a.manager.NodeManager(e,b.getLayers(),c,d),this.layersId=e,this.managerOverlays=new a.manager.NodeManager(f,b.getOverlays(),c,d),this.map=b,this.map.on("change:layergroup",this.onLayerGroupChanged,this),this.outline=c,this.overlaysId=f};return b.prototype.isIdLayerNode=function(a){return"string"!=typeof a?!1:0===a.indexOf(this.layersId)},b.prototype.isIdOverlayNode=function(a){return"string"!=typeof a?!1:0===a.indexOf(this.overlaysId)},b.prototype.isSelected=function(a){return a===this.outline.selected},b.prototype.getById=function(a){return this.isIdLayerNode(a)?this.managerLayers.getById(a):this.isIdOverlayNode(a)?this.managerOverlays.getById(a):null},b.prototype.getDetails=function(a){if(this.isIdLayerNode(a)){var b=this.managerLayers.getById(a);if(null!==b)return b.getDetails()}else if(this.isIdOverlayNode(a)){var c=this.managerOverlays.getById(a);if(null!==c)return c.getDetails()}return[]},b.prototype.getNode=function(a){return this.outline.get(a)},b.prototype.moveDown=function(a){return"undefined"==typeof a&&(a=this.outline.selected),this.isIdLayerNode(a)?this.managerLayers.moveDown(a):this.isIdOverlayNode(a)?this.managerOverlays.moveDown(a):!1},b.prototype.moveUp=function(a){return"undefined"==typeof a&&(a=this.outline.selected),this.isIdLayerNode(a)?this.managerLayers.moveUp(a):this.isIdOverlayNode(a)?this.managerOverlays.moveUp(a):!1},b.prototype.off=function(a,b,c){this.event.off(a,b,c),this.managerLayers.off(a,b,c),this.managerOverlays.off(a,b,c)},b.prototype.on=function(a,b,c){this.event.on(a,b,c),this.managerLayers.on(a,b,c),this.managerOverlays.on(a,b,c)},b.prototype.onItemSelected=function(a){this.event.trigger("select:item",a)},b.prototype.onLayerGroupChanged=function(a){this.managerLayers.setLayers(a.target.getLayers())},b.prototype.removeFromMap=function(a){return a.hasOwnProperty("id")?this.isIdLayerNode(a.id)?this.managerLayers.removeFromMap(a):this.isIdOverlayNode(a.id)?this.managerOverlays.removeFromMap(a):null:null},b.prototype.toggleNode=function(a){if("string"==typeof a){var b=this.outline.get(a),c=b.disabled;if(c?this.outline.enable(a):this.outline.disable(a),this.isIdLayerNode(a)){var d=this.managerLayers.getById(a);null!==d&&d.layer.setVisible(c)}else if(this.isIdOverlayNode(a)){var e=this.managerOverlays.getById(a);if(null!==e){var f=e.layer.getProperties();if(f.hasOwnProperty("element")){var g=$(f.element);c?g.show():g.hide()}}}}},b.prototype.updateItem=function(a,b){var c=this.getById(a);if(null!==c){c.setProperties(b);var d=this.outline.get(a);d.text=c.name(),this.outline.refresh()}},b.prototype.zoomTo=function(a){var b=this.getById(a);b.zoomTo(this.map)},a.manager.Manager=function(a,c,d,e,f){var g=new b(a,c,d,e,f);return{getById:g.getById.bind(g),getDetails:g.getDetails.bind(g),getNode:g.getNode.bind(g),isSelected:g.isSelected.bind(g),moveDown:g.moveDown.bind(g),moveUp:g.moveUp.bind(g),off:g.off.bind(g),on:g.on.bind(g),onItemSelected:g.onItemSelected.bind(g),removeFromMap:g.removeFromMap.bind(g),toggleNode:g.toggleNode.bind(g),updateItem:g.updateItem.bind(g),zoomTo:g.zoomTo.bind(g)}},a}(olexp||{}),function(a){var b=function(b,c,d,e){this.count=0,this.details=e,this.event=new a.event.Event({"remove:item":[]}),this.id=b,this.items=[],this.layers=c,this.layers.on("change:length",this.onLayerChanged,this),this.managers={},this.outline=d};return b.prototype.addLayer=function(c){this.count+=1;var d=this.id+"-"+this.count,e="Item "+this.count,f=c.getProperties();f.hasOwnProperty("name")&&(e=f.name);var g=new a.item.Item(d,e,c);this.items.push(g);var h={id:g.id,img:g.icon,text:g.name()},i=this.outline.get(this.id).nodes;if(0===i.length?this.outline.add(this.id,[h]):this.outline.insert(this.id,i[0].id,[h]),g.type===a.item.Type.GROUP){var j=c.getLayers(),k=new b(g.id,j,this.outline,this.details);j.forEach(function(a){k.addLayer(a)},this),this.managers[g.id]=k,this.outline.expand(g.id)}return g},b.prototype.getById=function(b,c){"undefined"==typeof c&&(c=!0);for(var d=this.getSize(),e=0;d>e;e++){if(this.items[e].id===b)return this.items[e];if(this.items[e].type===a.item.Type.GROUP&&c){var f=this.managers[this.items[e].id].getById(b);if(null===f)continue;if(f.id===b)return f}}return null},b.prototype.getByLayer=function(b,c){"undefined"==typeof c&&(c=!0);for(var d=this.getSize(),e=0;d>e;e++){if(this.items[e].layer===b)return this.items[e];if(this.items[e].type===a.item.Type.GROUP&&c){var f=this.managers[this.items[e].id].getByLayer(b);if(null===f)continue;if(f.layer===b)return f}}return null},b.prototype.getSize=function(){return this.items.length},b.prototype.isSelected=function(a){return a===this.outline.selected},b.prototype.isHidden=function(b){return b instanceof a.measure.Overlay},b.prototype.moveDown=function(b){var c=this.getById(b,!1);if(null!==c){var d=this.moveLayerUp(this.layers,c.layer);return d&&(d=this.moveItemDown(b)),d}for(var e=this.getSize(),f=0;e>f;f++)if(this.items[f].type===a.item.Type.GROUP){var g=this.managers[this.items[f].id].moveDown(b);if(null!==g)return g}return null},b.prototype.moveItemDown=function(a){var b=this.outline.get(a);if(null===b)return!1;var c=this.outline.find(b.parent.id,{parent:b.parent}),d=this.outline.get(b.parent.id,a,!0);if(d>=c.length-1)return!1;var e=c[d+1].id,f=c[d+1];return b.parent!==f.parent?!1:(this.outline.remove(e),this.outline.insert(b.parent,a,f),this.outline.select(a),!0)},b.prototype.moveItemUp=function(a){var b=this.outline.get(a);if(null===b)return!1;var c=this.outline.find(b.parent.id,{parent:b.parent}),d=this.outline.get(b.parent.id,a,!0);if(0>=d)return!1;var e=c[d-1].id,f=c[d-1];return b.parent!==f.parent?!1:(this.outline.remove(a),this.outline.insert(b.parent,e,b),this.outline.select(a),!0)},b.prototype.moveLayerDown=function(b,c){var d=a.util.indexOf(b,c),e=this.layers.getLength();if(e-1>d){var f=this.getByLayer(c,!1);return f.moving(!0),b.removeAt(d),b.insertAt(d+1,c),f.moving(!1),!0}return!1},b.prototype.moveLayerUp=function(b,c){var d=a.util.indexOf(b,c);if(d>0){var e=this.getByLayer(c,!1);return e.moving(!0),b.removeAt(d),b.insertAt(d-1,c),e.moving(!1),!0}return!1},b.prototype.moveUp=function(b){var c=this.getById(b,!1);if(null!==c){var d=this.moveLayerDown(this.layers,c.layer);return d&&(d=this.moveItemUp(b)), -d}for(var e=this.getSize(),f=0;e>f;f++)if(this.items[f].type===a.item.Type.GROUP){var g=this.managers[this.items[f].id].moveUp(b);if(null!==g)return g}return null},b.prototype.off=function(b,c,d){this.event.off(b,c,d);for(var e=this.getSize(),f=0;e>f;f++)this.items[f].type===a.item.Type.GROUP&&this.managers[this.items[f].id].off(b,c,d)},b.prototype.on=function(b,c,d){this.event.on(b,c,d);for(var e=this.getSize(),f=0;e>f;f++)this.items[f].type===a.item.Type.GROUP&&this.managers[this.items[f].id].on(b,c,d)},b.prototype.onItemRemoved=function(a){this.event.trigger("remove:item",a),this.isSelected(a.id)&&this.details.clear(),this.remove(a)},b.prototype.onLayerChanged=function(b){for(var c=b.target,d=c.getLength(),e=0;d>e;e++){var f=c.item(e);if(!this.isHidden(f)){var g=this.getByLayer(f);null===g&&this.addLayer(f)}}for(var h=this.toList(),i=h.length,j=0;i>j;j++){var k=h[j];if(!k.moving()){var l=a.util.indexOf(this.layers,k.layer);-1===l&&this.onItemRemoved(k)}}},b.prototype.remove=function(b){var c=this.items.indexOf(b);if(-1!==c)return this.items.splice(c,1),this.outline.remove(b.id),!0;for(var d=this.getSize(),e=0;d>e;e++)if(this.items[e].type===a.item.Type.GROUP){var f=this.managers[this.items[e].id].remove(id);if(f)return!0}return!1},b.prototype.removeFromMap=function(b){var c=this.layers.remove(b.layer);if("undefined"!=typeof c)return c;for(var d=this.getSize(),e=0;d>e;e++)if(this.items[e].type===a.item.Type.GROUP){var f=this.managers[this.items[e].id].removeFromMap(b);if(null!==f)return f}return null},b.prototype.setLayers=function(a){for(this.layers.un("change:length",this.onLayerChanged,this);this.items.length>0;)this.onItemRemoved(this.items[this.items.length-1]);this.layers=a,this.layers.on("change:length",this.onLayerChanged,this);for(var b=0;bc;c++)a.push(this.items[c]);return a},a.manager.NodeManager=function(a,c,d,e){var f=new b(a,c,d,e);return{getById:f.getById.bind(f),getByLayer:f.getByLayer.bind(f),moveDown:f.moveDown.bind(f),moveUp:f.moveUp.bind(f),off:f.off.bind(f),on:f.on.bind(f),removeFromMap:f.removeFromMap.bind(f),setLayers:f.setLayers.bind(f)}},a}(olexp||{}),olexp.measure=olexp.measure||{},function(a){a.measure.properties={area:"olexp-measure-property-area",length:"olexp-measure-property-length"};var b=function(a){ol.Overlay.call(this,a)};b.prototype=Object.create(ol.Overlay.prototype);var c=function(a,b,c){var d=$.extend(!0,{measure:{Tool:{continueLineMsg:"Click to continue drawing the line",continuePolygonMsg:"Click to continue drawing the polygon",helpTooltipOffset:[20,0],helpTooltipPositioning:"center-left",measuredStyle:new ol.style.Style({fill:new ol.style.Fill({color:"rgba(255, 255, 255, 0.2)"}),stroke:new ol.style.Stroke({color:"#ffcc33",width:2}),image:new ol.style.Circle({radius:7,fill:new ol.style.Fill({color:"#ffcc33"})})}),measuringStyle:new ol.style.Style({fill:new ol.style.Fill({color:"rgba(255, 255, 255, 0.2)"}),stroke:new ol.style.Stroke({color:"rgba(0, 0, 0, 0.5)",lineDash:[10,10],width:2}),image:new ol.style.Circle({radius:5,stroke:new ol.style.Stroke({color:"rgba(0, 0, 0, 0.7)"}),fill:new ol.style.Fill({color:"rgba(255, 255, 255, 0.2)"})})}),measureTooltipOffset:[0,-20],measureTooltipPositioning:"bottom-center",messageStart:"Click to start drawing. Double click to stop."}}},c);this.settings=d.measure.Tool,this.continueLineMsg=this.settings.continueLineMsg,this.continuePolygonMsg=this.settings.continuePolygonMsg,this.count=0,this.draw=null,this.drawing=!1,this.geodesic=!1,this.helpTooltip=null,this.helpTooltipElement=null,this.map=a,this.measureTooltip=null,this.measureTooltipElement=null,this.pointerMoveCallback=this.onPointerMove.bind(this),this.sketch=null,this.source=null,this.sphere=new ol.Sphere(6378137),this.type=b,this.vector=null};return c.prototype.createHelpTooltip=function(){this.helpTooltipElement&&this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement),this.helpTooltipElement=document.createElement("div"),this.helpTooltipElement.className="olexp-measure olexp-measure-hidden",this.helpTooltip=new a.measure.Overlay({element:this.helpTooltipElement,offset:this.settings.helpTooltipOffset,positioning:this.settings.helpTooltipPositioning}),this.map.addOverlay(this.helpTooltip)},c.prototype.createMeasureVector=function(){this.vector=new ol.layer.Vector({source:this.source,style:this.settings.measuredStyle}),this.vector.set("name","Measurement #"+(this.count+1)),this.map.addLayer(this.vector)},c.prototype.createMeasureTooltip=function(){this.measureTooltipElement&&this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement),this.measureTooltipElement=document.createElement("div"),this.measureTooltipElement.className="olexp-measure olexp-measure-active",this.measureTooltip=new a.measure.Overlay({element:this.measureTooltipElement,offset:this.settings.measureTooltipOffset,positioning:this.settings.measureTooltipPositioning}),this.measureTooltip.set("name","Measurement #"+(this.count+1)),this.map.addOverlay(this.measureTooltip)},c.prototype.formatArea=function(a){var b=0;if(this.geodesic){var c=this.map.getView().getProjection(),d=a.clone().transform(c,"EPSG:4326"),e=d.getLinearRing(0).getCoordinates();b=Math.abs(this.sphere.geodesicArea(e))}else b=a.getArea();var f="";return f=b>1e4?Math.round(b/1e6*100)/100+" km2":Math.round(100*b)/100+" m2"},c.prototype.formatLength=function(a){var b=0;if(this.geodesic)for(var c=this.map.getView().getProjection(),d=a.getCoordinates(),e=d.length,f=0;e-1>f;++f){var g=ol.proj.transform(d[f],c,"EPSG:4326"),h=ol.proj.transform(d[f+1],c,"EPSG:4326");b+=this.sphere.haversineDistance(g,h)}else b=Math.round(100*a.getLength())/100;var i;return i=b>100?Math.round(b/1e3*100)/100+" km":Math.round(100*b)/100+" m"},c.prototype.onPointerMove=function(a){if(!a.dragging){var b=this.settings.messageStart;if(this.sketch){var c=this.sketch.getGeometry();c instanceof ol.geom.Polygon?b=this.continuePolygonMsg:c instanceof ol.geom.LineString&&(b=this.continueLineMsg)}this.helpTooltipElement.innerHTML=b,this.helpTooltip.setPosition(a.coordinate),$(this.helpTooltipElement).removeClass("olexp-measure-hidden")}},c.prototype.setEnable=function(a){a?this.map.on("pointermove",this.pointerMoveCallback):this.map.un("pointermove",this.pointerMoveCallback),this.setInteraction(a)},c.prototype.setInteraction=function(b){"undefined"==typeof b&&(b=!0);var c=this;if(this.draw&&this.map.removeInteraction(this.draw),!b)return $(this.helpTooltipElement).addClass("olexp-measure-hidden"),void(this.drawing&&(this.map.removeLayer(this.vector),this.vector=null,this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement),this.measureTooltipElement=null,this.drawing=!1));$(this.helpTooltipElement).removeClass("olexp-measure-hidden"),this.source=new ol.source.Vector,this.draw=new ol.interaction.Draw({source:this.source,type:this.type,style:this.settings.measuringStyle}),this.map.addInteraction(this.draw),this.createMeasureTooltip(),this.createHelpTooltip();var d=null;this.draw.on("drawstart",function(a){this.drawing=!0,c.createMeasureVector();var b=a.coordinate;c.sketch=a.feature,d=c.sketch.getGeometry().on("change",function(a){var d="",e=a.target;e instanceof ol.geom.Polygon?(d=c.formatArea(e),b=e.getInteriorPoint().getCoordinates()):e instanceof ol.geom.LineString&&(d=c.formatLength(e),b=e.getLastCoordinate()),c.measureTooltipElement.innerHTML=d,c.measureTooltip.setPosition(b)})},this),this.draw.on("drawend",function(b){this.drawing=!1,c.count+=1;var e=c.sketch.getGeometry(),f={};e instanceof ol.geom.Polygon?(f[a.measure.properties.area]=c.formatArea(e),c.vector.setProperties(f)):e instanceof ol.geom.LineString&&(f[a.measure.properties.length]=c.formatLength(e),c.vector.setProperties(f)),c.sketch=null,c.measureTooltipElement.parentNode.removeChild(c.measureTooltipElement),c.measureTooltipElement=null,c.createMeasureTooltip(),ol.Observable.unByKey(d),c.setInteraction(!0)},this)},c.prototype.setType=function(a){this.type=a},a.measure.Tool=function(b,d){"undefined"==typeof d&&(d={}),"undefined"==typeof d.type&&(d.type=a.measure.Type.LINE),"undefined"==typeof d.settings&&(d.settings={});var e=new c(b,d.type,d.settings);return{setEnable:function(a){e.setEnable(a)},setType:function(a){e.setType(a)}}},a.measure.Type={AREA:"Polygon",LINE:"LineString"},a.measure.Overlay=b,a}(olexp||{}),olexp.menu=olexp.menu||{},function(a){var b=function(a,b){var c=$.extend(!0,{menu:{Properties:{field:35,form:{},popup:{height:130,style:"width: 100%; height: 100%;",title:"Edit Layer",width:365},span:4,text:"Properties"}}},b);this.icon="olexp-menu-properties",this.form=b.prefix+"-menu-properties-form",this.id=b.prefix+"-menu-properties",this.manager=a,this.name="layerform",this.settings=c.menu.Properties};return b.prototype.onClick=function(b){var c=this,d=b.target,e=this.manager.getById(d),f=e.getProperties(),g=this.settings.popup.height,h=this.settings.field,i=[];g+=h,i.push({field:"name",html:{caption:"Name",span:this.settings.span},required:!0,type:"text"});for(var j=e.getPropertyTypes(),k=$.map(j,function(a){return a.title}),l=0;ld;d++)if(b===a.item(d))return d;return-1},a.util.popup=function(a,b,c,d){var e=c.name,f=c.record;w2ui.hasOwnProperty(e)&&w2ui[e].destroy(),$().w2form($.extend(c,{actions:{save:function(){var a=this.validate();if(0===a.length){w2popup.close();var c=w2ui[e],d=c.getChanges();b(d)}},reset:function(){var a=w2ui[e];for(var b in f)a.record[b]=f[b];a.refresh()}}})),w2popup.open($.extend(d,{body:'
',onOpen:function(b){b.onComplete=function(){$("#w2ui-popup #"+a).w2render(e)}},onToggle:function(a){var b=w2ui[e];$(b.box).hide(),a.onComplete=function(){$(b.box).show(),b.resize()}}}))},a.util.toProperties=function(a){var b=a.getProperties();if(b.hasOwnProperty("features")){var c=b.features;if(c instanceof Array)if(1===c.length)c[0]instanceof ol.Feature&&(b=c[0].getProperties());else for(var d=0,e=0;e
'},olmap:{target:d+"-explorer-id-map"},overlays:{id:d+"-explorer-id-overlays"},settings:{prefix:d}});var e=this,f=$("
",{id:this.options.explorer.id,"class":this.options.explorer.cls});$("#"+b).append(f),this.layout=$("#"+this.options.explorer.id).w2layout({name:this.options.explorer.layout,panels:[this.options.navigation,this.options.map,this.options.toolbar]}),this.toolbar=$("").w2toolbar({name:this.options.explorer.toolbar}),this.navigation=$("").w2layout({name:this.options.explorer.navigation,onResize:function(){e.hasOwnProperty("map")&&e.map.updateSize(),e.hasOwnProperty("details")&&e.details.resize()},panels:[this.options.outline,this.options.details]}),this.outline=$("").w2sidebar({name:this.options.explorer.outline,nodes:[this.options.layers,this.options.overlays],onClick:function(a){var b=a.target,c=e.manager.getDetails(b);e.details.clear(),e.details.add(c),e.manager.onItemSelected(b)},onDblClick:function(a){var b=a.target;e.manager.toggleNode(b),e.manager.onItemSelected(b)},onRender:function(a){a.onComplete=function(){var a=e.outline.selected;e.manager.onItemSelected(a)}}}),this.details=$("").w2grid({columns:[{field:"property",caption:"Property",size:"100%",sortable:!0},{field:"value",caption:"Value",size:"100%",sortable:!0}],name:this.options.explorer.details}),this.navigation.content(this.options.outline.type,this.outline),this.navigation.content(this.options.details.type,this.details),this.layout.content(this.options.navigation.type,this.navigation),this.map=new ol.Map(this.options.olmap),this.manager=new a.manager.Manager(this.map,this.outline,this.details,this.options.layers.id,this.options.overlays.id);var g=a.menu.Zoom(this.manager,this.options.settings),h=a.menu.Properties(this.manager,this.options.settings),i=a.menu.Remove(this.manager,this.options.settings);this.menu={items:[],callbacks:{}},this.menu.items.push(g.menu),this.menu.items.push(h.menu),this.menu.items.push(i.menu),this.menu.callbacks[g.menu.id]=g.click,this.menu.callbacks[h.menu.id]=h.click,this.menu.callbacks[i.menu.id]=i.click,this.outline.menu=this.menu.items,this.outline.onMenuClick=function(a){var b=a.menuItem.id;b in e.menu.callbacks&&e.menu.callbacks[b](a)},this.util=new a.util.Util(this.options.settings);var j=this.util.getInteractions(this.map);for(var k in this.options.olinteractions){var l=j[k];this.options.olinteractions[k]&&this.map.addInteraction(l)}var m=this.util.getControls();for(var n in this.options.olcontrols){var o=m[n];this.map.addControl(o),o.setMap(this.options.olcontrols[n]?this.map:null)}this.selector=new a.selection.Feature(this.map,this.details),this.selector.setEnable(!0),this.api={details:this.details,layout:this.layout,manager:this.manager,map:this.map,navigation:this.navigation,options:this.options,outline:this.outline,toolbar:this.toolbar},this.options.controls.toolbarhide&&(this.toolbar.add(a.control.ToolbarHide(this.api,{hidden:this.options.toolbar.hidden,settings:this.options.settings})),this.toolbar.add({id:"break-toolbar-hide",type:"break"})),this.options.controls.layermanager&&(this.toolbar.add(a.control.LayerManager(this.api,this.manager,{details:{checked:!this.options.details.hidden},navigation:{checked:!this.options.navigation.hidden},settings:this.options.settings})),this.toolbar.add({id:"break-layer-manager",type:"break"})),this.options.controls.layermenu&&(this.toolbar.add(a.control.LayerMenu(this.api,this.manager,this.menu,{settings:this.options.settings})),this.toolbar.add({id:"break-item-menu",type:"break"})),this.options.controls.layercontrol&&(this.toolbar.add(a.control.LayerControl(this.api,{settings:this.options.settings})),this.toolbar.add({id:"break-layer-control",type:"break"})),this.options.controls.graticule&&(this.toolbar.add(a.control.Graticule(this.api,{settings:this.options.settings})),this.toolbar.add({id:"break-graticule",type:"break"})),this.options.controls.measure&&(this.toolbar.add(a.control.Measure(this.api,{settings:this.options.settings})),this.toolbar.add({id:"break-measure",type:"break"})),this.options.controls.exportmap&&(this.toolbar.add(a.control.ExportMap(this.api,{settings:this.options.settings})),this.toolbar.add({id:"break-export-map",type:"break"})),this.options.controls.editsettings&&(this.toolbar.add(a.control.EditSettings(this.api,{settings:this.options.settings})),this.toolbar.add({id:"break-edit-settings",type:"break"})),this.layout.set(this.options.toolbar.type,{content:"",show:{toolbar:!0},toolbar:this.toolbar})};a.destroy=function(a){void 0!==a.map&&a.map.setTarget(null),void 0!==a.details&&a.details.destroy(),void 0!==a.outline&&a.outline.destroy(),void 0!==a.navigation&&a.navigation.destroy(),void 0!==a.toolbar&&a.toolbar.destroy(),void 0!==a.layout&&a.layout.destroy()},a.Explorer=function(a,c){var d=new b(a,c);return d.api}}(olexp||{}),olexp.event=olexp.event||{},function(a){"use strict";var b=function(a){this.listeners=$.extend({},a)};return b.prototype.on=function(a,b,c){if(a in this.listeners){var d=b;"undefined"!=typeof c&&(d=b.bind(c)),this.listeners[a].push(d)}},b.prototype.register=function(a){a in this.listeners||(this.listeners[a]=[])},b.prototype.trigger=function(){var a=Array.prototype.slice.call(arguments),b=a.shift();if(b in this.listeners)for(var c=0;c-1&&this.listeners[a].splice(e,1)}},a.event.Event=function(a){var c=new b(a);return c},a}(olexp||{}),olexp.control=olexp.control||{},function(a){"use strict";var b=function(a,b){var c=$.extend(!0,{control:{EditSettings:{form:{header:"",style:"border: 0px; background-color: transparent;"},hint:"Edit Controls",popup:{height:380,style:"width: 100%; height: 100%;",title:"Edit Controls",width:225},span:6}}},b);this.settings=c.control.EditSettings,this.button=b.prefix+"-control-edit-settings-button",this.icon="olexp-control-edit-settings",this.id=b.prefix+"-control-edit-settings-form",this.map=a,this.name=b.prefix+"-control-edit-settings-form"};return b.prototype.display=function(){var b=this,c=[{html:{caption:"Full Screen",span:this.settings.span},name:"fullscreen",type:"checkbox"},{html:{caption:"Mouse Position",span:this.settings.span},name:"mouseposition",type:"checkbox"},{html:{caption:"Overview Map",span:this.settings.span},name:"overviewmap",type:"checkbox"},{html:{caption:"Rotate",span:this.settings.span},name:"rotate",type:"checkbox"},{html:{caption:"Scale Line",span:this.settings.span},name:"scaleline",type:"checkbox"},{html:{caption:"Zoom",span:this.settings.span},name:"zoom",type:"checkbox"},{html:{caption:"Zoom Slider",span:this.settings.span},name:"zoomslider",type:"checkbox"},{html:{caption:"Zoom To Extent",span:this.settings.span},name:"zoomtoextent",type:"checkbox"}],d={fullscreen:this.isControlActive("fullscreen"),mouseposition:this.isControlActive("mouseposition"),overviewmap:this.isControlActive("overviewmap"),rotate:this.isControlActive("rotate"),scaleline:this.isControlActive("scaleline"),zoom:this.isControlActive("zoom"),zoomslider:this.isControlActive("zoomslider"),zoomtoextent:this.isControlActive("zoomtoextent")},e=function(a){for(var c in a){var d=a[c];b.setControl(c,d)}},f=$.extend(this.settings.form,{fields:c,name:this.name,record:d}),g=this.settings.popup;a.util.popup(this.id,e,f,g)},b.prototype.getControl=function(a){for(var b=this.map.getControls().getArray(),c=0;c');var d=document.getElementById(a);d.addEventListener("click",c.bind(this),!1),$("#"+a)[0].click(),$("#"+a).remove()},a.control.ExportMap=function(a,c){var d=new b(a.map,c.settings);return{hint:d.settings.hint,id:d.button,img:d.icon,onClick:function(a){d.toImage()},type:"button"}},a}(olexp||{}),function(a){var b=function(b,c){var d=$.extend(!0,{control:{Graticule:{enable:!1,form:{header:"",style:"border: 0px; background-color: transparent;"},hint:"Edit Grid Lines",options:{color:"000000",lineDash:[.5,4],width:2},popup:{height:225,style:"border: 0px; background-color: transparent;",title:"Edit Grid Lines",width:300},span:3}}},c);this.settings=d.control.Graticule,this.button=c.prefix+"-control-graticule-button",this.icon="olexp-control-graticule",this.id=c.prefix+"-control-graticule",this.map=b,this.name=c.prefix+"-control-graticule-form",this.util=new a.util.Util(d),this.graticule=this.util.getGraticule(this.settings.enable?this.map:null,$.extend({},this.settings.options))};return b.prototype.display=function(){var b=this,c=[{html:{caption:"Enable",span:this.settings.span},name:"enable",required:!0,type:"checkbox"},{html:{caption:"Color",span:this.settings.span},name:"color",options:{silent:!1},required:!0,type:"color"},{html:{caption:"Width",span:this.settings.span},name:"width",options:{arrows:!0,max:4,min:.25,placeholder:"0.25 - 4",silent:!1,step:.25},required:!0,type:"float"}],d=this.graticule.olexp_record,e=function(a){for(var c in a)d[c]=a[c];var e=$.extend({},d);delete e.enable,b.graticule.setMap(null),b.graticule=b.util.getGraticule(d.enable?b.map:null,e)},f=$.extend(this.settings.form,{fields:c,name:this.name,record:d}),g=this.settings.popup;a.util.popup(this.id,e,f,g)},a.control.Graticule=function(a,c){"undefined"==typeof c&&(c={}),"undefined"==typeof c.settings&&(c.settings={});var d=new b(a.map,c.settings);return{hint:d.settings.hint,id:d.button,img:d.icon,onClick:function(a){d.display()},type:"button"}},a}(olexp||{}),function(a){var b=function(b,c){var d=$.extend(!0,{control:{LayerControlTile:{form:{header:"",style:"border: 0px; background-color: transparent;"},hint:"Add Tile Layer",popup:{height:165,style:"border: 0px; background-color: transparent;",title:"Add Tile Layer",width:290},span:3},LayerControlVector:{form:{header:"File Types: "+$.map(a.util.FileTypes,function(a){return" "+a.name}),style:"border: 0px; background-color: transparent;"},hint:"Add Vector Layer",popup:{height:195,style:"border: 0px; background-color: transparent;",title:"Add Vector Layer",width:350},span:4}}},c);this.settingsTile=d.control.LayerControlTile,this.settingsVector=d.control.LayerControlVector,this.icons={tile:"olexp-control-layer-control-add-tile",vector:"olexp-control-layer-control-add-vector"},this.buttons={tile:c.prefix+"-control-layer-control-add-tile-button",vector:c.prefix+"-control-layer-control-add-vector-button"},this.ids={tile:c.prefix+"-control-layer-control-add-tile",vector:c.prefix+"-control-layer-control-add-vector"},this.map=b,this.names={tile:c.prefix+"-control-tile-form",vector:c.prefix+"-control-vector-form"},this.util=new a.util.Util(this.map)};return b.prototype.tile=function(){var b=this,c=this.util.getTileTypes(),d=$.map(c,function(a){return a.name}),e=[{field:"tile_source",html:{caption:"Source",span:this.settingsTile.span},options:{items:d},required:!0,type:"list"}],f={};f[e[0].field]=null;var g=function(a){for(var d in a)if(d===e[0].field){var f=a[d].id;for(var g in c)if(f===c[g].name){var h=c[g],i=h["class"],j=new ol.layer.Tile({source:new i(h.settings)});j.set("name",f),b.map.addLayer(j)}}},h=$.extend(this.settingsTile.form,{fields:e,name:this.names.tile,record:f}),i=this.settingsTile.popup;a.util.popup(this.ids.tile,g,h,i)},b.prototype.vector=function(){var b=this,c=[{field:"vector_source",html:{caption:"Source",span:this.settingsVector.span},options:{placeholder:"Click to add file",silent:!1},required:!0,type:"file"}],d={};d[c[0].field]=null;var e=function(d){for(var e in d)if(e===c[0].field)for(var f in d[e]){var g=d[e][f].content;if("undefined"!=typeof g&&null!==g){var h=d[e][f].name,i=h.replace(/\.[^\/.]+$/,""),j=a.util.getReader(h);if(null===j)return void w2alert("Unable to open file "+h,"Error");var k=atob(g),l=b.map.getView().getProjection(),m={featureProjection:l},n=j.readFeatures(k,m);b.util.addLayerVector(b.map,i,n)}}},f=$.extend(this.settingsVector.form,{fields:c,name:this.names.vector,record:d}),g=this.settingsVector.popup;a.util.popup(this.ids.vector,e,f,g)},a.control.LayerControl=function(a,c){"undefined"==typeof c&&(c={}),"undefined"==typeof c.tile&&(c.tile=!0),"undefined"==typeof c.vector&&(c.vector=!0),"undefined"==typeof c.settings&&(c.settings={});var d=new b(a.map,c.settings),e=[];return c.tile&&e.push({hint:d.settingsTile.hint,id:d.buttons.tile,img:d.icons.tile,onClick:function(a){d.tile()},type:"button"}),c.vector&&e.push({hint:d.settingsVector.hint,id:d.buttons.vector,img:d.icons.vector,onClick:function(a){d.vector()},type:"button"}),e},a}(olexp||{}),olexp=function(a){var b=function(a,b,c){var d=$.extend(!0,{control:{LayerManager:{hintDetailsHide:"Hide details",hintDetailsShow:"Show details",hintMoveDown:"Move item down",hintMoveUp:"Move item up",hintOutlineHide:"Hide outline",hintOutlineShow:"Show outline"}}},c);this.buttons={details:c.prefix+"-control-layer-manager-button-details",down:c.prefix+"-control-layer-manager-button-down",navigation:c.prefix+"-control-layer-manager-button-navigation",up:c.prefix+"-control-layer-manager-button-up"},this.explorer=a,this.icons={details:"olexp-control-layer-manager-details",down:"olexp-control-layer-manager-down",navigation:"olexp-control-layer-manager-navigation",up:"olexp-control-layer-manager-up"},this.manager=b,this.settings=d.control.LayerManager,this.manager.on("remove:item",this.onItemRemoved,this),this.manager.on("select:item",this.onItemSelected,this)};return b.prototype.details=function(){this.explorer.navigation.toggle(this.explorer.options.details.type);var a=this.explorer.navigation.get(this.explorer.options.details.type),b=this.explorer.toolbar.get(this.buttons.details);b.hint=this.hintDetails(a.hidden),this.explorer.toolbar.refresh()},b.prototype.down=function(){this.manager.moveDown()},b.prototype.hintDetails=function(a){return a?this.settings.hintDetailsShow:this.settings.hintDetailsHide},b.prototype.hintNavigation=function(a){return a?this.settings.hintOutlineShow:this.settings.hintOutlineHide},b.prototype.navigation=function(){this.explorer.layout.toggle(this.explorer.options.navigation.type);var a=this.explorer.layout.get(this.explorer.options.navigation.type),b=this.explorer.toolbar.get(this.buttons.navigation);b.hint=this.hintNavigation(a.hidden),this.explorer.toolbar.refresh()},b.prototype.onItemRemoved=function(a){this.manager.isSelected(a.id)&&(this.explorer.toolbar.disable(this.buttons.up),this.explorer.toolbar.disable(this.buttons.down))},b.prototype.onItemSelected=function(a){if("undefined"!=typeof a){var b=this.manager.getById(a);if(null!==b){var c=this.manager.getNode(b.id);c.disabled?(this.explorer.toolbar.disable(this.buttons.up),this.explorer.toolbar.disable(this.buttons.down)):(this.explorer.toolbar.enable(this.buttons.up),this.explorer.toolbar.enable(this.buttons.down))}}},b.prototype.up=function(){this.manager.moveUp()},a.control.LayerManager=function(a,c,d){"undefined"==typeof d&&(d={}),"undefined"==typeof d.details&&(d.details={}),"undefined"==typeof d.details.enabled&&(d.details.enabled=!0),"undefined"==typeof d.details.checked&&(d.details.checked=!0),"undefined"==typeof d.down&&(d.down=!0),"undefined"==typeof d.navigation&&(d.navigation={}),"undefined"==typeof d.navigation.enabled&&(d.navigation.enabled=!0),"undefined"==typeof d.navigation.checked&&(d.navigation.checked=!0),"undefined"==typeof d.up&&(d.up=!0);var e=new b(a,c,d.settings),f=[];return d.navigation.enabled&&f.push({checked:d.navigation.checked,hint:e.hintNavigation(!d.navigation.checked),id:e.buttons.navigation,img:e.icons.navigation,onClick:function(a){e.navigation()},type:"check"}),d.details.enabled&&f.push({checked:d.details.checked,hint:e.hintDetails(!d.details.checked),id:e.buttons.details,img:e.icons.details,onClick:function(a){e.details()},type:"check"}),d.up&&f.push({disabled:!0,hint:e.settings.hintMoveUp,id:e.buttons.up,img:e.icons.up,onClick:function(a){e.up()},type:"button"}),d.down&&f.push({disabled:!0,hint:e.settings.hintMoveDown,id:e.buttons.down,img:e.icons.down,onClick:function(a){e.down()},type:"button"}),f},a}(olexp||{}),function(a){var b=function(a,b,c,d){var e=$.extend(!0,{control:{LayerMenu:{arrow:!0,hint:"Item Options",text:""}}},d);this.button=d.prefix+"-control-layer-menu",this.explorer=a,this.icon="olexp-control-layer-menu",this.manager=b,this.menu=c,this.settings=e.control.LayerMenu,this.manager.on("remove:item",this.onItemRemoved,this),this.manager.on("select:item",this.onItemSelected,this)};return b.prototype.onItemRemoved=function(a){this.manager.isSelected(a.id)&&this.explorer.toolbar.disable(this.button)},b.prototype.onItemSelected=function(a){if("undefined"!=typeof a){var b=this.manager.getById(a);if(null!==b){var c=this.manager.getNode(b.id);c.disabled?this.explorer.toolbar.disable(this.button):this.explorer.toolbar.enable(this.button)}}},a.control.LayerMenu=function(a,c,d,e){var f=new b(a,c,d,e.settings);return a.toolbar.on("click",function(b){if(null!==a.outline.selected){var c=f.button+":";if(!(b.target.indexOf(c)<0)){var e=b.target.replace(c,"");e in d.callbacks&&d.callbacks[e]({target:a.outline.selected})}}}),{arrow:f.settings.arrow,disabled:!0,hint:f.settings.hint,id:f.button,img:f.icon,items:f.menu.items,text:f.settings.text,type:"menu"}},a}(olexp||{}),function(a){var b=function(b,c){var d=$.extend(!0,{control:{Measurement:{hintArea:"Measure area",hintLength:"Measure length"}}},c);this.explorer=b,this.icons={area:"olexp-control-measure-area",length:"olexp-control-measure-length"},this.ids={area:c.prefix+"-control-measure-area-button",length:c.prefix+"-control-measure-length-button"},this.settings=d.control.Measurement,this.tool=new a.measure.Tool(b.map,{type:a.measure.Type.LINE,settings:c})};return b.prototype.area=function(){var b=!this.explorer.toolbar.get(this.ids.area).checked;this.measure(a.measure.Type.AREA,b)},b.prototype.length=function(){var b=!this.explorer.toolbar.get(this.ids.length).checked;this.measure(a.measure.Type.LINE,b)},b.prototype.measure=function(a,b){this.tool.setEnable(!1),b&&(this.tool.setType(a),this.tool.setEnable(!0))},a.control.Measure=function(a,c){"undefined"==typeof c&&(c={}),"undefined"==typeof c.area&&(c.area=!0),"undefined"==typeof c.length&&(c.length=!0),"undefined"==typeof c.settings&&(c.settings={});var d=new b(a,c.settings),e=[];return c.area&&e.push({hint:d.settings.hintArea,id:d.ids.area,img:d.icons.area,onClick:function(b){c.length&&a.toolbar.uncheck(d.ids.length),d.area()},type:"check"}),c.length&&e.push({hint:d.settings.hintLength,id:d.ids.length,img:d.icons.length,onClick:function(b){c.area&&a.toolbar.uncheck(d.ids.area),d.length()},type:"check"}),e},a}(olexp||{}),function(a){var b=function(b,c){var d=$.extend(!0,{control:{ToolbarHide:{hint:"Hide toolbar"}}},c.settings);this.button=c.settings.prefix+"-control-toolbar-hide-button",this.explorer=b,this.icon="olexp-control-toolbar-hide",this.settings=d.control.ToolbarHide,this.show=a.ol.ToolbarShow(this.explorer,c)};return b.prototype.hide=function(){this.explorer.layout.hide(this.explorer.options.toolbar.type),this.show.setMap(this.explorer.map)},a.control.ToolbarHide=function(a,c){var d=new b(a,c);return{hint:d.settings.hint,id:d.button,img:d.icon,onClick:function(a){d.hide()},type:"button"}},a}(olexp||{}),olexp.item=olexp.item||{},function(a){"use strict";a.item.icons={group:"olexp-item-group",heatmap:"olexp-item-heatmap",image:"olexp-item-image",overlay:"olexp-item-overlay",tile:"olexp-item-tile",vector:"olexp-item-vector"};var b=function(a,c,d){this.id=a,this.layer=d,this.moving=!1,this.name=c,this.type=b.getType(this.layer),this.icon=b.getIcon(this.type)};return b.prototype.getDetails=function(){var b={};b.Name=this.name;var c=this.layer.getProperties();if(c.hasOwnProperty(a.measure.properties.area)?b.Area=c[a.measure.properties.area]:c.hasOwnProperty(a.measure.properties.length)&&(b.Length=c[a.measure.properties.length]),this.type===a.item.Type.GROUP){var d=this.layer.getLayers();b["Layer Count"]=d.getLength()}if(this.type===a.item.Type.VECTOR){var e=this.layer.getSource(),f=e.getFeatures();b["Feature Count"]=f.length}var g=a.util.toRecords(b);return g},b.prototype.getExtent=function(){if(this.type===a.item.Type.OVERLAY)return null;if(this.type===a.item.Type.GROUP){var c=null,d=this.layer.getLayers();return d.forEach(function(a,d,e){var f=b.getLayerExtent(a);null===c&&null!==f?c=f:null!==c&&null!==f&&(c=ol.extent.extend(c,f))},this),c}return b.getLayerExtent(this.layer)},b.getIcon=function(b){return b===a.item.Type.GROUP?a.item.icons.group:b===a.item.Type.HEATMAP?a.item.icons.heatmap:b===a.item.Type.IMAGE?a.item.icons.image:b===a.item.Type.OVERLAY?a.item.icons.overlay:b===a.item.Type.TILE?a.item.icons.tile:b===a.item.Type.VECTOR?a.item.icons.vector:"icon-page"},b.getLayerExtent=function(a){var b=a.getExtent();if("undefined"==typeof b){var c=a.getSource();null!==c&&(c instanceof ol.source.Cluster||c instanceof ol.source.VectorTile||c instanceof ol.source.Vector)&&(b=c.getExtent())}return"undefined"==typeof b?null:b},b.prototype.getPropertyTypes=function(){return this.layer instanceof ol.layer.Layer?a.item.LayerProperties:this.layer instanceof ol.Overlay?a.item.OverlayProperties:{}},b.prototype.getProperties=function(){var a={name:this.name},b=this.getPropertyTypes();for(var c in b)a[c]=this.layer.get(c);return a},b.getType=function(b){return b instanceof ol.layer.Group?a.item.Type.GROUP:b instanceof ol.layer.Heatmap?a.item.Type.HEATMAP:b instanceof ol.layer.Image?a.item.Type.IMAGE:b instanceof ol.layer.Tile?a.item.Type.TILE:b instanceof ol.layer.Vector?a.item.Type.VECTOR:b instanceof ol.Overlay?a.item.Type.OVERLAY:null},b.prototype.setProperties=function(a){a.hasOwnProperty("name")&&(this.name=a.name);var b=this.getPropertyTypes();for(var c in b)a.hasOwnProperty(c)&&this.layer.set(c,a[c])},b.prototype.property=function(a,b){return"undefined"!=typeof this[a]?("undefined"!=typeof b&&(this[a]=b),this[a]):void 0},b.prototype.zoomTo=function(b){var c=b.getView();if(this.type===a.item.Type.OVERLAY){var d=this.layer.getPosition();if("undefined"!=typeof d)return void c.setCenter(d);w2alert("Overlay has no position defined to which to zoom.","Warning")}else{var e=this.getExtent();if(null!==e)return void c.fit(e,b.getSize());w2alert("Layer has no extent defined to which to zoom.","Warning")}},a.item.Item=function(a,c,d){var e=new b(a,c,d);return{getDetails:e.getDetails.bind(e),getProperties:e.getProperties.bind(e),getPropertyTypes:e.getPropertyTypes.bind(e),icon:e.icon,id:e.id,layer:e.layer,moving:function(a){return e.property("moving",a)},name:function(a){return e.property("name",a)},setProperties:e.setProperties.bind(e),type:e.type,zoomTo:e.zoomTo.bind(e)}},a.item.OverlayProperties={},a.item.LayerProperties={opacity:{title:"Opacity"}},a.item.Type={GROUP:0,HEATMAP:1,IMAGE:2,OVERLAY:3,TILE:4,VECTOR:5},a}(olexp||{}),olexp.manager=olexp.manager||{},function(a){"use strict";var b=function(b,c,d,e,f){this.event=new a.event.Event({"select:item":[]}),this.managerLayers=new a.manager.NodeManager(e,b.getLayers(),c,d),this.layersId=e,this.managerOverlays=new a.manager.NodeManager(f,b.getOverlays(),c,d),this.map=b,this.map.on("change:layergroup",this.onLayerGroupChanged,this),this.outline=c,this.overlaysId=f};return b.prototype.isIdLayerNode=function(a){return"string"!=typeof a?!1:0===a.indexOf(this.layersId)},b.prototype.isIdOverlayNode=function(a){return"string"!=typeof a?!1:0===a.indexOf(this.overlaysId)},b.prototype.isSelected=function(a){return a===this.outline.selected},b.prototype.getById=function(a){return this.isIdLayerNode(a)?this.managerLayers.getById(a):this.isIdOverlayNode(a)?this.managerOverlays.getById(a):null},b.prototype.getDetails=function(a){if(this.isIdLayerNode(a)){var b=this.managerLayers.getById(a);if(null!==b)return b.getDetails()}else if(this.isIdOverlayNode(a)){var c=this.managerOverlays.getById(a);if(null!==c)return c.getDetails()}return[]},b.prototype.getNode=function(a){return this.outline.get(a)},b.prototype.moveDown=function(a){return"undefined"==typeof a&&(a=this.outline.selected),this.isIdLayerNode(a)?this.managerLayers.moveDown(a):this.isIdOverlayNode(a)?this.managerOverlays.moveDown(a):!1},b.prototype.moveUp=function(a){return"undefined"==typeof a&&(a=this.outline.selected),this.isIdLayerNode(a)?this.managerLayers.moveUp(a):this.isIdOverlayNode(a)?this.managerOverlays.moveUp(a):!1},b.prototype.off=function(a,b,c){this.event.off(a,b,c),this.managerLayers.off(a,b,c),this.managerOverlays.off(a,b,c)},b.prototype.on=function(a,b,c){this.event.on(a,b,c),this.managerLayers.on(a,b,c),this.managerOverlays.on(a,b,c)},b.prototype.onItemSelected=function(a){this.event.trigger("select:item",a)},b.prototype.onLayerGroupChanged=function(a){this.managerLayers.setLayers(a.target.getLayers())},b.prototype.removeFromMap=function(a){return a.hasOwnProperty("id")?this.isIdLayerNode(a.id)?this.managerLayers.removeFromMap(a):this.isIdOverlayNode(a.id)?this.managerOverlays.removeFromMap(a):null:null},b.prototype.toggleNode=function(a){if("string"==typeof a){var b=this.outline.get(a),c=b.disabled;if(c?this.outline.enable(a):this.outline.disable(a),this.isIdLayerNode(a)){var d=this.managerLayers.getById(a);null!==d&&d.layer.setVisible(c)}else if(this.isIdOverlayNode(a)){var e=this.managerOverlays.getById(a);if(null!==e){var f=e.layer.getProperties();if(f.hasOwnProperty("element")){var g=$(f.element);c?g.show():g.hide()}}}}},b.prototype.updateItem=function(a,b){var c=this.getById(a);if(null!==c){c.setProperties(b);var d=this.outline.get(a);d.text=c.name(),this.outline.refresh()}},b.prototype.zoomTo=function(a){var b=this.getById(a);b.zoomTo(this.map)},a.manager.Manager=function(a,c,d,e,f){var g=new b(a,c,d,e,f);return{getById:g.getById.bind(g),getDetails:g.getDetails.bind(g),getNode:g.getNode.bind(g),isSelected:g.isSelected.bind(g),moveDown:g.moveDown.bind(g),moveUp:g.moveUp.bind(g),off:g.off.bind(g),on:g.on.bind(g),onItemSelected:g.onItemSelected.bind(g),removeFromMap:g.removeFromMap.bind(g),toggleNode:g.toggleNode.bind(g),updateItem:g.updateItem.bind(g),zoomTo:g.zoomTo.bind(g)}},a}(olexp||{}),function(a){var b=function(b,c,d,e){this.count=0,this.details=e,this.event=new a.event.Event({"remove:item":[]}),this.id=b,this.items=[],this.layers=c,this.layers.on("change:length",this.onLayerChanged,this),this.managers={},this.outline=d};return b.prototype.addLayer=function(c){this.count+=1;var d=this.id+"-"+this.count,e="Item "+this.count,f=c.getProperties();f.hasOwnProperty("name")&&(e=f.name);var g=new a.item.Item(d,e,c);this.items.push(g);var h={id:g.id,img:g.icon,text:g.name()},i=this.outline.get(this.id).nodes;if(0===i.length?this.outline.add(this.id,[h]):this.outline.insert(this.id,i[0].id,[h]),g.type===a.item.Type.GROUP){var j=c.getLayers(),k=new b(g.id,j,this.outline,this.details);j.forEach(function(a){k.addLayer(a)},this),this.managers[g.id]=k,this.outline.expand(g.id)}return g},b.prototype.getById=function(b,c){"undefined"==typeof c&&(c=!0);for(var d=this.getSize(),e=0;d>e;e++){if(this.items[e].id===b)return this.items[e];if(this.items[e].type===a.item.Type.GROUP&&c){var f=this.managers[this.items[e].id].getById(b);if(null===f)continue;if(f.id===b)return f}}return null},b.prototype.getByLayer=function(b,c){"undefined"==typeof c&&(c=!0);for(var d=this.getSize(),e=0;d>e;e++){if(this.items[e].layer===b)return this.items[e];if(this.items[e].type===a.item.Type.GROUP&&c){var f=this.managers[this.items[e].id].getByLayer(b);if(null===f)continue;if(f.layer===b)return f}}return null},b.prototype.getSize=function(){return this.items.length},b.prototype.isSelected=function(a){return a===this.outline.selected},b.prototype.isHidden=function(b){return b instanceof a.measure.Overlay},b.prototype.moveDown=function(b){var c=this.getById(b,!1);if(null!==c){var d=this.moveLayerUp(this.layers,c.layer);return d&&(d=this.moveItemDown(b)),d}for(var e=this.getSize(),f=0;e>f;f++)if(this.items[f].type===a.item.Type.GROUP){var g=this.managers[this.items[f].id].moveDown(b);if(null!==g)return g}return null},b.prototype.moveItemDown=function(a){var b=this.outline.get(a);if(null===b)return!1;var c=this.outline.find(b.parent.id,{parent:b.parent}),d=this.outline.get(b.parent.id,a,!0);if(d>=c.length-1)return!1;var e=c[d+1].id,f=c[d+1];return b.parent!==f.parent?!1:(this.outline.remove(e),this.outline.insert(b.parent,a,f),this.outline.select(a),!0)},b.prototype.moveItemUp=function(a){var b=this.outline.get(a);if(null===b)return!1;var c=this.outline.find(b.parent.id,{parent:b.parent}),d=this.outline.get(b.parent.id,a,!0);if(0>=d)return!1;var e=c[d-1].id,f=c[d-1];return b.parent!==f.parent?!1:(this.outline.remove(a),this.outline.insert(b.parent,e,b),this.outline.select(a),!0)},b.prototype.moveLayerDown=function(b,c){var d=a.util.indexOf(b,c),e=this.layers.getLength();if(e-1>d){var f=this.getByLayer(c,!1);return f.moving(!0),b.removeAt(d),b.insertAt(d+1,c),f.moving(!1),!0}return!1},b.prototype.moveLayerUp=function(b,c){var d=a.util.indexOf(b,c);if(d>0){var e=this.getByLayer(c,!1);return e.moving(!0),b.removeAt(d),b.insertAt(d-1,c),e.moving(!1),!0}return!1},b.prototype.moveUp=function(b){var c=this.getById(b,!1);if(null!==c){var d=this.moveLayerDown(this.layers,c.layer); +return d&&(d=this.moveItemUp(b)),d}for(var e=this.getSize(),f=0;e>f;f++)if(this.items[f].type===a.item.Type.GROUP){var g=this.managers[this.items[f].id].moveUp(b);if(null!==g)return g}return null},b.prototype.off=function(b,c,d){this.event.off(b,c,d);for(var e=this.getSize(),f=0;e>f;f++)this.items[f].type===a.item.Type.GROUP&&this.managers[this.items[f].id].off(b,c,d)},b.prototype.on=function(b,c,d){this.event.on(b,c,d);for(var e=this.getSize(),f=0;e>f;f++)this.items[f].type===a.item.Type.GROUP&&this.managers[this.items[f].id].on(b,c,d)},b.prototype.onItemRemoved=function(a){this.event.trigger("remove:item",a),this.isSelected(a.id)&&this.details.clear(),this.remove(a)},b.prototype.onLayerChanged=function(b){for(var c=b.target,d=c.getLength(),e=0;d>e;e++){var f=c.item(e);if(!this.isHidden(f)){var g=this.getByLayer(f);null===g&&this.addLayer(f)}}for(var h=this.toList(),i=h.length,j=0;i>j;j++){var k=h[j];if(!k.moving()){var l=a.util.indexOf(this.layers,k.layer);-1===l&&this.onItemRemoved(k)}}},b.prototype.remove=function(b){var c=this.items.indexOf(b);if(-1!==c)return this.items.splice(c,1),this.outline.remove(b.id),!0;for(var d=this.getSize(),e=0;d>e;e++)if(this.items[e].type===a.item.Type.GROUP){var f=this.managers[this.items[e].id].remove(id);if(f)return!0}return!1},b.prototype.removeFromMap=function(b){var c=this.layers.remove(b.layer);if("undefined"!=typeof c)return c;for(var d=this.getSize(),e=0;d>e;e++)if(this.items[e].type===a.item.Type.GROUP){var f=this.managers[this.items[e].id].removeFromMap(b);if(null!==f)return f}return null},b.prototype.setLayers=function(a){for(this.layers.un("change:length",this.onLayerChanged,this);this.items.length>0;)this.onItemRemoved(this.items[this.items.length-1]);this.layers=a,this.layers.on("change:length",this.onLayerChanged,this);for(var b=0;bc;c++)a.push(this.items[c]);return a},a.manager.NodeManager=function(a,c,d,e){var f=new b(a,c,d,e);return{getById:f.getById.bind(f),getByLayer:f.getByLayer.bind(f),moveDown:f.moveDown.bind(f),moveUp:f.moveUp.bind(f),off:f.off.bind(f),on:f.on.bind(f),removeFromMap:f.removeFromMap.bind(f),setLayers:f.setLayers.bind(f)}},a}(olexp||{}),olexp.measure=olexp.measure||{},function(a){"use strict";a.measure.properties={area:"olexp-measure-property-area",length:"olexp-measure-property-length"};var b=function(a){ol.Overlay.call(this,a)};b.prototype=Object.create(ol.Overlay.prototype);var c=function(a,b,c){var d=$.extend(!0,{measure:{Tool:{continueLineMsg:"Click to continue drawing the line",continuePolygonMsg:"Click to continue drawing the polygon",helpTooltipOffset:[20,0],helpTooltipPositioning:"center-left",measuredStyle:new ol.style.Style({fill:new ol.style.Fill({color:"rgba(255, 255, 255, 0.2)"}),stroke:new ol.style.Stroke({color:"#ffcc33",width:2}),image:new ol.style.Circle({radius:7,fill:new ol.style.Fill({color:"#ffcc33"})})}),measuringStyle:new ol.style.Style({fill:new ol.style.Fill({color:"rgba(255, 255, 255, 0.2)"}),stroke:new ol.style.Stroke({color:"rgba(0, 0, 0, 0.5)",lineDash:[10,10],width:2}),image:new ol.style.Circle({radius:5,stroke:new ol.style.Stroke({color:"rgba(0, 0, 0, 0.7)"}),fill:new ol.style.Fill({color:"rgba(255, 255, 255, 0.2)"})})}),measureTooltipOffset:[0,-20],measureTooltipPositioning:"bottom-center",messageStart:"Click to start drawing. Double click to stop."}}},c);this.settings=d.measure.Tool,this.continueLineMsg=this.settings.continueLineMsg,this.continuePolygonMsg=this.settings.continuePolygonMsg,this.count=0,this.draw=null,this.drawing=!1,this.geodesic=!1,this.helpTooltip=null,this.helpTooltipElement=null,this.map=a,this.measureTooltip=null,this.measureTooltipElement=null,this.pointerMoveCallback=this.onPointerMove.bind(this),this.sketch=null,this.source=null,this.sphere=new ol.Sphere(6378137),this.type=b,this.vector=null};return c.prototype.createHelpTooltip=function(){this.helpTooltipElement&&this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement),this.helpTooltipElement=document.createElement("div"),this.helpTooltipElement.className="olexp-measure olexp-measure-hidden",this.helpTooltip=new a.measure.Overlay({element:this.helpTooltipElement,offset:this.settings.helpTooltipOffset,positioning:this.settings.helpTooltipPositioning}),this.map.addOverlay(this.helpTooltip)},c.prototype.createMeasureVector=function(){this.vector=new ol.layer.Vector({source:this.source,style:this.settings.measuredStyle}),this.vector.set("name","Measurement #"+(this.count+1)),this.map.addLayer(this.vector)},c.prototype.createMeasureTooltip=function(){this.measureTooltipElement&&this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement),this.measureTooltipElement=document.createElement("div"),this.measureTooltipElement.className="olexp-measure olexp-measure-active",this.measureTooltip=new a.measure.Overlay({element:this.measureTooltipElement,offset:this.settings.measureTooltipOffset,positioning:this.settings.measureTooltipPositioning}),this.measureTooltip.set("name","Measurement #"+(this.count+1)),this.map.addOverlay(this.measureTooltip)},c.prototype.formatArea=function(a){var b=0;if(this.geodesic){var c=this.map.getView().getProjection(),d=a.clone().transform(c,"EPSG:4326"),e=d.getLinearRing(0).getCoordinates();b=Math.abs(this.sphere.geodesicArea(e))}else b=a.getArea();var f="";return f=b>1e4?Math.round(b/1e6*100)/100+" km2":Math.round(100*b)/100+" m2"},c.prototype.formatLength=function(a){var b=0;if(this.geodesic)for(var c=this.map.getView().getProjection(),d=a.getCoordinates(),e=d.length,f=0;e-1>f;++f){var g=ol.proj.transform(d[f],c,"EPSG:4326"),h=ol.proj.transform(d[f+1],c,"EPSG:4326");b+=this.sphere.haversineDistance(g,h)}else b=Math.round(100*a.getLength())/100;var i;return i=b>100?Math.round(b/1e3*100)/100+" km":Math.round(100*b)/100+" m"},c.prototype.onPointerMove=function(a){if(!a.dragging){var b=this.settings.messageStart;if(this.sketch){var c=this.sketch.getGeometry();c instanceof ol.geom.Polygon?b=this.continuePolygonMsg:c instanceof ol.geom.LineString&&(b=this.continueLineMsg)}this.helpTooltipElement.innerHTML=b,this.helpTooltip.setPosition(a.coordinate),$(this.helpTooltipElement).removeClass("olexp-measure-hidden")}},c.prototype.setEnable=function(a){a?this.map.on("pointermove",this.pointerMoveCallback):this.map.un("pointermove",this.pointerMoveCallback),this.setInteraction(a)},c.prototype.setInteraction=function(b){"undefined"==typeof b&&(b=!0);var c=this;if(this.draw&&this.map.removeInteraction(this.draw),!b)return $(this.helpTooltipElement).addClass("olexp-measure-hidden"),void(this.drawing&&(this.map.removeLayer(this.vector),this.vector=null,this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement),this.measureTooltipElement=null,this.drawing=!1));$(this.helpTooltipElement).removeClass("olexp-measure-hidden"),this.source=new ol.source.Vector,this.draw=new ol.interaction.Draw({source:this.source,type:this.type,style:this.settings.measuringStyle}),this.map.addInteraction(this.draw),this.createMeasureTooltip(),this.createHelpTooltip();var d=null;this.draw.on("drawstart",function(a){this.drawing=!0,c.createMeasureVector();var b=a.coordinate;c.sketch=a.feature,d=c.sketch.getGeometry().on("change",function(a){var d="",e=a.target;e instanceof ol.geom.Polygon?(d=c.formatArea(e),b=e.getInteriorPoint().getCoordinates()):e instanceof ol.geom.LineString&&(d=c.formatLength(e),b=e.getLastCoordinate()),c.measureTooltipElement.innerHTML=d,c.measureTooltip.setPosition(b)})},this),this.draw.on("drawend",function(b){this.drawing=!1,c.count+=1;var e=c.sketch.getGeometry(),f={};e instanceof ol.geom.Polygon?(f[a.measure.properties.area]=c.formatArea(e),c.vector.setProperties(f)):e instanceof ol.geom.LineString&&(f[a.measure.properties.length]=c.formatLength(e),c.vector.setProperties(f)),c.sketch=null,c.measureTooltipElement.parentNode.removeChild(c.measureTooltipElement),c.measureTooltipElement=null,c.createMeasureTooltip(),ol.Observable.unByKey(d),c.setInteraction(!0)},this)},c.prototype.setType=function(a){this.type=a},a.measure.Tool=function(b,d){"undefined"==typeof d&&(d={}),"undefined"==typeof d.type&&(d.type=a.measure.Type.LINE),"undefined"==typeof d.settings&&(d.settings={});var e=new c(b,d.type,d.settings);return{setEnable:function(a){e.setEnable(a)},setType:function(a){e.setType(a)}}},a.measure.Type={AREA:"Polygon",LINE:"LineString"},a.measure.Overlay=b,a}(olexp||{}),olexp.menu=olexp.menu||{},function(a){"use strict";var b=function(a,b){var c=$.extend(!0,{menu:{Properties:{field:35,form:{},popup:{height:130,style:"width: 100%; height: 100%;",title:"Edit Layer",width:365},span:4,text:"Properties"}}},b);this.icon="olexp-menu-properties",this.form=b.prefix+"-menu-properties-form",this.id=b.prefix+"-menu-properties",this.manager=a,this.name="layerform",this.settings=c.menu.Properties};return b.prototype.onClick=function(b){var c=this,d=b.target,e=this.manager.getById(d),f=e.getProperties(),g=this.settings.popup.height,h=this.settings.field,i=[];g+=h,i.push({field:"name",html:{caption:"Name",span:this.settings.span},required:!0,type:"text"});for(var j=e.getPropertyTypes(),k=$.map(j,function(a){return a.title}),l=0;ld;d++)if(b===a.item(d))return d;return-1},a.util.popup=function(a,b,c,d){var e=c.name,f=c.record;w2ui.hasOwnProperty(e)&&w2ui[e].destroy(),$().w2form($.extend(c,{actions:{save:function(){var a=this.validate();if(0===a.length){w2popup.close();var c=w2ui[e],d=c.getChanges();b(d)}},reset:function(){var a=w2ui[e];for(var b in f)a.record[b]=f[b];a.refresh()}}})),w2popup.open($.extend(d,{body:'
',onOpen:function(b){b.onComplete=function(){$("#w2ui-popup #"+a).w2render(e)}},onToggle:function(a){var b=w2ui[e];$(b.box).hide(),a.onComplete=function(){$(b.box).show(),b.resize()}}}))},a.util.toProperties=function(a){var b=a.getProperties();if(b.hasOwnProperty("features")){var c=b.features;if(c instanceof Array)if(1===c.length)c[0]instanceof ol.Feature&&(b=c[0].getProperties());else for(var d=0,e=0;e */ -.ol-control,.ol-scale-line{position:absolute;padding:2px}.ol-box{box-sizing:border-box;border-radius:2px;border:2px solid #00f}.ol-mouse-position{top:8px;right:8px;position:absolute}.ol-scale-line{background:rgba(0,60,136,.3);border-radius:4px;bottom:8px;left:8px}.ol-scale-line-inner{border:1px solid #eee;border-top:none;color:#eee;font-size:10px;text-align:center;margin:1px;will-change:contents,width}.ol-overlay-container{will-change:left,right,top,bottom}.ol-unsupported{display:none}.ol-viewport .ol-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.ol-control{background-color:rgba(255,255,255,.4);border-radius:4px}.ol-control:hover{background-color:rgba(255,255,255,.6)}.ol-zoom{top:.5em;left:.5em}.ol-rotate{top:.5em;right:.5em;transition:opacity .25s linear,visibility 0s linear}.ol-rotate.ol-hidden{opacity:0;visibility:hidden;transition:opacity .25s linear,visibility 0s linear .25s}.ol-zoom-extent{top:4.643em;left:.5em}.ol-full-screen{right:.5em;top:.5em}@media print{.ol-control{display:none}}.ol-control button{display:block;margin:1px;padding:0;color:#fff;font-size:1.14em;font-weight:700;text-decoration:none;text-align:center;height:1.375em;width:1.375em;line-height:.4em;background-color:rgba(0,60,136,.5);border:none;border-radius:2px}.ol-control button::-moz-focus-inner{border:none;padding:0}.ol-zoom-extent button{line-height:1.4em}.ol-compass{display:block;font-weight:400;font-size:1.2em;will-change:transform}.ol-touch .ol-control button{font-size:1.5em}.ol-touch .ol-zoom-extent{top:5.5em}.ol-control button:focus,.ol-control button:hover{text-decoration:none;background-color:rgba(0,60,136,.7)}.ol-zoom .ol-zoom-in{border-radius:2px 2px 0 0}.ol-zoom .ol-zoom-out{border-radius:0 0 2px 2px}.ol-attribution{text-align:right;bottom:.5em;right:.5em;max-width:calc(100% - 1.3em)}.ol-attribution ul{margin:0;padding:0 .5em;font-size:.7rem;line-height:1.375em;color:#000;text-shadow:0 0 2px #fff}.ol-attribution li{display:inline;list-style:none;line-height:inherit}.ol-attribution li:not(:last-child):after{content:" "}.ol-attribution img{max-height:2em;max-width:inherit;vertical-align:middle}.ol-attribution button,.ol-attribution ul{display:inline-block}.ol-attribution.ol-collapsed ul{display:none}.ol-attribution.ol-logo-only ul{display:block}.ol-attribution:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-attribution.ol-uncollapsible{bottom:0;right:0;border-radius:4px 0 0;height:1.1em;line-height:1em}.ol-attribution.ol-logo-only{background:0 0;bottom:.4em;height:1.1em;line-height:1em}.ol-attribution.ol-uncollapsible img{margin-top:-.2em;max-height:1.6em}.ol-attribution.ol-logo-only button,.ol-attribution.ol-uncollapsible button{display:none}.ol-zoomslider{top:4.5em;left:.5em;height:200px}.ol-zoomslider button{position:relative;height:10px}.ol-touch .ol-zoomslider{top:5.5em}.ol-overviewmap{left:.5em;bottom:.5em}.ol-overviewmap.ol-uncollapsible{bottom:0;left:0;border-radius:0 4px 0 0}.ol-overviewmap .ol-overviewmap-map,.ol-overviewmap button{display:inline-block}.ol-overviewmap .ol-overviewmap-map{border:1px solid #7b98bc;height:150px;margin:2px;width:150px}.ol-overviewmap:not(.ol-collapsed) button{bottom:1px;left:2px;position:absolute}.ol-overviewmap.ol-collapsed .ol-overviewmap-map,.ol-overviewmap.ol-uncollapsible button{display:none}.ol-overviewmap:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-overviewmap-box{border:2px dotted rgba(0,60,136,.7)} -/* w2ui 1.4.3 (c) http://w2ui.com, vitmalina@gmail.com */ -@font-face{font-family:w2ui-font;src:url("data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAWIAAoAAAAACAgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAAA9AAAAEMAAABWQLxMsmNtYXAAAAE4AAAAOgAAAUriGRC2Z2x5ZgAAAXQAAAH9AAACgLu4vTRoZWFkAAADdAAAADAAAAA2AOYXBGhoZWEAAAOkAAAAIAAAACQD8wHHaG10eAAAA8QAAAAWAAAAIA7dAABsb2NhAAAD3AAAABIAAAASAngBuG1heHAAAAPwAAAAHwAAACABFQA2bmFtZQAABBAAAAEtAAACIsTQ/zJwb3N0AAAFQAAAAEgAAABi4/7ZEHicY2BkvMM4gYGVgYPRhTGNgYHBHUp/ZZBkaGFgYGJgZWbACgLSXFMYHD4yfmRnPPD/AIMe4wEGR6AwI0gOANHZC/IAeJxjYGBgZoBgGQZGBhBwAfIYwXwWBg0gzQakGRmYGBg+sv//D1LwkRFE8zNA1QMBIxvDiAcAddwGvgAAeJxFkLFv01AQxu97LrHdRImjpnaS1gnEia3IoqAktkkiEhaEOiCsDkEo8dyBDkytKpYKVWwssKKKAYmBREKMLJSFoRJ/AGJhY0NZGFgSzrUinvR+d++7T+/ePQLRci4IJ3SFCLIjG8CH+ZPwHHdwkkSS2PMXP3DGmUxpoo123lrt5nj8fjyejsc4W0zwNtl8FfHCKV5QnaOhF3IJUrUbkGPYnSGcGH6risBvGQhdVY0iVXXVkhJN1JL6/6xOIqWk4tRlJiVFiSJFSUrsZ+tkoqpEgt/6Hb/wjtZog2gonBx24AyFJUuNwMvha+/CvLi3vq1f785GsxGuTqfWc5O1N/r2+lNrOl38ZHnWpdUMr/CaLKLGZiHl4hI1+zasGB2/Dy9GSzfRbul4qaWPtHSQ0Y7SWpxmgnSc/mblMKNpmcOVEhfj+5d/8BGfqMl9bKuWFYWKaLf8YIAq9IKc5TY7ojNgTTcC7iEjaN4yPdswbM+81t8UimRLojq66YbdWq0bus375t21bwgcw/H6nmNUyhIkR/DsTasXPgx7VtV8oDx6XIxHE8vl8rMAzqlEDZ7QseUBPP6tLOQKDH5HqooKfLvB2gABa1lgflzI60VxsLd3IJj1YRn5/Wx9Syy++LvArn/JzH4e5WE98TCLer5wnBNb9WcrB5PoH084dg8AAAB4nGNgZGBgAOKMsPib8fw2Xxm4mRhA4PzjbBcY/f////1MjIwHgFwOBrA0AFcuDPF4nGNgZGBgPPD/AIMeEwMDw/9/TEwMQBEUwAEAe34EvHicY2JgYGCCYsbJCJpxO4QNABdTAesAAAAAAAAAEgAsAGgAjgC+AP4BQAAAeJxjYGRgYOBg0GJgZgABJiDmAkIGhv9gPgMADYEBTAB4nG2PTW7CMBCFXyBQFaQKtVKl7qwuuqkIPwsWHAD2LNiH4ARQEkeOQeICPUHP0DP0BF32DD1KX8IoixZbHn/z5o1/AAzwBQ/V8HBbx2q0cMPswm3SQNgnPwl30MezcJf6ULiHV8yE+3hAyBM8vzrtHk64hTu8Cbepvwv75A/hDh7xKdyl/i3cwxo/wn28eLN9ZPJhbHK30skxDW2TN7DWttybXE2CcaMtda5t6PRWbc6qPCVT52IVW5OpBas6TY0qrDnoyAU754r5aBSLHkQmwx4RDHL+Oq53hxU0EhyR8sf2Sv2/smaHRclKlStMEGB8xbekL6+9ITONLb0bnBlLnHjnlKqjW3FZ9mSkhfRqviclKxR17UAloh5gV3cVmGPEGf/xB/Ursl9uDmByAAAAeJxtwUEOgCAMBMAu0sI3SdMEIwKh8n8PXp2hQB+mf5kIAQciGIKEzFpNr6Sj7bs76xruMq3r2eJs22XZtPKIW1laiV6rCBDA") format("woff");font-weight:400;font-style:normal}[class^=w2ui-icon-]:before,[class*=" w2ui-icon-"]:before{font-family:w2ui-font;display:inline-block;vertical-align:middle;line-height:1;font-weight:400;font-style:normal;speak:none;text-decoration:inherit;text-transform:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w2ui-icon-check:before{content:"\f101"}.w2ui-icon-columns:before{content:"\f102"}.w2ui-icon-cross:before{content:"\f103"}.w2ui-icon-pencil:before{content:"\f104"}.w2ui-icon-plus:before{content:"\f105"}.w2ui-icon-reload:before{content:"\f106"}.w2ui-icon-search:before{content:"\f107"}.w2ui-reset{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;font-family:Verdana,Arial,sans-serif;font-size:11px}.w2ui-reset *{color:default;line-height:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0}.w2ui-reset table{font-family:Verdana,Arial,sans-serif;font-size:11px;max-width:none;background-color:transparent;border-collapse:separate;border-spacing:0}.w2ui-reset input,.w2ui-reset textarea{width:auto;height:auto;vertical-align:baseline;padding:4px}.w2ui-reset select{padding:1px;height:23px}.w2ui-centered{position:absolute;left:0;right:0;top:50%;-webkit-transform:translateY(-50%);-moz-transform:translateY(-50%);-ms-transform:translateY(-50%);-o-transform:translateY(-50%);transform:translateY(-50%);max-height:100%;margin:0;padding:0 10px;text-align:center}.w2ui-disabled,.w2ui-readonly{background-color:#f1f1f1!important;color:#777!important}input:not([type=button]),select,textarea{padding:4px;border:1px solid #bbb;border-radius:3px;color:#000;background-color:#fff;line-height:normal}input:not([type=button]):focus,select:focus,textarea:focus{outline-color:#72b2ff}input:not([type=button]):disabled,select:disabled,textarea:disabled,input:not([type=button])[readonly],select[readonly],textarea[readonly]{background-color:#f1f1f1;color:#777}input::-ms-clear{display:none}input:-ms-input-placeholder{color:#aaa!important}select{padding:2px}input[type=checkbox].w2ui-toggle{position:absolute;opacity:0;width:46px;height:22px;padding:0;margin:0;margin-left:2px}input[type=checkbox].w2ui-toggle+div{display:inline-block;width:46px;height:22px;border:1px solid #bbb;border-radius:30px;background-color:#eee;-webkit-transition-duration:.3s;-webkit-transition-property:background-color,box-shadow;-moz-transition-duration:.3s;-moz-transition-property:background-color,box-shadow;box-shadow:inset 0 0 0 0 rgba(0,0,0,.4);margin-left:2px}input[type=checkbox].w2ui-toggle:disabled+div{opacity:.3}input[type=checkbox].w2ui-toggle+div>div{float:left;width:22px;height:22px;border-radius:inherit;background:#f5f5f5;-webkit-transition-duration:.3s;-webkit-transition-property:transform,background-color,box-shadow;-moz-transition-duration:.3s;-moz-transition-property:transform,background-color;box-shadow:0 0 1px #323232,0 0 0 1px rgba(200,200,200,.6);pointer-events:none;margin-top:-1px;margin-left:-1px}input[type=checkbox].w2ui-toggle:checked+div{border:1px solid #00a23f;box-shadow:inset 0 0 0 12px #54B350}input[type=checkbox].w2ui-toggle:checked+div>div{-webkit-transform:translate3d(24px,0,0);-moz-transform:translate3d(24px,0,0);background-color:#fff;box-shadow:0 2px 5px rgba(0,0,0,.3),0 0 0 1px #00a23f}input[type=checkbox].w2ui-toggle.blue:checked+div{border:1px solid #206FAD;box-shadow:inset 0 0 0 12px #35A6EB}input[type=checkbox].w2ui-toggle.blue:checked+div>div{box-shadow:0 2px 5px rgba(0,0,0,.3),0 0 0 1px #206fad}input[type=checkbox].w2ui-toggle:focus{outline:0}.w2ui-overlay{position:absolute;margin-top:6px;margin-left:-17px;display:none;z-index:1300;color:inherit;background-color:#fbfbfb;border:3px solid #777;box-shadow:0 2px 10px #999;border-radius:4px;text-align:left}.w2ui-overlay table td{color:inherit}.w2ui-overlay:before{content:"";position:absolute;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg);width:12px;height:12px;border:3px solid #777;border-color:inherit;background-color:inherit;border-left:1px solid transparent;border-bottom:1px solid transparent;border-bottom-left-radius:50px;margin:-9px 0 0 30px}.w2ui-overlay:after{display:none;content:"";position:absolute;-webkit-transform:rotate(135deg);-moz-transform:rotate(135deg);-ms-transform:rotate(135deg);-o-transform:rotate(135deg);transform:rotate(135deg);width:12px;height:12px;border:3px solid #777;border-color:inherit;background-color:inherit;border-left:1px solid transparent;border-bottom:1px solid transparent;border-bottom-left-radius:50px;margin:-7px 0 0 30px}.w2ui-overlay.w2ui-overlay-popup{z-index:1700}.w2ui-tag{position:absolute;z-index:1300;opacity:0;-webkit-transition:opacity .3s;-moz-transition:opacity .3s;-ms-transition:opacity .3s;-o-transition:opacity .3s;transition:opacity .3s}.w2ui-tag .w2ui-tag-body{background-color:rgba(60,60,60,.82);display:inline-block;position:absolute;border-radius:4px;padding:4px 10px;margin-left:10px;margin-top:0;color:#fff!important;box-shadow:1px 1px 3px #000;line-height:100%;font-size:11px;font-family:Verdana,Arial,sans-serif}.w2ui-tag .w2ui-tag-body:before{content:"";position:absolute;width:0;height:0;border-top:5px solid transparent;border-right:5px solid rgba(60,60,60,.82);border-bottom:5px solid transparent;margin:2px 0 0 -15px}.w2ui-tag.w2ui-tag-popup{z-index:1700}.w2ui-overlay table.w2ui-drop-menu{width:100%;color:#000;background-color:#fff;padding:5px 0;cursor:default}.w2ui-overlay table.w2ui-drop-menu td{white-space:nowrap}.w2ui-overlay table.w2ui-drop-menu .w2ui-item-even{color:inherit;background-color:#fff}.w2ui-overlay table.w2ui-drop-menu .w2ui-item-odd{color:inherit;background-color:#f3f6fa}.w2ui-overlay table.w2ui-drop-menu .w2ui-item-group{color:#444;font-weight:700;background-color:#ECEDF0;border-bottom:1px solid #D3D2D4}.w2ui-overlay table.w2ui-drop-menu td.menu-icon{padding:3px 0 4px 6px;width:20px}.w2ui-overlay table.w2ui-drop-menu td.menu-text{padding:8px 10px 8px 5px;width:auto}.w2ui-overlay table.w2ui-drop-menu td.menu-count{text-align:right}.w2ui-overlay table.w2ui-drop-menu td.menu-count>span{border:1px solid #9da4af;border-radius:20px;width:auto;height:18px;padding:2px 7px;margin:3px 5px 0;background-color:#e7f0fc;color:#667274;box-shadow:0 0 2px #fff;text-shadow:1px 1px 1px #e6e6e6}.w2ui-overlay table.w2ui-drop-menu tr:hover{color:inherit;background-color:#e6f0ff}.w2ui-overlay table.w2ui-drop-menu tr.w2ui-selected{background-color:#b6d5fb}.w2ui-overlay table.w2ui-drop-menu tr.w2ui-selected td{color:inherit}.w2ui-overlay table.w2ui-drop-menu tr.w2ui-disabled{opacity:.4;background-color:#fff!important}.w2ui-overlay table.w2ui-drop-menu .w2ui-icon{font-size:14px;color:#8d99a7;display:inline-block;padding-top:4px}.w2ui-marker{color:#444;background-color:rgba(252,244,161,.48)}.w2ui-spinner{display:inline-block;background-size:100%;background-repeat:no-repeat;background-image:url(data:image/gif;base64,R0lGODlhgACAAKIAAP///93d3bu7u5mZmQAA/wAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFBQAEACwCAAIAfAB8AAAD/0i63P4wygYqmDjrzbtflvWNZGliYXiubKuloivPLlzReD7al+7/Eh5wSFQIi8hHYBkwHUmD6CD5YTJLz49USuVYraRsZ7vtar7XnQ1Kjpoz6LRHvGlz35O4nEPP2O94EnpNc2sef1OBGIOFMId/inB6jSmPdpGScR19EoiYmZobnBCIiZ95k6KGGp6ni4wvqxilrqBfqo6skLW2YBmjDa28r6Eosp27w8Rov8ekycqoqUHODrTRvXsQwArC2NLF29UM19/LtxO5yJd4Au4CK7DUNxPebG4e7+8n8iv2WmQ66BtoYpo/dvfacBjIkITBE9DGlMvAsOIIZjIUAixliv9ixYZVtLUos5GjwI8gzc3iCGghypQqrbFsme8lwZgLZtIcYfNmTJ34WPTUZw5oRxdD9w0z6iOpO15MgTh1BTTJUKos39jE+o/KS64IFVmsFfYT0aU7capdy7at27dw48qdS7eu3bt480I02vUbX2F/JxYNDImw4GiGE/P9qbhxVpWOI/eFKtlNZbWXuzlmG1mv58+gQ4seTbq06dOoU6vGQZJy0FNlMcV+czhQ7SQmYd8eMhPs5BxVdfcGEtV3buDBXQ+fURxx8oM6MT9P+Fh6dOrH2zavc13u9JXVJb520Vp8dvC76wXMuN5Sepm/1WtkEZHDefnzR9Qvsd9+/wi8+en3X0ntYVcSdAE+UN4zs7ln24CaLagghIxBaGF8kFGoIYV+Ybghh841GIyI5ICIFoklJsigihmimJOLEbLYIYwxSgigiZ+8l2KB+Ml4oo/w8dijjcrouCORKwIpnJIjMnkkksalNeR4fuBIm5UEYImhIlsGCeWNNJphpJdSTlkml1jWeOY6TnaRpppUctcmFW9mGSaZceYopH9zkjnjUe59iR5pdapWaGqHopboaYua1qije67GJ6CuJAAAIfkEBQUABAAsCgACAFcAMAAAA/9Iutz+ML5Ag7w46z0r5WAoSp43nihXVmnrdusrv+s332dt4Tyo9yOBUJD6oQBIQGs4RBlHySSKyczVTtHoidocPUNZaZAr9F5FYbGI3PWdQWn1mi36buLKFJvojsHjLnshdhl4L4IqbxqGh4gahBJ4eY1kiX6LgDN7fBmQEJI4jhieD4yhdJ2KkZk8oiSqEaatqBekDLKztBG2CqBACq4wJRi4PZu1sA2+v8C6EJexrBAD1AOBzsLE0g/V1UvYR9sN3eR6lTLi4+TlY1wz6Qzr8u1t6FkY8vNzZTxaGfn6mAkEGFDgL4LrDDJDyE4hEIbdHB6ESE1iD4oVLfLAqPETIsOODwmCDJlv5MSGJklaS6khAQAh+QQFBQAEACwfAAIAVwAwAAAD/0i63P5LSAGrvTjrNuf+YKh1nWieIumhbFupkivPBEzR+GnnfLj3ooFwwPqdAshAazhEGUXJJIrJ1MGOUamJ2jQ9QVltkCv0XqFh5IncBX01afGYnDqD40u2z76JK/N0bnxweC5sRB9vF34zh4gjg4uMjXobihWTlJUZlw9+fzSHlpGYhTminKSepqebF50NmTyor6qxrLO0L7YLn0ALuhCwCrJAjrUqkrjGrsIkGMW/BMEPJcphLgDaABjUKNEh29vdgTLLIOLpF80s5xrp8ORVONgi8PcZ8zlRJvf40tL8/QPYQ+BAgjgMxkPIQ6E6hgkdjoNIQ+JEijMsasNY0RQix4gKP+YIKXKkwJIFF6JMudFEAgAh+QQFBQAEACw8AAIAQgBCAAAD/kg0PPowykmrna3dzXvNmSeOFqiRaGoyaTuujitv8Gx/661HtSv8gt2jlwIChYtc0XjcEUnMpu4pikpv1I71astytkGh9wJGJk3QrXlcKa+VWjeSPZHP4Rtw+I2OW81DeBZ2fCB+UYCBfWRqiQp0CnqOj4J1jZOQkpOUIYx/m4oxg5cuAaYBO4Qop6c6pKusrDevIrG2rkwptrupXB67vKAbwMHCFcTFxhLIt8oUzLHOE9Cy0hHUrdbX2KjaENzey9Dh08jkz8Tnx83q66bt8PHy8/T19vf4+fr6AP3+/wADAjQmsKDBf6AOKjS4aaHDgZMeSgTQcKLDhBYPEswoA1BBAgAh+QQFBQAEACxOAAoAMABXAAAD7Ei6vPOjyUkrhdDqfXHm4OZ9YSmNpKmiqVqykbuysgvX5o2HcLxzup8oKLQQix0UcqhcVo5ORi+aHFEn02sDeuWqBGCBkbYLh5/NmnldxajX7LbPBK+PH7K6narfO/t+SIBwfINmUYaHf4lghYyOhlqJWgqDlAuAlwyBmpVnnaChoqOkpaanqKmqKgGtrq+wsbA1srW2ry63urasu764Jr/CAb3Du7nGt7TJsqvOz9DR0tPU1TIA2ACl2dyi3N/aneDf4uPklObj6OngWuzt7u/d8fLY9PXr9eFX+vv8+PnYlUsXiqC3c6PmUUgAACH5BAUFAAQALE4AHwAwAFcAAAPpSLrc/m7IAau9bU7MO9GgJ0ZgOI5leoqpumKt+1axPJO1dtO5vuM9yi8TlAyBvSMxqES2mo8cFFKb8kzWqzDL7Xq/4LB4TC6bz1yBes1uu9uzt3zOXtHv8xN+Dx/x/wJ6gHt2g3Rxhm9oi4yNjo+QkZKTCgGWAWaXmmOanZhgnp2goaJdpKGmp55cqqusrZuvsJays6mzn1m4uRAAvgAvuBW/v8GwvcTFxqfIycA3zA/OytCl0tPPO7HD2GLYvt7dYd/ZX99j5+Pi6tPh6+bvXuTuzujxXens9fr7YPn+7egRI9PPHrgpCQAAIfkEBQUABAAsPAA8AEIAQgAAA/lIutz+UI1Jq7026h2x/xUncmD5jehjrlnqSmz8vrE8u7V5z/m5/8CgcEgsGo/IpHLJbDqf0Kh0ShBYBdTXdZsdbb/Yrgb8FUfIYLMDTVYz2G13FV6Wz+lX+x0fdvPzdn9WeoJGAYcBN39EiIiKeEONjTt0kZKHQGyWl4mZdREAoQAcnJhBXBqioqSlT6qqG6WmTK+rsa1NtaGsuEu6o7yXubojsrTEIsa+yMm9SL8osp3PzM2cStDRykfZ2tfUtS/bRd3ewtzV5pLo4eLjQuUp70Hx8t9E9eqO5Oku5/ztdkxi90qPg3x2EMpR6IahGocPCxp8AGtigwQAIfkEBQUABAAsHwBOAFcAMAAAA/9Iutz+MMo36pg4682J/V0ojs1nXmSqSqe5vrDXunEdzq2ta3i+/5DeCUh0CGnF5BGULC4tTeUTFQVONYAs4CfoCkZPjFar83rBx8l4XDObSUL1Ott2d1U4yZwcs5/xSBB7dBMBhgEYfncrTBGDW4WHhomKUY+QEZKSE4qLRY8YmoeUfkmXoaKInJ2fgxmpqqulQKCvqRqsP7WooriVO7u8mhu5NacasMTFMMHCm8qzzM2RvdDRK9PUwxzLKdnaz9y/Kt8SyR3dIuXmtyHpHMcd5+jvWK4i8/TXHff47SLjQvQLkU+fG29rUhQ06IkEG4X/Rryp4mwUxSgLL/7IqFETB8eONT6ChCFy5ItqJomES6kgAQAh+QQFBQAEACwKAE4AVwAwAAAD/0i63A4QuEmrvTi3yLX/4MeNUmieITmibEuppCu3sDrfYG3jPKbHveDktxIaF8TOcZmMLI9NyBPanFKJp4A2IBx4B5lkdqvtfb8+HYpMxp3Pl1qLvXW/vWkli16/3dFxTi58ZRcChwIYf3hWBIRchoiHiotWj5AVkpIXi4xLjxiaiJR/T5ehoomcnZ+EGamqq6VGoK+pGqxCtaiiuJVBu7yaHrk4pxqwxMUzwcKbyrPMzZG90NGDrh/JH8t72dq3IN1jfCHb3L/e5ebh4ukmxyDn6O8g08jt7tf26ybz+m/W9GNXzUQ9fm1Q/APoSWAhhfkMAmpEbRhFKwsvCsmosRIHx444PoKcIXKkjIImjTzjkQAAIfkEBQUABAAsAgA8AEIAQgAAA/VIBNz+8KlJq72Yxs1d/uDVjVxogmQqnaylvkArT7A63/V47/m2/8CgcEgsGo/IpHLJbDqf0Kh0Sj0FroGqDMvVmrjgrDcTBo8v5fCZki6vCW33Oq4+0832O/at3+f7fICBdzsChgJGeoWHhkV0P4yMRG1BkYeOeECWl5hXQ5uNIAOjA1KgiKKko1CnqBmqqk+nIbCkTq20taVNs7m1vKAnurtLvb6wTMbHsUq4wrrFwSzDzcrLtknW16tI2tvERt6pv0fi48jh5h/U6Zs77EXSN/BE8jP09ZFA+PmhP/xvJgAMSGBgQINvEK5ReIZhQ3QEMTBLAAAh+QQFBQAEACwCAB8AMABXAAAD50i6DA4syklre87qTbHn4OaNYSmNqKmiqVqyrcvBsazRpH3jmC7yD98OCBF2iEXjBKmsAJsWHDQKmw571l8my+16v+CweEwum8+hgHrNbrvbtrd8znbR73MVfg838f8BeoB7doN0cYZvaIuMjY6PkJGSk2gClgJml5pjmp2YYJ6dX6GeXaShWaeoVqqlU62ir7CXqbOWrLafsrNctjIDwAMWvC7BwRWtNsbGFKc+y8fNsTrQ0dK3QtXAYtrCYd3eYN3c49/a5NVj5eLn5u3s6e7x8NDo9fbL+Mzy9/T5+tvUzdN3Zp+GBAAh+QQJBQAEACwCAAIAfAB8AAAD/0i63P4wykmrvTjrzbv/YCiOZGmeaKqubOu+cCzPdArcQK2TOL7/nl4PSMwIfcUk5YhUOh3M5nNKiOaoWCuWqt1Ou16l9RpOgsvEMdocXbOZ7nQ7DjzTaeq7zq6P5fszfIASAYUBIYKDDoaGIImKC4ySH3OQEJKYHZWWi5iZG0ecEZ6eHEOio6SfqCaqpaytrpOwJLKztCO2jLi1uoW8Ir6/wCHCxMG2x7muysukzb230M6H09bX2Nna29zd3t/g4cAC5OXm5+jn3Ons7eba7vHt2fL16tj2+QL0+vXw/e7WAUwnrqDBgwgTKlzIsKHDh2gGSBwAccHEixAvaqTYcFCjRoYeNyoM6REhyZIHT4o0qPIjy5YTTcKUmHImx5cwE85cmJPnSYckK66sSAAj0aNIkypdyrSp06dQo0qdSrWq1atYs2rdyrWr169gwxZJAAA7)}.w2ui-icon{background-repeat:no-repeat;height:16px;width:16px;overflow:hidden;margin:2px;display:inline-block}.w2ui-icon.icon-search,.w2ui-icon.icon-search-down{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAgCAYAAAB+ZAqzAAACuElEQVRYw9WXSWhTQRjHR0UKLqhFaV0OUih68GAOWjyJKypCpAoV8aIiioIICiKiB1GMtE3MYmry2moXDz1UDx7sUXHBhQpSaRVxrYpWcMO9avx/8AJh/CbznHkxdeB3Cd/8589kvuUJkWcdjCTHghUgAi6DJ+AVeAqugSQIggniXywcNBJsB70g44EHYBcYXUhTM8EFj4ZkboKqQpiqAv2GprK8o7/f75t6pjn0M3gNPmri3vtycxAZA64qDvkJ2kENqAQTQQWoBg74qth3B4y3NbZDIX4fzNfsnQtuK/YfsjFVCh4pMq3Co0Y5uMVoUGkpy8aFT5xaeSzVEo45bXdBt4LeaLq1k0RXMYJfdDfFmAuAD4zWlty4UNyZEkm19MUb2zMw8Sfp1u+IWSrcIimLnTG8/SijdU6OO5poDESdtgHZVBzUHm/amhW7zoitMTS2mNHqASPk2FDCCcLMYK6p+obmulyxfiYLA4bGKFvfSnrUvkq5+Lpk8z4yRH8r3l/X4WiqJFfspSQ0CGYZGpsMnkt6L+h31Z76hpMdeOwPQ7H0NFnssST0C8wxNDaDKb6kP06150gsHahNNlVzYheZd7HJ0BiX4VRGhpmIhRixKyZilM2M1mnTArtIUbU3/qVO0H0GvmQ4CY4C3YopYYlHjXlggNG4R33Ypi2tVtwaPeTdNMkq9pVQZQdvFPs32zbx4aAjzxhDRfIAWAeWg7VgrzsY5ht/zoNJtubKwA3LITGjSKRyW3NTwaUCmKOSMd3WHH0ZJRQZZkOP1zFKZ3CB++4+aQ6kEeksWAb2a2L7qDv49S1Q6T72MOgEXa6RGFhP3wpS/B6NOWpRs0UxFg7eqTFHjX1hscxtAz/ymEuIYi0cvgF8Y0w5Ro3dZ3M1boJkTaXEUFlug6fsdsRQWzTj0cey+N/Xb2sj5lTh2M6OAAAAAElFTkSuQmCC) no-repeat center!important;background-size:14px 12px!important;opacity:.9}.w2ui-icon.icon-folder{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGrSURBVDjLxZO7ihRBFIa/6u0ZW7GHBUV0UQQTZzd3QdhMQxOfwMRXEANBMNQX0MzAzFAwEzHwARbNFDdwEd31Mj3X7a6uOr9BtzNjYjKBJ6nicP7v3KqcJFaxhBVtZUAK8OHlld2st7Xl3DJPVONP+zEUV4HqL5UDYHr5xvuQAjgl/Qs7TzvOOVAjxjlC+ePSwe6DfbVegLVuT4r14eTr6zvA8xSAoBLzx6pvj4l+DZIezuVkG9fY2H7YRQIMZIBwycmzH1/s3F8AapfIPNF3kQk7+kw9PWBy+IZOdg5Ug3mkAATy/t0usovzGeCUWTjCz0B+Sj0ekfdvkZ3abBv+U4GaCtJ1iEm6ANQJ6fEzrG/engcKw/wXQvEKxSEKQxRGKE7Izt+DSiwBJMUSm71rguMYhQKrBygOIRStf4TiFFRBvbRGKiQLWP29yRSHKBTtfdBmHs0BUpgvtgF4yRFR+NUKi0XZcYjCeCG2smkzLAHkbRBmP0/Uk26O5YnUActBp1GsAI+S5nRJJJal5K1aAMrq0d6Tm9uI6zjyf75dAe6tx/SsWeD//o2/Ab6IH3/h25pOAAAAAElFTkSuQmCC) no-repeat center!important}.w2ui-icon.icon-page{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAINSURBVBgZBcG/r55zGAfg6/4+z3va01NHlYgzEfE7MdCIGISFgS4Gk8ViYyM2Mdlsko4GSf8Do0FLRCIkghhYJA3aVBtEz3nP89wf11VJvPDepdd390+8Nso5nESBQoq0pfvXm9fzWf19453LF85vASqJlz748vInb517dIw6EyYBIIG49u+xi9/c9MdvR//99MPPZ7+4cP4IZhhTPbwzT2d+vGoaVRRp1rRliVvHq+cfvM3TD82+7mun0o/ceO7NT+/4/KOXjwZU1ekk0840bAZzMQ2mooqh0A72d5x/6sB9D5zYnff3PoYBoWBgFKPKqDKqjCpjKr//dcu9p489dra88cydps30KswACfNEKanSaxhlntjJ8Mv12Paie+vZ+0+oeSwwQ0Iw1xAR1CiFNJkGO4wu3ZMY1AAzBI0qSgmCNJsJUEOtJSMaCTBDLyQ0CknAGOgyTyFFiLI2awMzdEcSQgSAAKVUmAeNkxvWJWCGtVlDmgYQ0GFtgg4pNtOwbBcwQy/Rife/2yrRRVI0qYCEBly8Z+P4qMEMy7JaVw72N568e+iwhrXoECQkfH91kY7jwwXMsBx1L93ZruqrK6uuiAIdSnTIKKPLPFcvay8ww/Hh+ufeznTXu49v95IMoQG3784gYXdTqvRmqn/Wpa/ADFX58MW3L71SVU9ETgEIQQQIOOzub+fhIvwPRDgeVjWDahIAAAAASUVORK5CYII=) no-repeat center!important}.w2ui-lock{display:none;position:absolute;z-index:1400;top:0;left:0;width:100%;height:100%;opacity:.15;filter:alpha(opacity=15);background-color:#333}.w2ui-lock-msg{display:none;position:absolute;z-index:1400;top:45%;left:50%;-webkit-transform:translateX(-50%) translateY(-50%);-moz-transform:translateX(-50%) translateY(-50%);-ms-transform:translateX(-50%) translateY(-50%);-o-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);width:200px;height:80px;padding:30px 8px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-size:13px;font-family:Verdana,Arial,sans-serif;opacity:.8;filter:alpha(opacity=80);background-color:#555;color:#fff;text-align:center;border-radius:5px;border:2px solid #444}.w2ui-lock-msg .w2ui-spinner{display:inline-block;width:24px;height:24px;margin:-3px 8px -7px -10px}button.btn{display:inline-block;border-radius:4px;margin:0 5px;padding:7px 12px 6px!important;color:#666;font-size:12px!important;border:1px solid #B6B6B6;background-image:-webkit-linear-gradient(#fff 0,#e7e7e7 100%);background-image:-moz-linear-gradient(#fff 0,#e7e7e7 100%);background-image:-ms-linear-gradient(#fff 0,#e7e7e7 100%);background-image:-o-linear-gradient(#fff 0,#e7e7e7 100%);background-image:linear-gradient(#fff 0,#e7e7e7 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffe7e7e7', endColorstr='#ffffffff', GradientType=0);outline:0;box-shadow:0 1px 0 #fff;cursor:default;min-width:75px;line-height:100%!important;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}button.btn:hover{text-decoration:none;border:1px solid #bbb;background-image:-webkit-linear-gradient(#f7f7f7 0,#ddd 100%);background-image:-moz-linear-gradient(#f7f7f7 0,#ddd 100%);background-image:-ms-linear-gradient(#f7f7f7 0,#ddd 100%);background-image:-o-linear-gradient(#f7f7f7 0,#ddd 100%);background-image:linear-gradient(#f7f7f7 0,#ddd 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffdddddd', endColorstr='#fff7f7f7', GradientType=0);color:#333}button.btn:active,button.btn.clicked{border:1px solid #999;background-image:-webkit-linear-gradient(#ccc 0,#ccc 100%);background-image:-moz-linear-gradient(#ccc 0,#ccc 100%);background-image:-ms-linear-gradient(#ccc 0,#ccc 100%);background-image:-o-linear-gradient(#ccc 0,#ccc 100%);background-image:linear-gradient(#ccc 0,#ccc 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffcccccc', endColorstr='#ffcccccc', GradientType=0);text-shadow:1px 1px 1px #eee}button.btn:disabled{border:1px solid #bbb!important;background:#f7f7f7!important;color:#bdbcbc!important;text-shadow:none!important}button.btn-blue{color:#fff;background-image:-webkit-linear-gradient(#80c0f7 0,#269df0 100%);background-image:-moz-linear-gradient(#80c0f7 0,#269df0 100%);background-image:-ms-linear-gradient(#80c0f7 0,#269df0 100%);background-image:-o-linear-gradient(#80c0f7 0,#269df0 100%);background-image:linear-gradient(#80c0f7 0,#269df0 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff269df0', endColorstr='#ff80c0f7', GradientType=0);border:1px solid #538AB7;text-shadow:1px 1px 1px #777}button.btn-blue:hover{color:#fff;background-image:-webkit-linear-gradient(#73b6f0 0,#2391dd 100%);background-image:-moz-linear-gradient(#73b6f0 0,#2391dd 100%);background-image:-ms-linear-gradient(#73b6f0 0,#2391dd 100%);background-image:-o-linear-gradient(#73b6f0 0,#2391dd 100%);background-image:linear-gradient(#73b6f0 0,#2391dd 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff2391dd', endColorstr='#ff73b6f0', GradientType=0);border:1px solid #497BA3;text-shadow:1px 1px 1px #777}button.btn-blue:active,button.btn-blue.clicked{color:#fff;background-image:-webkit-linear-gradient(#1e83c9 0,#1e83c9 100%);background-image:-moz-linear-gradient(#1e83c9 0,#1e83c9 100%);background-image:-ms-linear-gradient(#1e83c9 0,#1e83c9 100%);background-image:-o-linear-gradient(#1e83c9 0,#1e83c9 100%);background-image:linear-gradient(#1e83c9 0,#1e83c9 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff1e83c9', endColorstr='#ff1e83c9', GradientType=0);border:1px solid #1268A6;text-shadow:1px 1px 1px #777}button.btn-green{color:#fff;background-image:-webkit-linear-gradient(#81cf81 0,#52a452 100%);background-image:-moz-linear-gradient(#81cf81 0,#52a452 100%);background-image:-ms-linear-gradient(#81cf81 0,#52a452 100%);background-image:-o-linear-gradient(#81cf81 0,#52a452 100%);background-image:linear-gradient(#81cf81 0,#52a452 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff52a452', endColorstr='#ff81cf81', GradientType=0);border:1px solid #479247;text-shadow:1px 1px 1px #777}button.btn-green:hover{color:#fff;background-image:-webkit-linear-gradient(#6abe68 0,#3f8f3d 100%);background-image:-moz-linear-gradient(#6abe68 0,#3f8f3d 100%);background-image:-ms-linear-gradient(#6abe68 0,#3f8f3d 100%);background-image:-o-linear-gradient(#6abe68 0,#3f8f3d 100%);background-image:linear-gradient(#6abe68 0,#3f8f3d 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff3f8f3d', endColorstr='#ff6abe68', GradientType=0);border:1px solid #479247;text-shadow:1px 1px 1px #777}button.btn-green:active,button.btn-green.clicked{color:#fff;background-image:-webkit-linear-gradient(#377d36 0,#377d36 100%);background-image:-moz-linear-gradient(#377d36 0,#377d36 100%);background-image:-ms-linear-gradient(#377d36 0,#377d36 100%);background-image:-o-linear-gradient(#377d36 0,#377d36 100%);background-image:linear-gradient(#377d36 0,#377d36 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff377d36', endColorstr='#ff377d36', GradientType=0);border:1px solid #555!important;text-shadow:1px 1px 1px #777}button.btn-orange{color:#fff;background-image:-webkit-linear-gradient(#fcc272 0,#fb8822 100%);background-image:-moz-linear-gradient(#fcc272 0,#fb8822 100%);background-image:-ms-linear-gradient(#fcc272 0,#fb8822 100%);background-image:-o-linear-gradient(#fcc272 0,#fb8822 100%);background-image:linear-gradient(#fcc272 0,#fb8822 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fffb8822', endColorstr='#fffcc272', GradientType=0);border:1px solid #B68B4C;text-shadow:1px 1px 1px #777}button.btn-orange:hover{color:#fff;background-image:-webkit-linear-gradient(#f4ad59 0,#f1731f 100%);background-image:-moz-linear-gradient(#f4ad59 0,#f1731f 100%);background-image:-ms-linear-gradient(#f4ad59 0,#f1731f 100%);background-image:-o-linear-gradient(#f4ad59 0,#f1731f 100%);background-image:linear-gradient(#f4ad59 0,#f1731f 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff1731f', endColorstr='#fff4ad59', GradientType=0);border:1px solid #B68B4C;text-shadow:1px 1px 1px #777}button.btn-orange:active,button.btn-orange.clicked{color:#fff;border:1px solid #666;background-image:-webkit-linear-gradient(#b98747 0,#b98747 100%);background-image:-moz-linear-gradient(#b98747 0,#b98747 100%);background-image:-ms-linear-gradient(#b98747 0,#b98747 100%);background-image:-o-linear-gradient(#b98747 0,#b98747 100%);background-image:linear-gradient(#b98747 0,#b98747 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffb98747', endColorstr='#ffb98747', GradientType=0);text-shadow:1px 1px 1px #777}button.btn-red{color:#fff;background-image:-webkit-linear-gradient(#ff6e70 0,#c72d2d 100%);background-image:-moz-linear-gradient(#ff6e70 0,#c72d2d 100%);background-image:-ms-linear-gradient(#ff6e70 0,#c72d2d 100%);background-image:-o-linear-gradient(#ff6e70 0,#c72d2d 100%);background-image:linear-gradient(#ff6e70 0,#c72d2d 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffc72d2d', endColorstr='#ffff6e70', GradientType=0);border:1px solid #BB3C3E;text-shadow:1px 1px 1px #777}button.btn-red:hover{color:#fff;background-image:-webkit-linear-gradient(#ee696c 0,#ae2527 100%);background-image:-moz-linear-gradient(#ee696c 0,#ae2527 100%);background-image:-ms-linear-gradient(#ee696c 0,#ae2527 100%);background-image:-o-linear-gradient(#ee696c 0,#ae2527 100%);background-image:linear-gradient(#ee696c 0,#ae2527 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffae2527', endColorstr='#ffee696c', GradientType=0);border:1px solid #BB3C3E;text-shadow:1px 1px 1px #777}button.btn-red:active,button.btn-red.clicked{color:#fff;border:1px solid #861C1E;background-image:-webkit-linear-gradient(#9c2123 0,#9c2123 100%);background-image:-moz-linear-gradient(#9c2123 0,#9c2123 100%);background-image:-ms-linear-gradient(#9c2123 0,#9c2123 100%);background-image:-o-linear-gradient(#9c2123 0,#9c2123 100%);background-image:linear-gradient(#9c2123 0,#9c2123 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff9c2123', endColorstr='#ff9c2123', GradientType=0);text-shadow:1px 1px 1px #777}.w2ui-form{position:relative;color:#000;background-color:#f5f6f7;border:1px solid silver;border-radius:3px;padding:0;overflow:hidden!important}.w2ui-form>div{position:absolute;overflow:hidden}.w2ui-form .w2ui-form-header{position:absolute;left:0;right:0;border-bottom:1px solid #99bbe8!important;overflow:hidden;color:#444;font-size:13px;text-align:center;padding:8px;background-image:-webkit-linear-gradient(#dae6f3,#c2d5ed);background-image:-moz-linear-gradient(#dae6f3,#c2d5ed);background-image:-ms-linear-gradient(#dae6f3,#c2d5ed);background-image:-o-linear-gradient(#dae6f3,#c2d5ed);background-image:linear-gradient(#dae6f3,#c2d5ed);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffdae6f3', endColorstr='#ffc2d5ed', GradientType=0);border-top-left-radius:3px;border-top-right-radius:3px}.w2ui-form .w2ui-form-toolbar{position:absolute;left:0;right:0;margin:0;padding:6px 3px;border-bottom:1px solid #d5d8d8}.w2ui-form .w2ui-form-tabs{margin:0;padding:0}.w2ui-form .w2ui-tabs{position:absolute;left:0;right:0;border-top-left-radius:3px;border-top-right-radius:3px;padding-top:5px!important;background-color:#fafafa}.w2ui-form .w2ui-tabs .w2ui-tab.active{background-color:#f5f6f7}.w2ui-form .w2ui-page{position:absolute;left:0;right:0;overflow:auto;padding:10px;border-left:1px solid inherit;border-right:1px solid inherit;background-color:inherit;border-radius:3px}.w2ui-form .w2ui-buttons{position:absolute;left:0;right:0;bottom:0;text-align:center;border-top:1px solid #d5d8d8;border-bottom:0 solid #d5d8d8;background-color:#fafafa;padding:15px 0!important;border-bottom-left-radius:3px;border-bottom-right-radius:3px}.w2ui-form .w2ui-buttons input[type=button],.w2ui-form .w2ui-buttons button{min-width:80px;margin-right:5px}.w2ui-form input[type=checkbox],.w2ui-form input[type=radio]{margin-top:4px;margin-bottom:4px}.w2ui-form input[type=checkbox].w2ui-toggle{margin:0}.w2ui-group-title{padding:5px 2px;color:#8D96A2;text-shadow:1px 1px 2px #fdfdfd;font-size:120%}.w2ui-group{background-color:#ebecef;margin:5px 0 10px;padding:10px 5px;border-top:1px solid #cedcea;border-bottom:1px solid #cedcea}.w2ui-field>label{display:block;float:left;margin-top:7px;margin-bottom:3px;width:120px;padding:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:right;min-height:20px;color:#666}.w2ui-field>div{margin-bottom:3px;margin-left:128px;padding:3px;min-height:28px;float:none}.w2ui-field.w2ui-required>div{position:relative}.w2ui-field.w2ui-required>div::before{content:'*';position:absolute;margin-top:5px;margin-left:-9px;color:red}.w2ui-field.w2ui-span1>label{width:20px}.w2ui-field.w2ui-span1>div{margin-left:28px}.w2ui-field.w2ui-span2>label{width:40px}.w2ui-field.w2ui-span2>div{margin-left:48px}.w2ui-field.w2ui-span3>label{width:60px}.w2ui-field.w2ui-span3>div{margin-left:68px}.w2ui-field.w2ui-span4>label{width:80px}.w2ui-field.w2ui-span4>div{margin-left:88px}.w2ui-field.w2ui-span5>label{width:100px}.w2ui-field.w2ui-span5>div{margin-left:108px}.w2ui-field.w2ui-span6>label{width:120px}.w2ui-field.w2ui-span6>div{margin-left:128px}.w2ui-field.w2ui-span7>label{width:140px}.w2ui-field.w2ui-span7>div{margin-left:148px}.w2ui-field.w2ui-span8>label{width:160px}.w2ui-field.w2ui-span8>div{margin-left:168px}.w2ui-field.w2ui-span9>label{width:180px}.w2ui-field.w2ui-span9>div{margin-left:188px}.w2ui-field.w2ui-span10>label{width:200px}.w2ui-field.w2ui-span10>div{margin-left:208px}.w2ui-error{border:1px solid #ffa8a8!important;background-color:#fff4eb!important}.w2field{padding:3px;border-radius:3px;border:1px solid silver}.w2ui-field-helper{position:absolute;display:inline-block;line-height:100%;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none}.w2ui-field-helper .w2ui-field-up{position:absolute;top:0;padding:2px 3px}.w2ui-field-helper .w2ui-field-down{position:absolute;bottom:0;padding:2px 3px}.w2ui-field-helper .arrow-up:hover{border-bottom-color:#81C6FF}.w2ui-field-helper .arrow-down:hover{border-top-color:#81C6FF}.arrow-up{background:0 0;width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:5px solid #777;font-size:0;line-height:0}.arrow-down{background:0 0;width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid #777;font-size:0;line-height:0}.arrow-left{background:0 0;width:0;height:0;border-bottom:4px solid transparent;border-top:4px solid transparent;border-right:5px solid #777;font-size:0;line-height:0}.arrow-right{background:0 0;width:0;height:0;border-bottom:4px solid transparent;border-top:4px solid transparent;border-left:5px solid #777;font-size:0;line-height:0}.w2ui-color{padding:5px;padding-top:8px;background-color:#fff;border-radius:3px}.w2ui-color>table{table-layout:fixed;width:160px}.w2ui-color>table td{width:20px;height:20px;text-align:center}.w2ui-color>table td div{cursor:pointer;display:inline-block;width:16px;height:17px;padding:1px 4px;border:1px solid transparent;color:#fff;text-shadow:0 0 2px #000}.w2ui-color>table td div:hover{outline:1px solid #666;border:1px solid #fff}.w2ui-calendar{margin:0;padding:1px;line-height:108%}.w2ui-calendar .w2ui-calendar-title{margin:0 -1px;padding:7px 2px;background-image:-webkit-linear-gradient(#f6f6f6,#d9d9d9);background-image:-moz-linear-gradient(#f6f6f6,#d9d9d9);background-image:-ms-linear-gradient(#f6f6f6,#d9d9d9);background-image:-o-linear-gradient(#f6f6f6,#d9d9d9);background-image:linear-gradient(#f6f6f6,#d9d9d9);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff6f6f6', endColorstr='#ffd9d9d9', GradientType=0);border-bottom:1px solid #bbb;color:#555;text-align:center;text-shadow:1px 1px 1px #eee;cursor:pointer}.w2ui-calendar .w2ui-calendar-jump{position:absolute;top:27px;left:0;right:0;bottom:0;background-color:#FaFaFa}.w2ui-calendar .w2ui-calendar-jump>:first-child{position:absolute;top:0;left:0;bottom:0;width:110px;overflow:hidden;padding-top:5px;border-right:1px solid silver}.w2ui-calendar .w2ui-calendar-jump>:last-child{position:absolute;top:0;right:0;bottom:0;width:88px;overflow-x:hidden;overflow-y:auto;padding-top:5px;text-align:center}.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-month,.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-year{display:inline-block;padding:5px 0;text-align:center;float:left;margin:2px;width:50px;cursor:default;border:1px solid transparent;border-radius:2px}.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-year{float:none;width:95%}.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-month:hover,.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-year:hover{border:1px solid #ccc;color:#000;background-color:#efefef}.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-month.selected,.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-year.selected{border:1px solid #ccc;color:#000;background-color:#dadada}.w2ui-calendar .w2ui-calendar-previous,.w2ui-calendar .w2ui-calendar-next{width:24px;height:20px;color:#666;border:1px solid transparent;border-radius:3px;padding:2px 3px 1px 2px;margin:-4px 0 0 0;cursor:default}.w2ui-calendar .w2ui-calendar-previous:hover,.w2ui-calendar .w2ui-calendar-next:hover{border:1px solid silver;background-color:#efefef}.w2ui-calendar .w2ui-calendar-previous>div,.w2ui-calendar .w2ui-calendar-next>div{position:absolute;border-left:4px solid #888;border-top:4px solid #888;border-right:4px solid transparent;border-bottom:4px solid transparent;width:0;height:0;padding:0;margin:3px 0 0}.w2ui-calendar .w2ui-calendar-previous{float:left}.w2ui-calendar .w2ui-calendar-previous>div{-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg);margin-left:6px}.w2ui-calendar .w2ui-calendar-next{float:right}.w2ui-calendar .w2ui-calendar-next>div{-webkit-transform:rotate(135deg);-moz-transform:rotate(135deg);-ms-transform:rotate(135deg);-o-transform:rotate(135deg);transform:rotate(135deg);margin-left:2px;margin-right:2px}.w2ui-calendar table.w2ui-calendar-days{padding:0}.w2ui-calendar table.w2ui-calendar-days td{border:1px solid #fff;color:#000;background-color:#f9f9f9;padding:6px;cursor:default;text-align:right}.w2ui-calendar table.w2ui-calendar-days td.w2ui-saturday,.w2ui-calendar table.w2ui-calendar-days td.w2ui-sunday{border:1px solid #fff;color:#c8493b;background-color:#f9f9f9}.w2ui-calendar table.w2ui-calendar-days td.w2ui-saturday:hover,.w2ui-calendar table.w2ui-calendar-days td.w2ui-sunday:hover{border:1px solid #ccc;color:#000;background-color:#e9e9e9}.w2ui-calendar table.w2ui-calendar-days td.w2ui-saturday.w2ui-blocked,.w2ui-calendar table.w2ui-calendar-days td.w2ui-sunday.w2ui-blocked{text-decoration:line-through;border:1px solid #fff;color:#ccc;background-color:#fff}.w2ui-calendar table.w2ui-calendar-days td.w2ui-today{border:1px solid #8cb067;color:#000;background-color:#e2f7cd}.w2ui-calendar table.w2ui-calendar-days td:hover{border:1px solid #ccc;color:#000;background-color:#e9e9e9}.w2ui-calendar table.w2ui-calendar-days td.w2ui-blocked{text-decoration:line-through;border:1px solid #fff;color:#ccc;background-color:#fff}.w2ui-calendar table.w2ui-calendar-days td.w2ui-day-empty{border:1px solid #fff;background-color:#fdfdfd}.w2ui-calendar table.w2ui-calendar-days tr.w2ui-day-title td{border:1px solid #fff;color:gray;background-color:#fff;text-align:center;padding:6px}.w2ui-calendar-time{padding:5px;cursor:default}.w2ui-calendar-time td div{padding:7px 10px;text-align:center;border:1px solid transparent;white-space:nowrap}.w2ui-calendar-time td:nth-child(even){background-color:#f6f6f6}.w2ui-calendar-time td div:hover{border:1px solid #ccc;color:#000;background-color:#e9e9e9}.w2ui-calendar-time td div.w2ui-blocked{text-decoration:line-through;border:1px solid #fff;color:#ccc;background-color:#fff}.w2ui-select{cursor:default;color:#000!important;background-image:-webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-ms-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%)}.w2ui-list{color:inherit;position:absolute;padding:0;margin:0;min-height:25px;overflow:auto;border:1px solid silver;border-radius:3px;font-size:6px;line-height:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;background-color:#fff}.w2ui-list input[type=text]{-webkit-box-shadow:none;-moz-box-shadow:none;-ms-box-shadow:none;-o-box-shadow:none;box-shadow:none}.w2ui-list ul{list-style-type:none;background-color:#000;margin:0;padding:0}.w2ui-list ul li{float:left;margin:2px 1px 0 2px;border-radius:3px;width:auto;padding:3px 10px 1px 7px;border:1px solid #88b0d6;background-color:#eff3f5;white-space:nowrap;cursor:default;font-family:verdana;font-size:11px;line-height:100%;height:20px;overflow:hidden;text-overflow:ellipsis;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-list ul li:hover{background-color:#d0dbe1}.w2ui-list ul li:last-child{border-radius:0;border:1px solid transparent;background-color:transparent}.w2ui-list ul li:last-child input{padding:1px;padding-top:0;margin:0;border:0;outline:0;height:auto;line-height:100%;font-size:inherit;font-family:inherit;background-color:transparent}.w2ui-list ul li .w2ui-list-remove{float:right;width:15px;height:14px;margin:-1px -9px 0 3px;border-radius:15px}.w2ui-list ul li .w2ui-list-remove:hover{background-color:#D77F7F;color:#fff}.w2ui-list ul li .w2ui-list-remove:before{position:relative;top:0;padding:0;margin:0;left:5px;color:inherit;opacity:.7;text-shadow:inherit;font-size:inherit;font-variant:small-caps;content:'x';line-height:100%}.w2ui-list ul li>span.file-size{pointer-events:none;color:#777}.w2ui-list .w2ui-enum-placeholder{display:inline;position:absolute;pointer-events:none;color:#999;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-list.w2ui-file-dragover{background-color:#E4FFDA;border:1px solid #93E07D}.w2ui-layout{overflow:hidden!important;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-layout *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-layout>div{position:absolute;overflow:hidden;border:0;margin:0;padding:0;outline:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-layout>div .w2ui-panel{display:none;position:absolute;z-index:120}.w2ui-layout>div .w2ui-panel .w2ui-panel-title{padding:5px;background-image:-webkit-linear-gradient(#dae6f3,#c2d5ed);background-image:-moz-linear-gradient(#dae6f3,#c2d5ed);background-image:-ms-linear-gradient(#dae6f3,#c2d5ed);background-image:-o-linear-gradient(#dae6f3,#c2d5ed);background-image:linear-gradient(#dae6f3,#c2d5ed);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffdae6f3', endColorstr='#ffc2d5ed', GradientType=0);border:1px solid #b9cee9;border-bottom:1px solid #99bbe8}.w2ui-layout>div .w2ui-panel .w2ui-panel-tabs{position:absolute;left:0;top:0;right:0;z-index:2;display:none;overflow:hidden;background-color:#fafafa;padding:4px 0}.w2ui-layout>div .w2ui-panel .w2ui-panel-tabs>.w2ui-tab.active{background-color:#f5f6f7}.w2ui-layout>div .w2ui-panel .w2ui-panel-toolbar{position:absolute;left:0;top:0;right:0;z-index:2;display:none;overflow:hidden;background-color:#fafafa;border-bottom:1px solid silver;padding:4px}.w2ui-layout>div .w2ui-panel .w2ui-panel-content{position:absolute;left:0;top:0;right:0;bottom:0;z-index:1;color:inherit;background-color:#f5f6f7}.w2ui-layout>div .w2ui-resizer{display:none;position:absolute;z-index:121;background-color:transparent}.w2ui-layout>div .w2ui-resizer:hover,.w2ui-layout>div .w2ui-resizer.active{background-color:#d7e4f2}.w2ui-grid{position:relative;border:1px solid silver;border-radius:2px;overflow:hidden!important}.w2ui-grid>div{position:absolute;overflow:hidden}.w2ui-grid .w2ui-grid-header{position:absolute;border-bottom:1px solid #99bbe8!important;height:28px;overflow:hidden;color:#444;font-size:13px;text-align:center;padding:7px;background-image:-webkit-linear-gradient(#dae6f3,#c2d5ed);background-image:-moz-linear-gradient(#dae6f3,#c2d5ed);background-image:-ms-linear-gradient(#dae6f3,#c2d5ed);background-image:-o-linear-gradient(#dae6f3,#c2d5ed);background-image:linear-gradient(#dae6f3,#c2d5ed);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffdae6f3', endColorstr='#ffc2d5ed', GradientType=0);border-top-left-radius:2px;border-top-right-radius:2px}.w2ui-grid .w2ui-grid-toolbar{position:absolute;border-bottom:1px solid silver;background-color:#eaeaea;height:38px;padding:7px 3px 4px;margin:0;box-shadow:0 1px 2px #ddd}.w2ui-grid .w2ui-toolbar-search{width:160px;margin-right:3px}.w2ui-grid .w2ui-toolbar-search .w2ui-search-all{outline:0!important;width:160px;border-radius:10px;line-height:normal;height:22px;border:1px solid #b9b9b9;color:#000;background-color:#fff;padding:3px 18px 3px 23px;margin:0}.w2ui-grid .w2ui-toolbar-search .w2ui-search-down{position:absolute;margin-top:-7px;margin-left:6px}.w2ui-grid .w2ui-toolbar-search .w2ui-search-clear{position:absolute;width:16px;height:16px;margin-top:-8px;margin-left:-20px;border-radius:15px;cursor:default}.w2ui-grid .w2ui-toolbar-search .w2ui-search-clear:hover{background-color:#D77F7F;color:#fff}.w2ui-grid .w2ui-toolbar-search .w2ui-search-clear:before{position:relative;top:1px;left:5px;opacity:.6;color:inherit;text-shadow:inherit;content:'x';cursor:default}.w2ui-grid .w2ui-grid-body{position:absolute;overflow:hidden;padding:0;background-color:#fff;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.w2ui-grid .w2ui-grid-body input,.w2ui-grid .w2ui-grid-body select,.w2ui-grid .w2ui-grid-body textarea{user-select:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;-o-user-select:text}.w2ui-grid .w2ui-grid-body .w2ui-grid-columns{overflow:hidden;position:absolute;left:0;top:0;right:0;box-shadow:0 1px 4px #ddd;height:auto}.w2ui-grid .w2ui-grid-body .w2ui-grid-columns table{height:auto}.w2ui-grid .w2ui-grid-body .w2ui-grid-columns .w2ui-resizer{position:absolute;z-index:1000;display:block;background-image:none;background-color:rgba(0,0,0,0);padding:0;margin:0;width:6px;height:12px;cursor:col-resize}.w2ui-grid .w2ui-grid-body .w2ui-grid-records{position:absolute;left:0;right:0;top:0;bottom:0}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-odd{color:inherit;background-color:#fff}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-odd:hover{color:inherit;background-color:#e6f0ff}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-odd.w2ui-empty-record:hover{background-color:#fff}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-even{color:inherit;background-color:#f3f6fa}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-even:hover{color:inherit;background-color:#e6f0ff}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-even.w2ui-empty-record:hover{background-color:#f3f6fa}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-selected,.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr td.w2ui-selected{color:#000!important;background-color:#b6d5ff!important}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-expanded{background-color:#CCDCF0!important}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-expanded1{height:0;border-bottom:1px solid #b2bac0;background-color:#CCDCF0}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-expanded1>div{height:100%;margin:0;padding:0}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-expanded2{height:0;border-radius:0;border-bottom:1px solid #b2bac0}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-expanded2>div{height:0;border:0;transition:height .3s,opacity .3s}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-load-more{border-top:1px solid #d6d5d7;cursor:pointer}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-load-more>div{text-align:center;color:#777;background-color:rgba(233,237,243,.5);padding:10px 0 15px;border-top:1px solid #fff}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-load-more>div:hover{color:inherit;background-color:#e6f0ff}.w2ui-grid .w2ui-grid-body table{border-spacing:0;border-collapse:collapse;table-layout:fixed;width:1px}.w2ui-grid .w2ui-grid-body table .w2ui-head{margin:0;padding:0;border-right:1px solid #c5c5c5;border-bottom:1px solid #c5c5c5;color:#000;background-image:-webkit-linear-gradient(#f9f9f9,#e4e4e4);background-image:-moz-linear-gradient(#f9f9f9,#e4e4e4);background-image:-ms-linear-gradient(#f9f9f9,#e4e4e4);background-image:-o-linear-gradient(#f9f9f9,#e4e4e4);background-image:linear-gradient(#f9f9f9,#e4e4e4);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#ffe4e4e4', GradientType=0)}.w2ui-grid .w2ui-grid-body table .w2ui-head>div{padding:7px 3px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;position:relative}.w2ui-grid .w2ui-grid-body table .w2ui-head.w2ui-col-intersection{border-right-color:#72b2ff}.w2ui-grid .w2ui-grid-body table .w2ui-head.w2ui-reorder-cols-head:hover{cursor:move}.w2ui-grid .w2ui-grid-body table .w2ui-head .col-intersection-marker{padding:0;position:absolute;height:100%;top:0}.w2ui-grid .w2ui-grid-body table .w2ui-head .col-intersection-marker.left{left:0;margin-left:-5px}.w2ui-grid .w2ui-grid-body table .w2ui-head .col-intersection-marker.right{right:0;margin-right:-5px}.w2ui-grid .w2ui-grid-body table .w2ui-head .col-intersection-marker .top-marker{position:absolute;top:0;height:0;width:0;border-top:5px solid #72b2ff;border-left:5px solid transparent;border-right:5px solid transparent}.w2ui-grid .w2ui-grid-body table .w2ui-head .col-intersection-marker .bottom-marker{position:absolute;bottom:0;height:0;width:0;border-bottom:5px solid #72b2ff;border-left:5px solid transparent;border-right:5px solid transparent}.w2ui-grid .w2ui-grid-body table td{border-right:1px solid #d6d5d7;border-bottom:0 solid #d6d5d7;cursor:default;overflow:hidden}.w2ui-grid .w2ui-grid-body table td.w2ui-grid-data{margin:0;padding:0}.w2ui-grid .w2ui-grid-body table td.w2ui-grid-data>div{padding:3px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.w2ui-grid .w2ui-grid-body table td.w2ui-grid-data>div.flexible-record{height:auto;overflow:visible;white-space:normal}.w2ui-grid .w2ui-grid-body table td:last-child{border-right:0}.w2ui-grid .w2ui-grid-body table .w2ui-col-number{width:34px;color:#777;background-color:rgba(233,237,243,.5)}.w2ui-grid .w2ui-grid-body table .w2ui-col-number div{padding:0 7px 0 3px;text-align:right}.w2ui-grid .w2ui-grid-body table .w2ui-col-select{width:26px}.w2ui-grid .w2ui-grid-body table .w2ui-col-select div{padding:0;text-align:center;overflow:hidden}.w2ui-grid .w2ui-grid-body table .w2ui-col-select div input[type=checkbox]{margin-top:2px;position:relative}.w2ui-grid .w2ui-grid-body table .w2ui-col-expand{width:26px}.w2ui-grid .w2ui-grid-body table .w2ui-col-expand div{padding:0;text-align:center;font-weight:700}.w2ui-grid .w2ui-grid-body div.w2ui-col-header{height:auto!important;width:100%;overflow:hidden;padding-right:10px!important}.w2ui-grid .w2ui-grid-body div.w2ui-col-header>div.w2ui-sort-up{border:4px solid transparent;border-bottom:5px solid #8D99A7;margin-top:-2px;margin-right:-7px;float:right}.w2ui-grid .w2ui-grid-body div.w2ui-col-header>div.w2ui-sort-down{border:4px solid transparent;border-top:5px solid #8D99A7;margin-top:2px;margin-right:-7px;float:right}.w2ui-grid .w2ui-grid-body .w2ui-col-group{text-align:center}.w2ui-grid .w2ui-changed{background:url(data:image/gif;base64,R0lGODlhCgAKAJEAALAABf///wAAAAAAACH5BAEAAAIALAAAAAAKAAoAAAIPlI8Hy8mbxIsSUnup3rQAADs=) no-repeat top right}.w2ui-grid .w2ui-editable{overflow:hidden;height:100%!important;margin:0!important;padding:0!important}.w2ui-grid .w2ui-editable input{border:0;border-radius:0;margin:0;padding:4px 3px;width:100%;height:100%}.w2ui-grid .w2ui-editable input.w2ui-select{outline:0!important;background:#fff}.w2ui-grid .w2ui-grid-summary{position:absolute;box-shadow:0 -1px 4px #aaa}.w2ui-grid .w2ui-grid-summary table{color:inherit}.w2ui-grid .w2ui-grid-summary table .w2ui-odd{background-color:#eef5eb}.w2ui-grid .w2ui-grid-summary table .w2ui-even{background-color:#f8fff5}.w2ui-grid .w2ui-grid-footer{position:absolute;margin:0;padding:0;text-align:center;height:24px;overflow:hidden;user-select:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;-o-user-select:text;box-shadow:0 -1px 4px #eee;color:#444;background-color:#f8f8f8;border-top:1px solid #ddd;border-bottom-left-radius:2px;border-bottom-right-radius:2px}.w2ui-grid .w2ui-grid-footer .w2ui-footer-left{float:left;padding-top:5px;padding-left:5px}.w2ui-grid .w2ui-grid-footer .w2ui-footer-right{float:right;padding-top:5px;padding-right:5px}.w2ui-grid .w2ui-grid-footer .w2ui-footer-center{padding:2px;text-align:center}.w2ui-grid .w2ui-grid-footer .w2ui-footer-center .w2ui-footer-nav{width:110px;margin:0 auto;padding:0;text-align:center}.w2ui-grid .w2ui-grid-footer .w2ui-footer-center .w2ui-footer-nav input[type=text]{padding:1px 2px 2px;border-radius:3px;width:40px;text-align:center}.w2ui-grid .w2ui-grid-footer .w2ui-footer-center .w2ui-footer-nav a.w2ui-footer-btn{display:inline-block;border-radius:3px;cursor:pointer;font-size:11px;line-height:16px;padding:1px 5px;width:30px;height:18px;margin-top:-1px;color:#000;background-color:transparent}.w2ui-grid .w2ui-grid-footer .w2ui-footer-center .w2ui-footer-nav a.w2ui-footer-btn:hover{color:#000;background-color:#aec8ff}.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr.w2ui-odd,.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr.w2ui-even,.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr.w2ui-odd:hover,.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr.w2ui-even:hover{background-color:inherit}.w2ui-ss .w2ui-grid-records table td{border-right-width:1px;border-bottom:1px solid #efefef}.w2ui-ss .w2ui-grid-records table tr:first-child td{border-bottom:0}.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr.w2ui-selected,.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr td.w2ui-selected{background-color:#EEF4FE!important}.w2ui-ss .w2ui-changed{background:inherit}.w2ui-ss .w2ui-grid-body .w2ui-selection{position:absolute;border:2px solid #6299DA;pointer-events:none}.w2ui-ss .w2ui-grid-body .w2ui-selection .w2ui-selection-resizer{cursor:crosshair;position:absolute;bottom:0;right:0;width:6px;height:6px;margin-right:-3px;margin-bottom:-3px;background-color:#457FC2;border:.5px solid #fff;outline:1px solid #fff;pointer-events:auto}.w2ui-overlay .w2ui-select-field{padding:8px 5px;cursor:default}.w2ui-overlay .w2ui-select-field table{font-size:11px;font-family:Verdana,Arial,sans-serif;border-spacing:0;border-collapse:border-collapse}.w2ui-overlay .w2ui-select-field table tr:hover{background-color:#b6d5ff}.w2ui-overlay .w2ui-select-field table td:nth-child(1){padding:3px 3px 3px 6px}.w2ui-overlay .w2ui-select-field table td:nth-child(1) input{margin:3px 2px 2px}.w2ui-overlay .w2ui-select-field table td:nth-child(2){padding:3px 15px 3px 3px}.w2ui-overlay .w2ui-col-on-off{padding:4px 0}.w2ui-overlay .w2ui-col-on-off table{border-spacing:0;border-collapse:border-collapse}.w2ui-overlay .w2ui-col-on-off table tr:hover{background-color:#b6d5ff}.w2ui-overlay .w2ui-col-on-off table td input[type=checkbox]{margin:3px 2px 2px}.w2ui-overlay .w2ui-col-on-off table td label{display:block;padding:3px 0;padding-right:10px}.w2ui-overlay .w2ui-col-on-off table td:first-child{padding:4px 0 4px 6px}.w2ui-overlay .w2ui-col-on-off table td:last-child{padding:4px 6px 4px 0}.w2ui-overlay .w2ui-grid-searches{text-align:left;padding:0;border-top:0;background-color:#f7f6f0}.w2ui-overlay .w2ui-grid-searches table{padding:4px;padding-top:12px;border-collapse:border-collapse}.w2ui-overlay .w2ui-grid-searches table td{padding:4px}.w2ui-overlay .w2ui-grid-searches table td.close-btn{width:20px;padding-right:20px}.w2ui-overlay .w2ui-grid-searches table td.close-btn button{min-width:24px;height:24px;padding-top:6px!important}.w2ui-overlay .w2ui-grid-searches table td.caption{text-align:right;padding-right:5px;border-right:1px solid #e8e8e3}.w2ui-overlay .w2ui-grid-searches table td.operator{text-align:left;padding:0 10px;padding-right:5px;border-right:1px solid #e8e8e3}.w2ui-overlay .w2ui-grid-searches table td.operator select{width:100%;color:#000;padding:0 15px 0 5px;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-image:-webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-ms-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%)}.w2ui-overlay .w2ui-grid-searches table td.operator select::-ms-expand{display:none}.w2ui-overlay .w2ui-grid-searches table td.value{padding-right:5px;padding-left:5px}.w2ui-overlay .w2ui-grid-searches table td.value input[type=text]{border-radius:3px;padding:3px;margin-right:3px;height:23px}.w2ui-overlay .w2ui-grid-searches table td.value select{padding:3px;margin-right:3px;height:23px}.w2ui-overlay .w2ui-grid-searches table td.actions{border-right:0}.w2ui-overlay .w2ui-grid-searches table td.actions>div{margin:-7px;margin-top:15px;padding:13px 0;text-align:center;background-color:#efefe9;border-top:1px solid #e8e8e3}.w2ui-popup{position:fixed;z-index:1600;overflow:hidden;font-family:Verdana,Arial,sans-serif;border-radius:6px;padding:0;margin:0;border:1px solid #777;background-color:#eee;box-shadow:0 0 25px #555}.w2ui-popup,.w2ui-popup *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-popup .w2ui-msg-title{padding:6px;border-radius:6px 6px 0 0;background-image:-webkit-linear-gradient(#ececec,#dfdfdf);background-image:-moz-linear-gradient(#ececec,#dfdfdf);background-image:-ms-linear-gradient(#ececec,#dfdfdf);background-image:-o-linear-gradient(#ececec,#dfdfdf);background-image:linear-gradient(#ececec,#dfdfdf);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffececec', endColorstr='#ffdfdfdf', GradientType=0);border-bottom:2px solid #bfbfbf;position:absolute;overflow:hidden;height:32px;left:0;right:0;top:0;text-overflow:ellipsis;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;cursor:move;font-size:15px;color:#555;z-index:300}.w2ui-popup .w2ui-msg-button{float:right;width:18px;height:18px;cursor:pointer;overflow:hidden;padding:0;margin:0 3px 0 0;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAQCAYAAABQrvyxAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAj1JREFUeNrslr9rFFEQxz/zZi/qxSgW2lsqkiYoBku5Ro1o4UFKEYkgSaxSCLYqdv5IEVPYCMJJwERWrK0CKhoQ8hdobQTjXW7njcXlYnLunQQu0YDTLOy+Nzvfme98Z8Td2ckW2OGWdMvRvYfT/RGfBPoBBVpLK0AEPgVkdGL06vt/CoB5nBaRE8AXYKXNsQIwaB4fAwOtH+88mn4m7ifN4vUYebWBKkFKqjIV3N9NjI2Uuw5ARI45fBanH+F77iFnN8JHETmS68P9NHBQNTwHL8foaSN4SqoyA/SZyL4tqQAQBVYCLOFYlNxmq0WorVLpN9Oe5LKt1CsgRVWpAOfB66phBuhTkepSdfnKVjaxNJMSWn/iawmTtpeDp6pWBpaBoqrMqoYU6AOqIbFhxGa3R4V8nfNNKLUESzXJhoCvQC+wF/gW1C5IiC+2XUbD5jA3rd4C26NR3945IA2iRzqRJgdElJJlSQocAKrAD2A/6Ev3cLajjN59MDWHyKl2voOI1zKbv3Xj2lCHJFoz+LXuBoIAjnUklEvJrDDT5LwmdhG8blkyBxRjXSu4loE0X4VEznXKV3SnoOFMB7YUolBcbcKNdxuPXUBPu8pbLXsK0ghebVjEXgNoYmXLtGLuxd6ePU+AQ20AaIrb4DpFycmSv81/7YsiMgAstB1kQgE47O4LuQmCNwGOB7VxCb/URsRSTbhkmU4ifGiZHd1Z5m7fnxoIQSaBo39YJRZj9LGb4yPzXWm1/9voX7afAwAC5tacDTA2XgAAAABJRU5ErkJggg==) no-repeat center left;background-position:0 0;color:transparent!important;border-radius:3px;border:1px solid transparent}.w2ui-popup .w2ui-msg-close{margin-top:0;background-position:-32px 0}.w2ui-popup .w2ui-msg-close:hover{background-color:#ccc;border:1px solid #aaa}.w2ui-popup .w2ui-msg-max{background-position:-16px 0}.w2ui-popup .w2ui-msg-max:hover{background-color:#ccc;border:1px solid #aaa}.w2ui-popup .w2ui-box1,.w2ui-popup .w2ui-box2{position:absolute;left:0;right:0;top:32px;bottom:55px;z-index:100}.w2ui-popup .w2ui-msg-body{font-size:13px;line-height:130%;padding:0 7px 7px;color:#000;background-color:#eee;position:absolute;overflow:auto;width:100%;height:100%}.w2ui-popup .w2ui-popup-message{position:absolute;z-index:250;background-color:#f9f9f9;border:1px solid #999;box-shadow:0 0 15px #aaa;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;border-top:0;border-radius:0 0 6px 6px;overflow:auto}.w2ui-popup .w2ui-msg-buttons{padding:12px;border-radius:0 0 6px 6px;border-top:1px solid #d5d8d8;background-color:#f1f1f1;text-align:center;position:absolute;overflow:hidden;height:52px;left:0;right:0;bottom:0;z-index:200}.w2ui-popup .w2ui-msg-no-title{border-top-left-radius:6px;border-top-right-radius:6px;top:0!important}.w2ui-popup .w2ui-msg-no-buttons{border-bottom-left-radius:6px;border-bottom-right-radius:6px;bottom:0!important}.w2ui-sidebar{cursor:default;overflow:hidden!important;background-color:#edf1f6!important;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-sidebar *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-sidebar>div{position:relative;overflow:hidden}.w2ui-sidebar .w2ui-sidebar-top{position:absolute;z-index:2;top:0;left:0;right:0}.w2ui-sidebar .w2ui-sidebar-bottom{position:absolute;z-index:2;bottom:0;left:0;right:0}.w2ui-sidebar .w2ui-sidebar-div{position:absolute;z-index:1;overflow:auto;top:0;bottom:0;left:0;right:0;padding:2px 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.w2ui-sidebar .w2ui-sidebar-div table{width:100%}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node{background-color:#edf1f6;border-top:1px solid transparent;border-bottom:1px solid transparent;margin:0;padding:1px 0}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node table{pointer-events:none}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-caption,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image>span,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node td.w2ui-node-dots{color:#000;text-shadow:0 0 0 #fff;pointer-events:none}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-caption:hover,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image:hover,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image>span:hover,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node td.w2ui-node-dots:hover{color:inherit}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node:hover{border-top:1px solid #f9f9f9;border-bottom:1px solid #f9f9f9;background-color:#d7e1ef}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image{width:22px;text-align:center;pointer-events:none}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image>span{color:#516173!important}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node input{pointer-events:auto}.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected:hover{background-image:-webkit-linear-gradient(#69b1e0,#4a96d3);background-image:-moz-linear-gradient(#69b1e0,#4a96d3);background-image:-ms-linear-gradient(#69b1e0,#4a96d3);background-image:-o-linear-gradient(#69b1e0,#4a96d3);background-image:linear-gradient(#69b1e0,#4a96d3);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff69b1e0', endColorstr='#ff4a96d3', GradientType=0);border-top:1px solid #5295cd;border-bottom:1px solid #2661a6}.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected .w2ui-node-caption,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected:hover .w2ui-node-caption,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected .w2ui-node-image,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected:hover .w2ui-node-image,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected .w2ui-node-image>span,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected:hover .w2ui-node-image>span,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected td.w2ui-node-dots,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected:hover td.w2ui-node-dots{color:#fff!important;text-shadow:1px 1px 2px #666!important}.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled:hover{background:transparent!important;border-top:1px solid transparent;border-bottom:1px solid transparent}.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled .w2ui-node-caption,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled:hover .w2ui-node-caption,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled .w2ui-node-image,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled:hover .w2ui-node-image,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled .w2ui-node-image>span,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled:hover .w2ui-node-image>span,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled td.w2ui-node-dots,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled:hover td.w2ui-node-dots{opacity:.4;filter:alpha(opacity=40);color:#000!important;text-shadow:0 0 0 #fff!important}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node-caption{white-space:nowrap;padding:5px 0 5px 3px;margin:1px 0 1px 22px;position:relative;z-index:1;font-size:12px}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node-group{white-space:nowrap;overflow:hidden;padding:10px 0 10px 10px;margin:0;cursor:default;color:#868b92;background-color:transparent}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node-group :nth-child(1){margin-right:10px;float:right;color:transparent}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node-group :nth-child(2){font-weight:400;text-transform:uppercase}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node-sub{overflow:hidden}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-dots{width:18px;padding:0 0 1px 7px;text-align:center}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-dots .w2ui-expand{width:16px;margin-top:-3px;pointer-events:auto}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-data{padding:1px 1px 3px}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-data .w2ui-node-image{padding:3px 0 0;float:left}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-data .w2ui-node-image>span{font-size:16px;color:#000;text-shadow:0 0 0 #fff}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-data .w2ui-node-image.w2ui-icon{margin-top:3px}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-data .w2ui-node-count{float:right;border:1px solid #9da4af;border-radius:20px;width:auto;height:18px;padding:2px 7px;margin:3px 4px -2px 0;background-color:#e7f0fc;color:#667274;box-shadow:0 0 2px #fff;text-shadow:1px 1px 1px #e6e6e6;position:relative;z-index:2}.w2ui-tabs{cursor:default;overflow:hidden!important;background-color:#fafafa;padding:3px 0;padding-bottom:0!important}.w2ui-tabs table{border-bottom:1px solid silver;padding:0 7px}.w2ui-tabs .w2ui-tab{padding:6px 20px;text-align:center;color:#000;background-color:transparent;border:1px solid silver;border-bottom:1px solid silver;white-space:nowrap;margin:1px 1px -1px 0;border-top-left-radius:4px;border-top-right-radius:4px;cursor:default}.w2ui-tabs .w2ui-tab.active{color:#000;background-color:#fff;border:1px solid silver;border-bottom:1px solid transparent}.w2ui-tabs .w2ui-tab.closable{padding:6px 28px 6px 20px}.w2ui-tabs .w2ui-tab-close{color:#555;text-shadow:1px 1px 1px #bbb;float:right;margin:6px 4px 0 0;padding:0 0 0 5px;width:16px;height:16px;opacity:.9;border:0;border-top:3px solid transparent;border-radius:9px}.w2ui-tabs .w2ui-tab-close:hover{background-color:#D77F7F;color:#fff}.w2ui-tabs .w2ui-tab-close:before{position:relative;top:-2px;left:0;opacity:.6;color:inherit;text-shadow:inherit;content:'x'}.w2ui-toolbar{margin:0;padding:2px;outline:0;background-color:#efefef;overflow:hidden!important;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.w2ui-toolbar .disabled{opacity:.3;filter:alpha(opacity=30)}.w2ui-toolbar table{table-layout:auto!important}.w2ui-toolbar table td{border:0!important}.w2ui-toolbar table.w2ui-button{margin:0 1px;border-radius:4px;height:24px;border:1px solid transparent;background-color:transparent}.w2ui-toolbar table.w2ui-button .w2ui-tb-image{width:16px;height:16px;padding:0;margin:2px 4px 3px 3px!important;border:0!important;text-align:center}.w2ui-toolbar table.w2ui-button .w2ui-tb-image>span{font-size:15px;margin-top:3px;display:block;color:#8d99a7}.w2ui-toolbar table.w2ui-button .w2ui-tb-caption{color:#000;padding:0 4px 0 2px}.w2ui-toolbar table.w2ui-button .w2ui-tb-count{padding:0 4px 0 0}.w2ui-toolbar table.w2ui-button .w2ui-tb-count>span{border:1px solid #9da4af;border-radius:20px;width:auto;height:18px;padding:2px 7px;background-color:#e7f0fc;color:#667274;box-shadow:0 0 2px #fff;text-shadow:1px 1px 1px #e6e6e6}.w2ui-toolbar table.w2ui-button .w2ui-tb-down{padding:3px}.w2ui-toolbar table.w2ui-button .w2ui-tb-down>div{border:4px solid transparent;border-top:5px solid #8D99A7;margin-top:5px}.w2ui-toolbar table.w2ui-button.over{border:1px solid #ccc;background-color:#eee}.w2ui-toolbar table.w2ui-button.over .w2ui-tb-caption{color:#000}.w2ui-toolbar table.w2ui-button.down{border:1px solid #aaa;background-color:#ddd}.w2ui-toolbar table.w2ui-button.down .w2ui-tb-caption{color:#666}.w2ui-toolbar table.w2ui-button.checked{border:1px solid #aaa;background-color:#fff}.w2ui-toolbar table.w2ui-button.checked .w2ui-tb-caption{color:#000}.w2ui-toolbar table.w2ui-button table{height:17px;border-radius:4px;cursor:default}.w2ui-toolbar .w2ui-break{background-image:-webkit-linear-gradient(top,rgba(153,153,153,.1) 0,#999 40%,#999 60%,rgba(153,153,153,.1) 100%);background-image:-moz-linear-gradient(top,rgba(153,153,153,.1) 0,#999 40%,#999 60%,rgba(153,153,153,.1) 100%);background-image:-ms-linear-gradient(top,rgba(153,153,153,.1) 0,#999 40%,#999 60%,rgba(153,153,153,.1) 100%);background-image:-o-linear-gradient(top,rgba(153,153,153,.1) 0,#999 40%,#999 60%,rgba(153,153,153,.1) 100%);background-image:linear-gradient(top,rgba(153,153,153,.1) 0,#999 40%,#999 60%,rgba(153,153,153,.1) 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff999999', endColorstr='#ff999999', GradientType=0);width:1px!important;height:22px;padding:0;margin:0 6px}.w2ui-listview{overflow:auto!important;background-color:#fff!important;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-listview *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-listview>ul{list-style-type:none;margin:0;cursor:default}.w2ui-listview>ul>li{display:inline-block;vertical-align:top;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;border:1px solid transparent;border-radius:4px}.w2ui-listview>ul>li.w2ui-focused{border:1px solid #2661a6}.w2ui-listview>ul>li.w2ui-selected{border:1px solid #2661a6}.w2ui-listview>ul>li.w2ui-selected,.w2ui-listview>ul>li.w2ui-selected.hover{background-image:-webkit-linear-gradient(#69b1e0,#4a96d3);background-image:-moz-linear-gradient(#69b1e0,#4a96d3);background-image:-ms-linear-gradient(#69b1e0,#4a96d3);background-image:-o-linear-gradient(#69b1e0,#4a96d3);background-image:linear-gradient(#69b1e0,#4a96d3);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff69b1e0', endColorstr='#ff4a96d3', GradientType=0)}.w2ui-listview>ul>li.w2ui-selected>div>div.caption,.w2ui-listview>ul>li.w2ui-selected.hover>div>div.caption{color:#fff}.w2ui-listview>ul>li.w2ui-selected>div>div.description,.w2ui-listview>ul>li.w2ui-selected.hover>div>div.description{color:#ddd}.w2ui-listview>ul>li.w2ui-selected>div>div.extra>div>div,.w2ui-listview>ul>li.w2ui-selected.hover>div>div.extra>div>div{color:#ddd}.w2ui-listview>ul>li.hover{background-color:#d7e1ef;border:1px solid #2661a6}.w2ui-listview>ul>li div{vertical-align:middle}.w2ui-listview>ul>li>div>div.caption{display:block;text-align:center;word-wrap:break-word;max-height:50px;color:#000;font-size:12px}.w2ui-listview>ul>li>div>div.description{display:none;text-align:left;color:#777;font-size:12px}.w2ui-listview>ul>li>div>div.extra{display:none}.w2ui-listview>ul>li>div>div.extra>div>div{color:#777}.w2ui-icon-small>ul{padding:1px 0 0 1px}.w2ui-icon-small>ul>li{margin:0 1px 1px 0;padding:2px;width:250px;white-space:nowrap}.w2ui-icon-small>ul>li>div>div.w2ui-listview-img{display:inline-block;width:26px;height:22px;font-size:21px;margin-right:2px}.w2ui-icon-small>ul>li>div>div.caption{display:inline-block}.w2ui-icon-medium>ul{padding:4px 0 0 4px}.w2ui-icon-medium>ul>li{margin:0 4px 4px 0;padding:4px;width:100px}.w2ui-icon-medium>ul>li>div>div.w2ui-listview-img{display:block;width:92px;height:60px;font-size:57px;margin-left:auto;margin-right:auto;background-position:center}.w2ui-icon-large>ul{padding:4px 0 0 4px}.w2ui-icon-large>ul>li{margin:0 4px 4px 0;padding:4px;width:160px}.w2ui-icon-large>ul>li>div>div.w2ui-listview-img{display:block;width:152px;height:120px;font-size:114px;margin-left:auto;margin-right:auto;background-position:center}.w2ui-icon-tile>ul{padding:1px 0 0 1px}.w2ui-icon-tile>ul>li{margin:0 1px 1px 0;padding:4px;width:250px;white-space:nowrap}.w2ui-icon-tile>ul>li>div>div.w2ui-listview-img{display:inline-block;width:72px;height:60px;font-size:57px;float:left;margin-right:4px}.w2ui-icon-tile>ul>li>div>div.caption{text-align:left}.w2ui-icon-tile>ul>li>div>div.description{display:block}.w2ui-table>ul{padding:0}.w2ui-table>ul>li{width:100%;padding:2px;border-radius:0;border-bottom:1px dotted #d3d3d3}.w2ui-table>ul>li>div{display:inline-block;position:relative;width:100%;white-space:nowrap;overflow:hidden}.w2ui-table>ul>li>div>div.w2ui-listview-img{display:inline-block;width:38px;height:32px;font-size:31px;margin-right:2px}.w2ui-table>ul>li>div>div.caption{display:inline-block}.w2ui-table>ul>li>div>div.extra{display:inline-block;position:absolute;right:0;height:100%;background-color:#fff}.w2ui-table>ul>li>div>div.extra>div:before{display:inline-block;height:100%;width:0;content:'';vertical-align:middle}.w2ui-table>ul>li>div>div.extra>div{display:inline}.w2ui-table>ul>li>div>div.extra>div>div{display:inline-block;font-size:12px}.w2ui-table>ul>li.w2ui-selected div.extra,.w2ui-table>ul>li.w2ui-selected.hover div.extra{background-image:-webkit-linear-gradient(#69b1e0,#4a96d3);background-image:-moz-linear-gradient(#69b1e0,#4a96d3);background-image:-ms-linear-gradient(#69b1e0,#4a96d3);background-image:-o-linear-gradient(#69b1e0,#4a96d3);background-image:linear-gradient(#69b1e0,#4a96d3);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff69b1e0', endColorstr='#ff4a96d3', GradientType=0)}.w2ui-table>ul>li.hover div.extra{background-color:#d7e1ef}.w2ui-listview>ul>li div.icon-none{border:1px solid rgba(102,102,102,.35)} +/* olexp 0.1.2 (c) Daniel Pulido */ +.ol-control,.ol-scale-line{position:absolute;padding:2px}.ol-box{box-sizing:border-box;border-radius:2px;border:2px solid #00f}.ol-mouse-position{top:8px;right:8px;position:absolute}.ol-scale-line{background:rgba(0,60,136,.3);border-radius:4px;bottom:8px;left:8px}.ol-scale-line-inner{border:1px solid #eee;border-top:none;color:#eee;font-size:10px;text-align:center;margin:1px;will-change:contents,width}.ol-overlay-container{will-change:left,right,top,bottom}.ol-unsupported{display:none}.ol-viewport .ol-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.ol-control{background-color:rgba(255,255,255,.4);border-radius:4px}.ol-control:hover{background-color:rgba(255,255,255,.6)}.ol-zoom{top:.5em;left:.5em}.ol-rotate{top:.5em;right:.5em;transition:opacity .25s linear,visibility 0s linear}.ol-rotate.ol-hidden{opacity:0;visibility:hidden;transition:opacity .25s linear,visibility 0s linear .25s}.ol-zoom-extent{top:4.643em;left:.5em}.ol-full-screen{right:.5em;top:.5em}@media print{.ol-control{display:none}}.ol-control button{display:block;margin:1px;padding:0;color:#fff;font-size:1.14em;font-weight:700;text-decoration:none;text-align:center;height:1.375em;width:1.375em;line-height:.4em;background-color:rgba(0,60,136,.5);border:none;border-radius:2px}.ol-control button::-moz-focus-inner{border:none;padding:0}.ol-zoom-extent button{line-height:1.4em}.ol-compass{display:block;font-weight:400;font-size:1.2em;will-change:transform}.ol-touch .ol-control button{font-size:1.5em}.ol-touch .ol-zoom-extent{top:5.5em}.ol-control button:focus,.ol-control button:hover{text-decoration:none;background-color:rgba(0,60,136,.7)}.ol-zoom .ol-zoom-in{border-radius:2px 2px 0 0}.ol-zoom .ol-zoom-out{border-radius:0 0 2px 2px}.ol-attribution{text-align:right;bottom:.5em;right:.5em;max-width:calc(100% - 1.3em)}.ol-attribution ul{margin:0;padding:0 .5em;font-size:.7rem;line-height:1.375em;color:#000;text-shadow:0 0 2px #fff}.ol-attribution li{display:inline;list-style:none;line-height:inherit}.ol-attribution li:not(:last-child):after{content:" "}.ol-attribution img{max-height:2em;max-width:inherit;vertical-align:middle}.ol-attribution button,.ol-attribution ul{display:inline-block}.ol-attribution.ol-collapsed ul{display:none}.ol-attribution.ol-logo-only ul{display:block}.ol-attribution:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-attribution.ol-uncollapsible{bottom:0;right:0;border-radius:4px 0 0;height:1.1em;line-height:1em}.ol-attribution.ol-logo-only{background:0 0;bottom:.4em;height:1.1em;line-height:1em}.ol-attribution.ol-uncollapsible img{margin-top:-.2em;max-height:1.6em}.ol-attribution.ol-logo-only button,.ol-attribution.ol-uncollapsible button{display:none}.ol-zoomslider{top:4.5em;left:.5em;height:200px}.ol-zoomslider button{position:relative;height:10px}.ol-touch .ol-zoomslider{top:5.5em}.ol-overviewmap{left:.5em;bottom:.5em}.ol-overviewmap.ol-uncollapsible{bottom:0;left:0;border-radius:0 4px 0 0}.ol-overviewmap .ol-overviewmap-map,.ol-overviewmap button{display:inline-block}.ol-overviewmap .ol-overviewmap-map{border:1px solid #7b98bc;height:150px;margin:2px;width:150px}.ol-overviewmap:not(.ol-collapsed) button{bottom:1px;left:2px;position:absolute}.ol-overviewmap.ol-collapsed .ol-overviewmap-map,.ol-overviewmap.ol-uncollapsible button{display:none}.ol-overviewmap:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-overviewmap-box{border:2px dotted rgba(0,60,136,.7)} +/* w2ui 1.4.3 (c) http://w2ui.com, vitmalina@gmail.com */ +@font-face{font-family:w2ui-font;src:url("data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAWIAAoAAAAACAgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAAA9AAAAEMAAABWQLxMsmNtYXAAAAE4AAAAOgAAAUriGRC2Z2x5ZgAAAXQAAAH9AAACgLu4vTRoZWFkAAADdAAAADAAAAA2AOYXBGhoZWEAAAOkAAAAIAAAACQD8wHHaG10eAAAA8QAAAAWAAAAIA7dAABsb2NhAAAD3AAAABIAAAASAngBuG1heHAAAAPwAAAAHwAAACABFQA2bmFtZQAABBAAAAEtAAACIsTQ/zJwb3N0AAAFQAAAAEgAAABi4/7ZEHicY2BkvMM4gYGVgYPRhTGNgYHBHUp/ZZBkaGFgYGJgZWbACgLSXFMYHD4yfmRnPPD/AIMe4wEGR6AwI0gOANHZC/IAeJxjYGBgZoBgGQZGBhBwAfIYwXwWBg0gzQakGRmYGBg+sv//D1LwkRFE8zNA1QMBIxvDiAcAddwGvgAAeJxFkLFv01AQxu97LrHdRImjpnaS1gnEia3IoqAktkkiEhaEOiCsDkEo8dyBDkytKpYKVWwssKKKAYmBREKMLJSFoRJ/AGJhY0NZGFgSzrUinvR+d++7T+/ePQLRci4IJ3SFCLIjG8CH+ZPwHHdwkkSS2PMXP3DGmUxpoo123lrt5nj8fjyejsc4W0zwNtl8FfHCKV5QnaOhF3IJUrUbkGPYnSGcGH6risBvGQhdVY0iVXXVkhJN1JL6/6xOIqWk4tRlJiVFiSJFSUrsZ+tkoqpEgt/6Hb/wjtZog2gonBx24AyFJUuNwMvha+/CvLi3vq1f785GsxGuTqfWc5O1N/r2+lNrOl38ZHnWpdUMr/CaLKLGZiHl4hI1+zasGB2/Dy9GSzfRbul4qaWPtHSQ0Y7SWpxmgnSc/mblMKNpmcOVEhfj+5d/8BGfqMl9bKuWFYWKaLf8YIAq9IKc5TY7ojNgTTcC7iEjaN4yPdswbM+81t8UimRLojq66YbdWq0bus375t21bwgcw/H6nmNUyhIkR/DsTasXPgx7VtV8oDx6XIxHE8vl8rMAzqlEDZ7QseUBPP6tLOQKDH5HqooKfLvB2gABa1lgflzI60VxsLd3IJj1YRn5/Wx9Syy++LvArn/JzH4e5WE98TCLer5wnBNb9WcrB5PoH084dg8AAAB4nGNgZGBgAOKMsPib8fw2Xxm4mRhA4PzjbBcY/f////1MjIwHgFwOBrA0AFcuDPF4nGNgZGBgPPD/AIMeEwMDw/9/TEwMQBEUwAEAe34EvHicY2JgYGCCYsbJCJpxO4QNABdTAesAAAAAAAAAEgAsAGgAjgC+AP4BQAAAeJxjYGRgYOBg0GJgZgABJiDmAkIGhv9gPgMADYEBTAB4nG2PTW7CMBCFXyBQFaQKtVKl7qwuuqkIPwsWHAD2LNiH4ARQEkeOQeICPUHP0DP0BF32DD1KX8IoixZbHn/z5o1/AAzwBQ/V8HBbx2q0cMPswm3SQNgnPwl30MezcJf6ULiHV8yE+3hAyBM8vzrtHk64hTu8Cbepvwv75A/hDh7xKdyl/i3cwxo/wn28eLN9ZPJhbHK30skxDW2TN7DWttybXE2CcaMtda5t6PRWbc6qPCVT52IVW5OpBas6TY0qrDnoyAU754r5aBSLHkQmwx4RDHL+Oq53hxU0EhyR8sf2Sv2/smaHRclKlStMEGB8xbekL6+9ITONLb0bnBlLnHjnlKqjW3FZ9mSkhfRqviclKxR17UAloh5gV3cVmGPEGf/xB/Ursl9uDmByAAAAeJxtwUEOgCAMBMAu0sI3SdMEIwKh8n8PXp2hQB+mf5kIAQciGIKEzFpNr6Sj7bs76xruMq3r2eJs22XZtPKIW1laiV6rCBDA") format("woff");font-weight:400;font-style:normal}[class^=w2ui-icon-]:before,[class*=" w2ui-icon-"]:before{font-family:w2ui-font;display:inline-block;vertical-align:middle;line-height:1;font-weight:400;font-style:normal;speak:none;text-decoration:inherit;text-transform:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w2ui-icon-check:before{content:"\f101"}.w2ui-icon-columns:before{content:"\f102"}.w2ui-icon-cross:before{content:"\f103"}.w2ui-icon-pencil:before{content:"\f104"}.w2ui-icon-plus:before{content:"\f105"}.w2ui-icon-reload:before{content:"\f106"}.w2ui-icon-search:before{content:"\f107"}.w2ui-reset{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;font-family:Verdana,Arial,sans-serif;font-size:11px}.w2ui-reset *{color:default;line-height:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0}.w2ui-reset table{font-family:Verdana,Arial,sans-serif;font-size:11px;max-width:none;background-color:transparent;border-collapse:separate;border-spacing:0}.w2ui-reset input,.w2ui-reset textarea{width:auto;height:auto;vertical-align:baseline;padding:4px}.w2ui-reset select{padding:1px;height:23px}.w2ui-centered{position:absolute;left:0;right:0;top:50%;-webkit-transform:translateY(-50%);-moz-transform:translateY(-50%);-ms-transform:translateY(-50%);-o-transform:translateY(-50%);transform:translateY(-50%);max-height:100%;margin:0;padding:0 10px;text-align:center}.w2ui-disabled,.w2ui-readonly{background-color:#f1f1f1!important;color:#777!important}input:not([type=button]),select,textarea{padding:4px;border:1px solid #bbb;border-radius:3px;color:#000;background-color:#fff;line-height:normal}input:not([type=button]):focus,select:focus,textarea:focus{outline-color:#72b2ff}input:not([type=button]):disabled,select:disabled,textarea:disabled,input:not([type=button])[readonly],select[readonly],textarea[readonly]{background-color:#f1f1f1;color:#777}input::-ms-clear{display:none}input:-ms-input-placeholder{color:#aaa!important}select{padding:2px}input[type=checkbox].w2ui-toggle{position:absolute;opacity:0;width:46px;height:22px;padding:0;margin:0;margin-left:2px}input[type=checkbox].w2ui-toggle+div{display:inline-block;width:46px;height:22px;border:1px solid #bbb;border-radius:30px;background-color:#eee;-webkit-transition-duration:.3s;-webkit-transition-property:background-color,box-shadow;-moz-transition-duration:.3s;-moz-transition-property:background-color,box-shadow;box-shadow:inset 0 0 0 0 rgba(0,0,0,.4);margin-left:2px}input[type=checkbox].w2ui-toggle:disabled+div{opacity:.3}input[type=checkbox].w2ui-toggle+div>div{float:left;width:22px;height:22px;border-radius:inherit;background:#f5f5f5;-webkit-transition-duration:.3s;-webkit-transition-property:transform,background-color,box-shadow;-moz-transition-duration:.3s;-moz-transition-property:transform,background-color;box-shadow:0 0 1px #323232,0 0 0 1px rgba(200,200,200,.6);pointer-events:none;margin-top:-1px;margin-left:-1px}input[type=checkbox].w2ui-toggle:checked+div{border:1px solid #00a23f;box-shadow:inset 0 0 0 12px #54B350}input[type=checkbox].w2ui-toggle:checked+div>div{-webkit-transform:translate3d(24px,0,0);-moz-transform:translate3d(24px,0,0);background-color:#fff;box-shadow:0 2px 5px rgba(0,0,0,.3),0 0 0 1px #00a23f}input[type=checkbox].w2ui-toggle.blue:checked+div{border:1px solid #206FAD;box-shadow:inset 0 0 0 12px #35A6EB}input[type=checkbox].w2ui-toggle.blue:checked+div>div{box-shadow:0 2px 5px rgba(0,0,0,.3),0 0 0 1px #206fad}input[type=checkbox].w2ui-toggle:focus{outline:0}.w2ui-overlay{position:absolute;margin-top:6px;margin-left:-17px;display:none;z-index:1300;color:inherit;background-color:#fbfbfb;border:3px solid #777;box-shadow:0 2px 10px #999;border-radius:4px;text-align:left}.w2ui-overlay table td{color:inherit}.w2ui-overlay:before{content:"";position:absolute;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg);width:12px;height:12px;border:3px solid #777;border-color:inherit;background-color:inherit;border-left:1px solid transparent;border-bottom:1px solid transparent;border-bottom-left-radius:50px;margin:-9px 0 0 30px}.w2ui-overlay:after{display:none;content:"";position:absolute;-webkit-transform:rotate(135deg);-moz-transform:rotate(135deg);-ms-transform:rotate(135deg);-o-transform:rotate(135deg);transform:rotate(135deg);width:12px;height:12px;border:3px solid #777;border-color:inherit;background-color:inherit;border-left:1px solid transparent;border-bottom:1px solid transparent;border-bottom-left-radius:50px;margin:-7px 0 0 30px}.w2ui-overlay.w2ui-overlay-popup{z-index:1700}.w2ui-tag{position:absolute;z-index:1300;opacity:0;-webkit-transition:opacity .3s;-moz-transition:opacity .3s;-ms-transition:opacity .3s;-o-transition:opacity .3s;transition:opacity .3s}.w2ui-tag .w2ui-tag-body{background-color:rgba(60,60,60,.82);display:inline-block;position:absolute;border-radius:4px;padding:4px 10px;margin-left:10px;margin-top:0;color:#fff!important;box-shadow:1px 1px 3px #000;line-height:100%;font-size:11px;font-family:Verdana,Arial,sans-serif}.w2ui-tag .w2ui-tag-body:before{content:"";position:absolute;width:0;height:0;border-top:5px solid transparent;border-right:5px solid rgba(60,60,60,.82);border-bottom:5px solid transparent;margin:2px 0 0 -15px}.w2ui-tag.w2ui-tag-popup{z-index:1700}.w2ui-overlay table.w2ui-drop-menu{width:100%;color:#000;background-color:#fff;padding:5px 0;cursor:default}.w2ui-overlay table.w2ui-drop-menu td{white-space:nowrap}.w2ui-overlay table.w2ui-drop-menu .w2ui-item-even{color:inherit;background-color:#fff}.w2ui-overlay table.w2ui-drop-menu .w2ui-item-odd{color:inherit;background-color:#f3f6fa}.w2ui-overlay table.w2ui-drop-menu .w2ui-item-group{color:#444;font-weight:700;background-color:#ECEDF0;border-bottom:1px solid #D3D2D4}.w2ui-overlay table.w2ui-drop-menu td.menu-icon{padding:3px 0 4px 6px;width:20px}.w2ui-overlay table.w2ui-drop-menu td.menu-text{padding:8px 10px 8px 5px;width:auto}.w2ui-overlay table.w2ui-drop-menu td.menu-count{text-align:right}.w2ui-overlay table.w2ui-drop-menu td.menu-count>span{border:1px solid #9da4af;border-radius:20px;width:auto;height:18px;padding:2px 7px;margin:3px 5px 0;background-color:#e7f0fc;color:#667274;box-shadow:0 0 2px #fff;text-shadow:1px 1px 1px #e6e6e6}.w2ui-overlay table.w2ui-drop-menu tr:hover{color:inherit;background-color:#e6f0ff}.w2ui-overlay table.w2ui-drop-menu tr.w2ui-selected{background-color:#b6d5fb}.w2ui-overlay table.w2ui-drop-menu tr.w2ui-selected td{color:inherit}.w2ui-overlay table.w2ui-drop-menu tr.w2ui-disabled{opacity:.4;background-color:#fff!important}.w2ui-overlay table.w2ui-drop-menu .w2ui-icon{font-size:14px;color:#8d99a7;display:inline-block;padding-top:4px}.w2ui-marker{color:#444;background-color:rgba(252,244,161,.48)}.w2ui-spinner{display:inline-block;background-size:100%;background-repeat:no-repeat;background-image:url(data:image/gif;base64,R0lGODlhgACAAKIAAP///93d3bu7u5mZmQAA/wAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFBQAEACwCAAIAfAB8AAAD/0i63P4wygYqmDjrzbtflvWNZGliYXiubKuloivPLlzReD7al+7/Eh5wSFQIi8hHYBkwHUmD6CD5YTJLz49USuVYraRsZ7vtar7XnQ1Kjpoz6LRHvGlz35O4nEPP2O94EnpNc2sef1OBGIOFMId/inB6jSmPdpGScR19EoiYmZobnBCIiZ95k6KGGp6ni4wvqxilrqBfqo6skLW2YBmjDa28r6Eosp27w8Rov8ekycqoqUHODrTRvXsQwArC2NLF29UM19/LtxO5yJd4Au4CK7DUNxPebG4e7+8n8iv2WmQ66BtoYpo/dvfacBjIkITBE9DGlMvAsOIIZjIUAixliv9ixYZVtLUos5GjwI8gzc3iCGghypQqrbFsme8lwZgLZtIcYfNmTJ34WPTUZw5oRxdD9w0z6iOpO15MgTh1BTTJUKos39jE+o/KS64IFVmsFfYT0aU7capdy7at27dw48qdS7eu3bt480I02vUbX2F/JxYNDImw4GiGE/P9qbhxVpWOI/eFKtlNZbWXuzlmG1mv58+gQ4seTbq06dOoU6vGQZJy0FNlMcV+czhQ7SQmYd8eMhPs5BxVdfcGEtV3buDBXQ+fURxx8oM6MT9P+Fh6dOrH2zavc13u9JXVJb520Vp8dvC76wXMuN5Sepm/1WtkEZHDefnzR9Qvsd9+/wi8+en3X0ntYVcSdAE+UN4zs7ln24CaLagghIxBaGF8kFGoIYV+Ybghh841GIyI5ICIFoklJsigihmimJOLEbLYIYwxSgigiZ+8l2KB+Ml4oo/w8dijjcrouCORKwIpnJIjMnkkksalNeR4fuBIm5UEYImhIlsGCeWNNJphpJdSTlkml1jWeOY6TnaRpppUctcmFW9mGSaZceYopH9zkjnjUe59iR5pdapWaGqHopboaYua1qije67GJ6CuJAAAIfkEBQUABAAsCgACAFcAMAAAA/9Iutz+ML5Ag7w46z0r5WAoSp43nihXVmnrdusrv+s332dt4Tyo9yOBUJD6oQBIQGs4RBlHySSKyczVTtHoidocPUNZaZAr9F5FYbGI3PWdQWn1mi36buLKFJvojsHjLnshdhl4L4IqbxqGh4gahBJ4eY1kiX6LgDN7fBmQEJI4jhieD4yhdJ2KkZk8oiSqEaatqBekDLKztBG2CqBACq4wJRi4PZu1sA2+v8C6EJexrBAD1AOBzsLE0g/V1UvYR9sN3eR6lTLi4+TlY1wz6Qzr8u1t6FkY8vNzZTxaGfn6mAkEGFDgL4LrDDJDyE4hEIbdHB6ESE1iD4oVLfLAqPETIsOODwmCDJlv5MSGJklaS6khAQAh+QQFBQAEACwfAAIAVwAwAAAD/0i63P5LSAGrvTjrNuf+YKh1nWieIumhbFupkivPBEzR+GnnfLj3ooFwwPqdAshAazhEGUXJJIrJ1MGOUamJ2jQ9QVltkCv0XqFh5IncBX01afGYnDqD40u2z76JK/N0bnxweC5sRB9vF34zh4gjg4uMjXobihWTlJUZlw9+fzSHlpGYhTminKSepqebF50NmTyor6qxrLO0L7YLn0ALuhCwCrJAjrUqkrjGrsIkGMW/BMEPJcphLgDaABjUKNEh29vdgTLLIOLpF80s5xrp8ORVONgi8PcZ8zlRJvf40tL8/QPYQ+BAgjgMxkPIQ6E6hgkdjoNIQ+JEijMsasNY0RQix4gKP+YIKXKkwJIFF6JMudFEAgAh+QQFBQAEACw8AAIAQgBCAAAD/kg0PPowykmrna3dzXvNmSeOFqiRaGoyaTuujitv8Gx/661HtSv8gt2jlwIChYtc0XjcEUnMpu4pikpv1I71astytkGh9wJGJk3QrXlcKa+VWjeSPZHP4Rtw+I2OW81DeBZ2fCB+UYCBfWRqiQp0CnqOj4J1jZOQkpOUIYx/m4oxg5cuAaYBO4Qop6c6pKusrDevIrG2rkwptrupXB67vKAbwMHCFcTFxhLIt8oUzLHOE9Cy0hHUrdbX2KjaENzey9Dh08jkz8Tnx83q66bt8PHy8/T19vf4+fr6AP3+/wADAjQmsKDBf6AOKjS4aaHDgZMeSgTQcKLDhBYPEswoA1BBAgAh+QQFBQAEACxOAAoAMABXAAAD7Ei6vPOjyUkrhdDqfXHm4OZ9YSmNpKmiqVqykbuysgvX5o2HcLxzup8oKLQQix0UcqhcVo5ORi+aHFEn02sDeuWqBGCBkbYLh5/NmnldxajX7LbPBK+PH7K6narfO/t+SIBwfINmUYaHf4lghYyOhlqJWgqDlAuAlwyBmpVnnaChoqOkpaanqKmqKgGtrq+wsbA1srW2ry63urasu764Jr/CAb3Du7nGt7TJsqvOz9DR0tPU1TIA2ACl2dyi3N/aneDf4uPklObj6OngWuzt7u/d8fLY9PXr9eFX+vv8+PnYlUsXiqC3c6PmUUgAACH5BAUFAAQALE4AHwAwAFcAAAPpSLrc/m7IAau9bU7MO9GgJ0ZgOI5leoqpumKt+1axPJO1dtO5vuM9yi8TlAyBvSMxqES2mo8cFFKb8kzWqzDL7Xq/4LB4TC6bz1yBes1uu9uzt3zOXtHv8xN+Dx/x/wJ6gHt2g3Rxhm9oi4yNjo+QkZKTCgGWAWaXmmOanZhgnp2goaJdpKGmp55cqqusrZuvsJays6mzn1m4uRAAvgAvuBW/v8GwvcTFxqfIycA3zA/OytCl0tPPO7HD2GLYvt7dYd/ZX99j5+Pi6tPh6+bvXuTuzujxXens9fr7YPn+7egRI9PPHrgpCQAAIfkEBQUABAAsPAA8AEIAQgAAA/lIutz+UI1Jq7026h2x/xUncmD5jehjrlnqSmz8vrE8u7V5z/m5/8CgcEgsGo/IpHLJbDqf0Kh0ShBYBdTXdZsdbb/Yrgb8FUfIYLMDTVYz2G13FV6Wz+lX+x0fdvPzdn9WeoJGAYcBN39EiIiKeEONjTt0kZKHQGyWl4mZdREAoQAcnJhBXBqioqSlT6qqG6WmTK+rsa1NtaGsuEu6o7yXubojsrTEIsa+yMm9SL8osp3PzM2cStDRykfZ2tfUtS/bRd3ewtzV5pLo4eLjQuUp70Hx8t9E9eqO5Oku5/ztdkxi90qPg3x2EMpR6IahGocPCxp8AGtigwQAIfkEBQUABAAsHwBOAFcAMAAAA/9Iutz+MMo36pg4682J/V0ojs1nXmSqSqe5vrDXunEdzq2ta3i+/5DeCUh0CGnF5BGULC4tTeUTFQVONYAs4CfoCkZPjFar83rBx8l4XDObSUL1Ott2d1U4yZwcs5/xSBB7dBMBhgEYfncrTBGDW4WHhomKUY+QEZKSE4qLRY8YmoeUfkmXoaKInJ2fgxmpqqulQKCvqRqsP7WooriVO7u8mhu5NacasMTFMMHCm8qzzM2RvdDRK9PUwxzLKdnaz9y/Kt8SyR3dIuXmtyHpHMcd5+jvWK4i8/TXHff47SLjQvQLkU+fG29rUhQ06IkEG4X/Rryp4mwUxSgLL/7IqFETB8eONT6ChCFy5ItqJomES6kgAQAh+QQFBQAEACwKAE4AVwAwAAAD/0i63A4QuEmrvTi3yLX/4MeNUmieITmibEuppCu3sDrfYG3jPKbHveDktxIaF8TOcZmMLI9NyBPanFKJp4A2IBx4B5lkdqvtfb8+HYpMxp3Pl1qLvXW/vWkli16/3dFxTi58ZRcChwIYf3hWBIRchoiHiotWj5AVkpIXi4xLjxiaiJR/T5ehoomcnZ+EGamqq6VGoK+pGqxCtaiiuJVBu7yaHrk4pxqwxMUzwcKbyrPMzZG90NGDrh/JH8t72dq3IN1jfCHb3L/e5ebh4ukmxyDn6O8g08jt7tf26ybz+m/W9GNXzUQ9fm1Q/APoSWAhhfkMAmpEbRhFKwsvCsmosRIHx444PoKcIXKkjIImjTzjkQAAIfkEBQUABAAsAgA8AEIAQgAAA/VIBNz+8KlJq72Yxs1d/uDVjVxogmQqnaylvkArT7A63/V47/m2/8CgcEgsGo/IpHLJbDqf0Kh0Sj0FroGqDMvVmrjgrDcTBo8v5fCZki6vCW33Oq4+0832O/at3+f7fICBdzsChgJGeoWHhkV0P4yMRG1BkYeOeECWl5hXQ5uNIAOjA1KgiKKko1CnqBmqqk+nIbCkTq20taVNs7m1vKAnurtLvb6wTMbHsUq4wrrFwSzDzcrLtknW16tI2tvERt6pv0fi48jh5h/U6Zs77EXSN/BE8jP09ZFA+PmhP/xvJgAMSGBgQINvEK5ReIZhQ3QEMTBLAAAh+QQFBQAEACwCAB8AMABXAAAD50i6DA4syklre87qTbHn4OaNYSmNqKmiqVqyrcvBsazRpH3jmC7yD98OCBF2iEXjBKmsAJsWHDQKmw571l8my+16v+CweEwum8+hgHrNbrvbtrd8znbR73MVfg838f8BeoB7doN0cYZvaIuMjY6PkJGSk2gClgJml5pjmp2YYJ6dX6GeXaShWaeoVqqlU62ir7CXqbOWrLafsrNctjIDwAMWvC7BwRWtNsbGFKc+y8fNsTrQ0dK3QtXAYtrCYd3eYN3c49/a5NVj5eLn5u3s6e7x8NDo9fbL+Mzy9/T5+tvUzdN3Zp+GBAAh+QQJBQAEACwCAAIAfAB8AAAD/0i63P4wykmrvTjrzbv/YCiOZGmeaKqubOu+cCzPdArcQK2TOL7/nl4PSMwIfcUk5YhUOh3M5nNKiOaoWCuWqt1Ou16l9RpOgsvEMdocXbOZ7nQ7DjzTaeq7zq6P5fszfIASAYUBIYKDDoaGIImKC4ySH3OQEJKYHZWWi5iZG0ecEZ6eHEOio6SfqCaqpaytrpOwJLKztCO2jLi1uoW8Ir6/wCHCxMG2x7muysukzb230M6H09bX2Nna29zd3t/g4cAC5OXm5+jn3Ons7eba7vHt2fL16tj2+QL0+vXw/e7WAUwnrqDBgwgTKlzIsKHDh2gGSBwAccHEixAvaqTYcFCjRoYeNyoM6REhyZIHT4o0qPIjy5YTTcKUmHImx5cwE85cmJPnSYckK66sSAAj0aNIkypdyrSp06dQo0qdSrWq1atYs2rdyrWr169gwxZJAAA7)}.w2ui-icon{background-repeat:no-repeat;height:16px;width:16px;overflow:hidden;margin:2px;display:inline-block}.w2ui-icon.icon-search,.w2ui-icon.icon-search-down{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAgCAYAAAB+ZAqzAAACuElEQVRYw9WXSWhTQRjHR0UKLqhFaV0OUih68GAOWjyJKypCpAoV8aIiioIICiKiB1GMtE3MYmry2moXDz1UDx7sUXHBhQpSaRVxrYpWcMO9avx/8AJh/CbznHkxdeB3Cd/8589kvuUJkWcdjCTHghUgAi6DJ+AVeAqugSQIggniXywcNBJsB70g44EHYBcYXUhTM8EFj4ZkboKqQpiqAv2GprK8o7/f75t6pjn0M3gNPmri3vtycxAZA64qDvkJ2kENqAQTQQWoBg74qth3B4y3NbZDIX4fzNfsnQtuK/YfsjFVCh4pMq3Co0Y5uMVoUGkpy8aFT5xaeSzVEo45bXdBt4LeaLq1k0RXMYJfdDfFmAuAD4zWlty4UNyZEkm19MUb2zMw8Sfp1u+IWSrcIimLnTG8/SijdU6OO5poDESdtgHZVBzUHm/amhW7zoitMTS2mNHqASPk2FDCCcLMYK6p+obmulyxfiYLA4bGKFvfSnrUvkq5+Lpk8z4yRH8r3l/X4WiqJFfspSQ0CGYZGpsMnkt6L+h31Z76hpMdeOwPQ7H0NFnssST0C8wxNDaDKb6kP06150gsHahNNlVzYheZd7HJ0BiX4VRGhpmIhRixKyZilM2M1mnTArtIUbU3/qVO0H0GvmQ4CY4C3YopYYlHjXlggNG4R33Ypi2tVtwaPeTdNMkq9pVQZQdvFPs32zbx4aAjzxhDRfIAWAeWg7VgrzsY5ht/zoNJtubKwA3LITGjSKRyW3NTwaUCmKOSMd3WHH0ZJRQZZkOP1zFKZ3CB++4+aQ6kEeksWAb2a2L7qDv49S1Q6T72MOgEXa6RGFhP3wpS/B6NOWpRs0UxFg7eqTFHjX1hscxtAz/ymEuIYi0cvgF8Y0w5Ro3dZ3M1boJkTaXEUFlug6fsdsRQWzTj0cey+N/Xb2sj5lTh2M6OAAAAAElFTkSuQmCC) no-repeat center!important;background-size:14px 12px!important;opacity:.9}.w2ui-icon.icon-folder{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGrSURBVDjLxZO7ihRBFIa/6u0ZW7GHBUV0UQQTZzd3QdhMQxOfwMRXEANBMNQX0MzAzFAwEzHwARbNFDdwEd31Mj3X7a6uOr9BtzNjYjKBJ6nicP7v3KqcJFaxhBVtZUAK8OHlld2st7Xl3DJPVONP+zEUV4HqL5UDYHr5xvuQAjgl/Qs7TzvOOVAjxjlC+ePSwe6DfbVegLVuT4r14eTr6zvA8xSAoBLzx6pvj4l+DZIezuVkG9fY2H7YRQIMZIBwycmzH1/s3F8AapfIPNF3kQk7+kw9PWBy+IZOdg5Ug3mkAATy/t0usovzGeCUWTjCz0B+Sj0ekfdvkZ3abBv+U4GaCtJ1iEm6ANQJ6fEzrG/engcKw/wXQvEKxSEKQxRGKE7Izt+DSiwBJMUSm71rguMYhQKrBygOIRStf4TiFFRBvbRGKiQLWP29yRSHKBTtfdBmHs0BUpgvtgF4yRFR+NUKi0XZcYjCeCG2smkzLAHkbRBmP0/Uk26O5YnUActBp1GsAI+S5nRJJJal5K1aAMrq0d6Tm9uI6zjyf75dAe6tx/SsWeD//o2/Ab6IH3/h25pOAAAAAElFTkSuQmCC) no-repeat center!important}.w2ui-icon.icon-page{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAINSURBVBgZBcG/r55zGAfg6/4+z3va01NHlYgzEfE7MdCIGISFgS4Gk8ViYyM2Mdlsko4GSf8Do0FLRCIkghhYJA3aVBtEz3nP89wf11VJvPDepdd390+8Nso5nESBQoq0pfvXm9fzWf19453LF85vASqJlz748vInb517dIw6EyYBIIG49u+xi9/c9MdvR//99MPPZ7+4cP4IZhhTPbwzT2d+vGoaVRRp1rRliVvHq+cfvM3TD82+7mun0o/ceO7NT+/4/KOXjwZU1ekk0840bAZzMQ2mooqh0A72d5x/6sB9D5zYnff3PoYBoWBgFKPKqDKqjCpjKr//dcu9p489dra88cydps30KswACfNEKanSaxhlntjJ8Mv12Paie+vZ+0+oeSwwQ0Iw1xAR1CiFNJkGO4wu3ZMY1AAzBI0qSgmCNJsJUEOtJSMaCTBDLyQ0CknAGOgyTyFFiLI2awMzdEcSQgSAAKVUmAeNkxvWJWCGtVlDmgYQ0GFtgg4pNtOwbBcwQy/Rife/2yrRRVI0qYCEBly8Z+P4qMEMy7JaVw72N568e+iwhrXoECQkfH91kY7jwwXMsBx1L93ZruqrK6uuiAIdSnTIKKPLPFcvay8ww/Hh+ufeznTXu49v95IMoQG3784gYXdTqvRmqn/Wpa/ADFX58MW3L71SVU9ETgEIQQQIOOzub+fhIvwPRDgeVjWDahIAAAAASUVORK5CYII=) no-repeat center!important}.w2ui-lock{display:none;position:absolute;z-index:1400;top:0;left:0;width:100%;height:100%;opacity:.15;filter:alpha(opacity=15);background-color:#333}.w2ui-lock-msg{display:none;position:absolute;z-index:1400;top:45%;left:50%;-webkit-transform:translateX(-50%) translateY(-50%);-moz-transform:translateX(-50%) translateY(-50%);-ms-transform:translateX(-50%) translateY(-50%);-o-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);width:200px;height:80px;padding:30px 8px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-size:13px;font-family:Verdana,Arial,sans-serif;opacity:.8;filter:alpha(opacity=80);background-color:#555;color:#fff;text-align:center;border-radius:5px;border:2px solid #444}.w2ui-lock-msg .w2ui-spinner{display:inline-block;width:24px;height:24px;margin:-3px 8px -7px -10px}button.btn{display:inline-block;border-radius:4px;margin:0 5px;padding:7px 12px 6px!important;color:#666;font-size:12px!important;border:1px solid #B6B6B6;background-image:-webkit-linear-gradient(#fff 0,#e7e7e7 100%);background-image:-moz-linear-gradient(#fff 0,#e7e7e7 100%);background-image:-ms-linear-gradient(#fff 0,#e7e7e7 100%);background-image:-o-linear-gradient(#fff 0,#e7e7e7 100%);background-image:linear-gradient(#fff 0,#e7e7e7 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffe7e7e7', endColorstr='#ffffffff', GradientType=0);outline:0;box-shadow:0 1px 0 #fff;cursor:default;min-width:75px;line-height:100%!important;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}button.btn:hover{text-decoration:none;border:1px solid #bbb;background-image:-webkit-linear-gradient(#f7f7f7 0,#ddd 100%);background-image:-moz-linear-gradient(#f7f7f7 0,#ddd 100%);background-image:-ms-linear-gradient(#f7f7f7 0,#ddd 100%);background-image:-o-linear-gradient(#f7f7f7 0,#ddd 100%);background-image:linear-gradient(#f7f7f7 0,#ddd 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffdddddd', endColorstr='#fff7f7f7', GradientType=0);color:#333}button.btn:active,button.btn.clicked{border:1px solid #999;background-image:-webkit-linear-gradient(#ccc 0,#ccc 100%);background-image:-moz-linear-gradient(#ccc 0,#ccc 100%);background-image:-ms-linear-gradient(#ccc 0,#ccc 100%);background-image:-o-linear-gradient(#ccc 0,#ccc 100%);background-image:linear-gradient(#ccc 0,#ccc 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffcccccc', endColorstr='#ffcccccc', GradientType=0);text-shadow:1px 1px 1px #eee}button.btn:disabled{border:1px solid #bbb!important;background:#f7f7f7!important;color:#bdbcbc!important;text-shadow:none!important}button.btn-blue{color:#fff;background-image:-webkit-linear-gradient(#80c0f7 0,#269df0 100%);background-image:-moz-linear-gradient(#80c0f7 0,#269df0 100%);background-image:-ms-linear-gradient(#80c0f7 0,#269df0 100%);background-image:-o-linear-gradient(#80c0f7 0,#269df0 100%);background-image:linear-gradient(#80c0f7 0,#269df0 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff269df0', endColorstr='#ff80c0f7', GradientType=0);border:1px solid #538AB7;text-shadow:1px 1px 1px #777}button.btn-blue:hover{color:#fff;background-image:-webkit-linear-gradient(#73b6f0 0,#2391dd 100%);background-image:-moz-linear-gradient(#73b6f0 0,#2391dd 100%);background-image:-ms-linear-gradient(#73b6f0 0,#2391dd 100%);background-image:-o-linear-gradient(#73b6f0 0,#2391dd 100%);background-image:linear-gradient(#73b6f0 0,#2391dd 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff2391dd', endColorstr='#ff73b6f0', GradientType=0);border:1px solid #497BA3;text-shadow:1px 1px 1px #777}button.btn-blue:active,button.btn-blue.clicked{color:#fff;background-image:-webkit-linear-gradient(#1e83c9 0,#1e83c9 100%);background-image:-moz-linear-gradient(#1e83c9 0,#1e83c9 100%);background-image:-ms-linear-gradient(#1e83c9 0,#1e83c9 100%);background-image:-o-linear-gradient(#1e83c9 0,#1e83c9 100%);background-image:linear-gradient(#1e83c9 0,#1e83c9 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff1e83c9', endColorstr='#ff1e83c9', GradientType=0);border:1px solid #1268A6;text-shadow:1px 1px 1px #777}button.btn-green{color:#fff;background-image:-webkit-linear-gradient(#81cf81 0,#52a452 100%);background-image:-moz-linear-gradient(#81cf81 0,#52a452 100%);background-image:-ms-linear-gradient(#81cf81 0,#52a452 100%);background-image:-o-linear-gradient(#81cf81 0,#52a452 100%);background-image:linear-gradient(#81cf81 0,#52a452 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff52a452', endColorstr='#ff81cf81', GradientType=0);border:1px solid #479247;text-shadow:1px 1px 1px #777}button.btn-green:hover{color:#fff;background-image:-webkit-linear-gradient(#6abe68 0,#3f8f3d 100%);background-image:-moz-linear-gradient(#6abe68 0,#3f8f3d 100%);background-image:-ms-linear-gradient(#6abe68 0,#3f8f3d 100%);background-image:-o-linear-gradient(#6abe68 0,#3f8f3d 100%);background-image:linear-gradient(#6abe68 0,#3f8f3d 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff3f8f3d', endColorstr='#ff6abe68', GradientType=0);border:1px solid #479247;text-shadow:1px 1px 1px #777}button.btn-green:active,button.btn-green.clicked{color:#fff;background-image:-webkit-linear-gradient(#377d36 0,#377d36 100%);background-image:-moz-linear-gradient(#377d36 0,#377d36 100%);background-image:-ms-linear-gradient(#377d36 0,#377d36 100%);background-image:-o-linear-gradient(#377d36 0,#377d36 100%);background-image:linear-gradient(#377d36 0,#377d36 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff377d36', endColorstr='#ff377d36', GradientType=0);border:1px solid #555!important;text-shadow:1px 1px 1px #777}button.btn-orange{color:#fff;background-image:-webkit-linear-gradient(#fcc272 0,#fb8822 100%);background-image:-moz-linear-gradient(#fcc272 0,#fb8822 100%);background-image:-ms-linear-gradient(#fcc272 0,#fb8822 100%);background-image:-o-linear-gradient(#fcc272 0,#fb8822 100%);background-image:linear-gradient(#fcc272 0,#fb8822 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fffb8822', endColorstr='#fffcc272', GradientType=0);border:1px solid #B68B4C;text-shadow:1px 1px 1px #777}button.btn-orange:hover{color:#fff;background-image:-webkit-linear-gradient(#f4ad59 0,#f1731f 100%);background-image:-moz-linear-gradient(#f4ad59 0,#f1731f 100%);background-image:-ms-linear-gradient(#f4ad59 0,#f1731f 100%);background-image:-o-linear-gradient(#f4ad59 0,#f1731f 100%);background-image:linear-gradient(#f4ad59 0,#f1731f 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff1731f', endColorstr='#fff4ad59', GradientType=0);border:1px solid #B68B4C;text-shadow:1px 1px 1px #777}button.btn-orange:active,button.btn-orange.clicked{color:#fff;border:1px solid #666;background-image:-webkit-linear-gradient(#b98747 0,#b98747 100%);background-image:-moz-linear-gradient(#b98747 0,#b98747 100%);background-image:-ms-linear-gradient(#b98747 0,#b98747 100%);background-image:-o-linear-gradient(#b98747 0,#b98747 100%);background-image:linear-gradient(#b98747 0,#b98747 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffb98747', endColorstr='#ffb98747', GradientType=0);text-shadow:1px 1px 1px #777}button.btn-red{color:#fff;background-image:-webkit-linear-gradient(#ff6e70 0,#c72d2d 100%);background-image:-moz-linear-gradient(#ff6e70 0,#c72d2d 100%);background-image:-ms-linear-gradient(#ff6e70 0,#c72d2d 100%);background-image:-o-linear-gradient(#ff6e70 0,#c72d2d 100%);background-image:linear-gradient(#ff6e70 0,#c72d2d 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffc72d2d', endColorstr='#ffff6e70', GradientType=0);border:1px solid #BB3C3E;text-shadow:1px 1px 1px #777}button.btn-red:hover{color:#fff;background-image:-webkit-linear-gradient(#ee696c 0,#ae2527 100%);background-image:-moz-linear-gradient(#ee696c 0,#ae2527 100%);background-image:-ms-linear-gradient(#ee696c 0,#ae2527 100%);background-image:-o-linear-gradient(#ee696c 0,#ae2527 100%);background-image:linear-gradient(#ee696c 0,#ae2527 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffae2527', endColorstr='#ffee696c', GradientType=0);border:1px solid #BB3C3E;text-shadow:1px 1px 1px #777}button.btn-red:active,button.btn-red.clicked{color:#fff;border:1px solid #861C1E;background-image:-webkit-linear-gradient(#9c2123 0,#9c2123 100%);background-image:-moz-linear-gradient(#9c2123 0,#9c2123 100%);background-image:-ms-linear-gradient(#9c2123 0,#9c2123 100%);background-image:-o-linear-gradient(#9c2123 0,#9c2123 100%);background-image:linear-gradient(#9c2123 0,#9c2123 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff9c2123', endColorstr='#ff9c2123', GradientType=0);text-shadow:1px 1px 1px #777}.w2ui-form{position:relative;color:#000;background-color:#f5f6f7;border:1px solid silver;border-radius:3px;padding:0;overflow:hidden!important}.w2ui-form>div{position:absolute;overflow:hidden}.w2ui-form .w2ui-form-header{position:absolute;left:0;right:0;border-bottom:1px solid #99bbe8!important;overflow:hidden;color:#444;font-size:13px;text-align:center;padding:8px;background-image:-webkit-linear-gradient(#dae6f3,#c2d5ed);background-image:-moz-linear-gradient(#dae6f3,#c2d5ed);background-image:-ms-linear-gradient(#dae6f3,#c2d5ed);background-image:-o-linear-gradient(#dae6f3,#c2d5ed);background-image:linear-gradient(#dae6f3,#c2d5ed);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffdae6f3', endColorstr='#ffc2d5ed', GradientType=0);border-top-left-radius:3px;border-top-right-radius:3px}.w2ui-form .w2ui-form-toolbar{position:absolute;left:0;right:0;margin:0;padding:6px 3px;border-bottom:1px solid #d5d8d8}.w2ui-form .w2ui-form-tabs{margin:0;padding:0}.w2ui-form .w2ui-tabs{position:absolute;left:0;right:0;border-top-left-radius:3px;border-top-right-radius:3px;padding-top:5px!important;background-color:#fafafa}.w2ui-form .w2ui-tabs .w2ui-tab.active{background-color:#f5f6f7}.w2ui-form .w2ui-page{position:absolute;left:0;right:0;overflow:auto;padding:10px;border-left:1px solid inherit;border-right:1px solid inherit;background-color:inherit;border-radius:3px}.w2ui-form .w2ui-buttons{position:absolute;left:0;right:0;bottom:0;text-align:center;border-top:1px solid #d5d8d8;border-bottom:0 solid #d5d8d8;background-color:#fafafa;padding:15px 0!important;border-bottom-left-radius:3px;border-bottom-right-radius:3px}.w2ui-form .w2ui-buttons input[type=button],.w2ui-form .w2ui-buttons button{min-width:80px;margin-right:5px}.w2ui-form input[type=checkbox],.w2ui-form input[type=radio]{margin-top:4px;margin-bottom:4px}.w2ui-form input[type=checkbox].w2ui-toggle{margin:0}.w2ui-group-title{padding:5px 2px;color:#8D96A2;text-shadow:1px 1px 2px #fdfdfd;font-size:120%}.w2ui-group{background-color:#ebecef;margin:5px 0 10px;padding:10px 5px;border-top:1px solid #cedcea;border-bottom:1px solid #cedcea}.w2ui-field>label{display:block;float:left;margin-top:7px;margin-bottom:3px;width:120px;padding:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:right;min-height:20px;color:#666}.w2ui-field>div{margin-bottom:3px;margin-left:128px;padding:3px;min-height:28px;float:none}.w2ui-field.w2ui-required>div{position:relative}.w2ui-field.w2ui-required>div::before{content:'*';position:absolute;margin-top:5px;margin-left:-9px;color:red}.w2ui-field.w2ui-span1>label{width:20px}.w2ui-field.w2ui-span1>div{margin-left:28px}.w2ui-field.w2ui-span2>label{width:40px}.w2ui-field.w2ui-span2>div{margin-left:48px}.w2ui-field.w2ui-span3>label{width:60px}.w2ui-field.w2ui-span3>div{margin-left:68px}.w2ui-field.w2ui-span4>label{width:80px}.w2ui-field.w2ui-span4>div{margin-left:88px}.w2ui-field.w2ui-span5>label{width:100px}.w2ui-field.w2ui-span5>div{margin-left:108px}.w2ui-field.w2ui-span6>label{width:120px}.w2ui-field.w2ui-span6>div{margin-left:128px}.w2ui-field.w2ui-span7>label{width:140px}.w2ui-field.w2ui-span7>div{margin-left:148px}.w2ui-field.w2ui-span8>label{width:160px}.w2ui-field.w2ui-span8>div{margin-left:168px}.w2ui-field.w2ui-span9>label{width:180px}.w2ui-field.w2ui-span9>div{margin-left:188px}.w2ui-field.w2ui-span10>label{width:200px}.w2ui-field.w2ui-span10>div{margin-left:208px}.w2ui-error{border:1px solid #ffa8a8!important;background-color:#fff4eb!important}.w2field{padding:3px;border-radius:3px;border:1px solid silver}.w2ui-field-helper{position:absolute;display:inline-block;line-height:100%;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none}.w2ui-field-helper .w2ui-field-up{position:absolute;top:0;padding:2px 3px}.w2ui-field-helper .w2ui-field-down{position:absolute;bottom:0;padding:2px 3px}.w2ui-field-helper .arrow-up:hover{border-bottom-color:#81C6FF}.w2ui-field-helper .arrow-down:hover{border-top-color:#81C6FF}.arrow-up{background:0 0;width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:5px solid #777;font-size:0;line-height:0}.arrow-down{background:0 0;width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid #777;font-size:0;line-height:0}.arrow-left{background:0 0;width:0;height:0;border-bottom:4px solid transparent;border-top:4px solid transparent;border-right:5px solid #777;font-size:0;line-height:0}.arrow-right{background:0 0;width:0;height:0;border-bottom:4px solid transparent;border-top:4px solid transparent;border-left:5px solid #777;font-size:0;line-height:0}.w2ui-color{padding:5px;padding-top:8px;background-color:#fff;border-radius:3px}.w2ui-color>table{table-layout:fixed;width:160px}.w2ui-color>table td{width:20px;height:20px;text-align:center}.w2ui-color>table td div{cursor:pointer;display:inline-block;width:16px;height:17px;padding:1px 4px;border:1px solid transparent;color:#fff;text-shadow:0 0 2px #000}.w2ui-color>table td div:hover{outline:1px solid #666;border:1px solid #fff}.w2ui-calendar{margin:0;padding:1px;line-height:108%}.w2ui-calendar .w2ui-calendar-title{margin:0 -1px;padding:7px 2px;background-image:-webkit-linear-gradient(#f6f6f6,#d9d9d9);background-image:-moz-linear-gradient(#f6f6f6,#d9d9d9);background-image:-ms-linear-gradient(#f6f6f6,#d9d9d9);background-image:-o-linear-gradient(#f6f6f6,#d9d9d9);background-image:linear-gradient(#f6f6f6,#d9d9d9);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff6f6f6', endColorstr='#ffd9d9d9', GradientType=0);border-bottom:1px solid #bbb;color:#555;text-align:center;text-shadow:1px 1px 1px #eee;cursor:pointer}.w2ui-calendar .w2ui-calendar-jump{position:absolute;top:27px;left:0;right:0;bottom:0;background-color:#FaFaFa}.w2ui-calendar .w2ui-calendar-jump>:first-child{position:absolute;top:0;left:0;bottom:0;width:110px;overflow:hidden;padding-top:5px;border-right:1px solid silver}.w2ui-calendar .w2ui-calendar-jump>:last-child{position:absolute;top:0;right:0;bottom:0;width:88px;overflow-x:hidden;overflow-y:auto;padding-top:5px;text-align:center}.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-month,.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-year{display:inline-block;padding:5px 0;text-align:center;float:left;margin:2px;width:50px;cursor:default;border:1px solid transparent;border-radius:2px}.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-year{float:none;width:95%}.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-month:hover,.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-year:hover{border:1px solid #ccc;color:#000;background-color:#efefef}.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-month.selected,.w2ui-calendar .w2ui-calendar-jump .w2ui-jump-year.selected{border:1px solid #ccc;color:#000;background-color:#dadada}.w2ui-calendar .w2ui-calendar-previous,.w2ui-calendar .w2ui-calendar-next{width:24px;height:20px;color:#666;border:1px solid transparent;border-radius:3px;padding:2px 3px 1px 2px;margin:-4px 0 0 0;cursor:default}.w2ui-calendar .w2ui-calendar-previous:hover,.w2ui-calendar .w2ui-calendar-next:hover{border:1px solid silver;background-color:#efefef}.w2ui-calendar .w2ui-calendar-previous>div,.w2ui-calendar .w2ui-calendar-next>div{position:absolute;border-left:4px solid #888;border-top:4px solid #888;border-right:4px solid transparent;border-bottom:4px solid transparent;width:0;height:0;padding:0;margin:3px 0 0}.w2ui-calendar .w2ui-calendar-previous{float:left}.w2ui-calendar .w2ui-calendar-previous>div{-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg);margin-left:6px}.w2ui-calendar .w2ui-calendar-next{float:right}.w2ui-calendar .w2ui-calendar-next>div{-webkit-transform:rotate(135deg);-moz-transform:rotate(135deg);-ms-transform:rotate(135deg);-o-transform:rotate(135deg);transform:rotate(135deg);margin-left:2px;margin-right:2px}.w2ui-calendar table.w2ui-calendar-days{padding:0}.w2ui-calendar table.w2ui-calendar-days td{border:1px solid #fff;color:#000;background-color:#f9f9f9;padding:6px;cursor:default;text-align:right}.w2ui-calendar table.w2ui-calendar-days td.w2ui-saturday,.w2ui-calendar table.w2ui-calendar-days td.w2ui-sunday{border:1px solid #fff;color:#c8493b;background-color:#f9f9f9}.w2ui-calendar table.w2ui-calendar-days td.w2ui-saturday:hover,.w2ui-calendar table.w2ui-calendar-days td.w2ui-sunday:hover{border:1px solid #ccc;color:#000;background-color:#e9e9e9}.w2ui-calendar table.w2ui-calendar-days td.w2ui-saturday.w2ui-blocked,.w2ui-calendar table.w2ui-calendar-days td.w2ui-sunday.w2ui-blocked{text-decoration:line-through;border:1px solid #fff;color:#ccc;background-color:#fff}.w2ui-calendar table.w2ui-calendar-days td.w2ui-today{border:1px solid #8cb067;color:#000;background-color:#e2f7cd}.w2ui-calendar table.w2ui-calendar-days td:hover{border:1px solid #ccc;color:#000;background-color:#e9e9e9}.w2ui-calendar table.w2ui-calendar-days td.w2ui-blocked{text-decoration:line-through;border:1px solid #fff;color:#ccc;background-color:#fff}.w2ui-calendar table.w2ui-calendar-days td.w2ui-day-empty{border:1px solid #fff;background-color:#fdfdfd}.w2ui-calendar table.w2ui-calendar-days tr.w2ui-day-title td{border:1px solid #fff;color:gray;background-color:#fff;text-align:center;padding:6px}.w2ui-calendar-time{padding:5px;cursor:default}.w2ui-calendar-time td div{padding:7px 10px;text-align:center;border:1px solid transparent;white-space:nowrap}.w2ui-calendar-time td:nth-child(even){background-color:#f6f6f6}.w2ui-calendar-time td div:hover{border:1px solid #ccc;color:#000;background-color:#e9e9e9}.w2ui-calendar-time td div.w2ui-blocked{text-decoration:line-through;border:1px solid #fff;color:#ccc;background-color:#fff}.w2ui-select{cursor:default;color:#000!important;background-image:-webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-ms-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%)}.w2ui-list{color:inherit;position:absolute;padding:0;margin:0;min-height:25px;overflow:auto;border:1px solid silver;border-radius:3px;font-size:6px;line-height:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;background-color:#fff}.w2ui-list input[type=text]{-webkit-box-shadow:none;-moz-box-shadow:none;-ms-box-shadow:none;-o-box-shadow:none;box-shadow:none}.w2ui-list ul{list-style-type:none;background-color:#000;margin:0;padding:0}.w2ui-list ul li{float:left;margin:2px 1px 0 2px;border-radius:3px;width:auto;padding:3px 10px 1px 7px;border:1px solid #88b0d6;background-color:#eff3f5;white-space:nowrap;cursor:default;font-family:verdana;font-size:11px;line-height:100%;height:20px;overflow:hidden;text-overflow:ellipsis;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-list ul li:hover{background-color:#d0dbe1}.w2ui-list ul li:last-child{border-radius:0;border:1px solid transparent;background-color:transparent}.w2ui-list ul li:last-child input{padding:1px;padding-top:0;margin:0;border:0;outline:0;height:auto;line-height:100%;font-size:inherit;font-family:inherit;background-color:transparent}.w2ui-list ul li .w2ui-list-remove{float:right;width:15px;height:14px;margin:-1px -9px 0 3px;border-radius:15px}.w2ui-list ul li .w2ui-list-remove:hover{background-color:#D77F7F;color:#fff}.w2ui-list ul li .w2ui-list-remove:before{position:relative;top:0;padding:0;margin:0;left:5px;color:inherit;opacity:.7;text-shadow:inherit;font-size:inherit;font-variant:small-caps;content:'x';line-height:100%}.w2ui-list ul li>span.file-size{pointer-events:none;color:#777}.w2ui-list .w2ui-enum-placeholder{display:inline;position:absolute;pointer-events:none;color:#999;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-list.w2ui-file-dragover{background-color:#E4FFDA;border:1px solid #93E07D}.w2ui-layout{overflow:hidden!important;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-layout *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-layout>div{position:absolute;overflow:hidden;border:0;margin:0;padding:0;outline:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-layout>div .w2ui-panel{display:none;position:absolute;z-index:120}.w2ui-layout>div .w2ui-panel .w2ui-panel-title{padding:5px;background-image:-webkit-linear-gradient(#dae6f3,#c2d5ed);background-image:-moz-linear-gradient(#dae6f3,#c2d5ed);background-image:-ms-linear-gradient(#dae6f3,#c2d5ed);background-image:-o-linear-gradient(#dae6f3,#c2d5ed);background-image:linear-gradient(#dae6f3,#c2d5ed);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffdae6f3', endColorstr='#ffc2d5ed', GradientType=0);border:1px solid #b9cee9;border-bottom:1px solid #99bbe8}.w2ui-layout>div .w2ui-panel .w2ui-panel-tabs{position:absolute;left:0;top:0;right:0;z-index:2;display:none;overflow:hidden;background-color:#fafafa;padding:4px 0}.w2ui-layout>div .w2ui-panel .w2ui-panel-tabs>.w2ui-tab.active{background-color:#f5f6f7}.w2ui-layout>div .w2ui-panel .w2ui-panel-toolbar{position:absolute;left:0;top:0;right:0;z-index:2;display:none;overflow:hidden;background-color:#fafafa;border-bottom:1px solid silver;padding:4px}.w2ui-layout>div .w2ui-panel .w2ui-panel-content{position:absolute;left:0;top:0;right:0;bottom:0;z-index:1;color:inherit;background-color:#f5f6f7}.w2ui-layout>div .w2ui-resizer{display:none;position:absolute;z-index:121;background-color:transparent}.w2ui-layout>div .w2ui-resizer:hover,.w2ui-layout>div .w2ui-resizer.active{background-color:#d7e4f2}.w2ui-grid{position:relative;border:1px solid silver;border-radius:2px;overflow:hidden!important}.w2ui-grid>div{position:absolute;overflow:hidden}.w2ui-grid .w2ui-grid-header{position:absolute;border-bottom:1px solid #99bbe8!important;height:28px;overflow:hidden;color:#444;font-size:13px;text-align:center;padding:7px;background-image:-webkit-linear-gradient(#dae6f3,#c2d5ed);background-image:-moz-linear-gradient(#dae6f3,#c2d5ed);background-image:-ms-linear-gradient(#dae6f3,#c2d5ed);background-image:-o-linear-gradient(#dae6f3,#c2d5ed);background-image:linear-gradient(#dae6f3,#c2d5ed);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffdae6f3', endColorstr='#ffc2d5ed', GradientType=0);border-top-left-radius:2px;border-top-right-radius:2px}.w2ui-grid .w2ui-grid-toolbar{position:absolute;border-bottom:1px solid silver;background-color:#eaeaea;height:38px;padding:7px 3px 4px;margin:0;box-shadow:0 1px 2px #ddd}.w2ui-grid .w2ui-toolbar-search{width:160px;margin-right:3px}.w2ui-grid .w2ui-toolbar-search .w2ui-search-all{outline:0!important;width:160px;border-radius:10px;line-height:normal;height:22px;border:1px solid #b9b9b9;color:#000;background-color:#fff;padding:3px 18px 3px 23px;margin:0}.w2ui-grid .w2ui-toolbar-search .w2ui-search-down{position:absolute;margin-top:-7px;margin-left:6px}.w2ui-grid .w2ui-toolbar-search .w2ui-search-clear{position:absolute;width:16px;height:16px;margin-top:-8px;margin-left:-20px;border-radius:15px;cursor:default}.w2ui-grid .w2ui-toolbar-search .w2ui-search-clear:hover{background-color:#D77F7F;color:#fff}.w2ui-grid .w2ui-toolbar-search .w2ui-search-clear:before{position:relative;top:1px;left:5px;opacity:.6;color:inherit;text-shadow:inherit;content:'x';cursor:default}.w2ui-grid .w2ui-grid-body{position:absolute;overflow:hidden;padding:0;background-color:#fff;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.w2ui-grid .w2ui-grid-body input,.w2ui-grid .w2ui-grid-body select,.w2ui-grid .w2ui-grid-body textarea{user-select:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;-o-user-select:text}.w2ui-grid .w2ui-grid-body .w2ui-grid-columns{overflow:hidden;position:absolute;left:0;top:0;right:0;box-shadow:0 1px 4px #ddd;height:auto}.w2ui-grid .w2ui-grid-body .w2ui-grid-columns table{height:auto}.w2ui-grid .w2ui-grid-body .w2ui-grid-columns .w2ui-resizer{position:absolute;z-index:1000;display:block;background-image:none;background-color:rgba(0,0,0,0);padding:0;margin:0;width:6px;height:12px;cursor:col-resize}.w2ui-grid .w2ui-grid-body .w2ui-grid-records{position:absolute;left:0;right:0;top:0;bottom:0}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-odd{color:inherit;background-color:#fff}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-odd:hover{color:inherit;background-color:#e6f0ff}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-odd.w2ui-empty-record:hover{background-color:#fff}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-even{color:inherit;background-color:#f3f6fa}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-even:hover{color:inherit;background-color:#e6f0ff}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-even.w2ui-empty-record:hover{background-color:#f3f6fa}.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr.w2ui-selected,.w2ui-grid .w2ui-grid-body .w2ui-grid-records table tr td.w2ui-selected{color:#000!important;background-color:#b6d5ff!important}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-expanded{background-color:#CCDCF0!important}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-expanded1{height:0;border-bottom:1px solid #b2bac0;background-color:#CCDCF0}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-expanded1>div{height:100%;margin:0;padding:0}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-expanded2{height:0;border-radius:0;border-bottom:1px solid #b2bac0}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-expanded2>div{height:0;border:0;transition:height .3s,opacity .3s}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-load-more{border-top:1px solid #d6d5d7;cursor:pointer}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-load-more>div{text-align:center;color:#777;background-color:rgba(233,237,243,.5);padding:10px 0 15px;border-top:1px solid #fff}.w2ui-grid .w2ui-grid-body .w2ui-grid-records .w2ui-load-more>div:hover{color:inherit;background-color:#e6f0ff}.w2ui-grid .w2ui-grid-body table{border-spacing:0;border-collapse:collapse;table-layout:fixed;width:1px}.w2ui-grid .w2ui-grid-body table .w2ui-head{margin:0;padding:0;border-right:1px solid #c5c5c5;border-bottom:1px solid #c5c5c5;color:#000;background-image:-webkit-linear-gradient(#f9f9f9,#e4e4e4);background-image:-moz-linear-gradient(#f9f9f9,#e4e4e4);background-image:-ms-linear-gradient(#f9f9f9,#e4e4e4);background-image:-o-linear-gradient(#f9f9f9,#e4e4e4);background-image:linear-gradient(#f9f9f9,#e4e4e4);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#ffe4e4e4', GradientType=0)}.w2ui-grid .w2ui-grid-body table .w2ui-head>div{padding:7px 3px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;position:relative}.w2ui-grid .w2ui-grid-body table .w2ui-head.w2ui-col-intersection{border-right-color:#72b2ff}.w2ui-grid .w2ui-grid-body table .w2ui-head.w2ui-reorder-cols-head:hover{cursor:move}.w2ui-grid .w2ui-grid-body table .w2ui-head .col-intersection-marker{padding:0;position:absolute;height:100%;top:0}.w2ui-grid .w2ui-grid-body table .w2ui-head .col-intersection-marker.left{left:0;margin-left:-5px}.w2ui-grid .w2ui-grid-body table .w2ui-head .col-intersection-marker.right{right:0;margin-right:-5px}.w2ui-grid .w2ui-grid-body table .w2ui-head .col-intersection-marker .top-marker{position:absolute;top:0;height:0;width:0;border-top:5px solid #72b2ff;border-left:5px solid transparent;border-right:5px solid transparent}.w2ui-grid .w2ui-grid-body table .w2ui-head .col-intersection-marker .bottom-marker{position:absolute;bottom:0;height:0;width:0;border-bottom:5px solid #72b2ff;border-left:5px solid transparent;border-right:5px solid transparent}.w2ui-grid .w2ui-grid-body table td{border-right:1px solid #d6d5d7;border-bottom:0 solid #d6d5d7;cursor:default;overflow:hidden}.w2ui-grid .w2ui-grid-body table td.w2ui-grid-data{margin:0;padding:0}.w2ui-grid .w2ui-grid-body table td.w2ui-grid-data>div{padding:3px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.w2ui-grid .w2ui-grid-body table td.w2ui-grid-data>div.flexible-record{height:auto;overflow:visible;white-space:normal}.w2ui-grid .w2ui-grid-body table td:last-child{border-right:0}.w2ui-grid .w2ui-grid-body table .w2ui-col-number{width:34px;color:#777;background-color:rgba(233,237,243,.5)}.w2ui-grid .w2ui-grid-body table .w2ui-col-number div{padding:0 7px 0 3px;text-align:right}.w2ui-grid .w2ui-grid-body table .w2ui-col-select{width:26px}.w2ui-grid .w2ui-grid-body table .w2ui-col-select div{padding:0;text-align:center;overflow:hidden}.w2ui-grid .w2ui-grid-body table .w2ui-col-select div input[type=checkbox]{margin-top:2px;position:relative}.w2ui-grid .w2ui-grid-body table .w2ui-col-expand{width:26px}.w2ui-grid .w2ui-grid-body table .w2ui-col-expand div{padding:0;text-align:center;font-weight:700}.w2ui-grid .w2ui-grid-body div.w2ui-col-header{height:auto!important;width:100%;overflow:hidden;padding-right:10px!important}.w2ui-grid .w2ui-grid-body div.w2ui-col-header>div.w2ui-sort-up{border:4px solid transparent;border-bottom:5px solid #8D99A7;margin-top:-2px;margin-right:-7px;float:right}.w2ui-grid .w2ui-grid-body div.w2ui-col-header>div.w2ui-sort-down{border:4px solid transparent;border-top:5px solid #8D99A7;margin-top:2px;margin-right:-7px;float:right}.w2ui-grid .w2ui-grid-body .w2ui-col-group{text-align:center}.w2ui-grid .w2ui-changed{background:url(data:image/gif;base64,R0lGODlhCgAKAJEAALAABf///wAAAAAAACH5BAEAAAIALAAAAAAKAAoAAAIPlI8Hy8mbxIsSUnup3rQAADs=) no-repeat top right}.w2ui-grid .w2ui-editable{overflow:hidden;height:100%!important;margin:0!important;padding:0!important}.w2ui-grid .w2ui-editable input{border:0;border-radius:0;margin:0;padding:4px 3px;width:100%;height:100%}.w2ui-grid .w2ui-editable input.w2ui-select{outline:0!important;background:#fff}.w2ui-grid .w2ui-grid-summary{position:absolute;box-shadow:0 -1px 4px #aaa}.w2ui-grid .w2ui-grid-summary table{color:inherit}.w2ui-grid .w2ui-grid-summary table .w2ui-odd{background-color:#eef5eb}.w2ui-grid .w2ui-grid-summary table .w2ui-even{background-color:#f8fff5}.w2ui-grid .w2ui-grid-footer{position:absolute;margin:0;padding:0;text-align:center;height:24px;overflow:hidden;user-select:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;-o-user-select:text;box-shadow:0 -1px 4px #eee;color:#444;background-color:#f8f8f8;border-top:1px solid #ddd;border-bottom-left-radius:2px;border-bottom-right-radius:2px}.w2ui-grid .w2ui-grid-footer .w2ui-footer-left{float:left;padding-top:5px;padding-left:5px}.w2ui-grid .w2ui-grid-footer .w2ui-footer-right{float:right;padding-top:5px;padding-right:5px}.w2ui-grid .w2ui-grid-footer .w2ui-footer-center{padding:2px;text-align:center}.w2ui-grid .w2ui-grid-footer .w2ui-footer-center .w2ui-footer-nav{width:110px;margin:0 auto;padding:0;text-align:center}.w2ui-grid .w2ui-grid-footer .w2ui-footer-center .w2ui-footer-nav input[type=text]{padding:1px 2px 2px;border-radius:3px;width:40px;text-align:center}.w2ui-grid .w2ui-grid-footer .w2ui-footer-center .w2ui-footer-nav a.w2ui-footer-btn{display:inline-block;border-radius:3px;cursor:pointer;font-size:11px;line-height:16px;padding:1px 5px;width:30px;height:18px;margin-top:-1px;color:#000;background-color:transparent}.w2ui-grid .w2ui-grid-footer .w2ui-footer-center .w2ui-footer-nav a.w2ui-footer-btn:hover{color:#000;background-color:#aec8ff}.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr.w2ui-odd,.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr.w2ui-even,.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr.w2ui-odd:hover,.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr.w2ui-even:hover{background-color:inherit}.w2ui-ss .w2ui-grid-records table td{border-right-width:1px;border-bottom:1px solid #efefef}.w2ui-ss .w2ui-grid-records table tr:first-child td{border-bottom:0}.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr.w2ui-selected,.w2ui-ss .w2ui-grid-body .w2ui-grid-records table tr td.w2ui-selected{background-color:#EEF4FE!important}.w2ui-ss .w2ui-changed{background:inherit}.w2ui-ss .w2ui-grid-body .w2ui-selection{position:absolute;border:2px solid #6299DA;pointer-events:none}.w2ui-ss .w2ui-grid-body .w2ui-selection .w2ui-selection-resizer{cursor:crosshair;position:absolute;bottom:0;right:0;width:6px;height:6px;margin-right:-3px;margin-bottom:-3px;background-color:#457FC2;border:.5px solid #fff;outline:1px solid #fff;pointer-events:auto}.w2ui-overlay .w2ui-select-field{padding:8px 5px;cursor:default}.w2ui-overlay .w2ui-select-field table{font-size:11px;font-family:Verdana,Arial,sans-serif;border-spacing:0;border-collapse:border-collapse}.w2ui-overlay .w2ui-select-field table tr:hover{background-color:#b6d5ff}.w2ui-overlay .w2ui-select-field table td:nth-child(1){padding:3px 3px 3px 6px}.w2ui-overlay .w2ui-select-field table td:nth-child(1) input{margin:3px 2px 2px}.w2ui-overlay .w2ui-select-field table td:nth-child(2){padding:3px 15px 3px 3px}.w2ui-overlay .w2ui-col-on-off{padding:4px 0}.w2ui-overlay .w2ui-col-on-off table{border-spacing:0;border-collapse:border-collapse}.w2ui-overlay .w2ui-col-on-off table tr:hover{background-color:#b6d5ff}.w2ui-overlay .w2ui-col-on-off table td input[type=checkbox]{margin:3px 2px 2px}.w2ui-overlay .w2ui-col-on-off table td label{display:block;padding:3px 0;padding-right:10px}.w2ui-overlay .w2ui-col-on-off table td:first-child{padding:4px 0 4px 6px}.w2ui-overlay .w2ui-col-on-off table td:last-child{padding:4px 6px 4px 0}.w2ui-overlay .w2ui-grid-searches{text-align:left;padding:0;border-top:0;background-color:#f7f6f0}.w2ui-overlay .w2ui-grid-searches table{padding:4px;padding-top:12px;border-collapse:border-collapse}.w2ui-overlay .w2ui-grid-searches table td{padding:4px}.w2ui-overlay .w2ui-grid-searches table td.close-btn{width:20px;padding-right:20px}.w2ui-overlay .w2ui-grid-searches table td.close-btn button{min-width:24px;height:24px;padding-top:6px!important}.w2ui-overlay .w2ui-grid-searches table td.caption{text-align:right;padding-right:5px;border-right:1px solid #e8e8e3}.w2ui-overlay .w2ui-grid-searches table td.operator{text-align:left;padding:0 10px;padding-right:5px;border-right:1px solid #e8e8e3}.w2ui-overlay .w2ui-grid-searches table td.operator select{width:100%;color:#000;padding:0 15px 0 5px;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-image:-webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-ms-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:-o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-image:linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%)}.w2ui-overlay .w2ui-grid-searches table td.operator select::-ms-expand{display:none}.w2ui-overlay .w2ui-grid-searches table td.value{padding-right:5px;padding-left:5px}.w2ui-overlay .w2ui-grid-searches table td.value input[type=text]{border-radius:3px;padding:3px;margin-right:3px;height:23px}.w2ui-overlay .w2ui-grid-searches table td.value select{padding:3px;margin-right:3px;height:23px}.w2ui-overlay .w2ui-grid-searches table td.actions{border-right:0}.w2ui-overlay .w2ui-grid-searches table td.actions>div{margin:-7px;margin-top:15px;padding:13px 0;text-align:center;background-color:#efefe9;border-top:1px solid #e8e8e3}.w2ui-popup{position:fixed;z-index:1600;overflow:hidden;font-family:Verdana,Arial,sans-serif;border-radius:6px;padding:0;margin:0;border:1px solid #777;background-color:#eee;box-shadow:0 0 25px #555}.w2ui-popup,.w2ui-popup *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-popup .w2ui-msg-title{padding:6px;border-radius:6px 6px 0 0;background-image:-webkit-linear-gradient(#ececec,#dfdfdf);background-image:-moz-linear-gradient(#ececec,#dfdfdf);background-image:-ms-linear-gradient(#ececec,#dfdfdf);background-image:-o-linear-gradient(#ececec,#dfdfdf);background-image:linear-gradient(#ececec,#dfdfdf);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffececec', endColorstr='#ffdfdfdf', GradientType=0);border-bottom:2px solid #bfbfbf;position:absolute;overflow:hidden;height:32px;left:0;right:0;top:0;text-overflow:ellipsis;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;cursor:move;font-size:15px;color:#555;z-index:300}.w2ui-popup .w2ui-msg-button{float:right;width:18px;height:18px;cursor:pointer;overflow:hidden;padding:0;margin:0 3px 0 0;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAQCAYAAABQrvyxAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAj1JREFUeNrslr9rFFEQxz/zZi/qxSgW2lsqkiYoBku5Ro1o4UFKEYkgSaxSCLYqdv5IEVPYCMJJwERWrK0CKhoQ8hdobQTjXW7njcXlYnLunQQu0YDTLOy+Nzvfme98Z8Td2ckW2OGWdMvRvYfT/RGfBPoBBVpLK0AEPgVkdGL06vt/CoB5nBaRE8AXYKXNsQIwaB4fAwOtH+88mn4m7ifN4vUYebWBKkFKqjIV3N9NjI2Uuw5ARI45fBanH+F77iFnN8JHETmS68P9NHBQNTwHL8foaSN4SqoyA/SZyL4tqQAQBVYCLOFYlNxmq0WorVLpN9Oe5LKt1CsgRVWpAOfB66phBuhTkepSdfnKVjaxNJMSWn/iawmTtpeDp6pWBpaBoqrMqoYU6AOqIbFhxGa3R4V8nfNNKLUESzXJhoCvQC+wF/gW1C5IiC+2XUbD5jA3rd4C26NR3945IA2iRzqRJgdElJJlSQocAKrAD2A/6Ev3cLajjN59MDWHyKl2voOI1zKbv3Xj2lCHJFoz+LXuBoIAjnUklEvJrDDT5LwmdhG8blkyBxRjXSu4loE0X4VEznXKV3SnoOFMB7YUolBcbcKNdxuPXUBPu8pbLXsK0ghebVjEXgNoYmXLtGLuxd6ePU+AQ20AaIrb4DpFycmSv81/7YsiMgAstB1kQgE47O4LuQmCNwGOB7VxCb/URsRSTbhkmU4ifGiZHd1Z5m7fnxoIQSaBo39YJRZj9LGb4yPzXWm1/9voX7afAwAC5tacDTA2XgAAAABJRU5ErkJggg==) no-repeat center left;background-position:0 0;color:transparent!important;border-radius:3px;border:1px solid transparent}.w2ui-popup .w2ui-msg-close{margin-top:0;background-position:-32px 0}.w2ui-popup .w2ui-msg-close:hover{background-color:#ccc;border:1px solid #aaa}.w2ui-popup .w2ui-msg-max{background-position:-16px 0}.w2ui-popup .w2ui-msg-max:hover{background-color:#ccc;border:1px solid #aaa}.w2ui-popup .w2ui-box1,.w2ui-popup .w2ui-box2{position:absolute;left:0;right:0;top:32px;bottom:55px;z-index:100}.w2ui-popup .w2ui-msg-body{font-size:13px;line-height:130%;padding:0 7px 7px;color:#000;background-color:#eee;position:absolute;overflow:auto;width:100%;height:100%}.w2ui-popup .w2ui-popup-message{position:absolute;z-index:250;background-color:#f9f9f9;border:1px solid #999;box-shadow:0 0 15px #aaa;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;border-top:0;border-radius:0 0 6px 6px;overflow:auto}.w2ui-popup .w2ui-msg-buttons{padding:12px;border-radius:0 0 6px 6px;border-top:1px solid #d5d8d8;background-color:#f1f1f1;text-align:center;position:absolute;overflow:hidden;height:52px;left:0;right:0;bottom:0;z-index:200}.w2ui-popup .w2ui-msg-no-title{border-top-left-radius:6px;border-top-right-radius:6px;top:0!important}.w2ui-popup .w2ui-msg-no-buttons{border-bottom-left-radius:6px;border-bottom-right-radius:6px;bottom:0!important}.w2ui-sidebar{cursor:default;overflow:hidden!important;background-color:#edf1f6!important;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-sidebar *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-sidebar>div{position:relative;overflow:hidden}.w2ui-sidebar .w2ui-sidebar-top{position:absolute;z-index:2;top:0;left:0;right:0}.w2ui-sidebar .w2ui-sidebar-bottom{position:absolute;z-index:2;bottom:0;left:0;right:0}.w2ui-sidebar .w2ui-sidebar-div{position:absolute;z-index:1;overflow:auto;top:0;bottom:0;left:0;right:0;padding:2px 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.w2ui-sidebar .w2ui-sidebar-div table{width:100%}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node{background-color:#edf1f6;border-top:1px solid transparent;border-bottom:1px solid transparent;margin:0;padding:1px 0}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node table{pointer-events:none}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-caption,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image>span,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node td.w2ui-node-dots{color:#000;text-shadow:0 0 0 #fff;pointer-events:none}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-caption:hover,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image:hover,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image>span:hover,.w2ui-sidebar .w2ui-sidebar-div .w2ui-node td.w2ui-node-dots:hover{color:inherit}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node:hover{border-top:1px solid #f9f9f9;border-bottom:1px solid #f9f9f9;background-color:#d7e1ef}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image{width:22px;text-align:center;pointer-events:none}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node .w2ui-node-image>span{color:#516173!important}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node input{pointer-events:auto}.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected:hover{background-image:-webkit-linear-gradient(#69b1e0,#4a96d3);background-image:-moz-linear-gradient(#69b1e0,#4a96d3);background-image:-ms-linear-gradient(#69b1e0,#4a96d3);background-image:-o-linear-gradient(#69b1e0,#4a96d3);background-image:linear-gradient(#69b1e0,#4a96d3);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff69b1e0', endColorstr='#ff4a96d3', GradientType=0);border-top:1px solid #5295cd;border-bottom:1px solid #2661a6}.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected .w2ui-node-caption,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected:hover .w2ui-node-caption,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected .w2ui-node-image,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected:hover .w2ui-node-image,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected .w2ui-node-image>span,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected:hover .w2ui-node-image>span,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected td.w2ui-node-dots,.w2ui-sidebar .w2ui-sidebar-div .w2ui-selected:hover td.w2ui-node-dots{color:#fff!important;text-shadow:1px 1px 2px #666!important}.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled:hover{background:transparent!important;border-top:1px solid transparent;border-bottom:1px solid transparent}.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled .w2ui-node-caption,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled:hover .w2ui-node-caption,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled .w2ui-node-image,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled:hover .w2ui-node-image,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled .w2ui-node-image>span,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled:hover .w2ui-node-image>span,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled td.w2ui-node-dots,.w2ui-sidebar .w2ui-sidebar-div .w2ui-disabled:hover td.w2ui-node-dots{opacity:.4;filter:alpha(opacity=40);color:#000!important;text-shadow:0 0 0 #fff!important}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node-caption{white-space:nowrap;padding:5px 0 5px 3px;margin:1px 0 1px 22px;position:relative;z-index:1;font-size:12px}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node-group{white-space:nowrap;overflow:hidden;padding:10px 0 10px 10px;margin:0;cursor:default;color:#868b92;background-color:transparent}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node-group :nth-child(1){margin-right:10px;float:right;color:transparent}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node-group :nth-child(2){font-weight:400;text-transform:uppercase}.w2ui-sidebar .w2ui-sidebar-div .w2ui-node-sub{overflow:hidden}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-dots{width:18px;padding:0 0 1px 7px;text-align:center}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-dots .w2ui-expand{width:16px;margin-top:-3px;pointer-events:auto}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-data{padding:1px 1px 3px}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-data .w2ui-node-image{padding:3px 0 0;float:left}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-data .w2ui-node-image>span{font-size:16px;color:#000;text-shadow:0 0 0 #fff}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-data .w2ui-node-image.w2ui-icon{margin-top:3px}.w2ui-sidebar .w2ui-sidebar-div td.w2ui-node-data .w2ui-node-count{float:right;border:1px solid #9da4af;border-radius:20px;width:auto;height:18px;padding:2px 7px;margin:3px 4px -2px 0;background-color:#e7f0fc;color:#667274;box-shadow:0 0 2px #fff;text-shadow:1px 1px 1px #e6e6e6;position:relative;z-index:2}.w2ui-tabs{cursor:default;overflow:hidden!important;background-color:#fafafa;padding:3px 0;padding-bottom:0!important}.w2ui-tabs table{border-bottom:1px solid silver;padding:0 7px}.w2ui-tabs .w2ui-tab{padding:6px 20px;text-align:center;color:#000;background-color:transparent;border:1px solid silver;border-bottom:1px solid silver;white-space:nowrap;margin:1px 1px -1px 0;border-top-left-radius:4px;border-top-right-radius:4px;cursor:default}.w2ui-tabs .w2ui-tab.active{color:#000;background-color:#fff;border:1px solid silver;border-bottom:1px solid transparent}.w2ui-tabs .w2ui-tab.closable{padding:6px 28px 6px 20px}.w2ui-tabs .w2ui-tab-close{color:#555;text-shadow:1px 1px 1px #bbb;float:right;margin:6px 4px 0 0;padding:0 0 0 5px;width:16px;height:16px;opacity:.9;border:0;border-top:3px solid transparent;border-radius:9px}.w2ui-tabs .w2ui-tab-close:hover{background-color:#D77F7F;color:#fff}.w2ui-tabs .w2ui-tab-close:before{position:relative;top:-2px;left:0;opacity:.6;color:inherit;text-shadow:inherit;content:'x'}.w2ui-toolbar{margin:0;padding:2px;outline:0;background-color:#efefef;overflow:hidden!important;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.w2ui-toolbar .disabled{opacity:.3;filter:alpha(opacity=30)}.w2ui-toolbar table{table-layout:auto!important}.w2ui-toolbar table td{border:0!important}.w2ui-toolbar table.w2ui-button{margin:0 1px;border-radius:4px;height:24px;border:1px solid transparent;background-color:transparent}.w2ui-toolbar table.w2ui-button .w2ui-tb-image{width:16px;height:16px;padding:0;margin:2px 4px 3px 3px!important;border:0!important;text-align:center}.w2ui-toolbar table.w2ui-button .w2ui-tb-image>span{font-size:15px;margin-top:3px;display:block;color:#8d99a7}.w2ui-toolbar table.w2ui-button .w2ui-tb-caption{color:#000;padding:0 4px 0 2px}.w2ui-toolbar table.w2ui-button .w2ui-tb-count{padding:0 4px 0 0}.w2ui-toolbar table.w2ui-button .w2ui-tb-count>span{border:1px solid #9da4af;border-radius:20px;width:auto;height:18px;padding:2px 7px;background-color:#e7f0fc;color:#667274;box-shadow:0 0 2px #fff;text-shadow:1px 1px 1px #e6e6e6}.w2ui-toolbar table.w2ui-button .w2ui-tb-down{padding:3px}.w2ui-toolbar table.w2ui-button .w2ui-tb-down>div{border:4px solid transparent;border-top:5px solid #8D99A7;margin-top:5px}.w2ui-toolbar table.w2ui-button.over{border:1px solid #ccc;background-color:#eee}.w2ui-toolbar table.w2ui-button.over .w2ui-tb-caption{color:#000}.w2ui-toolbar table.w2ui-button.down{border:1px solid #aaa;background-color:#ddd}.w2ui-toolbar table.w2ui-button.down .w2ui-tb-caption{color:#666}.w2ui-toolbar table.w2ui-button.checked{border:1px solid #aaa;background-color:#fff}.w2ui-toolbar table.w2ui-button.checked .w2ui-tb-caption{color:#000}.w2ui-toolbar table.w2ui-button table{height:17px;border-radius:4px;cursor:default}.w2ui-toolbar .w2ui-break{background-image:-webkit-linear-gradient(top,rgba(153,153,153,.1) 0,#999 40%,#999 60%,rgba(153,153,153,.1) 100%);background-image:-moz-linear-gradient(top,rgba(153,153,153,.1) 0,#999 40%,#999 60%,rgba(153,153,153,.1) 100%);background-image:-ms-linear-gradient(top,rgba(153,153,153,.1) 0,#999 40%,#999 60%,rgba(153,153,153,.1) 100%);background-image:-o-linear-gradient(top,rgba(153,153,153,.1) 0,#999 40%,#999 60%,rgba(153,153,153,.1) 100%);background-image:linear-gradient(top,rgba(153,153,153,.1) 0,#999 40%,#999 60%,rgba(153,153,153,.1) 100%);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff999999', endColorstr='#ff999999', GradientType=0);width:1px!important;height:22px;padding:0;margin:0 6px}.w2ui-listview{overflow:auto!important;background-color:#fff!important;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-listview *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.w2ui-listview>ul{list-style-type:none;margin:0;cursor:default}.w2ui-listview>ul>li{display:inline-block;vertical-align:top;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;border:1px solid transparent;border-radius:4px}.w2ui-listview>ul>li.w2ui-focused{border:1px solid #2661a6}.w2ui-listview>ul>li.w2ui-selected{border:1px solid #2661a6}.w2ui-listview>ul>li.w2ui-selected,.w2ui-listview>ul>li.w2ui-selected.hover{background-image:-webkit-linear-gradient(#69b1e0,#4a96d3);background-image:-moz-linear-gradient(#69b1e0,#4a96d3);background-image:-ms-linear-gradient(#69b1e0,#4a96d3);background-image:-o-linear-gradient(#69b1e0,#4a96d3);background-image:linear-gradient(#69b1e0,#4a96d3);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff69b1e0', endColorstr='#ff4a96d3', GradientType=0)}.w2ui-listview>ul>li.w2ui-selected>div>div.caption,.w2ui-listview>ul>li.w2ui-selected.hover>div>div.caption{color:#fff}.w2ui-listview>ul>li.w2ui-selected>div>div.description,.w2ui-listview>ul>li.w2ui-selected.hover>div>div.description{color:#ddd}.w2ui-listview>ul>li.w2ui-selected>div>div.extra>div>div,.w2ui-listview>ul>li.w2ui-selected.hover>div>div.extra>div>div{color:#ddd}.w2ui-listview>ul>li.hover{background-color:#d7e1ef;border:1px solid #2661a6}.w2ui-listview>ul>li div{vertical-align:middle}.w2ui-listview>ul>li>div>div.caption{display:block;text-align:center;word-wrap:break-word;max-height:50px;color:#000;font-size:12px}.w2ui-listview>ul>li>div>div.description{display:none;text-align:left;color:#777;font-size:12px}.w2ui-listview>ul>li>div>div.extra{display:none}.w2ui-listview>ul>li>div>div.extra>div>div{color:#777}.w2ui-icon-small>ul{padding:1px 0 0 1px}.w2ui-icon-small>ul>li{margin:0 1px 1px 0;padding:2px;width:250px;white-space:nowrap}.w2ui-icon-small>ul>li>div>div.w2ui-listview-img{display:inline-block;width:26px;height:22px;font-size:21px;margin-right:2px}.w2ui-icon-small>ul>li>div>div.caption{display:inline-block}.w2ui-icon-medium>ul{padding:4px 0 0 4px}.w2ui-icon-medium>ul>li{margin:0 4px 4px 0;padding:4px;width:100px}.w2ui-icon-medium>ul>li>div>div.w2ui-listview-img{display:block;width:92px;height:60px;font-size:57px;margin-left:auto;margin-right:auto;background-position:center}.w2ui-icon-large>ul{padding:4px 0 0 4px}.w2ui-icon-large>ul>li{margin:0 4px 4px 0;padding:4px;width:160px}.w2ui-icon-large>ul>li>div>div.w2ui-listview-img{display:block;width:152px;height:120px;font-size:114px;margin-left:auto;margin-right:auto;background-position:center}.w2ui-icon-tile>ul{padding:1px 0 0 1px}.w2ui-icon-tile>ul>li{margin:0 1px 1px 0;padding:4px;width:250px;white-space:nowrap}.w2ui-icon-tile>ul>li>div>div.w2ui-listview-img{display:inline-block;width:72px;height:60px;font-size:57px;float:left;margin-right:4px}.w2ui-icon-tile>ul>li>div>div.caption{text-align:left}.w2ui-icon-tile>ul>li>div>div.description{display:block}.w2ui-table>ul{padding:0}.w2ui-table>ul>li{width:100%;padding:2px;border-radius:0;border-bottom:1px dotted #d3d3d3}.w2ui-table>ul>li>div{display:inline-block;position:relative;width:100%;white-space:nowrap;overflow:hidden}.w2ui-table>ul>li>div>div.w2ui-listview-img{display:inline-block;width:38px;height:32px;font-size:31px;margin-right:2px}.w2ui-table>ul>li>div>div.caption{display:inline-block}.w2ui-table>ul>li>div>div.extra{display:inline-block;position:absolute;right:0;height:100%;background-color:#fff}.w2ui-table>ul>li>div>div.extra>div:before{display:inline-block;height:100%;width:0;content:'';vertical-align:middle}.w2ui-table>ul>li>div>div.extra>div{display:inline}.w2ui-table>ul>li>div>div.extra>div>div{display:inline-block;font-size:12px}.w2ui-table>ul>li.w2ui-selected div.extra,.w2ui-table>ul>li.w2ui-selected.hover div.extra{background-image:-webkit-linear-gradient(#69b1e0,#4a96d3);background-image:-moz-linear-gradient(#69b1e0,#4a96d3);background-image:-ms-linear-gradient(#69b1e0,#4a96d3);background-image:-o-linear-gradient(#69b1e0,#4a96d3);background-image:linear-gradient(#69b1e0,#4a96d3);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff69b1e0', endColorstr='#ff4a96d3', GradientType=0)}.w2ui-table>ul>li.hover div.extra{background-color:#d7e1ef}.w2ui-listview>ul>li div.icon-none{border:1px solid rgba(102,102,102,.35)} .olexp-explorer-content,.olexp-explorer-map{height:100%;width:100%}.olexp-control-layer-manager-down{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAUVBMVEX///+9vQC9vQCWlpbm5ubb26fExCW+vgDIyCbS01HBwQ3U1VzX2Gbw8KC/vwbExBLAwAbAwAfj43bk5HrBwQjBwQfj43XAwAji4nTZ2VX///9Z+37dAAAAA3RSTlMA1kayq0LiAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAHNJREFUKM/F0ckOgCAMRVHA4SlSFRWH//9RKZogrNwY77InTSAV4t+KrAhl0gdQfARVjSupUqibVvuxbhuZAjoDIoLpkIG5wbyFHhg8DMCYbdiJuHkJGzHArTzfwPDIP9XtNFswPK8j/cQePJfpMVWQ8PMTKmUIMs6ZAJ8AAAAYdEVYdEF1dGhvcgBSb2JlcnQgU3pjemVwYW5la19WsQgAAABSdEVYdENvcHlyaWdodABDQyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzMuMC9eg1q8AAAAGHRFWHRDcmVhdGlvbiBUaW1lADIwMDgtMTItMTJYLju/AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjQyOjQ0LTA0OjAwt/PTXAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNi0wNDowMO1wzfYAAAAndEVYdERlc2NyaXB0aW9uAGh0dHA6Ly9yb2JlcnQuc3pjemVwYW5lay5wbJBZSGAAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC)}.olexp-control-layer-control-add-vector{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA+VBMVEX///9HZntLaH1La4BKaHxLaH1LaH1KZ3tFZHhLaH1AWHA9Wm46WmtEYndKZ3w8Wm08WW4+W2w8Wm5AYHBajFpZjFnA3vJJZns8Wm6WlpaUlJVJYnN9hYtWa3pue4Tm5ua1vsNUbn/i4+S6wsdRbH3i4uNwhZOVo63l5eVedoaqtbzR1NdJZXfT1tmrtbxddYWToqtziJVSbH66wcZUbX64wMabqbFtgpFWb4DY2txLZnnIzdBie4xNan5qgZFeeIped4qrt79dd4nF0cV4n3hajFpynXOBqIKFq4bO2s/M2M2IrImKrovs7e3N2c7P2tC8y7y5ybn///9EpCZXAAAAFnRSTlMAieVi5t3c9K7gIOwfw+98ri3qEMk8P+Ru4wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAADpSURBVCjPbdLrTsIwAIbhwhBEBVHHoCp+gKIoKKjgCVGRjU3pFO7/ZuwBKHZ7f7RpnzRplxFCEkmLxJZyNvTCSluLgU+ZTQ1Zp1Qul5y0XGxt76wgl9cnCNktLPf39g/0aUoPj46pqnJCqQagWqtDdHrWwD/A+YXYb15ewYBW+5qPN52mCejeAvW7e2igChq9Ph4eEQVUn55fBnGA1+EbYuHd+YiH0ecIGLuezC5qkLkTP/j6DvyJbYA3ZSwMGZt6JjAFLAI/oew3AjM1zyWsJW7EmUf0NxOtg2oBNt+az8RDjD+maC8f+AeaIjk7ipjOKAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNVQxMToyNTozNC0wNDowMNic0/sAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MjctMDQ6MDCHrcbcAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg==)}.olexp-control-graticule{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABZVBMVEW01e9bhb+DqdR6otB+pNLI5vqJr9iFq9VHdLR8o9HE4/jA3/ZslMhIdbWSt93H5flmkMWoyei+3fROerhUgLt0m8xoksaCqNSDqtXF4/hPe7irzOqGrNZahb5hi8KfwuRdh8DG5PmszetymstNebdnkMV0nMxLd7ZVgbxYg72myOeAptOOs9u42PGnyeiavuGNstqFq9aLsNlul8ldiMCx0e1RfLm21vC72/NTfrrH5vp9pNGZveF1nM1zmstQfbmGq9bB4PZ3ns6Xu+CDqNRIdbS62vN5oM9Sfbp4n86gwuRUf7u62fLD4ve52fKRtdxjjcSMsdqaveG11fDC4fdpkseQtNx6odCbv+KBp9RrlMdtlsmhw+XF5Pmpy+lkjsSHrNeHrddokcaQtdxkjcSqy+pJdbWHrNauz+yszutLeLZeiMBljsSDqdVeicFMeLdZhL6Msdmz1O9VgLuWut/G5fn///9aqb94AAAAAWJLR0R2MWPJQQAAAAlwSFlzAAAN1wAADdcBQiibeAAAAXRJREFUKM9l0Pk3AlEUB/BXfBmFGpMiRkUNaUGLtrFUKFtpsaRV2ZdK8v97M4j45Z773ueee8+9hCiUA4PA0DDAAMNDwOCISqkgBOrRsXENtKwMrBaY4HSTahBAb9ArprhpGaaNM7MKfg6gYDJbML9g1dkExiDYFpeU8xaziYLKvkzd4XS5V5jVFfeag76W7SoQj5dm8Pkht4LfJz29HpD1AE2CofAXhENBGgPrQRKRKsQNfAE2RCkqN8nWdhSIxXsQj9EQ3dkle4nk/sHhUQ+OdMcH+8mEk+6RSp+MeTNZNsfkc2w2Y7WeplMIE6nq7PyiINh4xsrbhMKlR/qCDMUSeq1QKvagbIz+gqix/A2VKn4BqpVvqF31wVVNhnrDdX3TBzfXcDXqpJRI3t7dq39A/fD4FEqUaCvT80uTa7U/z95ucc32q0aeEWnQOrqbdHY2lwcakc/hfAd9M9DhZUi94Q/gLSVBN/YPYl0K74L4D0QB7x8Kmj3ZLAlwHgAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0xMC0yMoA45boAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjVUMTE6NTE6MTEtMDQ6MDDoUU7YAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI2LTA0OjAwIdrNaAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAPdEVYdFRpdGxlAGdyYXRpY3VsZZJv4HwAAAAASUVORK5CYII=)}.olexp-control-export-map{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAwFBMVEX///+ZmZmcnJyampqYmJiZmZmbm5u3t7eqqqqampqXl5eYmJiZmZk8W246W22ZmZmVlZWcnJyAgICbm5vT09Pg4ODm5ubf39+WlpbR0dHX19fZ2dm3wMVXcYE8Wm5RbX5pgZBthZRxiJZ0i5lwh5XY2911i5mClqLU2Nrb3d6PoKuvr6+ioqK/v7/j5OSpqam7u7ulpaVke4rW2Nqzs7PIyMjHx8esrKzL0NNQany3t7fJycnOzs7R1ddKZHT///8tFxR7AAAAFHRSTlMAI7TffAqt/veV+/no1kbmWfgCvQR3K/YAAAABYktHRACIBR1IAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAqklEQVQoz9XRWQ6CMBCA4borWkXFEReGRSiCO66oeP9jWWIEa+oB/J+afpmkzRDyq0KxVK7IoFrT6g0ZKAMYNmWgA4Au1sphpI0nkKX/PUwNfEXbIhimZTszx7ZMKgK6HniM+czFL2DA5swPQiYBXhiEHBbLlTiRHtYcNttdDgjpm6J9hKRzOJ7On3DBmN8jUbvX2z2HBBLEmE+RntpXst098B0V99ym2c+fRzQtIQC3ZTAAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjVUMTE6NTI6MDMtMDQ6MDBYU+RsAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI5LTA0OjAw15K9gQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII=)}.olexp-control-measure-length{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYBAMAAAASWSDLAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAGFBMVEX///9VV1NSU1HT18+Rk488Wm5QUFD////r4EM9AAAABXRSTlMA/f79/vIq1voAAAABYktHRACIBR1IAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAQklEQVQY02NgoBiwwhgBGJxQKMDkICsjAzAKKgpBkQADo3GyGRRhcJxNjJNNQCSIAwTJIALGcUbmGMM4gnAggNsBAKVhFsLRWT/tAAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDA4LTEyLTEyWC47vwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNVQxMTo1MToxMS0wNDowMOhRTtgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzYtMDQ6MDDtcM32AAAAJ3RFWHREZXNjcmlwdGlvbgBodHRwOi8vcm9iZXJ0LnN6Y3plcGFuZWsucGyQWUhgAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg==)}.olexp-control-edit-settings{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAB/lBMVEX////IpgvFogLEogDDnwDIpgvHnwDGowjJpw7GowbGowTIpgfGowPkzmHNrRrGpAjHpgnGogTNqwzixiDGowLNrRvEoQPEoQLNqwnixhvIpQPNqgbGowDNqgXGogDSshDGowLSsQ3EoQHHpAHHowDDnwC/nwDSsQrFoQDGowHSsQzRrwbIpgjHpQfHpQXSsQnQrwXEoQDGogDGogLNqwfJpwHGowLNqgfIpgHGoQDIpgTGowDixRXMqQPWtwLFogDGowHixBDLqAPGogHGogHHpAHy44r88qrz5Y7+9a/676P34jr365r+9KT25nT34Tn75jn75TX88qj47Jz98pn87nj86lb13zn54zn75jf75TP75C/33yj98Y787Wz76Ev75z775jr75Tb75TL75C733yf974P862L03jn03Tb75TH75Cz54Cbz3kjy2Sf75Cv74yf13B/74yb74yL64R3v1RXozQ/kyQvfwwb750H02hz54Bz02xbv1hHq0QvlzAbiyQT750D75jv03TDx1hfy2RTt1A/ozwnjygTx4HDx31jx2j313zfw1xPr0g3mzQjfxQTdwgPcwQP13i/y2CLozQ7gxgT54S374yP74h/s0hLiyAT33yv75Cr13BjhxwT33yn74yj74yT74iD33Rvv1RTz2hjkyQjy2Bb///9QqXrkAAAARnRSTlMAtfseVd8g6feKivfp/POH34fz/Onz/Pzz/PfzivOH8/Pz/N+1gAjz+/Pz87Xf3/Pz/N+H8/OK8/OK9/f88/zp6fzz3+n3Dl9naQAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAAGOSURBVCjPY2AgCBiZgIARTZCZhYGB1c3d3Y2VgYGFGSHOxs7BycDq4enpwcrAxc3DhhDn9eLjB0sICAp5C4tAZZjZeT09vUTFfDx9/cQl/AMCJUUgprFweHl6egYFe4aEhoVHREZFx0ixQLRw8oFkPGPj4hMSk5JTUqVlYJbwiwZ5+qalZ2QGBGZl58jKQd3PysoqFhwSmiuvoKCYl19QqKSsrKwClGBy8/DwARojr6qmpqpeVFxSWlZeoQGScAcZU5mpoMbAoKZZVV1TW1ffAJEAuqaxqRki0dLa1t7RAZHo7OruAbpGC2SUdm9f/4SJEyeBJHR09fSUJmdlT9HX1DSYWlc/zdDIyEgF4jBjk+n5BTNmtswCGTPbVA7mDTPzOXOBrpkHNKYDCOZbWELEWawWLFy0eMlSoGs6ps0GyVhDgoRZxGbGzGW2hss7OiYYms7v6LCzh0YJm4PjCic554kdHRON5Czm29kjIsTF1ZLBCCzBYGmNEIdErdGkhoZJRqhRCwYqGkCgQjjRAAC4W228IT8VJAAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0wNC0wM3cLCUkAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjVUMTE6NTI6MDMtMDQ6MDBYU+RsAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjM1LTA0OjAw3JjXawAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAOdEVYdFRpdGxlAHNldHRpbmdzRrN3QwAAAABJRU5ErkJggg==)}.olexp-control-measure-area{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYBAMAAAASWSDLAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAG1BMVEX///9VV1NSU1HT18+Rk488Wm6CoLRQUFD///+VUipIAAAABXRSTlMA/f79/vIq1voAAAABYktHRACIBR1IAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAWklEQVQY02NgQAGsoaEBCE5aGgonFAIgHAhIJcgBakBwAkAkJicUZCuUA3dHKAMewCioKARFAgyMxsXmUITBcTYxLjYBkSAOEBSDCBjHGZljDOMIwoEAbgcAAFUrLNBnsGw7AAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDA4LTEyLTEyWC47vwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNVQxMTo1MToxMS0wNDowMOhRTtgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzUtMDQ6MDDcmNdrAAAAJ3RFWHREZXNjcmlwdGlvbgBodHRwOi8vcm9iZXJ0LnN6Y3plcGFuZWsucGyQWUhgAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg==)}.olexp-control-layer-control-add-tile{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAARVBMVEX///9ajFpZjFk8Wm6CoLSWlpbm5ubF0cV4n3hajFpumm6AqIGEqoXO2s/M2M2GrIeKrovs7e3N2c7P2tC8y7y5ybn///8H9fLcAAAAA3RSTlMAyTzPIdReAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAHRJREFUKM+t0ksOgCAMQEGqoqIoxc/9r2pbwCiYuOFtmnQ2EFDqr5bqKJ71QUtpyTNBz1WENtbrtK4Pd98wjEaCJoNxmu2y2nmCDIxD9B7RmRwwABaweWkv4AjzFHjEJyKmlH491xNCEYBW58EXyf5KA+mCF5KaCagHkknTAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI1VDExOjI1OjM0LTA0OjAw2JzT+wAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNS0wNDowMNyY12sAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC)}.olexp-control-toolbar-hide{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABWVBMVEX///8AAAArK0ArNTUwNzcuMzgtNTUwNDQoNjY3Nzc6QkJHTU5UWVpna212eXqBhIaPkpKcnp+Tl5hxdHZhZmdXXV5NU1VITU9ATU0AAABCRklaX2DDxcXl5eW9v79rb3FOUlQ/RkbHx8esr6/j4+OXmpro6Ojm5ubl5eXm5ubm5ubp6enp6enm5ubLy8tVWlxVampNUlRWW1tjZ2h5fX6oqqplamtTV1gxMTFTWVp+goPIyci0trWDiIjX19eChIaNkJBcYGEgQEAnOztITU1ydXeipKRlaWu2uLjY2tqQk5V3enuIjIy+wb5fZGUzMzNeYmPHyMePkpJxdXVucnJ4fX58f4B1eXpzdnaFiInHycetr69ZXV8uLi5VVVVXWlx3enq/wcGoqqpnbGxOVFRMTlFgZWZucnJ2ent1eXlnbG1YXF5ARUXu7uzd3dzh4uDt7evp6uj////Z6plGAAAAbXRSTlMAAQwYJTI/OxMObZakqammpJ2arbKonHgUAm2njICQtaRFMpaBnSFwbWhlOS8KitUMbaDOwp/qmRXB3v3yrYW97scIDWrX672ChK/X5P3MD8H85ca+rr/Lz+P88KoLA43V+u/GWFu0wcvNuaA0nka8DgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAAC0SURBVCjPY2CgOmBkYmZhZWPnQBXl5OLm4eXjFxAUEhYRFROXgApLSknLyCIBOXkFRbCEkrIsGlBRVQNJqMtiAg2QhCYWCS2QhDYWCR2QhC6GWXr6BkA3GRoZm6CKm5qZA9VbWFpZ29giCdvZOzg6gZ3r7OLq5u4BEfX08vbx9fOH+dwiIDAoOCQ0LDwiMio3OiYWESZx8QmJuXn5BbmFSckpqMEVl5qWnpGZlZ1D/fihCwAAE8IpsYDcOLEAAAAYdEVYdEF1dGhvcgBSb2JlcnQgU3pjemVwYW5la19WsQgAAABSdEVYdENvcHlyaWdodABDQyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzMuMC9eg1q8AAAAGHRFWHRDcmVhdGlvbiBUaW1lADIwMDgtMTItMTJYLju/AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDE2OjIzOjQ0LTA0OjAwDFw9bAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzoyNi0wNDowMCHazWgAAAAndEVYdERlc2NyaXB0aW9uAGh0dHA6Ly9yb2JlcnQuc3pjemVwYW5lay5wbJBZSGAAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC)}.olexp-control-layer-manager-navigation{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYBAMAAAASWSDLAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAMFBMVEX///9BX3JBX3JCX3I8Wm7I5vqmxdhEY3dAXnNph5tlhJhFYnfm5uZXcIGst77///+b4/bXAAAABHRSTlMA6P3oG6ESOAAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAABMSURBVBjTY2DADURcoMARyHENhYIQIMetxCN1ClDCC8xp8U5dAuR4hqArU4EZ4ATk+JyBgiMgzhXfM0+AEn5HMGQGXJkJzNXOeMIGALCya915oHCyAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDE3OjUwOjI1LTA0OjAwc95IWgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNC0wNDowMHrv3N8AAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC)}.olexp-control-layer-manager-up{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAb1BMVEX///+9vQC9vQCWlpbm5ubb26fExCW+vgDIyCbS01HT1FjQ0UvDwxTPz0XU1VzX2GbS01DCwg3a2lrBwQzR0UvR0k/j43jw8KDl5X3Q0UzCwgzk5Hnl5XzR0k3k5Hrk5Hu/vwbDww/AwAa/vwX///86q3s0AAAAA3RSTlMA1kayq0LiAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAH5JREFUKM/F0dsOgjAMgOGVCQUE5pxQ5Xx4/3d0i4nQ3hP+myX9brpUqWvToh1urBNAnwRxgr8g4pCkWX4vyjxLgQNW5mGf7mUqFGBq19DbfYyEuu2IqHeDBDtSaLICZsTFzxfENcBe2NRDeJQ+nobB8TrwB+DHjAA3P938z78plwn5biz3jQAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAwOC0xMi0xMlguO78AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjI6NDI6NDQtMDQ6MDC389NcAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI4LTA0OjAwceW2NQAAACd0RVh0RGVzY3JpcHRpb24AaHR0cDovL3JvYmVydC5zemN6ZXBhbmVrLnBskFlIYAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII=)}.olexp-control-layer-manager-details{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAyVBMVEX///87Wm47Wm08Wm6ElqJfeIhPa308WW5AQIDCyc56j51ed4icqrR2i5k8Wm6grrdddoc8Wm67w8hfeIhOanw8Wm6qtbw8WW6yu8GUo6x6jZqVo62Wlpbu7uzO09WElqFheohGYHLs7OqYpq9ieoprgpGTpK29xcluhJKClqLY293m5uZTbX5+kp+yvMLb3d5OaXtpgY+OoKqisLivusBNaXpcd4bAx8xQanxVcIDHzNCtt720vcNqeYNIYnNFYHKUoqvj5OT////5SfIOAAAAHHRSTlMAyZgu7+nhfAT57uPz7d706uX46ujm9uL38u7z87N4ewAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAACtSURBVCjPzdHZDoIwEEBRCipYta4VBQQUt1rcHfcF/v+nJJAA5d3E+3rSTKeVpD/NKpTBSOgHYAlgO+4YyUoRJt50Nl+UyhVVE8FbMrbiVYxrqgC2v2Zss61j3CBKHpzdnh2OpybGrbacBxfgfOG80+1RivJwBYDbnfdplF44AfBIAIkzUhBn2H4ETz6IILlV2uv9CUIeDimJ98jSVGKYpmmQeHPhdxQZ6clbfQFNzCgU6GJ0sAAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0xMC0yMoA45boAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjI6MzE6MTctMDQ6MDAM92klAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI3LTA0OjAwh63G3AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAQdEVYdFRpdGxlAGxheWVyIGluZm8RUEZfAAAAAElFTkSuQmCC)}.olexp-control-layer-menu{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAY1BMVEX///88W246W20+XXCWlpbm5ua3wMVXcYE8Wm5RbX5pgZBthZRxiJZ0i5lwh5V1i5k/XXDCyc6RoKrf4eKJm6e2vsTl5eV6jZrf4eFacoPe4OF1iZZDYHOwusDc3t/N0dT////L7exBAAAABHRSTlMA1kbW8wSwegAAAAFiS0dEAIgFHUgAAAAJcEhZcwAADdcAAA3XAUIom3gAAABtSURBVCjPxdHHDoAgEEVR2igKNuzY/v8vjYjRIXFpvMt3Mqsh5N9E0A2A+gDERxDF8owyDHGSKp1plSYUg8wLXxnAtVfmBeoXaCAEX9s5uPN7P7iLR24e2wHsRNB3qJyXFTqwG8fPZLQ0RxNnO72DCnTXfN++AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI1VDExOjIyOjU1LTA0OjAwWljKsQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNy0wNDowMEsHxkIAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC)}.olexp-item-image{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABO1BMVEUAAAA8Wm47WW2cnJxqiJy8vLyEorbBwcGCoLSWlpY8Wm48Wm5DYXV7ma2EorZqiJw7WW08Wm48Wm48Wm48Wm47WW07WW2YmJigoKCioqJ4jp1qiJygoKCEoraHorWCoLSCoLSUlJShoaGxtLaCkpx/ormVlZWioqK3traCgoK2trW1tbWWlpabm5uysrK2tra1tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpY8Wm5DYXV7ma2EorZqiJw7WW1CYHR8mq6Fo7dph5xohppWdIhUcoZceo7V1dXd3d3e3d2jtsOCobV9m69BX3M4Vmrn5+ehtMF5mKx2lKg6WGxYdYjm5ubo5+d7j5w/XXI9W284V2t1iZd0iJY0U2g4Vmt2iZeeqrN3i5ieq7P///+3Ru7wAAAAPnRSTlMAAAAAAAAAAAAAQGRiYmJiYmMiplmmWWyqpuBZpln97FA0pekuB5ul5xjn55uR5uHj6NEWwGlzdFMXAmNlQRdviEwAAAABYktHRGjLbPQiAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAwElEQVQY02NgAAJGLm4eXj5+AUEhRgYwYBS2s3dwdHK2E4EKMIk6u7i6OTk7izExMDCLS0hKSrl7eHp5OzlJszAwsMr4+Pr5BwQGBXs5OsqyMTCwS/qGhISGhbtERMrJK3AwMCgq+UZFx8S6xMUnKKuoAgXU1IECiUnJ8UkpGpqcDBCBkNTEtLTEdC24QFRINBCEaCMEIAC3QAiED9Wio6unb6ANAoZGxiABE1MzcwtLTRAwtgIJWFtb29hyMsABAOfZLuUNID9SAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjQyOjEzLTA0OjAwOrTjtgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNy0wNDowMEsHxkIAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC)}.olexp-item-group{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAZlBMVEX///8gSocgSocgSocgSocgSocgSocgSocgSoeIioV+hIUpUIfu7uzh5OYsVI2FiIUjTIfs7eshS4dAZJfn6OgmT4onUIvY3eEwV4/J0NozWZA7X5SdrsRAY5aTpb8uVY6YqsL///+1ixGOAAAACXRSTlMAUufoasVTONg7C2lAAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAGBJREFUGNNdzkcSgDAIQFHsoth79/6nNH2Cf8FMHosAoArCKAa/JM1y74miopTTAhFVtRjo9ohNi2iBZF1PDIZxMoAa5qXmsG47h+O8ONzPy0GmD/NBf2oOc4cj/PJ2qg+0UQc1SZnCjgAAABh0RVh0QXV0aG9yAFJvYmVydCBTemN6ZXBhbmVrX1axCAAAAFJ0RVh0Q29weXJpZ2h0AENDIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wL16DWrwAAAAYdEVYdENyZWF0aW9uIFRpbWUAMjAxMS0wMy0xMR3JYZ0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjM6MDA6MzgtMDQ6MDATLMoLAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjQzLTA0OjAwtY3rSAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAARdEVYdFRpdGxlAGdyb3VwIGxheWVyMZzWCQAAAABJRU5ErkJggg==)}.olexp-item-heatmap{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAACZFBMVEW+2fW+2fa92fK01dWm0KmYy4Vwt0NgsCJqtEB6unCTw76iye++2fSz1dGgzpaRyWuKxlKMx093vCVwtw5ttQ1crwVnszS82O2o0a+QyGWLxlCgzli82WfT4HDj2FrnzE3bz0WKuB1XqwOBvIW51+aNx1iczVfH3Wvq4X/yzozstYnfi2rLdVzKn0qRqSRSngaDvY282O+gzpiNx1O312Tq5n3z0orqrJPilJHXeHm9Wl6zZ1K+pj9wmhRSlCSPvbyp0rSOx1m62GXz54LvwI7jmJHeg4TVcHG8XF20a1DBoESSpiZOjQZjllyYvN+21t2UynOk0Fru6n7xxo3ilZPbeXrRZme8YVm5fky8qD6QpSRRjgdWkDZ9oKyZvOOr0rvE3Gr55Ifmo5PdgoPSaGfAcFbAl0azrjZ1nBdKjANSjix2nJuJqcuewumhz5yOx1HR4HD11YrgjonTbGzEfFPGrUKlrS5ekw1KixFdk0t3nZ2DosOVuNyjyfGl0KaMx1LH3Wz10oLZdnHBaVrFpkSysjRfkxBVkDVwmoiAoLmQsdWhx+6x1c2KxV2izUfw2VrPeF2/jEq+tTpwmhhbkkh7nqqDocOCocKOsNOgxe2x0u17vGJwtxDW1j/QrkjHskCNpCJUkCZ5nqaCocOCocGMrtCfxOukyvOIv55crw2qxCvPv0CprzBXkA5nl2+Mrc+ew+qjyfKcxtpmsjJuqQ+mri9nlhBSjil6nqeLrM6ew+mjyfCGv5daphVTkgdIigZmlmeDo8ONrtCdwumgyOd+u35epylkoUqHrbuWud+gxez///+BqYbEAAAAAWJLR0TLhLMGcAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAQdJREFUGNNjYAABRiZmFlY2dg5OLm4wl4eXj19AUEhYRFSMC8QXl5CUkpaRlZNXUFRSBvJV+FTV1DU0tbR1dPX0DRgYDI2MTUzNzC0sraxtbO3sGRgcHJ2cXVzd3D08vbx9fP0Y/AMCg4JDQsPCIyKjomNi4xjiVRMSk5JTUtPSMzKzsnNyGfLyCwqLiktKy8orKquqa2oZ6uobGpuaW1rb2js6q7u6axl6evv6J0ycNHnK1GnTZ8ysrWWYNXvO3HnzFyxctHjJ0mW1QIHlK1auWr1m7bolS9Zv2AgS2Lhp85at27bvWLxzVy0IMNTu3rN33/4DBw8d3ggV2Hjk6LHjJ06eqoUAADN6Yn18G+yHAAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDEyLTA0LTI1nbbUYwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo0MjoxMy0wNDowMDq047YAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzItMDQ6MDAZP+nlAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAAl0RVh0VGl0bGUAZGVtUqgAxgAAAABJRU5ErkJggg==)}.olexp-item-overlay{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABnlBMVEUAAABiYmJhYWOHh0G4uDOcnJy8vLzBwcGHh4iXl5eWlpZgYGCIiIicnJx5eXpQUFJ5eUWQkD6VlTx8fE69vbyVlW6Ojj2UlD2Tkz2CgkKQkD7V1Szg4Cm4uDvf3ynd3Sre3iqqqjiYmJigoKCioqKhoaOXl2SgoKCGhmGQkD+UlD2cnJ15eXuUlJShoaG2traDg4OVlZWioqK1tbWCgoKWlpabm5uysrK2tra2tra2trW2tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpbb29W7u7a3t6nFxUDV1S7g4Cq4uDy8vLe5uavGxkHV1dXd3d3d3d7ExLW6upC9vZCiooOkpKOxsavn5+fh4eLZ2drW1tjY2NjAwMC+vr7n5ubh4eHR0dHNzc3c3Nzo6Ojh4uLN0dTp6OjZ2dnQ0NDk5OTZ292NnaezvcPIztHT09PW1tbe3d3X2tuFmKSouMCUpK7l5eXj4+Pm5ubV2dqaq7Tf5umXprDX2tx8k6KRqLePoKvf4eKZqLKKnamwusH///912DDDAAAASXRSTlMAAAAAAAAAAAAAAEfj7sUTRoKAqPvrjIKDcoP8/v7+/v7YbKqmptSm84+D5xg0pecYm6XnGJuR5uHj5+fo0RbAaXN0UxcCY2VBXXRV9wAAAAFiS0dEiRxhJswAAAAJcEhZcwAADdcAAA3XAUIom3gAAADNSURBVBjTY2CAAEZuHl4+fiYoj1lAUEhYxFNUTFxCEizAIiUtI+vl7SMnr6DIwKqkrKKq5uvnHxAYBBZgUw8OCQ0Lj4iMitbQ1AJqYVcJiYmJjYtPSEzS1uEA6tfVC0mOSUlNS03P0DfgBAoYGoVkZmXnpOam5hmbcEEE8gsKi9KLS+ACpWXlFZUxVdU1cIHauvqG5JoahEBjU3NLDLJAa1t7B1AgBiJgamZuYWllbWxsbGNrBxKwd3B0cnYxAQE7V5CAm5ubuwcXAxwAAHTkNv/yoA4lAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjQyOjEzLTA0OjAwOrTjtgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozMi0wNDowMBk/6eUAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC)}.olexp-item-tile{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABelBMVEUAAAAePUpAXnE9XG49W3BRboNCYHOcnJxJZ3q8vLxMan7BwcGAiI2Xl5eWlpYAGyE/XXFJZ3pOa39FYnZEYnY3VWcnRlZHZXhuiZuCmql4k6Vceo5gfpJObIE6WG1BX3NvipxujKBNa38kQlOYmJigoKCioqKhoKBqfouTq7tffZE7V2qgoKBbeo1BX3KUlJShoaGVlZWioqJlgZNQbYE5V22VnaJvd3y3traDg4K1tbWCgoKWlpabm5uysrK2tra1tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpaascB7lqiEorVvjaFujKCMpbZpiJyEorZ3lalsiZ6AnrLV1dXe3t7R09R+kp9+mKlvi51lgpZykKNqiJxceo5ti5/d3d3n5+fg4eK+xcq0vcO1vsS2v8V6j51mhJhde47m5ubp6Ojp6ejq6emQoq1wjqJsip6OoKxohppujKGHmaVXdYmwucChrbbk5OX////lQAoeAAAATnRSTlMAAAAAAAAAAAAAAAAAAAABL2eNdUUIA1TO+f785oAROtz1dQNsqqam0f7QFqbmNTSlm6X4gxHoGucY5xibkebh4+jRFsBpc3RTFwJjZUFlaURvAAAAAWJLR0R9prEQyQAAAAlwSFlzAAAN1wAADdcBQiibeAAAAMJJREFUGNNjYAABRn4BQSFhEVEmBghgFhOXkJSSlpGVY4EIsMor+PkHBAYpKimzMbCrqKqpa2gGh4SGhUdoaXMwcOpERkXHxMbFJyQmJevqcTFwq6WkpqVnZGZl5+SCBfQNUvLy8gsKCouKS8BaDI2AAkCQWlpWDjYULlBRaWxiCrQWLlBVbWbOw4AQyKtJtbDkRRbIy7Oy5oMIpEL4qRABG1s7ewcrEHB0cgYJuLi6uXt4WoOAsxdIwNvb28eXjwEOAGCvOxqF81rtAAAAGHRFWHRBdXRob3IAUm9iZXJ0IFN6Y3plcGFuZWtfVrEIAAAAUnRFWHRDb3B5cmlnaHQAQ0MgQXR0cmlidXRpb24tU2hhcmVBbGlrZSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXoNavAAAABh0RVh0Q3JlYXRpb24gVGltZQAyMDEyLTA0LTMw9McRrQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo0MjoxMy0wNDowMDq047YAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MjctMDQ6MDCHrcbcAAAAQXRFWHREZXNjcmlwdGlvbgBHZW5lcmljIGljb24gZm9yIE9HQyBXZWIgc2VydmljZSAtIE9XUwogKFdNUyxXRlMsV0NTKYljsRwAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAG3RFWHRUaXRsZQBsYXllciBPR0MgV2ViIHNlcnZpY2Vl1KvyAAAAAElFTkSuQmCC)}.olexp-item-vector{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABYlBMVEVohppLaX4AAABLa4Bph5tGZHlLaH0rSWE5V2xAXnOdnJyXlpa8vLyWlpbBwcFUcodriJ1KaH1NcIVNcodKan9KaH1La4BXdoplgpZGZHgxTmRriJ1mhJg6WGxRb4N2lKgAMVo4VWo7WW03Vmo7WW1KaH1Ucog7WW1ObIFbeY5Kan+ZmJiYm5xmd4N/iI+jo6KhoaGioqJreoV0goubmpqVlJSgoKCysrKEhIS1tbWCgoKUlJShoaGVlZWioqKWlpabm5uysrK2tra1tbW1tbWioqKOjo6WlpaWlpaSkpKSkpKQkJCBgYGbm5uWlpaWlpaWlpbW1ta9xMiJmaPT1dbe3d3f3t7FycyGlqHQ09Xd3d3k5OWcqbKuuL/o5+fl5eWeqrOtt73n5+fo6OfQ1NaLm6bS1tjJztLa3N3m5uaut76Ypa+RoKq3v8XX2tt2jp54j6DY29zn5+bf4OGaq7f////ACgSZAAAAUXRSTlMAAAAAAAAAAAAAAAAAAAB6zjICAh1ADmHXRQ+5zpCz1wJZbgUdsmggSHcea7jYraamprnYlw+m5xjnGDSlm6Wbkebh4+jRFsBpc3RTFwJjZUGgI6O7AAAAAWJLR0R1qGqY+wAAAAlwSFlzAAAN1wAADdcBQiibeAAAAMFJREFUGNNjYOAXEGRkYmJiFhIUFBYRFWNgEZeQZAUKsElJy8jKyYsysCsoKilzMDFxqqiqqWtoajFwaevo6ukbGBoYGZuYcjMxMfCYBQYFh4SGhUdEmlvwAgX4DKOiY2Lj4hMSkyytQALWNlHJKalp6akZUAFbu6jMpKzsnNykTCSBvPyCwiIkgczikpLiTGSBzGIgH0UADOACSRA+1BZ7B0cnZ0sQcHF1Awm4e3h6eftYgYCbL0jAz8/PPwDIgAEAQjY2sOYkNQMAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDMtMjRUMjI6NDI6MTMtMDQ6MDA6tOO2AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA1LTE3VDE4OjUzOjI0LTA0OjAwtkXcQQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII=)}.olexp-measure{background:#000;background:rgba(0,0,0,.5);border-radius:4px;color:#fff;opacity:.7;padding:4px 8px;position:relative;white-space:nowrap}.olexp-measure-active{font-weight:700;opacity:1}.olexp-measure-static{background-color:#fc3;border:1px solid #fff;color:#000}.olexp-measure-active:before,.olexp-measure-static:before{border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #000;border-top:6px solid rgba(0,0,0,.5);bottom:-6px;content:"";left:50%;margin-left:-7px;position:absolute}.olexp-measure-static:before{border-top-color:#fc3}.olexp-measure-hidden{display:none}.olexp-menu-remove{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA/FBMVEUAAACcnJyWlpa8vLzBwcGVlpbSZGSYmJigoKCioqKhoaGioqKampqTk5OgoKCxsbGEhIS1tbWCgoKUlJShoaGVlZWioqK0tbWBgoLJgoLQa2vUamrTaWnTZmbWcHCWlpabm5uysrK2tra1tbXJgYGWlpaWlpaSkpKSkpKQkJCBgYF6hobOZWXSY2OWlpaWlpaWlpbSZGTSZGTSZGTSZGTV1dXd3d3n5+fm5ubm5+fj0tLcoaHaf3/diYndjIzdi4vbhobalpbekpLhnJzgm5vXeHjbmprkxMTq5eXp5OTo2trZiYnYhITZkpLYjIzUcHDSYmLSYWHSZGT///9J6V6JAAAANXRSTlMAAAAAAAAAbKqmpqeXEKbnGOcYNKWbpecY96+nnFPim5Hm4eP3wGlzdFMXFqT0Y2VBU+L0mxGrfJUAAAABYktHRFN6Zx0GAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAlUlEQVQY02NgIB0wsnNwcoEBNw8vE1CAmc/UDAr4BUACLJxm5hZgYC4oBBIQFjGzgAKIgKgYTgFLcQlWZAEra0kpaRlZuICltY2tnb2DHELA0cnZ2dnFFSQAttbSzd3D08PLm0FeQVFJWVBQUFzFx9fX18+fQVVNXUNTS0hIWycgEAh0GfT09PQNgPazGRoFBQUZmwAAfGshdfRsxLUAAAAYdEVYdEF1dGhvcgBSb2JlcnQgU3pjemVwYW5la19WsQgAAABSdEVYdENvcHlyaWdodABDQyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzMuMC9eg1q8AAAAGHRFWHRDcmVhdGlvbiBUaW1lADIwMDgtMTItMTJYLju/AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE2LTAzLTI0VDIyOjUyOjE4LTA0OjAw+T1ojAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0wNS0xN1QxODo1MzozNC0wNDowMHrv3N8AAAAndEVYdERlc2NyaXB0aW9uAGh0dHA6Ly9yb2JlcnQuc3pjemVwYW5lay5wbJBZSGAAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC)}.olexp-menu-zoom{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAB2lBMVEUAAAB8e3tJSUkaGhpVVVVLS0tWVlacnJy8vLzBwcF+fn5RUVFISEiUlJSWlpaXl5dKSkpSUlJQUFBTU1NPT09AQEBCQkJYWFh+fn6trq67u7upqqqHh4djY2NHR0c3NzdcXFycnJzf4OD09vb2+Pjt7u7c3NywsLBvb2+YmJigoKCioqKJiYmVlZXg4eHz9fXq6+vg4eHd3d3d3d3l5eUlJSWgoKDc3Nzk5OTc3Nzd3d3k5OShoaFUVFSUlJShoaHn5+epqalRUVGVlZWioqLi4uKbm5tUVFTl5eXS0tJ6enrf39/c3NyamppZWVnAwMCSkpJdXV1BQUGWlpaenp6Pj49gYGAxMTGTk5R+fnyxsbGBgYF+fHewoG6jjEWHhYKxsbK1tbW1tbWioqKOjo6ijUx3dnGQkZOFhYWCgoKbm5txcG5xZ0pqZ12RkpOXl5fV1dXZ2dmoqKjKysrz9PTx8vLm5ubk5OTe3t7d3d2mpqbe39/2+Pjt7e3a2tqjo6Pr7Ozy8/Pq6url5eW0tLS8vLzn5+fm5+fi4uKXl5dpaWnExMSrq6tEREMZGRnX19fg4ODb29uwr66xpHuGdkNDQ0K0p3zoxValklaqqqnpxVd7dF7CpEX///8MWklrAAAAcHRSTlMAAAAAAAAAAAAAAAAAAAAAFTdJPyIDBkKVw9nGo2ERA1i+4u/s3c/IhWyqpqvZ8fj69u/q0AKm+tHO+s3APzSlzMlKm6XNuDfRzpP607xC+7lZBZul70IDoqvnGOLl7+Pn5+jRFv62VBcYAm+/hWRBY/kEXQAAAAFiS0dEnQa78rEAAAAJcEhZcwAADdcAAA3XAUIom3gAAADySURBVBjTY2AAA0YBQSFhEVEmCI+BSUxcQlJKWkZWjpkFxGeVV1BUUlZRVVPXkGNjYNfU0tbR1dM3MDQyNlGXNWXgMCsoLCouKS0rLze3sJQRYeDUrqisqq6pLSsrs7KwtrFlsLOvrKsvq2kACzg4OjE4u1RWFBU2NoEFXN3cQQLNLa1t7SABD08vAZBAR2dXd1tbWZu3j68fF1Cgrqe3r6u1f8JE/4DAIG6G4JBJk6dM7Wwpqq8KDQvnYWCIiJw2fcbMjuaKusqoaF6gu2NiZ8XFJyQCQVJyCh9QYPac1LT0jEwQSMkCCWTn5Obl8zPAAQBxnUmB66PzwgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo1MjoxOC0wNDowMPk9aIwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MjUtMDQ6MDAQMtf1AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg==)}.olexp-menu-properties{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABPlBMVEUAAACcnJyWlpa8vLzBwcGVlpnEoACYmJigoKCioqKhoaGioqKampqTk5OgoKCxsbGEhIS1tbWCgoKUlJShoaGVlZWioqK0tbmBgoW6rXW5mxXEnwDDngDDnwDOsCzRtTjVvU7HpQ3OsS6Wlpabm5uysrK2tra1tbW6rXGWlpaWlpaSkpKSkpKQkJCBgYFveam5mhHUu0fEoACWlpaWlpaWlpbDnwDMribEoADEoADV1dXd3d3n5+fm5ubm5+nn6Ovl5eHf2Lnb0Jzf2LfMsTXMriTNsCvazpbMribVu0rVvEvbx2jv6MHv6cXazZXPsS/WvU/ezHby7tL4+Ozh0YXLqx7n6OzMrSPZw1/s47b5+e/i0obQtDbIpxPKqRfp4Kvj1I3cyGvHpg/EoADr4rLaxmbGowrEnwDKqhz///9c6MQYAAAAOnRSTlMAAAAAAAAAbKqmpqeXEKbnGOcYNKWbpecY72NTTSL8/PW2/puR5uHj78Bpc3RTFxNi+/VjZUEpxPejjuW4JwAAAAFiS0dEabxrxLQAAAAJcEhZcwAADdcAAA3XAUIom3gAAACnSURBVBjTY2AgHTCyc3BygQE3Dy8TUICZz8oaCvgFQAIsnNY2tmBgIygEEhAWsbaFAoiAqBhUwM5eXIIVScDB0UlSSlpGFiZg5+zi6iYnr6AIE7B39/D08vbxVYIL+PkHBAYFh4SCBEDWhrmHR0RGRcfEMiirqKqpCwqKa8TFJyQmJSczaGpp6+jqCekbGKakpqUnGzEYGxubmDIxsJmZZyQnJ1tYAgAz9Sdtd6GLUgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNi0wMy0yNFQyMjo1MjoxOC0wNDowMPk9aIwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDUtMTdUMTg6NTM6MzEtMDQ6MDAo1/N4AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg==)}.olexp-ol-toolbar-show{left:2.75em;top:.5em}.ol-mouse-position{background:#95b9e6;background:rgba(0,60,136,.5);bottom:8px;color:#eee;font-size:10px;left:auto;margin:1px;padding:2px;position:absolute;right:.5em;text-align:center;top:auto}.ol-overviewmap{bottom:2.25em}.ol-rotate{top:5em}.ol-zoom-extent{left:auto;right:.5em;top:2.75em}.ol-zoomslider{width:28px}.w2ui-toolbar table.w2ui-button .w2ui-tb-image{height:24px;width:24px} \ No newline at end of file diff --git a/dist/olexp.sa.min.js b/dist/olexp.sa.min.js index e1f60b8..b58aaed 100644 --- a/dist/olexp.sa.min.js +++ b/dist/olexp.sa.min.js @@ -1,999 +1,999 @@ -/*! jQuery v2.1.3 | (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=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,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=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.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},n.extend=n.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||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},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?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},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=s(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(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;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=s(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&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=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.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;++db;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.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="",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);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(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&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.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?n.extend(a,d):d}},e={};return d.pipe=d.then,n.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&&n.isFunction(a.promise)?e:0,g=1===f?a:n.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]&&n.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;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(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};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c) -},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.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.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.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 L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),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),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==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,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!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(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.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 this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(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=jb(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?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(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&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(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,n.cleanData(ob(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,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("