Single layer visible in LayerList widget (ArcGIS JavaScript) - widget

Is it possible to have a single layer visible on the map in this ESRI tutorial LayerList widget ?
Each time you click on a layer, the previous one should deactivate. So you always have only one layer on the map.
Michelle

Updated answer with version 4 of the API.
It is possible to add the functionality at creating the widget using 2 features.
The listItemCreatedFunction function-
https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-LayerList.html#listItemCreatedFunction
According to the api:
Specifies a function that accesses each ListItem. Each list item can be modified according to its modifiable properties. Actions can be added to list items using the actionsSections property of the ListItem.
and the operationalItems property-
https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-LayerList.html#operationalItems
According to the api:
A collection of ListItems representing operational layers.
var LayerListWidget = new LayerList({
listItemCreatedFunction: (event) => {
var itemView = event.item; // layer-view of selection
itemView.watch("visible", (event) => {
LayerListWidget.operationalItems.forEach((layerView) => {
if (layerView.layer.id != itemView.layer.id) {
layerView.visible = false;
}
});
});
},
view: view,
});

I managed to write a code for you . Check it and let me know :
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Layer List Dijit</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.20/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.20/esri/css/esri.css">
<script language="javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<style>
html, body, .container, #map {
height:100%;
width:100%;
margin:0;
padding:0;
margin:0;
font-family: "Open Sans";
}
#map {
padding:0;
}
#layerListPane{
width:25%;
}
.esriLayer{
background-color: #fff;
}
.esriLayerList .esriList{
border-top:none;
}
.esriLayerList .esriTitle {
background-color: #fff;
border-bottom:none;
}
.esriLayerList .esriList ul{
background-color: #fff;
}
</style>
<script>var dojoConfig = { parseOnLoad: true };var busy=false;</script>
<script src="https://js.arcgis.com/3.20/"></script>
<script>
require([
"esri/arcgis/utils",
"esri/dijit/LayerList",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dojo/domReady!"
], function(
arcgisUtils,
LayerList
) {
//Create a map based on an ArcGIS Online web map id
arcgisUtils.createMap("f63fed3f87fc488489e27c026fa5d434", "map").then(function(response){
var myWidget = new LayerList({
map: response.map,
layers: arcgisUtils.getLayerList(response)
},"layerList");
myWidget.on("toggle",function(evt){
if(busy) return;
selectedLayerSubIndex = evt.subLayerIndex;
if(selectedLayerSubIndex) return;
selectedLayerIndex = evt.layerIndex;
visibility = evt.visible;
elm = $("#layerListPane input[type=checkbox][data-layer-index="+selectedLayerIndex+"]:not([data-sublayer-index])");
otherCheckedElems = $("#layerListPane input[type=checkbox][data-layer-index!="+selectedLayerIndex+"]:not([data-sublayer-index]):checked");
if(visibility){
busy=true;
otherCheckedElems.each(function () {
$(this).click();
});
busy=false;
}
else{
checkedLength = otherCheckedElems.length
if(checkedLength==0) setTimeout("elm.click();", 100);
}
})
myWidget.startup();
});
});
</script>
</head>
<body class="claro">
<div class="container" data-dojo-type="dijit/layout/BorderContainer"
data-dojo-props="design:'headline',gutters:false">
<div id="layerListPane" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'right'">
<div id="layerList"></div>
</div>
<div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
</div>
</body>
</html>

Related

Always show click-count

I have been trying to create a like counter for a webpage. Currently, It only shows the number likes when someone presses the button. The code is written below.
<!DOCTYPE html>
<html>
<head>
<script>
function clickCounter() {
if(typeof(Storage) !== "undefined") {
if (localStorage.clickcount) {
localStorage.clickcount = Number(localStorage.clickcount)+1;
} else {
localStorage.clickcount = 1;
}
document.getElementById("result").innerHTML =localStorage.clickcount;
}
}
</script>
</head>
<body>
<p><button onclick="clickCounter()" type="button" style="background-image:url(URL TAKEN OUT DUE TO COPYRIGHT ISSUE); background-position:left; background-repeat:no-repeat; padding-left:30px; padding-top:4px; padding-bottom:4px; padding-right:4px" > Please Like! </button> </p>
<div id="result"></div>
</body>
</html>
I am aware that .innerHTML is the problem behind 'the number of likes' not being shown but I am not sure how to make it so that it always displayed and centred above the button.
Eg. If the page has 143 likes.
143
Please Like!
Please help me out - Thank You so much for reading
You have to display the counter initially, and then keep track each time it changes.
<!DOCTYPE html>
<html>
<head>
<script>
function clickCounter() {
if(typeof(Storage) !== "undefined") {
if (localStorage.clickcount) {
localStorage.clickcount = Number(localStorage.clickcount)+1;
} else {
localStorage.clickcount = 1;
}
showCounter();
}
}
function showCounter(){
if(typeof(Storage) !== "undefined") {
document.getElementById("result").innerHTML =localStorage.clickcount;
}
}
</script>
</head>
<body>
<p><button onclick="clickCounter()" type="button" style="background-image:url(URL TAKEN OUT DUE TO COPYRIGHT ISSUE); background-position:left; background-repeat:no-repeat; padding-left:30px; padding-top:4px; padding-bottom:4px; padding-right:4px" > Please Like! </button> </p>
<div id="result"></div>
<script>
showCounter(); //Fisrt call, Once the page is loaded.
</script>
</body>
</html>

access variable from controller to custom directive in AngularJS

index.html
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-app="webQueryApp">
<div ng-controller="TestAppController">
<div class="operationalArea" my-Draggable > click me </div>
</div>
</div>
</body>
</html>
-
style.css
.operationalArea {
background-color: #eeeeee;
height: 100px;
width: 100px;
float: left;
padding: 5px;
}
app.js
var webQueryApp = angular.module("webQueryApp", [ ]);
webQueryApp.directive('myDraggable', function(){
return{
//link start
link: function ($scope, element, attrs) {
element.bind('click', function(event) {
console.log("element clicked and arr is "+attrs.arr);
});
}
//link end
};
});
webQueryApp.controller('TestAppController', function($scope, $http) {
var app = this;
console.log("hello console");
$scope.arr=[1,2,3,4];
});
you can see in plunker
http://plnkr.co/edit/aabS53ZgjKnrXWu1aFtt?p=preview
i want to use controller arr value in custom directive.
but it says undefined. while i am tring i can't have the scope of table.
other wise send me a reference where i can found the solution.
From the plunker you provided, just modify the directive scope property to the follwing
scope: {
data: '=',
}
and you are going to be able to use the array by calling $scope.data

Externally linked .css file is not working with html5 code

I have following html file in my visual studio 2013 project
!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<link href="css/my.css" type="text/css" rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/mobile/1.4.2/jquery.mobile- 1.4.2.css">
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.3.js'></script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.css">
<script type='text/javascript' src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
<script type='text/javascript' src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/additional-methods.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
#loginBody {
color: aqua;
}
</style>
<script type='text/javascript'>
$(document).on('pageinit', function () {
//$.support.cors =true,
//$.mobile.allowCrossDomainPages = true;
$('#frmLogin').validate(
{
rules: {
username: {
required: true
},
password: {
required: true
}
},
messages: {
username: {
required: "Please enter your username."
},
password: {
required: "Please enter your password."
}
},
errorPlacement: function (error, element) {
error.appendTo(element.parent().prev());
},
submitHandler: function (form) {
//$("#frmLogin").submit(function (event) {
//event.preventDefault();
var credentials = { username: $("#username").val(), password: $("#password").val() };
$.ajax({
type: "POST",
url: "api/auth", // this url is just a placeholder
cache: false,
data: JSON.stringify(credentials),
contentType: "application/json; charset=utf-8",
success: function(data,status,jqxhr)
{
//validate the response here, set variables... whatever needed
//and if credentials are valid, forward to the next page
if (data.status == "success")
{
var obj = $.parseJSON(data);
localStorage.setItem("acccessToken", obj.accessToken);
alert(obj.accessToken);
$(":mobile-pagecontainer").pagecontainer ("change", "Authorization.html", { role: "page" });
//window.location.href = "http://www.jqueryvalidation.org";
}
else if(data.status== "error")
{
alert("Authentication Invalid.Please try again!");
return false;
}
//or show an error message
},
error: function (jqxhr, status, errorMsg)
{
// server couldn't be reached or other error
alert("jqXHR Status : " + jqxhr.status + " Status: " + status + " Error: " + errorMsg);
}
}, "json");
return false;
}//);
});
});
</script>
<style type="text/css">
label.error
{
color: red;
font-size: 16px;
font-weight: normal;
line-height: 1.4;
margin-top: 0.5em;
width: 100%;
float: none;
}
#media screen and (orientation: portrait){
label.error { margin-left: 0; display: block; }
}
#media screen and (orientation: landscape){
label.error { display: inline-block; margin-left: 22%; }
}
em { color: red; font-weight: bold; padding-right: .25em; }
</style>
</head>
<body id="loginBody">
<div data-role="page" id="login">
<div data-role="header">
<h1> Intergraph </h1>
</div>
<div data-role="content">
<form id="frmLogin" method="post" action="api/auth" data-ajax="false">
<div data-role="fieldcontain">
<label for="username">
<em>* </em> Username:
</label>
<input type="text" id="username"
name="username" />
</div>
<div data-role="fieldcontain">
<label for="password">
<em>* </em>Password:
</label>
<input type="password" id="password"
name="password" />
</div>
<div class="ui-body ui-body-b">
<button class="btnLogin" type="submit" id="loginBtn"
data-theme="a">
Login
</button>
</div>
</form>
</div>
<!--<div data-role="page" id="success" data-theme="b">
<div data-role="header">
<h1>Thank You!!!</h1>
</div>
</div>-->
</div>
</body>
</html>
And here is code inside my my.css file
#loginBody
{
background: url('../images/my-generic-curved-background.png') no-repeat fixed center bottom;
background-size:390px 320px; color:blue;
}
#loginContent
{
text-align:center;
margin-top:210px;
color:aquamarine;
}
Now the weird thing is this file is not read or not loaded (I'm not sure and even I don't know how to ascertain that) but when I replace #loginBody selector with * (all) I can see the image in the background of the page is displayed and also blue color in the portion of the page which is not covered by the image (so may be my.css file is getting loaded on the run , I would suppose). So precisely what I mean is that css rules are getting applied on for * (all) selector and other selectors too but not for #loginBody selector, why is that?
All ideas and suggestions will be highly appreciated.
Thanks
You need to override the base styles setup by JQM. The .ui-overlay-a class sets colours that you aren't overriding and you've also placed your my.css before any JQM includes. To override, your my.css must be last in the link includes and you need to use !important.
I would suggest heading to the bottom of the official themes page and look through the overrides for each section. They don't provide information on background images but it will show you what the capabilities are out-of-the-box.
http://demos.jquerymobile.com/1.0rc2/docs/api/themes.html
The data-theme attribute can be applied to the header and footer
containers to apply any of the lettered theme color swatches. While
the data-theme attribute could be added to the content container, we
recommend adding it instead to div or container that has been assigned
the data-role="page" attribute to ensure that the background color is
applied to the full page.
I'd also suggest using developer tools to inspect the elements and how JQM is settings styles. In Chrome/FF you right click on an element and select Inspect Element.

jsplumb.connect not working for dynamically created endpoints

I need help to understand the jsplumb.connect concept. I am trying to create endpoints from xml file and trying to connect the endpoints. But i am able to generate the endpoint but not the connections.
XML file
<?xml version="1.0" encoding="utf-8" ?>
<apps>
<source nodeStyle="Dot" nodeRadius="15">#66CCFF</source>
<target nodeStyle="Dot" nodeRadius="15">#66CCFF</target>
</apps>
html file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script>
<script type="text/javascript" src="../js/jquery.jsPlumb-1.3.16-all-min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
var i=0;
var nodeName, nodeVal,nodeStyle,nodeRadius;
$.get('data1.xml', function(d){
$(d).find('apps').each(function(){
jsPlumb.Defaults.EndpointStyles = [{ fillStyle:"none" }, { fillStyle:"none" }];
while($(this).children()[i].nodeName!=null)
{
nodeName = $(this).children()[i].nodeName;
nodeVal = $(this).find($(this).children()[i].nodeName).text();
nodeStyle = $(this).find($(this).children()[i].nodeName).attr('nodeStyle');
nodeRadius = $(this).find($(this).children()[i].nodeName).attr('nodeRadius');
var nodeName = jsPlumb.addEndpoint( nodeName, {
overlays: [["Label", { label: nodeName, id: "label"+nodeName}]],
paintStyle: { fillStyle: nodeVal},
endpoint: [nodeStyle , { radius: nodeRadius }]
});
i++;
}
jsPlumb.bind("ready", function () {
jsPlumb.connect({
source: source, target: target, paintStyle: { lineWidth: 10, strokeStyle: '#66CCFF' },
endpoint: ["Dot", { radius: 15}], anchor: "BottomCenter",
connector: "Straight",
detachable: false,
overlays: [
["Label", {
fillStyle: "rgba(100,100,100,80)",
color: "white",
font: "12px sans-serif",
borderStyle: "black",
borderWidth: 2
}],
["Arrow", { location: 0.5}]
]
})
});
});
});
});
</script>
</head>
<body>
<div id="source" style="position: absolute; left: 100px; top: 250px;">
</div>
<div id="target" style="position: absolute; left: 600px; top: 250px;">
</div>
</body>
</html>
This can be accomplished programatically by first setting the uuid parameter of each endpoint like so:
jsPlumb.addEndpoint("0",{uuid:"ep0_0", isSource:true, isTarget:true});
jsPlumb.addEndpoint("1",{uuid:"ep1_0", isSource:true, isTarget:true});
And then connecting them as such
jsPlumb.connect({ uuids:["ep0_0","ep1_0"] });
//With more options looks like...
//jsPlumb.connect({ uuids:["ep0_0", "ep1_0"], endpoint: endpoint, anchors: flat_to_flat_anchors, overlays:overlays });
The html:
<div id="0" class="window"></div>
<div id="1" class="window"></div>
Bare bone js:
jsPlumb.addEndpoint("0",{uuid:"ep1"});
jsPlumb.addEndpoint("1",{uuid:"ep2"});
jsPlumb.connect({ uuids:["ep1","ep2"] });

how do i change button/image onclick to active state?

Here is what i want:
Now in more detail:
I have 2 iframes, one on top of the other. the one above has 4 buttons/images, the one below is where a url/link will be displayed when one of these buttons/images gets clicked. i got this working...
what i want now is to have those buttons change image from inactive (ie. light pink) to active (ie. red) state when they are clicked. also, when i click on another of the 4 buttons it will turn red and the previous active (red) button/image must turn back to its inactive state (light pink). so i want 2 images here: (1) active.png and (2) inactive.png.
ALSO, i want the buttons to change to active.png when i hover over them. this i was able to manage with onmouseover and onmouseout effect. its just the ACTIVE part is what i cant figure out.
do i need javascript or can i do without it in case some user has it disabled?
i was also thinking about maybe using radio buttons and then skinning them with my active.png and inactive.png using css or something, but i dont know how to do this either :P i dont know what is the best and simplest way to go?
------------UPDATE-----------
ok i got something working but im not all the way there yet. it might not even be the way to go, but what i've done is create 4 links and given them all an id (ie.button1, button2..)
then in css i did this for each:
button1 { width: 66px; height: 70px; display: block; background-image:url(images/inactive1.png); }
button1:hover { width: 66px; height: 70px; display: block; background-image:url(images/active1.png); }
button1:focus{ width: 66px; height: 70px; display: block; background-image:url(images/active1.png); }
but i dont want it to loose focus unless another one of the buttons is clicked. cuz now its loosing focus if i click anywhere on the page :( how can i fix this?
I made these two files that cover all:
<!DOCTYPE html>
<html>
<head runat="server">
<title>Deep East Music</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<style type="text/css">
.buttons { float:left; width:60px; height:25px; margin:10px 0 0 5px; cursor:pointer; }
.buttons[isselected = "true"] { background-color:#ff7373; }
.buttons[isselected = "false"] { background-color:#cccccc; }
</style>
<script type="text/javascript">
$(document).ready(function () {
$("#button1").click(function () {
$(".buttons").attr("isselected", "false");
$(this).attr("isselected", "true");
$("#myiframe").attr("src", "https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F38593173");
});
$("#button2").click(function () {
$(".buttons").attr("isselected", "false");
$(this).attr("isselected", "true");
$("#myiframe").attr("src", "https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F37674430");
////Use one of these if you need to reload the iframe
//$('#myiframe').contentWindow.location.reload(true);
//$("#myiframe").attr("src", $("#myiframe").attr("src"));
});
$("#button3").click(function () {
$(".buttons").attr("isselected", "false");
$(this).attr("isselected", "true");
$("#myiframe").attr("src", "https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Fplaylists%2F3442336");
});
$("#button4").click(function () {
$(".buttons").attr("isselected", "false");
$(this).attr("isselected", "true");
$("#myiframe").attr("src", "https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F38359257");
});
});
function ClickedButton1 () {
$("#myiframe").attr("src", "https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F38593173");
return false;
};
function ClickedButton2 () {
$("#myiframe").attr("src", "https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F37674430");
return false;
};
function ClickedButton3 () {
$("#myiframe").attr("src", "https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Fplaylists%2F3442336");
return false;
};
function ClickedButton4 () {
$("#myiframe").attr("src", "https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F38359257");
return false;
};
</script>
</head>
<body>
<div>
<div id="button1" class="buttons" isselected="true">button1</div>
<div id="button2" class="buttons" isselected="false">button2</div>
<div id="button3" class="buttons" isselected="false">button3</div>
<div id="button4" class="buttons" isselected="false">button4</div>
<iframe id="mybuttonsiframe" width="100%" height="60" scrolling="no" frameborder="no" src="buttons.htm"></iframe>
<iframe id="myiframe" width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F38593173"></iframe>
</div>
</body>
</html>
And buttons.htm looks like:
<!DOCTYPE html>
<html>
<head runat="server">
<title>Deep East Music</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<style type="text/css">
/* CSS Here */
.iframebuttons { float:left; width:100px; height:25px; margin:10px 0 0 5px; cursor:pointer; }
.iframebuttons[isselected = "true"] { background-color:#ff7373; }
.iframebuttons[isselected = "false"] { background-color:#cccccc; }
</style>
<script type="text/javascript">
$(document).ready(function () {
$("#iframebutton1").click(function () {
$(".iframebuttons").attr("isselected", "false");
$(this).attr("isselected", "true");
parent.ClickedButton1();
});
$("#iframebutton2").click(function () {
$(".iframebuttons").attr("isselected", "false");
$(this).attr("isselected", "true");
parent.ClickedButton2();
});
$("#iframebutton3").click(function () {
$(".iframebuttons").attr("isselected", "false");
$(this).attr("isselected", "true");
parent.ClickedButton3();
});
$("#iframebutton4").click(function () {
$(".iframebuttons").attr("isselected", "false");
$(this).attr("isselected", "true");
parent.ClickedButton4();
});
});
</script>
</head>
<body>
<input type="button" id="iframebutton1" class="iframebuttons" isselected="true" value="iframebutton1" />
<input type="button" id="iframebutton2" class="iframebuttons" isselected="false" value="iframebutton2" />
<input type="button" id="iframebutton3" class="iframebuttons" isselected="false" value="iframebutton3" />
<input type="button" id="iframebutton4" class="iframebuttons" isselected="false" value="iframebutton4" />
</body>
</html>
The only way to do this without JS, is to create four static pages as mentioned in the comment to your original post.
Your body markup would look like this:
<ul id="nav">
<li class="active"></li>
<li></li>
<li></li>
<li></li>
</ul>
<iframe src="www.url.com">
</iframe>
The list above is your Navigation. You do not need a separate iframe, since you have four static pages. In each static page, the li-element containing the link to the active static page gets a class called "active".
The iframe stores the url, you want to be displayed in there.
In your css file, you can style your navigation like that:
#nav a {background: url('images/inactive.png');}
#nav a:hover,
#nav li.active a{
background: url('images/active1.png');
}
This should work, but a solution using JS would be much more elegant.