Committer: dpetrov
LJSUP-7759: Native sharingU trunk/htdocs/js/share.js
Modified: trunk/htdocs/js/share.js =================================================================== --- trunk/htdocs/js/share.js 2011-03-03 05:27:55 UTC (rev 18451) +++ trunk/htdocs/js/share.js 2011-03-03 05:30:37 UTC (rev 18452) @@ -1,6 +1,92 @@ ;(function( window, $ ) { +/** +* +* Livejournal sharing script. +* +* Usage: +* +* .. Somewhere in the head .. +* <script type="text/javascript"> +* //show only three links in popup by default +* LJShare.init({"ml":{"close":"Close","title":"Share"},"links":["facebook","twitter","email"]}) +* </script> +* +* .. Somewhere on the page .. +* <a href="#">share</a> +* <script type="text/javascript"> +* LJShare.link( { +* "url":"http://community.livejournal.com/news/750.html", +* "title":"Some title", +* "description":"Some description", +* "links": [ "twitter", "vkontakte", "moimir" ] //we want custom buttons there +* }); +* </script> +* +* +*/ + +function preload( srcArr ) { + for( var i = srcArr.length; --i; + ( new Image() ).src = srcArr[ i ] + '?' + Math.random() ); +} + +preload( [ + '/img/popup-cls.gif', + '/img/popup-arr.gif', + '/img/icons/sharethis.gif' +] ); + +function supplant(str, o) { + return str.replace(/{([^{}]*)}/g, + function (a, b) { + var r = o[b]; + return typeof r === 'string' || typeof r === 'number' ? r : a; + } + ); +}; + +var selectors = { + close: ".i-popup-close", + links: ".b-sharethis-services a", + arrow: ".i-popup-arr" +}; + +// four arrow positions availible +var arrow_opts = { + className: "i-popup-arr", + position: { + tl: "i-popup-arrtl", + tr: "i-popup-arrtr", + bl: "i-popup-arrbl", + br: "i-popup-arrbr" + } +}; + +var template = { + //here we take values from global_options.ml object + start: ' \ + <div class="b-sharethis b-popup"> \ + <div class="b-popup-outer"> \ + <div class="b-popup-inner"> \ + <div class="b-sharethis-head">{title}</div> \ + <div class="b-sharethis-services">', + //here we take values from an object made from service object. Availible vars: name, url, title. + item: '<span class="b-sharethis-{name}"><a href="{url}" target="_blank">{title}</a></span>', + //here we take values from global_options.ml object + end: '</div> \ + </div> \ + <i class="i-popup-arr i-popup-arrtl"></i><i class="i-popup-close" title="{close}"></i> \ + </div> \ + </div>' +}; + +//buildLink takes values passed to the url with link method ( title, post url, description ) var default_options = { + ml: { + close: "Close", + title: "Share" + }, services: { livejournal: { title: 'LiveJournal', bindLink: 'http://www.livejournal.com/update.bml?repost={url}' @@ -33,6 +119,7 @@ title: 'Odnoklassniki', bindLink: 'http://www.odnoklassniki.ru/dk?st.cmd=addShare&st.s=1&st._surl={url}' } }, + //list of links wich will be shown, when user will click on share link. Can be overriden in init and link methods. links: [ 'livejournal', 'facebook', 'twitter', 'vkontakte', 'odnoklassniki', 'moimir', 'email', 'digg', 'tumblr', 'stumbleupon' ] }; @@ -40,13 +127,28 @@ window.LJShare = {}; +/** +* Overrides default options for current page. +* +* @param Object opts Options object, may contain the following fields: +* ml - translation strings to use; +* services - An Object, that contains configuration fields for services links; +* links - array of links that will be shown to the user in popup. +*/ window.LJShare.init = function( opts ) { if( opts ) { - global_options.services = $.extend( true, {}, default_options.services, opts.services ); + global_options = $.extend( true, {}, default_options, opts ); global_options.links = opts.links || global_options.links; } } +/** +* Bind share popup to the latest link found on the page +* +* @param Object opts Options object, may contain the following fields: +* title, description, url - parameters of the page you want to share; +* links - array of links that will be shown to the user in popup. +*/ window.LJShare.link = function( opts ) { var defaults = { title: '', @@ -57,33 +159,37 @@ var link = jQuery( 'a:last' ), url = link.attr( 'href' ), options = jQuery.extend( {}, defaults, { url: url } , opts ), - dom; + dom, arrow; - options.links = ( opts.links ) ? opts.links : global_options.links; + var links = ( opts.links ) ? opts.links : global_options.links; function buildDom() { - var list = jQuery( '<ul>', { "class": 'ljshare-service-list' } ), - li, a, clickFunc; + var str = supplant( template.start, global_options.ml ), + serviceName, serviceObj; - for( var i = 0; i < options.links.length; ++i ) { - a = jQuery( '<a>' ) - .html( global_options.services[ options.links[i] ].title ); + for( var i = 0; i < links.length; ++i ) { + serviceName = links[i]; + serviceObj = global_options.services[ serviceName ]; - global_options.services[ options.links[i] ].href = a; - $( '<li>', { "class": 'ljshare-service-' + options.links[i] } ) - .append( a ) - .appendTo( list ); + str+= supplant( template.item, { + name: serviceName, + title: serviceObj.title, + url: supplant( serviceObj.bindLink, options ) + } ); } - dom = $( '<div>', { 'class': 'ljshare-container' } ).css( { + str += supplant( template.end, global_options.ml ); + + dom = $( str ).css( { position: 'absolute', visibility: 'hidden' - } ).append( list ); + } ); } function injectDom() { dom.appendTo( $( document.body ) ); + arrow = dom.find( selectors.arrow ); } function bindControls() { @@ -91,57 +197,49 @@ ev.stopPropagation(); } ); - $( window ).bind( 'click', function( ev ) { - togglePopup( false ); - } ); - - for( var i = 0; i < options.links.length; ++i ) { - _bindLink( global_options.services[ options.links[i] ] ); - } + dom.find( selectors.close ).bind( 'click', function( ev ) { togglePopup( false ); } ); + $( document ).bind( 'click', function( ev ) { togglePopup( false ); } ); + $( window ).bind( 'resize', function( ev ) { togglePopup( false ); } ); + dom.find( selectors.links ).click( function() { togglePopup( false ); } ); } - function _bindLink( service ) { - if( typeof service.bindLink === "string" ) { - callback = function() { - togglePopup( false ); - window.open( service.bindLink.replace( "{url}", encodeURIComponent( options.url ) ) - .replace( "{title}", options.title ) ); - } - } else { - callback = service.bindLink; - } - service.href.click( callback ); - } - function updatePopupPosition() { var linkPos = link.offset(), - linkH = link.height(), linkW = link.width(); + linkH = link.height(), linkW = link.width(), + arrPos = ""; - var scrollOffset = ( window.scrollY !== undefined ) ? scrollY : - ( window.pageYOffset ) ? pageYOffset : - (((t = document.documentElement) || (t = document.body.parentNode)) && typeof t.ScrollTop == 'number' ? t : document.body).ScrollTop; + dom.css( { left: "0px", top: "0px" } ); + var scrollOffset = $( window ).scrollTop(); var upperSpace = linkPos.top - scrollOffset; var lowerSpace = $( window ).height() - upperSpace - linkH; var domH = dom.height(), domW = dom.width(); var linkTop = linkPos.top, linkLeft = linkPos.left; + + //we decide whether the popup should be shown under or above the link if( lowerSpace < domH && upperSpace > domH ) { linkTop -= domH + 5; + arrPos += "b"; } else { linkTop += linkH + 5; + arrPos += "t"; } + //we decide whether the popup should positioned to the left or to the right from the link var windowW = $( window ).width(); if( linkPos.left + domW > windowW ) { - linkLeft = windowW - domW - 10; + linkLeft = windowW - domW - 8; + arrPos += "r"; + } else { + arrPos += "l"; + linkLeft -= 30; } - dom.css( { - left: linkLeft + "px", - top: linkTop + "px" - } ); + arrow.removeClass().addClass( arrow_opts.className ).addClass( arrow_opts.position[ arrPos ] ); + + dom.css( { left: linkLeft + "px",top: linkTop + "px" } ); } function togglePopup( show ) {