Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2015 Open Networking Laboratory |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | /* |
| 18 | ONOS GUI -- Widget -- Button Service |
| 19 | */ |
| 20 | (function () { |
| 21 | 'use strict'; |
| 22 | |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 23 | // injected refs |
Bri Prebilic Cole | 9a5e006 | 2015-05-11 17:20:57 -0700 | [diff] [blame] | 24 | var $log, $rootScope, fs, is, tts; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 25 | |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 26 | // configuration |
Bri Prebilic Cole | 258f046 | 2015-02-25 14:48:50 -0800 | [diff] [blame] | 27 | var btnSize = 25, |
| 28 | btnPadding = 4; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 29 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 30 | |
| 31 | // === Helper Functions |
| 32 | |
| 33 | function divExists(div, msg) { |
| 34 | if (!div) { |
| 35 | $log.warn('div undefined (' + msg + ')'); |
| 36 | } |
| 37 | return !!div; |
| 38 | } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 39 | |
| 40 | function createDiv(div, cls, id) { |
| 41 | return div.append('div') |
| 42 | .classed(cls, true) |
| 43 | .attr('id', id); |
| 44 | } |
| 45 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 46 | function noop() {} |
| 47 | |
| 48 | function buttonWidth() { |
| 49 | return btnSize + 2 * btnPadding; |
| 50 | } |
| 51 | |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 52 | function addTooltip(elem, tooltip) { |
| 53 | elem.on('mouseover', function () { tts.showTooltip(this, tooltip); }); |
| 54 | elem.on('mouseout', function () { tts.cancelTooltip(this); }); |
Bri Prebilic Cole | 9a5e006 | 2015-05-11 17:20:57 -0700 | [diff] [blame] | 55 | $rootScope.$on('$routeChangeStart', function () { |
| 56 | tts.cancelTooltip(elem.node()); |
| 57 | }); |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 58 | } |
| 59 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 60 | |
| 61 | // === BUTTON ================================================= |
| 62 | |
| 63 | // div is where to put the button (d3.selection of a DIV element) |
| 64 | // id should be globally unique |
| 65 | // gid is glyph ID (from Glyph Service) |
| 66 | // cb is callback function on click |
| 67 | // tooltip is text for tooltip |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 68 | function button(div, id, gid, cb, tooltip) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 69 | if (!divExists(div, 'button')) return null; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 70 | |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 71 | var btnDiv = createDiv(div, 'button', id), |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 72 | cbFnc = fs.isF(cb) || noop; |
| 73 | |
Bri Prebilic Cole | 5000a75 | 2015-02-23 17:20:53 -0800 | [diff] [blame] | 74 | is.loadIcon(btnDiv, gid, btnSize, true); |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 75 | if (tooltip) { addTooltip(btnDiv, tooltip); } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 76 | |
| 77 | btnDiv.on('click', cbFnc); |
| 78 | |
| 79 | return { |
| 80 | id: id, |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 81 | width: buttonWidth |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 82 | } |
| 83 | } |
| 84 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 85 | |
| 86 | // === TOGGLE BUTTON ========================================== |
| 87 | |
| 88 | // div is where to put the button (d3.selection of a DIV element) |
| 89 | // id should be globally unique |
| 90 | // gid is glyph ID (from Glyph Service) |
| 91 | // initState is whether the toggle is on or not to begin |
| 92 | // cb is callback function on click |
| 93 | // tooltip is text for tooltip |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 94 | function toggle(div, id, gid, initState, cb, tooltip) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 95 | if (!divExists(div, 'toggle button')) return null; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 96 | |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 97 | var sel = !!initState, |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 98 | togDiv = createDiv(div, 'toggleButton', id), |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 99 | cbFnc = fs.isF(cb) || noop; |
| 100 | |
Bri Prebilic Cole | 5000a75 | 2015-02-23 17:20:53 -0800 | [diff] [blame] | 101 | is.loadIcon(togDiv, gid, btnSize, true); |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 102 | togDiv.classed('selected', sel); |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 103 | if (tooltip) { addTooltip(togDiv, tooltip); } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 104 | |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 105 | function _toggle(b, nocb) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 106 | sel = (b === undefined) ? !sel : !!b; |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 107 | togDiv.classed('selected', sel); |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 108 | nocb || cbFnc(sel); |
| 109 | } |
| 110 | |
| 111 | // toggle the button state without invoking the callback |
| 112 | function toggleNoCb() { |
| 113 | _toggle(undefined, true); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 114 | } |
| 115 | |
| 116 | togDiv.on('click', _toggle); |
| 117 | |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 118 | return { |
| 119 | id: id, |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 120 | width: buttonWidth, |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 121 | selected: function () { return sel; }, |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 122 | toggle: _toggle, |
| 123 | toggleNoCb: toggleNoCb |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 124 | } |
| 125 | } |
| 126 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 127 | |
| 128 | // === RADIO BUTTON SET ======================================= |
| 129 | |
| 130 | |
| 131 | // div is where to put the button (d3.selection of a DIV element) |
| 132 | // id should be globally unique |
| 133 | // rset is an array of button descriptors of the following form: |
| 134 | // { |
| 135 | // gid: glyphId, |
| 136 | // tooltip: tooltipText, |
| 137 | // cb: callbackFunction |
| 138 | // } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 139 | function radioSet(div, id, rset) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 140 | if (!divExists(div, 'radio button set')) return null; |
| 141 | |
| 142 | if (!fs.isA(rset) || !rset.length) { |
| 143 | $log.warn('invalid array (radio button set)'); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 144 | return null; |
| 145 | } |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 146 | |
| 147 | var rDiv = createDiv(div, 'radioSet', id), |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 148 | rads = [], |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 149 | idxByKey = {}, |
| 150 | currIdx = 0; |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 151 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 152 | function rsetWidth() { |
| 153 | return ((btnSize + btnPadding) * rads.length) + btnPadding; |
| 154 | } |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 155 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 156 | function rbclick() { |
| 157 | var id = d3.select(this).attr('id'), |
| 158 | m = /^.*-(\d+)$/.exec(id), |
| 159 | idx = Number(m[1]); |
| 160 | |
| 161 | if (idx !== currIdx) { |
| 162 | rads[currIdx].el.classed('selected', false); |
| 163 | currIdx = idx; |
| 164 | rads[currIdx].el.classed('selected', true); |
| 165 | invokeCurrent(); |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 166 | } |
| 167 | } |
| 168 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 169 | // { |
| 170 | // gid: gid, |
| 171 | // tooltip: ..., (optional) |
| 172 | // key: ..., (optional) |
| 173 | // cb: cb |
| 174 | // id: ... (added by us) |
| 175 | // index: ... (added by us) |
| 176 | // } |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 177 | |
| 178 | rset.forEach(function (btn, index) { |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 179 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 180 | if (!fs.isO(btn)) { |
| 181 | $log.warn('radio button descriptor at index ' + index + |
| 182 | ' not an object'); |
| 183 | return; |
| 184 | } |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 185 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 186 | var rid = id + '-' + index, |
| 187 | initSel = (index === 0), |
| 188 | rbdiv = createDiv(rDiv, 'radioButton', rid); |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 189 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 190 | rbdiv.classed('selected', initSel); |
| 191 | rbdiv.on('click', rbclick); |
| 192 | is.loadIcon(rbdiv, btn.gid, btnSize, true); |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 193 | if (btn.tooltip) { addTooltip(rbdiv, btn.tooltip); } |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 194 | angular.extend(btn, { |
| 195 | el: rbdiv, |
| 196 | id: rid, |
| 197 | cb: fs.isF(btn.cb) || noop, |
| 198 | index: index |
| 199 | }); |
| 200 | |
| 201 | if (btn.key) { |
| 202 | idxByKey[btn.key] = index; |
| 203 | } |
| 204 | |
| 205 | rads.push(btn); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 206 | }); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 207 | |
| 208 | |
| 209 | function invokeCurrent() { |
| 210 | var curr = rads[currIdx]; |
| 211 | curr.cb(curr.index, curr.key); |
| 212 | } |
| 213 | |
| 214 | function selected(x) { |
| 215 | var curr = rads[currIdx], |
| 216 | idx; |
| 217 | |
| 218 | if (x === undefined) { |
| 219 | return curr.key || curr.index; |
| 220 | } else { |
| 221 | idx = idxByKey[x]; |
| 222 | if (idx === undefined) { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 223 | $log.warn('no radio button with key:', x); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 224 | } else { |
| 225 | selectedIndex(idx); |
| 226 | } |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | function selectedIndex(x) { |
| 231 | if (x === undefined) { |
| 232 | return currIdx; |
| 233 | } else { |
| 234 | if (x >= 0 && x < rads.length) { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 235 | if (currIdx !== x) { |
| 236 | currIdx = x; |
| 237 | invokeCurrent(); |
| 238 | } else { |
| 239 | $log.warn('current index already selected:', x); |
| 240 | } |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 241 | } else { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 242 | $log.warn('invalid radio button index:', x); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 243 | } |
| 244 | } |
| 245 | } |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 246 | |
| 247 | return { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 248 | width: rsetWidth, |
| 249 | selected: selected, |
| 250 | selectedIndex: selectedIndex |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 251 | } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 252 | } |
| 253 | |
Bri Prebilic Cole | 258f046 | 2015-02-25 14:48:50 -0800 | [diff] [blame] | 254 | |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 255 | angular.module('onosWidget') |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 256 | .factory('ButtonService', |
Bri Prebilic Cole | 9a5e006 | 2015-05-11 17:20:57 -0700 | [diff] [blame] | 257 | ['$log', '$rootScope', 'FnService', 'IconService', 'TooltipService', |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 258 | |
Bri Prebilic Cole | 9a5e006 | 2015-05-11 17:20:57 -0700 | [diff] [blame] | 259 | function (_$log_, _$rootScope_, _fs_, _is_, _tts_) { |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 260 | $log = _$log_; |
Bri Prebilic Cole | 9a5e006 | 2015-05-11 17:20:57 -0700 | [diff] [blame] | 261 | $rootScope = _$rootScope_; |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 262 | fs = _fs_; |
| 263 | is = _is_; |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 264 | tts = _tts_; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 265 | |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 266 | return { |
| 267 | button: button, |
| 268 | toggle: toggle, |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 269 | radioSet: radioSet |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 270 | }; |
| 271 | }]); |
| 272 | |
| 273 | }()); |