jquery.socialshareprivacy.js (25081B)
1 /* 2 * jquery.socialshareprivacy.js | 2 Klicks fuer mehr Datenschutz (1.6) 3 * 4 * http://www.heise.de/extras/socialshareprivacy/ 5 * http://www.heise.de/ct/artikel/2-Klicks-fuer-mehr-Datenschutz-1333879.html 6 * 7 * Copyright (c) 2011-2014 Hilko Holweg, Sebastian Hilbig, Nicolas Heiringhoff, Juergen Schmidt, 8 * Heise Zeitschriften Verlag GmbH & Co. KG, http://www.heise.de 9 * 10 * is released under the MIT License http://www.opensource.org/licenses/mit-license.php 11 * 12 * Spread the word, link to us if you can. 13 */ 14 (function ($) { 15 16 "use strict"; 17 18 // 19 // helper functions 20 // 21 22 // abbreviate at last blank before length and add "\u2026" (horizontal ellipsis) 23 function abbreviateText(text, length) { 24 var abbreviated = decodeURIComponent(text); 25 if (abbreviated.length <= length) { 26 return text; 27 } 28 29 var lastWhitespaceIndex = abbreviated.substring(0, length - 1).lastIndexOf(' '); 30 abbreviated = encodeURIComponent(abbreviated.substring(0, lastWhitespaceIndex)) + "\u2026"; 31 32 return abbreviated; 33 } 34 35 // returns content of <meta name="" content=""> tags or '' if empty/non existant 36 function getMeta(name) { 37 var metaContent = $('meta[name="' + name + '"]').attr('content'); 38 return metaContent || ''; 39 } 40 41 // create tweet text from content of <meta name="DC.title"> and <meta name="DC.creator"> 42 // fallback to content of <title> tag 43 function getTweetText() { 44 var title = getMeta('DC.title'); 45 var creator = getMeta('DC.creator'); 46 47 if (title.length > 0 && creator.length > 0) { 48 title += ' - ' + creator; 49 } else { 50 title = $('title').text(); 51 } 52 53 return encodeURIComponent(title); 54 } 55 56 // build URI from rel="canonical" or document.location 57 function getURI() { 58 var uri = document.location.href; 59 var canonical = $("link[rel=canonical]").attr("href"); 60 61 if (canonical && canonical.length > 0) { 62 if (canonical.indexOf("http") < 0) { 63 canonical = document.location.protocol + "//" + document.location.host + canonical; 64 } 65 uri = canonical; 66 } 67 68 return uri; 69 } 70 71 function cookieSet(name, value, days, path, domain) { 72 var expires = new Date(); 73 expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000)); 74 document.cookie = name + '=' + value + '; expires=' + expires.toUTCString() + '; path=' + path + '; domain=' + domain; 75 } 76 function cookieDel(name, value, path, domain) { 77 var expires = new Date(); 78 expires.setTime(expires.getTime() - 100); 79 document.cookie = name + '=' + value + '; expires=' + expires.toUTCString() + '; path=' + path + '; domain=' + domain; 80 } 81 82 // extend jquery with our plugin function 83 $.fn.socialSharePrivacy = function (settings) { 84 var defaults = { 85 'services' : { 86 'facebook' : { 87 'status' : 'on', 88 'dummy_img' : '../../core/backend/admin/modules/share_buttons/socialshareprivacy/images/dummy_facebook.png', 89 'perma_option' : 'on', 90 'referrer_track' : '', 91 'action' : 'recommend', 92 'layout' : 'button_count', 93 'sharer' : { 94 'status' : 'off', 95 'dummy_img' : '../../core/backend/admin/modules/share_buttons/socialshareprivacy/images/dummy_facebook_share_de.png', 96 'img' : '../../core/backend/admin/modules/share_buttons/socialshareprivacy/images/dummy_facebook_share_active_de.png' 97 } 98 }, 99 'twitter' : { 100 'status' : 'on', 101 'dummy_img' : '../../core/backend/admin/modules/share_buttons/socialshareprivacy/images/dummy_twitter.png', 102 'perma_option' : 'on', 103 'referrer_track' : '', 104 'tweet_text' : getTweetText, 105 'count' : 'horizontal' 106 }, 107 'gplus' : { 108 'status' : 'on', 109 'dummy_img' : '../../core/backend/admin/modules/share_buttons/socialshareprivacy/images/dummy_gplus.png', 110 'perma_option' : 'on', 111 'referrer_track' : '', 112 'size' : 'medium' 113 } 114 }, 115 'info_link' : 'http://www.heise.de/ct/artikel/2-Klicks-fuer-mehr-Datenschutz-1333879.html', 116 'cookie_path' : '/', 117 'cookie_domain' : document.location.host, 118 'cookie_expires' : '365', 119 'css_path' : '../../core/backend/admin/modules/share_buttons/socialshareprivacy/socialshareprivacy.css', 120 'uri' : getURI, 121 'language' : 'de', 122 'lang_path' : '../../core/backend/admin/modules/share_buttons/socialshareprivacy/lang/', 123 'skin' : 'light', 124 'alignment' : 'horizontal', 125 'switch_alignment' : 'left', 126 'perma_orientation' : 'down' 127 }; 128 129 // Standardwerte des Plug-Ins mit den vom User angegebenen Optionen ueberschreiben 130 var options = $.extend(true, defaults, settings); 131 132 var facebook_on = (options.services.facebook.status === 'on'); 133 var facebook_sharer_on = (options.services.facebook.sharer.status === 'on'); 134 var twitter_on = (options.services.twitter.status === 'on'); 135 var gplus_on = (options.services.gplus.status === 'on'); 136 137 // check if at least one service is "on" 138 if (!facebook_on && !twitter_on && !gplus_on) { 139 return; 140 } 141 142 // insert stylesheet into document and prepend target element 143 if (options.css_path.length > 0 && $(window).data('socialshareprivacy_css') != '1') { 144 // IE fix (noetig fuer IE < 9 - wird hier aber fuer alle IE gemacht) 145 if (document.createStyleSheet) { 146 document.createStyleSheet(options.css_path); 147 } 148 else { 149 $('head').append('<link rel="stylesheet" type="text/css" href="' + options.css_path + '" />'); 150 } 151 152 $(window).data('socialshareprivacy_css','1'); 153 } 154 155 var language; 156 157 function loadLangFile() { 158 var d = $.Deferred(); 159 160 $.getJSON(options.lang_path + options.language+'.lang', function(data) { 161 language = data; 162 d.resolve(); 163 }).fail(function(s){ 164 if(typeof console !== "undefined") { 165 console.log('Error ' + s.status + ' while loading the language file ('+options.lang_path+options.language+'.lang)'); 166 } 167 d.reject(); 168 }); 169 170 return d.promise(); 171 } 172 173 return this.each(function () { 174 $('div#socialshareprivacy').each(function(){ 175 var iteration = this; 176 177 $.when( 178 loadLangFile()) 179 .then( function() { 180 $(iteration).prepend('<ul class="social_share_privacy_area clearfix"></ul>'); 181 var context = $('.social_share_privacy_area', iteration); 182 183 // Class for dark skinning 184 if(options.skin == 'dark') { 185 $(context).addClass('skin-dark'); 186 } 187 188 // Class for alignment 189 if(options.alignment == 'vertical') { 190 $(context).addClass('vertical'); 191 192 if(options.switch_alignment == 'right' && 193 ((facebook_on && options.services.facebook.layout == 'box_count') || (!facebook_on)) && 194 ((twitter_on && options.services.twitter.count == 'vertical') || (!twitter_on)) && 195 ((gplus_on && options.services.gplus.size == 'tall') || (!gplus_on))) { 196 $(context).addClass('switch_right'); 197 } 198 } 199 200 // canonical uri that will be shared 201 var uri = options.uri; 202 if (typeof uri === 'function') { 203 uri = uri(context); 204 } 205 206 // 207 // Facebook 208 // 209 if (facebook_on) { 210 var fb_dummy_btn; 211 var fb_code; 212 213 var fb_height = options.services.facebook.layout == 'box_count' ? '61' : '21'; 214 var fb_width = options.services.facebook.layout == 'box_count' ? '90' : '130'; 215 216 var fb_enc_uri = encodeURIComponent(uri + options.services.facebook.referrer_track); 217 218 if (facebook_sharer_on) { 219 fb_dummy_btn = '<img src="' + options.services.facebook.sharer.dummy_img + '" alt="Facebook "Share"-Dummy" class="fb_like_privacy_dummy" />'; 220 fb_code = '<a href="#" onclick="window.open(\'https://www.facebook.com/sharer/sharer.php?u=' + fb_enc_uri + '\', \'facebook-share-dialog\', \'width=626,height=436\'); return false;"><img src="'+options.services.facebook.sharer.img+'" alt="" /></a>'; 221 } 222 else { 223 fb_dummy_btn = '<img src="' + options.services.facebook.dummy_img + '" alt="Facebook "Like"-Dummy" class="fb_like_privacy_dummy" />'; 224 fb_code = '<iframe src="//www.facebook.com/plugins/like.php?locale=' + language.services.facebook.language + '&href=' + fb_enc_uri + '&width=' + fb_width + '&layout=' + options.services.facebook.layout + '&action=' + options.services.facebook.action + '&show_faces=false&share=false&height=' + fb_height + '&colorscheme=' + options.skin + '" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:' + fb_width + 'px; height:' + fb_height + 'px;" allowTransparency="true"></iframe>'; 225 } 226 context.append('<li class="facebook help_info clearfix"><span class="info">' + language.services.facebook.txt_info + '</span><a href="#" class="switch off">' + language.services.facebook.txt_fb_off + '</a><div class="fb_like dummy_btn">' + fb_dummy_btn + '</div></li>'); 227 228 var $container_fb = $('li.facebook', context); 229 $(context).on('click', 'li.facebook div.fb_like img.fb_like_privacy_dummy,li.facebook .switch', function (e) { 230 e.preventDefault(); 231 if ($container_fb.find('.switch').hasClass('off')) { 232 $container_fb.addClass('info_off'); 233 $container_fb.find('.switch').addClass('on').removeClass('off').html(language.services.facebook.txt_fb_on); 234 $container_fb.find('img.fb_like_privacy_dummy').replaceWith(fb_code); 235 } 236 else { 237 $container_fb.removeClass('info_off'); 238 $container_fb.find('.switch').addClass('off').removeClass('on').html(language.services.facebook.txt_fb_off); 239 $container_fb.find('.fb_like').html(fb_dummy_btn); 240 } 241 }); 242 } 243 244 // 245 // Twitter 246 // 247 if (twitter_on) { 248 var text = options.services.twitter.tweet_text; 249 if (typeof text === 'function') { 250 text = text(); 251 } 252 // 120 is the max character count left after twitters automatic url shortening with t.co 253 text = abbreviateText(text, '120'); 254 255 var tw_height = options.services.twitter.count == 'horizontal' ? '25' : '62'; 256 var tw_width = options.services.twitter.count == 'horizontal' ? '130' : '83'; 257 258 var twitter_enc_uri = encodeURIComponent(uri + options.services.twitter.referrer_track); 259 var twitter_count_url = encodeURIComponent(uri); 260 var twitter_code = '<iframe allowtransparency="true" frameborder="0" scrolling="no" src="//platform.twitter.com/widgets/tweet_button.html?url=' + twitter_enc_uri + '&counturl=' + twitter_count_url + '&text=' + text + '&count=' + options.services.twitter.count + '&lang=' + language.services.twitter.language + '&dnt=true" style="width:' + tw_width + 'px; height:' + tw_height + 'px;"></iframe>'; 261 var twitter_dummy_btn = '<img src="' + options.services.twitter.dummy_img + '" alt=""Tweet this"-Dummy" class="tweet_this_dummy" />'; 262 263 context.append('<li class="twitter help_info clearfix"><span class="info">' + language.services.twitter.txt_info + '</span><a href="#" class="switch off">' + language.services.twitter.txt_twitter_off + '</a><div class="tweet dummy_btn">' + twitter_dummy_btn + '</div></li>'); 264 265 var $container_tw = $('li.twitter', context); 266 267 $(context).on('click', 'li.twitter div.tweet img,li.twitter .switch', function (e) { 268 e.preventDefault(); 269 if ($container_tw.find('.switch').hasClass('off')) { 270 $container_tw.addClass('info_off'); 271 $container_tw.find('.switch').addClass('on').removeClass('off').html(language.services.twitter.txt_twitter_on); 272 $container_tw.find('img.tweet_this_dummy').replaceWith(twitter_code); 273 } 274 else { 275 $container_tw.removeClass('info_off'); 276 $container_tw.find('.switch').addClass('off').removeClass('on').html(language.services.twitter.txt_twitter_off); 277 $container_tw.find('.tweet').html(twitter_dummy_btn); 278 } 279 }); 280 } 281 282 // 283 // Google+ 284 // 285 if (gplus_on) { 286 // fuer G+ wird die URL nicht encoded, da das zu einem Fehler fuehrt 287 var gplus_uri = uri + options.services.gplus.referrer_track; 288 289 // we use the Google+ "asynchronous" code, standard code is flaky if inserted into dom after load 290 var gplus_code = '<div class="g-plusone" data-size="' + options.services.gplus.size + '" data-href="' + gplus_uri + '"></div><script type="text/javascript">window.___gcfg = {lang: "' + language.services.gplus.language + '"}; (function() { var po = document.createElement("script"); po.type = "text/javascript"; po.async = true; po.src = "https://apis.google.com/js/platform.js"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(po, s); })(); </script>'; 291 var gplus_dummy_btn = '<img src="' + options.services.gplus.dummy_img + '" alt=""Google+1"-Dummy" class="gplus_one_dummy" />'; 292 293 context.append('<li class="gplus help_info clearfix"><span class="info">' + language.services.gplus.txt_info + '</span><a href="#" class="switch off">' + language.services.gplus.txt_gplus_off + '</a><div class="gplusone dummy_btn">' + gplus_dummy_btn + '</div></li>'); 294 295 var $container_gplus = $('li.gplus', context); 296 297 $(context).on('click', 'li.gplus div.gplusone img,li.gplus .switch', function (e) { 298 e.preventDefault(); 299 if ($container_gplus.find('.switch').hasClass('off')) { 300 $container_gplus.addClass('info_off'); 301 $container_gplus.find('.switch').addClass('on').removeClass('off').html(language.services.gplus.txt_gplus_on); 302 $container_gplus.find('img.gplus_one_dummy').replaceWith(gplus_code); 303 } 304 else { 305 $container_gplus.removeClass('info_off'); 306 $container_gplus.find('.switch').addClass('off').removeClass('on').html(language.services.gplus.txt_gplus_off); 307 $container_gplus.find('.gplusone').html(gplus_dummy_btn); 308 } 309 }); 310 } 311 312 // 313 // Der Info/Settings-Bereich wird eingebunden 314 // 315 context.append('<li class="settings_info ' + options.perma_orientation + '"><div class="settings_info_menu off perma_option_off"><a href="' + options.info_link + '"><span class="help_info icon"><span class="info">' + language.txt_help + '</span></span></a></div></li>'); 316 317 // Info-Overlays mit leichter Verzoegerung einblenden 318 $(context).on('mouseenter', '.help_info:not(.info_off)', function () { 319 var $info_wrapper = $(this); 320 var timeout_id = window.setTimeout(function () { $($info_wrapper).addClass('display'); }, 500); 321 $(this).data('timeout_id', timeout_id); 322 }); 323 $(context).on('mouseleave', '.help_info', function () { 324 var timeout_id = $(this).data('timeout_id'); 325 window.clearTimeout(timeout_id); 326 if ($(this).hasClass('display')) { 327 $(this).removeClass('display'); 328 } 329 }); 330 331 var facebook_perma = (options.services.facebook.perma_option === 'on'); 332 var twitter_perma = (options.services.twitter.perma_option === 'on'); 333 var gplus_perma = (options.services.gplus.perma_option === 'on'); 334 335 // Menue zum dauerhaften Einblenden der aktiven Dienste via Cookie einbinden 336 if ((facebook_on && facebook_perma) || (twitter_on && twitter_perma) || (gplus_on && gplus_perma)) { 337 338 // Cookies abrufen 339 var cookie_list = document.cookie.split(';'); 340 var cookies = '{'; 341 var i = 0; 342 for (; i < cookie_list.length; i += 1) { 343 var foo = cookie_list[i].split('='); 344 // Spaces and Quotes getting removed 345 foo[0] = $.trim(foo[0].replace(/"/g, '')); 346 foo[1] = $.trim(foo[1].replace(/"/g, '')); 347 cookies += '"' + foo[0] + '":"' + foo[1] + '"'; 348 if (i < cookie_list.length - 1) { 349 cookies += ','; 350 } 351 } 352 cookies += '}'; 353 cookies = jQuery.parseJSON(cookies); 354 355 // Container definieren 356 var $container_settings_info = $('li.settings_info', context); 357 358 // Klasse entfernen, die das i-Icon alleine formatiert, da Perma-Optionen eingeblendet werden 359 $container_settings_info.find('.settings_info_menu').removeClass('perma_option_off'); 360 361 // Perma-Optionen-Icon (.settings) und Formular (noch versteckt) einbinden 362 $container_settings_info.find('.settings_info_menu').append('<a href="#" class="settings">' + language.settings + '</a><form><fieldset><legend>' + language.settings_perma + '</legend></fieldset></form>'); 363 364 365 var random = 'r' + Math.floor(Math.random()*101); 366 367 // Die Dienste mit <input> und <label>, sowie checked-Status laut Cookie, schreiben 368 var checked = ' checked="checked"'; 369 if (facebook_on && facebook_perma) { 370 var perma_status_facebook = cookies.socialSharePrivacy_facebook === 'perma_on' ? checked : ''; 371 $container_settings_info.find('form fieldset').append( 372 '<input type="checkbox" name="perma_status_facebook" id="' + random + '_perma_status_facebook"' + perma_status_facebook + ' /><label for="'+random+'_perma_status_facebook">' + language.services.facebook.perma_display_name + '</label>' 373 ); 374 } 375 376 if (twitter_on && twitter_perma) { 377 var perma_status_twitter = cookies.socialSharePrivacy_twitter === 'perma_on' ? checked : ''; 378 $container_settings_info.find('form fieldset').append( 379 '<input type="checkbox" name="perma_status_twitter" id="' + random + '_perma_status_twitter"' + perma_status_twitter + ' /><label for="'+random+'_perma_status_twitter">' + language.services.twitter.perma_display_name + '</label>' 380 ); 381 } 382 383 if (gplus_on && gplus_perma) { 384 var perma_status_gplus = cookies.socialSharePrivacy_gplus === 'perma_on' ? checked : ''; 385 $container_settings_info.find('form fieldset').append( 386 '<input type="checkbox" name="perma_status_gplus" id="'+random+'_perma_status_gplus"' + perma_status_gplus + ' /><label for="'+random+'_perma_status_gplus">' + language.services.gplus.perma_display_name + '</label>' 387 ); 388 } 389 390 // Settings-Menue per Tastatur erreichbar machen, die Mouseevents werden getriggert 391 $(context).on('click', 'li.settings_info .settings', function (e) { 392 e.preventDefault(); 393 if($(this).data('keyb') == 'on') { 394 $('li.settings_info', context).trigger('mouseleave'); 395 $(this).data('keyb','off'); 396 } 397 else { 398 $('li.settings_info .settings', context).trigger('mouseenter'); 399 $(this).data('keyb','on'); 400 } 401 }); 402 403 // Einstellungs-Menue bei mouseover ein-/ausblenden 404 $(context).on('mouseenter', 'li.settings_info .settings', function () { 405 var timeout_id = window.setTimeout(function () { $container_settings_info.find('.settings_info_menu').removeClass('off').addClass('on'); }, 500); 406 $(this).data('timeout_id', timeout_id); 407 }); 408 $(context).on('mouseleave', 'li.settings_info', function () { 409 var timeout_id = $(this).data('timeout_id'); 410 window.clearTimeout(timeout_id); 411 $container_settings_info.find('.settings_info_menu').removeClass('on').addClass('off'); 412 }); 413 414 // Klick-Interaktion auf <input> um Dienste dauerhaft ein- oder auszuschalten (Cookie wird gesetzt oder geloescht) 415 $(context).on('click', 'li.settings_info fieldset input', function (event) { 416 var click = event.target.id; 417 var service = click.substr(click.lastIndexOf('_') + 1, click.length); 418 var cookie_name = 'socialSharePrivacy_' + service; 419 420 if ($('#' + event.target.id + ':checked').length) { 421 cookieSet(cookie_name, 'perma_on', options.cookie_expires, options.cookie_path, options.cookie_domain); 422 $('form fieldset label[for=' + click + ']', context).addClass('checked'); 423 } 424 else { 425 cookieDel(cookie_name, 'perma_on', options.cookie_path, options.cookie_domain); 426 $('form fieldset label[for=' + click + ']', context).removeClass('checked'); 427 } 428 }); 429 430 // Dienste automatisch einbinden, wenn entsprechendes Cookie vorhanden ist 431 if (facebook_on && facebook_perma && cookies.socialSharePrivacy_facebook === 'perma_on') { 432 $('li.facebook .switch', context).click(); 433 } 434 if (twitter_on && twitter_perma && cookies.socialSharePrivacy_twitter === 'perma_on') { 435 $('li.twitter .switch', context).click(); 436 } 437 if (gplus_on && gplus_perma && cookies.socialSharePrivacy_gplus === 'perma_on') { 438 $('li.gplus .switch', context).click(); 439 } 440 } 441 }); // .then() 442 }); 443 }); // this.each(function () 444 }; // $.fn.socialSharePrivacy = function (settings) { 445 }(jQuery));