X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=view%2Ftheme%2Ffrio%2Fjs%2Ftheme.js;h=a8787a6eb5dced342fee554f28e0c3f198a75980;hb=20a2918bdaaa9108765228a9cabdab1c52de329e;hp=c149271804fe377f25a3ac1be5cc8b187162f276;hpb=2092fa03b2070a24168520f42d8d65932c3d67f2;p=friendica.git diff --git a/view/theme/frio/js/theme.js b/view/theme/frio/js/theme.js index c149271804..a8787a6eb5 100644 --- a/view/theme/frio/js/theme.js +++ b/view/theme/frio/js/theme.js @@ -10,7 +10,7 @@ $(document).ready(function(){ $("#back-to-top").fadeOut(); } }); - + // scroll body to 0px on click $("#back-to-top").click(function () { $("body,html").animate({ @@ -40,7 +40,7 @@ $(document).ready(function(){ $(".field.select > select, .field.custom > select").addClass("form-control"); // move the tabbar to the second nav bar - $("section ul.tabbar").first().appendTo("#topbar-second > .container > #tabmenu"); + $("section .tabbar-wrapper").first().appendTo("#topbar-second > .container > #tabmenu"); // add mask css url to the logo-img container // @@ -54,7 +54,7 @@ $(document).ready(function(){ } // make responsive tabmenu with flexmenu.js - // the menupoints which doesn't fit in the second nav bar will moved to a + // the menupoints which doesn't fit in the second nav bar will moved to a // dropdown menu. Look at common_tabs.tpl $("ul.tabs.flex-nav").flexMenu({ 'cutoff': 2, @@ -82,17 +82,17 @@ $(document).ready(function(){ return false; } }); - - if(checked == true) { - $("a#item-delete-selected").fadeTo(400, 1); - $("a#item-delete-selected").show(); + + if(checked) { + $("#item-delete-selected").fadeTo(400, 1); + $("#item-delete-selected").show(); } else { - $("a#item-delete-selected").fadeTo(400, 0, function(){ - $("a#item-delete-selected").hide(); - }); + $("#item-delete-selected").fadeTo(400, 0, function(){ + $("#item-delete-selected").hide(); + }); } }); - + //$('ul.flex-nav').flexMenu(); // initialize the bootstrap tooltips @@ -128,7 +128,7 @@ $(document).ready(function(){ // append the new heading to the navbar $("#topbar-second > .container > #tabmenu").append(newText); - // try to get the value of the original search input to insert it + // try to get the value of the original search input to insert it // as value in the nav-search-input var searchValue = $("#search-wrapper .form-group-search input").val(); @@ -208,11 +208,8 @@ $(document).ready(function(){ // Dropdown menus with the class "dropdown-head" will display the active tab // as button text - $("body").on('click', '.dropdown-head .dropdown-menu li a', function(){ - $(this).closest(".dropdown").find('.btn').html($(this).text() + ' '); - $(this).closest(".dropdown").find('.btn').val($(this).data('value')); - $(this).closest("ul").children("li").show(); - $(this).parent("li").hide(); + $("body").on('click', '.dropdown-head .dropdown-menu li a, .dropdown-head .dropdown-menu li button', function(){ + toggleDropdownText(this); }); /* setup onoff widgets */ @@ -256,40 +253,112 @@ $(document).ready(function(){ input.val(val); }); + // Set the padding for input elements with inline buttons + // + // In Frio we use some input elements where the submit button is visually + // inside the the input field (through css). We need to set a padding-right + // to the input element where the padding value would be at least the width + // of the button. Otherwise long user input would be invisible because it is + // behind the button. + $("body").on('click', '.form-group-search > input', function() { + // Get the width of the button (if the button isn't available + // buttonWidth will be null + var buttonWidth = $(this).next('.form-button-search').outerWidth(); + + if (buttonWidth) { + // Take the width of the button and ad 5px + var newWidth = buttonWidth + 5; + // Set the padding of the input element according + // to the width of the button + $(this).css('padding-right', newWidth); + } + + }); + + /* + * This event handler hides all comment UI when the user clicks anywhere on the page + * It ensures that we aren't closing the current comment box + * + * We are making an exception for buttons because of a race condition with the + * comment opening button that results in an already closed comment UI. + */ + $(document).on('click', function(event) { + if (event.target.type === 'button') { + return true; + } + + var $dontclosethis = $(event.target).closest('.wall-item-comment-wrapper').find('.comment-edit-form'); + $('.wall-item-comment-wrapper .comment-edit-submit-wrapper:visible').each(function() { + var $parent = $(this).parent('.comment-edit-form'); + var itemId = $parent.data('itemId'); + + if ($dontclosethis[0] != $parent[0]) { + var textarea = $parent.find('textarea').get(0) + + commentCloseUI(textarea, itemId); + } + }); + }); + + // Customize some elements when the app is used in standalone mode on Android + if (window.matchMedia('(display-mode: standalone)').matches) { + // Open links to source outside of the webview + $('body').on('click', '.plink', function (e) { + $(e.target).attr('target', '_blank'); + }); + } + + /* + * This event listeners ensures that the textarea size is updated event if the + * value is changed externally (textcomplete, insertFormatting, fbrowser...) + */ + $(document).on('change', 'textarea', function(event) { + autosize.update(event.target); + }); + + /* + * Sticky aside on page scroll + * We enable the sticky aside only when window is wider than + * 976px - which is the maximum width where the aside is shown in + * mobile style - because on chrome-based browsers (desktop and + * android) the sticky plugin in mobile style causes the browser to + * scroll back to top the main content, making it impossible + * to navigate. + * A side effect is that the sitky aside isn't really responsive, + * since is enabled or not at page loading time. + */ + if ($(window).width() > 976) { + $("aside").stick_in_parent({ + offset_top: 100, // px, header + tab bar + spacing + recalc_every: 10 + }); + // recalculate sticky aside on clicks on elements + // this handle height changes on expanding submenus + $("aside").on("click", "a", function(){ + $(document.body).trigger("sticky_kit:recalc"); + }); + } + + /* + * Add or remove "aside-out" class to body tag + * when the mobile aside is shown or hidden. + * The class is used in css to disable scroll in page when the aside + * is shown. + */ + $("aside") + .on("shown.bs.offcanvas", function() { + $("body").addClass("aside-out"); + }) + .on("hidden.bs.offcanvas", function() { + $("body").removeClass("aside-out"); + }); + + // Event listener for 'Show & hide event map' button in the network stream. + $("body").on("click", ".event-map-btn", function() { + showHideEventMap(this); + }); + }); -//function commentOpenUI(obj, id) { -// $(document).unbind( "click.commentOpen", handler ); -// -// var handler = function() { -// if(obj.value == '{{$comment}}') { -// obj.value = ''; -// $("#comment-edit-text-" + id).addClass("comment-edit-text-full").removeClass("comment-edit-text-empty"); -// // Choose an arbitrary tab index that's greater than what we're using in jot (3 of them) -// // The submit button gets tabindex + 1 -// $("#comment-edit-text-" + id).attr('tabindex','9'); -// $("#comment-edit-submit-" + id).attr('tabindex','10'); -// $("#comment-edit-submit-wrapper-" + id).show(); -// } -// }; -// -// $(document).bind( "click.commentOpen", handler ); -//} -// -//function commentCloseUI(obj, id) { -// $(document).unbind( "click.commentClose", handler ); -// -// var handler = function() { -// if(obj.value === '') { -// obj.value = '{{$comment}}'; -// $("#comment-edit-text-" + id).removeClass("comment-edit-text-full").addClass("comment-edit-text-empty"); -// $("#comment-edit-text-" + id).removeAttr('tabindex'); -// $("#comment-edit-submit-" + id).removeAttr('tabindex'); -// $("#comment-edit-submit-wrapper-" + id).hide(); -// } -// }; -// -// $(document).bind( "click.commentClose", handler ); -//} function openClose(theID) { var elem = document.getElementById(theID); @@ -311,7 +380,6 @@ function showHide(theID) { } } - function showHideComments(id) { if( $('#collapsed-comments-' + id).is(':visible')) { $('#collapsed-comments-' + id).slideUp(); @@ -325,6 +393,37 @@ function showHideComments(id) { } } +// Show & hide event map in the network stream by button click. +function showHideEventMap(elm) { + // Get the id of the map element - it should be provided through + // the atribute "data-map-id". + var mapID = elm.getAttribute('data-map-id'); + + // Get translation labels. + var mapshow = elm.getAttribute('data-show-label'); + var maphide = elm.getAttribute('data-hide-label'); + + // Change the button labels. + if (elm.innerText == mapshow) { + $('#' + elm.id).text(maphide); + } else { + $('#' + elm.id).text(mapshow); + } + // Because maps are iframe elements, we cant hide it through css (display: none). + // We solve this issue by putting the map outside the screen with css. + // So the first time the 'Show map' button is pressed we move the map + // element into the screen area. + var mappos = $('#' + mapID).css('position'); + + if (mappos === 'absolute') { + $('#' + mapID).hide(); + $('#' + mapID).css({position: 'relative', left: 'auto', top: 'auto'}); + openClose(mapID); + } else { + openClose(mapID); + } + return false; +} function justifyPhotos() { justifiedGalleryActive = true; @@ -421,28 +520,34 @@ function filter_replace(item) { return item.name; } -(function( $ ) { +(function($) { $.fn.contact_filter = function(backend_url, typ, autosubmit, onselect) { - if(typeof typ === 'undefined') typ = ''; - if(typeof autosubmit === 'undefined') autosubmit = false; + if (typeof typ === 'undefined') { + typ = ''; + } + + if (typeof autosubmit === 'undefined') { + autosubmit = false; + } // Autocomplete contacts contacts = { match: /(^)([^\n]+)$/, index: 2, - search: function(term, callback) { contact_search(term, callback, backend_url, typ); }, + search: function(term, callback) {contact_search(term, callback, backend_url, typ);}, replace: filter_replace, - template: contact_filter, + template: contact_filter }; this.attr('autocomplete','off'); var a = this.textcomplete([contacts], {className:'accontacts', appendTo: '#contact-list'}); - a.on('textComplete:select', function(e, value, strategy) { $(".dropdown-menu.textcomplete-dropdown.media-list").show(); }); + a.on('textComplete:select', function(e, value, strategy) { + $(".dropdown-menu.textcomplete-dropdown.media-list").show(); + }); }; })( jQuery ); - // current time in milliseconds, to send each request to make sure // we 're not getting 304 response function timeNow() { @@ -583,31 +688,38 @@ String.prototype.rtrim = function() { return trimmed; }; -// Scroll to a specific item and highlight it -// Note: jquery.color.js is needed -function scrollToItem(itemID) { - if( typeof itemID === "undefined") +/** + * Scroll the screen to the item element whose id is provided, then highlights it + * + * Note: jquery.color.js is required + * + * @param {string} elementId The item element id + * @returns {undefined} + */ +function scrollToItem(elementId) { + if (typeof elementId === "undefined") { return; + } - var elm = $('#'+itemID); + var $el = $(document.getElementById(elementId)); // Test if the Item exists - if(!elm.length) + if (!$el.length) { return; + } // Define the colors which are used for highlighting var colWhite = {backgroundColor:'#F5F5F5'}; var colShiny = {backgroundColor:'#FFF176'}; - // Get the Item Position (we need to substract 100 to match - // correct position - var itemPos = $(elm).offset().top - 100; + // Get the Item Position (we need to substract 100 to match correct position + var itemPos = $el.offset().top - 100; // Scroll to the DIV with the ID (GUID) $('html, body').animate({ scrollTop: itemPos }, 400, function() { // Highlight post/commenent with ID (GUID) - $(elm).animate(colWhite, 1000).animate(colShiny).animate(colWhite, 600); + $el.animate(colWhite, 1000).animate(colShiny).animate(colWhite, 600); }); } @@ -620,3 +732,89 @@ function htmlToText(htmlString) { return text; } + +/** + * Sends a /like API call and updates the display of the relevant action button + * before the update reloads the item. + * + * @param {string} ident The id of the relevant item + * @param {string} verb The verb of the action + * @returns {undefined} + */ +function doLikeAction(ident, verb) { + unpause(); + + if (verb.indexOf('attend') === 0) { + $('.item-' + ident + ' .button-event:not(#' + verb + '-' + ident + ')').removeClass('active'); + } + $('#' + verb + '-' + ident).toggleClass('active'); + $('#like-rotator-' + ident.toString()).show(); + $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate ); + liking = 1; + force_update = true; + update_item = ident.toString(); +} + +// Decodes a hexadecimally encoded binary string +function hex2bin (s) { + // discuss at: http://locutus.io/php/hex2bin/ + // original by: Dumitru Uzun (http://duzun.me) + // example 1: hex2bin('44696d61') + // returns 1: 'Dima' + // example 2: hex2bin('00') + // returns 2: '\x00' + // example 3: hex2bin('2f1q') + // returns 3: false + var ret = []; + var i = 0; + var l; + s += ''; + + for (l = s.length; i < l; i += 2) { + var c = parseInt(s.substr(i, 1), 16); + var k = parseInt(s.substr(i + 1, 1), 16); + if (isNaN(c) || isNaN(k)) { + return false; + } + ret.push((c << 4) | k); + } + return String.fromCharCode.apply(String, ret); +} + +// Convert binary data into hexadecimal representation +function bin2hex (s) { + // From: http://phpjs.org/functions + // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // + bugfixed by: Onno Marsman + // + bugfixed by: Linuxworld + // + improved by: ntoniazzi (http://phpjs.org/functions/bin2hex:361#comment_177616) + // * example 1: bin2hex('Kev'); + // * returns 1: '4b6576' + // * example 2: bin2hex(String.fromCharCode(0x00)); + // * returns 2: '00' + + var i, l, o = "", n; + + s += ""; + + for (i = 0, l = s.length; i < l; i++) { + n = s.charCodeAt(i).toString(16); + o += n.length < 2 ? "0" + n : n; + } + + return o; +} + +// Dropdown menus with the class "dropdown-head" will display the active tab +// as button text +function toggleDropdownText(elm) { + $(elm).closest(".dropdown").find('.btn').html($(elm).text() + ' '); + $(elm).closest(".dropdown").find('.btn').val($(elm).data('value')); + $(elm).closest("ul").children("li").show(); + $(elm).parent("li").hide(); +} + +// Check if element does have a specific class +function hasClass(elem, cls) { + return (" " + elem.className + " " ).indexOf( " "+cls+" " ) > -1; +}