UNPKG

sku-pg

Version:

Skulpt is a Javascript implementation of Python 2.x. Python that runs in your browser!

682 lines (589 loc) 20.5 kB
// Copyright 2006 The Closure Library Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * @fileoverview Definition of the RoundedCorners class. This depends on the * GSE servlet: http://go/roundedcornerservlet.java * The sevlet provides the images for that this class depends on for generating * the rounded corners. See com.google.javascript.closure.RoundedCornerServlet * for sample usage. * * */ goog.provide('goog.ui.RoundedCorners'); goog.provide('goog.ui.RoundedCorners.Corners'); goog.require('goog.Uri'); goog.require('goog.color'); goog.require('goog.dom'); goog.require('goog.math.Size'); goog.require('goog.string'); goog.require('goog.style'); goog.require('goog.userAgent'); /** * Class for constructing the HTML for a rounded corner border based on the * RoundedCornerServlet server class. * * @constructor * @param {goog.Uri|string} servletUri The uri to the RoundedCornerServlet for * fetching the rounded corner images. */ goog.ui.RoundedCorners = function(servletUri) { this.servletUri_ = servletUri; /** * Size of the border corners * @type {goog.math.Size} * @private */ this.size_ = new goog.math.Size(8, 8); /** * Which corners to show. * @type {number} * @private */ this.cornersToShow_ = goog.ui.RoundedCorners.Corners.ALL; }; /** * A convenience method to round the corners of a given element. * To achieve the rounding, the rounded corners div replaces the element in its * parent. The element is added as the content of the rounded corners div. * * @param {Element} element The element to provide with rounded corners. * @param {string} servletUri The uri to the RoundedCornerServlet for * fetching the rounded corner images. * @param {goog.math.Size=} opt_borderThickness The rounded corners border * see setBorderThickness(). If no value is supplied, (5, 5) will be used. * @param {number=} opt_corners The corners to round. A bitwise integer. If no * corners are specified, goog.ui.RoundedCorners.Corners.ALL will be used. */ goog.ui.RoundedCorners.roundElement = function( element, servletUri, opt_borderThickness, opt_corners) { var roundedCorners = new goog.ui.RoundedCorners(servletUri); roundedCorners.setColor(goog.style.getBackgroundColor(element)); // Look to the parent for a background color. var backgroundColor; var parent = /** @type {Element} */ (element.parentNode); backgroundColor = goog.style.getBackgroundColor(parent); // Default to white if the color is invalid. /** @preserveTry */ try { goog.color.parse(backgroundColor); } catch (ex) { backgroundColor = 'white'; } roundedCorners.setBackgroundColor(backgroundColor); if (!goog.isDef(opt_corners)) { opt_corners = goog.ui.RoundedCorners.Corners.ALL; } roundedCorners.setCornersToShow(opt_corners); if (!goog.isDef(opt_borderThickness)) { opt_borderThickness = new goog.math.Size(5, 5); } roundedCorners.setBorderThickness(opt_borderThickness); var roundedContainer = goog.dom.htmlToDocumentFragment( roundedCorners.getBackgroundHtml()); parent.replaceChild(roundedContainer, element); // Remove the content element, replace it with the element to round. goog.dom.removeNode(goog.dom.getLastElementChild(roundedContainer)); goog.dom.appendChild(roundedContainer, element); }; /** * Foreground color of the rounded corners * @type {string} * @private */ goog.ui.RoundedCorners.prototype.color_ = '#ff0000'; /** * Background color of the rounded corners * @type {string} * @private */ goog.ui.RoundedCorners.prototype.bgColor_ = ''; /** * Inner color of the rounded corners * @type {string} * @private */ goog.ui.RoundedCorners.prototype.inColor_ = ''; /** * HTML content that goes inside the template * @type {string} * @private */ goog.ui.RoundedCorners.prototype.content_ = ''; /** * Padding style for the internal content * @type {string} * @private */ goog.ui.RoundedCorners.prototype.padding_ = ''; /** * An explicit height for the HTML. If null, no height is specified * @type {?string} * @private */ goog.ui.RoundedCorners.prototype.height_ = null; /** * The format of the image. Either PNG or GIF * @type {string} * @private */ goog.ui.RoundedCorners.prototype.imageFormat_ = 'png'; /** * The width of the border line. If 0, width == corner radius * @type {number} * @private */ goog.ui.RoundedCorners.prototype.lineWidth_ = 0; /** * Enum for specifying which corners to include. * @enum {number} */ goog.ui.RoundedCorners.Corners = { /** * Include just the top-left corner. */ TOP_LEFT: 1, /** * Include just the top-right corner. */ TOP_RIGHT: 2, /** * Include just the bottom-left corner. */ BOTTOM_LEFT: 4, /** * Include just the bottom-right corner. */ BOTTOM_RIGHT: 8, /** * Include just the left corners. */ LEFT: 5, // TOP_LEFT | BOTTOM_LEFT /** * Include just the right corners. */ RIGHT: 10, // TOP_RIGHT | BOTTOM_RIGHT /** * Include just the top corners. */ TOP: 3, // TOP_LEFT | TOP_RIGHT /** * Include just the bottom corners. */ BOTTOM: 12, // BOTTOM_LEFT | BOTTOM_RIGHT /** * Include all corners. */ ALL: 15 // TOP | BOTTOM }; /** * Returns the foreground color * @return {string} The color in hex format. */ goog.ui.RoundedCorners.prototype.getColor = function() { return this.color_; }; /** * Sets the foreground color. * @param {string} color The color in a format parsable by goog.color.parse(). */ goog.ui.RoundedCorners.prototype.setColor = function(color) { this.color_ = goog.color.parse(color).hex; }; /** * Returns the background color * @return {string} The color in hex format or null for transparent. */ goog.ui.RoundedCorners.prototype.getBackgroundColor = function() { return this.bgColor_; }; /** * Sets the background color. * @param {string} bgColor The color in a format parsable by goog.color.parse() * or empty string if transparent. */ goog.ui.RoundedCorners.prototype.setBackgroundColor = function(bgColor) { if (goog.string.isEmpty(bgColor)) { this.bgColor_ = ''; } else { this.bgColor_ = goog.color.parse(bgColor).hex; } }; /** * Returns the inner color * @return {string} The color in hex format or null for transparent. */ goog.ui.RoundedCorners.prototype.getInnerColor = function() { return this.inColor_; }; /** * Sets the inner color. * @param {string} inColor The color in a format parsable by goog.color.parse() * or empty string if transparent. */ goog.ui.RoundedCorners.prototype.setInnerColor = function(inColor) { if (goog.string.isEmpty(inColor)) { this.inColor_ = ''; } else { this.inColor_ = goog.color.parse(inColor).hex; } }; /** * Returns the border thickness. The height and width specifies the width and * height of the corner images that form the arcs. The height dictates the * thickness of the top and bottom borders and width dicates the thickness of * the left and right borders. * * @return {goog.math.Size} The border size. */ goog.ui.RoundedCorners.prototype.getBorderThickness = function() { return this.size_; }; /** * Sets the border thickness. The height and width specifies the width and * height of the corner images that form the arcs. The height dictates the * thickness of the top and bottom borders and width dicates the thickness of * the left and right borders. * * @param {goog.math.Size} size The border size. */ goog.ui.RoundedCorners.prototype.setBorderThickness = function(size) { this.size_ = size; }; /** * Returns the explicit height of the element creating the border or * background. * For the #getBorderHtml case, this usually isn't necessary to set as it will * size to content. For the #getBackgroundHtml case, this may be necessary to * set in certain cases in IE because of an off-by-1 bug in IE's bottom * positioning code. * * @return {?string} The height as a style string (e.g. '2px' or '3em'). */ goog.ui.RoundedCorners.prototype.getExplicitHeight = function() { return this.height_; }; /** * Sets the explicit height of the element creating the border or background. * For the #getBorderHtml case, this usually isn't necessary to set as it will * size to content. For the #getBackgroundHtml case, this may be necessary to * set in certain cases in IE because of an off-by-1 bug in IE's bottom * positioning code. * * @param {string} height The height as a style string (e.g. '2px' or '3em'). */ goog.ui.RoundedCorners.prototype.setExplicitHeight = function(height) { this.height_ = height; }; /** * Returns the padding of the rounded corner border. * * @return {string} The padding as a style string (e.g. '2px 4px'). */ goog.ui.RoundedCorners.prototype.getPadding = function() { return this.padding_; }; /** * Sets the padding of the rounded corner border. * * @param {string} padding The padding as a style string (e.g. '2px 4px'). */ goog.ui.RoundedCorners.prototype.setPadding = function(padding) { this.padding_ = padding; }; /** * Returns the width of the border line. If 0, border is width/height * of corners * * @return {number} The width. */ goog.ui.RoundedCorners.prototype.getLineWidth = function() { return this.lineWidth_; }; /** * Sets the width of the border line. If 0, border is width/height * of corners * * @param {number} lineWidth The width. */ goog.ui.RoundedCorners.prototype.setLineWidth = function(lineWidth) { this.lineWidth_ = lineWidth; }; /** * Returns which corners to show * * @return {number} The corners to show. */ goog.ui.RoundedCorners.prototype.getCornersToShow = function() { return this.cornersToShow_; }; /** * Sets which corners to show * * @param {number} cornersToShow The corners to show. */ goog.ui.RoundedCorners.prototype.setCornersToShow = function(cornersToShow) { this.cornersToShow_ = cornersToShow; }; /** * Returns the image format. Currently, only png and gif are supported. * * @return {string} The image format. */ goog.ui.RoundedCorners.prototype.getImageFormat = function() { return this.imageFormat_; }; /** * Sets the image format. Currently, only png and gif are supported. * * @param {string} imageFormat The image format. */ goog.ui.RoundedCorners.prototype.setImageFormat = function(imageFormat) { if (imageFormat != 'png' && imageFormat != 'gif') { throw Error('Image format must be \'png\' or \'gif\''); } this.imageFormat_ = imageFormat; }; /** * Returns the content of the borders * * @return {string} The content of the borders. */ goog.ui.RoundedCorners.prototype.getContent = function() { return this.content_; }; /** * Sets the content of the borders * * @param {string} html The content of the borders. */ goog.ui.RoundedCorners.prototype.setContent = function(html) { this.content_ = html; }; /** * Returns the HTML of a 9-cell table (when all corners are needed) that uses * transparent images in the corners, a solid color on the sides, and the * content in the middle cell. * * @return {string} The html of the table. */ goog.ui.RoundedCorners.prototype.getBorderHtml = function() { // TODO(user): convert to client-side template mechanism when one exists // the html is built like a template so that this can later be // converted easily to a templating mechanism like JST. var sb = []; sb.push('<table border=0 style="empty-cells:show;' + 'border-collapse:{{%collapse}};' + 'table-layout:fixed;width:100%;margin:0;padding:0;' + 'height:{{%heightStyle}}" cellspacing=0 cellpadding=0>'); if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.TOP_LEFT || this.cornersToShow_ & goog.ui.RoundedCorners.Corners.BOTTOM_LEFT) { sb.push('<col width="{{%w}}">'); } sb.push('<col>'); if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.TOP_RIGHT || this.cornersToShow_ & goog.ui.RoundedCorners.Corners.BOTTOM_LEFT) { sb.push('<col width="{{%w}}">'); } if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.TOP_LEFT || this.cornersToShow_ & goog.ui.RoundedCorners.Corners.TOP_RIGHT) { sb.push('<tr>'); if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.TOP_LEFT) { sb.push('<td style="{{%tlStyle}}; width:{{%w}}px; height:{{%h}}px">' + '</td>'); } sb.push('<td style="{{%tmColor}}"></td>'); if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.TOP_RIGHT) { sb.push('<td style="{{%trStyle}}; width:{{%w}}px; height:{{%h}}px">' + '</td>'); } sb.push('</tr>'); } sb.push('<tr>'); if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.TOP_LEFT || this.cornersToShow_ & goog.ui.RoundedCorners.Corners.BOTTOM_LEFT) { sb.push('<td style="{{%mlStyle}};{{%mlColor}};width:{{%w}}px;"></td>'); } sb.push('<td style="padding: {{%p}}">{{%content}}</td>'); if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.TOP_RIGHT || this.cornersToShow_ & goog.ui.RoundedCorners.Corners.BOTTOM_RIGHT) { sb.push('<td style="{{%mrStyle}}; {{%mrColor}};width:{{%w}}px;"></td>'); } sb.push('</tr>'); if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.BOTTOM_LEFT || this.cornersToShow_ & goog.ui.RoundedCorners.Corners.BOTTOM_RIGHT) { sb.push('<tr>'); if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.BOTTOM_LEFT) { sb.push('<td style="{{%blStyle}} width:{{%w}}px; height:{{%h}}px;">' + '</td>'); } sb.push('<td style="{{%bmColor}}"></td>'); if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.BOTTOM_RIGHT) { sb.push('<td style="{{%brStyle}};width:{{%w}}px; height:{{%h}}px">' + '</td>'); } sb.push('</tr>'); } sb.push('</table>'); return this.performTemplateSubstitutions_(sb.join('')); }; /** * Returns the HTML for a relatively positioned DIV that includes four * absolutely positioned DIVs for the corner images and a DIV for the content. * * @return {string} The html of the table. */ goog.ui.RoundedCorners.prototype.getBackgroundHtml = function() { // TODO(user): convert to client-side template mechanism when one exists // the html is built like a template so that this can later be converted // easily to a templating mechanism like JST. var sb = []; sb.push('<div style="position:relative;padding:{{%p}};' + 'background-color:{{%color}};height:{{%heightStyle}}">'); if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.TOP_LEFT) { sb.push('<div style="{{%tlStyle}};width:{{%w}}px; height:{{%h}}px;' + 'position:absolute;top:0;left:0;font-size:0"></div>'); } if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.BOTTOM_LEFT) { sb.push('<div style="{{%blStyle}};width:{{%w}}px; height:{{%h}}px;' + 'position:absolute;bottom:0px;left:0;font-size:0"></div>'); } if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.BOTTOM_RIGHT) { sb.push('<div style="{{%brStyle}};width:{{%w}}px; height:{{%h}}px;' + 'position:absolute;bottom:0px;right:0;font-size:0"></div>'); } if (this.cornersToShow_ & goog.ui.RoundedCorners.Corners.TOP_RIGHT) { sb.push('<div style="{{%trStyle}};width:{{%w}}px; height:{{%h}}px;' + 'position:absolute;top:0;right:0;font-size:0"></div>'); } sb.push('<div>{{%content}}</div>'); sb.push('</div>'); return this.performTemplateSubstitutions_(sb.join('')); }; /** * Performs the substitutions in the templates to values determined at runtime. * @param {string} htmlTemplate The template to use. * @return {string} The template with the substitutions. * @private */ goog.ui.RoundedCorners.prototype.performTemplateSubstitutions_ = function(htmlTemplate) { var html = htmlTemplate; var ctx = this.getCtx_(); for (var key in ctx) { var regex = new RegExp('{{%' + key + '}}', 'g'); html = html.replace(regex, ctx[key]); } return html; }; /** * Returns the context object used by the template mechanism * @return {Object} The context object. * @private */ goog.ui.RoundedCorners.prototype.getCtx_ = function() { var colorHex = this.color_.substring(1); var ctx = {}; ctx['tlStyle'] = this.getCornerStyle_('tl'); ctx['trStyle'] = this.getCornerStyle_('tr'); ctx['mlStyle'] = ''; ctx['mrStyle'] = ''; ctx['blStyle'] = this.getCornerStyle_('bl'); ctx['brStyle'] = this.getCornerStyle_('br'); if (this.cornersToShow_ == goog.ui.RoundedCorners.Corners.RIGHT) { ctx['tlStyle'] = ctx['mlStyle'] = ctx['blStyle'] = 'display:none'; } else if (this.cornersToShow_ == goog.ui.RoundedCorners.Corners.LEFT) { ctx['trStyle'] = ctx['mrStyle'] = ctx['brStyle'] = 'display:none'; } if (this.height_ != null) { ctx['heightStyle'] = this.height_; } else { ctx['heightStyle'] = goog.userAgent.IE && goog.userAgent.VERSION < 7 ? '0px;' : 'auto;'; } ctx['color'] = this.color_; ctx['mlColor'] = this.colorStyleFor_('left'); ctx['mrColor'] = this.colorStyleFor_('right'); ctx['tmColor'] = this.colorStyleFor_('top'); ctx['bmColor'] = this.colorStyleFor_('bottom'); ctx['collapse'] = this.lineWidth_ ? (goog.userAgent.IE ? 'collapse' : '') : 'collapse'; ctx['w'] = this.size_.width; ctx['h'] = this.size_.height; ctx['p'] = this.padding_; ctx['content'] = this.content_; return ctx; }; /** * Get the CSS style for a given side with the current diplay parameters. * Will return either a background or border color * @param {string} side The side: left|top|right|bottom. * @return {string} The style. * @private */ goog.ui.RoundedCorners.prototype.colorStyleFor_ = function(side) { return this.lineWidth_ ? 'border-' + side + ': ' + this.lineWidth_ + 'px solid ' + this.color_ : 'background-color:' + this.color_; }; /** * Returns the background image style string that uses AlphaImageLoader for IE6 * and background-images for other browsers * @param {string} corner The corner of the image. * @return {string} The style string. * @private */ goog.ui.RoundedCorners.prototype.getCornerStyle_ = function(corner) { var uri = this.createUri_(corner); if ((goog.string.isEmpty(this.color_) || goog.string.isEmpty(this.bgColor_) || goog.string.isEmpty(this.inColor_)) && goog.userAgent.IE && goog.userAgent.VERSION > 5.5 && goog.userAgent.VERSION < 7) { // if need transparency, must do this in < IE7 return 'filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + uri + '\', sizingMethod=\'crop\')'; } else { return 'background: url(' + uri + ') no-repeat top left;'; } }; /** * Returns the image Uri for a specific corner image. * @param {string} corner The corner of the image. * @return {goog.Uri} The uri. * @private */ goog.ui.RoundedCorners.prototype.createUri_ = function(corner) { // e.g. rc?a=tl&c=#aaa&w=8&h=8 var uri = new goog.Uri(this.servletUri_); uri.setParameterValue('a', corner); uri.setParameterValue('c', this.removeHash_(this.color_)); uri.setParameterValue('bc', this.removeHash_(this.bgColor_)); uri.setParameterValue('ic', this.removeHash_(this.inColor_)); uri.setParameterValue('w', String(this.size_.width)); uri.setParameterValue('h', String(this.size_.height)); uri.setParameterValue('lw', String(this.lineWidth_)); uri.setParameterValue('m', this.imageFormat_); return uri; }; /** * Helper function to remove hash from the color string * @param {string} s The string to remove the has from. * @return {string} The color name without the hash. * @private */ goog.ui.RoundedCorners.prototype.removeHash_ = function(s) { if (goog.string.startsWith(s, '#')) { return s.substring(1); } return s; };