]> git.mxchange.org Git - friendica.git/blob - js/main.js
958b0a8ae3c8d74b92671b203f5b694f9ab4d42e
[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                         console.log("on", id);
96                         $.colorbox.close();
97                         var textarea = document.getElementById("comment-edit-text-" +id);
98                         var start = textarea.selectionStart;
99                         var end = textarea.selectionEnd;
100                         textarea.value = textarea.value.substring(0, start) + bbcode + textarea.value.substring(end, textarea.value.length);
101                 });
102
103
104
105                 /* setup onoff widgets */
106                 $(".onoff input").each(function(){
107                         val = $(this).val();
108                         id = $(this).attr("id");
109                         $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
110
111                 });
112                 $(".onoff > a").click(function(event){
113                         event.preventDefault();
114                         var input = $(this).siblings("input");
115                         var val = 1-input.val();
116                         var id = input.attr("id");
117                         $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
118                         $("#"+id+"_onoff ."+ (val==1?"on":"off")).removeClass("hidden");
119                         input.val(val);
120                         //console.log(id);
121                 });
122
123                 /* setup field_richtext */
124                 setupFieldRichtext();
125
126                 /* popup menus */
127                 function close_last_popup_menu() {
128                         if(last_popup_menu) {
129                                 last_popup_menu.hide();
130                                 last_popup_menu.off('click', function(e) {e.stopPropagation()});
131                                 last_popup_button.removeClass("selected");
132                                 last_popup_menu = null;
133                                 last_popup_button = null;
134                         }
135                 }
136                 $('a[rel^=#]').click(function(e){
137                         e.preventDefault();
138                         var parent = $(this).parent();
139                         var isSelected = (last_popup_button && parent.attr('id') == last_popup_button.attr('id'));
140                         close_last_popup_menu();
141                         if(isSelected) return false;
142                         menu = $( $(this).attr('rel') );
143                         e.preventDefault();
144                         e.stopPropagation();
145                         if (menu.attr('popup')=="false") return false;
146                         parent.toggleClass("selected");
147                         menu.toggle();
148                         if (menu.css("display") == "none") {
149                                 last_popup_menu = null;
150                                 last_popup_button = null;
151                         } else {
152                                 last_popup_menu = menu;
153                                 last_popup_menu.on('click', function(e) {e.stopPropagation()});
154                                 last_popup_button = parent;
155                                 $('#nav-notifications-menu').perfectScrollbar('update');
156                         }
157                         return false;
158                 });
159                 $('html').click(function() {
160                         close_last_popup_menu();
161                 });
162
163                 // fancyboxes
164                 $("a.popupbox").colorbox({
165                         'inline' : true,
166                         'transition' : 'elastic'
167                 });
168                 $("a.ajax-popupbox").colorbox({
169                         'transition' : 'elastic'
170                 });
171
172                 /* notifications template */
173                 var notifications_tpl= unescape($("#nav-notifications-template[rel=template]").html());
174                 var notifications_all = unescape($('<div>').append( $("#nav-notifications-see-all").clone() ).html()); //outerHtml hack
175                 var notifications_mark = unescape($('<div>').append( $("#nav-notifications-mark-all").clone() ).html()); //outerHtml hack
176                 var notifications_empty = unescape($("#nav-notifications-menu").html());
177
178                 /* enable perfect-scrollbars for different elements */
179                 $('#nav-notifications-menu, aside').perfectScrollbar();
180
181                 /* nav update event  */
182                 $('nav').bind('nav-update', function(e, data){
183                         var invalid = data.invalid || 0;
184                         if(invalid == 1) { window.location.href=window.location.href }
185
186                         ['net', 'home', 'intro', 'mail', 'events', 'birthdays', 'notify'].forEach(function(type) {
187                                 var number = data[type];
188                                 if (number == 0) {
189                                         number = '';
190                                         $('#' + type + '-update').removeClass('show');
191                                 } else {
192                                         $('#' + type + '-update').addClass('show');
193                                 }
194                                 $('#' + type + '-update').text(number);
195                         });
196
197                         var intro = data['intro'];
198                         if(intro == 0) { intro = ''; $('#intro-update-li').removeClass('show') } else { $('#intro-update-li').addClass('show') }
199                         $('#intro-update-li').html(intro);
200
201                         var mail = data['mail'];
202                         if(mail == 0) { mail = ''; $('#mail-update-li').removeClass('show') } else { $('#mail-update-li').addClass('show') }
203                         $('#mail-update-li').html(mail);
204
205                         $(".sidebar-group-li .notify").removeClass("show");
206                         $(data.groups).each(function(key, group) {
207                                 var gid = group.id;
208                                 var gcount = group.count;
209                                 $(".group-"+gid+" .notify").addClass("show").text(gcount);
210                         });
211
212                         $(".forum-widget-entry .notify").removeClass("show");
213                         $(data.forums).each(function(key, forum) {
214                                 var fid = forum.id;
215                                 var fcount = forum.count;
216                                 $(".forum-"+fid+" .notify").addClass("show").text(fcount);
217                         });
218
219                         if (data.notifications.length == 0) {
220                                 $("#nav-notifications-menu").html(notifications_empty);
221                         } else {
222                                 var nnm = $("#nav-notifications-menu");
223                                 nnm.html(notifications_all + notifications_mark);
224
225                                 var notification_lastitem = parseInt(localStorage.getItem("notification-lastitem"));
226                                 var notification_id = 0;
227                                 $(data.notifications).each(function(key, notif){
228                                         var text = notif.message.format('<span class="contactname">' + notif.name + '</span>');
229                                         var contact = ('<a href="' + notif.url + '"><span class="contactname">' + notif.name + '</span></a>');
230                                         var seenclass = (notif.seen == 1) ? "notify-seen" : "notify-unseen";
231                                         var html = notifications_tpl.format(
232                                                 notif.href,                     // {0}  // link to the source
233                                                 notif.photo,                    // {1}  // photo of the contact
234                                                 text,                       // {2}  // preformatted text (autor + text)
235                                                 notif.date,                     // {3}  // date of notification (time ago)
236                                                 seenclass,                  // {4}  // visited status of the notification
237                                                 new Date(notif.timestamp*1000), // {5}  // date of notification
238                                                 notif.url,                      // {6}  // profile url of the contact
239                                                 notif.message.format(contact),  // {7}  // preformatted html (text including author profile url)
240                                                 ''                          // {8}  // Deprecated
241                                         );
242                                         nnm.append(html);
243                                 });
244                                 $(data.notifications.reverse()).each(function(key, e){
245                                         notification_id = parseInt(e.timestamp);
246                                         if (notification_lastitem !== null && notification_id > notification_lastitem) {
247                                                 if (getNotificationPermission() === "granted") {
248                                                         var notification = new Notification(document.title, {
249                                                                                           body: decodeHtml(e.message.replace('&rarr; ', '').format(e.name)),
250                                                                                           icon: e.photo,
251                                                                                          });
252                                                         notification['url'] = e.href;
253                                                         notification.addEventListener("click", function(ev){
254                                                                 window.location = ev.target.url;
255                                                         });
256                                                 }
257                                         }
258
259                                 });
260                                 notification_lastitem = notification_id;
261                                 localStorage.setItem("notification-lastitem", notification_lastitem)
262
263                                 $("img[data-src]", nnm).each(function(i, el){
264                                         // Add src attribute for images with a data-src attribute
265                                         // However, don't bother if the data-src attribute is empty, because
266                                         // an empty "src" tag for an image will cause some browsers
267                                         // to prefetch the root page of the Friendica hub, which will
268                                         // unnecessarily load an entire profile/ or network/ page
269                                         if($(el).data("src") != '') $(el).attr('src', $(el).data("src"));
270                                 });
271                         }
272
273                         var notif = data['notify'];
274                         if (notif > 0){
275                                 $("#nav-notifications-linkmenu").addClass("on");
276                         } else {
277                                 $("#nav-notifications-linkmenu").removeClass("on");
278                         }
279
280                         console.log(data.sysmsgs);
281
282                         $(data.sysmsgs.notice).each(function(key, message){
283                                 $.jGrowl(message, {sticky: true, theme: 'notice'});
284                         });
285                         $(data.sysmsgs.info).each(function(key, message){
286                                 $.jGrowl(message, {sticky: false, theme: 'info', life: 5000});
287                         });
288
289                         /* update the js scrollbars */
290                         $('#nav-notifications-menu').perfectScrollbar('update');
291
292                 });
293
294                 NavUpdate();
295                 // Allow folks to stop the ajax page updates with the pause/break key
296                 $(document).keydown(function(event) {
297                         if(event.keyCode == '8') {
298                                 var target = event.target || event.srcElement;
299                                 if (!/input|textarea/i.test(target.nodeName)) {
300                                         return false;
301                                 }
302                         }
303                         if(event.keyCode == '19' || (event.ctrlKey && event.which == '32')) {
304                                 event.preventDefault();
305                                 if(stopped == false) {
306                                         stopped = true;
307                                         if (event.ctrlKey) {
308                                                 totStopped = true;
309                                         }
310                                         $('#pause').html('<img src="images/pause.gif" alt="pause" style="border: 1px solid black;" />');
311                                 } else {
312                                         unpause();
313                                 }
314                         } else {
315                                 if (!totStopped) {
316                                         unpause();
317                                 }
318                         }
319                 });
320
321                 // Set an event listener for infinite scroll
322                 if(typeof infinite_scroll !== 'undefined') {
323                         $(window).scroll(function(e){
324                                 if ($(document).height() != $(window).height()) {
325                                         // First method that is expected to work - but has problems with Chrome
326                                         if ($(window).scrollTop() > ($(document).height() - $(window).height() * 1.5))
327                                                 loadScrollContent();
328                                 } else {
329                                         // This method works with Chrome - but seems to be much slower in Firefox
330                                         if ($(window).scrollTop() > (($("section").height() + $("header").height() + $("footer").height()) - $(window).height() * 1.5))
331                                                 loadScrollContent();
332                                 }
333                         });
334                 }
335
336
337         });
338
339         function NavUpdate() {
340
341                 if (!stopped) {
342                         var pingCmd = 'ping?format=json' + ((localUser != 0) ? '&f=&uid=' + localUser : '');
343                         $.get(pingCmd, function(data) {
344                                 if (data.result) {
345                                         // send nav-update event
346                                         $('nav').trigger('nav-update', data.result);
347
348                                         // start live update
349                                         ['network', 'profile', 'community', 'notes', 'display'].forEach(function (src) {
350                                                 if ($('#live-' + src).length) {
351                                                         liveUpdate(src);
352                                                 }
353                                         });
354                                         if ($('#live-photos').length) {
355                                                 if (liking) {
356                                                         liking = 0;
357                                                         window.location.href = window.location.href;
358                                                 }
359                                         }
360                                 }
361                         }) ;
362                 }
363                 timer = setTimeout(NavUpdate, updateInterval);
364         }
365
366         function liveUpdate(src) {
367                 if((src == null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; }
368                 if(($('.comment-edit-text-full').length) || (in_progress)) {
369                         if(livetime) {
370                                 clearTimeout(livetime);
371                         }
372                         livetime = setTimeout(function() {liveUpdate(src)}, 5000);
373                         return;
374                 }
375                 if(livetime != null)
376                         livetime = null;
377
378                 prev = 'live-' + src;
379
380                 in_progress = true;
381
382                 if ($(document).scrollTop() == 0)
383                         force_update = true;
384
385                 var udargs = ((netargs.length) ? '/' + netargs : '');
386                 var update_url = 'update_' + src + udargs + '&p=' + profile_uid + '&page=' + profile_page + '&force=' + ((force_update) ? 1 : 0);
387
388                 $.get(update_url,function(data) {
389                         in_progress = false;
390                         force_update = false;
391                         //                      $('.collapsed-comments',data).each(function() {
392                         //      var ident = $(this).attr('id');
393                         //      var is_hidden = $('#' + ident).is(':hidden');
394                         //      if($('#' + ident).length) {
395                         //              $('#' + ident).replaceWith($(this));
396                         //              if(is_hidden)
397                         //                      $('#' + ident).hide();
398                         //      }
399                         //});
400
401                         // add a new thread
402                         $('.toplevel_item',data).each(function() {
403                                 var ident = $(this).attr('id');
404
405                                 if($('#' + ident).length == 0 && profile_page == 1) {
406                                         $('img',this).each(function() {
407                                                 $(this).attr('src',$(this).attr('dst'));
408                                         });
409                                         $('#' + prev).after($(this));
410                                 }
411                                 else {
412                                         // Find out if the hidden comments are open, so we can keep it that way
413                                         // if a new comment has been posted
414                                         var id = $('.hide-comments-total', this).attr('id');
415                                         if(typeof id != 'undefined') {
416                                                 id = id.split('-')[3];
417                                                 var commentsOpen = $("#collapsed-comments-" + id).is(":visible");
418                                         }
419
420                                         $('img',this).each(function() {
421                                                 $(this).attr('src',$(this).attr('dst'));
422                                         });
423                                         //vScroll = $(document).scrollTop();
424                                         $('html').height($('html').height());
425                                         $('#' + ident).replaceWith($(this));
426
427                                         if(typeof id != 'undefined') {
428                                                 if(commentsOpen) showHideComments(id);
429                                         }
430                                         $('html').height('auto');
431                                         //$(document).scrollTop(vScroll);
432                                 }
433                                 prev = ident;
434                         });
435
436                         // reset vars for inserting individual items
437
438                         /*                      prev = 'live-' + src;
439
440                         $('.wall-item-outside-wrapper',data).each(function() {
441                                 var ident = $(this).attr('id');
442
443                                 if($('#' + ident).length == 0 && prev != 'live-' + src) {
444                                                 $('img',this).each(function() {
445                                                         $(this).attr('src',$(this).attr('dst'));
446                                                 });
447                                                 $('#' + prev).after($(this));
448                                 }
449                                 else {
450                                         $('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago'));
451                                         if($('#' + ident + ' ' + '.comment-edit-text-empty').length)
452                                                 $('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
453                                         $('#' + ident + ' ' + '.hide-comments-total').replaceWith($(this).find('.hide-comments-total'));
454                                         $('#' + ident + ' ' + '.wall-item-like').replaceWith($(this).find('.wall-item-like'));
455                                         $('#' + ident + ' ' + '.wall-item-dislike').replaceWith($(this).find('.wall-item-dislike'));
456                                         $('#' + ident + ' ' + '.my-comment-photo').each(function() {
457                                                 $(this).attr('src',$(this).attr('dst'));
458                                         });
459                                 }
460                                 prev = ident;
461                         });
462                         */
463                         $('.like-rotator').hide();
464                         if(commentBusy) {
465                                 commentBusy = false;
466                                 $('body').css('cursor', 'auto');
467                         }
468                         /* autocomplete @nicknames */
469                         $(".comment-edit-form  textarea").editor_autocomplete(baseurl+"/acl");
470                         /* autocomplete bbcode */
471                         $(".comment-edit-form  textarea").bbco_autocomplete('bbcode');
472
473                         // setup videos, since VideoJS won't take care of any loaded via AJAX
474                         if(typeof videojs != 'undefined') videojs.autoSetup();
475                 });
476         }
477
478         function imgbright(node) {
479                 $(node).removeClass("drophide").addClass("drop");
480         }
481
482         function imgdull(node) {
483                 $(node).removeClass("drop").addClass("drophide");
484         }
485
486         // Since our ajax calls are asynchronous, we will give a few
487         // seconds for the first ajax call (setting like/dislike), then
488         // run the updater to pick up any changes and display on the page.
489         // The updater will turn any rotators off when it's done.
490         // This function will have returned long before any of these
491         // events have completed and therefore there won't be any
492         // visible feedback that anything changed without all this
493         // trickery. This still could cause confusion if the "like" ajax call
494         // is delayed and NavUpdate runs before it completes.
495
496         function dolike(ident,verb) {
497                 unpause();
498                 $('#like-rotator-' + ident.toString()).show();
499                 $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate );
500                 liking = 1;
501                 force_update = true;
502         }
503
504         function dosubthread(ident) {
505                 unpause();
506                 $('#like-rotator-' + ident.toString()).show();
507                 $.get('subthread/' + ident.toString(), NavUpdate );
508                 liking = 1;
509         }
510
511
512         function dostar(ident) {
513                 ident = ident.toString();
514                 $('#like-rotator-' + ident).show();
515                 $.get('starred/' + ident, function(data) {
516                         if(data.match(/1/)) {
517                                 $('#starred-' + ident).addClass('starred');
518                                 $('#starred-' + ident).removeClass('unstarred');
519                                 $('#star-' + ident).addClass('hidden');
520                                 $('#unstar-' + ident).removeClass('hidden');
521                         }
522                         else {
523                                 $('#starred-' + ident).addClass('unstarred');
524                                 $('#starred-' + ident).removeClass('starred');
525                                 $('#star-' + ident).removeClass('hidden');
526                                 $('#unstar-' + ident).addClass('hidden');
527                         }
528                         $('#like-rotator-' + ident).hide();
529                 });
530         }
531
532         function doignore(ident) {
533                 ident = ident.toString();
534                 $('#like-rotator-' + ident).show();
535                 $.get('ignored/' + ident, function(data) {
536                         if(data.match(/1/)) {
537                                 $('#ignored-' + ident).addClass('ignored');
538                                 $('#ignored-' + ident).removeClass('unignored');
539                                 $('#ignore-' + ident).addClass('hidden');
540                                 $('#unignore-' + ident).removeClass('hidden');
541                         }
542                         else {
543                                 $('#ignored-' + ident).addClass('unignored');
544                                 $('#ignored-' + ident).removeClass('ignored');
545                                 $('#ignore-' + ident).removeClass('hidden');
546                                 $('#unignore-' + ident).addClass('hidden');
547                         }
548                         $('#like-rotator-' + ident).hide();
549                 });
550         }
551
552         function getPosition(e) {
553                 var cursor = {x:0, y:0};
554                 if ( e.pageX || e.pageY  ) {
555                         cursor.x = e.pageX;
556                         cursor.y = e.pageY;
557                 }
558                 else {
559                         if( e.clientX || e.clientY ) {
560                                 cursor.x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
561                                 cursor.y = e.clientY + (document.documentElement.scrollTop  || document.body.scrollTop)  - document.documentElement.clientTop;
562                         }
563                         else {
564                                 if( e.x || e.y ) {
565                                         cursor.x = e.x;
566                                         cursor.y = e.y;
567                                 }
568                         }
569                 }
570                 return cursor;
571         }
572
573         var lockvisible = false;
574
575         function lockview(event,id) {
576                 event = event || window.event;
577                 cursor = getPosition(event);
578                 if(lockvisible) {
579                         lockviewhide();
580                 }
581                 else {
582                         lockvisible = true;
583                         $.get('lockview/' + id, function(data) {
584                                 $('#panel').html(data);
585                                 $('#panel').css({ 'left': cursor.x + 5 , 'top': cursor.y + 5});
586                                 $('#panel').show();
587                         });
588                 }
589         }
590
591         function lockviewhide() {
592                 lockvisible = false;
593                 $('#panel').hide();
594         }
595
596         function post_comment(id) {
597                 unpause();
598                 commentBusy = true;
599                 $('body').css('cursor', 'wait');
600                 $("#comment-preview-inp-" + id).val("0");
601                 $.post(
602                         "item",
603                         $("#comment-edit-form-" + id).serialize(),
604                         function(data) {
605                                 if(data.success) {
606                                         $("#comment-edit-wrapper-" + id).hide();
607                                         $("#comment-edit-text-" + id).val('');
608                                         var tarea = document.getElementById("comment-edit-text-" + id);
609                                         if(tarea)
610                                                 commentClose(tarea,id);
611                                         if(timer) clearTimeout(timer);
612                                         timer = setTimeout(NavUpdate,10);
613                                         force_update = true;
614                                 }
615                                 if(data.reload) {
616                                         window.location.href=data.reload;
617                                 }
618                         },
619                         "json"
620                 );
621                 return false;
622         }
623
624
625         function preview_comment(id) {
626                 $("#comment-preview-inp-" + id).val("1");
627                 $("#comment-edit-preview-" + id).show();
628                 $.post(
629                         "item",
630                         $("#comment-edit-form-" + id).serialize(),
631                         function(data) {
632                                 if(data.preview) {
633                                         $("#comment-edit-preview-" + id).html(data.preview);
634                                         $("#comment-edit-preview-" + id + " a").click(function() { return false; });
635                                 }
636                         },
637                         "json"
638                 );
639                 return true;
640         }
641
642
643
644         function showHideComments(id) {
645                 if( $("#collapsed-comments-" + id).is(":visible")) {
646                         $("#collapsed-comments-" + id).hide();
647                         $("#hide-comments-" + id).html(window.showMore);
648                 }
649                 else {
650                         $("#collapsed-comments-" + id).show();
651                         $("#hide-comments-" + id).html(window.showFewer);
652                 }
653         }
654
655
656
657         function preview_post() {
658                 $("#jot-preview").val("1");
659                 $("#jot-preview-content").show();
660                 tinyMCE.triggerSave();
661                 $.post(
662                         "item",
663                         $("#profile-jot-form").serialize(),
664                         function(data) {
665                                 if(data.preview) {
666                                         $("#jot-preview-content").html(data.preview);
667                                         $("#jot-preview-content" + " a").click(function() { return false; });
668                                 }
669                         },
670                         "json"
671                 );
672                 $("#jot-preview").val("0");
673                 return true;
674         }
675
676
677         function unpause() {
678                 // unpause auto reloads if they are currently stopped
679                 totStopped = false;
680                 stopped = false;
681                 $('#pause').html('');
682         }
683
684         // load more network content (used for infinite scroll)
685         function loadScrollContent() {
686                 if (lockLoadContent) return;
687                 lockLoadContent = true;
688
689                 $("#scroll-loader").fadeIn('normal');
690
691                 // the page number to load is one higher than the actual
692                 // page number
693                 infinite_scroll.pageno+=1;
694
695                 console.log('Loading page ' + infinite_scroll.pageno);
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 }