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