Subversion-Projekte lars-tiefland.ci

Revision

Revision 47 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
41 lars 1
/*
2
 * jquery.socialshareprivacy.js | 2 Klicks fuer mehr Datenschutz
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 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'         : '/styles/images/dummy_facebook.png',
89
                    'txt_info'          : '2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Facebook senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i</em>.',
90
                    'txt_fb_off'        : 'nicht mit Facebook verbunden',
91
                    'txt_fb_on'         : 'mit Facebook verbunden',
92
                    'perma_option'      : 'on',
93
                    'display_name'      : 'Facebook',
94
                    'referrer_track'    : '',
95
                    'language'          : 'de_DE',
96
                    'action'            : 'recommend'
97
                },
98
                'twitter' : {
99
                    'status'            : 'on',
100
                    'dummy_img'         : '/styles/images/dummy_twitter.png',
101
                    'txt_info'          : '2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Twitter senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i</em>.',
102
                    'txt_twitter_off'   : 'nicht mit Twitter verbunden',
103
                    'txt_twitter_on'    : 'mit Twitter verbunden',
104
                    'perma_option'      : 'on',
105
                    'display_name'      : 'Twitter',
106
                    'referrer_track'    : '',
107
                    'tweet_text'        : getTweetText,
108
                    'language'          : 'en'
109
                },
110
                'gplus' : {
111
                    'status'            : 'on',
112
                    'dummy_img'         : '/styles/images/dummy_gplus.png',
113
                    'txt_info'          : '2 Klicks f&uuml;r mehr Datenschutz: Erst wenn Sie hier klicken, wird der Button aktiv und Sie k&ouml;nnen Ihre Empfehlung an Google+ senden. Schon beim Aktivieren werden Daten an Dritte &uuml;bertragen &ndash; siehe <em>i</em>.',
114
                    'txt_gplus_off'     : 'nicht mit Google+ verbunden',
115
                    'txt_gplus_on'      : 'mit Google+ verbunden',
116
                    'perma_option'      : 'on',
117
                    'display_name'      : 'Google+',
118
                    'referrer_track'    : '',
119
                    'language'          : 'de'
120
                }
121
            },
122
            'info_link'         : 'http://www.heise.de/ct/artikel/2-Klicks-fuer-mehr-Datenschutz-1333879.html',
123
            'txt_help'          : 'Wenn Sie diese Felder durch einen Klick aktivieren, werden Informationen an Facebook, Twitter oder Google in die USA &uuml;bertragen und unter Umst&auml;nden auch dort gespeichert. N&auml;heres erfahren Sie durch einen Klick auf das <em>i</em>.',
124
            'settings_perma'    : 'Dauerhaft aktivieren und Daten&uuml;ber&shy;tragung zustimmen:',
125
            'cookie_path'       : '/',
126
            'cookie_domain'     : document.location.host,
127
            'cookie_expires'    : '365',
128
            'css_path'          : 'socialshareprivacy/socialshareprivacy.css',
129
            'uri'               : getURI
130
        };
131
 
132
        // Standardwerte des Plug-Ings mit den vom User angegebenen Optionen ueberschreiben
133
        var options = $.extend(true, defaults, settings);
134
 
135
        var facebook_on = (options.services.facebook.status === 'on');
136
        var twitter_on  = (options.services.twitter.status  === 'on');
137
        var gplus_on    = (options.services.gplus.status    === 'on');
138
 
139
        // check if at least one service is "on"
140
        if (!facebook_on && !twitter_on && !gplus_on) {
141
            return;
142
        }
143
 
144
        // insert stylesheet into document and prepend target element
145
        if (options.css_path.length > 0) {
146
            // IE fix (noetig fuer IE < 9 - wird hier aber fuer alle IE gemacht)
147
            if (document.createStyleSheet) {
148
                document.createStyleSheet(options.css_path);
149
            } else {
150
                $('head').append('<link rel="stylesheet" type="text/css" href="' + options.css_path + '" />');
151
            }
152
        }
153
 
154
        return this.each(function () {
155
 
156
            $(this).prepend('<ul class="social_share_privacy_area"></ul>');
157
            var context = $('.social_share_privacy_area', this);
158
 
159
            // canonical uri that will be shared
160
            var uri = options.uri;
161
 
162
            if (typeof uri === 'function') {
163
                uri = uri(context);
164
            }
165
 
166
 
167
            //
168
            // Facebook
169
            //
170
            if (facebook_on) {
171
 
172
                var fb_enc_uri = encodeURIComponent(uri + '?from=facebook' + options.services.facebook.referrer_track);
173
 
174
                var fb_code = '<iframe src="http://www.facebook.com/plugins/like.php?locale=' + options.services.facebook.language + '&amp;href=' + fb_enc_uri + '&amp;send=false&amp;layout=button_count&amp;width=120&amp;show_faces=false&amp;action=' + options.services.facebook.action + '&amp;colorscheme=light&amp;font&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:145px; height:21px;" allowTransparency="true"></iframe>';
175
 
176
                var fb_dummy_btn = '<img src="' + options.services.facebook.dummy_img + '" alt="Facebook &quot;Like&quot;-Dummy" class="fb_like_privacy_dummy" />';
177
 
178
                context.append('<li class="facebook help_info"><span class="info">' + options.services.facebook.txt_info + '</span><span class="switch off">' + options.services.facebook.txt_fb_off + '</span><div class="fb_like dummy_btn">' + fb_dummy_btn + '</div></li>');
179
 
180
                var $container_fb = $('li.facebook', context);
181
 
182
                $('li.facebook div.fb_like img.fb_like_privacy_dummy,li.facebook span.switch', context).live('click', function () {
183
                    if ($container_fb.find('span.switch').hasClass('off')) {
184
                        $container_fb.addClass('info_off');
185
                        $container_fb.find('span.switch').addClass('on').removeClass('off').html(options.services.facebook.txt_fb_on);
186
                        $container_fb.find('img.fb_like_privacy_dummy').replaceWith(fb_code);
187
                    } else {
188
                        $container_fb.removeClass('info_off');
189
                        $container_fb.find('span.switch').addClass('off').removeClass('on').html(options.services.facebook.txt_fb_off);
190
                        $container_fb.find('.fb_like').html(fb_dummy_btn);
191
                    }
192
                });
193
            }
194
 
195
            //
196
            // Twitter
197
            //
198
            if (twitter_on) {
199
                var text = options.services.twitter.tweet_text;
200
                if (typeof text === 'function') {
201
                    text = text();
202
                }
203
                // 120 is the max character count left after twitters automatic url shortening with t.co
204
                text = abbreviateText(text, '120');
205
 
206
                var twitter_enc_uri = encodeURIComponent(uri + '?from=twitter' + options.services.twitter.referrer_track);
207
                var twitter_count_url = encodeURIComponent(uri);
208
                var twitter_code = '<iframe allowtransparency="true" frameborder="0" scrolling="no" src="http://platform.twitter.com/widgets/tweet_button.html?url=' + twitter_enc_uri + '&amp;counturl=' + twitter_count_url + '&amp;text=' + text + '&amp;count=horizontal&amp;lang=' + options.services.twitter.language + '" style="width:130px; height:25px;"></iframe>';
209
                var twitter_dummy_btn = '<img src="' + options.services.twitter.dummy_img + '" alt="&quot;Tweet this&quot;-Dummy" class="tweet_this_dummy" />';
210
 
211
                context.append('<li class="twitter help_info"><span class="info">' + options.services.twitter.txt_info + '</span><span class="switch off">' + options.services.twitter.txt_twitter_off + '</span><div class="tweet dummy_btn">' + twitter_dummy_btn + '</div></li>');
212
 
213
                var $container_tw = $('li.twitter', context);
214
 
215
                $('li.twitter div.tweet img,li.twitter span.switch', context).live('click', function () {
216
                    if ($container_tw.find('span.switch').hasClass('off')) {
217
                        $container_tw.addClass('info_off');
218
                        $container_tw.find('span.switch').addClass('on').removeClass('off').html(options.services.twitter.txt_twitter_on);
219
                        $container_tw.find('img.tweet_this_dummy').replaceWith(twitter_code);
220
                    } else {
221
                        $container_tw.removeClass('info_off');
222
                        $container_tw.find('span.switch').addClass('off').removeClass('on').html(options.services.twitter.txt_twitter_off);
223
                        $container_tw.find('.tweet').html(twitter_dummy_btn);
224
                    }
225
                });
226
            }
227
 
228
            //
229
            // Google+
230
            //
231
            if (gplus_on) {
232
                // fuer G+ wird die URL nicht encoded, da das zu einem Fehler fuehrt
233
                var gplus_uri = uri + '?from=googleplus' + options.services.gplus.referrer_track;
234
 
235
                // we use the Google+ "asynchronous" code, standard code is flaky if inserted into dom after load
236
                var gplus_code = '<div class="g-plusone" data-size="medium" data-href="' + gplus_uri + '"></div><script type="text/javascript">window.___gcfg = {lang: "' + options.services.gplus.language + '"}; (function() { var po = document.createElement("script"); po.type = "text/javascript"; po.async = true; po.src = "https://apis.google.com/js/plusone.js"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(po, s); })(); </script>';
237
                var gplus_dummy_btn = '<img src="' + options.services.gplus.dummy_img + '" alt="&quot;Google+1&quot;-Dummy" class="gplus_one_dummy" />';
238
 
239
                context.append('<li class="gplus help_info"><span class="info">' + options.services.gplus.txt_info + '</span><span class="switch off">' + options.services.gplus.txt_gplus_off + '</span><div class="gplusone dummy_btn">' + gplus_dummy_btn + '</div></li>');
240
 
241
                var $container_gplus = $('li.gplus', context);
242
 
243
                $('li.gplus div.gplusone img,li.gplus span.switch', context).live('click', function () {
244
                    if ($container_gplus.find('span.switch').hasClass('off')) {
245
                        $container_gplus.addClass('info_off');
246
                        $container_gplus.find('span.switch').addClass('on').removeClass('off').html(options.services.gplus.txt_gplus_on);
247
                        $container_gplus.find('img.gplus_one_dummy').replaceWith(gplus_code);
248
                    } else {
249
                        $container_gplus.removeClass('info_off');
250
                        $container_gplus.find('span.switch').addClass('off').removeClass('on').html(options.services.gplus.txt_gplus_off);
251
                        $container_gplus.find('.gplusone').html(gplus_dummy_btn);
252
                    }
253
                });
254
            }
255
 
256
            //
257
            // Der Info/Settings-Bereich wird eingebunden
258
            //
259
            context.append('<li class="settings_info"><div class="settings_info_menu off perma_option_off"><a href="' + options.info_link + '"><span class="help_info icon"><span class="info">' + options.txt_help + '</span></span></a></div></li>');
260
 
261
            // Info-Overlays mit leichter Verzoegerung einblenden
262
            $('.help_info:not(.info_off)', context).live('mouseenter', function () {
263
                var $info_wrapper = $(this);
264
                var timeout_id = window.setTimeout(function () { $($info_wrapper).addClass('display'); }, 500);
265
                $(this).data('timeout_id', timeout_id);
266
            });
267
            $('.help_info', context).live('mouseleave', function () {
268
                var timeout_id = $(this).data('timeout_id');
269
                window.clearTimeout(timeout_id);
270
                if ($(this).hasClass('display')) {
271
                    $(this).removeClass('display');
272
                }
273
            });
274
 
275
            var facebook_perma = (options.services.facebook.perma_option === 'on');
276
            var twitter_perma  = (options.services.twitter.perma_option  === 'on');
277
            var gplus_perma    = (options.services.gplus.perma_option    === 'on');
278
 
279
            // Menue zum dauerhaften Einblenden der aktiven Dienste via Cookie einbinden
280
            // Die IE7 wird hier ausgenommen, da er kein JSON kann und die Cookies hier ueber JSON-Struktur abgebildet werden
281
            if (((facebook_on && facebook_perma)
282
                || (twitter_on && twitter_perma)
283
                || (gplus_on && gplus_perma))
284
                    && (!$.browser.msie || ($.browser.msie && $.browser.version > 7.0))) {
285
 
286
                // Cookies abrufen
287
                var cookie_list = document.cookie.split(';');
288
                var cookies = '{';
289
                var i = 0;
290
                for (; i < cookie_list.length; i += 1) {
291
                    var foo = cookie_list[i].split('=');
292
                    cookies += '"' + $.trim(foo[0]) + '":"' + $.trim(foo[1]) + '"';
293
                    if (i < cookie_list.length - 1) {
294
                        cookies += ',';
295
                    }
296
                }
297
                cookies += '}';
298
                cookies = JSON.parse(cookies);
299
 
300
                // Container definieren
301
                var $container_settings_info = $('li.settings_info', context);
302
 
303
                // Klasse entfernen, die das i-Icon alleine formatiert, da Perma-Optionen eingeblendet werden
304
                $container_settings_info.find('.settings_info_menu').removeClass('perma_option_off');
305
 
306
                // Perma-Optionen-Icon (.settings) und Formular (noch versteckt) einbinden
307
                $container_settings_info.find('.settings_info_menu').append('<span class="settings">Einstellungen</span><form><fieldset><legend>' + options.settings_perma + '</legend></fieldset></form>');
308
 
309
 
310
                // Die Dienste mit <input> und <label>, sowie checked-Status laut Cookie, schreiben
311
                var checked = ' checked="checked"';
312
                if (facebook_on && facebook_perma) {
313
                    var perma_status_facebook = cookies.socialSharePrivacy_facebook === 'perma_on' ? checked : '';
314
                    $container_settings_info.find('form fieldset').append(
315
                        '<input type="checkbox" name="perma_status_facebook" id="perma_status_facebook"'
316
                            + perma_status_facebook + ' /><label for="perma_status_facebook">'
317
                            + options.services.facebook.display_name + '</label>'
318
                    );
319
                }
320
 
321
                if (twitter_on && twitter_perma) {
322
                    var perma_status_twitter = cookies.socialSharePrivacy_twitter === 'perma_on' ? checked : '';
323
                    $container_settings_info.find('form fieldset').append(
324
                        '<input type="checkbox" name="perma_status_twitter" id="perma_status_twitter"'
325
                            + perma_status_twitter + ' /><label for="perma_status_twitter">'
326
                            + options.services.twitter.display_name + '</label>'
327
                    );
328
                }
329
 
330
                if (gplus_on && gplus_perma) {
331
                    var perma_status_gplus = cookies.socialSharePrivacy_gplus === 'perma_on' ? checked : '';
332
                    $container_settings_info.find('form fieldset').append(
333
                        '<input type="checkbox" name="perma_status_gplus" id="perma_status_gplus"'
334
                            + perma_status_gplus + ' /><label for="perma_status_gplus">'
335
                            + options.services.gplus.display_name + '</label>'
336
                    );
337
                }
338
 
339
                // Cursor auf Pointer setzen fuer das Zahnrad
340
                $container_settings_info.find('span.settings').css('cursor', 'pointer');
341
 
342
                // Einstellungs-Menue bei mouseover ein-/ausblenden
343
                $($container_settings_info.find('span.settings'), context).live('mouseenter', function () {
344
                    var timeout_id = window.setTimeout(function () { $container_settings_info.find('.settings_info_menu').removeClass('off').addClass('on'); }, 500);
345
                    $(this).data('timeout_id', timeout_id);
346
                });
347
                $($container_settings_info, context).live('mouseleave', function () {
348
                    var timeout_id = $(this).data('timeout_id');
349
                    window.clearTimeout(timeout_id);
350
                    $container_settings_info.find('.settings_info_menu').removeClass('on').addClass('off');
351
                });
352
 
353
                // Klick-Interaktion auf <input> um Dienste dauerhaft ein- oder auszuschalten (Cookie wird gesetzt oder geloescht)
354
                $($container_settings_info.find('fieldset input')).live('click', function (event) {
355
                    var click = event.target.id;
356
                    var service = click.substr(click.lastIndexOf('_') + 1, click.length);
357
                    var cookie_name = 'socialSharePrivacy_' + service;
358
 
359
                    if ($('#' + event.target.id + ':checked').length) {
360
                        cookieSet(cookie_name, 'perma_on', options.cookie_expires, options.cookie_path, options.cookie_domain);
361
                        $('form fieldset label[for=' + click + ']', context).addClass('checked');
362
                    } else {
363
                        cookieDel(cookie_name, 'perma_on', options.cookie_path, options.cookie_domain);
364
                        $('form fieldset label[for=' + click + ']', context).removeClass('checked');
365
                    }
366
                });
367
 
368
                // Dienste automatisch einbinden, wenn entsprechendes Cookie vorhanden ist
369
                if (facebook_on && facebook_perma && cookies.socialSharePrivacy_facebook === 'perma_on') {
370
                    $('li.facebook span.switch', context).click();
371
                }
372
                if (twitter_on && twitter_perma && cookies.socialSharePrivacy_twitter === 'perma_on') {
373
                    $('li.twitter span.switch', context).click();
374
                }
375
                if (gplus_on && gplus_perma && cookies.socialSharePrivacy_gplus === 'perma_on') {
376
                    $('li.gplus span.switch', context).click();
377
                }
378
            }
379
        }); // this.each(function ()
380
    };      // $.fn.socialSharePrivacy = function (settings) {
381
}(jQuery));
382