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});
54 /* setup comment textarea buttons */
55 /* comment textarea buttons needs some "data-*" attributes to work:
56 * data-role="insert-formatting" : to mark the element as a formatting button
57 * data-comment="<string>" : string for "Comment", used by insertFormatting() function
58 * data-bbcode="<string>" : name of the bbcode element to insert. insertFormatting() will insert it as "[name][/name]"
59 * data-id="<string>" : id of the comment, used to find other comment-related element, like the textarea
61 $('body').on('click','[data-role="insert-formatting"]', function(e) {
64 var comment = o.data('comment');
65 var bbcode = o.data('bbcode');
66 var id = o.data('id');
68 Dialog.doImageBrowser("comment", id);
71 insertFormatting(comment, bbcode, id);
74 /* event from comment textarea button popups */
75 /* insert returned bbcode at cursor position or replace selected text */
76 $("body").on("fbrowser.image.comment", function(e, filename, bbcode, id) {
77 console.log("on", id);
79 var textarea = document.getElementById("comment-edit-text-" +id);
80 var start = textarea.selectionStart;
81 var end = textarea.selectionEnd;
82 textarea.value = textarea.value.substring(0, start) + bbcode + textarea.value.substring(end, textarea.value.length);
87 /* setup onoff widgets */
88 $(".onoff input").each(function(){
90 id = $(this).attr("id");
91 $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
94 $(".onoff > a").click(function(event){
95 event.preventDefault();
96 var input = $(this).siblings("input");
97 var val = 1-input.val();
98 var id = input.attr("id");
99 $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
100 $("#"+id+"_onoff ."+ (val==1?"on":"off")).removeClass("hidden");
105 /* setup field_richtext */
106 setupFieldRichtext();
109 function close_last_popup_menu() {
110 if(last_popup_menu) {
111 last_popup_menu.hide();
112 last_popup_button.removeClass("selected");
113 last_popup_menu = null;
114 last_popup_button = null;
117 $('a[rel^=#]').click(function(e){
119 var parent = $(this).parent();
120 var isSelected = (last_popup_button && parent.attr('id') == last_popup_button.attr('id'));
121 close_last_popup_menu();
122 if(isSelected) return false;
123 menu = $( $(this).attr('rel') );
126 if (menu.attr('popup')=="false") return false;
127 parent.toggleClass("selected");
129 if (menu.css("display") == "none") {
130 last_popup_menu = null;
131 last_popup_button = null;
133 last_popup_menu = menu;
134 last_popup_button = parent;
138 $('html').click(function() {
139 close_last_popup_menu();
143 $("a.popupbox").colorbox({
145 'transition' : 'elastic'
149 /* notifications template */
150 var notifications_tpl= unescape($("#nav-notifications-template[rel=template]").html());
151 var notifications_all = unescape($('<div>').append( $("#nav-notifications-see-all").clone() ).html()); //outerHtml hack
152 var notifications_mark = unescape($('<div>').append( $("#nav-notifications-mark-all").clone() ).html()); //outerHtml hack
153 var notifications_empty = unescape($("#nav-notifications-menu").html());
155 /* nav update event */
156 $('nav').bind('nav-update', function(e,data){
157 var invalid = $(data).find('invalid').text();
158 if(invalid == 1) { window.location.href=window.location.href }
160 var net = $(data).find('net').text();
161 if(net == 0) { net = ''; $('#net-update').removeClass('show') } else { $('#net-update').addClass('show') }
162 $('#net-update').html(net);
164 var home = $(data).find('home').text();
165 if(home == 0) { home = ''; $('#home-update').removeClass('show') } else { $('#home-update').addClass('show') }
166 $('#home-update').html(home);
168 var intro = $(data).find('intro').text();
169 if(intro == 0) { intro = ''; $('#intro-update').removeClass('show') } else { $('#intro-update').addClass('show') }
170 $('#intro-update').html(intro);
172 var mail = $(data).find('mail').text();
173 if(mail == 0) { mail = ''; $('#mail-update').removeClass('show') } else { $('#mail-update').addClass('show') }
174 $('#mail-update').html(mail);
176 var intro = $(data).find('intro').text();
177 if(intro == 0) { intro = ''; $('#intro-update-li').removeClass('show') } else { $('#intro-update-li').addClass('show') }
178 $('#intro-update-li').html(intro);
180 var mail = $(data).find('mail').text();
181 if(mail == 0) { mail = ''; $('#mail-update-li').removeClass('show') } else { $('#mail-update-li').addClass('show') }
182 $('#mail-update-li').html(mail);
185 var allevents = $(data).find('all-events').text();
186 if(allevents == 0) { allevents = ''; $('#allevents-update').removeClass('show') } else { $('#allevents-update').addClass('show') }
187 $('#allevents-update').html(allevents);
189 var alleventstoday = $(data).find('all-events-today').text();
190 if(alleventstoday == 0) { $('#allevents-update').removeClass('notif-allevents-today') } else { $('#allevents-update').addClass('notif-allevents-today') }
192 var events = $(data).find('events').text();
193 if(events == 0) { events = ''; $('#events-update').removeClass('show') } else { $('#events-update').addClass('show') }
194 $('#events-update').html(events);
196 var eventstoday = $(data).find('events-today').text();
197 if(eventstoday == 0) { $('#events-update').removeClass('notif-events-today') } else { $('#events-update').addClass('notif-events-today') }
199 var birthdays = $(data).find('birthdays').text();
200 if(birthdays == 0) {birthdays = ''; $('#birthdays-update').removeClass('show') } else { $('#birthdays-update').addClass('show') }
201 $('#birthdays-update').html(birthdays);
203 var birthdaystoday = $(data).find('birthdays-today').text();
204 if(birthdaystoday == 0) { $('#birthdays-update').removeClass('notif-birthdays-today') } else { $('#birthdays-update').addClass('notif-birthdays-today') }
207 var eNotif = $(data).find('notif')
209 if (eNotif.children("note").length==0){
210 $("#nav-notifications-menu").html(notifications_empty);
212 nnm = $("#nav-notifications-menu");
213 nnm.html(notifications_all + notifications_mark);
214 //nnm.attr('popup','true');
216 var notification_lastitem = parseInt(localStorage.getItem("notification-lastitem"));
217 var notification_id = 0;
218 eNotif.children("note").each(function(){
220 var text = e.text().format("<span class='contactname'>"+e.attr('name')+"</span>");
221 var seenclass = (e.attr('seen')==1)?"notify-seen":"notify-unseen";
222 var html = notifications_tpl.format(e.attr('href'),
223 e.attr('photo'), // {0}
225 e.attr('date'), // {2}
227 new Date(e.attr('timestamp')*1000) // {4}
231 $(eNotif.children("note").get().reverse()).each(function(){
233 notification_id = parseInt(e.attr('timestamp'));
234 if (notification_lastitem!== null && notification_id > notification_lastitem) {
235 if (getNotificationPermission()==="granted") {
236 var notification = new Notification(document.title, {
237 body: e.text().replace('→ ','').format(e.attr('name')),
238 icon: e.attr('photo'),
240 notification['url'] = e.attr('href');
241 notification.addEventListener("click", function(ev){
242 window.location = ev.target.url;
248 notification_lastitem = notification_id;
249 localStorage.setItem("notification-lastitem", notification_lastitem)
251 $("img[data-src]", nnm).each(function(i, el){
252 // Add src attribute for images with a data-src attribute
253 // However, don't bother if the data-src attribute is empty, because
254 // an empty "src" tag for an image will cause some browsers
255 // to prefetch the root page of the Friendica hub, which will
256 // unnecessarily load an entire profile/ or network/ page
257 if($(el).data("src") != '') $(el).attr('src', $(el).data("src"));
261 notif = eNotif.attr('count');
263 $("#nav-notifications-linkmenu").addClass("on");
265 $("#nav-notifications-linkmenu").removeClass("on");
267 if(notif == 0) { notif = ''; $('#notify-update').removeClass('show') } else { $('#notify-update').addClass('show') }
268 $('#notify-update').html(notif);
270 var eSysmsg = $(data).find('sysmsgs');
271 eSysmsg.children("notice").each(function(){
272 text = $(this).text();
273 $.jGrowl(text, { sticky: true, theme: 'notice' });
275 eSysmsg.children("info").each(function(){
276 text = $(this).text();
277 $.jGrowl(text, { sticky: false, theme: 'info', life: 5000 });
283 // Allow folks to stop the ajax page updates with the pause/break key
284 $(document).keydown(function(event) {
285 if(event.keyCode == '8') {
286 var target = event.target || event.srcElement;
287 if (!/input|textarea/i.test(target.nodeName)) {
291 if(event.keyCode == '19' || (event.ctrlKey && event.which == '32')) {
292 event.preventDefault();
293 if(stopped == false) {
298 $('#pause').html('<img src="images/pause.gif" alt="pause" style="border: 1px solid black;" />');
312 function NavUpdate() {
315 var pingCmd = 'ping' + ((localUser != 0) ? '?f=&uid=' + localUser : '');
316 $.get(pingCmd,function(data) {
317 $(data).find('result').each(function() {
318 // send nav-update event
319 $('nav').trigger('nav-update', this);
324 if($('#live-network').length) { src = 'network'; liveUpdate(); }
325 if($('#live-profile').length) { src = 'profile'; liveUpdate(); }
326 if($('#live-community').length) { src = 'community'; liveUpdate(); }
327 if($('#live-notes').length) { src = 'notes'; liveUpdate(); }
328 if($('#live-display').length) { src = 'display'; liveUpdate(); }
329 /* if($('#live-display').length) {
332 window.location.href=window.location.href
335 if($('#live-photos').length) {
338 window.location.href=window.location.href
348 timer = setTimeout(NavUpdate,updateInterval);
351 function liveUpdate() {
352 if((src == null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; }
353 if(($('.comment-edit-text-full').length) || (in_progress)) {
355 clearTimeout(livetime);
357 livetime = setTimeout(liveUpdate, 5000);
363 prev = 'live-' + src;
367 if ($(document).scrollTop() == 0)
370 var udargs = ((netargs.length) ? '/' + netargs : '');
371 var update_url = 'update_' + src + udargs + '&p=' + profile_uid + '&page=' + profile_page + '&force=' + ((force_update) ? 1 : 0);
373 $.get(update_url,function(data) {
375 force_update = false;
376 // $('.collapsed-comments',data).each(function() {
377 // var ident = $(this).attr('id');
378 // var is_hidden = $('#' + ident).is(':hidden');
379 // if($('#' + ident).length) {
380 // $('#' + ident).replaceWith($(this));
382 // $('#' + ident).hide();
387 $('.toplevel_item',data).each(function() {
388 var ident = $(this).attr('id');
390 if($('#' + ident).length == 0 && profile_page == 1) {
391 $('img',this).each(function() {
392 $(this).attr('src',$(this).attr('dst'));
394 $('#' + prev).after($(this));
397 // Find out if the hidden comments are open, so we can keep it that way
398 // if a new comment has been posted
399 var id = $('.hide-comments-total', this).attr('id');
400 if(typeof id != 'undefined') {
401 id = id.split('-')[3];
402 var commentsOpen = $("#collapsed-comments-" + id).is(":visible");
405 $('img',this).each(function() {
406 $(this).attr('src',$(this).attr('dst'));
408 //vScroll = $(document).scrollTop();
409 $('html').height($('html').height());
410 $('#' + ident).replaceWith($(this));
412 if(typeof id != 'undefined') {
413 if(commentsOpen) showHideComments(id);
415 $('html').height('auto');
416 //$(document).scrollTop(vScroll);
421 // reset vars for inserting individual items
423 /* prev = 'live-' + src;
425 $('.wall-item-outside-wrapper',data).each(function() {
426 var ident = $(this).attr('id');
428 if($('#' + ident).length == 0 && prev != 'live-' + src) {
429 $('img',this).each(function() {
430 $(this).attr('src',$(this).attr('dst'));
432 $('#' + prev).after($(this));
435 $('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago'));
436 if($('#' + ident + ' ' + '.comment-edit-text-empty').length)
437 $('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
438 $('#' + ident + ' ' + '.hide-comments-total').replaceWith($(this).find('.hide-comments-total'));
439 $('#' + ident + ' ' + '.wall-item-like').replaceWith($(this).find('.wall-item-like'));
440 $('#' + ident + ' ' + '.wall-item-dislike').replaceWith($(this).find('.wall-item-dislike'));
441 $('#' + ident + ' ' + '.my-comment-photo').each(function() {
442 $(this).attr('src',$(this).attr('dst'));
448 $('.like-rotator').hide();
451 $('body').css('cursor', 'auto');
453 /* autocomplete @nicknames */
454 $(".comment-edit-form textarea").contact_autocomplete(baseurl+"/acl");
456 // setup videos, since VideoJS won't take care of any loaded via AJAX
457 if(typeof videojs != 'undefined') videojs.autoSetup();
461 function imgbright(node) {
462 $(node).removeClass("drophide").addClass("drop");
465 function imgdull(node) {
466 $(node).removeClass("drop").addClass("drophide");
469 // Since our ajax calls are asynchronous, we will give a few
470 // seconds for the first ajax call (setting like/dislike), then
471 // run the updater to pick up any changes and display on the page.
472 // The updater will turn any rotators off when it's done.
473 // This function will have returned long before any of these
474 // events have completed and therefore there won't be any
475 // visible feedback that anything changed without all this
476 // trickery. This still could cause confusion if the "like" ajax call
477 // is delayed and NavUpdate runs before it completes.
479 function dolike(ident,verb) {
481 $('#like-rotator-' + ident.toString()).show();
482 $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate );
487 function dosubthread(ident) {
489 $('#like-rotator-' + ident.toString()).show();
490 $.get('subthread/' + ident.toString(), NavUpdate );
495 function dostar(ident) {
496 ident = ident.toString();
497 $('#like-rotator-' + ident).show();
498 $.get('starred/' + ident, function(data) {
499 if(data.match(/1/)) {
500 $('#starred-' + ident).addClass('starred');
501 $('#starred-' + ident).removeClass('unstarred');
502 $('#star-' + ident).addClass('hidden');
503 $('#unstar-' + ident).removeClass('hidden');
506 $('#starred-' + ident).addClass('unstarred');
507 $('#starred-' + ident).removeClass('starred');
508 $('#star-' + ident).removeClass('hidden');
509 $('#unstar-' + ident).addClass('hidden');
511 $('#like-rotator-' + ident).hide();
515 function doignore(ident) {
516 ident = ident.toString();
517 $('#like-rotator-' + ident).show();
518 $.get('ignored/' + ident, function(data) {
519 if(data.match(/1/)) {
520 $('#ignored-' + ident).addClass('ignored');
521 $('#ignored-' + ident).removeClass('unignored');
522 $('#ignore-' + ident).addClass('hidden');
523 $('#unignore-' + ident).removeClass('hidden');
526 $('#ignored-' + ident).addClass('unignored');
527 $('#ignored-' + ident).removeClass('ignored');
528 $('#ignore-' + ident).removeClass('hidden');
529 $('#unignore-' + ident).addClass('hidden');
531 $('#like-rotator-' + ident).hide();
535 function getPosition(e) {
536 var cursor = {x:0, y:0};
537 if ( e.pageX || e.pageY ) {
542 if( e.clientX || e.clientY ) {
543 cursor.x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
544 cursor.y = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
556 var lockvisible = false;
558 function lockview(event,id) {
559 event = event || window.event;
560 cursor = getPosition(event);
566 $.get('lockview/' + id, function(data) {
567 $('#panel').html(data);
568 $('#panel').css({ 'left': cursor.x + 5 , 'top': cursor.y + 5});
574 function lockviewhide() {
579 function post_comment(id) {
582 $('body').css('cursor', 'wait');
583 $("#comment-preview-inp-" + id).val("0");
586 $("#comment-edit-form-" + id).serialize(),
589 $("#comment-edit-wrapper-" + id).hide();
590 $("#comment-edit-text-" + id).val('');
591 var tarea = document.getElementById("comment-edit-text-" + id);
593 commentClose(tarea,id);
594 if(timer) clearTimeout(timer);
595 timer = setTimeout(NavUpdate,10);
599 window.location.href=data.reload;
608 function preview_comment(id) {
609 $("#comment-preview-inp-" + id).val("1");
610 $("#comment-edit-preview-" + id).show();
613 $("#comment-edit-form-" + id).serialize(),
616 $("#comment-edit-preview-" + id).html(data.preview);
617 $("#comment-edit-preview-" + id + " a").click(function() { return false; });
627 function showHideComments(id) {
628 if( $("#collapsed-comments-" + id).is(":visible")) {
629 $("#collapsed-comments-" + id).hide();
630 $("#hide-comments-" + id).html(window.showMore);
633 $("#collapsed-comments-" + id).show();
634 $("#hide-comments-" + id).html(window.showFewer);
640 function preview_post() {
641 $("#jot-preview").val("1");
642 $("#jot-preview-content").show();
643 tinyMCE.triggerSave();
646 $("#profile-jot-form").serialize(),
649 $("#jot-preview-content").html(data.preview);
650 $("#jot-preview-content" + " a").click(function() { return false; });
655 $("#jot-preview").val("0");
661 // unpause auto reloads if they are currently stopped
664 $('#pause').html('');
669 // Converts the binary representation of data to hex
672 // discuss at: http://phpjs.org/functions/bin2hex
673 // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
674 // + bugfixed by: Onno Marsman
675 // + bugfixed by: Linuxworld
676 // * example 1: bin2hex('Kev');
677 // * returns 1: '4b6576'
678 // * example 2: bin2hex(String.fromCharCode(0x00));
680 var v,i, f = 0, a = [];
684 for (i = 0; i<f; i++) {
685 a[i] = s.charCodeAt(i).toString(16).replace(/^([\da-f])$/,"0$1");
691 function groupChangeMember(gid, cid, sec_token) {
692 $('body .fakelink').css('cursor', 'wait');
693 $.get('group/' + gid + '/' + cid + "?t=" + sec_token, function(data) {
694 $('#group-update-wrapper').html(data);
695 $('body .fakelink').css('cursor', 'auto');
699 function profChangeMember(gid,cid) {
700 $('body .fakelink').css('cursor', 'wait');
701 $.get('profperm/' + gid + '/' + cid, function(data) {
702 $('#prof-update-wrapper').html(data);
703 $('body .fakelink').css('cursor', 'auto');
707 function contactgroupChangeMember(gid,cid) {
708 $('body').css('cursor', 'wait');
709 $.get('contactgroup/' + gid + '/' + cid, function(data) {
710 $('body').css('cursor', 'auto');
715 function checkboxhighlight(box) {
716 if($(box).is(':checked')) {
717 $(box).addClass('checkeditem');
720 $(box).removeClass('checkeditem');
724 function notifyMarkAll() {
725 $.get('notify/mark/all', function(data) {
726 if(timer) clearTimeout(timer);
727 timer = setTimeout(NavUpdate,1000);
733 // code from http://www.tinymce.com/wiki.php/How-to_implement_a_custom_file_browser
734 function fcFileBrowser (field_name, url, type, win) {
735 /* TODO: If you work with sessions in PHP and your client doesn't accept cookies you might need to carry
736 the session name and session ID in the request string (can look like this: "?PHPSESSID=88p0n70s9dsknra96qhuk6etm5").
737 These lines of code extract the necessary parameters and add them back to the filebrowser URL again. */
740 var cmsURL = baseurl+"/fbrowser/"+type+"/";
742 tinyMCE.activeEditor.windowManager.open({
744 title : 'File Browser',
745 width : 420, // Your dimensions may differ - toy around with them!
748 inline : "yes", // This parameter only has an effect if you use the inlinepopups plugin!
749 close_previous : "no"
757 function setupFieldRichtext(){
760 mode : "specific_textareas",
761 editor_selector: "fieldRichtext",
762 plugins : "bbcode,paste, inlinepopups",
763 theme_advanced_buttons1 : "bold,italic,underline,undo,redo,link,unlink,image,forecolor,formatselect,code",
764 theme_advanced_buttons2 : "",
765 theme_advanced_buttons3 : "",
766 theme_advanced_toolbar_location : "top",
767 theme_advanced_toolbar_align : "center",
768 theme_advanced_blockformats : "blockquote,code",
769 theme_advanced_resizing : true,
770 paste_text_sticky : true,
771 entity_encoding : "raw",
772 add_unload_trigger : false,
773 remove_linebreaks : false,
774 //force_p_newlines : false,
775 //force_br_newlines : true,
776 forced_root_block : 'div',
778 content_css: baseurl+"/view/custom_tinymce.css",
779 theme_advanced_path : false,
780 file_browser_callback : "fcFileBrowser",
786 * sprintf in javascript
787 * "{0} and {1}".format('zero','uno');
789 String.prototype.format = function() {
790 var formatted = this;
791 for (var i = 0; i < arguments.length; i++) {
792 var regexp = new RegExp('\\{'+i+'\\}', 'gi');
793 formatted = formatted.replace(regexp, arguments[i]);
798 Array.prototype.remove = function(item) {
799 to=undefined; from=this.indexOf(item);
800 var rest = this.slice((to || from) + 1 || this.length);
801 this.length = from < 0 ? this.length + from : from;
802 return this.push.apply(this, rest);
805 function previewTheme(elm) {
806 theme = $(elm).val();
807 $.getJSON('pretheme?f=&theme=' + theme,function(data) {
808 $('#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>');
813 // notification permission settings in localstorage
814 // set by settings page
815 function getNotificationPermission() {
816 if (window["Notification"] === undefined) {
819 if (Notification.permission === 'granted') {
820 var val = localStorage.getItem('notification-permissions');
821 if (val === null) return 'denied';
824 return Notification.permission;
829 * Show a dialog loaded from an url
830 * By defaults this load the url in an iframe in colorbox
831 * Themes can overwrite `show()` function to personalize it
838 * @return object colorbox
840 show : function (url) {
841 var size = Dialog._get_size();
842 return $.colorbox({href: url, iframe:true,innerWidth: size.width+'px',innerHeight: size.height+'px'})
846 * Show the Image browser dialog
849 * @param string id (optional)
852 * The name will be used to build the event name
853 * fired by image browser dialog when the user select
854 * an image. The optional id will be passed as argument
855 * to the event handler
857 doImageBrowser : function (name, id) {
858 var url = Dialog._get_url("image",name,id);
859 return Dialog.show(url);
863 * Show the File browser dialog
866 * @param string id (optional)
869 * The name will be used to build the event name
870 * fired by file browser dialog when the user select
871 * a file. The optional id will be passed as argument
872 * to the event handler
874 doFileBrowser : function (name, id) {
875 var url = Dialog._get_url("file",name,id);
876 return Dialog.show(url);
879 _get_url : function(type, name, id) {
881 if (id !== undefined) hash = hash + "-" + id;
882 return baseurl + "/fbrowser/"+type+"/?mode=minimal#"+hash;
885 _get_size: function() {
887 width: window.innerWidth-50,
888 height: window.innerHeight-100