]> git.mxchange.org Git - friendica.git/blob - js/main.js
fix desktop notification logic, add onclick handler
[friendica.git] / js / main.js
1   function resizeIframe(obj) {
2     obj.style.height = 0;
3     obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
4   }
5
6   function openClose(theID) {
7     if(document.getElementById(theID).style.display == "block") { 
8       document.getElementById(theID).style.display = "none" 
9     }
10     else { 
11       document.getElementById(theID).style.display = "block" 
12     } 
13   }
14
15   function openMenu(theID) {
16       document.getElementById(theID).style.display = "block" 
17   }
18
19   function closeMenu(theID) {
20       document.getElementById(theID).style.display = "none" 
21   }
22
23
24
25         var src = null;
26         var prev = null;
27         var livetime = null;
28         var force_update = false;
29         var stopped = false;
30         var totStopped = false;
31         var timer = null;
32         var pr = 0;
33         var liking = 0;
34         var in_progress = false;
35         var langSelect = false;
36         var commentBusy = false;
37         var last_popup_menu = null;
38         var last_popup_button = null;
39
40         $(function() {
41                 $.ajaxSetup({cache: false});
42
43                 /* setup tooltips *//*
44                 $("a,.tt").each(function(){
45                         var e = $(this);
46                         var pos="bottom";
47                         if (e.hasClass("tttop")) pos="top";
48                         if (e.hasClass("ttbottom")) pos="bottom";
49                         if (e.hasClass("ttleft")) pos="left";
50                         if (e.hasClass("ttright")) pos="right";
51                         e.tipTip({defaultPosition: pos, edgeOffset: 8});
52                 });*/
53                 
54                 
55                 
56                 /* setup onoff widgets */
57                 $(".onoff input").each(function(){
58                         val = $(this).val();
59                         id = $(this).attr("id");
60                         $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
61                         
62                 });
63                 $(".onoff > a").click(function(event){
64                         event.preventDefault(); 
65                         var input = $(this).siblings("input");
66                         var val = 1-input.val();
67                         var id = input.attr("id");
68                         $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
69                         $("#"+id+"_onoff ."+ (val==1?"on":"off")).removeClass("hidden");
70                         input.val(val);
71                         //console.log(id);
72                 });
73                 
74                 /* setup field_richtext */
75                 setupFieldRichtext();
76
77                 /* popup menus */
78                 function close_last_popup_menu() {
79                         if(last_popup_menu) {
80                                 last_popup_menu.hide();
81                                 last_popup_button.removeClass("selected");
82                                 last_popup_menu = null;
83                                 last_popup_button = null;
84                         }
85                 }
86                 $('a[rel^=#]').click(function(e){
87                         e.preventDefault();
88                         var parent = $(this).parent();
89                         var isSelected = (last_popup_button && parent.attr('id') == last_popup_button.attr('id'));
90                         close_last_popup_menu();
91                         if(isSelected) return false;
92                         menu = $( $(this).attr('rel') );
93                         e.preventDefault();
94                         e.stopPropagation();
95                         if (menu.attr('popup')=="false") return false;
96                         parent.toggleClass("selected");
97                         menu.toggle();
98                         if (menu.css("display") == "none") {
99                                 last_popup_menu = null;
100                                 last_popup_button = null;
101                         } else {
102                                 last_popup_menu = menu;
103                                 last_popup_button = parent;
104                         }
105                         return false;
106                 });
107                 $('html').click(function() {
108                         close_last_popup_menu();
109                 });
110                 
111                 // fancyboxes
112                 $("a.popupbox").colorbox({
113                         'inline' : true,
114                         'transition' : 'elastic'
115                 });
116                 
117
118                 /* notifications template */
119                 var notifications_tpl= unescape($("#nav-notifications-template[rel=template]").html());
120                 var notifications_all = unescape($('<div>').append( $("#nav-notifications-see-all").clone() ).html()); //outerHtml hack
121                 var notifications_mark = unescape($('<div>').append( $("#nav-notifications-mark-all").clone() ).html()); //outerHtml hack
122                 var notifications_empty = unescape($("#nav-notifications-menu").html());
123                 
124                 /* nav update event  */
125                 $('nav').bind('nav-update', function(e,data){;
126                         var invalid = $(data).find('invalid').text();
127                         if(invalid == 1) { window.location.href=window.location.href }
128
129                         var net = $(data).find('net').text();
130                         if(net == 0) { net = ''; $('#net-update').removeClass('show') } else { $('#net-update').addClass('show') }
131                         $('#net-update').html(net);
132
133                         var home = $(data).find('home').text();
134                         if(home == 0) { home = '';  $('#home-update').removeClass('show') } else { $('#home-update').addClass('show') }
135                         $('#home-update').html(home);
136                         
137                         var intro = $(data).find('intro').text();
138                         if(intro == 0) { intro = '';  $('#intro-update').removeClass('show') } else { $('#intro-update').addClass('show') }
139                         $('#intro-update').html(intro);
140
141                         var mail = $(data).find('mail').text();
142                         if(mail == 0) { mail = '';  $('#mail-update').removeClass('show') } else { $('#mail-update').addClass('show') }
143                         $('#mail-update').html(mail);
144                         
145                         var intro = $(data).find('intro').text();
146                         if(intro == 0) { intro = '';  $('#intro-update-li').removeClass('show') } else { $('#intro-update-li').addClass('show') }
147                         $('#intro-update-li').html(intro);
148
149                         var mail = $(data).find('mail').text();
150                         if(mail == 0) { mail = '';  $('#mail-update-li').removeClass('show') } else { $('#mail-update-li').addClass('show') }
151                         $('#mail-update-li').html(mail);
152
153
154                         var allevents = $(data).find('all-events').text();
155                         if(allevents == 0) { allevents = ''; $('#allevents-update').removeClass('show') } else { $('#allevents-update').addClass('show') }
156                         $('#allevents-update').html(allevents);
157
158                         var alleventstoday = $(data).find('all-events-today').text();
159                         if(alleventstoday == 0) { $('#allevents-update').removeClass('notif-allevents-today') } else { $('#allevents-update').addClass('notif-allevents-today') }
160
161                         var events = $(data).find('events').text();
162                         if(events == 0) { events = ''; $('#events-update').removeClass('show') } else { $('#events-update').addClass('show') }
163                         $('#events-update').html(events);
164
165                         var eventstoday = $(data).find('events-today').text();
166                         if(eventstoday == 0) { $('#events-update').removeClass('notif-events-today') } else { $('#events-update').addClass('notif-events-today') }
167
168                         var birthdays = $(data).find('birthdays').text();
169                         if(birthdays == 0) {birthdays = ''; $('#birthdays-update').removeClass('show') } else { $('#birthdays-update').addClass('show') }
170                         $('#birthdays-update').html(birthdays);
171
172                         var birthdaystoday = $(data).find('birthdays-today').text();
173                         if(birthdaystoday == 0) { $('#birthdays-update').removeClass('notif-birthdays-today') } else { $('#birthdays-update').addClass('notif-birthdays-today') }
174
175
176                         var eNotif = $(data).find('notif')
177                         
178                         if (eNotif.children("note").length==0){
179                                 $("#nav-notifications-menu").html(notifications_empty);
180                         } else {
181                                 nnm = $("#nav-notifications-menu");
182                                 nnm.html(notifications_all + notifications_mark);
183                                 //nnm.attr('popup','true');
184
185                                 var notification_lastitem = localStorage.getItem("notification-lastitem");
186                                 var notification_first_id = 0;
187                                 
188                                 eNotif.children("note").each(function(){
189                                         e = $(this);
190                                         text = e.text().format("<span class='contactname'>"+e.attr('name')+"</span>");
191                                         html = notifications_tpl.format(e.attr('href'),e.attr('photo'), text, e.attr('date'), e.attr('seen'));
192                                         nnm.append(html);
193                                         
194                                         var notification_id = e.attr('href').match(/\d+$/)[0];
195                                         console.log(notification_lastitem, notification_id);
196                                         if (notification_lastitem!== null && notification_id!=notification_lastitem) {
197                                                 console.log( "eh!",getNotificationPermission() );
198                                                 if (notification_first_id===0) notification_first_id = notification_id;
199                                                 if (getNotificationPermission()==="granted") {
200                                                         var notification = new Notification(document.title, {
201                                                                                           body: e.text().replace('&rarr; ','').format(e.attr('name')),
202                                                                                           icon: e.attr('photo'),
203                                                                                          });
204                                                         // close notification after 5 secs.
205                                                         // see https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API#Closing_notifications
206                                                         setTimeout(notification.close.bind(notification), 5000);
207                                                         
208                                                         notification.addEventListener("click", function(ev){
209                                                                 window.location = ev.target.data;
210                                                         });
211                                                 }
212                                         }
213                                         if (notification_id == notification_lastitem) {
214                                                 if (notification_first_id===0) notification_first_id = notification_id;
215                                                 notification_lastitem = null;
216                                         }
217                                 
218                                         
219                                 });
220                                 if (notification_first_id!==0) notification_lastitem = notification_first_id;
221                                 console.log("end:", notification_lastitem, notification_first_id);
222                                 localStorage.setItem("notification-lastitem", notification_lastitem)
223
224                                 $("img[data-src]", nnm).each(function(i, el){
225                                         // Add src attribute for images with a data-src attribute
226                                         // However, don't bother if the data-src attribute is empty, because
227                                         // an empty "src" tag for an image will cause some browsers
228                                         // to prefetch the root page of the Friendica hub, which will
229                                         // unnecessarily load an entire profile/ or network/ page
230                                         if($(el).data("src") != '') $(el).attr('src', $(el).data("src"));
231                                 });
232                         }
233
234                         notif = eNotif.attr('count');
235                         if (notif>0){
236                                 $("#nav-notifications-linkmenu").addClass("on");
237                         } else {
238                                 $("#nav-notifications-linkmenu").removeClass("on");
239                         }
240                         if(notif == 0) { notif = ''; $('#notify-update').removeClass('show') } else { $('#notify-update').addClass('show') }
241                         $('#notify-update').html(notif);
242                         
243                         var eSysmsg = $(data).find('sysmsgs');
244                         eSysmsg.children("notice").each(function(){
245                                 text = $(this).text();
246                                 $.jGrowl(text, { sticky: true, theme: 'notice' });
247                         });
248                         eSysmsg.children("info").each(function(){
249                                 text = $(this).text();
250                                 $.jGrowl(text, { sticky: false, theme: 'info', life: 5000 });
251                         });
252                         
253                 });
254
255                 NavUpdate(); 
256                 // Allow folks to stop the ajax page updates with the pause/break key
257                 $(document).keydown(function(event) {
258                         if(event.keyCode == '8') {
259                                 var target = event.target || event.srcElement;
260                                 if (!/input|textarea/i.test(target.nodeName)) {
261                                         return false;
262                                 }
263                         }
264                         if(event.keyCode == '19' || (event.ctrlKey && event.which == '32')) {
265                                 event.preventDefault();
266                                 if(stopped == false) {
267                                         stopped = true;
268                                         if (event.ctrlKey) {
269                                                 totStopped = true;
270                                         }
271                                         $('#pause').html('<img src="images/pause.gif" alt="pause" style="border: 1px solid black;" />');
272                                 } else {
273                                         unpause();
274                                 }
275                         } else {
276                                 if (!totStopped) {
277                                         unpause();
278                                 }
279                         }
280                 });
281                 
282                 
283         });
284
285         function NavUpdate() {
286
287                 if(! stopped) {
288                         var pingCmd = 'ping' + ((localUser != 0) ? '?f=&uid=' + localUser : '');
289                         $.get(pingCmd,function(data) {
290                                 $(data).find('result').each(function() {
291                                         // send nav-update event
292                                         $('nav').trigger('nav-update', this);
293                                         
294                                         
295                                         // start live update
296
297                                         if($('#live-network').length)   { src = 'network'; liveUpdate(); }
298                                         if($('#live-profile').length)   { src = 'profile'; liveUpdate(); }
299                                         if($('#live-community').length) { src = 'community'; liveUpdate(); }
300                                         if($('#live-notes').length)     { src = 'notes'; liveUpdate(); }
301                                         if($('#live-display').length)     { src = 'display'; liveUpdate(); }
302 /*                                      if($('#live-display').length) {
303                                                 if(liking) {
304                                                         liking = 0;
305                                                         window.location.href=window.location.href 
306                                                 }
307                                         }*/
308                                         if($('#live-photos').length) { 
309                                                 if(liking) {
310                                                         liking = 0;
311                                                         window.location.href=window.location.href 
312                                                 }
313                                         }
314
315                                         
316                                         
317                                         
318                                 });
319                         }) ;
320                 }
321                 timer = setTimeout(NavUpdate,updateInterval);
322         }
323
324         function liveUpdate() {
325                 if((src == null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; }
326                 if(($('.comment-edit-text-full').length) || (in_progress)) {
327                         if(livetime) {
328                                 clearTimeout(livetime);
329                         }
330                         livetime = setTimeout(liveUpdate, 5000);
331                         return;
332                 }
333                 if(livetime != null)
334                         livetime = null;
335
336                 prev = 'live-' + src;
337
338                 in_progress = true;
339
340                 if ($(document).scrollTop() == 0)
341                         force_update = true;
342
343                 var udargs = ((netargs.length) ? '/' + netargs : '');
344                 var update_url = 'update_' + src + udargs + '&p=' + profile_uid + '&page=' + profile_page + '&force=' + ((force_update) ? 1 : 0);
345
346                 $.get(update_url,function(data) {
347                         in_progress = false;
348                         force_update = false;
349                         //                      $('.collapsed-comments',data).each(function() {
350                         //      var ident = $(this).attr('id');
351                         //      var is_hidden = $('#' + ident).is(':hidden');
352                         //      if($('#' + ident).length) {
353                         //              $('#' + ident).replaceWith($(this));
354                         //              if(is_hidden)
355                         //                      $('#' + ident).hide();
356                         //      }
357                         //});
358
359                         // add a new thread
360                         $('.toplevel_item',data).each(function() {
361                                 var ident = $(this).attr('id');
362
363                                 if($('#' + ident).length == 0 && profile_page == 1) {
364                                         $('img',this).each(function() {
365                                                 $(this).attr('src',$(this).attr('dst'));
366                                         });
367                                         $('#' + prev).after($(this));
368                                 }
369                                 else {
370                                         // Find out if the hidden comments are open, so we can keep it that way
371                                         // if a new comment has been posted
372                                         var id = $('.hide-comments-total', this).attr('id');
373                                         if(typeof id != 'undefined') {
374                                                 id = id.split('-')[3];
375                                                 var commentsOpen = $("#collapsed-comments-" + id).is(":visible");
376                                         }
377
378                                         $('img',this).each(function() {
379                                                 $(this).attr('src',$(this).attr('dst'));
380                                         });
381                                         //vScroll = $(document).scrollTop();
382                                         $('html').height($('html').height());
383                                         $('#' + ident).replaceWith($(this));
384
385                                         if(typeof id != 'undefined') {
386                                                 if(commentsOpen) showHideComments(id);
387                                         }
388                                         $('html').height('auto');
389                                         //$(document).scrollTop(vScroll);
390                                 }
391                                 prev = ident;
392                         });
393
394                         // reset vars for inserting individual items
395
396                         /*                      prev = 'live-' + src;
397
398                         $('.wall-item-outside-wrapper',data).each(function() {
399                                 var ident = $(this).attr('id');
400
401                                 if($('#' + ident).length == 0 && prev != 'live-' + src) {
402                                                 $('img',this).each(function() {
403                                                         $(this).attr('src',$(this).attr('dst'));
404                                                 });
405                                                 $('#' + prev).after($(this));
406                                 }
407                                 else { 
408                                         $('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago')); 
409                                         if($('#' + ident + ' ' + '.comment-edit-text-empty').length)
410                                                 $('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
411                                         $('#' + ident + ' ' + '.hide-comments-total').replaceWith($(this).find('.hide-comments-total'));
412                                         $('#' + ident + ' ' + '.wall-item-like').replaceWith($(this).find('.wall-item-like'));
413                                         $('#' + ident + ' ' + '.wall-item-dislike').replaceWith($(this).find('.wall-item-dislike'));
414                                         $('#' + ident + ' ' + '.my-comment-photo').each(function() {
415                                                 $(this).attr('src',$(this).attr('dst'));
416                                         });
417                                 }
418                                 prev = ident; 
419                         });
420                         */
421                         $('.like-rotator').hide();
422                         if(commentBusy) {
423                                 commentBusy = false;
424                                 $('body').css('cursor', 'auto');
425                         }
426                         /* autocomplete @nicknames */
427                         $(".comment-edit-form  textarea").contact_autocomplete(baseurl+"/acl");
428
429                         // setup videos, since VideoJS won't take care of any loaded via AJAX
430                         if(typeof videojs != 'undefined') videojs.autoSetup();
431                 });
432         }
433
434         function imgbright(node) {
435                 $(node).removeClass("drophide").addClass("drop");
436         }
437
438         function imgdull(node) {
439                 $(node).removeClass("drop").addClass("drophide");
440         }
441
442         // Since our ajax calls are asynchronous, we will give a few 
443         // seconds for the first ajax call (setting like/dislike), then 
444         // run the updater to pick up any changes and display on the page.
445         // The updater will turn any rotators off when it's done. 
446         // This function will have returned long before any of these
447         // events have completed and therefore there won't be any
448         // visible feedback that anything changed without all this
449         // trickery. This still could cause confusion if the "like" ajax call
450         // is delayed and NavUpdate runs before it completes.
451
452         function dolike(ident,verb) {
453                 unpause();
454                 $('#like-rotator-' + ident.toString()).show();
455                 $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate );
456                 liking = 1;
457                 force_update = true;
458         }
459
460         function dosubthread(ident) {
461                 unpause();
462                 $('#like-rotator-' + ident.toString()).show();
463                 $.get('subthread/' + ident.toString(), NavUpdate );
464                 liking = 1;
465         }
466
467
468         function dostar(ident) {
469                 ident = ident.toString();
470                 $('#like-rotator-' + ident).show();
471                 $.get('starred/' + ident, function(data) {
472                         if(data.match(/1/)) {
473                                 $('#starred-' + ident).addClass('starred');
474                                 $('#starred-' + ident).removeClass('unstarred');
475                                 $('#star-' + ident).addClass('hidden');
476                                 $('#unstar-' + ident).removeClass('hidden');
477                         }
478                         else {
479                                 $('#starred-' + ident).addClass('unstarred');
480                                 $('#starred-' + ident).removeClass('starred');
481                                 $('#star-' + ident).removeClass('hidden');
482                                 $('#unstar-' + ident).addClass('hidden');
483                         }
484                         $('#like-rotator-' + ident).hide();
485                 });
486         }
487
488         function doignore(ident) {
489                 ident = ident.toString();
490                 $('#like-rotator-' + ident).show();
491                 $.get('ignored/' + ident, function(data) {
492                         if(data.match(/1/)) {
493                                 $('#ignored-' + ident).addClass('ignored');
494                                 $('#ignored-' + ident).removeClass('unignored');
495                                 $('#ignore-' + ident).addClass('hidden');
496                                 $('#unignore-' + ident).removeClass('hidden');
497                         }
498                         else {
499                                 $('#ignored-' + ident).addClass('unignored');
500                                 $('#ignored-' + ident).removeClass('ignored');
501                                 $('#ignore-' + ident).removeClass('hidden');
502                                 $('#unignore-' + ident).addClass('hidden');
503                         }
504                         $('#like-rotator-' + ident).hide();
505                 });
506         }
507
508         function getPosition(e) {
509                 var cursor = {x:0, y:0};
510                 if ( e.pageX || e.pageY  ) {
511                         cursor.x = e.pageX;
512                         cursor.y = e.pageY;
513                 }
514                 else {
515                         if( e.clientX || e.clientY ) {
516                                 cursor.x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
517                                 cursor.y = e.clientY + (document.documentElement.scrollTop  || document.body.scrollTop)  - document.documentElement.clientTop;
518                         }
519                         else {
520                                 if( e.x || e.y ) {
521                                         cursor.x = e.x;
522                                         cursor.y = e.y;
523                                 }
524                         }
525                 }
526                 return cursor;
527         }
528
529         var lockvisible = false;
530
531         function lockview(event,id) {
532                 event = event || window.event;
533                 cursor = getPosition(event);
534                 if(lockvisible) {
535                         lockviewhide();
536                 }
537                 else {
538                         lockvisible = true;
539                         $.get('lockview/' + id, function(data) {
540                                 $('#panel').html(data);
541                                 $('#panel').css({ 'left': cursor.x + 5 , 'top': cursor.y + 5});
542                                 $('#panel').show();
543                         });
544                 }
545         }
546
547         function lockviewhide() {
548                 lockvisible = false;
549                 $('#panel').hide();
550         }
551
552         function post_comment(id) {
553                 unpause();
554                 commentBusy = true;
555                 $('body').css('cursor', 'wait');
556                 $("#comment-preview-inp-" + id).val("0");
557                 $.post(  
558              "item",  
559              $("#comment-edit-form-" + id).serialize(),
560                         function(data) {
561                                 if(data.success) {
562                                         $("#comment-edit-wrapper-" + id).hide();
563                                         $("#comment-edit-text-" + id).val('');
564                                 var tarea = document.getElementById("comment-edit-text-" + id);
565                                         if(tarea)
566                                                 commentClose(tarea,id);
567                                         if(timer) clearTimeout(timer);
568                                         timer = setTimeout(NavUpdate,10);
569                                         force_update = true;
570                                 }
571                                 if(data.reload) {
572                                         window.location.href=data.reload;
573                                 }
574                         },
575                         "json"  
576          );  
577          return false;  
578         }
579
580
581         function preview_comment(id) {
582                 $("#comment-preview-inp-" + id).val("1");
583                 $("#comment-edit-preview-" + id).show();
584                 $.post(  
585              "item",  
586              $("#comment-edit-form-" + id).serialize(),
587                         function(data) {
588                                 if(data.preview) {
589                                                 
590                                         $("#comment-edit-preview-" + id).html(data.preview);
591                                         $("#comment-edit-preview-" + id + " a").click(function() { return false; });
592                                 }
593                         },
594                         "json"  
595          );  
596          return true;  
597         }
598
599
600
601         function showHideComments(id) {
602                 if( $("#collapsed-comments-" + id).is(":visible")) {
603                         $("#collapsed-comments-" + id).hide();
604                         $("#hide-comments-" + id).html(window.showMore);
605                 }
606                 else {
607                         $("#collapsed-comments-" + id).show();
608                         $("#hide-comments-" + id).html(window.showFewer);
609                 }
610         }
611
612
613
614         function preview_post() {
615                 $("#jot-preview").val("1");
616                 $("#jot-preview-content").show();
617                 tinyMCE.triggerSave();
618                 $.post(  
619                         "item",  
620                         $("#profile-jot-form").serialize(),
621                         function(data) {
622                                 if(data.preview) {                      
623                                         $("#jot-preview-content").html(data.preview);
624                                         $("#jot-preview-content" + " a").click(function() { return false; });
625                                 }
626                         },
627                         "json"  
628                 );  
629                 $("#jot-preview").val("0");
630                 return true;  
631         }
632
633
634         function unpause() {
635                 // unpause auto reloads if they are currently stopped
636                 totStopped = false;
637                 stopped = false;
638             $('#pause').html('');
639         }
640                 
641
642     function bin2hex(s){  
643         // Converts the binary representation of data to hex    
644         //   
645         // version: 812.316  
646         // discuss at: http://phpjs.org/functions/bin2hex  
647         // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)  
648         // +   bugfixed by: Onno Marsman  
649         // +   bugfixed by: Linuxworld  
650         // *     example 1: bin2hex('Kev');  
651         // *     returns 1: '4b6576'  
652         // *     example 2: bin2hex(String.fromCharCode(0x00));  
653         // *     returns 2: '00'  
654         var v,i, f = 0, a = [];  
655         s += '';  
656         f = s.length;  
657           
658         for (i = 0; i<f; i++) {  
659             a[i] = s.charCodeAt(i).toString(16).replace(/^([\da-f])$/,"0$1");  
660         }  
661           
662         return a.join('');  
663     }  
664
665         function groupChangeMember(gid, cid, sec_token) {
666                 $('body .fakelink').css('cursor', 'wait');
667                 $.get('group/' + gid + '/' + cid + "?t=" + sec_token, function(data) {
668                                 $('#group-update-wrapper').html(data);
669                                 $('body .fakelink').css('cursor', 'auto');                              
670                 });
671         }
672
673         function profChangeMember(gid,cid) {
674                 $('body .fakelink').css('cursor', 'wait');
675                 $.get('profperm/' + gid + '/' + cid, function(data) {
676                                 $('#prof-update-wrapper').html(data);
677                                 $('body .fakelink').css('cursor', 'auto');                              
678                 });
679         }
680
681         function contactgroupChangeMember(gid,cid) {
682                 $('body').css('cursor', 'wait');
683                 $.get('contactgroup/' + gid + '/' + cid, function(data) {
684                                 $('body').css('cursor', 'auto');
685                 });
686         }
687
688
689 function checkboxhighlight(box) {
690   if($(box).is(':checked')) {
691         $(box).addClass('checkeditem');
692   }
693   else {
694         $(box).removeClass('checkeditem');
695   }
696 }
697
698 function notifyMarkAll() {
699         $.get('notify/mark/all', function(data) {
700                 if(timer) clearTimeout(timer);
701                 timer = setTimeout(NavUpdate,1000);
702                 force_update = true;
703         });
704 }
705
706
707 // code from http://www.tinymce.com/wiki.php/How-to_implement_a_custom_file_browser
708 function fcFileBrowser (field_name, url, type, win) {
709     /* TODO: If you work with sessions in PHP and your client doesn't accept cookies you might need to carry
710        the session name and session ID in the request string (can look like this: "?PHPSESSID=88p0n70s9dsknra96qhuk6etm5").
711        These lines of code extract the necessary parameters and add them back to the filebrowser URL again. */
712
713
714     var cmsURL = baseurl+"/fbrowser/"+type+"/";
715
716     tinyMCE.activeEditor.windowManager.open({
717         file : cmsURL,
718         title : 'File Browser',
719         width : 420,  // Your dimensions may differ - toy around with them!
720         height : 400,
721         resizable : "yes",
722         inline : "yes",  // This parameter only has an effect if you use the inlinepopups plugin!
723         close_previous : "no"
724     }, {
725         window : win,
726         input : field_name
727     });
728     return false;
729   }
730
731 function setupFieldRichtext(){
732         tinyMCE.init({
733                 theme : "advanced",
734                 mode : "specific_textareas",
735                 editor_selector: "fieldRichtext",
736                 plugins : "bbcode,paste, inlinepopups",
737                 theme_advanced_buttons1 : "bold,italic,underline,undo,redo,link,unlink,image,forecolor,formatselect,code",
738                 theme_advanced_buttons2 : "",
739                 theme_advanced_buttons3 : "",
740                 theme_advanced_toolbar_location : "top",
741                 theme_advanced_toolbar_align : "center",
742                 theme_advanced_blockformats : "blockquote,code",
743                 theme_advanced_resizing : true,
744                 paste_text_sticky : true,
745                 entity_encoding : "raw",
746                 add_unload_trigger : false,
747                 remove_linebreaks : false,
748                 //force_p_newlines : false,
749                 //force_br_newlines : true,
750                 forced_root_block : 'div',
751                 convert_urls: false,
752                 content_css: baseurl+"/view/custom_tinymce.css",
753                 theme_advanced_path : false,
754                 file_browser_callback : "fcFileBrowser",
755         });
756 }
757
758
759 /** 
760  * sprintf in javascript 
761  *      "{0} and {1}".format('zero','uno'); 
762  **/
763 String.prototype.format = function() {
764     var formatted = this;
765     for (var i = 0; i < arguments.length; i++) {
766         var regexp = new RegExp('\\{'+i+'\\}', 'gi');
767         formatted = formatted.replace(regexp, arguments[i]);
768     }
769     return formatted;
770 };
771 // Array Remove
772 Array.prototype.remove = function(item) {
773   to=undefined; from=this.indexOf(item);
774   var rest = this.slice((to || from) + 1 || this.length);
775   this.length = from < 0 ? this.length + from : from;
776   return this.push.apply(this, rest);
777 };
778
779 function previewTheme(elm) {
780         theme = $(elm).val();
781         $.getJSON('pretheme?f=&theme=' + theme,function(data) {
782                         $('#theme-preview').html('<div id="theme-desc">' + data.desc + '</div><div id="theme-version">' + data.version + '</div><div id="theme-credits">' + data.credits + '</div><a href="' + data.img + '"><img src="' + data.img + '" width="320" height="240" alt="' + theme + '" /></a>');
783         });
784
785 }
786
787 // notification permission settings in localstorage
788 // set by settings page
789 function getNotificationPermission() {
790         if (window.Notification === undefined) {
791                 return null;
792         }
793     if (Notification.permission === 'granted') {
794         return localStorage.getItem('notification-permissions');
795     } else {
796         return Notification.permission;
797     }
798 }