Saturday Jul 23, 2016

Twitter, Codebird, and JavaScript

In my "bower.json" file, I have a dependency set like this:

"codebird-js": "2.6.0"

That enables Codebird to be installed.

Next, I went to apps.twitter.com and created a new application, so that I now have a Consumer Key (API Key) and a Consumer Secret (API Secret).

<script type="text/javascript">
    var cb = new Codebird;
    cb.setConsumerKey(
            "replace-with-consumer-key",
            "replace-with-consumer-secret");
    cb.__call(
            "search_tweets",
            "q=NetBeans",
            function (response) {
                var statuses = response.statuses;
                for (var i = 0; i < statuses.length; i++){
                    var status = statuses[i];
                    var screen_name = status.user.screen_name;
                    var text = status.text;
                    console.log(screen_name + ": " + text);
                } 
            }, true);
</script>

The point of this blog entry is really to come to a point where you can see how to parse Twitter. Above, in bold, is the code needed for that. Printed out into the console you'll now see names/texts of those who have tweeted about NetBeans.

Friday Jul 22, 2016

OAuth and Oracle JET

OAuth is an open protocol to allow secure authorization in a simple and standard method from web, mobile, and desktop applications. Oracle JET includes a helper library for working with OAuth, though not OAuth itself, i.e., Oracle JET does not ship with OAuth. Instead, it provides a helper class that helps you manage OAuth tokens and requests, rather than including the OAuth client libraries that are needed. Also, there is documentation for the OAuth helper library in the Oracle JET Developer Guide, in a chapter named Using oj.OAuth in Your Oracle JET Application.

In your "define" block, you need to include "ojs/ojmodel", since that's where the OAuth class is provided. The OAuth class provides the methods you can use to initialize the oj.OAuth object, verify initialization, and calculate the authorization header based on client credentials or access token.

Once you have included "ojs/model", you initialize "oj.OAuth", as described in the chapter, e.g.:

self.myOAuth = new oj.OAuth('X-Authorization');

When you use the Oracle JET Common Model, you'll find the "oj.Collection.extend" enables you to reference your "oj.OAuth" object. Also see the related JavaScript documentation:

http://www.oracle.com/webfolder/technetwork/jet/jsdocs/oj.OAuth.html

Here's all the code for a real "define" block that includes OAuth for working with Twitter. Take note of the bits in bold below, which are the statements relating to OAuth:

define(['ojs/ojcore', 
        'knockout', 
        'jquery', 
        'ojs/ojmodel', 
        'ojs/ojtable', 
        'ojs/ojcollectiontabledatasource'],
    function (oj, ko, $) {
        function HeaderViewModel() {
            var self = this;
            self.TweetCol = ko.observable();
            self.datasource = ko.observable();
            self.serviceURL = 'https://api.jublo.net/codebird/1.1/search/tweets.json';
            self.myOAuth = new oj.OAuth('X-Authorization');
            self.parseTweet = function (response) {
                return {
                    id_str: response['id_str'],
                    text: response['text'],
                    userName: response['user']['name']
                };
            };
            var Tweet = oj.Model.extend({
                urlRoot: self.serviceURL,
                parse: self.parseTweet,
                idAttribute: 'id_str'
            });
            var myTweet = new Tweet();
            var TweetCollection = oj.Collection.extend({
                url: self.serviceURL + '?q=NetBeans',
                model: myTweet,
                oauth: self.myOAuth
            });
            self.getData = function () {
                self.datasource(null);
                self.TweetCol(new TweetCollection());
                self.myOAuth.setAccessTokenRequest(
                    JSON.parse(sessionStorage.getItem('credentials'))
                );
                self.TweetCol().fetch({
                    success: function () {
                        self.datasource(
                            new oj.CollectionTableDataSource(self.TweetCol())
                        );
                    },
                    error: function (jqXHR, textStatus, errorThrown) {
                        console.log('Error in fetch: ' + textStatus);
                    }
                });
            };
        }
        return new HeaderViewModel();
    }
);

In "main.js", the "credentials.js" file is loaded:

var prop;
$.ajax({
    url: 'js/credentials.json',
    dataType: 'json',
    async: false,
    success: function (data) {
        sessionStorage.setItem('credentials', JSON.stringify(data));
    },
    error: function (req, status, err) {
        console.log('something went wrong', status, err);
    }
});

The "credentials.js" file has this content:

{
    "client_id": "blabla",
    "client_secret": "blabla",
    "bearer_url": "https://api.jublo.net/codebird/oauth2/token",
    "access_token": "blabla"
}

Above, Codebird is used. Codebird is a library that is commonly used to manage OAuth2 connections to Twitter. And, instead of setting up your own code, you can use Codebird's proxy service.

In the "define" block above, notice the "self.getData" at the end, which ties everything together, and is called from the view:

<button data-bind="click: getData, 
                   ojComponent: { 
                       component: 'ojButton', 
                       label: 'Get Data'}">Get Data</button>
<hr>
<table 
    data-bind="ojComponent: {
            component: 'ojTable', 
            data: datasource,
	    columnsDefault: {headerStyle: 'text-align: left; white-space:nowrap;'}, 
            columns:
               [
                  {headerText: 'User ', field: 'userName'},
                  {headerText: 'Text', field: 'text'}
               ]}">
</table>

That's it. A complete sample scenario that uses OAuth with Oracle JET.

Thursday Jul 21, 2016

JBoss Data Virtualization with Oracle JET

I met with Cojan van Ballegooijen who is involved with the Red Hat JBoss Data Virtualization project. Read about that here:

http://www.jboss.org/products/datavirt/overview

I'm interested in setting up a scenario where Oracle JET could provide a dashboard on top of a VDB (virtual database).

Here's the steps we took to get started.

  1. We started by downloading the 6.3.0 Beta of JBoss Data Virtualization: http://developers.redhat.com/products/datavirt/download.

  2. After running "java -jar" on the JAR downloaded above, we had installed the product and had a folder named "EAP-6.4.0".

  3. In the folder "quickstarts/dynamicvdb-datafederation", there's a folder "src/teiidfiles", which we copied into the root, i.e., into the "EAP-6.4.0" folder.

  4. In the folder "standalone/configuration", there's a file named "standalone.xml", where we tweaked the reference to "jboss.dir" so that it pointed to the hardcoded location of the EAP-6.4.0 folder, i.e., there was a problem with slash escaping on Windows of the "jboss.dir" reference and to workaround that we hardcoded the path, for the data source with the jndi-name "java:/accounts-ds".

  5. Then we ran "bin/standalone.bat", the process started, the "teiidfiles" were loaded, and at this location we saw the JSON payload: http://localhost:8080/odata4/Portfolio/Accounts/CUSTOMER?$format=json

OK, great, we have the JSON, which provided the data from the VBD. Once we have JSON, the step to an Oracle JET dashboard is trivial, since Oracle JET has all kinds of hooks for working with JSON.

However, there's one stumbling block at this point and that is that authentication is needed for accessing our data. It seems that Keycloak is needed in this scenario:

https://access.redhat.com/documentation/en/red-hat-jboss-data-virtualization/6.3/security-guide/chapter-11-oauth-based-security-for-odata

That's the next step. Once that's done, then we have here a nice scenario for creating user interfaces on top of virtual databases created via JBoss Data Virtualization.

Tuesday Jul 19, 2016

Company Presentations on Oracle JET with NetBeans IDE

Today I spent some time with Oracle colleagues in presenting Oracle JET to a company in the Netherlands. The company was using a technology stack that included a front-end technology that needs to be modernized for various reasons and Oracle JET was presented to them as the way to bring the front-end of an application into the modern world of HTML5, CSS3, and JavaScript.

Of course, many small demos were done to make the key points of the benefits of Oracle JET. And those demos were all done in NetBeans IDE, with the great Oracle JET Support plugin!

Does your company want to modernize web front-ends? Take a look at Oracle JET, it's all open source and free, and available at http://github.com/oracle/oraclejet. We're doing company presentations on Oracle JET all over the world, if you're interested, let me know!

Thursday Jul 14, 2016

JSX in NetBeans IDE 8.2

JSX is a XML-like syntax extension to ECMAScript without any defined semantics. Many more details about it can be found here:

https://facebook.github.io/jsx/

JSX is popular in the React community which "recommend[s] using JSX because it is a concise and familiar syntax for defining tree structures with attributes. It's more familiar for casual developers such as designers." Many more details about that can be found here:

https://facebook.github.io/react/docs/jsx-in-depth.html

Many NetBeans IDE users have been asking for JSX support in NetBeans IDE, since they are using React:

https://netbeans.org/bugzilla/show_bug.cgi?id=250778

As you can see from the above, the NetBeans team has added parsing and lexing support for JSX over the past few days.

Let's take a look at the result, using this repo as an example project to try out JSX support in NetBeans IDE:

https://github.com/reactjs/react-tutorial

Here's what I see in a very (very very) recent NetBeans IDE build (click to enlarge the image):

Contrast the above to the same file opened in the current release of NetBeans IDE, i.e., NetBeans IDE 8.1, to see the difference:

Great news, isn't it? :-) At this point, don't expect extensive support for JSX or for React. However, as you can see above, at least you can now edit your files without there being error markings everywhere, which made NetBeans IDE impossible to work with when working with JSX.

Wednesday Jul 13, 2016

NetBeans Platform: An Ideal Platform for Scientific Computing

The session catalog for JavaOne 2016 is available here:

https://oracle.rainfocus.com/scripts/catalog/oow16.jsp?event=javaone&search.event=javaone

One of the entries you'll find there is this one: 

Interesting. A NetBeans Platform application that I had never heard of before. It looks like this:

And here's more info about it:

The above comes from here:

https://www.janelia.org/confocal-imagery-management-and-analysis-tools

I'm looking forward to attending this session at JavaOne this year! 

Tuesday Jul 12, 2016

Gallery Demos for JavaScript: Galleria.io

Following on from part 2, in this part we add Galleria.io to our set of dependencies in 'bower.json':

"dependencies": {
    "oraclejet": "2.0.2",
    "galleria": "1.4.2"
}

Here's the source code:

https://github.com/GeertjanWielenga/GalleriaDemos/tree/master/Galleria3-Galleria.io/app

The project structure is as follows:

Since Galleria.io is not an AMD module, we need to shim in the 'require.config':

shim: {
   'jquery': {
       exports: ['jQuery', '$']
   },
   'galleriaio': ['jquery']
}

The end result looks like this:

And, again, a Knockout component is created and used like this:

<div data-bind="component: {name:'galleria', 
    params: {
      uniqueID: '1',
      width: 300,
      height: 300,
      images: [
        'images/galleria1.jpg',
        'images/galleria3.jpg',
        'images/galleria4.jpg'
      ]
    }
}"></div>

Monday Jul 11, 2016

Gallery Demos for JavaScript: JQuery UI Accordion

Continuing from the first part, let's now move towards modularity via Require and data bindings via Knockout. 

Here is the application:

https://github.com/GeertjanWielenga/GalleriaDemos/tree/master/Galleria2-Knockout/app

The project structure is like this, which looks a lot like the structure of an Oracle JET application, though an Oracle JET template was not the starting point of the below. Instead, I started with a plain ordinary HTML/JavaScript application and built up the structure from there, i.e., as a normal JavaScript application:


Here the JQuery UI Accordion component is used, which looks as follows in this case: 

To make sure that the versions of the various libraries work together, instead of getting hold of JQuery, JQuery UI, Require, and Knockout separately, I'm getting hold of all of them at once via Oracle JET in 'bower.json':

"oraclejet": "2.0.2"

Each gallery makes use of a Knockout component created in the project, which is used as follows: 

<div data-bind="component: {name:'galleria', 
    params: {
      uniqueID: '1',
      images: [
        'images/galleria1.jpg',
        'images/galleria3.jpg',
        'images/galleria4.jpg'
      ]
    }
}"></div>

In the next part, we'll look at a different gallery component and set up the same kind of project structure to see how things work there.

Sunday Jul 10, 2016

Gallery Demos for JavaScript: PrimeUI Galleria

I'm looking at different image gallery components as examples of how to work with them in the context of Oracle JET. Also, these scenarios are example of how to migrate from non-Oracle JET applications to Oracle JET applications.

Here's the first, making use of the PrimeUI Galleria component:

https://github.com/GeertjanWielenga/GalleriaDemos/tree/master/Galleria1-Default/app

The structure of the application is like this: 


Here's how the component looks:

In the "bower.json" file, there is a single dependency:  

"primeui": "4.1.12"

In fact, this scenario is a plain normal JavaScript scenario that makes use of PrimeUI. No modularity, etc, just plain simple PrimeUI.

To get from the above scenario to an Oracle JET application, you'd need to include Require (for migration modularity) and Knockout (for migration to Knockout components and data bindings). That's the topic of the next blog entry.

Friday Jul 08, 2016

Timeline in Oracle JET

Let's take the "ojTimeline" component from the Oracle JET component library, as described here in the Oracle JET Cookbook, while taking note of the format of the related JSON file here. Then, downloading that file into our Oracle JET application and changing the details in the JSON file, let's recreate the NetBeans Roadmap in Oracle JET, with this result:

Here's the business logic in JavaScript, i.e., the "define" block, including a selection listener:

define(['text!../../seriesOneData.json', 'knockout', 'ojs/ojtimeline'],
    function (file, ko) {
        function mainContentViewModel() {
            var self = this;
            self.selected = ko.observable("Nothing is selected.");
            var content = JSON.parse(file);
            self.series = ko.observableArray(content)();
            self.optionChangeListener = function (event, data) {
                for (var i = 0; i < content.length; i++) {
                    if (content[i].id == data['value']) {
                        self.selected(content[i].title);
                    }
                }
            };
        }
        return new mainContentViewModel();
    });

And here's the HTML view that renders the above:

<div data-bind="ojComponent:{
    component: 'ojTimeline',
            majorAxis: {scale: 'years'},
            minorAxis: {scale: 'quarters'},
            start: new Date('Oct 1, 2013').toISOString(),
            end: new Date('Oct 31, 2016').toISOString(),
            optionChange: optionChangeListener,
            selectionMode: 'single',
            series: [{ 
                id: 's1',
                emptyText: 'No Data.',
                items: series,
                label: 'NetBeans Roadmap'
            }],
}" style="width: '100%'; height: 250px"></div>
<hr>
<h2>Selected: <span data-bind="text: selected"></span></h2>

Thursday Jul 07, 2016

Tag Cloud in Oracle JET

Here in the Oracle JET Cookbook the Oracle JET Tag Cloud is described. Here's the JSON file that is used there, which I have put in the "public_html" folder of my project.

What we'll create is the same as in the Cookbook, except we'll parse the JSON file with "JSON.parse" and we'll use a "define" block.


Here's a 'define' block for working with the "ojtagcloud" component:

define(['text!../../socialNetworks.json', 'ojs/ojtagcloud'],
    function (file) {
        function mainContentViewModel() {
            var self = this;
            self.tags = [];
            var content = JSON.parse(file);
            for (var i = 0; i < content.length; i++) {
                var network = content[i];
                self.tags.push({
                    id: network["id"],
                    label: network["id"],
                    value: network["total"],
                    shortDesc: network["id"] + ': ' + network["total"] + '%'
                });
            }
        }
        return new mainContentViewModel();
    });

Then here's the view:

<p style="font-weight:bold;text-align:center;">
  Social Networks Used by US Internet Users (Ages 14-54)
</p>
<div data-bind="ojComponent:{
        component: 'ojTagCloud',
                layout: 'cloud',
                items: tags
    }" >
</div>

Wednesday Jul 06, 2016

JQuery UI Datepicker Widget and Oracle JET

The jQuery UI Datepicker is a popular component. Let's integrate it into an Oracle JET application. Oracle JET is an open application architecture, together with a set of components, based on open source libraries, providing a logical framework within which components such as the jQuery UI Datepicker can be organized:

For background on this topic, see this YouTube clip by JB Brock:

https://www.youtube.com/watch?v=XcPcaSbaHFg

Take the following steps:

  1. Get the 'datepicker.js', from somewhere. For example, use Bower to add 'jquery-ui' to your project.

  2. In 'main.js', point to the folder where all the 'ui' components are found:
    'jqueryui': 'libs/jquery-ui/ui/', 
  3. Reference the CSS file below in your 'index.html':
    <link rel="stylesheet" 
        href=" //code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css"/>
    
  4. In your viewModel, add the 'datepicker' component in the 'define' block, while creating an observable property to hold the selected date and a callback function to handle selection:
    define(['ojs/ojcore', 'knockout', 'jqueryui/datepicker'],
        function (oj, ko) {
            function mainContentViewModel() {
                var self = this;
                self.selectedDate = ko.observable();
                self.dateSelector = function (dateText, inst) {
                    self.selectedDate(dateText);
                };
            }
            return new mainContentViewModel();
        });
  5. In your view, use the 'datepicker' component (while making sure to use the 'jqueryUI' binding, as pointed out in the YouTube clip above), using the "onSelect" option provided by the datepicker as a link to the view above, while providing a span element to display the selected date:
    <div 
         data-bind="jqueryUI: {
             component: 'datepicker', onSelect: dateSelector
         }">
    </div>
    <hr>
    Selected date: <span data-bind="text: selectedDate"></span>

That's it! Now you should see the datepicker and you should also see that the selected date is shown too.

Helpful links:

Tuesday Jul 05, 2016

Plotting Data on World Maps with Oracle JET

Our requirement is to use Oracle JET to show data on a world map, e.g., the number of employees in our organization working in various countries around the world. Below you see an example—three different ranges represented by colors on the map:

To get to the above point, let's start with the simplest imaginable world map scenario with Oracle JET's built-in maps for ojThematicMap.

Here's the view:

<div id='thematicMap-container'>
    <div id='thematicMap1' data-bind="ojComponent:{
            component: 'ojThematicMap',
                basemap: 'world',
                areaLayers: layers
        }" 
         style="height:500px;width:100%">
    </div>
</div>

Here's the viewModel:

define(['ojs/ojcore',
    'knockout',
    'ojs/ojthematicmap'],
        function (oj, ko) {
            function mainContentViewModel() {
                var self = this;
                self.layers = [{layer: 'countries'}];
            }
            return new mainContentViewModel();
        });

And here's the map that results from the simple code above:

However, you're more than likely to be in a situation where you're getting data from somewhere, e.g., XML or JSON, with info that you'd like to display on the map.

Here's a GeoJSON file that we can use as the starting point of our scenario:

https://raw.githubusercontent.com/johan/world.geo.json/master/countries.geo.json

We'll do the same thing as the earlier blog entry about Brazil, i.e., include the file above into your application, as explained earlier. Now, open the file, and add some more data into it, imagining that this data needs to be visualized on the map. The data you add needs to be in the "properties" section of some/each of the entries in the file. Below, you see that I have added "employees:2000" to the entry for United States of America. Do the same for a few of the other countries, i.e., add some random data into various properties sections to simulate some additional data that we want to be able to work with:

Now, we're in a scenario very similar to this one:

http://www.oracle.com/webfolder/technetwork/jet/uiComponents-thematicMap-default.html

Adapting our scenario to the sample above, here's the view:

<div id='thematicmap-container'>
    <div id='thematicmap1'
         data-bind="ojComponent:{
            component: 'ojThematicMap',
                basemap: 'Foo',
                mapProvider: mapProvider,
                areaLayers: layers
                }"
                 style="width:100%; height:400px;">
    </div>
    <div id='legend1' data-bind="ojComponent: {
      component: 'ojLegend',
          halign: 'center',
          orientation: 'horizontal',
          title: 'No. of Employees',
          titleHalign: 'center',
          titleStyle: 'font-size:14px;font-weight:bold;',
          textStyle: 'font-size:14px;',
          sections: legendSections
          }"
           style="width:100%; height:50px;">
  </div>
</div>

And here's the viewModel:

define(['text!../countries.geo.json',
    'ojs/ojcore',
    'knockout',
    'ojs/ojthematicmap', 'ojs/ojlegend'],
        function (geo, oj, ko) {
            function mainContentViewModel() {
                var self = this;
                self.mapProvider = {
                    geo: JSON.parse(geo),
                    propertiesKeys: {
                        id: 'name',
                        longLabel: 'name'
                    }
                };
                self.legendSections = [{items: [
                            {text: "0-500", color: '#FF0000'},
                            {text: "501-1000", color: '#0000CC'},
                            {text: "1001-2000", color: '#3AA54F'}
                        ]}];
                var getEmployeeColor = function (employees) {
                    if (employees <= 500)
                        return '#FF0000';
                    else if (employees <= 1000)
                        return '#0000CC';
                    else if (employees <= 2000)
                        return '#3AA54F';
                };
                var getStateId = function (state, stateIdMap) {
                    for (var id in stateIdMap) {
                        if (stateIdMap[id] == state)
                            return id;
                    }
                };
                var getEmployeeData = function (dataContext) {
                    var areaData = [];
                    var features = JSON.parse(geo).features;
                    for (var i = 0; i < features.length; i++) {
                        var name = features[i]["properties"]["name"];
                        var employees = features[i]["properties"]["employees"];
                        areaData.push({
                            id: 'a1',
                            location: getStateId(name, dataContext.ids),
                            color: getEmployeeColor(employees)
                        });
                    }
                    return areaData;
                };
                self.layers = [
                    {
                        layer: 'countries',
                        areaDataLayer: {id: 'adl1', areas: getEmployeeData}
                    }];
            }
            return new mainContentViewModel();
        });

The trickiest bit above is the parsing of the JSON. Take a look, in particular, at the piece of code in bold above.

Monday Jul 04, 2016

YouTube: Oracle JET, Maps, Java EE, and NetBeans IDE

During JavaOne Latin America, last week, Yolande from OTN did a NightHacking interview with me about Oracle JET.

Here it is, in 10 minutes, covering Oracle JET, Java EE, maps, the ojThematicMap component in Oracle JET, and NetBeans IDE:

Related reading:

Saturday Jul 02, 2016

Key Promoter Plugin for NetBeans IDE 8.1

I've reworked the Key Promoter plugin a bit.

http://plugins.netbeans.org/plugin/55751/key-promoter

The status bar (assuming you're using NetBeans IDE 8.1 and have installed the plugin for NetBeans IDE 8.1) now displays the keyboard shortcut of the most recently used action. In the screenshot below, notice the green display area in the status bar, i.e., at the bottom of the screenshot below, which is provided by the plugin, displaying info about the most recently used action:

However, a few actions are not displayed, because they're not logged when invoked, something which needs to be fixed, i.e., the fact that these are not logged into 'uigestures' means that they cannot be picked up by the plugin:

  • Alt-Shift-Up/Down (Move Line Up/Down) 
  • Ctrl-Shift-Up/Down (Copy Line Up/Down) 
  • Ctrl-Shift-R (Toggle Rectangular Selection)

Probably others too. Would be great to hear about any actions that aren't picked up by the plugin!

The sources of the plugin are here:

https://github.com/GeertjanWielenga/NetBeansKeyPromoter

 

Friday Jul 01, 2016

Integrating iTunes into Oracle JET

Here's a search string for iTunes:

https://itunes.apple.com/us/rss/toppaidapplications/limit=10/genre=6014/json

Let's integrate that into an Oracle JET application, with this result:

After a bit of fiddling with the parsing of the JSON, this is how I built up the table above.

Here's the view:

<table data-bind="ojComponent: {component: 'ojTable',
    data: dataSource,
    columns: [
        {headerText: 'Name', field: 'name'},
        {headerText: 'Price', field: 'price'}
    ]
        }">
</table>

Here's the viewModel: 

define(['ojs/ojcore', 'knockout', 'ojs/ojtable'
], function (oj, ko) {
    function homeContentViewModel() {
        var self = this;
        self.data = ko.observableArray();
        $.getJSON("https://itunes.apple.com/us/rss/toppaidapplications/limit=10/genre=6014/json").
                then(function (json) {
                    var entry = json.feed.entry;
                    $.each(entry, function () {
                        self.data.push({
                            name: this['im:name'].label,
                            price: this['im:price'].label
                        });
                    });
                });
        self.dataSource = new oj.ArrayTableDataSource(
                self.data,
                {idAttribute: 'name'}
        );
    }
    return homeContentViewModel;
});

Next steps would be to replace the hardcoded search string with some UI elements so that the user can specify the search string at runtime.

A reference that helped me with the above:

http://stackoverflow.com/questions/4925760/selecting-a-json-object-with-a-colon-in-the-key

Wednesday Jun 29, 2016

Integrating Brazil into Oracle JET

Using the info from yesterday, it's easy to integrate Brazil into Oracle JET:

To get started, get the brazil-states.geojson file and put it in your project as described yesterday. Below, the file has been renamed to "brazil.json".

Then here's your viewModel:

define(['text!../brazil.json',
        'ojs/ojcore',
        'knockout',
        'ojs/ojthematicmap'],
        function (geo, oj, ko) {
            function mainContentViewModel() {
                var self = this;
                self.mapProvider = {
                    geo: JSON.parse(geo),
                    propertiesKeys: {
                        id: 'name',
                        shortLabel: 'name',
                        longLabel: 'sigla'
                    }
                };
            }
            return new mainContentViewModel();
        });

And the view: 

<h1>Brazil Map</h1>
<div id='thematicmap1'
     data-bind="ojComponent:{
    component: 'ojThematicMap',
        basemap: 'Foo',
        mapProvider: mapProvider,
         areaLayers:
          [{
            layer: 'Bar',
            areaDataLayer: {
                id: 'adl1',
                areas: [
                    {id: 'a1', 'location': 'Tocantins', color: 'rgb(255, 181, 77)'},
                    {id: 'a2', 'location': 'Amazonas', color: 'rgb(255, 120, 90)'},
                    {id: 'a3', 'location': 'Mato Grosso', color: 'rgb(120, 30, 87)'},
                    {id: 'a4', 'location': 'Bahia', color: 'rgb(20, 80, 120)'}
                ]}
          }]
        }"
     style="width:100%; height:600px;"/>

Take note of "Foo" and "Bar" above, i.e., these labels can be anything you like, they're just there as identifiers. The same is true for the "id" in the "areaDataLayer". The colors above are just an example of what you can do, i.e., they don't signify anything in this example. 

All this is pretty cool, isn't it?

Tuesday Jun 28, 2016

GeoJSON and Oracle JET Maps

In the latest Oracle JET release notes, you'll find the Oracle JET maps now support GeoJSON. There's even a complete sample in the Oracle JET Cookbook

Let's see how to set that up within an Oracle JET module, rather than via the require block, which is how it is defined in the Oracle JET Cookbook. 

  1. Get the JSON file from the sample above here. Put it into your project structure, somewhere, e.g., here in the QuickStart Basic:



  2. In 'requirejs.config', in "main.js", include "proj4js", which is part of Oracle JET 2.0.2, read about it here:
    'proj4': 'libs/proj4js/dist/proj4'
  3. Define "home.js", or one of your other JET module's viewModels, as follows, slightly restructured from the Oracle JET Cookbook:
    define(['text!../uk_epsg27700.json',
            'proj4',
            'ojs/ojcore',
            'knockout',
            'ojs/ojthematicmap'],
            function (geo, proj4, oj, ko) {
                function mainContentViewModel() {
                    var self = this;
                    self.mapProvider = {
                        geo: JSON.parse(geo),
                        propertiesKeys: {
                            id: 'id',
                            shortLabel: 'sLabel',
                            longLabel: 'lLabel'
                        }
                    };
                    var storeLocations = [
                        {'long': 0.1278, 'lat': 51.5074, 'city': 'London'},
                        {'long': -1.257677, 'lat': 51.752022, 'city': 'Oxford'},
                        {'long': -0.460739, 'lat': 52.136436, 'city': 'Bedford'},
                        {'long': -7.318268, 'lat': 55.006763, 'city': 'Londonderry'},
                        {'long': -8.630498, 'lat': 52.668018, 'city': 'Limerick'},
                        {'long': -6.251495, 'lat': 53.353584, 'city': 'Dublin'}
                    ];
                    this.cities = [];
                    for (var i = 0; i < storeLocations.length; i++) {
                        var store = storeLocations[i];
                        // Call proj4js API with the proj4 projection mapping for EPSG:2770 and the long/lat coordinates.
                        var coords = proj4("+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs", [store.long, store.lat]);
                        this.cities.push({id: store.city, x: coords[0], y: coords[1], shortDesc: store.city});
                    }
    
                }
                return new mainContentViewModel();
            });
    
  4. Define "home.html", or one of your other JET module's view, as follows, all from the Oracle JET Cookbook:
    <h1>Home Content Area</h1>
    <div id='thematicmap1'
    data-bind="ojComponent:{
        component: 'ojThematicMap',
            basemap: 'unitedKingdom',
            mapProvider: mapProvider,
            areaLayers:
              [{
                layer: 'countries',
                areaDataLayer: {
                    id: 'adl1', 
                    areas: [{id: 'a1', 'location': 'GBR', color: 'rgb(255, 181, 77)'}]}
              }],
            pointDataLayers: [{id: 'pdl1', markers: cities}]
            }"
        style="width:100%; height:600px;"/>

That's it, you're done. Will be exploring this functionality more in upcoming blog entries.

Saturday Jun 18, 2016

Structuring ECMAScript 6 Modules via Babel and Webpack

Continuing from yesterday, since transpilation of ECMAScript 6 to ECMAScript 5 is needed because of the current state of browsers, and we've chosen Babel for that, and since we're using Webpack to bundle our generated ECMAScript 5 files... what would be a logical way to structure our source code so that you can easily find the code with which you need to work?

Let me suggest the following entries in package.json:

"scripts": {
    "babel": "babel public_html/js/src --presets babel-preset-es2015 --out-dir public_html/js/gen",
    "webpack": "webpack public_html/js/gen/main.js public_html/js/bundle.js"
},

What the above gives you is this:

In the "gen" folder is the output of Babel. And 'bundle.js', in the root of the "js" folder, is the result of Webpack's bundling process. They're green above because I haven't (and won't) commit them into my repo, they're simply generated whenever I need them to be. And that's a clear structure and let's me easily see what's what.

Does anyone have other/different/complementary/conflicting ideas about this structure? 

Friday Jun 17, 2016

ECMAScript 6, Modules, Babel, Webpack, and NetBeans IDE

I've been talking about modularity via Require.js in enterprise JavaScript applications for some time (because Oracle JET bundles Require.js as its modularity solution). ECMAScript 6 provides its own built-in module system and, since NetBeans IDE now provides ECMAScript 6 support (in development builds), let's rewrite my Require.js application to use ECMAScript 6 modularity.

The complete sample discussed below is here:

https://github.com/GeertjanWielenga/RequireJSSamples/tree/master/ECMAScript6Sales

Handily, you can compare the ECMAScript 6 sample above to the Require.js implementation:

https://github.com/GeertjanWielenga/RequireJSSamples/tree/master/ModularSales

...as well as the non-modular Sales application:

https://github.com/GeertjanWielenga/RequireJSSamples/tree/master/SimpleSales

Here's 'main.js':

import { buyThing } from './buyer';
name = 'John Smith';
console.log(name + " enters the system");
var result = buyThing(name);
console.log("sale success " + result);

In NetBeans, the above looks as follows:

Take note that there's the "import" keyword above, enabling me to import "buyThing" from 'buyer.js', since here there's an "export" keyword:

import { verifyName } from './authenticator';
import { sendThing } from './thing';
import { sendApology } from './thing';
export function buyThing(name) {
console.log(name + " is trying to buy"); var verified = verifyName(name); if(verified){ sendThing(name); } else { sendApology(name); } return verified; }

In NetBeans, the above looks as follows:

Notice that there are three imports above, the first of which is for 'authenticator.js', which is below...

export function verifyName(name) {
    var requiredNameLength = 1;
    console.log("authenticating " + name);
    return name.length > requiredNameLength;
}

...and here's the above in NetBeans...

...and the other two are for for 'thing.js':

export function sendThing(name){
    console.log("send thing to " + name);
}
export function sendApology(name){
    console.log("say sorry to " + name);
}

Here's the above in NetBeans:

In my 'package.json', I'm using Babel and Webpack: 

"scripts": {
    "babel": "babel public_html/js/src --presets babel-preset-es2015 --out-dir public_html/js",
    "webpack": "webpack public_html/js/main.js public_html/js/bundle.js"
},
"devDependencies": {
  "babel-cli": "^6.10.1",
  "babel-preset-es2015": "^6.9.0",
  "webpack": "^1.8.5"
}

You'll now have this:

You can run "npm install" directly in NetBeans:

You can run Babel and Webpack directly in NetBeans:

When I run Babel, the JavaScript files are transpiled to ECMAScript 5, since that's what browsers support right now. When Webpack is used, the entire application is bundled into "bundle.js", which avoids problems with the "require" keyword that you get from Babel transpilation.

Now, I refer to that one single file, i.e., "bundle.js", that you see above, in my "index.html" file.

Related reading:

About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Categories
Archives
« July 2016
SunMonTueWedThuFriSat
     
3
9
15
16
17
18
20
24
25
26
27
28
29
30
31
      
Today