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