ONOS-3263 : Initial cut of Reference App, consolidated from UI archetype overlay sample code.

Change-Id: Ifffec2ba95de0f1386c630fdc03ed48738492257
diff --git a/uiref/src/main/resources/app/view/uiRefTable/uiRefTable.js b/uiref/src/main/resources/app/view/uiRefTable/uiRefTable.js
new file mode 100644
index 0000000..70a082e
--- /dev/null
+++ b/uiref/src/main/resources/app/view/uiRefTable/uiRefTable.js
@@ -0,0 +1,141 @@
+// js for UI Reference App table view
+(function () {
+    'use strict';
+
+    // injected refs
+    var $log, $scope, fs, wss;
+
+    // constants
+    var detailsReq = 'uiRefTableDetailsRequest',
+        detailsResp = 'uiRefTableDetailsResponse',
+        pName = 'ov-ui-ref-table-item-details-panel',
+
+        propOrder = ['id', 'label', 'code'],
+        friendlyProps = ['Item ID', 'Item Label', 'Special Code'];
+
+
+    function addProp(tbody, index, value) {
+        var tr = tbody.append('tr');
+
+        function addCell(cls, txt) {
+            tr.append('td').attr('class', cls).html(txt);
+        }
+        addCell('label', friendlyProps[index] + ' :');
+        addCell('value', value);
+    }
+
+    function populatePanel(panel) {
+        var title = panel.append('h3'),
+            tbody = panel.append('table').append('tbody');
+
+        title.text('Item Details');
+
+        propOrder.forEach(function (prop, i) {
+            addProp(tbody, i, $scope.panelDetails[prop]);
+        });
+
+        panel.append('hr');
+        panel.append('h4').text('Comments');
+        panel.append('p').text($scope.panelDetails.comment);
+    }
+
+    function respDetailsCb(data) {
+        $scope.panelDetails = data.details;
+        $scope.$apply();
+    }
+
+    angular.module('ovUiRefTable', [])
+        .controller('OvUiRefTableCtrl',
+        ['$log', '$scope', 'TableBuilderService',
+            'FnService', 'WebSocketService',
+
+            function (_$log_, _$scope_, tbs, _fs_, _wss_) {
+                $log = _$log_;
+                $scope = _$scope_;
+                fs = _fs_;
+                wss = _wss_;
+
+                var handlers = {};
+                $scope.panelDetails = {};
+
+                // details response handler
+                handlers[detailsResp] = respDetailsCb;
+                wss.bindHandlers(handlers);
+
+                // custom selection callback
+                function selCb($event, row) {
+                    if ($scope.selId) {
+                        wss.sendEvent(detailsReq, { id: row.id });
+                    } else {
+                        $scope.hidePanel();
+                    }
+                    $log.debug('Got a click on:', row);
+                }
+
+                // TableBuilderService creating a table for us
+                tbs.buildTable({
+                    scope: $scope,
+                    tag: 'uiRefTable',
+                    selCb: selCb
+                });
+
+                // cleanup
+                $scope.$on('$destroy', function () {
+                    wss.unbindHandlers(handlers);
+                    $log.log('OvUiRefTableCtrl has been destroyed');
+                });
+
+                $log.log('OvUiRefTableCtrl has been created');
+            }])
+
+        .directive('ovUiRefTableItemDetailsPanel', ['PanelService', 'KeyService',
+            function (ps, ks) {
+                return {
+                    restrict: 'E',
+                    link: function (scope, element, attrs) {
+                        // insert details panel with PanelService
+                        // create the panel
+                        var panel = ps.createPanel(pName, {
+                            width: 200,
+                            margin: 20,
+                            hideMargin: 0
+                        });
+                        panel.hide();
+                        scope.hidePanel = function () { panel.hide(); };
+
+                        function closePanel() {
+                            if (panel.isVisible()) {
+                                $scope.selId = null;
+                                panel.hide();
+                                return true;
+                            }
+                            return false;
+                        }
+
+                        // create key bindings to handle panel
+                        ks.keyBindings({
+                            esc: [closePanel, 'Close the details panel'],
+                            _helpFormat: ['esc']
+                        });
+                        ks.gestureNotes([
+                            ['click', 'Select a row to show item details']
+                        ]);
+
+                        // update the panel's contents when the data is changed
+                        scope.$watch('panelDetails', function () {
+                            if (!fs.isEmptyObject(scope.panelDetails)) {
+                                panel.empty();
+                                populatePanel(panel);
+                                panel.show();
+                            }
+                        });
+
+                        // cleanup on destroyed scope
+                        scope.$on('$destroy', function () {
+                            ks.unbindKeys();
+                            ps.destroyPanel(pName);
+                        });
+                    }
+                };
+            }]);
+}());