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