opengrok-symbols-panel.js revision 1383
1370N/A/*
1370N/A * CDDL HEADER START
1370N/A *
1370N/A * The contents of this file are subject to the terms of the
1370N/A * Common Development and Distribution License (the "License").
1370N/A * You may not use this file except in compliance with the License.
1370N/A *
1370N/A * See LICENSE.txt included in this distribution for the specific
1370N/A * language governing permissions and limitations under the License.
1370N/A *
1370N/A * When distributing Covered Code, include this CDDL HEADER in each
1370N/A * file and include the License file at LICENSE.txt.
1370N/A * If applicable, add the following below this CDDL HEADER, with the
1370N/A * fields enclosed by brackets "[]" replaced with your own identifying
1370N/A * information: Portions Copyright [yyyy] [name of copyright owner]
1370N/A *
1370N/A * CDDL HEADER END
1370N/A */
1370N/A/*
1370N/A * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
1370N/A * Portions Copyright 2011, 2012, Jens Elkner.
1370N/A */
1370N/AYUI.add('symbols-panel', function(Y) {
1370N/A "use strict";
1370N/A var L = Y.Lang, BB = 'boundingBox',
1370N/A RESIZE='resize', KEYDOWN = 'keydown', MOUSEUP = 'mouseup',
1370N/A TOP = 'top', BOTTOM = 'bottom', RIGHT = 'right', LEFT='left',
1370N/A PWIDTH = 'pWidth', PHEIGHT = 'pHeight', PMARGIN = 'pMargin',
1370N/A HEIGHT = 'height', WIDTH = 'width', VISIBLE = 'visible';
1383N/A var getClassName = Y.ClassNameManager.getClassName;
1370N/A
1370N/A var panel = Y.Base.create('SymbolsPanel', Y.Widget,
1370N/A [Y.WidgetStdMod, Y.WidgetPosition, Y.WidgetStack, Y.WidgetAutohide,
1370N/A Y.WidgetButtons],
1370N/A { // instance members
1370N/A BOUNDING_TEMPLATE : '<div id="symbolsBB"></div>',
1370N/A CONTENT_TEMPLATE : '<div id="symbolsCB"></div>',
1370N/A
1370N/A // private helpers
1370N/A _getTop : function() { /* get optimal y position */
1370N/A var h = Y.one('#whole_header');
1370N/A return h.getY() + h.get('offsetHeight') + this.get(PMARGIN)[TOP];
1370N/A },
1370N/A _getLeft : function() { /* get optimal x position */
1370N/A return Y.DOM.winWidth() - this.get(WIDTH)
1370N/A - this.get(PMARGIN)[RIGHT] - Y.DOM.getScrollbarWidth();
1370N/A },
1370N/A _getHeight: function() { /* get optimal height */
1370N/A var h = Y.DOM.winHeight() - this._getTop() - this.get(PMARGIN)[BOTTOM];
1370N/A if (h > this.get(PHEIGHT)) {
1370N/A h = this.get(PHEIGHT);
1370N/A } else if (h < 50) {
1370N/A h = 50;
1370N/A }
1370N/A return h;
1370N/A },
1370N/A
1370N/A _adjustPosition : function() {
1370N/A var t, sbw = Y.DOM.getScrollbarWidth(), //assume same for vert/horiz
1370N/A w = this.get(WIDTH), h = this.get(HEIGHT)
1370N/A var right = Y.DOM.winWidth() - sbw - this.get(PMARGIN)[RIGHT],
1370N/A bottom = Y.DOM.winHeight() - sbw - this.get(PMARGIN)[BOTTOM];
1370N/A // assure a minimum size of 50x50
1370N/A if (w < 50) {
1370N/A w = this.get(PWIDTH);
1370N/A this.set(WIDTH, w);
1370N/A }
1370N/A if (h < 50) {
1370N/A h = this.get(PHEIGHT);
1370N/A this.set(HEIGHT, h);
1370N/A }
1370N/A // at least a part of the head should be visible for dragging
1370N/A t = this.get('y');
1370N/A if (t < 0 || bottom < 30) {
1370N/A this.set('y', 0);
1370N/A } else if (t + 30 > bottom) {
1370N/A this.set('y', bottom - 30);
1370N/A }
1370N/A t = this.get('x');
1370N/A if (t + w < 50 || right < 50) { // 50 because of the close button
1370N/A this.set('x', 50 - w);
1370N/A } else if (t + 50 > right) {
1370N/A this.set('x', right - 50);
1370N/A }
1370N/A },
1370N/A
1370N/A // public
1370N/A initializer : function(config) {
1370N/A config || (config = {});
1370N/A this.plug(Y.Plugin.Drag);
1370N/A this._listener = {};
1370N/A
1370N/A var bb = this.get(BB);
1370N/A var that = this;
1370N/A this._listener[MOUSEUP] = bb.on(MOUSEUP, function(e) {
1370N/A if (e.target == this) {
1370N/A that._fillHeight();
1370N/A };
1370N/A });
1370N/A this.set(HEIGHT, this._getHeight());
1370N/A this.set(WIDTH, this.get(PWIDTH));
1370N/A this.set('xy', [ this._getLeft(), this._getTop() ]);
1370N/A if (Y.UA.safari > 0) {
1370N/A bb.setStyle(RESIZE, 'none'); /* safari does stupid things */
1370N/A }
1370N/A this.dd.addHandle(this._stdModNode.one('#symbolsHd'));
1370N/A },
1370N/A
1370N/A /**
1370N/A * Hide the panel. It is different from just setting the 'visible'
1370N/A * property: unneeded listeners are removed from the panel after it
1370N/A * has been hidden.
1370N/A * @Override
1370N/A */
1370N/A hide : function() {
1370N/A this.set(VISIBLE, false);
1370N/A if (this._listener[KEYDOWN]) {
1370N/A Y.detach(this._listener[KEYDOWN]);
1370N/A this._listener[KEYDOWN] = null;
1370N/A }
1370N/A if (this._listener[RESIZE]) {
1370N/A Y.detach(this._listener[RESIZE]);
1370N/A this._listener[RESIZE] = null;
1370N/A }
1370N/A },
1370N/A
1370N/A /**
1370N/A * Show the panel. It is different from just setting the 'visible'
1370N/A * property: adjusts the position of the panel if necessary, syncs the
1370N/A * height of the fillSection (default: body) and adds additional
1370N/A * listeners before making it visible.
1370N/A * @Override
1370N/A */
1370N/A show : function() {
1370N/A var that = this;
1370N/A if (!this.get(VISIBLE)) {
1370N/A // a little hack for people who wanna play with resize
1370N/A this._listener[KEYDOWN] = Y.on(KEYDOWN, function(e) {
1370N/A if (e.keyCode !== 20) { /* scrollLock */
1370N/A return false;
1370N/A }
1370N/A var bb = that.get(BB);
1370N/A var style = bb.getStyle('overflow');
1370N/A style = (style === 'scroll') ? 'hidden' : 'scroll';
1370N/A bb.setStyle('overflow', style);
1370N/A style = bb.getStyle(RESIZE);
1370N/A if (style != 'both') {
1370N/A bb.setStyle(RESIZE, 'both');
1370N/A }
1370N/A });
1370N/A this._listener[RESIZE] = Y.on(RESIZE, function(e) {
1370N/A that._adjustPosition();
1370N/A that._fillHeight();
1370N/A });
1370N/A this._adjustPosition();
1370N/A this._fillHeight();
1370N/A }
1370N/A this.set(VISIBLE, true);
1383N/A },
1383N/A
1383N/A BUTTONS : {
1383N/A close: {
1383N/A label : 'Close',
1383N/A action : 'hide',
1383N/A section : 'header',
1383N/A classNames : getClassName('button', 'close')
1383N/A }
1383N/A },
1370N/A }, {
1370N/A // static
1370N/A ATTRS: {
1383N/A buttons : {
1383N/A value : ['close']
1383N/A },
1370N/A /* @attribute {Integer} preferred width of the panel */
1370N/A pWidth : {
1370N/A value: 240,
1370N/A validator: L.isNumber
1370N/A },
1370N/A /* @attribute {Integer} preferred height of the panel */
1370N/A pHeight : {
1370N/A value: 480,
1370N/A validator: L.isNumber
1370N/A },
1370N/A /* @attribute {} preferred distance of the panel incl. margins to
1370N/A * its "container" - used for positioning only. Invalid values are
1370N/A * treated as 0. */
1370N/A pMargin : {
1370N/A value: { top: 10, right: 10, bottom: 10, left: 10 },
1370N/A _setter: function (margin) {
1370N/A if (L.isNumber(margin)) {
1370N/A return { top: margin, right: margin, bottom: margin, left: margin };
1370N/A }
1370N/A if (L.isArray(margin)) {
1370N/A return {
1370N/A top : L.isNumber(margin[0]) || 0,
1370N/A right : L.isNumber(margin[1]) || 0,
1370N/A bottom : L.isNumber(margin[2]) || 0,
1370N/A left : L.isNumber(margin[3]) || 0
1370N/A };
1370N/A }
1370N/A if (L.isObject) {
1370N/A return {
1370N/A top : L.isNumber(margin[0]) || 0,
1370N/A right : L.isNumber(margin[1]) || 0,
1370N/A bottom : L.isNumber(margin[2]) || 0,
1370N/A left : L.isNumber(margin[3]) || 0
1370N/A }
1370N/A }
1370N/A return { top: 0, right: 0, bottom: 0, left: 0 };
1370N/A }
1370N/A },
1370N/A /* @attribute {Integer} CSS z-index value */
1370N/A zIndex : {
1370N/A value: 100
1370N/A }
1370N/A },
1370N/A
1370N/A /**
1370N/A * Create a node suitable to be used as <var>srcNode</var> aka content
1370N/A * box for an instance of SymbolPanel. The format for the symbolClass
1370N/A * parameter is as follows:
1370N/A * <pre>
1370N/A * symbolClass = '[' Section[','Section]*']'
1370N/A * Section = '[' SectionName',' CssClassName',' '[' Entry[',' Entry]* ']'']'
1370N/A * Entry = '[' SymbolName',' LineNumber ']'
1370N/A * *Name = &lt;String&gt;
1370N/A * *Number = &lt;Integer&gt;
1370N/A * </pre>
1370N/A * @param symbolClass symbol classes to use to create the body of the
1370N/A * panel.
1370N/A * @param title the text to show in the head of the content box.
1370N/A * @return a non-<code>null</code> node.
1370N/A */
1370N/A createSrcNode : function(symbolClass, title) {
1370N/A var Escape = Y.Escape;
1370N/A symbolClass || (symbolClass = []);
1370N/A title || (title = 'All Symbols');
1370N/A var contents = "<div id='symbolsCB'>"
1370N/A + "<div id='symbolsHd' class='yui3-widget-hd'><h3>" + title
1370N/A + "</h3></div>"
1370N/A + "<div id='symbols' class='yui3-widget-bd'>";
1370N/A for ( var i = 0; i < symbolClass.length; i++) {
1370N/A var symbol_class = symbolClass[i];
1370N/A var class_name = symbol_class[1];
1370N/A var symbols = symbol_class[2];
1370N/A contents += "<h4>" + symbol_class[0] + "</h4><ul>";
1370N/A for ( var j = 0; j < symbols.length; j++) {
1370N/A contents += "<li><a href='#" + symbols[j][1]
1370N/A + "' class='" + class_name + "'>"
1370N/A + Escape.html(symbols[j][0]) + "</a></li>";
1370N/A }
1370N/A contents += "</ul>"
1370N/A }
1370N/A contents += "</div>"
1370N/A + "<div id='symbolsFt' class='yui3-widget-ft'></div></div>"
1370N/A return Y.Node.create(contents);
1370N/A }
1370N/A });
1370N/A
1370N/A Y.SymbolsPanel = panel;
1370N/A}, '3.5.0pr2', {
1370N/A requires: ['widget', 'widget-autohide', 'widget-buttons',
1370N/A 'widget-position', 'widget-stack', 'widget-stdmod',
1370N/A 'dd-plugin', 'escape']
1370N/A});