Author: lindner
Date: Mon Aug 9 10:51:15 2010
New Revision: 983578
URL: http://svn.apache.org/viewvc?rev=983578&view=rev
Log:
SHINDIG-1401 | Patch from Vadim Gerasimov | Adding Wave feature to support Wave
Gadget API
Added:
shindig/trunk/extras/src/main/javascript/features-extras/wave/
shindig/trunk/extras/src/main/javascript/features-extras/wave/base.js
shindig/trunk/extras/src/main/javascript/features-extras/wave/dynamic-width.js
shindig/trunk/extras/src/main/javascript/features-extras/wave/externs.js
shindig/trunk/extras/src/main/javascript/features-extras/wave/fake_gadgets.js
shindig/trunk/extras/src/main/javascript/features-extras/wave/feature.xml
shindig/trunk/extras/src/main/javascript/features-extras/wave/participant.js
shindig/trunk/extras/src/main/javascript/features-extras/wave/state.js
shindig/trunk/extras/src/main/javascript/features-extras/wave/taming.js
shindig/trunk/extras/src/main/javascript/features-extras/wave/util.js
shindig/trunk/extras/src/main/javascript/features-extras/wave/wave.js
shindig/trunk/extras/src/main/javascript/features-extras/wave/wave.ui.js
Modified:
shindig/trunk/extras/src/main/javascript/features-extras/features.txt
Modified: shindig/trunk/extras/src/main/javascript/features-extras/features.txt
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/features.txt?rev=983578&r1=983577&r2=983578&view=diff
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/features.txt
(original)
+++ shindig/trunk/extras/src/main/javascript/features-extras/features.txt Mon
Aug 9 10:51:15 2010
@@ -17,3 +17,4 @@
# under the License.
features-extras/org.jquery.core-1.4.2/feature.xml
+features-extras/wave/feature.xml
Added: shindig/trunk/extras/src/main/javascript/features-extras/wave/base.js
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/wave/base.js?rev=983578&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/wave/base.js
(added)
+++ shindig/trunk/extras/src/main/javascript/features-extras/wave/base.js Mon
Aug 9 10:51:15 2010
@@ -0,0 +1,136 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * 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 Provides the top level wave object.
+ */
+
+/**
+ * @namespace This namespace defines the top level wave object
+ * within the Wave Gadgets API.
+ */
+var wave = wave || {};
+
+/**
+ * Constructs a callback given the provided callback
+ * and an optional context.
+ *
+ * @constructor
+ * @this {wave.Callback}
+ * @class This class is an immutable utility class for handlings callbacks
+ * with variable arguments and an optional context.
+ * @param {?(function(wave.State=, Object.<string, string>=)|
+ * function(Array.<wave.Participant>=)|
+ * function(wave.Mode.<number>=)
+ * )} callback A callback function
+ * or null.
+ * @param {Object=} opt_context If context is specified, the method will be
+ * called back in the context of that object (optional).
+ */
+wave.Callback = function(callback, opt_context) {
+ this.callback_ = callback;
+ this.context_ = opt_context || null;
+};
+
+/**
+ * Invokes the callback method with any arguments passed.
+ *
+ * @param {...} var_args
+ * @export
+ */
+wave.Callback.prototype.invoke = function(var_args) {
+ if (this.callback_) {
+ this.callback_.apply(this.context_, arguments);
+ }
+};
+
+/**
+ * @name wave.Mode
+ * @class Identifiers for wave modes exhibited by the blip containing
+ * the gadget.
+ * @enum {number}
+ * @export
+ */
+wave.Mode = {
+ /**
+ * @member wave.Mode
+ * @constant
+ * @name UNKNOWN
+ * @desc The blip containing the gadget is in an unknown mode.
+ * In this case, you should not attempt to edit the blip.
+ */
+ UNKNOWN: 0,
+ /**
+ * @member wave.Mode
+ * @constant
+ * @name VIEW
+ * @desc The blip containing the gadget is in view, but not edit mode.
+ */
+ VIEW: 1,
+ /**
+ * @member wave.Mode
+ * @constant
+ * @name EDIT
+ * @desc Editing the gadget blip
+ */
+ EDIT: 2,
+ /**
+ * @member wave.Mode
+ * @constant
+ * @name DIFF_ON_OPEN
+ * @desc The blip containing the gadget has changed since the last time
+ * it was opened and the gadget should notify this change to the user.
+ */
+ DIFF_ON_OPEN: 3,
+ /**
+ * @member wave.Mode
+ * @constant
+ * @name PLAYBACK
+ * @desc The blip containing the gadget is in playback mode.
+ */
+ PLAYBACK: 4
+}
+
+wave.API_PARAM_ = "wave";
+
+wave.ID_PARAM_ = "waveId";
+
+wave.id_ = null;
+
+wave.viewer_ = null;
+
+wave.host_ = null;
+
+wave.participants_ = [];
+
+wave.participantMap_ = {};
+
+wave.participantCallback_ = new wave.Callback(null);
+
+wave.state_ = null;
+
+wave.stateCallback_ = new wave.Callback(null);
+
+wave.privateState_ = null;
+
+wave.privateStateCallback_ = new wave.Callback(null);
+
+wave.mode_ = null;
+
+wave.modeCallback_ = new wave.Callback(null);
+
+wave.inWaveContainer_ = false;
Added:
shindig/trunk/extras/src/main/javascript/features-extras/wave/dynamic-width.js
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/wave/dynamic-width.js?rev=983578&view=auto
==============================================================================
---
shindig/trunk/extras/src/main/javascript/features-extras/wave/dynamic-width.js
(added)
+++
shindig/trunk/extras/src/main/javascript/features-extras/wave/dynamic-width.js
Mon Aug 9 10:51:15 2010
@@ -0,0 +1,176 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * 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.
+ *
+ */
+
+// TODO: Define a more convenient set of methods for iframe resizing in wave.
+
+/**
+ * @fileoverview This library augments gadgets.window with functionality
+ * to change the width of a gadget dynamically. Derived from the
+ * dynamic-height feature source code.
+ * See:
+ *
http://svn.apache.org/repos/asf/shindig/trunk/features/src/main/javascript/features/dynamic-height/dynamic-height.js
+ */
+
+/**
+ * @static
+ * @class This namespace is used by the Gadgets API for the features it offers
+ * in all containers, including Wave. Those are documented here:
+ * http://code.google.com/apis/gadgets/docs/reference/
+ * @name gadgets
+ */
+
+/**
+ * @static
+ * @class This namespace is defined by the Gadgets API, and documented here:
+ * http://code.google.com/apis/gadgets/docs/reference/#gadgets.window <br>
+ * The Wave Gadgets API adds an additional method on top of the set documented
+ * there.
+ * @name gadgets.window
+ */
+gadgets.window = gadgets.window || {};
+
+// we wrap these in an anonymous function to avoid storing private data
+// as members of gadgets.window.
+(function() {
+
+ var oldWidth;
+
+ /**
+ * Parse out the value (specified in px) for a CSS attribute of an element.
+ *
+ * @param {Element} elem the element with the attribute to look for.
+ * @param {string} attr the CSS attribute name of interest.
+ * @returns {number} the value of the px attr of the elem.
+ * @private
+ */
+ function parseIntFromElemPxAttribute(elem, attr) {
+ var style = window.getComputedStyle(elem, "");
+ var value = style.getPropertyValue(attr);
+ value.match(/^([0-9]+)/);
+ return parseInt(RegExp.$1, 10);
+ }
+
+ /**
+ * For Webkit-based browsers, calculate the width of the gadget iframe by
+ * iterating through all elements in the gadget, starting with the body tag.
+ * It is not sufficient to only account body children elements, because
+ * CSS style position "float" may place a child element outside of the
+ * containing parent element. Not counting "float" elements may lead to
+ * undercounting.
+ *
+ * @returns {number} the width of the gadget.
+ * @private
+ */
+ function getWidthForWebkit() {
+ var result = 0;
+ var queue = [ document.body ];
+
+ while (queue.length > 0) {
+ var elem = queue.shift();
+ var children = elem.childNodes;
+
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+ if (typeof child.offsetLeft !== 'undefined' &&
+ typeof child.scrollWidth !== 'undefined') {
+ // scrollHeight already accounts for border-bottom, padding-bottom.
+ var right = child.offsetLeft + child.scrollWidth +
+ parseIntFromElemPxAttribute(child, "margin-right");
+ result = Math.max(result, right);
+ }
+ queue.push(child);
+ }
+ }
+
+ // Add border, padding and margin of the containing body.
+ return result
+ + parseIntFromElemPxAttribute(document.body, "border-right")
+ + parseIntFromElemPxAttribute(document.body, "margin-right")
+ + parseIntFromElemPxAttribute(document.body, "padding-right");
+ }
+
+ /**
+ * Adjusts the gadget width
+ * @param {number=} opt_width An optional preferred width in pixels. If not
+ * specified, will attempt to fit the gadget to its content.
+ * @member gadgets.window
+ */
+ gadgets.window.adjustWidth = function(opt_width) {
+ var newWidth = parseInt(opt_width, 10);
+ var widthAutoCalculated = false;
+ if (isNaN(newWidth)) {
+ widthAutoCalculated = true;
+
+ // Resize the gadget to fit its content.
+
+ // Get the width of the viewport
+ var vw = gadgets.window.getViewportDimensions().width;
+ var body = document.body;
+ var docEl = document.documentElement;
+ if (document.compatMode === 'CSS1Compat' && docEl.scrollWidth) {
+ // In Strict mode:
+ // The inner content height is contained in either:
+ // document.documentElement.scrollWidth
+ // document.documentElement.offsetWidth
+ // Based on studying the values output by different browsers,
+ // use the value that's NOT equal to the viewport width found above.
+ newWidth = docEl.scrollWidth !== vw ?
+ docEl.scrollWidth : docEl.offsetWidth;
+ } else if (navigator.userAgent.indexOf('AppleWebKit') >= 0) {
+ // In Webkit:
+ // Property scrollWidth and offsetWidth will only increase in value.
+ // This will incorrectly calculate reduced width of a gadget
+ // (ie: made smaller).
+ newWidth = getWidthForWebkit();
+ } else if (body && docEl) {
+ // In Quirks mode:
+ // documentElement.clientWidth is equal to documentElement.offsetWidth
+ // except in IE. In most browsers, document.documentElement can be
used
+ // to calculate the inner content width.
+ // However, in other browsers (e.g. IE), document.body must be used
+ // instead. How do we know which one to use?
+ // If document.documentElement.clientWidth does NOT equal
+ // document.documentElement.offsetWidth, then use document.body.
+ var sw = docEl.scrollWidth;
+ var ow = docEl.offsetWidth;
+ if (docEl.clientWidth !== ow) {
+ sw = body.scrollWidth;
+ ow = body.offsetWidth;
+ }
+
+ // Detect whether the inner content width is bigger or smaller
+ // than the bounding box (viewport). If bigger, take the larger
+ // value. If smaller, take the smaller value.
+ if (sw > vw) {
+ // Content is larger
+ newWidth = sw > ow ? sw : ow;
+ } else {
+ // Content is smaller
+ newWidth = sw < ow ? sw : ow;
+ }
+ }
+ }
+
+ // Only make the RPC call if width has changed
+ if (newWidth !== oldWidth &&
+ !isNaN(newWidth) &&
+ !(widthAutoCalculated && newWidth === 0)) {
+ oldWidth = newWidth;
+ gadgets.rpc.call(null, "setIframeWidth", null, newWidth);
+ }
+ };
+}());
Added: shindig/trunk/extras/src/main/javascript/features-extras/wave/externs.js
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/wave/externs.js?rev=983578&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/wave/externs.js
(added)
+++ shindig/trunk/extras/src/main/javascript/features-extras/wave/externs.js
Mon Aug 9 10:51:15 2010
@@ -0,0 +1,25 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * 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 Contains variable declarations so that the jscompiler
+ * will not report errors on these objects.
+ */
+
+var gadgets;
+gadgets.rpc;
+gadgets.rpc.call = function(parent, serviceName, opt_callback, opt_params) {};
Added:
shindig/trunk/extras/src/main/javascript/features-extras/wave/fake_gadgets.js
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/wave/fake_gadgets.js?rev=983578&view=auto
==============================================================================
---
shindig/trunk/extras/src/main/javascript/features-extras/wave/fake_gadgets.js
(added)
+++
shindig/trunk/extras/src/main/javascript/features-extras/wave/fake_gadgets.js
Mon Aug 9 10:51:15 2010
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * 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 Provides stubs and fakes for the gadgets namespace
+ * that is used in the API. This is used by jsunit tests.
+ */
+var gadgets = gadgets || {};
+
+gadgets.util = {};
+
+gadgets.util.registerOnLoadHandler = function(callback) {
+ callback.call();
+};
+
+gadgets.util.getUrlParameters = function() {
+ var params = {};
+ var waveParamName = 'wave';
+ params[waveParamName] = true;
+ params.hasOwnProperty = function(key) {
+ return !!this[key];
+ }
+ return params;
+};
+
+gadgets.json = {};
+
+gadgets.json.parse = function(data) {
+ return data;
+};
+
+gadgets.rpc = {};
+
+gadgets.rpc.register = function() {};
+
+gadgets.rpc.call = function() {};
Added: shindig/trunk/extras/src/main/javascript/features-extras/wave/feature.xml
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/wave/feature.xml?rev=983578&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/wave/feature.xml
(added)
+++ shindig/trunk/extras/src/main/javascript/features-extras/wave/feature.xml
Mon Aug 9 10:51:15 2010
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you 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.
+-->
+<feature>
+ <name>wave</name>
+ <dependency>dynamic-height</dependency>
+ <dependency>locked-domain</dependency>
+ <dependency>rpc</dependency>
+ <gadget>
+ <script src="base.js"/>
+ <script src="dynamic-width.js"/>
+ <script src="participant.js"/>
+ <script src="state.js"/>
+ <script src="taming.js"/>
+ <script src="util.js"/>
+ <script src="wave.js"/>
+ <script src="wave.ui.js"/>
+ </gadget>
+</feature>
Added:
shindig/trunk/extras/src/main/javascript/features-extras/wave/participant.js
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/wave/participant.js?rev=983578&view=auto
==============================================================================
---
shindig/trunk/extras/src/main/javascript/features-extras/wave/participant.js
(added)
+++
shindig/trunk/extras/src/main/javascript/features-extras/wave/participant.js
Mon Aug 9 10:51:15 2010
@@ -0,0 +1,85 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * 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 Provides classes for defining and managing participants
+ * on a wave.
+ */
+
+/**
+ * Creates a new participant.
+ *
+ * @class This class specifies participants on a wave.
+ * @constructor
+ * Participant information can be dynamically updated (except for IDs).
+ * This includes the thumbnail URL, display name, and any future extensions to
+ * the participant. Instead of storing this information, gadgets should update
+ * displayed participant data each time they receive a participant callback.
+ * @this {wave.Participant}
+ * @param {string=} id Participant id.
+ * @param {string=} displayName Participant display name.
+ * @param {string=} thumbnailUrl Profile thumbnail URL.
+ */
+wave.Participant = function(id, displayName, thumbnailUrl) {
+ this.id_ = id || '';
+ this.displayName_ = displayName || '';
+ this.thumbnailUrl_ = thumbnailUrl || '';
+};
+
+/**
+ * Gets the unique identifier of this participant.
+ *
+ * @return {string} The participant's id.
+ * @export
+ */
+wave.Participant.prototype.getId = function() {
+ return this.id_;
+};
+
+/**
+ * Gets the human-readable display name of this participant.
+ *
+ * @return {string} The participant's human-readable display name.
+ * @export
+ */
+wave.Participant.prototype.getDisplayName = function() {
+ return this.displayName_;
+};
+
+/**
+ * Gets the url of the thumbnail image for this participant.
+ *
+ * @return {string} The participant's thumbnail image url.
+ * @export
+ */
+wave.Participant.prototype.getThumbnailUrl = function() {
+ return this.thumbnailUrl_;
+};
+
+/**
+ * Constructs a Participant object from JSON data.
+ *
+ * @param {!Object.<string, string>} json JSON object.
+ * @return {wave.Participant}
+ */
+wave.Participant.fromJson_ = function(json) {
+ var p = new wave.Participant();
+ p.id_ = json['id'];
+ p.displayName_ = json['displayName'];
+ p.thumbnailUrl_ = json['thumbnailUrl'];
+ return p;
+};
Added: shindig/trunk/extras/src/main/javascript/features-extras/wave/state.js
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/wave/state.js?rev=983578&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/wave/state.js
(added)
+++ shindig/trunk/extras/src/main/javascript/features-extras/wave/state.js Mon
Aug 9 10:51:15 2010
@@ -0,0 +1,167 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * 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 Provides classes for defining and managing the
+ * synchronized gadget state.
+ */
+
+/**
+ * Creates a new state object to hold properties of the gadget.
+ *
+ * @constructor
+ * @class This class contains state properties of the Gadget.
+ * @this {wave.State}
+ * @param {string=} opt_rpc rpc name
+ * @export
+ */
+wave.State = function(opt_rpc) {
+ this.setState_(null);
+ this.rpc_ = opt_rpc === undefined ? 'wave_gadget_state' : opt_rpc;
+};
+
+/**
+ * Retrieve a value from the synchronized state.
+ * As of now, get always returns a string. This will change at some point
+ * to return whatever was set.
+ *
+ * @param {string} key Value for the specified key to retrieve.
+ * @param {?string=} opt_default Optional default value if non-existant
+ * (optional).
+ * @return {?string} Object for the specified key or null if not found.
+ * @export
+ */
+wave.State.prototype.get = function(key, opt_default) {
+ if (key in this.state_) {
+ return this.state_[key];
+ }
+ return opt_default === undefined ? null: opt_default;
+};
+
+/**
+ * Retrieve the valid keys for the synchronized state.
+ *
+ * @return {Array.<string>} set of keys
+ * @export
+ */
+wave.State.prototype.getKeys = function() {
+ var keys = [];
+ for (var key in this.state_) {
+ keys.push(key);
+ }
+ return keys;
+};
+
+/**
+ * Updates the state delta. This is an asynchronous call that
+ * will update the state and not take effect immediately. Creating
+ * any key with a null value will attempt to delete the key.
+ *
+ * @param {!Object.<string, ?string>} delta Map of key-value pairs representing
+ * a delta of keys to update.
+ * @export
+ */
+wave.State.prototype.submitDelta = function(delta) {
+ gadgets.rpc.call(null, this.rpc_, null, delta);
+};
+
+/**
+ * Submits delta that contains only one key-value pair. Note that if value is
+ * null the key will be removed from the state.
+ * See submitDelta(delta) for semantic details.
+ *
+ * @param {string} key
+ * @param {?string} value
+ * @export
+ */
+wave.State.prototype.submitValue = function(key, value) {
+ var delta = {};
+ delta[key] = value;
+ this.submitDelta(delta);
+};
+
+/**
+ * Submits a delta to remove all key-values in the state.
+ *
+ * @export
+ */
+wave.State.prototype.reset = function() {
+ var delta = {};
+ for (var key in this.state_) {
+ delta[key] = null;
+ }
+ this.submitDelta(delta);
+};
+
+/**
+ * Pretty prints the current state object. Note this is a debug method
+ * only.
+ *
+ * @return {string} The stringified state.
+ * @export
+ */
+wave.State.prototype.toString = function() {
+ return wave.util.printJson(this.state_, true);
+};
+
+/**
+ * Set the state object to the given value.
+ *
+ * @param {Object.<string, string>} state
+ */
+wave.State.prototype.setState_ = function(state) {
+ this.state_ = state || {};
+};
+
+/**
+ * Calculate a delta object that would turn this state into the state given
+ * in the parameter when applied to this state.
+ *
+ * @param {!Object.<string, string>} state
+ * @return {!Object.<string, string>} delta
+ */
+wave.State.prototype.calculateDelta_ = function(state) {
+ var delta = {};
+ for (var key in state) {
+ var hasKey = this.state_.hasOwnProperty(key);
+ if (!hasKey || (this.state_[key] != state[key])) {
+ delta[key] = state[key];
+ }
+ }
+ for (var key in this.state_) {
+ if (!state.hasOwnProperty(key)) {
+ delta[key] = null;
+ }
+ }
+ return delta;
+};
+
+/**
+ * Apply the given delta object to this state.
+ *
+ * @param {!Object.<string, string>} delta
+ */
+wave.State.prototype.applyDelta_ = function(delta) {
+ this.state_ = this.state_ || {};
+ for (var key in delta) {
+ if (delta[key] != null) {
+ this.state_[key] = delta[key];
+ } else {
+ delete this.state_[key];
+ }
+ }
+};
Added: shindig/trunk/extras/src/main/javascript/features-extras/wave/taming.js
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/wave/taming.js?rev=983578&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/wave/taming.js
(added)
+++ shindig/trunk/extras/src/main/javascript/features-extras/wave/taming.js Mon
Aug 9 10:51:15 2010
@@ -0,0 +1,92 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * 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 Tame and expose wave.* API to cajoled gadgets.
+ */
+
+var tamings___ = tamings___ || [];
+var caja___;
+var ___;
+tamings___.push(function(imports) {
+ // wave.Mode is an object literal that holds only constants
+ ___.grantRead(wave, 'Mode');
+
+ /**
+ * The following taming of wave.Callback and wave.Callback.invoke
+ * is needed because:
+ * - wave.Callback is exposed to cajoled code
+ * - wave.Callback.invoke is exposed to cajoled code
+ * - the wave api invokes some callbacks constructed by itself
+ * and others constructed by cajoled code
+ */
+ function SafeCallback(tameCallback, opt_tameContext) {
+ var okCallback = {apply: ___.markFuncFreeze(function(ignored, args) {
+ return ___.callPub(tameCallback, 'apply', [opt_tameContext, args]);
+ })};
+ return new wave.Callback(okCallback, ___.USELESS);
+ }
+
+ SafeCallback.prototype = wave.Callback.prototype;
+ wave.Callback.prototype.constructor = SafeCallback;
+ ___.markCtor(SafeCallback, Object, 'Callback');
+ ___.primFreeze(SafeCallback);
+ ___.tamesTo(wave.Callback, SafeCallback);
+
+ ___.handleGenericMethod(SafeCallback.prototype, 'invoke', function(var_args)
{
+ return ___.callPub(this.callback_, 'apply', [___.tame(this.context_),
+ Array.slice(arguments, 0)]);
+ });
+
+ caja___.whitelistCtors([
+ [wave, 'Participant', Object],
+ [wave, 'State', Object]
+ ]);
+
+ caja___.whitelistMeths([
+ [wave.Participant, 'getDisplayName'],
+ [wave.Participant, 'getId'],
+ [wave.Participant, 'getThumbnailUrl'],
+
+ [wave.State, 'get'],
+ [wave.State, 'getKeys'],
+ [wave.State, 'reset'],
+ [wave.State, 'submitDelta'],
+ [wave.State, 'submitValue'],
+ [wave.State, 'toString']
+ ]);
+
+ caja___.whitelistFuncs([
+ [wave, 'getHost'],
+ [wave, 'getMode'],
+ [wave, 'getParticipantById'],
+ [wave, 'getParticipants'],
+ [wave, 'getState'],
+ [wave, 'getTime'],
+ [wave, 'getViewer'],
+ [wave, 'isInWaveContainer'],
+ [wave, 'log'],
+ [wave, 'setModeCallback'],
+ [wave, 'setParticipantCallback'],
+ [wave, 'setStateCallback'],
+
+ [wave.util, 'printJson']
+ ]);
+
+ imports.outers.wave = ___.tame(wave);
+ ___.grantRead(imports.outers, 'wave');
+});
Added: shindig/trunk/extras/src/main/javascript/features-extras/wave/util.js
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/wave/util.js?rev=983578&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/wave/util.js
(added)
+++ shindig/trunk/extras/src/main/javascript/features-extras/wave/util.js Mon
Aug 9 10:51:15 2010
@@ -0,0 +1,92 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * 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 Provides utility methods.
+ */
+
+/**
+ * @namespace This namespace defines utility methods for use within
+ * the Wave Gadgets API.
+ */
+wave.util = wave.util || {};
+
+wave.util.SPACES_ = ' ';
+
+wave.util.toSpaces_ = function(tabs) {
+ return wave.util.SPACES_.substring(0, tabs * 2);
+}
+
+wave.util.isArray_ = function(obj) {
+ try {
+ return obj && typeof(obj.length) == 'number';
+ } catch (e) {
+ return false;
+ }
+};
+
+/**
+ * Outputs JSON objects in text format. Optionally pretty print.
+ *
+ * @param {Object} obj The object to print.
+ * @param {boolean=} opt_pretty If true, pretty print (optional).
+ * @param {number=} opt_tabs Number of tabs to start indent.
+ * @return {string} The formatted object in text.
+ */
+wave.util.printJson = function(obj, opt_pretty, opt_tabs) {
+ if (!obj || typeof(obj.valueOf()) != 'object') {
+ if (typeof(obj) == 'string') {
+ return '\'' + obj + '\'';
+ }
+ else if (obj instanceof Function) {
+ return '[function]';
+ }
+ return '' + obj;
+ }
+ var text = [];
+ var isArray = wave.util.isArray_(obj);
+ var brace = isArray ? '[]' : '{}';
+ var newline = opt_pretty ? '\n' : '';
+ var spacer = opt_pretty ? ' ' : '';
+ var i = 0;
+ var tabs = opt_tabs || 1;
+ if (!opt_pretty) {
+ tabs = 0;
+ }
+ text.push(brace.charAt(0));
+ for (var key in obj) {
+ var value = obj[key];
+ if (i++ > 0) {
+ text.push(', ');
+ }
+ if (isArray) {
+ text.push(wave.util.printJson(value, opt_pretty, tabs + 1));
+ } else {
+ text.push(newline);
+ text.push(wave.util.toSpaces_(tabs));
+ text.push(key + ': ');
+ text.push(spacer);
+ text.push(wave.util.printJson(value, opt_pretty, tabs + 1));
+ }
+ }
+ if (!isArray) {
+ text.push(newline);
+ text.push(wave.util.toSpaces_(tabs - 1));
+ }
+ text.push(brace.charAt(1));
+ return text.join('');
+};
Added: shindig/trunk/extras/src/main/javascript/features-extras/wave/wave.js
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/wave/wave.js?rev=983578&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/wave/wave.js
(added)
+++ shindig/trunk/extras/src/main/javascript/features-extras/wave/wave.js Mon
Aug 9 10:51:15 2010
@@ -0,0 +1,388 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * 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 Provides access to the wave API in gadgets.
+ *
+ * Clients can access the wave API by the wave object.
+ *
+ * Example:
+ * <pre>
+ * var state;
+ * var privateState;
+ * var viewer;
+ * var participants;
+ * if (wave && wave.isInWaveContainer()) {
+ * state = wave.getState();
+ * privateState = wave.getPrivateState();
+ * viewer = wave.getViewer();
+ * participants = wave.getParticipants();
+ * }
+ * </pre>
+ */
+
+/**
+ * Checks the wave parameter to determine whether the gadget container claims
+ * to be wave-aware.
+ */
+wave.checkWaveContainer_ = function() {
+ var params = gadgets.util.getUrlParameters();
+ wave.inWaveContainer_ =
+ (params.hasOwnProperty(wave.API_PARAM_) && params[wave.API_PARAM_]);
+ wave.id_ = (params.hasOwnProperty(wave.ID_PARAM_) && params[wave.ID_PARAM_]);
+};
+
+/**
+ * Indicates whether the gadget runs inside a wave container.
+ *
+ * @return {boolean} whether the gadget runs inside a wave container
+ * @export
+ */
+wave.isInWaveContainer = function() {
+ return wave.inWaveContainer_;
+};
+
+/**
+ * Participant callback relay.
+ *
+ * @param {{myId: string, authorId: string,
+ * participants: Object.<string, string>}} data participants object.
+ */
+wave.receiveWaveParticipants_ = function(data) {
+ wave.viewer_ = null;
+ wave.host_ = null;
+ wave.participants_ = [];
+ wave.participantMap_ = {};
+ var myId = data['myId'];
+ var hostId = data['authorId'];
+ var participants = data['participants'];
+ for (var id in participants) {
+ var p = wave.Participant.fromJson_(participants[id]);
+ if (id == myId) {
+ wave.viewer_ = p;
+ }
+ if (id == hostId) {
+ wave.host_ = p;
+ }
+ wave.participants_.push(p);
+ wave.participantMap_[id] = p;
+ }
+ if (!wave.viewer_ && myId) {
+ // In this case, the viewer has not yet been added to the participant
+ // list, and so did not have a complete Participant object created.
+ // Let's create it here.
+ var p = new wave.Participant(myId, myId);
+ wave.viewer_ = p;
+ wave.participants_.push(p);
+ wave.participantMap_[myId] = p;
+ }
+ wave.participantCallback_.invoke(wave.participants_);
+};
+
+/**
+ * State callback relay.
+ *
+ * @param {!Object.<string, string>} data raw state data object.
+ */
+wave.receiveState_ = function(data) {
+ wave.state_ = wave.state_ || new wave.State('wave_gadget_state');
+ var delta = wave.state_.calculateDelta_(data);
+ wave.state_.setState_(data);
+ wave.stateCallback_.invoke(wave.state_, delta);
+};
+
+/**
+ * Private state callback relay.
+ *
+ * @param {!Object.<string, string>} data raw state data object.
+ */
+wave.receivePrivateState_ = function(data) {
+ wave.privateState_ =
+ wave.privateState_ || new wave.State('wave_private_gadget_state');
+ var delta = wave.privateState_.calculateDelta_(data);
+ wave.privateState_.setState_(data);
+ wave.privateStateCallback_.invoke(wave.privateState_, delta);
+};
+
+/**
+ * State delta callback relay.
+ *
+ * @param {!Object.<string, string>} delta the delta object.
+ */
+wave.receiveStateDelta_ = function(delta) {
+ wave.state_ = wave.state_ || new wave.State('wave_gadget_state');
+ wave.state_.applyDelta_(delta);
+ wave.stateCallback_.invoke(wave.state_, delta);
+};
+
+/**
+ * Private state delta callback relay.
+ *
+ * @param {!Object.<string, string>} delta the delta object.
+ */
+wave.receivePrivateStateDelta_ = function(delta) {
+ wave.privateState_ =
+ wave.privateState_ || new wave.State('wave_private_gadget_state');
+ wave.privateState_.applyDelta_(delta);
+ wave.privateStateCallback_.invoke(wave.privateState_, delta);
+};
+
+/**
+ * Mode callback relay.
+ *
+ * @param {!Object.<string, string>} data raw mode object.
+ */
+wave.receiveMode_ = function(data) {
+ wave.mode_ = data || {};
+ wave.modeCallback_.invoke(wave.getMode());
+};
+
+/**
+ * Get the <code>Participant</code> whose client renders this gadget.
+ *
+ * @return {wave.Participant} the viewer (null if not known)
+ * @export
+ */
+wave.getViewer = function() {
+ return wave.viewer_;
+};
+
+/**
+ * Returns the <code>Participant</code> who added this gadget
+ * to the blip.
+ * Note that the host may no longer be in the participant list.
+ *
+ * @return {wave.Participant} host (null if not known)
+ * @export
+ */
+wave.getHost = function() {
+ return wave.host_;
+};
+
+/**
+ * Returns a list of <code>Participant</code>s on the Wave.
+ *
+ * @return {Array.<wave.Participant>} Participant list.
+ * @export
+ */
+wave.getParticipants = function() {
+ return wave.participants_;
+};
+
+/**
+ * Returns a <code>Participant</code> with the given id.
+ *
+ * @param {string} id The id of the participant to retrieve.
+ * @return {wave.Participant} The participant with the given id.
+ * @export
+ */
+wave.getParticipantById = function(id) {
+ return wave.participantMap_[id];
+};
+
+/**
+ * Returns the gadget state as a <code>wave.State</code> object.
+ *
+ * @return {wave.State} gadget state (null if not known)
+ * @export
+ */
+wave.getState = function() {
+ return wave.state_;
+};
+
+/**
+ * Returns the private gadget state as a <code>wave.State</code> object.
+ *
+ * @return {wave.State} private gadget state (null if not known)
+ * @export
+ */
+wave.getPrivateState = function() {
+ return wave.privateState_;
+};
+
+/**
+ * Returns the gadget <code>wave.Mode</code>.
+ *
+ * @return {wave.Mode} gadget mode.
+ * @export
+ */
+wave.getMode = function() {
+ if (wave.mode_) {
+ var playback = wave.mode_['${playback}'];
+ var edit = wave.mode_['${edit}'];
+ if ((playback != null) && (edit != null)) {
+ if (playback == '1') {
+ return wave.Mode.PLAYBACK;
+ } else if (edit == '1') {
+ return wave.Mode.EDIT;
+ } else {
+ return wave.Mode.VIEW;
+ }
+ }
+ }
+ return wave.Mode.UNKNOWN;
+};
+
+/**
+ * Returns the playback state of the wave/wavelet/gadget.
+ * Note: For compatibility UNKNOWN mode identified as PLAYBACK.
+ *
+ * @return {boolean} whether the gadget is in the playback state
+ * @deprecated Use wave.getMode().
+ * @export
+ */
+wave.isPlayback = function() {
+ var mode = wave.getMode();
+ return (mode == wave.Mode.PLAYBACK) || (mode == wave.Mode.UNKNOWN);
+};
+
+/**
+ * Sets the gadget state update callback. If the state is already received
+ * from the container, the callback is invoked immediately to report the
+ * current gadget state. Only invoke callback can be defined. Consecutive calls
+ * would remove the old callback and set the new one.
+ *
+ * @param {function(wave.State=, Object.<string, string>=)} callback function
+ * @param {Object=} opt_context the object that receives the callback
+ * @export
+ */
+wave.setStateCallback = function(callback, opt_context) {
+ wave.stateCallback_ = new wave.Callback(callback, opt_context);
+ if (wave.state_) {
+ wave.stateCallback_.invoke(wave.state_, wave.state_.state_);
+ }
+};
+
+/**
+ * Sets the private gadget state update callback. Works similarly to
+ * setStateCallback but handles the private state events.
+ *
+ * @param {function(wave.State=, Object.<string, string>=)} callback function
+ * @param {Object=} opt_context the object that receives the callback
+ * @export
+ */
+wave.setPrivateStateCallback = function(callback, opt_context) {
+ wave.privateStateCallback_ = new wave.Callback(callback, opt_context);
+ if (wave.privateState_) {
+ wave.privateStateCallback_.invoke(
+ wave.privateState_, wave.privateState_.state_);
+ }
+};
+
+/**
+ * Sets the participant update callback. If the participant information is
+ * already received, the callback is invoked immediately to report the
+ * current participant information. Only one callback can be defined.
+ * Consecutive calls would remove old callback and set the new one.
+ *
+ * @param {function(Array.<wave.Participant>)} callback function
+ * @param {Object=} [opt_context] the object that receives the callback
+ * @export
+ */
+wave.setParticipantCallback = function(callback, opt_context) {
+ wave.participantCallback_ = new wave.Callback(callback, opt_context);
+ if (wave.participants_) {
+ wave.participantCallback_.invoke(wave.participants_);
+ }
+};
+
+/**
+ * Sets the mode change callback.
+ *
+ * @param {function(wave.Mode)} callback function
+ * @param {Object=} [opt_context] the object that receives the callback
+ * @export
+ */
+wave.setModeCallback = function(callback, opt_context) {
+ wave.modeCallback_ = new wave.Callback(callback, opt_context);
+ if (wave.mode_) {
+ wave.modeCallback_.invoke(wave.getMode());
+ }
+};
+
+/**
+ * Retrieves the current time of the viewer.
+ *
+ * TODO: Define the necessary gadget <-> container communication and
+ * implement playback time.
+ *
+ * @return {number} The gadget time.
+ * @export
+ */
+wave.getTime = function() {
+ // For now just return the current time.
+ return new Date().getTime();
+};
+
+/**
+ * Requests the container to output a log message.
+ *
+ * @param {string} message The message to output to the log.
+ * @export
+ */
+wave.log = function(message) {
+ gadgets.rpc.call(null, 'wave_log', null, message || '');
+};
+
+/**
+ * Requests the container to update the snippet visible in wave digest.
+ *
+ * @param {string} snippet Snippet to associate with the gadget.
+ * @export
+ */
+wave.setSnippet = function(snippet) {
+ gadgets.rpc.call(null, 'set_snippet', null, snippet || '');
+};
+
+/**
+ * Returns serialized wave ID or null if not known.
+ *
+ * @return {?string} Serialized wave ID.
+ * @export
+ */
+wave.getWaveId = function() {
+ return wave.id_;
+};
+
+/**
+ * Internal initialization.
+ */
+wave.internalInit_ = function() {
+ wave.checkWaveContainer_();
+ if (wave.isInWaveContainer()) {
+ gadgets.rpc.register('wave_participants', wave.receiveWaveParticipants_);
+ gadgets.rpc.register('wave_gadget_state', wave.receiveState_);
+ gadgets.rpc.register('wave_state_delta', wave.receiveStateDelta_);
+ gadgets.rpc.register(
+ 'wave_private_gadget_state', wave.receivePrivateState_);
+ gadgets.rpc.register(
+ 'wave_private_state_delta', wave.receivePrivateStateDelta_);
+ gadgets.rpc.register('wave_gadget_mode', wave.receiveMode_);
+ gadgets.rpc.call(null, 'wave_enable', null, '1.0');
+ }
+};
+
+/**
+ * Sets up the wave gadget variables and callbacks.
+ */
+(wave.init_ = function() {
+ if (window['gadgets']) {
+ gadgets.util.registerOnLoadHandler(function() {
+ wave.internalInit_();
+ });
+ }
+})();
Added: shindig/trunk/extras/src/main/javascript/features-extras/wave/wave.ui.js
URL:
http://svn.apache.org/viewvc/shindig/trunk/extras/src/main/javascript/features-extras/wave/wave.ui.js?rev=983578&view=auto
==============================================================================
--- shindig/trunk/extras/src/main/javascript/features-extras/wave/wave.ui.js
(added)
+++ shindig/trunk/extras/src/main/javascript/features-extras/wave/wave.ui.js
Mon Aug 9 10:51:15 2010
@@ -0,0 +1,136 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * 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 UI extension to the basic wave gadget API.
+ *
+ * wave.ui allows gadgets to get the look and feel of other
+ * wave elements.
+ *
+ * Example: turn a link into a wave button
+ * <pre>
+ * <a id="butTest" href="#" onclick="alert('hi!')">Text</a>
+ *
+ * <script>
+ * wave.ui.makeButton(document.getElementById('butTest'));
+ * </script>
+ * </pre>
+ */
+
+if (typeof wave == "undefined") {
+ wave = {};
+};
+
+if (typeof wave.ui == "undefined") {
+/**
+ * @namespace This namespace defines methods for creating a wave
+ * look & feel inside a gadget.
+ */
+ wave.ui = {};
+};
+
+wave.ui.BASE = 'http://wave-api.appspot.com/public/';
+
+wave.ui.cssLoaded = false;
+
+/**
+ * Loads a CSS with Wave-like styles into the gadget, including font
+ * properties, link properties, and the properties for the wave-styled
+ * button, dialog, and frame.
+ *
+ * @export
+ */
+wave.ui.loadCss = function() {
+ if (wave.ui.cssLoaded) {
+ return;
+ }
+ wave.ui.cssLoaded = true;
+ var fileref = document.createElement("link")
+ fileref.setAttribute("rel", "stylesheet")
+ fileref.setAttribute("type", "text/css")
+ fileref.setAttribute("href", wave.ui.BASE + "wave.ui.css")
+ document.getElementsByTagName("head")[0].appendChild(fileref)
+}
+
+/**
+ * Converts the passed in target into a wave-styled button.
+ *
+ * @param {Element} target element to turn into a button. The target should be
+ * an anchor element.
+ * @export
+ */
+wave.ui.makeButton = function(target) {
+ wave.ui.loadCss();
+ target.innerHTML = '<span>' + target.innerHTML + '</span>';
+ target.className += ' wavebutton';
+};
+
+/**
+ * Converts the passed in target into a wave-styled dialog.
+ *
+ * For now it only creates a centered box. The close button in the upper right
+ * corner will be default do nothing.
+ *
+ * @param {Element} target element to turn into a dialog. The target should be
+ * a div.
+ * @param {string} title
+ * @export
+ */
+wave.ui.makeDialog = function(target, title, onclick) {
+ wave.ui.loadCss();
+
+ var body = target.innerHTML;
+ target.innerHTML = '';
+
+ var headDiv = document.createElement('div');
+ headDiv.className = 'wavedialoghead';
+
+ var span = document.createElement('span');
+
+ var closeDiv = document.createElement('div');
+ closeDiv.className = 'wavedialogclose';
+ function closeFunction() {
+ target.style.display = 'none';
+ }
+ closeDiv.onclick = onclick || closeFunction;
+
+ span.appendChild(closeDiv);
+ span.appendChild(document.createTextNode(title));
+
+ headDiv.appendChild(span);
+ target.appendChild(headDiv);
+
+ var bodyDiv = document.createElement('div');
+ bodyDiv.className = 'wavedialogbody';
+ bodyDiv.innerHTML = body;
+ target.appendChild(bodyDiv);
+ target.className += ' wavedialog';
+};
+
+/**
+ * Converts the passed in target into a wave-styled frame.
+ *
+ * @param {Element} target element to turn into a frame. The target should be
+ * a div.
+ * @export
+ */
+wave.ui.makeFrame = function(target) {
+ wave.ui.loadCss();
+ target.innerHTML = '<div class="waveboxhead"><span> </span></div>' +
+ '<div class="waveboxbody">' + target.innerHTML + '</div>';
+ target.className += ' wavebox';
+};