2 function openClose(theID) {
3 if(document.getElementById(theID).style.display == "block") {
4 document.getElementById(theID).style.display = "none"
7 document.getElementById(theID).style.display = "block"
11 function openMenu(theID) {
12 document.getElementById(theID).style.display = "block"
15 function closeMenu(theID) {
16 document.getElementById(theID).style.display = "none"
24 var force_update = false;
27 var totStopped = false;
31 var in_progress = false;
32 var langSelect = false;
33 var commentBusy = false;
34 var last_popup_menu = null;
35 var last_popup_button = null;
38 $.ajaxSetup({cache: false});
40 msie = $.browser.msie ;
42 /* setup tooltips *//*
43 $("a,.tt").each(function(){
46 if (e.hasClass("tttop")) pos="top";
47 if (e.hasClass("ttbottom")) pos="bottom";
48 if (e.hasClass("ttleft")) pos="left";
49 if (e.hasClass("ttright")) pos="right";
50 e.tipTip({defaultPosition: pos, edgeOffset: 8});
55 /* setup onoff widgets */
56 $(".onoff input").each(function(){
58 id = $(this).attr("id");
59 $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
62 $(".onoff > a").click(function(event){
63 event.preventDefault();
64 var input = $(this).siblings("input");
65 var val = 1-input.val();
66 var id = input.attr("id");
67 $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
68 $("#"+id+"_onoff ."+ (val==1?"on":"off")).removeClass("hidden");
73 /* setup field_richtext */
77 function close_last_popup_menu() {
79 last_popup_menu.hide();
80 last_popup_button.removeClass("selected");
81 last_popup_menu = null;
82 last_popup_button = null;
85 $('a[rel^=#]').click(function(e){
86 close_last_popup_menu();
87 menu = $( $(this).attr('rel') );
90 if (menu.attr('popup')=="false") return false;
91 $(this).parent().toggleClass("selected");
93 if (menu.css("display") == "none") {
94 last_popup_menu = null;
95 last_popup_button = null;
97 last_popup_menu = menu;
98 last_popup_button = $(this).parent();
102 $('html').click(function() {
103 close_last_popup_menu();
107 /*$("a.popupbox").fancybox({
108 'transitionIn' : 'elastic',
109 'transitionOut' : 'elastic'
111 $("a.popupbox").colorbox({
113 'transition' : 'elastic'
117 /* notifications template */
118 var notifications_tpl= unescape($("#nav-notifications-template[rel=template]").html());
119 var notifications_all = unescape($('<div>').append( $("#nav-notifications-see-all").clone() ).html()); //outerHtml hack
120 var notifications_mark = unescape($('<div>').append( $("#nav-notifications-mark-all").clone() ).html()); //outerHtml hack
121 var notifications_empty = unescape($("#nav-notifications-menu").html());
123 /* nav update event */
124 $('nav').bind('nav-update', function(e,data){;
125 var invalid = $(data).find('invalid').text();
126 if(invalid == 1) { window.location.href=window.location.href }
128 var net = $(data).find('net').text();
129 if(net == 0) { net = ''; $('#net-update').removeClass('show') } else { $('#net-update').addClass('show') }
130 $('#net-update').html(net);
132 var home = $(data).find('home').text();
133 if(home == 0) { home = ''; $('#home-update').removeClass('show') } else { $('#home-update').addClass('show') }
134 $('#home-update').html(home);
136 var intro = $(data).find('intro').text();
137 if(intro == 0) { intro = ''; $('#intro-update').removeClass('show') } else { $('#intro-update').addClass('show') }
138 $('#intro-update').html(intro);
140 var mail = $(data).find('mail').text();
141 if(mail == 0) { mail = ''; $('#mail-update').removeClass('show') } else { $('#mail-update').addClass('show') }
142 $('#mail-update').html(mail);
144 var intro = $(data).find('intro').text();
145 if(intro == 0) { intro = ''; $('#intro-update-li').removeClass('show') } else { $('#intro-update-li').addClass('show') }
146 $('#intro-update-li').html(intro);
148 var mail = $(data).find('mail').text();
149 if(mail == 0) { mail = ''; $('#mail-update-li').removeClass('show') } else { $('#mail-update-li').addClass('show') }
150 $('#mail-update-li').html(mail);
153 var allevents = $(data).find('all-events').text();
154 if(allevents == 0) { allevents = ''; $('#allevents-update').removeClass('show') } else { $('#allevents-update').addClass('show') }
155 $('#allevents-update').html(allevents);
157 var alleventstoday = $(data).find('all-events-today').text();
158 if(alleventstoday == 0) { $('#allevents-update').removeClass('notif-allevents-today') } else { $('#allevents-update').addClass('notif-allevents-today') }
160 var events = $(data).find('events').text();
161 if(events == 0) { events = ''; $('#events-update').removeClass('show') } else { $('#events-update').addClass('show') }
162 $('#events-update').html(events);
164 var eventstoday = $(data).find('events-today').text();
165 if(eventstoday == 0) { $('#events-update').removeClass('notif-events-today') } else { $('#events-update').addClass('notif-events-today') }
167 var birthdays = $(data).find('birthdays').text();
168 if(birthdays == 0) {birthdays = ''; $('#birthdays-update').removeClass('show') } else { $('#birthdays-update').addClass('show') }
169 $('#birthdays-update').html(birthdays);
171 var birthdaystoday = $(data).find('birthdays-today').text();
172 if(birthdaystoday == 0) { $('#birthdays-update').removeClass('notif-birthdays-today') } else { $('#birthdays-update').addClass('notif-birthdays-today') }
175 var eNotif = $(data).find('notif')
177 if (eNotif.children("note").length==0){
178 $("#nav-notifications-menu").html(notifications_empty);
180 nnm = $("#nav-notifications-menu");
181 nnm.html(notifications_all + notifications_mark);
182 //nnm.attr('popup','true');
183 eNotif.children("note").each(function(){
185 text = e.text().format("<span class='contactname'>"+e.attr('name')+"</span>");
186 html = notifications_tpl.format(e.attr('href'),e.attr('photo'), text, e.attr('date'), e.attr('seen'));
190 $("img[data-src]", nnm).each(function(i, el){
191 // Add src attribute for images with a data-src attribute
192 // However, don't bother if the data-src attribute is empty, because
193 // an empty "src" tag for an image will cause some browsers
194 // to prefetch the root page of the Friendica hub, which will
195 // unnecessarily load an entire profile/ or network/ page
196 if($(el).data("src") != '') $(el).attr('src', $(el).data("src"));
200 notif = eNotif.attr('count');
202 $("#nav-notifications-linkmenu").addClass("on");
204 $("#nav-notifications-linkmenu").removeClass("on");
206 if(notif == 0) { notif = ''; $('#notify-update').removeClass('show') } else { $('#notify-update').addClass('show') }
207 $('#notify-update').html(notif);
209 var eSysmsg = $(data).find('sysmsgs');
210 eSysmsg.children("notice").each(function(){
211 text = $(this).text();
212 $.jGrowl(text, { sticky: true, theme: 'notice' });
214 eSysmsg.children("info").each(function(){
215 text = $(this).text();
216 $.jGrowl(text, { sticky: false, theme: 'info', life: 10000 });
222 // Allow folks to stop the ajax page updates with the pause/break key
223 $(document).keydown(function(event) {
224 if(event.keyCode == '8') {
225 var target = event.target || event.srcElement;
226 if (!/input|textarea/i.test(target.nodeName)) {
230 if(event.keyCode == '19' || (event.ctrlKey && event.which == '32')) {
231 event.preventDefault();
232 if(stopped == false) {
237 $('#pause').html('<img src="images/pause.gif" alt="pause" style="border: 1px solid black;" />');
251 function NavUpdate() {
254 var pingCmd = 'ping' + ((localUser != 0) ? '?f=&uid=' + localUser : '');
255 $.get(pingCmd,function(data) {
256 $(data).find('result').each(function() {
257 // send nav-update event
258 $('nav').trigger('nav-update', this);
263 if($('#live-network').length) { src = 'network'; liveUpdate(); }
264 if($('#live-profile').length) { src = 'profile'; liveUpdate(); }
265 if($('#live-community').length) { src = 'community'; liveUpdate(); }
266 if($('#live-notes').length) { src = 'notes'; liveUpdate(); }
267 if($('#live-display').length) { src = 'display'; liveUpdate(); }
268 /* if($('#live-display').length) {
271 window.location.href=window.location.href
274 if($('#live-photos').length) {
277 window.location.href=window.location.href
287 timer = setTimeout(NavUpdate,updateInterval);
290 function liveUpdate() {
291 if((src == null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; }
292 if(($('.comment-edit-text-full').length) || (in_progress)) {
294 clearTimeout(livetime);
296 livetime = setTimeout(liveUpdate, 10000);
302 prev = 'live-' + src;
306 if ($(document).scrollTop() == 0)
309 var udargs = ((netargs.length) ? '/' + netargs : '');
310 var update_url = 'update_' + src + udargs + '&p=' + profile_uid + '&page=' + profile_page + '&msie=' + ((msie) ? 1 : 0) + '&force=' + ((force_update) ? 1 : 0);
312 $.get(update_url,function(data) {
314 force_update = false;
315 // $('.collapsed-comments',data).each(function() {
316 // var ident = $(this).attr('id');
317 // var is_hidden = $('#' + ident).is(':hidden');
318 // if($('#' + ident).length) {
319 // $('#' + ident).replaceWith($(this));
321 // $('#' + ident).hide();
326 $('.toplevel_item',data).each(function() {
327 var ident = $(this).attr('id');
329 if($('#' + ident).length == 0 && profile_page == 1) {
330 $('img',this).each(function() {
331 $(this).attr('src',$(this).attr('dst'));
333 $('#' + prev).after($(this));
336 // Find out if the hidden comments are open, so we can keep it that way
337 // if a new comment has been posted
338 var id = $('.hide-comments-total', this).attr('id');
339 if(typeof id != 'undefined') {
340 id = id.split('-')[3];
341 var commentsOpen = $("#collapsed-comments-" + id).is(":visible");
344 $('img',this).each(function() {
345 $(this).attr('src',$(this).attr('dst'));
347 //vScroll = $(document).scrollTop();
348 $('html').height($('html').height());
349 $('#' + ident).replaceWith($(this));
351 if(typeof id != 'undefined') {
352 if(commentsOpen) showHideComments(id);
354 $('html').height('auto');
355 //$(document).scrollTop(vScroll);
360 // reset vars for inserting individual items
362 /* prev = 'live-' + src;
364 $('.wall-item-outside-wrapper',data).each(function() {
365 var ident = $(this).attr('id');
367 if($('#' + ident).length == 0 && prev != 'live-' + src) {
368 $('img',this).each(function() {
369 $(this).attr('src',$(this).attr('dst'));
371 $('#' + prev).after($(this));
374 $('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago'));
375 if($('#' + ident + ' ' + '.comment-edit-text-empty').length)
376 $('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
377 $('#' + ident + ' ' + '.hide-comments-total').replaceWith($(this).find('.hide-comments-total'));
378 $('#' + ident + ' ' + '.wall-item-like').replaceWith($(this).find('.wall-item-like'));
379 $('#' + ident + ' ' + '.wall-item-dislike').replaceWith($(this).find('.wall-item-dislike'));
380 $('#' + ident + ' ' + '.my-comment-photo').each(function() {
381 $(this).attr('src',$(this).attr('dst'));
387 $('.like-rotator').hide();
390 $('body').css('cursor', 'auto');
392 /* autocomplete @nicknames */
393 $(".comment-edit-form textarea").contact_autocomplete(baseurl+"/acl");
395 // setup videos, since VideoJS won't take care of any loaded via AJAX
396 if(typeof videojs != 'undefined') videojs.autoSetup();
400 function imgbright(node) {
401 $(node).removeClass("drophide").addClass("drop");
404 function imgdull(node) {
405 $(node).removeClass("drop").addClass("drophide");
408 // Since our ajax calls are asynchronous, we will give a few
409 // seconds for the first ajax call (setting like/dislike), then
410 // run the updater to pick up any changes and display on the page.
411 // The updater will turn any rotators off when it's done.
412 // This function will have returned long before any of these
413 // events have completed and therefore there won't be any
414 // visible feedback that anything changed without all this
415 // trickery. This still could cause confusion if the "like" ajax call
416 // is delayed and NavUpdate runs before it completes.
418 function dolike(ident,verb) {
420 $('#like-rotator-' + ident.toString()).show();
421 $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate );
426 function dosubthread(ident) {
428 $('#like-rotator-' + ident.toString()).show();
429 $.get('subthread/' + ident.toString(), NavUpdate );
434 function dostar(ident) {
435 ident = ident.toString();
436 $('#like-rotator-' + ident).show();
437 $.get('starred/' + ident, function(data) {
438 if(data.match(/1/)) {
439 $('#starred-' + ident).addClass('starred');
440 $('#starred-' + ident).removeClass('unstarred');
441 $('#star-' + ident).addClass('hidden');
442 $('#unstar-' + ident).removeClass('hidden');
445 $('#starred-' + ident).addClass('unstarred');
446 $('#starred-' + ident).removeClass('starred');
447 $('#star-' + ident).removeClass('hidden');
448 $('#unstar-' + ident).addClass('hidden');
450 $('#like-rotator-' + ident).hide();
454 function getPosition(e) {
455 var cursor = {x:0, y:0};
456 if ( e.pageX || e.pageY ) {
461 if( e.clientX || e.clientY ) {
462 cursor.x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
463 cursor.y = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
475 var lockvisible = false;
477 function lockview(event,id) {
478 event = event || window.event;
479 cursor = getPosition(event);
485 $.get('lockview/' + id, function(data) {
486 $('#panel').html(data);
487 $('#panel').css({ 'left': cursor.x + 5 , 'top': cursor.y + 5});
493 function lockviewhide() {
498 function post_comment(id) {
501 $('body').css('cursor', 'wait');
502 $("#comment-preview-inp-" + id).val("0");
505 $("#comment-edit-form-" + id).serialize(),
508 $("#comment-edit-wrapper-" + id).hide();
509 $("#comment-edit-text-" + id).val('');
510 var tarea = document.getElementById("comment-edit-text-" + id);
512 commentClose(tarea,id);
513 if(timer) clearTimeout(timer);
514 timer = setTimeout(NavUpdate,10);
518 window.location.href=data.reload;
527 function preview_comment(id) {
528 $("#comment-preview-inp-" + id).val("1");
529 $("#comment-edit-preview-" + id).show();
532 $("#comment-edit-form-" + id).serialize(),
536 $("#comment-edit-preview-" + id).html(data.preview);
537 $("#comment-edit-preview-" + id + " a").click(function() { return false; });
547 function showHideComments(id) {
548 if( $("#collapsed-comments-" + id).is(":visible")) {
549 $("#collapsed-comments-" + id).hide();
550 $("#hide-comments-" + id).html(window.showMore);
553 $("#collapsed-comments-" + id).show();
554 $("#hide-comments-" + id).html(window.showFewer);
560 function preview_post() {
561 $("#jot-preview").val("1");
562 $("#jot-preview-content").show();
563 tinyMCE.triggerSave();
566 $("#profile-jot-form").serialize(),
569 $("#jot-preview-content").html(data.preview);
570 $("#jot-preview-content" + " a").click(function() { return false; });
575 $("#jot-preview").val("0");
581 // unpause auto reloads if they are currently stopped
584 $('#pause').html('');
589 // Converts the binary representation of data to hex
592 // discuss at: http://phpjs.org/functions/bin2hex
593 // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
594 // + bugfixed by: Onno Marsman
595 // + bugfixed by: Linuxworld
596 // * example 1: bin2hex('Kev');
597 // * returns 1: '4b6576'
598 // * example 2: bin2hex(String.fromCharCode(0x00));
600 var v,i, f = 0, a = [];
604 for (i = 0; i<f; i++) {
605 a[i] = s.charCodeAt(i).toString(16).replace(/^([\da-f])$/,"0$1");
611 function groupChangeMember(gid, cid, sec_token) {
612 $('body .fakelink').css('cursor', 'wait');
613 $.get('group/' + gid + '/' + cid + "?t=" + sec_token, function(data) {
614 $('#group-update-wrapper').html(data);
615 $('body .fakelink').css('cursor', 'auto');
619 function profChangeMember(gid,cid) {
620 $('body .fakelink').css('cursor', 'wait');
621 $.get('profperm/' + gid + '/' + cid, function(data) {
622 $('#prof-update-wrapper').html(data);
623 $('body .fakelink').css('cursor', 'auto');
627 function contactgroupChangeMember(gid,cid) {
628 $('body').css('cursor', 'wait');
629 $.get('contactgroup/' + gid + '/' + cid, function(data) {
630 $('body').css('cursor', 'auto');
635 function checkboxhighlight(box) {
636 if($(box).is(':checked')) {
637 $(box).addClass('checkeditem');
640 $(box).removeClass('checkeditem');
644 function notifyMarkAll() {
645 $.get('notify/mark/all', function(data) {
646 if(timer) clearTimeout(timer);
647 timer = setTimeout(NavUpdate,1000);
653 // code from http://www.tinymce.com/wiki.php/How-to_implement_a_custom_file_browser
654 function fcFileBrowser (field_name, url, type, win) {
655 /* TODO: If you work with sessions in PHP and your client doesn't accept cookies you might need to carry
656 the session name and session ID in the request string (can look like this: "?PHPSESSID=88p0n70s9dsknra96qhuk6etm5").
657 These lines of code extract the necessary parameters and add them back to the filebrowser URL again. */
660 var cmsURL = baseurl+"/fbrowser/"+type+"/";
662 tinyMCE.activeEditor.windowManager.open({
664 title : 'File Browser',
665 width : 420, // Your dimensions may differ - toy around with them!
668 inline : "yes", // This parameter only has an effect if you use the inlinepopups plugin!
669 close_previous : "no"
677 function setupFieldRichtext(){
680 mode : "specific_textareas",
681 editor_selector: "fieldRichtext",
682 plugins : "bbcode,paste, inlinepopups",
683 theme_advanced_buttons1 : "bold,italic,underline,undo,redo,link,unlink,image,forecolor,formatselect,code",
684 theme_advanced_buttons2 : "",
685 theme_advanced_buttons3 : "",
686 theme_advanced_toolbar_location : "top",
687 theme_advanced_toolbar_align : "center",
688 theme_advanced_blockformats : "blockquote,code",
689 paste_text_sticky : true,
690 entity_encoding : "raw",
691 add_unload_trigger : false,
692 remove_linebreaks : false,
693 //force_p_newlines : false,
694 //force_br_newlines : true,
695 forced_root_block : 'div',
697 content_css: baseurl+"/view/custom_tinymce.css",
698 theme_advanced_path : false,
699 file_browser_callback : "fcFileBrowser",
705 * sprintf in javascript
706 * "{0} and {1}".format('zero','uno');
708 String.prototype.format = function() {
709 var formatted = this;
710 for (var i = 0; i < arguments.length; i++) {
711 var regexp = new RegExp('\\{'+i+'\\}', 'gi');
712 formatted = formatted.replace(regexp, arguments[i]);
717 Array.prototype.remove = function(item) {
718 to=undefined; from=this.indexOf(item);
719 var rest = this.slice((to || from) + 1 || this.length);
720 this.length = from < 0 ? this.length + from : from;
721 return this.push.apply(this, rest);
724 function previewTheme(elm) {
725 theme = $(elm).val();
726 $.getJSON('pretheme?f=&theme=' + theme,function(data) {
727 $('#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>');