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"
26 var totStopped = false;
30 var in_progress = false;
31 var langSelect = false;
32 var commentBusy = false;
33 var last_popup_menu = null;
34 var last_popup_button = null;
37 $.ajaxSetup({cache: false});
39 msie = $.browser.msie ;
41 /* setup tooltips *//*
42 $("a,.tt").each(function(){
45 if (e.hasClass("tttop")) pos="top";
46 if (e.hasClass("ttbottom")) pos="bottom";
47 if (e.hasClass("ttleft")) pos="left";
48 if (e.hasClass("ttright")) pos="right";
49 e.tipTip({defaultPosition: pos, edgeOffset: 8});
54 /* setup onoff widgets */
55 $(".onoff input").each(function(){
57 id = $(this).attr("id");
58 $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
61 $(".onoff > a").click(function(event){
62 event.preventDefault();
63 var input = $(this).siblings("input");
64 var val = 1-input.val();
65 var id = input.attr("id");
66 $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
67 $("#"+id+"_onoff ."+ (val==1?"on":"off")).removeClass("hidden");
72 /* setup field_richtext */
76 function close_last_popup_menu() {
78 last_popup_menu.hide();
79 last_popup_button.removeClass("selected");
80 last_popup_menu = null;
81 last_popup_button = null;
84 $('a[rel^=#]').click(function(e){
85 close_last_popup_menu();
86 menu = $( $(this).attr('rel') );
89 if (menu.attr('popup')=="false") return false;
90 $(this).parent().toggleClass("selected");
92 if (menu.css("display") == "none") {
93 last_popup_menu = null;
94 last_popup_button = null;
96 last_popup_menu = menu;
97 last_popup_button = $(this).parent();
101 $('html').click(function() {
102 close_last_popup_menu();
106 /*$("a.popupbox").fancybox({
107 'transitionIn' : 'elastic',
108 'transitionOut' : 'elastic'
110 $("a.popupbox").colorbox({
112 'transition' : 'elastic'
116 /* notifications template */
117 var notifications_tpl= unescape($("#nav-notifications-template[rel=template]").html());
118 var notifications_all = unescape($('<div>').append( $("#nav-notifications-see-all").clone() ).html()); //outerHtml hack
119 var notifications_mark = unescape($('<div>').append( $("#nav-notifications-mark-all").clone() ).html()); //outerHtml hack
120 var notifications_empty = unescape($("#nav-notifications-menu").html());
122 /* nav update event */
123 $('nav').bind('nav-update', function(e,data){;
124 var invalid = $(data).find('invalid').text();
125 if(invalid == 1) { window.location.href=window.location.href }
127 var net = $(data).find('net').text();
128 if(net == 0) { net = ''; $('#net-update').removeClass('show') } else { $('#net-update').addClass('show') }
129 $('#net-update').html(net);
131 var home = $(data).find('home').text();
132 if(home == 0) { home = ''; $('#home-update').removeClass('show') } else { $('#home-update').addClass('show') }
133 $('#home-update').html(home);
135 var intro = $(data).find('intro').text();
136 if(intro == 0) { intro = ''; $('#intro-update').removeClass('show') } else { $('#intro-update').addClass('show') }
137 $('#intro-update').html(intro);
139 var mail = $(data).find('mail').text();
140 if(mail == 0) { mail = ''; $('#mail-update').removeClass('show') } else { $('#mail-update').addClass('show') }
141 $('#mail-update').html(mail);
143 var intro = $(data).find('intro').text();
144 if(intro == 0) { intro = ''; $('#intro-update-li').removeClass('show') } else { $('#intro-update-li').addClass('show') }
145 $('#intro-update-li').html(intro);
147 var mail = $(data).find('mail').text();
148 if(mail == 0) { mail = ''; $('#mail-update-li').removeClass('show') } else { $('#mail-update-li').addClass('show') }
149 $('#mail-update-li').html(mail);
152 var allevents = $(data).find('all-events').text();
153 if(allevents == 0) { allevents = ''; $('#allevents-update').removeClass('show') } else { $('#allevents-update').addClass('show') }
154 $('#allevents-update').html(allevents);
156 var alleventstoday = $(data).find('all-events-today').text();
157 if(alleventstoday == 0) { $('#allevents-update').removeClass('notif-allevents-today') } else { $('#allevents-update').addClass('notif-allevents-today') }
159 var events = $(data).find('events').text();
160 if(events == 0) { events = ''; $('#events-update').removeClass('show') } else { $('#events-update').addClass('show') }
161 $('#events-update').html(events);
163 var eventstoday = $(data).find('events-today').text();
164 if(eventstoday == 0) { $('#events-update').removeClass('notif-events-today') } else { $('#events-update').addClass('notif-events-today') }
166 var birthdays = $(data).find('birthdays').text();
167 if(birthdays == 0) {birthdays = ''; $('#birthdays-update').removeClass('show') } else { $('#birthdays-update').addClass('show') }
168 $('#birthdays-update').html(birthdays);
170 var birthdaystoday = $(data).find('birthdays-today').text();
171 if(birthdaystoday == 0) { $('#birthdays-update').removeClass('notif-birthdays-today') } else { $('#birthdays-update').addClass('notif-birthdays-today') }
174 var eNotif = $(data).find('notif')
176 if (eNotif.children("note").length==0){
177 $("#nav-notifications-menu").html(notifications_empty);
179 nnm = $("#nav-notifications-menu");
180 nnm.html(notifications_all + notifications_mark);
181 //nnm.attr('popup','true');
182 eNotif.children("note").each(function(){
184 text = e.text().format("<span class='contactname'>"+e.attr('name')+"</span>");
185 html = notifications_tpl.format(e.attr('href'),e.attr('photo'), text, e.attr('date'), e.attr('seen'));
189 $("img[data-src]", nnm).each(function(i, el){
190 // Add src attribute for images with a data-src attribute
191 // However, don't bother if the data-src attribute is empty, because
192 // an empty "src" tag for an image will cause some browsers
193 // to prefetch the root page of the Friendica hub, which will
194 // unnecessarily load an entire profile/ or network/ page
195 if($(el).data("src") != '') $(el).attr('src', $(el).data("src"));
199 notif = eNotif.attr('count');
201 $("#nav-notifications-linkmenu").addClass("on");
203 $("#nav-notifications-linkmenu").removeClass("on");
205 if(notif == 0) { notif = ''; $('#notify-update').removeClass('show') } else { $('#notify-update').addClass('show') }
206 $('#notify-update').html(notif);
208 var eSysmsg = $(data).find('sysmsgs');
209 eSysmsg.children("notice").each(function(){
210 text = $(this).text();
211 $.jGrowl(text, { sticky: true, theme: 'notice' });
213 eSysmsg.children("info").each(function(){
214 text = $(this).text();
215 $.jGrowl(text, { sticky: false, theme: 'info', life: 10000 });
221 // Allow folks to stop the ajax page updates with the pause/break key
222 $(document).keydown(function(event) {
223 if(event.keyCode == '8') {
224 var target = event.target || event.srcElement;
225 if (!/input|textarea/i.test(target.nodeName)) {
229 if(event.keyCode == '19' || (event.ctrlKey && event.which == '32')) {
230 event.preventDefault();
231 if(stopped == false) {
236 $('#pause').html('<img src="images/pause.gif" alt="pause" style="border: 1px solid black;" />');
250 function NavUpdate() {
253 var pingCmd = 'ping' + ((localUser != 0) ? '?f=&uid=' + localUser : '');
254 $.get(pingCmd,function(data) {
255 $(data).find('result').each(function() {
256 // send nav-update event
257 $('nav').trigger('nav-update', this);
262 if($('#live-network').length) { src = 'network'; liveUpdate(); }
263 if($('#live-profile').length) { src = 'profile'; liveUpdate(); }
264 if($('#live-community').length) { src = 'community'; liveUpdate(); }
265 if($('#live-notes').length) { src = 'notes'; liveUpdate(); }
266 if($('#live-display').length) { src = 'display'; liveUpdate(); }
267 /* if($('#live-display').length) {
270 window.location.href=window.location.href
273 if($('#live-photos').length) {
276 window.location.href=window.location.href
286 timer = setTimeout(NavUpdate,updateInterval);
289 function liveUpdate() {
290 if((src == null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; }
291 if(($('.comment-edit-text-full').length) || (in_progress)) {
293 clearTimeout(livetime);
295 livetime = setTimeout(liveUpdate, 10000);
301 prev = 'live-' + src;
304 var udargs = ((netargs.length) ? '/' + netargs : '');
305 var update_url = 'update_' + src + udargs + '&p=' + profile_uid + '&page=' + profile_page + '&msie=' + ((msie) ? 1 : 0);
307 $.get(update_url,function(data) {
309 // $('.collapsed-comments',data).each(function() {
310 // var ident = $(this).attr('id');
311 // var is_hidden = $('#' + ident).is(':hidden');
312 // if($('#' + ident).length) {
313 // $('#' + ident).replaceWith($(this));
315 // $('#' + ident).hide();
320 $('.toplevel_item',data).each(function() {
321 var ident = $(this).attr('id');
323 if($('#' + ident).length == 0 && profile_page == 1) {
324 $('img',this).each(function() {
325 $(this).attr('src',$(this).attr('dst'));
327 $('#' + prev).after($(this));
330 // Find out if the hidden comments are open, so we can keep it that way
331 // if a new comment has been posted
332 var id = $('.hide-comments-total', this).attr('id');
333 if(typeof id != 'undefined') {
334 id = id.split('-')[3];
335 var commentsOpen = $("#collapsed-comments-" + id).is(":visible");
338 $('img',this).each(function() {
339 $(this).attr('src',$(this).attr('dst'));
341 //vScroll = $(document).scrollTop();
342 $('html').height($('html').height());
343 $('#' + ident).replaceWith($(this));
345 if(typeof id != 'undefined') {
346 if(commentsOpen) showHideComments(id);
348 $('html').height('auto');
349 //$(document).scrollTop(vScroll);
354 // reset vars for inserting individual items
356 /* prev = 'live-' + src;
358 $('.wall-item-outside-wrapper',data).each(function() {
359 var ident = $(this).attr('id');
361 if($('#' + ident).length == 0 && prev != 'live-' + src) {
362 $('img',this).each(function() {
363 $(this).attr('src',$(this).attr('dst'));
365 $('#' + prev).after($(this));
368 $('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago'));
369 if($('#' + ident + ' ' + '.comment-edit-text-empty').length)
370 $('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
371 $('#' + ident + ' ' + '.hide-comments-total').replaceWith($(this).find('.hide-comments-total'));
372 $('#' + ident + ' ' + '.wall-item-like').replaceWith($(this).find('.wall-item-like'));
373 $('#' + ident + ' ' + '.wall-item-dislike').replaceWith($(this).find('.wall-item-dislike'));
374 $('#' + ident + ' ' + '.my-comment-photo').each(function() {
375 $(this).attr('src',$(this).attr('dst'));
381 $('.like-rotator').hide();
384 $('body').css('cursor', 'auto');
386 /* autocomplete @nicknames */
387 $(".comment-edit-form textarea").contact_autocomplete(baseurl+"/acl");
389 // setup videos, since VideoJS won't take care of any loaded via AJAX
390 if(typeof videojs != 'undefined') videojs.autoSetup();
394 function imgbright(node) {
395 $(node).removeClass("drophide").addClass("drop");
398 function imgdull(node) {
399 $(node).removeClass("drop").addClass("drophide");
402 // Since our ajax calls are asynchronous, we will give a few
403 // seconds for the first ajax call (setting like/dislike), then
404 // run the updater to pick up any changes and display on the page.
405 // The updater will turn any rotators off when it's done.
406 // This function will have returned long before any of these
407 // events have completed and therefore there won't be any
408 // visible feedback that anything changed without all this
409 // trickery. This still could cause confusion if the "like" ajax call
410 // is delayed and NavUpdate runs before it completes.
412 function dolike(ident,verb) {
414 $('#like-rotator-' + ident.toString()).show();
415 $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate );
419 function dosubthread(ident) {
421 $('#like-rotator-' + ident.toString()).show();
422 $.get('subthread/' + ident.toString(), NavUpdate );
427 function dostar(ident) {
428 ident = ident.toString();
429 $('#like-rotator-' + ident).show();
430 $.get('starred/' + ident, function(data) {
431 if(data.match(/1/)) {
432 $('#starred-' + ident).addClass('starred');
433 $('#starred-' + ident).removeClass('unstarred');
434 $('#star-' + ident).addClass('hidden');
435 $('#unstar-' + ident).removeClass('hidden');
438 $('#starred-' + ident).addClass('unstarred');
439 $('#starred-' + ident).removeClass('starred');
440 $('#star-' + ident).removeClass('hidden');
441 $('#unstar-' + ident).addClass('hidden');
443 $('#like-rotator-' + ident).hide();
447 function getPosition(e) {
448 var cursor = {x:0, y:0};
449 if ( e.pageX || e.pageY ) {
454 if( e.clientX || e.clientY ) {
455 cursor.x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
456 cursor.y = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
468 var lockvisible = false;
470 function lockview(event,id) {
471 event = event || window.event;
472 cursor = getPosition(event);
478 $.get('lockview/' + id, function(data) {
479 $('#panel').html(data);
480 $('#panel').css({ 'left': cursor.x + 5 , 'top': cursor.y + 5});
486 function lockviewhide() {
491 function post_comment(id) {
494 $('body').css('cursor', 'wait');
495 $("#comment-preview-inp-" + id).val("0");
498 $("#comment-edit-form-" + id).serialize(),
501 $("#comment-edit-wrapper-" + id).hide();
502 $("#comment-edit-text-" + id).val('');
503 var tarea = document.getElementById("comment-edit-text-" + id);
505 commentClose(tarea,id);
506 if(timer) clearTimeout(timer);
507 timer = setTimeout(NavUpdate,10);
510 window.location.href=data.reload;
519 function preview_comment(id) {
520 $("#comment-preview-inp-" + id).val("1");
521 $("#comment-edit-preview-" + id).show();
524 $("#comment-edit-form-" + id).serialize(),
528 $("#comment-edit-preview-" + id).html(data.preview);
529 $("#comment-edit-preview-" + id + " a").click(function() { return false; });
539 function showHideComments(id) {
540 if( $("#collapsed-comments-" + id).is(":visible")) {
541 $("#collapsed-comments-" + id).hide();
542 $("#hide-comments-" + id).html(window.showMore);
545 $("#collapsed-comments-" + id).show();
546 $("#hide-comments-" + id).html(window.showFewer);
552 function preview_post() {
553 $("#jot-preview").val("1");
554 $("#jot-preview-content").show();
555 tinyMCE.triggerSave();
558 $("#profile-jot-form").serialize(),
561 $("#jot-preview-content").html(data.preview);
562 $("#jot-preview-content" + " a").click(function() { return false; });
567 $("#jot-preview").val("0");
573 // unpause auto reloads if they are currently stopped
576 $('#pause').html('');
581 // Converts the binary representation of data to hex
584 // discuss at: http://phpjs.org/functions/bin2hex
585 // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
586 // + bugfixed by: Onno Marsman
587 // + bugfixed by: Linuxworld
588 // * example 1: bin2hex('Kev');
589 // * returns 1: '4b6576'
590 // * example 2: bin2hex(String.fromCharCode(0x00));
592 var v,i, f = 0, a = [];
596 for (i = 0; i<f; i++) {
597 a[i] = s.charCodeAt(i).toString(16).replace(/^([\da-f])$/,"0$1");
603 function groupChangeMember(gid, cid, sec_token) {
604 $('body .fakelink').css('cursor', 'wait');
605 $.get('group/' + gid + '/' + cid + "?t=" + sec_token, function(data) {
606 $('#group-update-wrapper').html(data);
607 $('body .fakelink').css('cursor', 'auto');
611 function profChangeMember(gid,cid) {
612 $('body .fakelink').css('cursor', 'wait');
613 $.get('profperm/' + gid + '/' + cid, function(data) {
614 $('#prof-update-wrapper').html(data);
615 $('body .fakelink').css('cursor', 'auto');
619 function contactgroupChangeMember(gid,cid) {
620 $('body').css('cursor', 'wait');
621 $.get('contactgroup/' + gid + '/' + cid, function(data) {
622 $('body').css('cursor', 'auto');
627 function checkboxhighlight(box) {
628 if($(box).is(':checked')) {
629 $(box).addClass('checkeditem');
632 $(box).removeClass('checkeditem');
636 function notifyMarkAll() {
637 $.get('notify/mark/all', function(data) {
638 if(timer) clearTimeout(timer);
639 timer = setTimeout(NavUpdate,1000);
644 // code from http://www.tinymce.com/wiki.php/How-to_implement_a_custom_file_browser
645 function fcFileBrowser (field_name, url, type, win) {
646 /* TODO: If you work with sessions in PHP and your client doesn't accept cookies you might need to carry
647 the session name and session ID in the request string (can look like this: "?PHPSESSID=88p0n70s9dsknra96qhuk6etm5").
648 These lines of code extract the necessary parameters and add them back to the filebrowser URL again. */
651 var cmsURL = baseurl+"/fbrowser/"+type+"/";
653 tinyMCE.activeEditor.windowManager.open({
655 title : 'File Browser',
656 width : 420, // Your dimensions may differ - toy around with them!
659 inline : "yes", // This parameter only has an effect if you use the inlinepopups plugin!
660 close_previous : "no"
668 function setupFieldRichtext(){
671 mode : "specific_textareas",
672 editor_selector: "fieldRichtext",
673 plugins : "bbcode,paste, inlinepopups",
674 theme_advanced_buttons1 : "bold,italic,underline,undo,redo,link,unlink,image,forecolor,formatselect,code",
675 theme_advanced_buttons2 : "",
676 theme_advanced_buttons3 : "",
677 theme_advanced_toolbar_location : "top",
678 theme_advanced_toolbar_align : "center",
679 theme_advanced_blockformats : "blockquote,code",
680 paste_text_sticky : true,
681 entity_encoding : "raw",
682 add_unload_trigger : false,
683 remove_linebreaks : false,
684 //force_p_newlines : false,
685 //force_br_newlines : true,
686 forced_root_block : 'div',
688 content_css: baseurl+"/view/custom_tinymce.css",
689 theme_advanced_path : false,
690 file_browser_callback : "fcFileBrowser",
696 * sprintf in javascript
697 * "{0} and {1}".format('zero','uno');
699 String.prototype.format = function() {
700 var formatted = this;
701 for (var i = 0; i < arguments.length; i++) {
702 var regexp = new RegExp('\\{'+i+'\\}', 'gi');
703 formatted = formatted.replace(regexp, arguments[i]);
708 Array.prototype.remove = function(item) {
709 to=undefined; from=this.indexOf(item);
710 var rest = this.slice((to || from) + 1 || this.length);
711 this.length = from < 0 ? this.length + from : from;
712 return this.push.apply(this, rest);
715 function previewTheme(elm) {
716 theme = $(elm).val();
717 $.getJSON('pretheme?f=&theme=' + theme,function(data) {
718 $('#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>');