Sunday, July 20, 2014

Custom OpenLayers Panel and Buttons part 2


Like we said, Panel is just a parent div for button divs with some extra stuff. Let's continue with our code and create one.

    var panelButtons = [simpleBtn, simpleToggleBtn, simpleTool1Btn, simpleTool2Btn];

    panel = new OpenLayers.Control.Panel({
        displayClass: "controlPanel",
        defaultControl: panelButtons[3],
    });

    panel.addControls(panelButtons);
    
    //adding toolbar control to the map
    map.addControl(panel);

First, we created an array of buttons from previous post called 'panelButtons'.
Then we instantiated 'panel' object (OpenLayers.Control.Panel) with properties 'displayClass' and 'defaultControl' set. The first one is CSS class of panel's div and the second one is a control that will be activated by default when page loads, in our case it's the 4th one 'simpleTool2Btn'.
Next we added the array to the panel using panel's method addControls(Array).
Last we added our panel as control to our map object using map's method addControl(control object), provided that you have previously instantiated map object with the variable name 'map' (var map = new OpenLayers.Map()).
CSS setup is tedious, but simple enough. Note that for button that have displayClass set to simpleBtn you would have to use .simpleBtnItemInactive{...} and .simpleBtnItemActive{...}. The first class is for button being "idle" or not pressed and the other is when button is activated. This is used only by toggle and tool types of button.
Also note the difference between toggle and tool while using panel on the page. Toggle will stay active even when you switch tools, while only one tool can be activated at the time.

Here's how it should look at the end.

 And here is the entire code (HTML,CSS and JS).Cheers.

Saturday, July 19, 2014

Custom OpenLayers Panel and Buttons part 1

Simply put, buttons in OpenLayers are just divs that when clicked on execute some function, and Panel is just a parent div for buttons with few extra functions.
There are three types of buttons in OpenLayers: Button, Toggle and Tool, and they are represented as constants:

OpenLayers.Control.TYPE_BUTTON
OpenLayers.Control.TYPE_TOGGLE
OpenLayers.Control.TYPE_TOOL

Let's create all of those buttons. I'll start with the most basic type called button.

//this is a simple button
var simpleBtn = new OpenLayers.Control.Button({
 displayClass : "simpleBtn",
 id : "simpleBtn",
 type : OpenLayers.Control.TYPE_BUTTON,
 title : "Click me for awsome msg!",
 trigger : function() {
  var msg = "hello I'm pressed!";
  console.log(msg);
 }
});

Ok, so when we create a button we pass an object as an argument. First we use an inherited property to define a button's div class (displayClass). We will use this later, inside CSS file to set up a nice icon for this button.
Next we set the id property which could be useful if we want to search our map object for this button (map.getControl(id)).
After that we set the type to OpenLayers.Control.TYPE_BUTTON telling OpenLayers to execute trigger function every time we click this button.
The title property is of type string and holds text that will be displayed as tooltip when we hover over this button.
And finally the trigger property holds the actual function that is being executed every time we press our button. Trigger can ether be an anonymous function or can refer to existing functon in our code.

//this is a simple button
var simpleBtn = new OpenLayers.Control.Button({
 displayClass : "simpleBtn",
 id : "simpleBtn",
 type : OpenLayers.Control.TYPE_BUTTON,
 title : "Click me for awsome msg!",
 trigger : triggerFunction,
 }
});
function triggerFunction(){
 console.log("Someone called this function and I think I know who!");
}

Now, let's set a different type of button - the toggle button:

//this is a toggle button
var simpleToggleBtn = new OpenLayers.Control.Button({
 displayClass : "simpleToggleBtn",
 id : "simpleToggleBtn",
 type : OpenLayers.Control.TYPE_TOGGLE,
 title : "Toggle awesomeness on/off",
 eventListeners : {
  'activate' : function() {
   console.log("Awesomeness is on! :D");
  },
  'deactivate' : function() {
   console.log("Awesomeness is off. :(");
  },
 }
});

Let's talk about what's different from our first button. Well, first the type is set to OpenLayers.Control.TYPE_TOGGLE telling OpenLayers that this button has two "states" - the on state (simpleToggleBtn.active ==  true) and the off state (simpleToggleBtn.active == false).
Second, instead of trigger property we have a new one - eventListeners and it's an object with properties named after events, and every time one of those events occurs a proper function will execute. In our case we have two events - 'activate' and 'deactivate'. When we click on our toggle button we activate it, triggering 'activate' event and executing it's function. Toggle button stays active until we click it again at which time a 'deactivate' event occurs and proper function is executed. Same as for trigger, 'activate' and 'deactivate' can hold anonymous function or refer to existing one.

For our last type of a button - the tool button we will actually need two of them. Let's look at the code:

//this is a first tool button
var simpleTool1Btn = new OpenLayers.Control.Button({
 displayClass : "simpleTool1Btn",
 id : "simpleTool1Btn",
 type : OpenLayers.Control.TYPE_TOOL,
 title : "Tool for owning.",
 eventListeners : {
  'activate' : function() {
   console.log("We are now owning. :D");
  },
  'deactivate' : function() {
   console.log("We are owning no longer. :'(");
  },
 }
});

//this is a second tool button
var simpleTool2Btn = new OpenLayers.Control.Button({
 displayClass : "simpleTool2Btn",
 id : "simpleTool2Btn",
 type : OpenLayers.Control.TYPE_TOOL,
 title : "Tool for ruling.",
 eventListeners : {
  'activate' : function() {
   console.log("Our ruling is on! :D");
  },
  'deactivate' : function() {
   console.log("We rule no more. :'(");
  },
 }
});

Right away we see that only difference between toggle and tool button is type property, but it's an important one. You see, when you declare a button with the type property set to OpenLayers.Control.TYPE_TOOL you are telling it's panel to deactivate all other tools when you activate this one. And that's why we need two of them for demonstration purpose. If the simpleTool1Btn is activated, upon activating simpleTool2Btn the previous, simpleTool1Btn will be deactivated.

Next time we will create a panel for our buttons and set up a CSS file to correctly display our panel and it's buttons.

Friday, July 18, 2014

Replace Missing Tiles in OpenLayers 2.13

Say you want to have a custom replacement tile instead of annoying pink tile. Here's a quick and dirty way to do that:

var layer = new OpenLayers.Layer.XYZ("Layer", "tiles/${z}/${x}/${y}.png", {
     tileOptions : {
          onImageError : function() {
               this.setImgSrc('img/noTile.png');
          },
     }
});
Basically what we do here is tell OpenLayers that for each tile (tileOptions) that fails to load (onImageError) to set new url (setImgSrc(url)) which points to our noTile.png tile in the img directory.

Hello World!

This is the very first page on my new blog where you can read my scribbles about programming and related topics. Hope you'll find something useful.

Cheers.