1 function resizeIframe(obj) {
2 //obj.style.height = 0;
6 function _resizeIframe(obj, desth) {
7 var h = obj.style.height;
8 var ch = obj.contentWindow.document.body.scrollHeight + 'px';
12 //console.log("_resizeIframe", obj, desth, ch);
14 setTimeout(_resizeIframe, 500, obj, ch);
16 if (ch>0) obj.style.height = ch;
17 setTimeout(_resizeIframe, 1000, obj, ch);
21 function openClose(theID) {
22 if(document.getElementById(theID).style.display == "block") {
23 document.getElementById(theID).style.display = "none"
26 document.getElementById(theID).style.display = "block"
30 function openMenu(theID) {
31 document.getElementById(theID).style.display = "block"
34 function closeMenu(theID) {
35 document.getElementById(theID).style.display = "none"
38 function decodeHtml(html) {
39 var txt = document.createElement("textarea");
48 var force_update = false;
50 var totStopped = false;
54 var in_progress = false;
55 var langSelect = false;
56 var commentBusy = false;
57 var last_popup_menu = null;
58 var last_popup_button = null;
59 var lockLoadContent = false;
62 $.ajaxSetup({cache: false});
64 /* setup tooltips *//*
65 $("a,.tt").each(function(){
68 if (e.hasClass("tttop")) pos="top";
69 if (e.hasClass("ttbottom")) pos="bottom";
70 if (e.hasClass("ttleft")) pos="left";
71 if (e.hasClass("ttright")) pos="right";
72 e.tipTip({defaultPosition: pos, edgeOffset: 8});
75 /* setup comment textarea buttons */
76 /* comment textarea buttons needs some "data-*" attributes to work:
77 * data-role="insert-formatting" : to mark the element as a formatting button
78 * data-comment="<string>" : string for "Comment", used by insertFormatting() function
79 * data-bbcode="<string>" : name of the bbcode element to insert. insertFormatting() will insert it as "[name][/name]"
80 * data-id="<string>" : id of the comment, used to find other comment-related element, like the textarea
82 $('body').on('click','[data-role="insert-formatting"]', function(e) {
85 var comment = o.data('comment');
86 var bbcode = o.data('bbcode');
87 var id = o.data('id');
89 Dialog.doImageBrowser("comment", id);
92 insertFormatting(comment, bbcode, id);
95 /* event from comment textarea button popups */
96 /* insert returned bbcode at cursor position or replace selected text */
97 $("body").on("fbrowser.image.comment", function(e, filename, bbcode, id) {
98 console.log("on", id);
100 var textarea = document.getElementById("comment-edit-text-" +id);
101 var start = textarea.selectionStart;
102 var end = textarea.selectionEnd;
103 textarea.value = textarea.value.substring(0, start) + bbcode + textarea.value.substring(end, textarea.value.length);
108 /* setup onoff widgets */
109 $(".onoff input").each(function(){
111 id = $(this).attr("id");
112 $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
115 $(".onoff > a").click(function(event){
116 event.preventDefault();
117 var input = $(this).siblings("input");
118 var val = 1-input.val();
119 var id = input.attr("id");
120 $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
121 $("#"+id+"_onoff ."+ (val==1?"on":"off")).removeClass("hidden");
126 /* setup field_richtext */
127 setupFieldRichtext();
130 function close_last_popup_menu() {
131 if(last_popup_menu) {
132 last_popup_menu.hide();
133 last_popup_menu.off('click', function(e) {e.stopPropagation()});
134 last_popup_button.removeClass("selected");
135 last_popup_menu = null;
136 last_popup_button = null;
139 $('a[rel^=#]').click(function(e){
141 var parent = $(this).parent();
142 var isSelected = (last_popup_button && parent.attr('id') == last_popup_button.attr('id'));
143 close_last_popup_menu();
144 if(isSelected) return false;
145 menu = $( $(this).attr('rel') );
148 if (menu.attr('popup')=="false") return false;
149 parent.toggleClass("selected");
151 if (menu.css("display") == "none") {
152 last_popup_menu = null;
153 last_popup_button = null;
155 last_popup_menu = menu;
156 last_popup_menu.on('click', function(e) {e.stopPropagation()});
157 last_popup_button = parent;
158 $('#nav-notifications-menu').perfectScrollbar('update');
162 $('html').click(function() {
163 close_last_popup_menu();
167 $("a.popupbox").colorbox({
169 'transition' : 'elastic'
171 $("a.ajax-popupbox").colorbox({
172 'transition' : 'elastic'
175 /* notifications template */
176 var notifications_tpl= unescape($("#nav-notifications-template[rel=template]").html());
177 var notifications_all = unescape($('<div>').append( $("#nav-notifications-see-all").clone() ).html()); //outerHtml hack
178 var notifications_mark = unescape($('<div>').append( $("#nav-notifications-mark-all").clone() ).html()); //outerHtml hack
179 var notifications_empty = unescape($("#nav-notifications-menu").html());
181 /* enable perfect-scrollbars for different elements */
182 $('#nav-notifications-menu, aside').perfectScrollbar();
184 /* nav update event */
185 $('nav').bind('nav-update', function(e,data){
186 var invalid = $(data).find('invalid').text();
187 if(invalid == 1) { window.location.href=window.location.href }
189 var net = $(data).find('net').text();
190 if(net == 0) { net = ''; $('#net-update').removeClass('show') } else { $('#net-update').addClass('show') }
191 $('#net-update').html(net);
193 var home = $(data).find('home').text();
194 if(home == 0) { home = ''; $('#home-update').removeClass('show') } else { $('#home-update').addClass('show') }
195 $('#home-update').html(home);
197 var intro = $(data).find('intro').text();
198 if(intro == 0) { intro = ''; $('#intro-update').removeClass('show') } else { $('#intro-update').addClass('show') }
199 $('#intro-update').html(intro);
201 var mail = $(data).find('mail').text();
202 if(mail == 0) { mail = ''; $('#mail-update').removeClass('show') } else { $('#mail-update').addClass('show') }
203 $('#mail-update').html(mail);
205 var intro = $(data).find('intro').text();
206 if(intro == 0) { intro = ''; $('#intro-update-li').removeClass('show') } else { $('#intro-update-li').addClass('show') }
207 $('#intro-update-li').html(intro);
209 var mail = $(data).find('mail').text();
210 if(mail == 0) { mail = ''; $('#mail-update-li').removeClass('show') } else { $('#mail-update-li').addClass('show') }
211 $('#mail-update-li').html(mail);
214 var allevents = $(data).find('all-events').text();
215 if(allevents == 0) { allevents = ''; $('#allevents-update').removeClass('show') } else { $('#allevents-update').addClass('show') }
216 $('#allevents-update').html(allevents);
218 var alleventstoday = $(data).find('all-events-today').text();
219 if(alleventstoday == 0) { $('#allevents-update').removeClass('notif-allevents-today') } else { $('#allevents-update').addClass('notif-allevents-today') }
221 var events = $(data).find('events').text();
222 if(events == 0) { events = ''; $('#events-update').removeClass('show') } else { $('#events-update').addClass('show') }
223 $('#events-update').html(events);
225 var eventstoday = $(data).find('events-today').text();
226 if(eventstoday == 0) { $('#events-update').removeClass('notif-events-today') } else { $('#events-update').addClass('notif-events-today') }
228 var birthdays = $(data).find('birthdays').text();
229 if(birthdays == 0) {birthdays = ''; $('#birthdays-update').removeClass('show') } else { $('#birthdays-update').addClass('show') }
230 $('#birthdays-update').html(birthdays);
232 var birthdaystoday = $(data).find('birthdays-today').text();
233 if(birthdaystoday == 0) { $('#birthdays-update').removeClass('notif-birthdays-today') } else { $('#birthdays-update').addClass('notif-birthdays-today') }
235 $(".sidebar-group-li .notify").removeClass("show");
236 $(data).find("group").each(function() {
238 var gcount = this.innerHTML;
239 $(".group-"+gid+" .notify").addClass("show").text(gcount);
242 $(".forum-widget-entry .notify").removeClass("show");
243 $(data).find("forum").each(function() {
245 var fcount = this.innerHTML;
246 $(".forum-"+fid+" .notify").addClass("show").text(fcount);
250 var eNotif = $(data).find('notif')
252 if (eNotif.children("note").length==0){
253 $("#nav-notifications-menu").html(notifications_empty);
255 nnm = $("#nav-notifications-menu");
256 nnm.html(notifications_all + notifications_mark);
257 //nnm.attr('popup','true');
259 var notification_lastitem = parseInt(localStorage.getItem("notification-lastitem"));
260 var notification_id = 0;
261 eNotif.children("note").each(function(){
263 var text = e.text().format("<span class='contactname'>"+e.attr('name')+"</span>");
264 var contact = ("<a href="+e.attr('url')+"><span class='contactname'>"+e.attr('name')+"</span></a>");
265 var seenclass = (e.attr('seen')==1)?"notify-seen":"notify-unseen";
266 var html = notifications_tpl.format(
267 e.attr('href'), // {0} // link to the source
268 e.attr('photo'), // {1} // photo of the contact
269 text, // {2} // preformatet text (autor + text)
270 e.attr('date'), // {3} // date of notification (time ago)
271 seenclass, // {4} // vistiting status of the notification
272 new Date(e.attr('timestamp')*1000), // {5} //date of notification
273 e.attr('url'), // {6} // profile url of the contact
274 e.text().format(""), // {7} // clean status text
275 contact // {8} //preformatat author (name + profile url)
279 $(eNotif.children("note").get().reverse()).each(function(){
281 notification_id = parseInt(e.attr('timestamp'));
282 if (notification_lastitem!== null && notification_id > notification_lastitem) {
283 if (getNotificationPermission()==="granted") {
284 var notification = new Notification(document.title, {
285 body: decodeHtml(e.text().replace('→ ','').format(e.attr('name'))),
286 icon: e.attr('photo'),
288 notification['url'] = e.attr('href');
289 notification.addEventListener("click", function(ev){
290 window.location = ev.target.url;
296 notification_lastitem = notification_id;
297 localStorage.setItem("notification-lastitem", notification_lastitem)
299 $("img[data-src]", nnm).each(function(i, el){
300 // Add src attribute for images with a data-src attribute
301 // However, don't bother if the data-src attribute is empty, because
302 // an empty "src" tag for an image will cause some browsers
303 // to prefetch the root page of the Friendica hub, which will
304 // unnecessarily load an entire profile/ or network/ page
305 if($(el).data("src") != '') $(el).attr('src', $(el).data("src"));
309 notif = eNotif.attr('count');
311 $("#nav-notifications-linkmenu").addClass("on");
313 $("#nav-notifications-linkmenu").removeClass("on");
315 if(notif == 0) { notif = ''; $('#notify-update').removeClass('show') } else { $('#notify-update').addClass('show') }
316 $('#notify-update').html(notif);
318 var eSysmsg = $(data).find('sysmsgs');
319 eSysmsg.children("notice").each(function(){
320 text = $(this).text();
321 $.jGrowl(text, { sticky: true, theme: 'notice' });
323 eSysmsg.children("info").each(function(){
324 text = $(this).text();
325 $.jGrowl(text, { sticky: false, theme: 'info', life: 5000 });
328 /* update the js scrollbars */
329 $('#nav-notifications-menu').perfectScrollbar('update');
334 // Allow folks to stop the ajax page updates with the pause/break key
335 $(document).keydown(function(event) {
336 if(event.keyCode == '8') {
337 var target = event.target || event.srcElement;
338 if (!/input|textarea/i.test(target.nodeName)) {
342 if(event.keyCode == '19' || (event.ctrlKey && event.which == '32')) {
343 event.preventDefault();
344 if(stopped == false) {
349 $('#pause').html('<img src="images/pause.gif" alt="pause" style="border: 1px solid black;" />');
360 // Set an event listener for infinite scroll
361 if(typeof infinite_scroll !== 'undefined') {
362 $(window).scroll(function(e){
363 if ($(document).height() != $(window).height()) {
364 // First method that is expected to work - but has problems with Chrome
365 if ($(window).scrollTop() > ($(document).height() - $(window).height() * 1.5))
368 // This method works with Chrome - but seems to be much slower in Firefox
369 if ($(window).scrollTop() > (($("section").height() + $("header").height() + $("footer").height()) - $(window).height() * 1.5))
378 function NavUpdate() {
381 var pingCmd = 'ping' + ((localUser != 0) ? '?f=&uid=' + localUser : '');
382 $.get(pingCmd,function(data) {
383 $(data).find('result').each(function() {
384 // send nav-update event
385 $('nav').trigger('nav-update', this);
390 if($('#live-network').length) { src = 'network'; liveUpdate(); }
391 if($('#live-profile').length) { src = 'profile'; liveUpdate(); }
392 if($('#live-community').length) { src = 'community'; liveUpdate(); }
393 if($('#live-notes').length) { src = 'notes'; liveUpdate(); }
394 if($('#live-display').length) { src = 'display'; liveUpdate(); }
395 /* if($('#live-display').length) {
398 window.location.href=window.location.href
401 if($('#live-photos').length) {
404 window.location.href=window.location.href
414 timer = setTimeout(NavUpdate,updateInterval);
417 function liveUpdate() {
418 if((src == null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; }
419 if(($('.comment-edit-text-full').length) || (in_progress)) {
421 clearTimeout(livetime);
423 livetime = setTimeout(liveUpdate, 5000);
429 prev = 'live-' + src;
433 if ($(document).scrollTop() == 0)
436 var udargs = ((netargs.length) ? '/' + netargs : '');
437 var update_url = 'update_' + src + udargs + '&p=' + profile_uid + '&page=' + profile_page + '&force=' + ((force_update) ? 1 : 0);
439 $.get(update_url,function(data) {
441 force_update = false;
442 // $('.collapsed-comments',data).each(function() {
443 // var ident = $(this).attr('id');
444 // var is_hidden = $('#' + ident).is(':hidden');
445 // if($('#' + ident).length) {
446 // $('#' + ident).replaceWith($(this));
448 // $('#' + ident).hide();
453 $('.toplevel_item',data).each(function() {
454 var ident = $(this).attr('id');
456 if($('#' + ident).length == 0 && profile_page == 1) {
457 $('img',this).each(function() {
458 $(this).attr('src',$(this).attr('dst'));
460 $('#' + prev).after($(this));
463 // Find out if the hidden comments are open, so we can keep it that way
464 // if a new comment has been posted
465 var id = $('.hide-comments-total', this).attr('id');
466 if(typeof id != 'undefined') {
467 id = id.split('-')[3];
468 var commentsOpen = $("#collapsed-comments-" + id).is(":visible");
471 $('img',this).each(function() {
472 $(this).attr('src',$(this).attr('dst'));
474 //vScroll = $(document).scrollTop();
475 $('html').height($('html').height());
476 $('#' + ident).replaceWith($(this));
478 if(typeof id != 'undefined') {
479 if(commentsOpen) showHideComments(id);
481 $('html').height('auto');
482 //$(document).scrollTop(vScroll);
487 // reset vars for inserting individual items
489 /* prev = 'live-' + src;
491 $('.wall-item-outside-wrapper',data).each(function() {
492 var ident = $(this).attr('id');
494 if($('#' + ident).length == 0 && prev != 'live-' + src) {
495 $('img',this).each(function() {
496 $(this).attr('src',$(this).attr('dst'));
498 $('#' + prev).after($(this));
501 $('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago'));
502 if($('#' + ident + ' ' + '.comment-edit-text-empty').length)
503 $('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
504 $('#' + ident + ' ' + '.hide-comments-total').replaceWith($(this).find('.hide-comments-total'));
505 $('#' + ident + ' ' + '.wall-item-like').replaceWith($(this).find('.wall-item-like'));
506 $('#' + ident + ' ' + '.wall-item-dislike').replaceWith($(this).find('.wall-item-dislike'));
507 $('#' + ident + ' ' + '.my-comment-photo').each(function() {
508 $(this).attr('src',$(this).attr('dst'));
514 $('.like-rotator').hide();
517 $('body').css('cursor', 'auto');
519 /* autocomplete @nicknames */
520 $(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl");
521 /* autocomplete bbcode */
522 $(".comment-edit-form textarea").bbco_autocomplete('bbcode');
524 // setup videos, since VideoJS won't take care of any loaded via AJAX
525 if(typeof videojs != 'undefined') videojs.autoSetup();
529 function imgbright(node) {
530 $(node).removeClass("drophide").addClass("drop");
533 function imgdull(node) {
534 $(node).removeClass("drop").addClass("drophide");
537 // Since our ajax calls are asynchronous, we will give a few
538 // seconds for the first ajax call (setting like/dislike), then
539 // run the updater to pick up any changes and display on the page.
540 // The updater will turn any rotators off when it's done.
541 // This function will have returned long before any of these
542 // events have completed and therefore there won't be any
543 // visible feedback that anything changed without all this
544 // trickery. This still could cause confusion if the "like" ajax call
545 // is delayed and NavUpdate runs before it completes.
547 function dolike(ident,verb) {
549 $('#like-rotator-' + ident.toString()).show();
550 $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate );
555 function dosubthread(ident) {
557 $('#like-rotator-' + ident.toString()).show();
558 $.get('subthread/' + ident.toString(), NavUpdate );
563 function dostar(ident) {
564 ident = ident.toString();
565 $('#like-rotator-' + ident).show();
566 $.get('starred/' + ident, function(data) {
567 if(data.match(/1/)) {
568 $('#starred-' + ident).addClass('starred');
569 $('#starred-' + ident).removeClass('unstarred');
570 $('#star-' + ident).addClass('hidden');
571 $('#unstar-' + ident).removeClass('hidden');
574 $('#starred-' + ident).addClass('unstarred');
575 $('#starred-' + ident).removeClass('starred');
576 $('#star-' + ident).removeClass('hidden');
577 $('#unstar-' + ident).addClass('hidden');
579 $('#like-rotator-' + ident).hide();
583 function doignore(ident) {
584 ident = ident.toString();
585 $('#like-rotator-' + ident).show();
586 $.get('ignored/' + ident, function(data) {
587 if(data.match(/1/)) {
588 $('#ignored-' + ident).addClass('ignored');
589 $('#ignored-' + ident).removeClass('unignored');
590 $('#ignore-' + ident).addClass('hidden');
591 $('#unignore-' + ident).removeClass('hidden');
594 $('#ignored-' + ident).addClass('unignored');
595 $('#ignored-' + ident).removeClass('ignored');
596 $('#ignore-' + ident).removeClass('hidden');
597 $('#unignore-' + ident).addClass('hidden');
599 $('#like-rotator-' + ident).hide();
603 function getPosition(e) {
604 var cursor = {x:0, y:0};
605 if ( e.pageX || e.pageY ) {
610 if( e.clientX || e.clientY ) {
611 cursor.x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
612 cursor.y = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
624 var lockvisible = false;
626 function lockview(event,id) {
627 event = event || window.event;
628 cursor = getPosition(event);
634 $.get('lockview/' + id, function(data) {
635 $('#panel').html(data);
636 $('#panel').css({ 'left': cursor.x + 5 , 'top': cursor.y + 5});
642 function lockviewhide() {
647 function post_comment(id) {
650 $('body').css('cursor', 'wait');
651 $("#comment-preview-inp-" + id).val("0");
654 $("#comment-edit-form-" + id).serialize(),
657 $("#comment-edit-wrapper-" + id).hide();
658 $("#comment-edit-text-" + id).val('');
659 var tarea = document.getElementById("comment-edit-text-" + id);
661 commentClose(tarea,id);
662 if(timer) clearTimeout(timer);
663 timer = setTimeout(NavUpdate,10);
667 window.location.href=data.reload;
676 function preview_comment(id) {
677 $("#comment-preview-inp-" + id).val("1");
678 $("#comment-edit-preview-" + id).show();
681 $("#comment-edit-form-" + id).serialize(),
684 $("#comment-edit-preview-" + id).html(data.preview);
685 $("#comment-edit-preview-" + id + " a").click(function() { return false; });
695 function showHideComments(id) {
696 if( $("#collapsed-comments-" + id).is(":visible")) {
697 $("#collapsed-comments-" + id).hide();
698 $("#hide-comments-" + id).html(window.showMore);
701 $("#collapsed-comments-" + id).show();
702 $("#hide-comments-" + id).html(window.showFewer);
708 function preview_post() {
709 $("#jot-preview").val("1");
710 $("#jot-preview-content").show();
711 tinyMCE.triggerSave();
714 $("#profile-jot-form").serialize(),
717 $("#jot-preview-content").html(data.preview);
718 $("#jot-preview-content" + " a").click(function() { return false; });
723 $("#jot-preview").val("0");
729 // unpause auto reloads if they are currently stopped
732 $('#pause').html('');
735 // load more network content (used for infinite scroll)
736 function loadScrollContent() {
737 if (lockLoadContent) return;
738 lockLoadContent = true;
740 $("#scroll-loader").fadeIn('normal');
742 // the page number to load is one higher than the actual
744 infinite_scroll.pageno+=1;
746 console.log('Loading page ' + infinite_scroll.pageno);
748 // get the raw content from the next page and insert this content
749 // right before "#conversation-end"
750 $.get('network?mode=raw' + infinite_scroll.reload_uri + '&page=' + infinite_scroll.pageno, function(data) {
751 $("#scroll-loader").hide();
752 if ($(data).length > 0) {
753 $(data).insertBefore('#conversation-end');
754 lockLoadContent = false;
756 $("#scroll-end").fadeIn('normal');
762 // Converts the binary representation of data to hex
765 // discuss at: http://phpjs.org/functions/bin2hex
766 // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
767 // + bugfixed by: Onno Marsman
768 // + bugfixed by: Linuxworld
769 // * example 1: bin2hex('Kev');
770 // * returns 1: '4b6576'
771 // * example 2: bin2hex(String.fromCharCode(0x00));
773 var v,i, f = 0, a = [];
777 for (i = 0; i<f; i++) {
778 a[i] = s.charCodeAt(i).toString(16).replace(/^([\da-f])$/,"0$1");
784 function groupChangeMember(gid, cid, sec_token) {
785 $('body .fakelink').css('cursor', 'wait');
786 $.get('group/' + gid + '/' + cid + "?t=" + sec_token, function(data) {
787 $('#group-update-wrapper').html(data);
788 $('body .fakelink').css('cursor', 'auto');
792 function profChangeMember(gid,cid) {
793 $('body .fakelink').css('cursor', 'wait');
794 $.get('profperm/' + gid + '/' + cid, function(data) {
795 $('#prof-update-wrapper').html(data);
796 $('body .fakelink').css('cursor', 'auto');
800 function contactgroupChangeMember(gid,cid) {
801 $('body').css('cursor', 'wait');
802 $.get('contactgroup/' + gid + '/' + cid, function(data) {
803 $('body').css('cursor', 'auto');
808 function checkboxhighlight(box) {
809 if($(box).is(':checked')) {
810 $(box).addClass('checkeditem');
813 $(box).removeClass('checkeditem');
817 function notifyMarkAll() {
818 $.get('notify/mark/all', function(data) {
819 if(timer) clearTimeout(timer);
820 timer = setTimeout(NavUpdate,1000);
826 // code from http://www.tinymce.com/wiki.php/How-to_implement_a_custom_file_browser
827 function fcFileBrowser (field_name, url, type, win) {
828 /* TODO: If you work with sessions in PHP and your client doesn't accept cookies you might need to carry
829 the session name and session ID in the request string (can look like this: "?PHPSESSID=88p0n70s9dsknra96qhuk6etm5").
830 These lines of code extract the necessary parameters and add them back to the filebrowser URL again. */
833 var cmsURL = baseurl+"/fbrowser/"+type+"/";
835 tinyMCE.activeEditor.windowManager.open({
837 title : 'File Browser',
838 width : 420, // Your dimensions may differ - toy around with them!
841 inline : "yes", // This parameter only has an effect if you use the inlinepopups plugin!
842 close_previous : "no"
850 function setupFieldRichtext(){
853 mode : "specific_textareas",
854 editor_selector: "fieldRichtext",
855 plugins : "bbcode,paste, inlinepopups",
856 theme_advanced_buttons1 : "bold,italic,underline,undo,redo,link,unlink,image,forecolor,formatselect,code",
857 theme_advanced_buttons2 : "",
858 theme_advanced_buttons3 : "",
859 theme_advanced_toolbar_location : "top",
860 theme_advanced_toolbar_align : "center",
861 theme_advanced_blockformats : "blockquote,code",
862 theme_advanced_resizing : true,
863 paste_text_sticky : true,
864 entity_encoding : "raw",
865 add_unload_trigger : false,
866 remove_linebreaks : false,
867 //force_p_newlines : false,
868 //force_br_newlines : true,
869 forced_root_block : 'div',
871 content_css: baseurl+"/view/custom_tinymce.css",
872 theme_advanced_path : false,
873 file_browser_callback : "fcFileBrowser",
879 * sprintf in javascript
880 * "{0} and {1}".format('zero','uno');
882 String.prototype.format = function() {
883 var formatted = this;
884 for (var i = 0; i < arguments.length; i++) {
885 var regexp = new RegExp('\\{'+i+'\\}', 'gi');
886 formatted = formatted.replace(regexp, arguments[i]);
891 Array.prototype.remove = function(item) {
892 to=undefined; from=this.indexOf(item);
893 var rest = this.slice((to || from) + 1 || this.length);
894 this.length = from < 0 ? this.length + from : from;
895 return this.push.apply(this, rest);
898 function previewTheme(elm) {
899 theme = $(elm).val();
900 $.getJSON('pretheme?f=&theme=' + theme,function(data) {
901 $('#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>');
906 // notification permission settings in localstorage
907 // set by settings page
908 function getNotificationPermission() {
909 if (window["Notification"] === undefined) {
912 if (Notification.permission === 'granted') {
913 var val = localStorage.getItem('notification-permissions');
914 if (val === null) return 'denied';
917 return Notification.permission;
922 * Show a dialog loaded from an url
923 * By defaults this load the url in an iframe in colorbox
924 * Themes can overwrite `show()` function to personalize it
931 * @return object colorbox
933 show : function (url) {
934 var size = Dialog._get_size();
935 return $.colorbox({href: url, iframe:true,innerWidth: size.width+'px',innerHeight: size.height+'px'})
939 * Show the Image browser dialog
942 * @param string id (optional)
945 * The name will be used to build the event name
946 * fired by image browser dialog when the user select
947 * an image. The optional id will be passed as argument
948 * to the event handler
950 doImageBrowser : function (name, id) {
951 var url = Dialog._get_url("image",name,id);
952 return Dialog.show(url);
956 * Show the File browser dialog
959 * @param string id (optional)
962 * The name will be used to build the event name
963 * fired by file browser dialog when the user select
964 * a file. The optional id will be passed as argument
965 * to the event handler
967 doFileBrowser : function (name, id) {
968 var url = Dialog._get_url("file",name,id);
969 return Dialog.show(url);
972 _get_url : function(type, name, id) {
974 if (id !== undefined) hash = hash + "-" + id;
975 return baseurl + "/fbrowser/"+type+"/?mode=minimal#"+hash;
978 _get_size: function() {
980 width: window.innerWidth-50,
981 height: window.innerHeight-100