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');
185 var notification_lastitem = parseInt(localStorage.getItem("notification-lastitem"));
186 var notification_id = 0;
187 eNotif.children("note").each(function(){
189 var text = e.text().format("<span class='contactname'>"+e.attr('name')+"</span>");
190 var seenclass = (e.attr('seen')==1)?"notify-seen":"notify-unseen";
191 var html = notifications_tpl.format(e.attr('href'),
192 e.attr('photo'), // {0}
194 e.attr('date'), // {2}
196 new Date(e.attr('timestamp')*1000) // {4}
200 $(eNotif.children("note").get().reverse()).each(function(){
202 notification_id = parseInt(e.attr('timestamp'));
203 if (notification_lastitem!== null && notification_id > notification_lastitem) {
204 if (getNotificationPermission()==="granted") {
205 var notification = new Notification(document.title, {
206 body: e.text().replace('→ ','').format(e.attr('name')),
207 icon: e.attr('photo'),
209 notification['url'] = e.attr('href');
210 notification.addEventListener("click", function(ev){
211 window.location = ev.target.url;
217 notification_lastitem = notification_id;
218 localStorage.setItem("notification-lastitem", notification_lastitem)
220 $("img[data-src]", nnm).each(function(i, el){
221 // Add src attribute for images with a data-src attribute
222 // However, don't bother if the data-src attribute is empty, because
223 // an empty "src" tag for an image will cause some browsers
224 // to prefetch the root page of the Friendica hub, which will
225 // unnecessarily load an entire profile/ or network/ page
226 if($(el).data("src") != '') $(el).attr('src', $(el).data("src"));
230 notif = eNotif.attr('count');
232 $("#nav-notifications-linkmenu").addClass("on");
234 $("#nav-notifications-linkmenu").removeClass("on");
236 if(notif == 0) { notif = ''; $('#notify-update').removeClass('show') } else { $('#notify-update').addClass('show') }
237 $('#notify-update').html(notif);
239 var eSysmsg = $(data).find('sysmsgs');
240 eSysmsg.children("notice").each(function(){
241 text = $(this).text();
242 $.jGrowl(text, { sticky: true, theme: 'notice' });
244 eSysmsg.children("info").each(function(){
245 text = $(this).text();
246 $.jGrowl(text, { sticky: false, theme: 'info', life: 5000 });
252 // Allow folks to stop the ajax page updates with the pause/break key
253 $(document).keydown(function(event) {
254 if(event.keyCode == '8') {
255 var target = event.target || event.srcElement;
256 if (!/input|textarea/i.test(target.nodeName)) {
260 if(event.keyCode == '19' || (event.ctrlKey && event.which == '32')) {
261 event.preventDefault();
262 if(stopped == false) {
267 $('#pause').html('<img src="images/pause.gif" alt="pause" style="border: 1px solid black;" />');
281 function NavUpdate() {
284 var pingCmd = 'ping' + ((localUser != 0) ? '?f=&uid=' + localUser : '');
285 $.get(pingCmd,function(data) {
286 $(data).find('result').each(function() {
287 // send nav-update event
288 $('nav').trigger('nav-update', this);
293 if($('#live-network').length) { src = 'network'; liveUpdate(); }
294 if($('#live-profile').length) { src = 'profile'; liveUpdate(); }
295 if($('#live-community').length) { src = 'community'; liveUpdate(); }
296 if($('#live-notes').length) { src = 'notes'; liveUpdate(); }
297 if($('#live-display').length) { src = 'display'; liveUpdate(); }
298 /* if($('#live-display').length) {
301 window.location.href=window.location.href
304 if($('#live-photos').length) {
307 window.location.href=window.location.href
317 timer = setTimeout(NavUpdate,updateInterval);
320 function liveUpdate() {
321 if((src == null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; }
322 if(($('.comment-edit-text-full').length) || (in_progress)) {
324 clearTimeout(livetime);
326 livetime = setTimeout(liveUpdate, 5000);
332 prev = 'live-' + src;
336 if ($(document).scrollTop() == 0)
339 var udargs = ((netargs.length) ? '/' + netargs : '');
340 var update_url = 'update_' + src + udargs + '&p=' + profile_uid + '&page=' + profile_page + '&force=' + ((force_update) ? 1 : 0);
342 $.get(update_url,function(data) {
344 force_update = false;
345 // $('.collapsed-comments',data).each(function() {
346 // var ident = $(this).attr('id');
347 // var is_hidden = $('#' + ident).is(':hidden');
348 // if($('#' + ident).length) {
349 // $('#' + ident).replaceWith($(this));
351 // $('#' + ident).hide();
356 $('.toplevel_item',data).each(function() {
357 var ident = $(this).attr('id');
359 if($('#' + ident).length == 0 && profile_page == 1) {
360 $('img',this).each(function() {
361 $(this).attr('src',$(this).attr('dst'));
363 $('#' + prev).after($(this));
366 // Find out if the hidden comments are open, so we can keep it that way
367 // if a new comment has been posted
368 var id = $('.hide-comments-total', this).attr('id');
369 if(typeof id != 'undefined') {
370 id = id.split('-')[3];
371 var commentsOpen = $("#collapsed-comments-" + id).is(":visible");
374 $('img',this).each(function() {
375 $(this).attr('src',$(this).attr('dst'));
377 //vScroll = $(document).scrollTop();
378 $('html').height($('html').height());
379 $('#' + ident).replaceWith($(this));
381 if(typeof id != 'undefined') {
382 if(commentsOpen) showHideComments(id);
384 $('html').height('auto');
385 //$(document).scrollTop(vScroll);
390 // reset vars for inserting individual items
392 /* prev = 'live-' + src;
394 $('.wall-item-outside-wrapper',data).each(function() {
395 var ident = $(this).attr('id');
397 if($('#' + ident).length == 0 && prev != 'live-' + src) {
398 $('img',this).each(function() {
399 $(this).attr('src',$(this).attr('dst'));
401 $('#' + prev).after($(this));
404 $('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago'));
405 if($('#' + ident + ' ' + '.comment-edit-text-empty').length)
406 $('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
407 $('#' + ident + ' ' + '.hide-comments-total').replaceWith($(this).find('.hide-comments-total'));
408 $('#' + ident + ' ' + '.wall-item-like').replaceWith($(this).find('.wall-item-like'));
409 $('#' + ident + ' ' + '.wall-item-dislike').replaceWith($(this).find('.wall-item-dislike'));
410 $('#' + ident + ' ' + '.my-comment-photo').each(function() {
411 $(this).attr('src',$(this).attr('dst'));
417 $('.like-rotator').hide();
420 $('body').css('cursor', 'auto');
422 /* autocomplete @nicknames */
423 $(".comment-edit-form textarea").contact_autocomplete(baseurl+"/acl");
425 // setup videos, since VideoJS won't take care of any loaded via AJAX
426 if(typeof videojs != 'undefined') videojs.autoSetup();
430 function imgbright(node) {
431 $(node).removeClass("drophide").addClass("drop");
434 function imgdull(node) {
435 $(node).removeClass("drop").addClass("drophide");
438 // Since our ajax calls are asynchronous, we will give a few
439 // seconds for the first ajax call (setting like/dislike), then
440 // run the updater to pick up any changes and display on the page.
441 // The updater will turn any rotators off when it's done.
442 // This function will have returned long before any of these
443 // events have completed and therefore there won't be any
444 // visible feedback that anything changed without all this
445 // trickery. This still could cause confusion if the "like" ajax call
446 // is delayed and NavUpdate runs before it completes.
448 function dolike(ident,verb) {
450 $('#like-rotator-' + ident.toString()).show();
451 $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate );
456 function dosubthread(ident) {
458 $('#like-rotator-' + ident.toString()).show();
459 $.get('subthread/' + ident.toString(), NavUpdate );
464 function dostar(ident) {
465 ident = ident.toString();
466 $('#like-rotator-' + ident).show();
467 $.get('starred/' + ident, function(data) {
468 if(data.match(/1/)) {
469 $('#starred-' + ident).addClass('starred');
470 $('#starred-' + ident).removeClass('unstarred');
471 $('#star-' + ident).addClass('hidden');
472 $('#unstar-' + ident).removeClass('hidden');
475 $('#starred-' + ident).addClass('unstarred');
476 $('#starred-' + ident).removeClass('starred');
477 $('#star-' + ident).removeClass('hidden');
478 $('#unstar-' + ident).addClass('hidden');
480 $('#like-rotator-' + ident).hide();
484 function doignore(ident) {
485 ident = ident.toString();
486 $('#like-rotator-' + ident).show();
487 $.get('ignored/' + ident, function(data) {
488 if(data.match(/1/)) {
489 $('#ignored-' + ident).addClass('ignored');
490 $('#ignored-' + ident).removeClass('unignored');
491 $('#ignore-' + ident).addClass('hidden');
492 $('#unignore-' + ident).removeClass('hidden');
495 $('#ignored-' + ident).addClass('unignored');
496 $('#ignored-' + ident).removeClass('ignored');
497 $('#ignore-' + ident).removeClass('hidden');
498 $('#unignore-' + ident).addClass('hidden');
500 $('#like-rotator-' + ident).hide();
504 function getPosition(e) {
505 var cursor = {x:0, y:0};
506 if ( e.pageX || e.pageY ) {
511 if( e.clientX || e.clientY ) {
512 cursor.x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
513 cursor.y = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
525 var lockvisible = false;
527 function lockview(event,id) {
528 event = event || window.event;
529 cursor = getPosition(event);
535 $.get('lockview/' + id, function(data) {
536 $('#panel').html(data);
537 $('#panel').css({ 'left': cursor.x + 5 , 'top': cursor.y + 5});
543 function lockviewhide() {
548 function post_comment(id) {
551 $('body').css('cursor', 'wait');
552 $("#comment-preview-inp-" + id).val("0");
555 $("#comment-edit-form-" + id).serialize(),
558 $("#comment-edit-wrapper-" + id).hide();
559 $("#comment-edit-text-" + id).val('');
560 var tarea = document.getElementById("comment-edit-text-" + id);
562 commentClose(tarea,id);
563 if(timer) clearTimeout(timer);
564 timer = setTimeout(NavUpdate,10);
568 window.location.href=data.reload;
577 function preview_comment(id) {
578 $("#comment-preview-inp-" + id).val("1");
579 $("#comment-edit-preview-" + id).show();
582 $("#comment-edit-form-" + id).serialize(),
586 $("#comment-edit-preview-" + id).html(data.preview);
587 $("#comment-edit-preview-" + id + " a").click(function() { return false; });
597 function showHideComments(id) {
598 if( $("#collapsed-comments-" + id).is(":visible")) {
599 $("#collapsed-comments-" + id).hide();
600 $("#hide-comments-" + id).html(window.showMore);
603 $("#collapsed-comments-" + id).show();
604 $("#hide-comments-" + id).html(window.showFewer);
610 function preview_post() {
611 $("#jot-preview").val("1");
612 $("#jot-preview-content").show();
613 tinyMCE.triggerSave();
616 $("#profile-jot-form").serialize(),
619 $("#jot-preview-content").html(data.preview);
620 $("#jot-preview-content" + " a").click(function() { return false; });
625 $("#jot-preview").val("0");
631 // unpause auto reloads if they are currently stopped
634 $('#pause').html('');
639 // Converts the binary representation of data to hex
642 // discuss at: http://phpjs.org/functions/bin2hex
643 // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
644 // + bugfixed by: Onno Marsman
645 // + bugfixed by: Linuxworld
646 // * example 1: bin2hex('Kev');
647 // * returns 1: '4b6576'
648 // * example 2: bin2hex(String.fromCharCode(0x00));
650 var v,i, f = 0, a = [];
654 for (i = 0; i<f; i++) {
655 a[i] = s.charCodeAt(i).toString(16).replace(/^([\da-f])$/,"0$1");
661 function groupChangeMember(gid, cid, sec_token) {
662 $('body .fakelink').css('cursor', 'wait');
663 $.get('group/' + gid + '/' + cid + "?t=" + sec_token, function(data) {
664 $('#group-update-wrapper').html(data);
665 $('body .fakelink').css('cursor', 'auto');
669 function profChangeMember(gid,cid) {
670 $('body .fakelink').css('cursor', 'wait');
671 $.get('profperm/' + gid + '/' + cid, function(data) {
672 $('#prof-update-wrapper').html(data);
673 $('body .fakelink').css('cursor', 'auto');
677 function contactgroupChangeMember(gid,cid) {
678 $('body').css('cursor', 'wait');
679 $.get('contactgroup/' + gid + '/' + cid, function(data) {
680 $('body').css('cursor', 'auto');
685 function checkboxhighlight(box) {
686 if($(box).is(':checked')) {
687 $(box).addClass('checkeditem');
690 $(box).removeClass('checkeditem');
694 function notifyMarkAll() {
695 $.get('notify/mark/all', function(data) {
696 if(timer) clearTimeout(timer);
697 timer = setTimeout(NavUpdate,1000);
703 // code from http://www.tinymce.com/wiki.php/How-to_implement_a_custom_file_browser
704 function fcFileBrowser (field_name, url, type, win) {
705 /* TODO: If you work with sessions in PHP and your client doesn't accept cookies you might need to carry
706 the session name and session ID in the request string (can look like this: "?PHPSESSID=88p0n70s9dsknra96qhuk6etm5").
707 These lines of code extract the necessary parameters and add them back to the filebrowser URL again. */
710 var cmsURL = baseurl+"/fbrowser/"+type+"/";
712 tinyMCE.activeEditor.windowManager.open({
714 title : 'File Browser',
715 width : 420, // Your dimensions may differ - toy around with them!
718 inline : "yes", // This parameter only has an effect if you use the inlinepopups plugin!
719 close_previous : "no"
727 function setupFieldRichtext(){
730 mode : "specific_textareas",
731 editor_selector: "fieldRichtext",
732 plugins : "bbcode,paste, inlinepopups",
733 theme_advanced_buttons1 : "bold,italic,underline,undo,redo,link,unlink,image,forecolor,formatselect,code",
734 theme_advanced_buttons2 : "",
735 theme_advanced_buttons3 : "",
736 theme_advanced_toolbar_location : "top",
737 theme_advanced_toolbar_align : "center",
738 theme_advanced_blockformats : "blockquote,code",
739 theme_advanced_resizing : true,
740 paste_text_sticky : true,
741 entity_encoding : "raw",
742 add_unload_trigger : false,
743 remove_linebreaks : false,
744 //force_p_newlines : false,
745 //force_br_newlines : true,
746 forced_root_block : 'div',
748 content_css: baseurl+"/view/custom_tinymce.css",
749 theme_advanced_path : false,
750 file_browser_callback : "fcFileBrowser",
756 * sprintf in javascript
757 * "{0} and {1}".format('zero','uno');
759 String.prototype.format = function() {
760 var formatted = this;
761 for (var i = 0; i < arguments.length; i++) {
762 var regexp = new RegExp('\\{'+i+'\\}', 'gi');
763 formatted = formatted.replace(regexp, arguments[i]);
768 Array.prototype.remove = function(item) {
769 to=undefined; from=this.indexOf(item);
770 var rest = this.slice((to || from) + 1 || this.length);
771 this.length = from < 0 ? this.length + from : from;
772 return this.push.apply(this, rest);
775 function previewTheme(elm) {
776 theme = $(elm).val();
777 $.getJSON('pretheme?f=&theme=' + theme,function(data) {
778 $('#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>');
783 // notification permission settings in localstorage
784 // set by settings page
785 function getNotificationPermission() {
786 if (window["Notification"] === undefined) {
789 if (Notification.permission === 'granted') {
790 var val = localStorage.getItem('notification-permissions');
791 if (val === null) return 'denied';
794 return Notification.permission;