Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

change domains

  • Loading branch information...
commit 743c7e92296e26b09d623540a52016e7128d9f10 1 parent 3173c1f
Moritz Tolxdorff authored
1  README.md
View
@@ -0,0 +1 @@
+## Hangout-Lower-Third
1  TOS.txt
View
@@ -0,0 +1 @@
+coming soon
268 html5slider.js
View
@@ -0,0 +1,268 @@
+/*
+html5slider - a JS implementation of <input type=range> for Firefox 4 and up
+https://github.com/fryn/html5slider
+
+Copyright (c) 2010-2011 Frank Yan, <http://frankyan.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+(function() {
+
+// test for native support
+var test = document.createElement('input');
+try {
+ test.type = 'range';
+ if (test.type == 'range')
+ return;
+} catch (e) {
+ return;
+}
+
+// test for required property support
+if (!document.mozSetImageElement || !('MozAppearance' in test.style))
+ return;
+
+var scale;
+var isMac = navigator.platform == 'MacIntel';
+var thumb = {
+ radius: isMac ? 9 : 6,
+ width: isMac ? 22 : 12,
+ height: isMac ? 16 : 20
+};
+var track = '-moz-linear-gradient(top, transparent ' + (isMac ?
+ '6px, #999 6px, #999 7px, #ccc 9px, #bbb 11px, #bbb 12px, transparent 12px' :
+ '9px, #999 9px, #bbb 10px, #fff 11px, transparent 11px') +
+ ', transparent)';
+var styles = {
+ 'min-width': thumb.width + 'px',
+ 'min-height': thumb.height + 'px',
+ 'max-height': thumb.height + 'px',
+ padding: 0,
+ border: 0,
+ 'border-radius': 0,
+ cursor: 'default',
+ 'text-indent': '-999999px' // -moz-user-select: none; breaks mouse capture
+};
+var onChange = document.createEvent('HTMLEvents');
+onChange.initEvent('change', true, false);
+
+if (document.readyState == 'loading')
+ document.addEventListener('DOMContentLoaded', initialize, true);
+else
+ initialize();
+
+function initialize() {
+ // create initial sliders
+ Array.forEach(document.querySelectorAll('input[type=range]'), transform);
+ // create sliders on-the-fly
+ document.addEventListener('DOMNodeInserted', onNodeInserted, true);
+}
+
+function onNodeInserted(e) {
+ check(e.target);
+ if (e.target.querySelectorAll)
+ Array.forEach(e.target.querySelectorAll('input'), check);
+}
+
+function check(input, async) {
+ if (input.localName != 'input' || input.type == 'range');
+ else if (input.getAttribute('type') == 'range')
+ transform(input);
+ else if (!async)
+ setTimeout(check, 0, input, true);
+}
+
+function transform(slider) {
+
+ var isValueSet, areAttrsSet, isChanged, isClick, prevValue, rawValue, prevX;
+ var min, max, step, range, value = slider.value;
+
+ // lazily create shared slider affordance
+ if (!scale) {
+ scale = document.body.appendChild(document.createElement('hr'));
+ style(scale, {
+ '-moz-appearance': isMac ? 'scale-horizontal' : 'scalethumb-horizontal',
+ display: 'block',
+ visibility: 'visible',
+ opacity: 1,
+ position: 'fixed',
+ top: '-999999px'
+ });
+ document.mozSetImageElement('__sliderthumb__', scale);
+ }
+
+ // reimplement value and type properties
+ var getValue = function() { return '' + value; };
+ var setValue = function setValue(val) {
+ value = '' + val;
+ isValueSet = true;
+ draw();
+ delete slider.value;
+ slider.value = value;
+ slider.__defineGetter__('value', getValue);
+ slider.__defineSetter__('value', setValue);
+ };
+ slider.__defineGetter__('value', getValue);
+ slider.__defineSetter__('value', setValue);
+ slider.__defineGetter__('type', function() { return 'range'; });
+
+ // sync properties with attributes
+ ['min', 'max', 'step'].forEach(function(prop) {
+ if (slider.hasAttribute(prop))
+ areAttrsSet = true;
+ slider.__defineGetter__(prop, function() {
+ return this.hasAttribute(prop) ? this.getAttribute(prop) : '';
+ });
+ slider.__defineSetter__(prop, function(val) {
+ val === null ? this.removeAttribute(prop) : this.setAttribute(prop, val);
+ });
+ });
+
+ // initialize slider
+ slider.readOnly = true;
+ style(slider, styles);
+ update();
+
+ slider.addEventListener('DOMAttrModified', function(e) {
+ // note that value attribute only sets initial value
+ if (e.attrName == 'value' && !isValueSet) {
+ value = e.newValue;
+ draw();
+ }
+ else if (~['min', 'max', 'step'].indexOf(e.attrName)) {
+ update();
+ areAttrsSet = true;
+ }
+ }, true);
+
+ slider.addEventListener('mousedown', onDragStart, true);
+ slider.addEventListener('keydown', onKeyDown, true);
+ slider.addEventListener('focus', onFocus, true);
+ slider.addEventListener('blur', onBlur, true);
+
+ function onDragStart(e) {
+ isClick = true;
+ setTimeout(function() { isClick = false; }, 0);
+ if (e.button || !range)
+ return;
+ var width = parseFloat(getComputedStyle(this, 0).width);
+ var multiplier = (width - thumb.width) / range;
+ if (!multiplier)
+ return;
+ // distance between click and center of thumb
+ var dev = e.clientX - this.getBoundingClientRect().left - thumb.width / 2 -
+ (value - min) * multiplier;
+ // if click was not on thumb, move thumb to click location
+ if (Math.abs(dev) > thumb.radius) {
+ isChanged = true;
+ this.value -= -dev / multiplier;
+ }
+ rawValue = value;
+ prevX = e.clientX;
+ this.addEventListener('mousemove', onDrag, true);
+ this.addEventListener('mouseup', onDragEnd, true);
+ }
+
+ function onDrag(e) {
+ var width = parseFloat(getComputedStyle(this, 0).width);
+ var multiplier = (width - thumb.width) / range;
+ if (!multiplier)
+ return;
+ rawValue += (e.clientX - prevX) / multiplier;
+ prevX = e.clientX;
+ isChanged = true;
+ this.value = rawValue;
+ }
+
+ function onDragEnd() {
+ this.removeEventListener('mousemove', onDrag, true);
+ this.removeEventListener('mouseup', onDragEnd, true);
+ }
+
+ function onKeyDown(e) {
+ if (e.keyCode > 36 && e.keyCode < 41) { // 37-40: left, up, right, down
+ onFocus.call(this);
+ isChanged = true;
+ this.value = value + (e.keyCode == 38 || e.keyCode == 39 ? step : -step);
+ }
+ }
+
+ function onFocus() {
+ if (!isClick)
+ this.style.boxShadow = !isMac ? '0 0 0 2px #fb0' :
+ '0 0 2px 1px -moz-mac-focusring, inset 0 0 1px -moz-mac-focusring';
+ }
+
+ function onBlur() {
+ this.style.boxShadow = '';
+ }
+
+ // determines whether value is valid number in attribute form
+ function isAttrNum(value) {
+ return !isNaN(value) && +value == parseFloat(value);
+ }
+
+ // validates min, max, and step attributes and redraws
+ function update() {
+ min = isAttrNum(slider.min) ? +slider.min : 0;
+ max = isAttrNum(slider.max) ? +slider.max : 100;
+ if (max < min)
+ max = min > 100 ? min : 100;
+ step = isAttrNum(slider.step) && slider.step > 0 ? +slider.step : 1;
+ range = max - min;
+ draw(true);
+ }
+
+ // recalculates value property
+ function calc() {
+ if (!isValueSet && !areAttrsSet)
+ value = slider.getAttribute('value');
+ if (!isAttrNum(value))
+ value = (min + max) / 2;;
+ // snap to step intervals (WebKit sometimes does not - bug?)
+ value = Math.round((value - min) / step) * step + min;
+ if (value < min)
+ value = min;
+ else if (value > max)
+ value = min + ~~(range / step) * step;
+ }
+
+ // renders slider using CSS background ;)
+ function draw(attrsModified) {
+ calc();
+ if (isChanged && value != prevValue)
+ slider.dispatchEvent(onChange);
+ isChanged = false;
+ if (!attrsModified && value == prevValue)
+ return;
+ prevValue = value;
+ var position = range ? (value - min) / range * 100 : 0;
+ var bg = '-moz-element(#__sliderthumb__) ' + position + '% no-repeat, ';
+ style(slider, { background: bg + track });
+ }
+
+}
+
+function style(element, styles) {
+ for (var prop in styles)
+ element.style.setProperty(prop, styles[prop], 'important');
+}
+
+})();
BIN  i/header.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  i/volumecontrol_16x16.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  i/volumecontrol_220x140.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  i/volumecontrol_32x32.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  i/volumecontrol_icon.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  i/volumecontrol_icon_dev.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1  privacy.txt
View
@@ -0,0 +1 @@
+coming soon
198 style.css
View
@@ -0,0 +1,198 @@
+#container #header {
+ background-color: #f3f3f3;
+ height: 28px;
+ border-bottom: 1px solid #d9d9d9;
+ padding: 0 10px;
+ line-height: 24px;
+ font-weight: bold;
+ font-size: 11px;
+ vertical-align: middle;
+}
+
+#container #header .icon_header {
+ background-image: url(data:image/png;base64,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);
+ height: 16px;
+ width: 16px;
+ position: absolute;
+ top: 5px;
+ left: 5px;
+}
+
+#container #header .header_title {
+ margin-left: 18px;
+ line-height: 28px;
+}
+
+#container #body .button {
+ position: relative;
+ top: -20px;
+ left: 10px;
+ background-color: #fff;
+ border:1px solid transparent;
+ display:inline-block;
+ color:#2e2e2e;
+ height:18px;
+ width: 18px;
+ font-weight:bold;
+ padding:4px 8px;
+ text-decoration:none;
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACusAAArrAYKLDVoAAAAJdnBBZwAAABAAAAAQAFzGrcMAAACpSURBVCjPhZFdFYMwDIW/7swAk4AFJiGT0EoAC0hgEoaEImGVsFiYBSR0L0D56bb05Sa55940MZHfcU7Q1XQUjDR+SFWTFNwMR39JhFNGtVgnE8HJlpPyycJFbjyX/pWXN98tNiZ5AjlCiU5IKY976OloqKgIvHnQ7xVaFE+JIniUNreoGosQGHy/GiKunhUbrcRNbVFwFYIgBALqw/FYBYpy33/T/Dv3B1IyOMfkphoeAAAAFnRFWHRDcmVhdGlvbiBUaW1lADA3LzI5LzExsq7E0wAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAAAASUVORK5CYII=);
+ background-repeat: no repeat;
+}
+
+#container #body .button:hover {
+ -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
+ box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+ background-color: #f8f8f8;
+ border-color: #c6c6c6;
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEADMAMwAzhj9D9gAAAAlwSFlzAAAK6wAACusBgosNWgAAAAl2cEFnAAAAEAAAABAAXMatwwAAAdJJREFUOMtjuONlIXjHy2LVHS8LYwY04CEhZM1ADIiVl2C47G72DmZIkqJk/VFno793vCz+H3U2+pukKFmPSy+jr68vw8yZMxlSjXUZOvSU33EyM7kyMDCcQVeosu0EIzYDmDZv3syQn5/PMPvsZYaKS3eFvv/9tzv//G1GBlKBh4SQ9VFno7/eksIMR52N/ntLCjPc8bL4D8MMDAwMgdKigRgugDE4mZnFxNnZmKq05P+2XXvIWKUl/x/ZJYHSogzd+srrcBoAA3PvPW+aaKj6H5shWMMAxvj+9+8rBgYGhve//lxiYGBgINYQuAE7Xrw7ysDAwCDIxqJ3/O2nd+iGyHKxl7/8+esfugHMyBx2ZibtKHnxzGUPXxZf+vj10X8GBmU/aZH2tmsPmTJVpI/MuPNszaWPX1ajpANkjokgr1CYnNi+IGlR/eNvP7279PHLXntRAV8NXi6O/PO3GWHpRGXbibN4ozRJUbJ+mrHagzteFv+nGas9yFWVmfrs2TMGb0lhlBSLFwRKiwbe8bL4D4v70NBQBjRDBDG8ANOowssZqcfP42wpzCcE88qdz9+Xf//791X69LlHly1bxrB69WoGnAbgctX6p6/XE3Q6qQAAKXfICQ05gZwAAAAASUVORK5CYII=);
+ background-repeat: no repeat;
+}
+
+#container #body .button.muted{
+ position: relative;
+ top: -20px;
+ left: 10px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+ background-color: #DD4B49;
+ border:1px solid #B13C2E;
+ color:#2e2e2e;
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAJiS0dEADMVXUIkAAAACXBIWXMAAArrAAAK6wGCiw1aAAAACXZwQWcAAAAQAAAAEABcxq3DAAAA8ElEQVQoz42QIWvDUBSFzxuD6fZnzIapwChUT0REvKgnVxOzQOVjk4XOxW8mg0zkF4zMVNV0E9NVT5QmLlQ9TsWSpkkY7FMX7sfh3gOOmNJBje9iSIiqpANE2ljS2Eh31ncwkKhKOjzRS/BrReIPAfBdYyUMGwVQXkdQHnmuKLQpF83w/JTwQSwZiG76JQBUO2D/DSQMxJKBuBq+SkY6L0hSwvBxbmxPWKTGzu51nBe/t4RpT7gdv27IvFikXwdS1tX1iHS2JbOtjpvqBorySOW11XEEiHZ5LW+mk/Fnuf74eat2wSrBOzrCedZLhv9yBFAbl6dclBNrAAAAAElFTkSuQmCC);
+ background-repeat: no repeat;
+}
+
+#container #body {
+ background-color: #fff;
+ overflow-x: auto;
+}
+
+#container #body #participants {
+ list-style: none;
+ margin: 0px;
+ padding: 10px;
+}
+
+#container #body #participants li {
+ height: 40px;
+}
+
+#container #body #participants li img{
+ width: 32px;
+ height: 32px;
+ padding: 10px;
+}
+
+#container #body #participants li input[type="range"] {
+ -webkit-appearance: none;
+ background-color: #d9d9d9;
+ height: 3px;
+ position: relative;
+ top: -25px;
+ margin-left: 5px;
+ width: 185px;
+ border: 1px solid #d6d6d6;
+}
+
+#container #body #participants li input[type="range"]::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ position: relative;
+ top: -1px;
+ z-index: 1;
+ width: 7px;
+ height: 18px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#cfcfcf), color-stop(50%,#bbbbbb), color-stop(51%,#acacac), color-stop(100%,#909090));
+}
+
+#container #footer {
+ background-color: #f3f3f3;
+ border-right: 1px solid #d9d9d9;
+ height: 40px;
+ border-top: 1px solid #d9d9d9;
+}
+
+#container #footer .ltbutton {
+-webkit-border-radius: 2px;
+ border-radius: 2px;
+ background-color:#ededed;
+ border:1px solid #dcdcdc;
+ display:inline-block;
+ color:#2e2e2e;
+ font-family:arial;
+ font-size:15px;
+ font-weight:bold;
+ padding:4px 8px;
+ text-decoration:none;
+ float: right;
+ position: relative;
+ right: 5px;
+ top: 5px;
+}
+#container #footer .ltbutton:hover {
+-webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
+ box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
+-webkit-border-radius: 2px;
+ border-radius: 2px;
+ background-color:#dfdfdf;
+ color: #DD4B49;
+}
+
+#container #footer .ltbutton_muted {
+-webkit-border-radius: 2px;
+ border-radius: 2px;
+ background-color:#DD4B49;
+ border:1px solid #B13C2E;
+ display:inline-block;
+ color:#fff;
+ font-family:arial;
+ font-size:15px;
+ font-weight:bold;
+ padding:4px 8px;
+ text-decoration:none;
+}
+#container #footer .ltbutton_muted:hover {
+ background-color:#dd4b49;
+ color: #fff;
+}
+
+#container #footer .footer_note {
+ font-size:10px;
+ font-family:verdana;
+ color:#2e2e2e;
+ float:left;
+ position: relative;
+ left: 5px;
+ top: 15px;
+}
+
+#container #footer a {
+ font-size:10px;
+ font-family:verdana;
+ color:#2e2e2e;
+ text-decoration:none;
+}
+#container #footer a:hover {
+ text-decoration:underline;
+ padding-bottom: 5px;
+ margin-bottom: 5px;
+}
+
+#container #body #participants .gain {
+ position: absolute;
+ top: 10px;
+ left: 52px;
+ width: 3px;
+ height: 32px;
+ border: 0px solid #d9d9d9;
+ vertical-align: bottom;
+}
+#container #body #participants .gain_level {
+ position: relative;
+ bottom:0px;
+ width: 3px;
+}
1  support.txt
View
@@ -0,0 +1 @@
+coming soon
439 volumecontrol.js
View
@@ -0,0 +1,439 @@
+(function(){
+ /*
+ * Volume Control for Google+ Hangouts
+ * Copyright 2012 Moritz Tolxdorff
+ * Version: 1.0.3
+ * Release date: 06.04.2012
+ * Developers:
+ ** Moritz Tolxdorff
+ ** Robert Pitt
+ *
+ * Thanks:
+ ** Robert Pitt
+ */
+
+
+ /**
+ * @ApplicationController
+ * @constructor
+ */
+ function ApplicationController(){
+ if(!gapi){
+ throw "gapi not loaded!";
+ }
+
+ /**
+ * @ApplicationController.DEBUGGING - defines if debugging is enabled
+ * @private
+ * @type {boolean}
+ */
+ this.DEBUGGING = false;
+
+ /**
+ * @ApplicationController.maxHeight - defines the maximum window height
+ * @public
+ * @const
+ * @type {Number}
+ */
+ this.maxHeight = $(window).height();
+
+ /**
+ * @ApplicationController.globalShow - defines the initial state of globalShow
+ * @private
+ * @type {boolean}
+ */
+ this.globalMuted = false;
+
+ /**
+ * @ApplicationController.volumeColorEnum - defines colors for volume levels
+ * @public
+ * @enum
+ * @type {object}
+ */
+ this.volumeColorEnum = {
+ 1 : "#11b012",
+ 2 : "#4f9022",
+ 3 : "#847430",
+ 4 : "#a6623a",
+ 5 : "#cf4c44"
+ }
+
+ /*
+ * Bind gapi events when API is ready
+ */
+ gapi.hangout.onApiReady.add(this.onApiReady.bind(this));
+ gapi.hangout.onParticipantsChanged.add(this.onParticipantsChanged.bind(this));
+ gapi.hangout.av.onVolumesChanged.add(this.onVolumesChanged.bind(this));
+
+ /*
+ * Bind window events when window size has changed
+ */
+ $(window).resize(this.onWindowResize.bind(this));
+ }
+
+ /**
+ * @onParticipantsChanged - Fired participants changed
+ * @private
+ * @param evt {gapi.hangout.ParticipantsChangedEvent}
+ */
+ ApplicationController.prototype.onParticipantsChanged = function(evt){
+ this.generateControlls();
+ if(this.globalMuted == true){
+ var p = gapi.hangout.getParticipants();
+ for(var i=0; i<p.length; i++) {
+ gapi.hangout.av.setParticipantAudioLevel(p[i].id, 0)
+ }
+ }
+ }
+
+ /**
+ * @onVolumesChanged - Fired when volume levels change
+ * @private
+ * @param evt {gapi.hangout.av.VolumesChangedEvent}
+ */
+ ApplicationController.prototype.onVolumesChanged = function(evt){
+ var map = {};
+ var items = $("#participants li");
+
+ for(var i = 0; i < items.length; i++){
+ map[items[i].id.replace("participant_","")] = items[i];
+ }
+
+ for(var id in evt.volumes){
+ var level = parseInt(evt.volumes[id]);
+ if(id in map){
+ $(".gain_level", map[id]).css({"height": (6.4 * level), "margin-top": (32 - (level * 6.4))});
+
+ if(level in this.volumeColorEnum){
+ $(".gain_level", map[id]).css({"background-color": this.volumeColorEnum[level]});
+ }
+ }
+ }
+ }
+
+ /**
+ * @onWindowResize - Fired when window resizes
+ * @private
+ * @param evt {jQueryEventObject}
+ */
+ ApplicationController.prototype.onWindowResize = function(evt){
+ this.log("Window resized");
+ this.maxHeight = $(window).height();
+ this.scale();
+ }
+
+ /**
+ * @buildDOM - Building the DOM structure
+ * @private
+ */
+ ApplicationController.prototype.buildDOM = function(){
+ this.log("Building DOM");
+
+ /*
+ * Creates an empty div element
+ */
+ var div = this.createElement("div");
+
+ /*
+ * Creates an empty span element
+ */
+ var span = this.createElement("span");
+
+ /*
+ * Creates an empty a element
+ */
+ var a = this.createElement("a", {"target": "_blank"});
+
+ /*
+ * Create pane header
+ */
+ var header = div.clone().attr({"id": "header"});
+
+ /*
+ * Append icon and title to header
+ */
+ header.append(span.clone().attr({"class": "icon_header"}));
+ header.append(span.clone().attr({"class": "header_title"}).html("Volume Control v1.0.3"));
+
+ /*
+ * Create pane body
+ */
+ var body = div.clone().attr({"id": "body"}).css({"height": (this.maxHeight-70)+"px"});
+
+ /*
+ * Create the ul element for the template list and append it to the body
+ */
+ var ul = this.createElement("ul", {"id": "participants"}).appendTo(body);
+
+ /*
+ * Create the footer Div
+ */
+ var footer = div.clone().attr({"id": "footer"});
+
+ /*
+ * Create On/Off button and append it to the footer
+ */
+ var button = this.createElement("button", {"class": "ltbutton"}).text("Mute Hangout").appendTo(footer);
+
+ /*
+ * Append footer note to footer
+ */
+ footer.append(span.clone().attr({"class": "footer_note"}).html("&copy 2012 ").append(a.clone().attr({"href": "https://plus.google.com/117596712775912423303"}).html("Moritz")).append(" &amp; ").append(a.clone().attr({"href": "https://plus.google.com/110106586947414476573"}).html("Robert")));
+
+ /*
+ * Bind click event to the On/Off button
+ */
+ button.click(this.toggleMute.bind(this));
+
+ /*
+ * Append DOM structure to container
+ */
+ jQuery("#container").append(header, body, footer);
+ }
+
+ /**
+ * @scale - Scales the body for different resolutions
+ * @public
+ */
+ ApplicationController.prototype.scale = function(){
+ /*
+ * Set the maximum height of the body minus header, input div and footer
+ */
+ jQuery("#body").height(this.maxHeight-70);
+ }
+
+ /**
+ * @onSliderChange - Fired when a slider input[type=range] is moved
+ * @private
+ * @param evt {jQueryEventObject}
+ */
+ ApplicationController.prototype.onSliderChange = function(evt){
+ var li = jQuery(evt.target.parentNode);
+ var data = li.data("participant");
+ var level = parseInt(evt.target.value);
+ /* Function for future use when the API changes
+ if(level < 1){
+ level = parseFloat(level).toFixed(1);
+ gapi.hangout.av.setParticipantAudioLevel(data.id, [level,level]);
+ return;
+ }*/
+
+ /*
+ * Setting the audio level for a participant of which the slider was changed
+ */
+ gapi.hangout.av.setParticipantAudioLevel(data.id, [level,level]);
+
+ /*
+ * Switch between button styles depending on the mute state
+ */
+ level === 0 ? jQuery(".button",li).addClass("muted") : jQuery(".button",li).removeClass("muted");
+ }
+
+ /**
+ * @muteAllParticipants - mutes all participants in the hangout
+ * @public
+ * @param volume {int}
+ */
+ ApplicationController.prototype.setVolumeForAllParticipants = function(volume){
+ p = gapi.hangout.getParticipants();
+ for(i = 0; i < p.length; i++) {
+ gapi.hangout.av.setParticipantAudioLevel(p[i].id, volume)
+ }
+ }
+
+ /**
+ * @toggleMute - Fired when #button is clicked
+ * @public
+ * @see ApplicationController.buildDOM
+ */
+ ApplicationController.prototype.toggleMute = function(){
+ var muteButtons = jQuery("#participants li .button");
+ var rangeSliders = jQuery("#participants li input[type=range]");
+ if(this.globalMuted === false){
+ this.setVolumeForAllParticipants(0);
+
+ muteButtons.addClass("muted");
+ rangeSliders.val(0);
+ gapi.hangout.layout.displayNotice("You've muted the whole hangout. This only applies for yourself!");
+ gapi.hangout.av.setMicrophoneMute(true);
+ gapi.hangout.av.setCameraMute(true);
+ jQuery("#footer .ltbutton").text("Unmute Hangout").addClass("ltbutton_muted");
+ muteButtons.attr({"disabled": "disabled"});
+ rangeSliders.attr({"disabled": "disabled"});
+ this.globalMuted = true;
+ }else{
+ /* Commented for testing
+ gapi.hangout.av.setMicrophoneMute(false);
+ gapi.hangout.av.setCameraMute(false);
+ */
+ this.setVolumeForAllParticipants(1);
+
+ muteButtons.removeClass("muted");
+ rangeSliders.val(1);
+ gapi.hangout.layout.displayNotice("You've unmuted the whole hangout.");
+ gapi.hangout.av.clearMicrophoneMute();
+ gapi.hangout.av.clearCameraMute();
+ jQuery("#footer .ltbutton").text("Mute Hangout").removeClass("ltbutton_muted");
+ muteButtons.removeAttr("disabled");
+ rangeSliders.removeAttr("disabled");
+ this.globalMuted = false;
+ }
+ }
+
+ /**
+ * @toggleMuteParticipant - Fired when the participant mute button is clicked
+ * @public
+ * @param evt {jQueryEventObject}
+ */
+ ApplicationController.prototype.toggleMuteParticipant = function(evt){
+ var li = jQuery(evt.target.parentNode);
+
+ if(jQuery(evt.target).hasClass("muted")){
+ jQuery("input[type=range]",li)[0].value = 1;
+ jQuery(evt.target).removeClass("muted");
+ }else{
+ jQuery("input[type=range]",li)[0].value = 0;
+ jQuery(evt.target).addClass("muted");
+ }
+
+ jQuery("input[type=range]",li).trigger("change");
+ }
+
+ /**
+ * @generateControlls - Generates the slider and mute controlls for the participants
+ * @private
+ */
+ ApplicationController.prototype.generateControlls = function(){
+ var uid = gapi.hangout.getParticipantId();
+ var p = gapi.hangout.getParticipants();
+ var ul = jQuery("#participants");
+
+ /*
+ * Creates an empty div element
+ */
+ var div = this.createElement("div");
+
+ jQuery("li",ul).remove();
+
+ /*
+ * Loop through all participants
+ */
+ for(i = 0; i < p.length; i++) {
+ /*
+ * Ignore this itteration for current user
+ */
+ if(p[i].id == uid){
+ continue;
+ }
+
+ var cUser = p[i];
+
+ /*
+ * Setting all needed variables for participant volume level, placeHolder image and audio levels
+ */
+ var volume_level = gapi.hangout.av.getParticipantVolume(cUser.id);
+ var placeholderImage = "data:image/jpeg;base64,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";
+ var levels = gapi.hangout.av.getParticipantAudioLevel(cUser.id);
+
+ /*
+ * Creating li element for each participant
+ */
+ var li = this.createElement("li", {"id": "participant_" + cUser.id}).data("participant",cUser);
+
+ /*
+ * Creating outter gain div for the volume bar
+ */
+ var gain = div.clone().attr({"class": "gain"}).css({"top": ( 9 + i * 40 ) + "px"}).appendTo(li);
+
+ /*
+ * Creating the inner gain_level div for the color changing volume bar
+ */
+ var gain_level = div.clone().attr({"class": "gain_level"}).appendTo(gain);
+
+ /*
+ * Creating the profile image
+ */
+ var image = this.createElement("img", {"src": placeholderImage, "title": "Unknown"}).appendTo(li);
+
+ /*
+ * Creating the slider element
+ */
+ var slider = this.createElement("input", {"type": "range", "min": "0", "max": "10", "step": "1", "value": gapi.hangout.av.getParticipantAudioLevel(cUser.id)[0]}).appendTo(li);
+
+ /*
+ * Creating the participant mute button
+ */
+ var muteButton = this.createElement("input", {"type": "button", "class": "button", "value": ""});
+
+ /*
+ * Checking if the slider is below 0.1 or 0 to set the button to muted
+ */
+ if(levels[0] < 0.1 || levels[0] === 0){
+ muteButton.addClass("muted");
+ }
+
+ /*
+ * Binding the change and click event to elements
+ */
+ slider.bind("change", this.onSliderChange.bind(this));
+ muteButton.click(this.toggleMuteParticipant.bind(this));
+
+ /*
+ * If a participant is using the app use their profile picture and name instead of the placholders
+ */
+ if(cUser.person){
+ image.attr({"src": cUser.person.image.url, "title": cUser.person.displayName})
+ }
+
+ /*
+ * Appending the mute button to the li element and the li to the ul element
+ */
+ li.append(muteButton);
+ ul.append(li);
+ }
+ }
+
+ /**
+ * @createElement - Creates a new element
+ * @public
+ * @param type {String}
+ * @param attr {Object}
+ */
+ ApplicationController.prototype.createElement = function(type, attr){
+ return jQuery("<" + type + ">").attr(attr || {});
+ }
+
+ /**
+ * @log - Writes to console.log if DEBUGGING is enabled
+ * this.log(...)
+ * @private
+ * @param {Mixed}
+ */
+ ApplicationController.prototype.log = function(){
+ if(this.DEBUGGING === true){
+ console.log(Array.prototype.slice.call(arguments))
+ }
+ }
+
+ /**
+ * @onApiReady - Fired by gapi when it's ready
+ * @private
+ * @param event {gapi.hangout.apiReadyEvent}
+ */
+ ApplicationController.prototype.onApiReady = function(event){
+ if(event.isApiReady){
+ try {
+ this.buildDOM();
+ this.scale();
+ this.generateControlls();
+ console.log("Volume Control loaded!");
+ }
+ catch(err) {
+ console.log(err);
+ }
+ }
+ }
+
+ // Export instantiated ApplicationController to main window
+ window["appController"] = new ApplicationController();
+})()
44 volumecontrol.xml
View
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Module>
+ <!--
+ * Volume Control for Google+ Hangouts
+ * Copyright 2012 Moritz Tolxdorff
+ * Version: 1.0.3
+ * Release date: 06.04.2012
+ * Developers:
+ ** Moritz Tolxdorff
+ ** Robert Pitt
+ *
+ * Thanks:
+ ** Robert Pitt
+ -->
+ <ModulePrefs title="VolumeControl">
+ <Require feature="rpc"/>
+ <Require feature="views"/>
+ </ModulePrefs>
+ <Content type="html">
+ <![CDATA[
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
+ <script src="//hangoutsapi.talkgadget.google.com/hangouts/api/hangout.js?v=1.0"></script>
+ <link rel="stylesheet" type="text/css" href="//tolxdorff.appspot.com/a/volume/style.css" />
+ <!--[if lt IE 9]>
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+ <div id="container">
+ </div>
+ <script src="//tolxdorff.appspot.com/a/volume/html5slider.js"></script>
+ <script src="//tolxdorff.appspot.com/a/volume/volumecontrol.js"></script>
+ <script type="text/javascript">
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-30670305-1']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+ </script>
+ ]]>
+ </Content>
+</Module>
Please sign in to comment.
Something went wrong with that request. Please try again.