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