# HG changeset patch # User veltr # Date 1342099834 -7200 # Node ID 977a39c4ee80280ca19884768391ac29f9c43135 # Parent e47ed8eb75cd203b7ce7619e40d943b32e09260c Added URL Copy function to the Social Widget diff -r e47ed8eb75cd -r 977a39c4ee80 assets/psd/socialbuttons.psd Binary file assets/psd/socialbuttons.psd has changed diff -r e47ed8eb75cd -r 977a39c4ee80 src/js/defaults.js --- a/src/js/defaults.js Wed Jul 11 18:22:57 2012 +0200 +++ b/src/js/defaults.js Thu Jul 12 15:30:34 2012 +0200 @@ -14,7 +14,9 @@ raphael : "raphael-min.js", tracemanager : "tracemanager.js", jwPlayerSWF : "player.swf", - json : "json2.js" + json : "json2.js", + zeroClipboardJs: "ZeroClipboard.js", + zeroClipboardSwf: "ZeroClipboard.swf" }, locations : { // use to define locations outside defautl_dir @@ -32,22 +34,25 @@ IriSP.widgetsRequirements = { Sparkline: { noCss: true, - requires: "raphael" + requires: [ "raphael" ] }, Arrow: { noCss: true, - requires: "raphael" + requires: [ "raphael" ] }, Mediafragment: { noCss: true }, Trace : { noCss: true, - requires: "tracemanager" + requires: [ "tracemanager" ] }, SlideShare: { - requires: "swfObject" - } + requires: [ "swfObject" ] + }, + Social: { + requires: [ "zeroClipboardJs" ] + } } IriSP.guiDefaults = { diff -r e47ed8eb75cd -r 977a39c4ee80 src/js/init.js --- a/src/js/init.js Wed Jul 11 18:22:57 2012 +0200 +++ b/src/js/init.js Thu Jul 12 15:30:34 2012 +0200 @@ -75,13 +75,15 @@ /* widget specific requirements */ for(var _i = 0; _i < this.config.gui.widgets.length; _i++) { var _t = this.config.gui.widgets[_i].type; - if (typeof IriSP.widgetsRequirements[_t] !== "undefined" && typeof IriSP.widgetsRequirements[_t].requires !== "undefined") { - $L.script(IriSP.getLib(IriSP.widgetsRequirements[_t].requires)); + if (typeof IriSP.widgetsRequirements[_t] !== "undefined" && typeof IriSP.widgetsRequirements[_t].requires !== "undefined" ) { + for (var _j = 0; _j < IriSP.widgetsRequirements[_t].requires.length; _j++) { + $L.script(IriSP.getLib(IriSP.widgetsRequirements[_t].requires[_j])); + } } } var _this = this; - IriSP.log($L); + $L.wait(function() { _this.onLibsLoaded(); }); diff -r e47ed8eb75cd -r 977a39c4ee80 src/js/libs/ZeroClipboard.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/js/libs/ZeroClipboard.js Thu Jul 12 15:30:34 2012 +0200 @@ -0,0 +1,311 @@ +// Simple Set Clipboard System +// Author: Joseph Huckaby + +var ZeroClipboard = { + + version: "1.0.7", + clients: {}, // registered upload clients on page, indexed by id + moviePath: 'ZeroClipboard.swf', // URL to movie + nextId: 1, // ID of next movie + + $: function(thingy) { + // simple DOM lookup utility function + if (typeof(thingy) == 'string') thingy = document.getElementById(thingy); + if (!thingy.addClass) { + // extend element with a few useful methods + thingy.hide = function() { this.style.display = 'none'; }; + thingy.show = function() { this.style.display = ''; }; + thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; }; + thingy.removeClass = function(name) { + var classes = this.className.split(/\s+/); + var idx = -1; + for (var k = 0; k < classes.length; k++) { + if (classes[k] == name) { idx = k; k = classes.length; } + } + if (idx > -1) { + classes.splice( idx, 1 ); + this.className = classes.join(' '); + } + return this; + }; + thingy.hasClass = function(name) { + return !!this.className.match( new RegExp("\\s*" + name + "\\s*") ); + }; + } + return thingy; + }, + + setMoviePath: function(path) { + // set path to ZeroClipboard.swf + this.moviePath = path; + }, + + dispatch: function(id, eventName, args) { + // receive event from flash movie, send to client + var client = this.clients[id]; + if (client) { + client.receiveEvent(eventName, args); + } + }, + + register: function(id, client) { + // register new client to receive events + this.clients[id] = client; + }, + + getDOMObjectPosition: function(obj, stopObj) { + // get absolute coordinates for dom element + var info = { + left: 0, + top: 0, + width: obj.width ? obj.width : obj.offsetWidth, + height: obj.height ? obj.height : obj.offsetHeight + }; + + while (obj && (obj != stopObj)) { + info.left += obj.offsetLeft; + info.top += obj.offsetTop; + obj = obj.offsetParent; + } + + return info; + }, + + Client: function(elem) { + // constructor for new simple upload client + this.handlers = {}; + + // unique ID + this.id = ZeroClipboard.nextId++; + this.movieId = 'ZeroClipboardMovie_' + this.id; + + // register client with singleton to receive flash events + ZeroClipboard.register(this.id, this); + + // create movie + if (elem) this.glue(elem); + } +}; + +ZeroClipboard.Client.prototype = { + + id: 0, // unique ID for us + ready: false, // whether movie is ready to receive events or not + movie: null, // reference to movie object + clipText: '', // text to copy to clipboard + handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor + cssEffects: true, // enable CSS mouse effects on dom container + handlers: null, // user event handlers + + glue: function(elem, appendElem, stylesToAdd) { + // glue to DOM element + // elem can be ID or actual DOM element object + this.domElement = ZeroClipboard.$(elem); + + // float just above object, or zIndex 99 if dom element isn't set + var zIndex = 99; + if (this.domElement.style.zIndex) { + zIndex = parseInt(this.domElement.style.zIndex, 10) + 1; + } + + if (typeof(appendElem) == 'string') { + appendElem = ZeroClipboard.$(appendElem); + } + else if (typeof(appendElem) == 'undefined') { + appendElem = document.getElementsByTagName('body')[0]; + } + + // find X/Y position of domElement + var box = ZeroClipboard.getDOMObjectPosition(this.domElement, appendElem); + + // create floating DIV above element + this.div = document.createElement('div'); + var style = this.div.style; + style.position = 'absolute'; + style.left = '' + box.left + 'px'; + style.top = '' + box.top + 'px'; + style.width = '' + box.width + 'px'; + style.height = '' + box.height + 'px'; + style.zIndex = zIndex; + + if (typeof(stylesToAdd) == 'object') { + for (addedStyle in stylesToAdd) { + style[addedStyle] = stylesToAdd[addedStyle]; + } + } + + // style.backgroundColor = '#f00'; // debug + + appendElem.appendChild(this.div); + + this.div.innerHTML = this.getHTML( box.width, box.height ); + }, + + getHTML: function(width, height) { + // return HTML for movie + var html = ''; + var flashvars = 'id=' + this.id + + '&width=' + width + + '&height=' + height; + + if (navigator.userAgent.match(/MSIE/)) { + // IE gets an OBJECT tag + var protocol = location.href.match(/^https/i) ? 'https://' : 'http://'; + html += ''; + } + else { + // all other browsers get an EMBED tag + html += ''; + } + return html; + }, + + hide: function() { + // temporarily hide floater offscreen + if (this.div) { + this.div.style.left = '-2000px'; + } + }, + + show: function() { + // show ourselves after a call to hide() + this.reposition(); + }, + + destroy: function() { + // destroy control and floater + if (this.domElement && this.div) { + this.hide(); + this.div.innerHTML = ''; + + var body = document.getElementsByTagName('body')[0]; + try { body.removeChild( this.div ); } catch(e) {;} + + this.domElement = null; + this.div = null; + } + }, + + reposition: function(elem) { + // reposition our floating div, optionally to new container + // warning: container CANNOT change size, only position + if (elem) { + this.domElement = ZeroClipboard.$(elem); + if (!this.domElement) this.hide(); + } + + if (this.domElement && this.div) { + var box = ZeroClipboard.getDOMObjectPosition(this.domElement); + var style = this.div.style; + style.left = '' + box.left + 'px'; + style.top = '' + box.top + 'px'; + } + }, + + setText: function(newText) { + // set text to be copied to clipboard + this.clipText = newText; + if (this.ready) this.movie.setText(newText); + }, + + addEventListener: function(eventName, func) { + // add user event listener for event + // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel + eventName = eventName.toString().toLowerCase().replace(/^on/, ''); + if (!this.handlers[eventName]) this.handlers[eventName] = []; + this.handlers[eventName].push(func); + }, + + setHandCursor: function(enabled) { + // enable hand cursor (true), or default arrow cursor (false) + this.handCursorEnabled = enabled; + if (this.ready) this.movie.setHandCursor(enabled); + }, + + setCSSEffects: function(enabled) { + // enable or disable CSS effects on DOM container + this.cssEffects = !!enabled; + }, + + receiveEvent: function(eventName, args) { + // receive event from flash + eventName = eventName.toString().toLowerCase().replace(/^on/, ''); + + // special behavior for certain events + switch (eventName) { + case 'load': + // movie claims it is ready, but in IE this isn't always the case... + // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function + this.movie = document.getElementById(this.movieId); + if (!this.movie) { + var self = this; + setTimeout( function() { self.receiveEvent('load', null); }, 1 ); + return; + } + + // firefox on pc needs a "kick" in order to set these in certain cases + if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) { + var self = this; + setTimeout( function() { self.receiveEvent('load', null); }, 100 ); + this.ready = true; + return; + } + + this.ready = true; + this.movie.setText( this.clipText ); + this.movie.setHandCursor( this.handCursorEnabled ); + break; + + case 'mouseover': + if (this.domElement && this.cssEffects) { + this.domElement.addClass('hover'); + if (this.recoverActive) this.domElement.addClass('active'); + } + break; + + case 'mouseout': + if (this.domElement && this.cssEffects) { + this.recoverActive = false; + if (this.domElement.hasClass('active')) { + this.domElement.removeClass('active'); + this.recoverActive = true; + } + this.domElement.removeClass('hover'); + } + break; + + case 'mousedown': + if (this.domElement && this.cssEffects) { + this.domElement.addClass('active'); + } + break; + + case 'mouseup': + if (this.domElement && this.cssEffects) { + this.domElement.removeClass('active'); + this.recoverActive = false; + } + break; + } // switch eventName + + if (this.handlers[eventName]) { + for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) { + var func = this.handlers[eventName][idx]; + + if (typeof(func) == 'function') { + // actual function reference + func(this, args); + } + else if ((typeof(func) == 'object') && (func.length == 2)) { + // PHP style object + method, i.e. [myObject, 'myMethod'] + func[0][ func[1] ](this, args); + } + else if (typeof(func) == 'string') { + // name of function + window[func](this, args); + } + } // foreach event handler defined + } // user defined handler for event + } + +}; diff -r e47ed8eb75cd -r 977a39c4ee80 src/js/libs/ZeroClipboard.swf Binary file src/js/libs/ZeroClipboard.swf has changed diff -r e47ed8eb75cd -r 977a39c4ee80 src/js/widgets.js --- a/src/js/widgets.js Wed Jul 11 18:22:57 2012 +0200 +++ b/src/js/widgets.js Thu Jul 12 15:30:34 2012 +0200 @@ -110,14 +110,23 @@ IriSP.Widgets.Widget.prototype.insertSubwidget = function(_selector, _propname, _widgetoptions) { var _id = _selector.attr("id"), - _this = this; + _this = this, + _type = _widgetoptions.type, + $L = $LAB; if (typeof _id == "undefined") { _id = IriSP._.uniqueId(this.container + '_sub_widget_' + _widgetoptions.type); _selector.attr("id", _id); } _widgetoptions.container = _id; - _this.player.loadWidget(_widgetoptions, function(_widget) { - _this[_propname] = _widget; + if (typeof IriSP.widgetsRequirements[_type] !== "undefined" && typeof IriSP.widgetsRequirements[_type].requires !== "undefined" ) { + for (var _j = 0; _j < IriSP.widgetsRequirements[_type].requires.length; _j++) { + $L.script(IriSP.getLib(IriSP.widgetsRequirements[_type].requires[_j])); + } + } + $L.wait(function() { + _this.player.loadWidget(_widgetoptions, function(_widget) { + _this[_propname] = _widget; + }); }); } diff -r e47ed8eb75cd -r 977a39c4ee80 src/widgets/Annotation.js --- a/src/widgets/Annotation.js Wed Jul 11 18:22:57 2012 +0200 +++ b/src/widgets/Annotation.js Thu Jul 12 15:30:34 2012 +0200 @@ -132,6 +132,13 @@ } if (typeof this.socialWidget !== "undefined") { this.socialWidget.updateUrls(_url, _text); + } else { + var _this = this; + setTimeout(function() { + if (typeof _this.socialWidget !== "undefined") { + _this.socialWidget.updateUrls(_url, _text); + } + },800); } this.$.find(".Ldt-Annotation-Inner").removeClass("Ldt-Annotation-Empty"); } diff -r e47ed8eb75cd -r 977a39c4ee80 src/widgets/Social.css --- a/src/widgets/Social.css Wed Jul 11 18:22:57 2012 +0200 +++ b/src/widgets/Social.css Thu Jul 12 15:30:34 2012 +0200 @@ -2,6 +2,49 @@ display: inline-block; width: 24px; height: 24px; margin: 2px 0 0 2px; background: url(img/socialbuttons.png); } +.Ldt-Social-Url-Container { + display: inline-block; width: 24px; height: 24px; margin: 2px 0 0 2px; position: relative; +} + +a.Ldt-Social-Url { + margin: 0; background-position: -96px 0; +} + +a.Ldt-Social-Url:hover { + background-position: -96px -24px; +} + +.Ldt-Social-UrlPop { + position: absolute; left: 20px; top: -2px; background: url(img/socialcopy.png); + padding: 3px 0 0 12px; width: 218px; height: 27px; + display: none; +} + +.Ldt-Social-Input, .Ldt-Social-CopyBtn { + font-size: 11px; margin: 1px; border: 1px solid #ccc; height: 16px; + padding: 1px; border-radius: 2px; display: inline-block; +} + +.Ldt-Social-Input:hover, .Ldt-Social-CopyBtn.hover { + border-color: #8080ff; +} + +.Ldt-Social-Input { + width: 150px; +} + +.Ldt-Social-CopyBtn { + font-weight: bold; width: 50px; text-align: center; background: #f0f0ff; +} + +.Ldt-Social-CopyBtn.hover { + background: #ffe0a0; +} + +.Ldt-Social-CopyBtn.active { + background: #ff8000; +} + a.Ldt-Social-Twitter { background-position: 0 0; } diff -r e47ed8eb75cd -r 977a39c4ee80 src/widgets/Social.js --- a/src/widgets/Social.js Wed Jul 11 18:22:57 2012 +0200 +++ b/src/widgets/Social.js Thu Jul 12 15:30:34 2012 +0200 @@ -2,6 +2,7 @@ IriSP.Widgets.Social = function(player, config) { IriSP.Widgets.Widget.call(this, player, config); + ZeroClipboard.setMoviePath( IriSP.getLib('zeroClipboardSwf') ); } IriSP.Widgets.Social.prototype = new IriSP.Widgets.Widget(); @@ -9,6 +10,7 @@ IriSP.Widgets.Social.prototype.defaults = { text: "", url: "", + show_url: true, show_twitter: true, show_fb: true, show_gplus: true, @@ -16,7 +18,9 @@ } IriSP.Widgets.Social.prototype.template = - '{{#show_fb}}{{/show_fb}}' + '{{#show_url}}
' + + '
{{l10n.copy}}
{{/show_url}}' + + '{{#show_fb}}{{/show_fb}}' + '{{#show_twitter}}{{/show_twitter}}' + '{{#show_gplus}}{{/show_gplus}}' + '{{#show_mail}}{{/show_mail}}
'; @@ -24,20 +28,58 @@ IriSP.Widgets.Social.prototype.messages = { "fr": { share_on: "Partager sur", - share_mail: "Envoyer par courriel" + share_mail: "Envoyer par courriel", + share_link: "Partager le lien hypertexte", + copy: "Copier" }, "en" : { share_on: "Share on", - share_mail: "Share by e-mail" + share_mail: "Share by e-mail", + share_link: "Share hypertext link", + copy: "Copy" } } IriSP.Widgets.Social.prototype.draw = function() { this.renderTemplate(); + this.clipId = IriSP._.uniqueId("Ldt-Social-CopyBtn-"); + this.$.find(".Ldt-Social-CopyBtn").attr("id", this.clipId); + var _this = this; + this.$.find(".Ldt-Social-Url").click(function() { + _this.toggleCopy(); + return false; + }); + this.$.find(".Ldt-Social-Input").focus(function() { + this.select(); + }); this.updateUrls(this.url, this.text); } +IriSP.Widgets.Social.prototype.toggleCopy = function() { + var _pop = this.$.find(".Ldt-Social-UrlPop"); + _pop.toggle(); + if (_pop.is(":visible")) { + if (typeof this.clip == "undefined") { + this.clip = new ZeroClipboard.Client(); + this.clip.setHandCursor( true ); + this.clip.glue(this.clipId); + var _this = this; + this.clip.addEventListener( 'onMouseUp', function() { + _pop.hide(); + _this.clip.hide(); + }); + } + this.clip.show(); + this.clip.setText( this.url ); + this.$.find(".Ldt-Social-Input").val(this.url).focus(); + } else { + this.clip.hide(); + } +} + IriSP.Widgets.Social.prototype.updateUrls = function(_url, _text) { + this.url = _url; + this.text = _text; this.$.find(".Ldt-Social-Fb").attr("href", "http://www.facebook.com/share.php?" + IriSP.jQuery.param({ u: _url, t: _text })); this.$.find(".Ldt-Social-Twitter").attr("href", "https://twitter.com/intent/tweet?" + IriSP.jQuery.param({ url: _url, text: _text })); this.$.find(".Ldt-Social-Gplus").attr("href", "https://plusone.google.com/_/+1/confirm?" + IriSP.jQuery.param({ url: _url, title: _text })); diff -r e47ed8eb75cd -r 977a39c4ee80 src/widgets/img/socialbuttons.png Binary file src/widgets/img/socialbuttons.png has changed diff -r e47ed8eb75cd -r 977a39c4ee80 src/widgets/img/socialcopy.png Binary file src/widgets/img/socialcopy.png has changed