1 function resizeIframe(obj) {
3 obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
6 function openClose(theID) {
7 if(document.getElementById(theID).style.display == "block") {
8 document.getElementById(theID).style.display = "none"
11 document.getElementById(theID).style.display = "block"
15 function openMenu(theID) {
16 document.getElementById(theID).style.display = "block"
19 function closeMenu(theID) {
20 document.getElementById(theID).style.display = "none"
28 var force_update = false;
30 var totStopped = false;
34 var in_progress = false;
35 var langSelect = false;
36 var commentBusy = false;
37 var last_popup_menu = null;
38 var last_popup_button = null;
41 $.ajaxSetup({cache: false});
43 /* setup tooltips *//*
44 $("a,.tt").each(function(){
47 if (e.hasClass("tttop")) pos="top";
48 if (e.hasClass("ttbottom")) pos="bottom";
49 if (e.hasClass("ttleft")) pos="left";
50 if (e.hasClass("ttright")) pos="right";
51 e.tipTip({defaultPosition: pos, edgeOffset: 8});
56 /* setup onoff widgets */
57 $(".onoff input").each(function(){
59 id = $(this).attr("id");
60 $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
63 $(".onoff > a").click(function(event){
64 event.preventDefault();
65 var input = $(this).siblings("input");
66 var val = 1-input.val();
67 var id = input.attr("id");
68 $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
69 $("#"+id+"_onoff ."+ (val==1?"on":"off")).removeClass("hidden");
74 /* setup field_richtext */
78 function close_last_popup_menu() {
80 last_popup_menu.hide();
81 last_popup_button.removeClass("selected");
82 last_popup_menu = null;
83 last_popup_button = null;
86 $('a[rel^=#]').click(function(e){
88 var parent = $(this).parent();
89 var isSelected = (last_popup_button && parent.attr('id') == last_popup_button.attr('id'));
90 close_last_popup_menu();
91 if(isSelected) return false;
92 menu = $( $(this).attr('rel') );
95 if (menu.attr('popup')=="false") return false;
96 parent.toggleClass("selected");
98 if (menu.css("display") == "none") {
99 last_popup_menu = null;
100 last_popup_button = null;
102 last_popup_menu = menu;
103 last_popup_button = parent;
107 $('html').click(function() {
108 close_last_popup_menu();
112 $("a.popupbox").colorbox({
114 'transition' : 'elastic'
118 /* notifications template */
119 var notifications_tpl= unescape($("#nav-notifications-template[rel=template]").html());
120 var notifications_all = unescape($('<div>').append( $("#nav-notifications-see-all").clone() ).html()); //outerHtml hack
121 var notifications_mark = unescape($('<div>').append( $("#nav-notifications-mark-all").clone() ).html()); //outerHtml hack
122 var notifications_empty = unescape($("#nav-notifications-menu").html());
124 /* nav update event */
125 $('nav').bind('nav-update', function(e,data){;
126 var invalid = $(data).find('invalid').text();
127 if(invalid == 1) { window.location.href=window.location.href }
129 var net = $(data).find('net').text();
130 if(net == 0) { net = ''; $('#net-update').removeClass('show') } else { $('#net-update').addClass('show') }
131 $('#net-update').html(net);
133 var home = $(data).find('home').text();
134 if(home == 0) { home = ''; $('#home-update').removeClass('show') } else { $('#home-update').addClass('show') }
135 $('#home-update').html(home);
137 var intro = $(data).find('intro').text();
138 if(intro == 0) { intro = ''; $('#intro-update').removeClass('show') } else { $('#intro-update').addClass('show') }
139 $('#intro-update').html(intro);
141 var mail = $(data).find('mail').text();
142 if(mail == 0) { mail = ''; $('#mail-update').removeClass('show') } else { $('#mail-update').addClass('show') }
143 $('#mail-update').html(mail);
145 var intro = $(data).find('intro').text();
146 if(intro == 0) { intro = ''; $('#intro-update-li').removeClass('show') } else { $('#intro-update-li').addClass('show') }
147 $('#intro-update-li').html(intro);
149 var mail = $(data).find('mail').text();
150 if(mail == 0) { mail = ''; $('#mail-update-li').removeClass('show') } else { $('#mail-update-li').addClass('show') }
151 $('#mail-update-li').html(mail);
154 var allevents = $(data).find('all-events').text();
155 if(allevents == 0) { allevents = ''; $('#allevents-update').removeClass('show') } else { $('#allevents-update').addClass('show') }
156 $('#allevents-update').html(allevents);
158 var alleventstoday = $(data).find('all-events-today').text();
159 if(alleventstoday == 0) { $('#allevents-update').removeClass('notif-allevents-today') } else { $('#allevents-update').addClass('notif-allevents-today') }
161 var events = $(data).find('events').text();
162 if(events == 0) { events = ''; $('#events-update').removeClass('show') } else { $('#events-update').addClass('show') }
163 $('#events-update').html(events);
165 var eventstoday = $(data).find('events-today').text();
166 if(eventstoday == 0) { $('#events-update').removeClass('notif-events-today') } else { $('#events-update').addClass('notif-events-today') }
168 var birthdays = $(data).find('birthdays').text();
169 if(birthdays == 0) {birthdays = ''; $('#birthdays-update').removeClass('show') } else { $('#birthdays-update').addClass('show') }
170 $('#birthdays-update').html(birthdays);
172 var birthdaystoday = $(data).find('birthdays-today').text();
173 if(birthdaystoday == 0) { $('#birthdays-update').removeClass('notif-birthdays-today') } else { $('#birthdays-update').addClass('notif-birthdays-today') }
176 var eNotif = $(data).find('notif')
178 if (eNotif.children("note").length==0){
179 $("#nav-notifications-menu").html(notifications_empty);
181 nnm = $("#nav-notifications-menu");
182 nnm.html(notifications_all + notifications_mark);
183 //nnm.attr('popup','true');
184 eNotif.children("note").each(function(){
186 text = e.text().format("<span class='contactname'>"+e.attr('name')+"</span>");
187 html = notifications_tpl.format(e.attr('href'),e.attr('photo'), text, e.attr('date'), e.attr('seen'));
190 if(e.text().search('→') == 0) {
191 var notification = new Notification(document.title, {
192 body: e.text().replace('→ ',''),
193 icon: e.attr('photo')
196 // TODO (yet unsupported by most browsers):
197 // Implement notification.onclick()
203 $("img[data-src]", nnm).each(function(i, el){
204 // Add src attribute for images with a data-src attribute
205 // However, don't bother if the data-src attribute is empty, because
206 // an empty "src" tag for an image will cause some browsers
207 // to prefetch the root page of the Friendica hub, which will
208 // unnecessarily load an entire profile/ or network/ page
209 if($(el).data("src") != '') $(el).attr('src', $(el).data("src"));
213 notif = eNotif.attr('count');
215 $("#nav-notifications-linkmenu").addClass("on");
217 $("#nav-notifications-linkmenu").removeClass("on");
219 if(notif == 0) { notif = ''; $('#notify-update').removeClass('show') } else { $('#notify-update').addClass('show') }
220 $('#notify-update').html(notif);
222 var eSysmsg = $(data).find('sysmsgs');
223 eSysmsg.children("notice").each(function(){
224 text = $(this).text();
225 $.jGrowl(text, { sticky: true, theme: 'notice' });
227 eSysmsg.children("info").each(function(){
228 text = $(this).text();
229 $.jGrowl(text, { sticky: false, theme: 'info', life: 5000 });
235 // Allow folks to stop the ajax page updates with the pause/break key
236 $(document).keydown(function(event) {
237 if(event.keyCode == '8') {
238 var target = event.target || event.srcElement;
239 if (!/input|textarea/i.test(target.nodeName)) {
243 if(event.keyCode == '19' || (event.ctrlKey && event.which == '32')) {
244 event.preventDefault();
245 if(stopped == false) {
250 $('#pause').html('<img src="images/pause.gif" alt="pause" style="border: 1px solid black;" />');
264 function NavUpdate() {
267 var pingCmd = 'ping' + ((localUser != 0) ? '?f=&uid=' + localUser : '');
268 $.get(pingCmd,function(data) {
269 $(data).find('result').each(function() {
270 // send nav-update event
271 $('nav').trigger('nav-update', this);
276 if($('#live-network').length) { src = 'network'; liveUpdate(); }
277 if($('#live-profile').length) { src = 'profile'; liveUpdate(); }
278 if($('#live-community').length) { src = 'community'; liveUpdate(); }
279 if($('#live-notes').length) { src = 'notes'; liveUpdate(); }
280 if($('#live-display').length) { src = 'display'; liveUpdate(); }
281 /* if($('#live-display').length) {
284 window.location.href=window.location.href
287 if($('#live-photos').length) {
290 window.location.href=window.location.href
300 timer = setTimeout(NavUpdate,updateInterval);
303 function liveUpdate() {
304 if((src == null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; }
305 if(($('.comment-edit-text-full').length) || (in_progress)) {
307 clearTimeout(livetime);
309 livetime = setTimeout(liveUpdate, 5000);
315 prev = 'live-' + src;
319 if ($(document).scrollTop() == 0)
322 var udargs = ((netargs.length) ? '/' + netargs : '');
323 var update_url = 'update_' + src + udargs + '&p=' + profile_uid + '&page=' + profile_page + '&force=' + ((force_update) ? 1 : 0);
325 $.get(update_url,function(data) {
327 force_update = false;
328 // $('.collapsed-comments',data).each(function() {
329 // var ident = $(this).attr('id');
330 // var is_hidden = $('#' + ident).is(':hidden');
331 // if($('#' + ident).length) {
332 // $('#' + ident).replaceWith($(this));
334 // $('#' + ident).hide();
339 $('.toplevel_item',data).each(function() {
340 var ident = $(this).attr('id');
342 if($('#' + ident).length == 0 && profile_page == 1) {
343 $('img',this).each(function() {
344 $(this).attr('src',$(this).attr('dst'));
346 $('#' + prev).after($(this));
349 // Find out if the hidden comments are open, so we can keep it that way
350 // if a new comment has been posted
351 var id = $('.hide-comments-total', this).attr('id');
352 if(typeof id != 'undefined') {
353 id = id.split('-')[3];
354 var commentsOpen = $("#collapsed-comments-" + id).is(":visible");
357 $('img',this).each(function() {
358 $(this).attr('src',$(this).attr('dst'));
360 //vScroll = $(document).scrollTop();
361 $('html').height($('html').height());
362 $('#' + ident).replaceWith($(this));
364 if(typeof id != 'undefined') {
365 if(commentsOpen) showHideComments(id);
367 $('html').height('auto');
368 //$(document).scrollTop(vScroll);
373 // reset vars for inserting individual items
375 /* prev = 'live-' + src;
377 $('.wall-item-outside-wrapper',data).each(function() {
378 var ident = $(this).attr('id');
380 if($('#' + ident).length == 0 && prev != 'live-' + src) {
381 $('img',this).each(function() {
382 $(this).attr('src',$(this).attr('dst'));
384 $('#' + prev).after($(this));
387 $('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago'));
388 if($('#' + ident + ' ' + '.comment-edit-text-empty').length)
389 $('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
390 $('#' + ident + ' ' + '.hide-comments-total').replaceWith($(this).find('.hide-comments-total'));
391 $('#' + ident + ' ' + '.wall-item-like').replaceWith($(this).find('.wall-item-like'));
392 $('#' + ident + ' ' + '.wall-item-dislike').replaceWith($(this).find('.wall-item-dislike'));
393 $('#' + ident + ' ' + '.my-comment-photo').each(function() {
394 $(this).attr('src',$(this).attr('dst'));
400 $('.like-rotator').hide();
403 $('body').css('cursor', 'auto');
405 /* autocomplete @nicknames */
406 $(".comment-edit-form textarea").contact_autocomplete(baseurl+"/acl");
408 // setup videos, since VideoJS won't take care of any loaded via AJAX
409 if(typeof videojs != 'undefined') videojs.autoSetup();
413 function imgbright(node) {
414 $(node).removeClass("drophide").addClass("drop");
417 function imgdull(node) {
418 $(node).removeClass("drop").addClass("drophide");
421 // Since our ajax calls are asynchronous, we will give a few
422 // seconds for the first ajax call (setting like/dislike), then
423 // run the updater to pick up any changes and display on the page.
424 // The updater will turn any rotators off when it's done.
425 // This function will have returned long before any of these
426 // events have completed and therefore there won't be any
427 // visible feedback that anything changed without all this
428 // trickery. This still could cause confusion if the "like" ajax call
429 // is delayed and NavUpdate runs before it completes.
431 function dolike(ident,verb) {
433 $('#like-rotator-' + ident.toString()).show();
434 $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate );
439 function dosubthread(ident) {
441 $('#like-rotator-' + ident.toString()).show();
442 $.get('subthread/' + ident.toString(), NavUpdate );
447 function dostar(ident) {
448 ident = ident.toString();
449 $('#like-rotator-' + ident).show();
450 $.get('starred/' + ident, function(data) {
451 if(data.match(/1/)) {
452 $('#starred-' + ident).addClass('starred');
453 $('#starred-' + ident).removeClass('unstarred');
454 $('#star-' + ident).addClass('hidden');
455 $('#unstar-' + ident).removeClass('hidden');
458 $('#starred-' + ident).addClass('unstarred');
459 $('#starred-' + ident).removeClass('starred');
460 $('#star-' + ident).removeClass('hidden');
461 $('#unstar-' + ident).addClass('hidden');
463 $('#like-rotator-' + ident).hide();
467 function doignore(ident) {
468 ident = ident.toString();
469 $('#like-rotator-' + ident).show();
470 $.get('ignored/' + ident, function(data) {
471 if(data.match(/1/)) {
472 $('#ignored-' + ident).addClass('ignored');
473 $('#ignored-' + ident).removeClass('unignored');
474 $('#ignore-' + ident).addClass('hidden');
475 $('#unignore-' + ident).removeClass('hidden');
478 $('#ignored-' + ident).addClass('unignored');
479 $('#ignored-' + ident).removeClass('ignored');
480 $('#ignore-' + ident).removeClass('hidden');
481 $('#unignore-' + ident).addClass('hidden');
483 $('#like-rotator-' + ident).hide();
487 function getPosition(e) {
488 var cursor = {x:0, y:0};
489 if ( e.pageX || e.pageY ) {
494 if( e.clientX || e.clientY ) {
495 cursor.x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
496 cursor.y = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
508 var lockvisible = false;
510 function lockview(event,id) {
511 event = event || window.event;
512 cursor = getPosition(event);
518 $.get('lockview/' + id, function(data) {
519 $('#panel').html(data);
520 $('#panel').css({ 'left': cursor.x + 5 , 'top': cursor.y + 5});
526 function lockviewhide() {
531 function post_comment(id) {
534 $('body').css('cursor', 'wait');
535 $("#comment-preview-inp-" + id).val("0");
538 $("#comment-edit-form-" + id).serialize(),
541 $("#comment-edit-wrapper-" + id).hide();
542 $("#comment-edit-text-" + id).val('');
543 var tarea = document.getElementById("comment-edit-text-" + id);
545 commentClose(tarea,id);
546 if(timer) clearTimeout(timer);
547 timer = setTimeout(NavUpdate,10);
551 window.location.href=data.reload;
560 function preview_comment(id) {
561 $("#comment-preview-inp-" + id).val("1");
562 $("#comment-edit-preview-" + id).show();
565 $("#comment-edit-form-" + id).serialize(),
569 $("#comment-edit-preview-" + id).html(data.preview);
570 $("#comment-edit-preview-" + id + " a").click(function() { return false; });
580 function showHideComments(id) {
581 if( $("#collapsed-comments-" + id).is(":visible")) {
582 $("#collapsed-comments-" + id).hide();
583 $("#hide-comments-" + id).html(window.showMore);
586 $("#collapsed-comments-" + id).show();
587 $("#hide-comments-" + id).html(window.showFewer);
593 function preview_post() {
594 $("#jot-preview").val("1");
595 $("#jot-preview-content").show();
596 tinyMCE.triggerSave();
599 $("#profile-jot-form").serialize(),
602 $("#jot-preview-content").html(data.preview);
603 $("#jot-preview-content" + " a").click(function() { return false; });
608 $("#jot-preview").val("0");
614 // unpause auto reloads if they are currently stopped
617 $('#pause').html('');
622 // Converts the binary representation of data to hex
625 // discuss at: http://phpjs.org/functions/bin2hex
626 // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
627 // + bugfixed by: Onno Marsman
628 // + bugfixed by: Linuxworld
629 // * example 1: bin2hex('Kev');
630 // * returns 1: '4b6576'
631 // * example 2: bin2hex(String.fromCharCode(0x00));
633 var v,i, f = 0, a = [];
637 for (i = 0; i<f; i++) {
638 a[i] = s.charCodeAt(i).toString(16).replace(/^([\da-f])$/,"0$1");
644 function groupChangeMember(gid, cid, sec_token) {
645 $('body .fakelink').css('cursor', 'wait');
646 $.get('group/' + gid + '/' + cid + "?t=" + sec_token, function(data) {
647 $('#group-update-wrapper').html(data);
648 $('body .fakelink').css('cursor', 'auto');
652 function profChangeMember(gid,cid) {
653 $('body .fakelink').css('cursor', 'wait');
654 $.get('profperm/' + gid + '/' + cid, function(data) {
655 $('#prof-update-wrapper').html(data);
656 $('body .fakelink').css('cursor', 'auto');
660 function contactgroupChangeMember(gid,cid) {
661 $('body').css('cursor', 'wait');
662 $.get('contactgroup/' + gid + '/' + cid, function(data) {
663 $('body').css('cursor', 'auto');
668 function checkboxhighlight(box) {
669 if($(box).is(':checked')) {
670 $(box).addClass('checkeditem');
673 $(box).removeClass('checkeditem');
677 function notifyMarkAll() {
678 $.get('notify/mark/all', function(data) {
679 if(timer) clearTimeout(timer);
680 timer = setTimeout(NavUpdate,1000);
686 // code from http://www.tinymce.com/wiki.php/How-to_implement_a_custom_file_browser
687 function fcFileBrowser (field_name, url, type, win) {
688 /* TODO: If you work with sessions in PHP and your client doesn't accept cookies you might need to carry
689 the session name and session ID in the request string (can look like this: "?PHPSESSID=88p0n70s9dsknra96qhuk6etm5").
690 These lines of code extract the necessary parameters and add them back to the filebrowser URL again. */
693 var cmsURL = baseurl+"/fbrowser/"+type+"/";
695 tinyMCE.activeEditor.windowManager.open({
697 title : 'File Browser',
698 width : 420, // Your dimensions may differ - toy around with them!
701 inline : "yes", // This parameter only has an effect if you use the inlinepopups plugin!
702 close_previous : "no"
710 function setupFieldRichtext(){
713 mode : "specific_textareas",
714 editor_selector: "fieldRichtext",
715 plugins : "bbcode,paste, inlinepopups",
716 theme_advanced_buttons1 : "bold,italic,underline,undo,redo,link,unlink,image,forecolor,formatselect,code",
717 theme_advanced_buttons2 : "",
718 theme_advanced_buttons3 : "",
719 theme_advanced_toolbar_location : "top",
720 theme_advanced_toolbar_align : "center",
721 theme_advanced_blockformats : "blockquote,code",
722 theme_advanced_resizing : true,
723 paste_text_sticky : true,
724 entity_encoding : "raw",
725 add_unload_trigger : false,
726 remove_linebreaks : false,
727 //force_p_newlines : false,
728 //force_br_newlines : true,
729 forced_root_block : 'div',
731 content_css: baseurl+"/view/custom_tinymce.css",
732 theme_advanced_path : false,
733 file_browser_callback : "fcFileBrowser",
739 * sprintf in javascript
740 * "{0} and {1}".format('zero','uno');
742 String.prototype.format = function() {
743 var formatted = this;
744 for (var i = 0; i < arguments.length; i++) {
745 var regexp = new RegExp('\\{'+i+'\\}', 'gi');
746 formatted = formatted.replace(regexp, arguments[i]);
751 Array.prototype.remove = function(item) {
752 to=undefined; from=this.indexOf(item);
753 var rest = this.slice((to || from) + 1 || this.length);
754 this.length = from < 0 ? this.length + from : from;
755 return this.push.apply(this, rest);
758 function previewTheme(elm) {
759 theme = $(elm).val();
760 $.getJSON('pretheme?f=&theme=' + theme,function(data) {
761 $('#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>');