{"version":3,"file":"tile_fitter.min.js","sources":["https:\/\/kundenportal.comm-unity.at\/course\/format\/tiles\/amd\/src\/tile_fitter.js"],"sourcesContent":["\/\/ This file is part of Moodle - http:\/\/moodle.org\/\n\/\/\n\/\/ Moodle is free software: you can redistribute it and\/or modify\n\/\/ it under the terms of the GNU General Public License as published by\n\/\/ the Free Software Foundation, either version 3 of the License, or\n\/\/ (at your option) any later version.\n\/\/\n\/\/ Moodle is distributed in the hope that it will be useful,\n\/\/ but WITHOUT ANY WARRANTY; without even the implied warranty of\n\/\/ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\/\/ GNU General Public License for more details.\n\/\/\n\/\/ You should have received a copy of the GNU General Public License\n\/\/ along with Moodle. If not, see .\n\n\/**\n * Javascript Module to handle fitting tiles to screen.\n * Called when in non editing mode.\n *\n * @module format_tiles\/tile_fitter\n * @copyright 2019 David Watson {@link http:\/\/evolutioncode.uk}\n * @license http:\/\/www.gnu.org\/copyleft\/gpl.html GNU GPL v3 or later\n * @since Moodle 3.3\n *\/\n\n\/* eslint space-before-function-paren: 0 *\/\n\ndefine([\"jquery\", \"core\/ajax\"], function ($, ajax) {\n \"use strict\";\n\n var reOrgLocked = false;\n var courseId;\n var Selector = {\n PAGE: \"#page\",\n TILE: \".tile\",\n TILEID: \"#tile-\",\n TILE_COLLAPSED: \".tile-collapsed\",\n TILES_OUTER: \".format-tiles.jsenabled #format-tiles-multi-section-page\",\n TILES: \".format-tiles.jsenabled ul.tiles\",\n ACTIVITY: \".activity\",\n SPACER: \".spacer\",\n SECTION_ID: \"#section-\",\n OPEN_SECTION: \".moveablesection:visible\",\n SECTION_ZERO: \"#section-0\",\n CONTENT_SECTIONS: \".moveablesection\"\n };\n\n \/\/ Used to store a delayed AJAX request so we can replace it if user sets again within one second or two.\n var timeoutBeforeResizeAjax = null;\n\n \/\/ If we are in non JS nav mode, we may be on a single section page i.e\/. §ion=xx.\n const isSectionPage = $(Selector.TILES).length === 0;\n\n \/**\n * If we have a single tile on the last row it looks odd.\n * We might want to shrink the tile window down a little to even it out.\n * So we work out how many per row would be optimal, and shrink the window accordingly.\n * @see \\format_tiles\\local\\util::width_template_data() for more information.\n * @return {Promise}\n *\/\n var resizeTilesDivWidth = function() {\n const winWidth = $(window).width();\n \/\/ Create a new Deferred.\n const dfd = new $.Deferred();\n if (isSectionPage) {\n \/\/ No tile fitting on single section page.\n dfd.resolve();\n }\n const tiles = $(Selector.TILES);\n const tilesOuter = $(Selector.TILES_OUTER);\n const TILE_WIDTHS = {\n standard: 260,\n min: 225,\n mobileMin: 160\n };\n try {\n var tilesParentWidth = tilesOuter.parent().innerWidth();\n var firstTile = $(tiles.find(Selector.TILE)[0]);\n \/\/ Get the width of one tile.\n var oneTileWidth = firstTile.width()\n ? firstTile.width()\n : TILE_WIDTHS.standard; \/\/ Default standard as min tile width if we can't get the actual width.\n var tileMargin = 14; \/\/ Margin 7px either side.\n oneTileWidth = oneTileWidth + tileMargin;\n var resizeWidth = \"inherit\";\n \/\/ Skip if window is only 2 or smaller than 2 tiles wide already.\n \/\/ This ensures that we don't crush the tiles into the centre (i.e. we use at least x% of width).\n var maxPossibleTilesPerRow = Math.floor(tilesParentWidth \/ TILE_WIDTHS.min);\n var tileCount = ($(Selector.TILE).not(Selector.SPACER).length); \/\/ How many tiles in this course.\n if (tilesParentWidth < TILE_WIDTHS.mobileMin * 2) {\n \/\/ Only space for one tile - don't resize to save space.\n dfd.reject(\"Too narrow to resize\");\n } else if (tileCount <= 3 && tilesParentWidth > tileCount * TILE_WIDTHS.mobileMin) {\n resizeWidth = TILE_WIDTHS.standard * 4;\n } else if (tilesParentWidth < TILE_WIDTHS.min * 3) {\n resizeWidth = (TILE_WIDTHS.standard - tileMargin) * 2;\n } else if (maxPossibleTilesPerRow < 4) {\n \/\/ Here we set the max width to the space we have available, so that tiles are centred.\n resizeWidth = TILE_WIDTHS.standard * maxPossibleTilesPerRow;\n } else {\n \/\/ Make a range of numbers in an array. e.g. range(2,5) = [2, 3, 4, 5].\n var range = function (start, end) {\n var res = [];\n for (start; start <= end; start += 1) {\n res.push(start);\n }\n return res;\n };\n\n \/\/ How many tiles per row could we fit on the screen, if we put in as many as possible?\n var rowMaxCount = Math.min(\n Math.floor(tilesParentWidth \/ oneTileWidth),\n tileCount\n );\n \/\/ If we'd have a single row of more than 5 tiles, split it into 2.\n if (tileCount <= rowMaxCount && tileCount > 5) {\n resizeWidth = (Math.floor(tileCount \/ 2) + 1) * oneTileWidth;\n } else if (rowMaxCount > 3 && tileCount \/ rowMaxCount <= 3) {\n \/\/ If we can fit 3 tiles per row max, we don't restrict to 2, as this makes content window unnecessarily small.\n \/\/ Also if we have 3 or more rows (3 or more) we don't bother restricting as the last row is not so noticeable.\n\n \/\/ How many tiles per row do we want as a minimum (in order to occupy a reasonable amount of width)?\n var rowMinCount = Math.floor(tilesParentWidth \/ oneTileWidth);\n\n \/\/ What are the possibilities for tiles per row? Then we can look at which we want.\n var possibleRowCounts = range(rowMinCount, rowMaxCount).reverse(); \/\/ Something like [6, 5, 4, 3].\n\n \/\/ For each possibility, how many tiles would that leave on the last row?\n var lastRowRemainderTiles = possibleRowCounts.map(function (num) {\n return tileCount % num;\n });\n if (lastRowRemainderTiles.indexOf(0) !== -1) {\n \/\/ We have the option of having a *full* last row so take that.\n resizeWidth = oneTileWidth * possibleRowCounts[lastRowRemainderTiles.indexOf(0)];\n } else if (tileCount < rowMinCount) {\n resizeWidth = tileCount * oneTileWidth;\n } else {\n \/\/ Otherwise make the last row as full as possible (few tiles on last row looks worse).\n resizeWidth = oneTileWidth * possibleRowCounts[lastRowRemainderTiles.indexOf(\n Math.max.apply(null, lastRowRemainderTiles)\n )];\n }\n } else {\n \/\/ In these cases, we don't artificially narrow the view, but we do put a max width on of the existing width.\n \/\/ This is so that, when sections open under the tiles, they do not stick out with extra width beyond the tiles.\n \/\/ It also allows the auto margin to centre the tiles.\n resizeWidth = rowMaxCount * oneTileWidth;\n }\n }\n\n \/\/ If we already have the desired width, nothing to do here so skip it.\n \/\/ We use the width on the outer element tilesOuter so as to restrict width of section zero as well.\n var existingWidth = parseInt(tilesOuter.css(\"max-width\").replace(\"px\", \"\"));\n if (Math.abs(resizeWidth - existingWidth) < 50) {\n \/\/ Nothing to do.\n dfd.resolve();\n } else {\n \/\/ We set session width at the server so that next time it is rendered with PHP, it has the correct width already.\n var resizeTime = 500;\n const openSection = $(Selector.OPEN_SECTION);\n openSection.css('display', 'none');\n tilesOuter.css(\"max-width\", winWidth).animate({\"max-width\": resizeWidth}, resizeTime, \"swing\",\n function() {\n dfd.resolve();\n $(Selector.CONTENT_SECTIONS).css({\"max-width\": resizeWidth});\n if (openSection) {\n openSection.css('display', 'block');\n }\n }\n );\n }\n\n \/\/ If we already have scheduled AJAX request to set width, cancel it and replace it with a more up to date one.\n \/\/ We need not set the width on the server very often - once every 3 seconds is plenty.\n if (timeoutBeforeResizeAjax) {\n clearTimeout(timeoutBeforeResizeAjax);\n }\n timeoutBeforeResizeAjax = setTimeout(function () {\n\n ajax.call([{\n methodname: \"format_tiles_set_session_width\",\n args: {courseid: courseId, width: Math.floor(resizeWidth)}\n }]);\n }, 1000);\n } catch (err) {\n \/\/ Unset widths as something went wrong.\n tilesOuter.css(\"max-width\", winWidth).animate({\"max-width\": \"100%\"}, 500, \"swing\");\n ajax.call([{\n methodname: \"format_tiles_set_session_width\",\n args: {courseid: courseId, width: 0}\n }]);\n dfd.reject(\"Failed to resize\");\n }\n return dfd.promise();\n };\n\n var organiser = {\n \/**\n * Content sections need to be displayed after the row in which the tile to which they relate appears\n * e.g. we have a row of tiles 1-3 and then after that we need to have the content divs which contain the\n * related content. As this depends on device window size, we calculate this on page load and after window changes\n * e.g. navbar button at side is pressed or browser window is resized\n * @returns {Array} of rows, with the tile they need to be displayed after, and the sections in each row\n *\/\n getContentSectionPositions: function () {\n var rows = [];\n var currentSectionId;\n var previousTile;\n var openSections = $(Selector.OPEN_SECTION);\n \/\/ Hide these for an instant while we do the calculations.\n openSections.css(\"display\", \"none\");\n\n var maxTilesPerRow = 1;\n var thisRowCount = 0;\n var allTiles = $(Selector.TILES).children(Selector.TILE).not(Selector.TILE_COLLAPSED).not(\".spacer\");\n if (allTiles.length === 0) {\n \/\/ Course has no sections.\n return [];\n }\n allTiles.each(function (index, tile) {\n currentSectionId = $(tile).data(\"section\");\n var maxVerticalPositionDifference = 100;\n if (currentSectionId) {\n if (index === 0) {\n \/\/ We are on the first tile, so append a row and add tile ID to it.\n thisRowCount = 1;\n } else if (Math.abs($(tile).position().top - $(previousTile).position().top) <= maxVerticalPositionDifference) {\n thisRowCount += 1;\n \/\/ We are on the same row as the previous tile.\n \/\/ maxVerticalPositionDifference is because tiles on same row may have different vertical positions.\n \/\/ E.g. if one of the is in a hover state. If they are within 100 px max they must be on same row.\n } else {\n \/\/ On a new row.\n thisRowCount = 0;\n }\n if (thisRowCount > maxTilesPerRow) {\n maxTilesPerRow = thisRowCount;\n }\n previousTile = tile;\n }\n });\n openSections.css(\"display\", \"block\");\n\n \/\/ Now allocate rows of maxTilesPerRow each until we run out of tiles.\n allTiles.each(function (index, tile) {\n currentSectionId = $(tile).data(\"section\");\n if (rows.length === 0 || rows[rows.length - 1].sections.length >= maxTilesPerRow) {\n if (rows.length >= 1) {\n \/\/ Update the display after tag on previous row.\n rows[rows.length - 1].displayAfterTile =\n rows[rows.length - 1].sections[(rows[rows.length - 1].sections).length - 1];\n }\n \/\/ Start a new row.\n rows.push({\n displayAfterTile: \"\",\n sections: [currentSectionId]\n });\n } else {\n rows[rows.length - 1].sections.push(currentSectionId);\n }\n });\n rows[rows.length - 1].displayAfterTile =\n rows[rows.length - 1].sections[(rows[rows.length - 1].sections).length - 1];\n return rows;\n },\n\n \/**\n * Move content sections to appear under the correct tiles\n * so that when a tile is clicked, they expand under it\n * @param {Array} positionData\n * @param {function} callbacks\n *\/\n moveContentSectionsToPlaces: function (positionData, callbacks) {\n positionData.forEach(function (row) {\n row.sections.forEach(function (contentSection) {\n if (row.displayAfterTile === positionData[positionData.length - 1].displayAfterTile) {\n $(Selector.SECTION_ID + contentSection).detach().insertAfter($(\"ul.tiles .tile\").last());\n } else {\n $(Selector.SECTION_ID + contentSection).detach().insertAfter($(\"#tile-\" + row.displayAfterTile));\n }\n });\n });\n callbacks.forEach(function(func) {\n if (typeof func === \"function\") {\n func();\n }\n });\n },\n\n \/**\n * Re-organise the sections so that they are in the correct order\n * e.g. content section 3 is on the row below tile 3, so that\n * when tile 3 is clicked, content section 3 opens directly under it\n * @return {Promise}\n *\/\n runReOrg: function () {\n \/\/ Create a new Deferred.\n var dfd = new $.Deferred();\n if (reOrgLocked === true) {\n \/\/ Avoid repeated re-organisations - one at a time.\n dfd.reject(\"Re-org locked\");\n }\n reOrgLocked = true;\n\n organiser.moveContentSectionsToPlaces(\n organiser.getContentSectionPositions(),\n [\n function() {\n $(\"body\").removeClass(\"modal-open\");\n dfd.resolve(\"Finished organising tiles\");\n reOrgLocked = false;\n }\n ]\n );\n return dfd.promise();\n }\n };\n\n \/\/ We no longer set observers for size changes here as this appears in course.js in const resizeObserver.\n\n \/**\n * On initial page load, we need to unhide the tiles. They will have been hidden from PHP if we are using JS.\n * This is to cover the initial setting up of div width (i.e. allow us time to get screen width and set up).\n *\/\n const unHideTiles = function() {\n $(Selector.TILES_OUTER).animate({opacity: \"1\"}, \"fast\");\n $(Selector.SECTION_ZERO).animate({opacity: \"1\"}, \"fast\");\n $(\"#page-loading-icon\").fadeOut(500).remove();\n };\n\n return {\n init: function(courseIdInit, sectionOpen, fitTilesToWidth, isEditing) {\n courseId = courseIdInit;\n $(document).ready(function() {\n if (!isSectionPage) {\n \/\/ When we first load the page we want to move the tile contents divs.\n \/\/ Put them in the correct rows according to which row of tiles they relate to.\n \/\/ Only then do we re-open the last section the user had open.\n var organiseAndRevealTiles = function () {\n organiser.runReOrg().done(function() {\n if (sectionOpen && $(Selector.OPEN_SECTION).length === 0) {\n \/\/ Now open the tile user was on previously (if any).\n $(Selector.TILEID + sectionOpen).click();\n }\n unHideTiles();\n });\n };\n if (fitTilesToWidth && !isEditing) {\n \/\/ If we have a single tile on the last row it looks odd so resize window.\n resizeTilesDivWidth().done(function() {\n organiseAndRevealTiles();\n }).fail(function() {\n \/\/ If resize is rejected e.g. as screen is to narrow e.g. mobile.\n organiseAndRevealTiles();\n });\n } else {\n organiseAndRevealTiles();\n }\n }\n });\n },\n resizeTilesDivWidth: function() {\n return resizeTilesDivWidth();\n },\n runReOrg: function () {\n return organiser.runReOrg();\n }\n };\n});"],"names":["define","$","ajax","courseId","reOrgLocked","Selector","timeoutBeforeResizeAjax","isSectionPage","length","resizeTilesDivWidth","winWidth","window","width","dfd","Deferred","resolve","tiles","tilesOuter","TILE_WIDTHS","tilesParentWidth","parent","innerWidth","firstTile","find","oneTileWidth","resizeWidth","maxPossibleTilesPerRow","Math","floor","tileCount","not","reject","rowMaxCount","min","rowMinCount","possibleRowCounts","start","end","res","push","range","reverse","lastRowRemainderTiles","map","num","indexOf","max","apply","existingWidth","parseInt","css","replace","abs","openSection","animate","clearTimeout","setTimeout","call","methodname","args","courseid","err","promise","organiser","getContentSectionPositions","currentSectionId","previousTile","rows","openSections","maxTilesPerRow","thisRowCount","allTiles","children","each","index","tile","data","position","top","sections","displayAfterTile","moveContentSectionsToPlaces","positionData","callbacks","forEach","row","contentSection","detach","insertAfter","last","func","runReOrg","removeClass","init","courseIdInit","sectionOpen","fitTilesToWidth","isEditing","document","ready","organiseAndRevealTiles","done","click","opacity","fadeOut","remove","fail"],"mappings":"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\/D\/E,EAAEI,oBAAsBiF,gBAAgBC,SAASC,YAAYvF,EAAE,kBAAkBwF,QAEjFxF,EAAEI,oBAAsBiF,gBAAgBC,SAASC,YAAYvF,EAAE,SAAWoF,IAAIL,yBAI1FG,UAAUC,SAAQ,SAASM,MACH,mBAATA,MACPA,WAWZC,SAAU,eAEF9E,IAAM,IAAIZ,EAAEa,gBACI,IAAhBV,aAEAS,IAAIkB,OAAO,iBAEf3B,aAAc,EAEd2D,UAAUkB,4BACNlB,UAAUC,6BACV,CACI,WACI\/D,EAAE,QAAQ2F,YAAY,cACtB\/E,IAAIE,QAAQ,6BACZX,aAAc,KAInBS,IAAIiD,kBAgBZ,CACH+B,KAAM,SAASC,aAAcC,YAAaC,gBAAiBC,WACvD9F,SAAW2F,aACX7F,EAAEiG,UAAUC,OAAM,eACT5F,cAAe,KAIZ6F,uBAAyB,WACzBrC,UAAU4B,WAAWU,MAAK,WAClBN,aAAmD,IAApC9F,EAAEI,uBAAuBG,QAExCP,EAAEI,gBAAkB0F,aAAaO,QAjBzDrG,EAAEI,sBAAsBiD,QAAQ,CAACiD,QAAS,KAAM,QAChDtG,EAAEI,uBAAuBiD,QAAQ,CAACiD,QAAS,KAAM,QACjDtG,EAAE,sBAAsBuG,QAAQ,KAAKC,aAoBrBT,kBAAoBC,UAEpBxF,sBAAsB4F,MAAK,WACvBD,4BACDM,MAAK,WAEJN,4BAGJA,8BAKhB3F,oBAAqB,kBACVA,uBAEXkF,SAAU,kBACC5B,UAAU4B"}