Table of Contents for
Mastering OpenLayers 3

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Mastering OpenLayers 3 by Gábor Farkas Published by Packt Publishing, 2016
  1. Cover
  2. Table of Contents
  3. Mastering OpenLayers 3
  4. Mastering OpenLayers 3
  5. Credits
  6. About the Author
  7. About the Reviewer
  8. www.PacktPub.com
  9. Preface
  10. What you need for this book
  11. Who this book is for
  12. Conventions
  13. Reader feedback
  14. Customer support
  15. 1. Creating Simple Maps with OpenLayers 3
  16. Structure of OpenLayers 3
  17. Building the layout
  18. Using the API documentation
  19. Debugging the code
  20. Summary
  21. 2. Applying Custom Styles
  22. Customizing the default appearance
  23. Styling vector layers
  24. Customizing the appearance with JavaScript
  25. Creating a WebGIS client layout
  26. Summary
  27. 3. Working with Layers
  28. Building a layer tree
  29. Adding layers dynamically
  30. Adding vector layers with the File API
  31. Adding vector layers with a library
  32. Removing layers dynamically
  33. Changing layer attributes
  34. Changing the layer order with the Drag and Drop API
  35. Clearing the message bar
  36. Summary
  37. 4. Using Vector Data
  38. Accessing attributes
  39. Setting attributes
  40. Validating attributes
  41. Creating thematic layers
  42. Saving vector data
  43. Saving with WFS-T
  44. Modifying the geometry
  45. Summary
  46. 5. Creating Responsive Applications with Interactions and Controls
  47. Building the toolbar
  48. Mapping interactions to controls
  49. Building a set of feature selection controls
  50. Adding new vector layers
  51. Building a set of drawing tools
  52. Modifying and snapping to features
  53. Creating new interactions
  54. Building a measuring control
  55. Summary
  56. 6. Controlling the Map – View and Projection
  57. Customizing a view
  58. Constraining a view
  59. Creating a navigation history
  60. Working with extents
  61. Rotating a view
  62. Changing the map's projection
  63. Creating custom animations
  64. Summary
  65. 7. Mastering Renderers
  66. Using different renderers
  67. Creating a WebGL map
  68. Drawing lines and polygons with WebGL
  69. Blending layers
  70. Clipping layers
  71. Exporting a map
  72. Creating a raster calculator
  73. Creating a convolution matrix
  74. Clipping a layer with WebGL
  75. Summary
  76. 8. OpenLayers 3 for Mobile
  77. Responsive styling with CSS
  78. Generating geocaches
  79. Adding device-dependent controls
  80. Vectorizing the mobile version
  81. Making the mobile application interactive
  82. Summary
  83. 9. Tools of the Trade – Integrating Third-Party Applications
  84. Exporting a QGIS project
  85. Importing shapefiles
  86. Spatial analysis with Turf
  87. Spatial analysis with JSTS
  88. 3D rendering with Cesium
  89. Summary
  90. 10. Compiling Custom Builds with Closure
  91. Configuring Node JS
  92. Compiling OpenLayers 3
  93. Bundling an application with OpenLayers 3
  94. Extending OpenLayers 3
  95. Creating rich documentation with JSDoc
  96. Summary
  97. Index

Changing layer attributes

We've almost reached the state of a fully operational layer tree. The next step in the process is to add the capabilities of changing layer attributes. In this example, we will make sure that we can change any layer's visibility, opacity, and its name from the GUI. The example files are named ch03_attributes. As we are only adding further parts to the layer element, we mostly have to extend our createRegistry method.

Styling active layers

In our concept, only active layers can be modified. With this consideration, only the active layer element's options are exposed. The other layers will have the same nice, uniform height that shows only the layer's name and the visibility checkbox. We can easily implement this behavior with CSS:

.layercontainer .layer.active {
    border-color: orange;
    min-height: 2em;
    height: auto;
}
.layer div {
    display: none;
}
.layer.active div {
    display: block;
}

Note

In most browsers, the initial value works just fine when resetting values to their defaults. However, Internet Explorer won't interpret initial, and as all the browsers know auto, it is advisable to use it for increased compatibility.

Extending the method

Now that the styling of the elements is complete, we can create logic to manage the layer attributes. First, we add some listeners to the layer's name element so that we can change it by double-clicking on it:

this.createRegistry = function (layer, buffer) {
    […]
    layerSpan.addEventListener('dblclick', function () {
        this.contentEditable = true;
        layerDiv.classList.remove('ol-unselectable');
        this.focus();
    });
    layerSpan.addEventListener('blur', function () {
        if (this.contentEditable) {
            this.contentEditable = false;
            layer.set('name', this.textContent);
            layerDiv.classList.add('ol-unselectable');
            layerDiv.title = this.textContent;
            this.scrollTo(0, 0);
        }
    });

If we double-click on the layer name, our code changes its content to be editable, makes it selectable (otherwise, the editable attribute just wouldn't work on some browsers), and gives focus to it. If the element loses focus (the blur event), we restore the element's original status and update everything with the layer's new name. In the last step, we scroll to the start of the text as Firefox won't do it automatically.

Tip

Making an element's content editable is an easy solution, but it is not stable (add some line breaks to the layer name and see for yourself). As a more stable solution, you can add a hidden text input to the element, make it visible when it's double-clicked, bind it to the layer name and layer object correctly, and make it disappear on losing focus.

Next, we create a checkbox that controls the visibility of the layer. We control the top of it with CSS, and then bind it to the layer. We also gather its initial value from the layer object (luckily, both of them operate with Booleans):

    var visibleBox = document.createElement('input');
    visibleBox.type = 'checkbox';
    visibleBox.className = 'visible';
    visibleBox.checked = layer.getVisible();
    visibleBox.addEventListener('change', function () {
        if (this.checked) {
            layer.setVisible(true);
        } else {
            layer.setVisible(false);
        }
    });
    layerDiv.appendChild(this.stopPropagationOnEvent(visibleBox, 'click'));
    […]

With the layer object given to the method, we only have to toggle its visibility based on the status of the checkbox. However, we are faced with a new issue. If we click on the checkbox, we trigger the selection event, making our code select the checkbox and messing up our entire logic. To prevent this behavior, we create a stopPropagationOnEvent utility method, which has a quite meaningful name:

layerTree.prototype.stopPropagationOnEvent = function (node, event) {
    node.addEventListener(event, function (evt) {
        evt.stopPropagation();
    });
    return node;
};

In the last step, we return to the createRegistry method and define a slider, which we use to control the layer's opacity. We create a div element to store future controls and make sure that we can't deselect a layer by clicking on it. Next, we append the slider to it. Its initial value depends on the layer's current opacity, and it has a direct binding to the layer. Similar to the checkbox, we have to stop the slider from propagating, too:

Tip

We defined our bindings to work in only one way (GUI map). If you would like to have your layer tree updated in terms of the changes made to the map object, you have to register some listeners there, too.

    var layerControls = document.createElement('div');
    this.addSelectEvent(layerControls, true);
    var opacityHandler = document.createElement('input');
    opacityHandler.type = 'range';
    opacityHandler.min = 0;
    opacityHandler.max = 1;
    opacityHandler.step = 0.1;
    opacityHandler.value = layer.getOpacity();
    opacityHandler.addEventListener('input', function () {
        layer.setOpacity(this.value);
    });
    opacityHandler.addEventListener('change', function () {
        layer.setOpacity(this.value);
    });
    layerControls.appendChild(this.stopPropagationOnEvent(opacityHandler, 'click'));
    layerDiv.appendChild(layerControls);
    […]
};

Note

You must be wondering why we have registered a listener to the change event when we have one on the input event that fires immediately when we move the slider. Well, because of Internet Explorer, of course. Most major browsers fire an input event in this case, while IE 11 fires a change event.

If you save the code and load the example, you will see the attribute controls working. If you want to map other attributes to the GUI, you can easily do so by creating elements for them and appending them to layerControls:

Extending the method