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