1 /* 2 * SIMPLICITE - runtime & framework 3 * http://www.simplicite.fr 4 * Copyright (c)2006-2013 Simplicite Software. All rights reserved. 5 */ 6 7 /** 8 * UI toolkit (requires jQuery with $j alias). 9 * @class 10 */ 11 Simplicite.UI = { 12 13 /** 14 * Returns text for specified code (if no text is found code is returned). 15 * @param code Text code 16 * @function 17 */ 18 T: function(code) { 19 var t = Simplicite.TEXT !== undefined ? Simplicite.TEXT[code] : code; 20 return t === undefined ? code : t; 21 }, 22 23 /** @ignore */ 24 _spec: function(spec) { 25 return spec === undefined ? {} : (typeof spec === "function" ? { callback: spec } : spec); 26 }, 27 /** @ignore */ 28 _target: function(target) { 29 if (target !== undefined && typeof(target) == "string") 30 return $j("#" + target); 31 else 32 return target; 33 }, 34 35 /** @ignore */ 36 _style: function(spec) { 37 var s = ""; 38 if (spec === undefined) return s; 39 if (spec.width !== undefined && spec.width > 0) s += "width: " + spec.width + "px;"; 40 if (spec.height !== undefined && spec.height > 0) s += "height: " + spec.height + "px;"; 41 if (spec.top !== undefined) s += "top: " + spec.top + "px;"; 42 if (spec.bottom !== undefined) s += "bottom: " + spec.bottom + "px;"; 43 if (spec.left !== undefined) s += "left: " + spec.left + "px;"; 44 if (spec.right !== undefined) s += "right: " + spec.right + "px;"; 45 if (spec.style !== undefined) s += spec.style; 46 return s; 47 }, 48 49 /** 50 * Returns a new div. 51 * @param spec Specification: 52 * <ul> 53 * <li>id: DOM ID</li> 54 * <li>name: Optional name</li> 55 * <li>width: Width in px</li> 56 * <li>height: Height in px</li> 57 * <li>style: CSS styles</li> 58 * </ul> 59 * @function 60 */ 61 div: function(spec) { 62 spec = this._spec(spec); 63 var p = { id: spec.id, style: this._style(spec) }; 64 if (spec.name) p.name = spec.name; 65 return $j("<div/>", p).append(spec.content); 66 }, 67 68 /** 69 * Returns a new button. 70 * @param spec Specification: 71 * <ul> 72 * <li>id: DOM ID</li> 73 * <li>label: Label</li> 74 * <li>click: Click handler</li> 75 * <li>color: Color (red, green, blue, orange, purple)</li> 76 * <li>style: CSS styles</li> 77 * </ul> 78 * @function 79 */ 80 button: function(spec) { 81 spec = this._spec(spec); 82 return $j("<input/>", { type: "button", id: spec.id, style: this._style(spec) }).addClass("ui_button" + (spec.color === undefined ? "" : "_" + spec.color)).val(spec.label).click(spec.click); 83 }, 84 85 image: function(name) { 86 return $j("<img/>", { src: name != undefined ? Simplicite.ROOT + "/images/image/" + name : undefined }); 87 }, 88 89 icon: function(name) { 90 return $j("<img/>", { src: name != undefined ? Simplicite.ROOT + "/images/icon/" + name : undefined }); 91 }, 92 93 /** 94 * Returns a new image button. 95 * @param spec Specification: 96 * <ul> 97 * <li>id: DOM ID</li> 98 * <li>src: Image source</li> 99 * <li>label: Label set as alt text and title</li> 100 * <li>click: Click handler</li> 101 * <li>style: CSS styles</li> 102 * </ul> 103 * @function 104 */ 105 imageButton: function(spec) { 106 spec = this._spec(spec); 107 var src = spec.src; 108 if (src === undefined) { 109 if (spec.icon !== undefined) src = Simplicite.ROOT + "/images/icon/" + spec.icon; 110 else if (spec.image !== undefined) src = Simplicite.ROOT + "/images/image/" + spec.image; 111 } 112 return $j("<img/>", { id: spec.id, src: src, alt: spec.label, title: spec.label, style: this._style(spec) }).addClass("ui_button").click(spec.click); 113 }, 114 115 /** 116 * Returns a new form. 117 * @param spec Specification: 118 * <ul> 119 * <li>id: DOM ID</li> 120 * <li>action: Form action URL</li> 121 * <li>method: Form method</li> 122 * <li>multipart: Multipart form ?</li> 123 * <li>submit: Submit handler (overrides default submit)</li> 124 * <li>style: CSS styles</li> 125 * </ul> 126 * @function 127 */ 128 form: function(spec) { 129 var ui = this; 130 spec = this._spec(spec); 131 var f = $j("<form/>", { id: spec.id, method: spec.method, action: spec.action, style: this._style(spec) }); 132 if (spec.multipart == true) 133 f.attr("enctype", "multipart/form-data"); 134 if (spec.submit !== undefined) 135 f.submit(function() { 136 spec.submit.call(ui, f); 137 return false; 138 }); 139 return f; 140 }, 141 142 /** 143 * Returns a new iframe. 144 * @param url Source URL 145 */ 146 iframe: function(url) { 147 return $j("<iframe/>", { style: "border: none; margin: 0px; padding: 0px; width: 100%; height: 100%;", frameborder: "no", scrolling: "auto", src: url }); 148 }, 149 150 /** 151 * Is a popup active ? 152 */ 153 popupActive: false, 154 155 /** 156 * Returns and display a modal popup. 157 * <br/>Sample usage: 158 * <pre> 159 * popup({ width: 300, height: 200, beforeClose: function() { console.log("Popup closing..."); return true; }).append("<p>Hello world</p>"); 160 * </pre> 161 * @param spec Specification: 162 * <ul> 163 * <li>name: Popup name (ui_popup default)</li> 164 * <li>content: Popup content</li> 165 * <li>url: URL content (in an IFRAME)</li> 166 * <li>afterOpen After open handler</li> 167 * <li>closeable: Closeable ?</li> 168 * <li>beforeClose Before close handler (must return false to prevent popup closing)</li> 169 * <li>afterClose After close handler</li> 170 * <li>margin: Margin in px around the popup (not compatible with width and heigth)</li> 171 * <li>width: Width in px (not compatible with margin)</li> 172 * <li>height: Height in px (not compatible with margin)</li> 173 * <li>target: Target element (defaults to document body)</li> 174 * <li>style: CSS styles</li> 175 * </ul> 176 * @function 177 */ 178 popup: function(spec) { 179 var ui = this; 180 ui.popupActive = true; 181 spec = ui._spec(spec); 182 if (!spec.name) spec.name = "ui_popup"; 183 var b = ui._target(spec.target); 184 if (b === undefined || b.length == 0) { 185 b = $j("#body"); 186 if (b.length == 0) b = $j("body"); 187 } 188 var cl = spec.closeable === undefined || spec.closeable == true; 189 if (spec.margin === undefined || spec.margin <= 0) { 190 spec.margin = 0; 191 if (spec.width === undefined || spec.width <= 0) spec.width = 200; 192 if (spec.height === undefined || spec.height <= 0) spec.height = 100; 193 } else { 194 spec.width = 0; 195 spec.height = 0; 196 } 197 var close = function() { ui.popupClose(spec.beforeClose, spec.afterClose, spec.name); }; 198 b.addClass("ui_popupmask"); 199 var m = ui.div({ id:"ui_popupmask", name:spec.name+"mask" }); 200 if (Simplicite.Tools.isWinIE && (Simplicite.Tools.winIEVersion <= 8 || Simplicite.USE_HTML4)) 201 m.addClass("ui_opaque_ie8"); 202 else 203 m.addClass("ui_opaque"); 204 if (cl) m.click(close); 205 b.append(m); 206 m.show(); 207 var hm = Math.max(spec.margin > 0 ? spec.margin : Math.round((m.width() - spec.width) / 2), 30); 208 var vm = Math.max(spec.margin > 0 ? spec.margin : Math.round((m.height() - spec.height) / 2), 30); 209 var st = "left: " + hm + "px; right: " + hm + "px; top: " + vm + "px; bottom: " + vm + "px;"; 210 var p = ui.div({ id:"ui_popup", name: spec.name, style: st + ui._style(spec) }); 211 if (spec.url !== undefined) { 212 p.css("overflow", "hidden"); 213 p.addClass("ui_box").append(ui.iframe(spec.url)); 214 } 215 else if (spec.content !== undefined) 216 p.addClass("ui_box").append(spec.content); 217 b.append(p); 218 if (cl) { 219 var cst = "left: " + hm + "px; top: " + vm + "px;"; 220 var c = ui.div({ id:"ui_popupclose", name: spec.name+"close", style: cst }); 221 b.append(c.click(close)); 222 } 223 if (spec.afterOpen && spec.afterOpen.call) 224 spec.afterOpen.call(ui); 225 return p; 226 }, 227 228 /** @ignore */ 229 popupClose: function(beforeClose, afterClose, name) { 230 if (!name) name = "ui_popup"; 231 var c = true; 232 if (beforeClose && beforeClose.call) { 233 var r = beforeClose.call(this); 234 if (r !== undefined) c = r; 235 } 236 if (c) { 237 try { $j("[name='"+name+"']").remove(); } catch(e) {} 238 try { $j("[name='"+name+"close']").remove(); } catch(e) {} 239 try { $j("[name='"+name+"mask']").remove(); } catch(e) {} 240 $j("body").removeClass("ui_popupmask").removeClass("ui_popupmask_ie"); 241 this.popupActive = false; 242 if (afterClose && afterClose.call) 243 afterClose.call(this); 244 } 245 }, 246 247 /** 248 * Displays information popup. 249 * @param msg Information message 250 * @param callback Callback 251 * @function 252 */ 253 infoPopup: function(msg, callback) { 254 return this.popup({ afterClose: callback, content: $j("<h1/>").addClass("ui_info").html(this.T("INFO")) }).append($j("<p/>").addClass("ui_info").html(msg)); 255 }, 256 257 /** 258 * Displays warning popup. 259 * @param msg Warning message 260 * @param callback Callback 261 * @function 262 */ 263 warningPopup: function(msg, callback) { 264 return this.popup({ afterClose: callback, content: $j("<h1/>").addClass("ui_warning").html(this.T("WARNING")) }).append($j("<p/>").addClass("ui_warning").html(msg)); 265 }, 266 267 /** 268 * Get plain error message from error or exception. 269 * @param err Error message or exception 270 * @function 271 */ 272 getErrorMessage: function(err) { 273 var msg = ""; 274 if (err.messages !== undefined) { 275 for (var i = 0; i < err.messages.length; i++) 276 msg += (msg == "" ? "" : "\n") + err.messages[i]; 277 } else if (err.message !== undefined) 278 msg = err.message; 279 else if (err.description !== undefined) 280 msg = err.description; 281 else 282 msg = err; 283 return msg; 284 }, 285 286 /** 287 * Displays error popup. 288 * @param err Error (can be a message or an exception) 289 * @param callback Callback 290 * @function 291 */ 292 errorPopup: function(err, callback) { 293 var msg = this.getErrorMessage(err); 294 return this.popup({ afterClose: callback, content: $j("<h1/>").addClass("ui_error").html(this.T("ERROR")) }).append($j("<p/>").addClass("ui_error").html(msg)); 295 }, 296 297 /** 298 * Displays dialog popup. 299 * @param msg Warning message 300 * @param buttonSpecs Array of button specifications (cf. button() function) 301 * @function 302 */ 303 dialog: function(msg, buttonSpecs) { 304 var ui = this; 305 var c = $j("<p/>").addClass("ui_confirm").html(msg); 306 var bf = undefined; 307 if (buttonSpecs !== undefined) { 308 var b = ui.div({ style: "position: absolute; left: 0px; right: 0px; bottom: 5px;" }); 309 for (var i = 0; i < buttonSpecs.length; i++) { 310 var bs = ui._spec(buttonSpecs[i]); 311 var bi = ui.button(bs); 312 if (bs.focus === true) bf = bi; 313 b.append(bi); 314 } 315 c.append(b); 316 } 317 return ui.popup({ closeable: false, height: (msg.length/50+2)*25+10, content: c, afterOpen: bf == undefined ? undefined : function() { bf.focus(); } }); 318 }, 319 320 /** 321 * Displays simple dialog popup. 322 * @param msg Message 323 * @param callback Callback called when the OK button is clicked 324 * @function 325 */ 326 okDialog: function(msg, callback) { 327 var ui = this; 328 if (Simplicite.USE_HTML4) 329 alert(m); 330 else 331 return this.dialog(msg, [{ label: ui.T("OK"), color: "green", click: function() { ui.popupClose(undefined, callback); }, focus: true }]); 332 }, 333 334 /** 335 * Displays simple alert dialog popup. 336 * @param msg Message (can be simple message or a text code or a text code:message) 337 * @param callback Callback called when the OK button is clicked 338 * @function 339 */ 340 alert : function(msg, callback) { 341 var ui = this; 342 if (msg === undefined || msg == "") return; 343 var i = msg.indexOf(":"); 344 var m = (i < 0) ? this.T(msg) : this.T(msg.substring(0, i)) + (i+1 < msg.length ? ": " + msg.substring(i+1) : ""); 345 if (Simplicite.USE_HTML4) 346 alert(m); 347 else 348 return ui.okDialog(m, callback); 349 }, 350 351 /** 352 * Displays OK/CANCEL dialog popup. 353 * @param msg Message 354 * @param okCallback Callback called if the OK button is clicked 355 * @param cancelCallback Callback called if the CANCEL button is clicked 356 * @function 357 */ 358 okCancelDialog: function(msg, okCallback, cancelCallback) { 359 var ui = this; 360 if (Simplicite.USE_HTML4) { 361 if (confirm(msg)) 362 okCallback.call(ui); 363 else 364 cancelCallback.call(ui); 365 } else { 366 return ui.dialog(msg, [ 367 { label: ui.T("OK"), color: "green", click: function() { ui.popupClose(undefined, okCallback); }, focus: true }, 368 { label: ui.T("CANCEL"), color: "red", click: function() { ui.popupClose(undefined, cancelCallback); } } 369 ]); 370 } 371 }, 372 373 /** 374 * Displays YES/NO dialog popup. 375 * @param msg Message 376 * @param yesCallback Callback called if the YES button is clicked 377 * @param noCallback Callback called if the NO button is clicked 378 * @function 379 */ 380 yesNoDialog: function(msg, yesCallback, noCallback) { 381 var ui = this; 382 if (Simplicite.USE_HTML4) { 383 if (confirm(msg)) 384 yesCallback.call(ui); 385 else 386 noCallback.call(ui); 387 } else { 388 return ui.dialog(msg, [ 389 { label: ui.T("YES"), color: "green", click: function() { ui.popupClose(undefined, yesCallback); }, focus: true }, 390 { label: ui.T("NO"), color: "red", click: function() { ui.popupClose(undefined, noCallback); } } 391 ]); 392 } 393 }, 394 395 /** 396 * Displays YES/NO/CANCEL dialog popup. 397 * @param msg Message 398 * @param yesCallback Callback called if the YES button is clicked 399 * @param noCallback Callback called if the NO button is clicked 400 * @param cancelCallback Callback called the CANCEL button is clicked 401 * @function 402 */ 403 yesNoCancelDialog: function(msg, yesCallback, noCallback, cancelCallback) { 404 var ui = this; 405 if (Simplicite.USE_HTML4) { 406 if (confirm(msg)) 407 yesCallback.call(ui); 408 else 409 noCallback.call(ui); 410 } else { 411 return ui.dialog(msg, [ 412 { label: ui.T("YES"), color: "green", click: function() { ui.popupClose(undefined, yesCallback); }, focus: true }, 413 { label: ui.T("NO"), color: "red", click: function() { ui.popupClose(undefined, noCallback); } }, 414 { label: ui.T("CANCEL"), color: "orange", click: function() { ui.popupClose(undefined, cancelCallback); } } 415 ]); 416 } 417 }, 418 419 /** 420 * Show loading mask. 421 * @param spec Specification: 422 * <ul> 423 * <li>message: Message (mandatory)</li> 424 * <li>anim: Add animated gif (defaults to true) ?</li> 425 * <li>target: Target element (defaults to document body)</li> 426 * <li>callback: Callback</li> 427 * </ul> 428 * @function 429 */ 430 showLoading: function(spec) { 431 var l = undefined; 432 spec = this._spec(spec); 433 var t = (Simplicite.Tester && Simplicite.Tester.testId); 434 if (!t) { // no popup during testcase recording 435 var m = spec.message; 436 l = this.popup({ closeable: false, width: 200, height: 80, target: spec.target }).addClass("ui_loading"); 437 if (spec.anim === undefined || spec.anim == true) 438 l.append($j("<div/>").append(this.image("inprogress.gif"))); 439 if (m) l.addClass("ui_box").append(m); 440 } 441 var c = spec.callback; 442 if (c) { 443 var self = this; 444 // ZZZ a 100ms delay is required for the browser to display the spinner GIF 445 setTimeout(function() { c.call(self); }, 100); 446 } 447 return l; 448 }, 449 450 /** 451 * Hide loading mask. 452 * @param spec Specification: 453 * <ul> 454 * <li>callback: Callback</li> 455 * </ul> 456 */ 457 hideLoading: function(spec) { 458 this.popupClose(); 459 spec = this._spec(spec); 460 var c = spec.callback; 461 if (c !== undefined) 462 c.call(this); 463 }, 464 465 /** 466 * Show a toast message (hidden after specified delay). 467 * @param spec Specification: 468 * <ul> 469 * <li>message: Message (mandatory)</li> 470 * <li>delay: Hide delay (default is 1.5s)</li> 471 * <li>callback: Callback called after toast message is closed</li> 472 * <li>target: Target element (defaults to document body)</li> 473 * </ul> 474 * @function 475 */ 476 toast: function(spec) { 477 spec = this._spec(spec); 478 var m = spec.message; 479 var ui = this; 480 if (m === undefined || m == "") return; 481 ui.popup({ closeable: false, width: 200, height: (m.length/50+1)*25, target: spec.target }).addClass("ui_toast").addClass("ui_box").append(m); 482 setTimeout(function() { 483 ui.popupClose(undefined, spec.callback); 484 }, spec.delay === undefined ? 1500 : spec.delay); 485 }, 486 487 popupWindow: function(spec) { 488 spec = this._spec(spec); 489 var p = "location=no,menubar=no,status=no,toolbar=no,directories=no"; 490 if (spec.width != undefined) p = p + ",width=" + spec.width; 491 if (spec.height != undefined) p = p + ",height=" + spec.height; 492 if (spec.top != undefined) p = p + ",top=" + spec.top; 493 if (spec.left != undefined) p = p + ",left=" + spec.left; 494 return window.open(spec.url, spec.name === undefined ? "_blank" : spec.name, p); 495 }, 496 497 newWindow: function(url) { 498 return window.open(url, "_blank"); 499 }, 500 501 /** @ignore */ 502 _component: function(target, type, spec) { 503 var ui = this; 504 target = ui._target(target); 505 spec = ui._spec(spec); 506 var mc = $j("<div/>").addClass("ui_" + type); 507 target.append(mc); 508 var l = $j("<div/>").addClass("ui_" + type + "_label").append(spec.label); 509 mc.append(l); 510 var t = $j("<div/>").addClass("ui_" + type + "_toggle"); 511 if (spec.expandable == true && spec.expanded == false) t.hide(); 512 mc.append(t); 513 var c = $j("<div/>", { id: spec.id, style: ui._style(spec) }).addClass("ui_" + type + "_content").append(spec.content); 514 t.append(c); 515 var comp = { 516 label: l, 517 content: c, 518 spec: spec, 519 append: function(elt) { 520 this.content.append(elt); 521 return this; 522 }, 523 toggle: function() { 524 var c = this.content.parent(); 525 if (this.spec.expandEffect == "slide") 526 c.slideToggle(); 527 else if (this.spec.expandEffect == "fade") 528 c.fadeToggle(); 529 else 530 c.toggle(); 531 var l = this.label; 532 l.toggleClass("ui_plus"); 533 l.toggleClass("ui_minus"); 534 if (spec.toggle !== undefined) 535 spec.toggle.call(ui, this.content); 536 return this; 537 } 538 }; 539 if (spec.expandable == true) { 540 l.addClass("ui_button"); 541 l.addClass(spec.expanded == true ? "ui_minus" : "ui_plus"); 542 l.click(function() { comp.toggle(); }); 543 } 544 return comp; 545 }, 546 547 /** 548 * Add a new simple area to target 549 * @param target Target DOM ID or element 550 * @param spec Specification: 551 * <ul> 552 * <li>id: DOM ID</li> 553 * <li>label: Area label</li> 554 * <li>content: Area content</li> 555 * <li>expandable Expandable (false by default) ?</li> 556 * <li>expanded Expanded by default (true by default) ?</li> 557 * <li>expandEffect Expand effect : "slide" or "fade"</li> 558 * <li>toggle Toggle handler</li> 559 * <li>width: Width in px</li> 560 * <li>height: Height in px</li> 561 * <li>style: CSS styles</li> 562 * </ul> 563 * @function 564 */ 565 area: function(target, spec) { 566 return this._component(target, "area", spec); 567 }, 568 569 /** 570 * Add a new gadget to target 571 * @param target Target DOM ID or element 572 * @param spec Specification: 573 * <ul> 574 * <li>id: DOM ID</li> 575 * <li>label: Gadget label</li> 576 * <li>content: Gadget content</li> 577 * <li>expandable Expandable (false by default) ?</li> 578 * <li>expanded Expanded by default (true by default) ?</li> 579 * <li>expandEffect Expand effect : "slide" or "fade"</li> 580 * <li>toggle Toggle handler</li> 581 * <li>layout Gadget layout (e.g. "modern")</li> 582 * <li>width: Width in px</li> 583 * <li>height: Height in px</li> 584 * <li>style: CSS styles</li> 585 * </ul> 586 * @function 587 */ 588 gadget: function(target, spec) { 589 spec = this._spec(spec); 590 return this._component(target, "gadget" + (spec.layout !== undefined ? "_" + spec.layout : ""), spec); 591 }, 592 593 contextualpopup: function(spec) { 594 spec = this._spec(spec); 595 var p = this.div({ top: spec.top, left: spec.left, style: "position: absolute;" }); 596 delete spec.top; 597 delete spec.left; 598 var c = this._component(p, "contextualpopup", spec); 599 c.popup = p; 600 c.close = function() { p.remove(); }; 601 $j("body").append(p); 602 return c; 603 }, 604 605 /** 606 * Add new tabs to target 607 * @param target Target DOM ID or element 608 * @param specs Specifications, each one for one tab: 609 * <ul> 610 * <li>id: DOM ID</li> 611 * <li>label: Tab label</li> 612 * <li>content: Tab content</li> 613 * <li>changeEffect Change tab effect : "slide" or "fade"</li> 614 * <li>change Change tab handler</li> 615 * <li>width: Width in px</li> 616 * <li>height: Height in px</li> 617 * <li>style: CSS styles</li> 618 * </ul> 619 * @function 620 */ 621 tabs: function(target, specs) { 622 var ui = this; 623 target = ui._target(target); 624 var ts = { 625 specs: specs, 626 labels: [], 627 contents: [], 628 append: function(n, elt) { 629 if (n < 0 || n >= this.specs.length) return; 630 this.contents[n].append(elt); 631 return this; 632 }, 633 toggle: function(n) { 634 if (n < 0 || n >= this.specs.length) return; 635 var spec = this.specs[n]; 636 if (this.labels[n].hasClass("ui_tab_off")) { 637 for (var i = 0; i < this.labels.length; i++) { 638 var l = this.labels[i]; 639 var c = this.contents[i]; 640 if (i == n) { 641 l.removeClass("ui_tab_off"); 642 if (spec.activateEffect == "slide") 643 c.slideDown(); 644 else if (spec.activateEffect == "fade") 645 c.fadeIn(); 646 else 647 c.show(); 648 if (spec.activate !== undefined) 649 spec.activate.call(ui, c); 650 } else { 651 l.addClass("ui_tab_off"); 652 c.hide(); 653 } 654 } 655 } 656 return this; 657 } 658 }; 659 var g = $j("<div/>").addClass("ui_tab_group"); 660 target.append(g); 661 var n = 0; 662 for (var k in specs) { 663 specs[k] = ui._spec(specs[k]); 664 if (specs[k].active == true) n = k; 665 } 666 for (var i in specs) { 667 var spec = specs[i]; 668 var l = $j("<div/>").addClass("ui_tab").data("index", i).click(function() { ts.toggle($j(this).data("index")); }); 669 l.append(spec.label !== undefined ? spec.label : " "); 670 g.append(l); 671 ts.labels.push(l); 672 var c = $j("<div/>", { id: spec.id, style: ui._style(spec) }).addClass("ui_tab_content").append(spec.content); 673 target.append(c); 674 ts.contents.push(c); 675 if (i != n) { 676 l.addClass("ui_tab_off"); 677 c.hide(); 678 } else { 679 if (spec.activate !== undefined) 680 spec.activate.call(ui, c); 681 } 682 } 683 return ts; 684 }, 685 686 /** 687 * Pie chart using JQPlot 688 * @param target Target DOM ID or element 689 * @param spec Specifications: <ul> 690 * <li>values: Values</li> 691 * <li>labels: Labels</li> 692 * <li>options: Chart options</li> 693 */ 694 pieChart: function(target, spec) { 695 if ($j.jqplot == undefined) return; 696 spec = this._spec(spec); 697 if (typeof(target) != "string") target = target[0].id; 698 var v = []; 699 if (spec.labels !== undefined) 700 for (var i = 0; i < spec.values.length; i++) 701 v[i] = [ spec.labels[i], spec.values[i] ]; 702 else 703 v = spec.values; 704 var o = { 705 title: spec.title, 706 seriesDefaults: { renderer: $j.jqplot.PieRenderer, rendererOptions: { showDataLabels: true } }, 707 legend: { show: true, location: "ne" } 708 }; 709 if (spec.options !== undefined) $j.extend(true, o, spec.options); 710 setTimeout(function() { $j.jqplot(target, [ v ], o); }, 0); 711 }, 712 713 _chart: function(target, spec) { 714 if ($j.jqplot == undefined) return; 715 spec = this._spec(spec); 716 if (typeof(target) != "string") target = target[0].id; 717 var o = { 718 title: spec.title, 719 seriesDefaults: { rendererOptions: { showDataLabels: true } }, 720 axes: { xaxis: { renderer: $j.jqplot.CategoryAxisRenderer } } 721 }; 722 if (spec.labels !== undefined) { 723 o.axes.xaxis.ticks = spec.labels; 724 } 725 if (spec.names !== undefined) { 726 o.legend = { show: true, location: "nw" }; 727 o.series = new Array(); 728 for (var i = 0; i < spec.names.length; i++) { 729 o.series[i] = { label: spec.names[i] }; 730 } 731 } 732 if (spec.options !== undefined) $j.extend(true, o, spec.options); 733 setTimeout(function() { $j.jqplot(target, spec.values, o); }, 0); 734 }, 735 736 /** 737 * Line chart using JQPlot 738 * @param target Target DOM ID or element 739 * @param spec Specifications: <ul> 740 * <li>values: Values</li> 741 * <li>names: Names</li> 742 * <li>labels: Labels</li> 743 * <li>options: Chart options</li> 744 */ 745 lineChart: function(target, spec) { 746 if ($j.jqplot == undefined) return; 747 spec = this._spec(spec); 748 var o = { seriesDefaults: { pointLabels: { show: true } } }; 749 spec.options = spec.options !== undefined ? $j.extend(true, o, spec.options) : o; 750 this._chart(target, spec); 751 }, 752 753 /** 754 * Bar chart using JQPlot 755 * @param target Target DOM ID or element 756 * @param spec Specifications: <ul> 757 * <li>values: Values</li> 758 * <li>names: Names</li> 759 * <li>labels: Labels</li> 760 * <li>options: Chart options</li> 761 */ 762 barChart: function(target, spec) { 763 if ($j.jqplot == undefined) return; 764 spec = this._spec(spec); 765 var o = { seriesDefaults: { renderer: $j.jqplot.BarRenderer, pointLabels: { show: true } } }; 766 spec.options = spec.options !== undefined ? $j.extend(true, o, spec.options) : o; 767 this._chart(target, spec); 768 }, 769 770 /** 771 * Stack bar chart using JQPlot 772 * @param target Target DOM ID or element 773 * @param spec Specifications: <ul> 774 * <li>values: Values</li> 775 * <li>names: Names</li> 776 * <li>labels: Labels</li> 777 * <li>options: Chart options</li> 778 */ 779 stackBarChart: function(target, spec) { 780 if ($j.jqplot == undefined) return; 781 spec = this._spec(spec); 782 var o = { stackSeries: true, seriesDefaults: { renderer: $j.jqplot.BarRenderer, pointLabels: { show: true } } }; 783 spec.options = spec.options !== undefined ? $j.extend(true, o, spec.options) : o; 784 this._chart(target, spec, $j.jqplot.BarRenderer); 785 }, 786 787 /** 788 * Area bar chart using JQPlot 789 * @param target Target DOM ID or element 790 * @param spec Specifications: <ul> 791 * <li>values: Values</li> 792 * <li>names: Names</li> 793 * <li>labels: Labels</li> 794 * <li>options: Chart options</li> 795 */ 796 areaChart: function(target, spec) { 797 if ($j.jqplot == undefined) return; 798 spec = this._spec(spec); 799 var o = { seriesDefaults: { fill: true } }; 800 spec.options = spec.options !== undefined ? $j.extend(true, o, spec.options) : o; 801 this._chart(target, spec); 802 }, 803 804 /** 805 * Stack area bar chart using JQPlot 806 * @param target Target DOM ID or element 807 * @param spec Specifications: <ul> 808 * <li>values: Values</li> 809 * <li>names: Names</li> 810 * <li>labels: Labels</li> 811 * <li>options: Chart options</li> 812 */ 813 stackAreaChart: function(target, spec) { 814 if ($j.jqplot == undefined) return; 815 spec = this._spec(spec); 816 var o = { stackSeries: true, seriesDefaults: { fill: true } }; 817 spec.options = spec.options !== undefined ? $j.extend(true, o, spec.options) : o; 818 this._chart(target, spec); 819 }, 820 821 /** 822 * Returns a new social post bloc 823 * @param spec Specifications: <ul> 824 * <li>id: DOM ID</li> 825 * <li>date: Post date</li> 826 * <li>message: Post message (if undefined a form for new post is generated)</li> 827 * <li>about: Post reference</li> 828 * <li>followersOnly: Followers only post ?</li> 829 * <li>pictureURL: Picture URL</li> 830 * <li>userName: User full name</li> 831 * <li>userLogin: User login</li> 832 * <li>userID: User ID</li> 833 * <li>messagePlaceholder: New post form message textarea placeholder</li> 834 * <li>buttonLabel: New post form button label</li> 835 * <li>post: New post form handler</li> 836 */ 837 socialPost: function(spec) { 838 spec = this._spec(spec); 839 var d = this.div({ id: spec.id }).addClass("ui_social"); 840 if (spec.followersOnly !== undefined && spec.followersOnly === true) 841 d.addClass("ui_social_followers"); 842 var t = $j("<table/>", { style: "width: 100%;" }); 843 var tr = $j("<tr/>"); 844 t.append(tr); 845 if (spec.pictureURL) 846 tr.append($j("<td/>", { style: "width: 50px;" }).append($j("<img/>", { src: spec.pictureURL, title: spec.userName }))); 847 var td = $j("<td/>"); 848 td.append($j("<div/>").addClass("ui_social_user").text(spec.userName)); 849 if (spec.date !== undefined) 850 td.append($j("<div/>").addClass("ui_social_date").text(spec.date)); 851 var m = $j("<div/>").addClass("ui_social_post"); 852 if (spec.message === undefined) { 853 m.append($j("<textarea/>", { id: spec.id + "_message", style: "float: left;", cols: 80, rows: 2, placeholder: spec.messagePlaceholder }).addClass("ui_social_textarea")); 854 m.append(this.button({ label: spec.buttonLabel, click: spec.post !== undefined ? function() { 855 spec.post.call(this, spec.userID, new Date(), $j("#" + spec.id + "_message").val()); 856 } : undefined })); 857 } 858 else 859 m.text(spec.message); 860 td.append(m); 861 if (spec.about !== undefined) 862 td.append($j("<div/>").addClass("ui_social_about").text(spec.about)); 863 tr.append(td); 864 d.append(t); 865 return d; 866 }, 867 868 /** 869 * Return a news block 870 * @param n news 871 */ 872 news: function(n) { 873 var d = $j("<div/>"); 874 var t = $j("<table/>"); 875 var tr = $j("<tr/>"); 876 if (n.image && n.image.content) 877 tr.append($j("<td/>").append($j("<img/>", { src: "data:" + n.image.mime + ";base64," + n.image.content, style: "width: 75px;" }))).append($j("<td/>").append(" ")); 878 tr.append($j("<td/>").append($j("<p/>").addClass("rsstext").append($j("<span/>").addClass("rsstextdate").append(new Date().fromDateTimeValue(n.date))).append("<br/>").append($j("<span/>").addClass("rsstexttitle").append(n.title)))); 879 t.append(tr); 880 d.append(t).append($j("<p/>").addClass("rsstext").append(n.content.replace(/[\r\n]+/, "<br/>"))); 881 return d; 882 }, 883 884 /** 885 * Creates a new rotating ticker in designated target 886 * @param target Target element 887 * @param delay Rotation delay in milliseconds 888 */ 889 ticker: function(target, delay) { 890 /** @ignore */ 891 var ul = $j("<ul/>", { style: "margin: 0px; padding: 0px; list-style-type: none; overflow: hidden; height: " + target.height() + "px;" }); 892 ul.mouseover(function() { stop(); }); 893 ul.mouseout(function() { start(); }); 894 target.append(ul); 895 /** 896 * Clear ticker items 897 * @param item Item to append 898 */ 899 function clear() { 900 ul.clear(); 901 } 902 /** 903 * Appends an item to ticker 904 * @param item Item to append 905 */ 906 function append(item) { 907 ul.append($j("<li/>", { style: "margin: 0px; padding: 0px; list-style-type: none; height: " + target.height() + "px;" }).append(item)); 908 } 909 /** @ignore */ 910 var timer = undefined; 911 /** 912 * Start ticker 913 */ 914 function start() { 915 timer = setInterval(function() { 916 ul.find("li:first").slideUp(1500, function () { $j(this).appendTo(ul).show(); }); 917 }, delay); 918 } 919 /** 920 * Stop ticker 921 */ 922 function stop() { 923 if (timer) clearInterval(timer); 924 timer = undefined; 925 } 926 return { start: start, stop: stop, clear: clear, append: append }; 927 } 928 929 };