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 | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 24 | var $log, 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); }); |
| 55 | } |
| 56 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 57 | |
| 58 | // === BUTTON ================================================= |
| 59 | |
| 60 | // div is where to put the button (d3.selection of a DIV element) |
| 61 | // id should be globally unique |
| 62 | // gid is glyph ID (from Glyph Service) |
| 63 | // cb is callback function on click |
| 64 | // tooltip is text for tooltip |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 65 | function button(div, id, gid, cb, tooltip) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 66 | if (!divExists(div, 'button')) return null; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 67 | |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 68 | var btnDiv = createDiv(div, 'button', id), |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 69 | cbFnc = fs.isF(cb) || noop; |
| 70 | |
Bri Prebilic Cole | 5000a75 | 2015-02-23 17:20:53 -0800 | [diff] [blame] | 71 | is.loadIcon(btnDiv, gid, btnSize, true); |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 72 | if (tooltip) { addTooltip(btnDiv, tooltip); } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 73 | |
| 74 | btnDiv.on('click', cbFnc); |
| 75 | |
| 76 | return { |
| 77 | id: id, |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 78 | width: buttonWidth |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 79 | } |
| 80 | } |
| 81 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 82 | |
| 83 | // === TOGGLE BUTTON ========================================== |
| 84 | |
| 85 | // div is where to put the button (d3.selection of a DIV element) |
| 86 | // id should be globally unique |
| 87 | // gid is glyph ID (from Glyph Service) |
| 88 | // initState is whether the toggle is on or not to begin |
| 89 | // cb is callback function on click |
| 90 | // tooltip is text for tooltip |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 91 | function toggle(div, id, gid, initState, cb, tooltip) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 92 | if (!divExists(div, 'toggle button')) return null; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 93 | |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 94 | var sel = !!initState, |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 95 | togDiv = createDiv(div, 'toggleButton', id), |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 96 | cbFnc = fs.isF(cb) || noop; |
| 97 | |
Bri Prebilic Cole | 5000a75 | 2015-02-23 17:20:53 -0800 | [diff] [blame] | 98 | is.loadIcon(togDiv, gid, btnSize, true); |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 99 | togDiv.classed('selected', sel); |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 100 | if (tooltip) { addTooltip(togDiv, tooltip); } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 101 | |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 102 | function _toggle(b, nocb) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 103 | sel = (b === undefined) ? !sel : !!b; |
Bri Prebilic Cole | f7280d0 | 2015-02-24 16:20:47 -0800 | [diff] [blame] | 104 | togDiv.classed('selected', sel); |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 105 | nocb || cbFnc(sel); |
| 106 | } |
| 107 | |
| 108 | // toggle the button state without invoking the callback |
| 109 | function toggleNoCb() { |
| 110 | _toggle(undefined, true); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 111 | } |
| 112 | |
| 113 | togDiv.on('click', _toggle); |
| 114 | |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 115 | return { |
| 116 | id: id, |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 117 | width: buttonWidth, |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 118 | selected: function () { return sel; }, |
Simon Hunt | 0906014 | 2015-03-18 20:23:32 -0700 | [diff] [blame] | 119 | toggle: _toggle, |
| 120 | toggleNoCb: toggleNoCb |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 121 | } |
| 122 | } |
| 123 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 124 | |
| 125 | // === RADIO BUTTON SET ======================================= |
| 126 | |
| 127 | |
| 128 | // div is where to put the button (d3.selection of a DIV element) |
| 129 | // id should be globally unique |
| 130 | // rset is an array of button descriptors of the following form: |
| 131 | // { |
| 132 | // gid: glyphId, |
| 133 | // tooltip: tooltipText, |
| 134 | // cb: callbackFunction |
| 135 | // } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 136 | function radioSet(div, id, rset) { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 137 | if (!divExists(div, 'radio button set')) return null; |
| 138 | |
| 139 | if (!fs.isA(rset) || !rset.length) { |
| 140 | $log.warn('invalid array (radio button set)'); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 141 | return null; |
| 142 | } |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 143 | |
| 144 | var rDiv = createDiv(div, 'radioSet', id), |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 145 | rads = [], |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 146 | idxByKey = {}, |
| 147 | currIdx = 0; |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 148 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 149 | function rsetWidth() { |
| 150 | return ((btnSize + btnPadding) * rads.length) + btnPadding; |
| 151 | } |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 152 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 153 | function rbclick() { |
| 154 | var id = d3.select(this).attr('id'), |
| 155 | m = /^.*-(\d+)$/.exec(id), |
| 156 | idx = Number(m[1]); |
| 157 | |
| 158 | if (idx !== currIdx) { |
| 159 | rads[currIdx].el.classed('selected', false); |
| 160 | currIdx = idx; |
| 161 | rads[currIdx].el.classed('selected', true); |
| 162 | invokeCurrent(); |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 163 | } |
| 164 | } |
| 165 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 166 | // { |
| 167 | // gid: gid, |
| 168 | // tooltip: ..., (optional) |
| 169 | // key: ..., (optional) |
| 170 | // cb: cb |
| 171 | // id: ... (added by us) |
| 172 | // index: ... (added by us) |
| 173 | // } |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 174 | |
| 175 | rset.forEach(function (btn, index) { |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 176 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 177 | if (!fs.isO(btn)) { |
| 178 | $log.warn('radio button descriptor at index ' + index + |
| 179 | ' not an object'); |
| 180 | return; |
| 181 | } |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 182 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 183 | var rid = id + '-' + index, |
| 184 | initSel = (index === 0), |
| 185 | rbdiv = createDiv(rDiv, 'radioButton', rid); |
Bri Prebilic Cole | 664d470 | 2015-02-25 12:16:14 -0800 | [diff] [blame] | 186 | |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 187 | rbdiv.classed('selected', initSel); |
| 188 | rbdiv.on('click', rbclick); |
| 189 | is.loadIcon(rbdiv, btn.gid, btnSize, true); |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 190 | if (btn.tooltip) { addTooltip(rbdiv, btn.tooltip); } |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 191 | angular.extend(btn, { |
| 192 | el: rbdiv, |
| 193 | id: rid, |
| 194 | cb: fs.isF(btn.cb) || noop, |
| 195 | index: index |
| 196 | }); |
| 197 | |
| 198 | if (btn.key) { |
| 199 | idxByKey[btn.key] = index; |
| 200 | } |
| 201 | |
| 202 | rads.push(btn); |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 203 | }); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 204 | |
| 205 | |
| 206 | function invokeCurrent() { |
| 207 | var curr = rads[currIdx]; |
| 208 | curr.cb(curr.index, curr.key); |
| 209 | } |
| 210 | |
| 211 | function selected(x) { |
| 212 | var curr = rads[currIdx], |
| 213 | idx; |
| 214 | |
| 215 | if (x === undefined) { |
| 216 | return curr.key || curr.index; |
| 217 | } else { |
| 218 | idx = idxByKey[x]; |
| 219 | if (idx === undefined) { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 220 | $log.warn('no radio button with key:', x); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 221 | } else { |
| 222 | selectedIndex(idx); |
| 223 | } |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | function selectedIndex(x) { |
| 228 | if (x === undefined) { |
| 229 | return currIdx; |
| 230 | } else { |
| 231 | if (x >= 0 && x < rads.length) { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 232 | if (currIdx !== x) { |
| 233 | currIdx = x; |
| 234 | invokeCurrent(); |
| 235 | } else { |
| 236 | $log.warn('current index already selected:', x); |
| 237 | } |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 238 | } else { |
Bri Prebilic Cole | 1848917 | 2015-02-27 17:12:00 -0800 | [diff] [blame] | 239 | $log.warn('invalid radio button index:', x); |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 240 | } |
| 241 | } |
| 242 | } |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 243 | |
| 244 | return { |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 245 | width: rsetWidth, |
| 246 | selected: selected, |
| 247 | selectedIndex: selectedIndex |
Bri Prebilic Cole | 08381ce | 2015-02-20 17:01:50 -0800 | [diff] [blame] | 248 | } |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 249 | } |
| 250 | |
Bri Prebilic Cole | 258f046 | 2015-02-25 14:48:50 -0800 | [diff] [blame] | 251 | |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 252 | angular.module('onosWidget') |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 253 | .factory('ButtonService', |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 254 | ['$log', 'FnService', 'IconService', 'TooltipService', |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 255 | |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 256 | function (_$log_, _fs_, _is_, _tts_) { |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 257 | $log = _$log_; |
| 258 | fs = _fs_; |
| 259 | is = _is_; |
Bri Prebilic Cole | 54d0938 | 2015-03-19 18:40:27 -0700 | [diff] [blame] | 260 | tts = _tts_; |
Bri Prebilic Cole | 40be6b2 | 2015-02-19 17:12:23 -0800 | [diff] [blame] | 261 | |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 262 | return { |
| 263 | button: button, |
| 264 | toggle: toggle, |
Simon Hunt | 85fa2b8 | 2015-02-26 14:33:23 -0800 | [diff] [blame] | 265 | radioSet: radioSet |
Simon Hunt | 6925286 | 2015-02-26 11:26:08 -0800 | [diff] [blame] | 266 | }; |
| 267 | }]); |
| 268 | |
| 269 | }()); |