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 = localStorage.getItem("notification-lastitem");
186 var notification_first_id = 0;
188 eNotif.children("note").each(function(){
190 text = e.text().format("<span class='contactname'>"+e.attr('name')+"</span>");
191 html = notifications_tpl.format(e.attr('href'),e.attr('photo'), text, e.attr('date'), e.attr('seen'));
194 var notification_id = e.attr('href').match(/\d+$/)[0];
195 if (notification_lastitem!== null && notification_id!=notification_lastitem) {
196 if (notification_first_id===0) notification_first_id = notification_id;
197 if (getNotificationPermission()==="granted") {
198 var notification = new Notification(document.title, {
199 body: e.text().replace('→ ','').format(e.attr('name')),
200 icon: e.attr('photo'),
202 // close notification after 5 secs.
203 // see https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API#Closing_notifications
204 setTimeout(notification.close.bind(notification), 5000);
206 notification.addEventListener("click", function(ev){
207 window.location = ev.target.data;
211 if (notification_id == notification_lastitem) {
212 if (notification_first_id===0) notification_first_id = notification_id;
213 notification_lastitem = null;
218 if (notification_first_id!==0) notification_lastitem = notification_first_id;
219 localStorage.setItem("notification-lastitem", notification_lastitem)
221 $("img[data-src]", nnm).each(function(i, el){
222 // Add src attribute for images with a data-src attribute
223 // However, don't bother if the data-src attribute is empty, because
224 // an empty "src" tag for an image will cause some browsers
225 // to prefetch the root page of the Friendica hub, which will
226 // unnecessarily load an entire profile/ or network/ page
227 if($(el).data("src") != '') $(el).attr('src', $(el).data("src"));
231 notif = eNotif.attr('count');
233 $("#nav-notifications-linkmenu").addClass("on");
235 $("#nav-notifications-linkmenu").removeClass("on");
237 if(notif == 0) { notif = ''; $('#notify-update').removeClass('show') } else { $('#notify-update').addClass('show') }
238 $('#notify-update').html(notif);
240 var eSysmsg = $(data).find('sysmsgs');
241 eSysmsg.children("notice").each(function(){
242 text = $(this).text();
243 $.jGrowl(text, { sticky: true, theme: 'notice' });
245 eSysmsg.children("info").each(function(){
246 text = $(this).text();
247 $.jGrowl(text, { sticky: false, theme: 'info', life: 5000 });
253 // Allow folks to stop the ajax page updates with the pause/break key
254 $(document).keydown(function(event) {
255 if(event.keyCode == '8') {
256 var target = event.target || event.srcElement;
257 if (!/input|textarea/i.test(target.nodeName)) {
261 if(event.keyCode == '19' || (event.ctrlKey && event.which == '32')) {
262 event.preventDefault();
263 if(stopped == false) {
268 $('#pause').html('<img src="images/pause.gif" alt="pause" style="border: 1px solid black;" />');
282 function NavUpdate() {
285 var pingCmd = 'ping' + ((localUser != 0) ? '?f=&uid=' + localUser : '');
286 $.get(pingCmd,function(data) {
287 $(data).find('result').each(function() {
288 // send nav-update event
289 $('nav').trigger('nav-update', this);
294 if($('#live-network').length) { src = 'network'; liveUpdate(); }
295 if($('#live-profile').length) { src = 'profile'; liveUpdate(); }
296 if($('#live-community').length) { src = 'community'; liveUpdate(); }
297 if($('#live-notes').length) { src = 'notes'; liveUpdate(); }
298 if($('#live-display').length) { src = 'display'; liveUpdate(); }
299 /* if($('#live-display').length) {
302 window.location.href=window.location.href
305 if($('#live-photos').length) {
308 window.location.href=window.location.href
318 timer = setTimeout(NavUpdate,updateInterval);
321 function liveUpdate() {
322 if((src == null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; }
323 if(($('.comment-edit-text-full').length) || (in_progress)) {
325 clearTimeout(livetime);
327 livetime = setTimeout(liveUpdate, 5000);
333 prev = 'live-' + src;
337 if ($(document).scrollTop() == 0)
340 var udargs = ((netargs.length) ? '/' + netargs : '');
341 var update_url = 'update_' + src + udargs + '&p=' + profile_uid + '&page=' + profile_page + '&force=' + ((force_update) ? 1 : 0);
343 $.get(update_url,function(data) {
345 force_update = false;
346 // $('.collapsed-comments',data).each(function() {
347 // var ident = $(this).attr('id');
348 // var is_hidden = $('#' + ident).is(':hidden');
349 // if($('#' + ident).length) {
350 // $('#' + ident).replaceWith($(this));
352 // $('#' + ident).hide();
357 $('.toplevel_item',data).each(function() {
358 var ident = $(this).attr('id');
360 if($('#' + ident).length == 0 && profile_page == 1) {
361 $('img',this).each(function() {
362 $(this).attr('src',$(this).attr('dst'));
364 $('#' + prev).after($(this));
367 // Find out if the hidden comments are open, so we can keep it that way
368 // if a new comment has been posted
369 var id = $('.hide-comments-total', this).attr('id');
370 if(typeof id != 'undefined') {
371 id = id.split('-')[3];
372 var commentsOpen = $("#collapsed-comments-" + id).is(":visible");
375 $('img',this).each(function() {
376 $(this).attr('src',$(this).attr('dst'));
378 //vScroll = $(document).scrollTop();
379 $('html').height($('html').height());
380 $('#' + ident).replaceWith($(this));
382 if(typeof id != 'undefined') {
383 if(commentsOpen) showHideComments(id);
385 $('html').height('auto');
386 //$(document).scrollTop(vScroll);
391 // reset vars for inserting individual items
393 /* prev = 'live-' + src;
395 $('.wall-item-outside-wrapper',data).each(function() {
396 var ident = $(this).attr('id');
398 if($('#' + ident).length == 0 && prev != 'live-' + src) {
399 $('img',this).each(function() {
400 $(this).attr('src',$(this).attr('dst'));
402 $('#' + prev).after($(this));
405 $('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago'));
406 if($('#' + ident + ' ' + '.comment-edit-text-empty').length)
407 $('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
408 $('#' + ident + ' ' + '.hide-comments-total').replaceWith($(this).find('.hide-comments-total'));
409 $('#' + ident + ' ' + '.wall-item-like').replaceWith($(this).find('.wall-item-like'));
410 $('#' + ident + ' ' + '.wall-item-dislike').replaceWith($(this).find('.wall-item-dislike'));
411 $('#' + ident + ' ' + '.my-comment-photo').each(function() {
412 $(this).attr('src',$(this).attr('dst'));
418 $('.like-rotator').hide();
421 $('body').css('cursor', 'auto');
423 /* autocomplete @nicknames */
424 $(".comment-edit-form textarea").contact_autocomplete(baseurl+"/acl");
426 // setup videos, since VideoJS won't take care of any loaded via AJAX
427 if(typeof videojs != 'undefined') videojs.autoSetup();
431 function imgbright(node) {
432 $(node).removeClass("drophide").addClass("drop");
435 function imgdull(node) {
436 $(node).removeClass("drop").addClass("drophide");
439 // Since our ajax calls are asynchronous, we will give a few
440 // seconds for the first ajax call (setting like/dislike), then
441 // run the updater to pick up any changes and display on the page.
442 // The updater will turn any rotators off when it's done.
443 // This function will have returned long before any of these
444 // events have completed and therefore there won't be any
445 // visible feedback that anything changed without all this
446 // trickery. This still could cause confusion if the "like" ajax call
447 // is delayed and NavUpdate runs before it completes.
449 function dolike(ident,verb) {
451 $('#like-rotator-' + ident.toString()).show();
452 $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate );
457 function dosubthread(ident) {
459 $('#like-rotator-' + ident.toString()).show();
460 $.get('subthread/' + ident.toString(), NavUpdate );
465 function dostar(ident) {
466 ident = ident.toString();
467 $('#like-rotator-' + ident).show();
468 $.get('starred/' + ident, function(data) {
469 if(data.match(/1/)) {
470 $('#starred-' + ident).addClass('starred');
471 $('#starred-' + ident).removeClass('unstarred');
472 $('#star-' + ident).addClass('hidden');
473 $('#unstar-' + ident).removeClass('hidden');
476 $('#starred-' + ident).addClass('unstarred');
477 $('#starred-' + ident).removeClass('starred');
478 $('#star-' + ident).removeClass('hidden');
479 $('#unstar-' + ident).addClass('hidden');
481 $('#like-rotator-' + ident).hide();
485 function doignore(ident) {
486 ident = ident.toString();
487 $('#like-rotator-' + ident).show();
488 $.get('ignored/' + ident, function(data) {
489 if(data.match(/1/)) {
490 $('#ignored-' + ident).addClass('ignored');
491 $('#ignored-' + ident).removeClass('unignored');
492 $('#ignore-' + ident).addClass('hidden');
493 $('#unignore-' + ident).removeClass('hidden');
496 $('#ignored-' + ident).addClass('unignored');
497 $('#ignored-' + ident).removeClass('ignored');
498 $('#ignore-' + ident).removeClass('hidden');
499 $('#unignore-' + ident).addClass('hidden');
501 $('#like-rotator-' + ident).hide();
505 function getPosition(e) {
506 var cursor = {x:0, y:0};
507 if ( e.pageX || e.pageY ) {
512 if( e.clientX || e.clientY ) {
513 cursor.x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
514 cursor.y = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
526 var lockvisible = false;
528 function lockview(event,id) {
529 event = event || window.event;
530 cursor = getPosition(event);
536 $.get('lockview/' + id, function(data) {
537 $('#panel').html(data);
538 $('#panel').css({ 'left': cursor.x + 5 , 'top': cursor.y + 5});
544 function lockviewhide() {
549 function post_comment(id) {
552 $('body').css('cursor', 'wait');
553 $("#comment-preview-inp-" + id).val("0");
556 $("#comment-edit-form-" + id).serialize(),
559 $("#comment-edit-wrapper-" + id).hide();
560 $("#comment-edit-text-" + id).val('');
561 var tarea = document.getElementById("comment-edit-text-" + id);
563 commentClose(tarea,id);
564 if(timer) clearTimeout(timer);
565 timer = setTimeout(NavUpdate,10);
569 window.location.href=data.reload;
578 function preview_comment(id) {
579 $("#comment-preview-inp-" + id).val("1");
580 $("#comment-edit-preview-" + id).show();
583 $("#comment-edit-form-" + id).serialize(),
587 $("#comment-edit-preview-" + id).html(data.preview);
588 $("#comment-edit-preview-" + id + " a").click(function() { return false; });
598 function showHideComments(id) {
599 if( $("#collapsed-comments-" + id).is(":visible")) {
600 $("#collapsed-comments-" + id).hide();
601 $("#hide-comments-" + id).html(window.showMore);
604 $("#collapsed-comments-" + id).show();
605 $("#hide-comments-" + id).html(window.showFewer);
611 function preview_post() {
612 $("#jot-preview").val("1");
613 $("#jot-preview-content").show();
614 tinyMCE.triggerSave();
617 $("#profile-jot-form").serialize(),
620 $("#jot-preview-content").html(data.preview);
621 $("#jot-preview-content" + " a").click(function() { return false; });
626 $("#jot-preview").val("0");
632 // unpause auto reloads if they are currently stopped
635 $('#pause').html('');
640 // Converts the binary representation of data to hex
643 // discuss at: http://phpjs.org/functions/bin2hex
644 // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
645 // + bugfixed by: Onno Marsman
646 // + bugfixed by: Linuxworld
647 // * example 1: bin2hex('Kev');
648 // * returns 1: '4b6576'
649 // * example 2: bin2hex(String.fromCharCode(0x00));
651 var v,i, f = 0, a = [];
655 for (i = 0; i<f; i++) {
656 a[i] = s.charCodeAt(i).toString(16).replace(/^([\da-f])$/,"0$1");
662 function groupChangeMember(gid, cid, sec_token) {
663 $('body .fakelink').css('cursor', 'wait');
664 $.get('group/' + gid + '/' + cid + "?t=" + sec_token, function(data) {
665 $('#group-update-wrapper').html(data);
666 $('body .fakelink').css('cursor', 'auto');
670 function profChangeMember(gid,cid) {
671 $('body .fakelink').css('cursor', 'wait');
672 $.get('profperm/' + gid + '/' + cid, function(data) {
673 $('#prof-update-wrapper').html(data);
674 $('body .fakelink').css('cursor', 'auto');
678 function contactgroupChangeMember(gid,cid) {
679 $('body').css('cursor', 'wait');
680 $.get('contactgroup/' + gid + '/' + cid, function(data) {
681 $('body').css('cursor', 'auto');
686 function checkboxhighlight(box) {
687 if($(box).is(':checked')) {
688 $(box).addClass('checkeditem');
691 $(box).removeClass('checkeditem');
695 function notifyMarkAll() {
696 $.get('notify/mark/all', function(data) {
697 if(timer) clearTimeout(timer);
698 timer = setTimeout(NavUpdate,1000);
704 // code from http://www.tinymce.com/wiki.php/How-to_implement_a_custom_file_browser
705 function fcFileBrowser (field_name, url, type, win) {
706 /* TODO: If you work with sessions in PHP and your client doesn't accept cookies you might need to carry
707 the session name and session ID in the request string (can look like this: "?PHPSESSID=88p0n70s9dsknra96qhuk6etm5").
708 These lines of code extract the necessary parameters and add them back to the filebrowser URL again. */
711 var cmsURL = baseurl+"/fbrowser/"+type+"/";
713 tinyMCE.activeEditor.windowManager.open({
715 title : 'File Browser',
716 width : 420, // Your dimensions may differ - toy around with them!
719 inline : "yes", // This parameter only has an effect if you use the inlinepopups plugin!
720 close_previous : "no"
728 function setupFieldRichtext(){
731 mode : "specific_textareas",
732 editor_selector: "fieldRichtext",
733 plugins : "bbcode,paste, inlinepopups",
734 theme_advanced_buttons1 : "bold,italic,underline,undo,redo,link,unlink,image,forecolor,formatselect,code",
735 theme_advanced_buttons2 : "",
736 theme_advanced_buttons3 : "",
737 theme_advanced_toolbar_location : "top",
738 theme_advanced_toolbar_align : "center",
739 theme_advanced_blockformats : "blockquote,code",
740 theme_advanced_resizing : true,
741 paste_text_sticky : true,
742 entity_encoding : "raw",
743 add_unload_trigger : false,
744 remove_linebreaks : false,
745 //force_p_newlines : false,
746 //force_br_newlines : true,
747 forced_root_block : 'div',
749 content_css: baseurl+"/view/custom_tinymce.css",
750 theme_advanced_path : false,
751 file_browser_callback : "fcFileBrowser",
757 * sprintf in javascript
758 * "{0} and {1}".format('zero','uno');
760 String.prototype.format = function() {
761 var formatted = this;
762 for (var i = 0; i < arguments.length; i++) {
763 var regexp = new RegExp('\\{'+i+'\\}', 'gi');
764 formatted = formatted.replace(regexp, arguments[i]);
769 Array.prototype.remove = function(item) {
770 to=undefined; from=this.indexOf(item);
771 var rest = this.slice((to || from) + 1 || this.length);
772 this.length = from < 0 ? this.length + from : from;
773 return this.push.apply(this, rest);
776 function previewTheme(elm) {
777 theme = $(elm).val();
778 $.getJSON('pretheme?f=&theme=' + theme,function(data) {
779 $('#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>');
784 // notification permission settings in localstorage
785 // set by settings page
786 function getNotificationPermission() {
787 if (window["Notification"] === undefined) {
790 if (Notification.permission === 'granted') {
791 return localStorage.getItem('notification-permissions');
793 return Notification.permission;