diff --git a/IMATTC.user.js b/IMATTC.user.js index 16f6705..87b2b58 100644 --- a/IMATTC.user.js +++ b/IMATTC.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name IMATTC -// @version 1.4.2 +// @version 1.5.1 // @description A usability overhaul for the Ingress Mission Authoring Tool // @author @Chyld314 // @match https://mission-author-dot-betaspike.appspot.com/ @@ -29,97 +29,97 @@ $(function() { //Build CSS rules var newCssRules = ""; + + ".navbar-my-missions {cursor: pointer;}" + + ".list > .bordered-panel {padding: 15px;}" + + ".list .missions-list,.missions-list .panel-body .row {display: flex;flex-wrap: wrap;}" + + ".list .create-mission-button {margin: 0 5px;float: none!important;display: inline-block;}" + + ".missions-list, .name-view .bordered-panel, .type-view .bordered-panel {opacity: 0; transition: opacity 0.5s}" + + ".missions-list.ready, .name-view .bordered-panel.ready, .type-view .bordered-panel.ready {opacity:1}" + + ".missions-list .mission {border-width: 2px; margin: 10px 0 0; position: relative; padding: 5px; display: block;}" + + ".list .mission .action-button {width: 100%; min-width: initial; max-width: initial;}" + + ".mission-header-container {display: flex; align-items: stretch;}" + + ".mission-header-container div:nth-of-type(1){padding-right: 5px; width: 60px}" + + ".mission-header-container div:nth-of-type(2){width: calc(100% - 115px)}" + + ".mission-header-container div:nth-of-type(3){padding-left: 5px; width: 45px}" + + ".button, button {background-image: none;}" + + ".mission .name.glyphicon {font-size: 40px;}" + + ".mission .name:not(.glyphicon) {text-align: center; display: block;}" + + ".mission table {margin: 5px 0 10px;}" + + ".missions-list .panel-default { border-color: #5afbea; background-color: black; border-radius: 0;}" + + ".missions-list .panel-default>.panel-heading {color: #5afbea; background: #1f4549; border-radius: 0;}" + + ".missions-list .panel-default>.panel-heading a:hover {color: #5afbea;}" + + ".missions-list .panel-default>.panel-heading+.panel-collapse>.panel-body {border-top-color: black; padding-top: 0;}" + + ".missions-list .panel-heading a:after { font-family: 'Glyphicons Halflings'; content: '\\e114'; float: right; color: 5afbea; position: relative; left: 10px; }" + + ".missions-list .panel-heading h4.collapsed a:after {content: '\\e080'; }" + + ".modal {color: black;}" + + ".banner-preview .modal-body {background-color: #222;}" + + ".banner-preview .row {display: flex; flex-direction: row-reverse; flex-wrap:wrap-reverse!important}" + + ".banner-preview img {border-radius: 50%;border: 3px solid goldenrod;}" + + ".banner-preview .col-xs-2 {padding-bottom: 15px;}"; + + newCssRules += ".mission-list-item-published {background-image: none; background: #001a00; border-color: darkgreen;color: lightgreen;}" + + ".list .mission .mission-title-published {color: lightgreen;}" + + ".mission-list-item-published .table-bordered * {border-color: lightgreen;}" + + ".mission-list-item-published .button {color: lightgreen; border-color: lightgreen; background-color: #004d00;}" + + ".mission-list-item-published .button:hover {background-color: #003300;}" + + ".mission-list-item-published .button .caret {border-bottom-color: lightgreen;}"; + + newCssRules += ".mission-list-item-draft {background-image: none; background-color: #170703; border-color: #a42e12;color: #f7ba5f;}" + + ".list .mission .mission-title-draft {color: #f7ba5f;}" + + ".mission-list-item-draft .table-bordered * {border-color: #f7ba5f;}" + + ".mission-list-item-draft .button {color: #f7ba5f; border-color: #f7ba5f; background-color: #8a280f;}" + + ".mission-list-item-draft .button:hover {background-color: #73210d;}" + + ".mission-list-item-draft .button .caret {border-bottom-color: #f7ba5f;}"; + + newCssRules += ".mission-list-item-draft_of_published_mission {background-image: none; background-color: #1a1a00; border-color: olive;color: greenyellow;}" + + ".list .mission .mission-title-draft_of_published_mission {color: greenyellow;}" + + ".mission-list-item-draft_of_published_mission .table-bordered * {border-color: greenyellow;}" + + ".mission-list-item-draft_of_published_mission .button {color: greenyellow; border-color: greenyellow; background-color: #666600;}" + + ".mission-list-item-draft_of_published_mission .button:hover {background-color: #4d4d00;}" + + ".mission-list-item-draft_of_published_mission .button .caret {border-bottom-color: greenyellow;}"; + + newCssRules += ".mission-list-item-submitted {background-image: none; background-color: #181201; border-color: darkgoldenrod;color: gold;}" + + ".list .mission .mission-title-submitted {color: gold;}" + + ".mission-list-item-submitted .table-bordered * {border-color: gold;}" + + ".mission-list-item-submitted .button {color: gold; border-color: gold; background-color: #916a08;}" + + ".mission-list-item-submitted .button:hover {background-color: #785807;}" + + ".mission-list-item-submitted .button .caret {border-bottom-color: gold;}"; + + newCssRules += ".mission-list-item-disabled {background-image: none; background-color: #0d0d0d; border-color: #6b6b6b; color: red;}" + + ".list .mission .mission-title-disabled {color: red;}" + + ".mission-list-item-disabled .table-bordered * {border-color: red;}" + + ".mission-list-item-disabled .button {color: red; border-color: red; background-color: #595959;}" + + ".mission-list-item-disabled .button:hover {background-color: #4d4d4d;}" + + ".mission-list-item-disabled .button .caret {border-bottom-color: red;}"; + + newCssRules += ".mission-list-item-submitted_and_published {background-image: none; background-color: #0f1405; border-color: olivedrab;color: springgreen;}" + + ".list .mission .mission-title-submitted_and_published {color: springgreen;}" + + ".mission-list-item-submitted_and_published .table-bordered * {border-color: springgreen;}" + + ".mission-list-item-submitted_and_published .button {color: springgreen; border-color: springgreen; background-color: #5c7a1f;}" + + ".mission-list-item-submitted_and_published .button:hover {background-color: #4d6619;}" + + ".mission-list-item-submitted_and_published .button .caret {border-bottom-color: springgreen;}"; + + newCssRules += ".dropup {position: relative;}" + + ".dropup .dropdown-menu {top: initial; bottom: 30px; left: 0; right: 0; text-align: center;}" + + ".dropdown-menu > li > a {cursor: pointer;}" + + ".editor .view {width: initial;height: initial;text-align: center;margin: 0;}" + + ".editor .type-view, .editor .name-view {width: 100%;}" + + ".pagination>li>a {background: #0b0c0d;border-color: #5afbea;color: #5afbea; font-size: 18px;}" + + ".pagination>li>a:hover {background: #2b2c2d;border-color: #5afbea;color: #5afbea;}" + + ".pagination>.active>a, .pagination>.active>a:hover {background-color: #5afbea;border-color: #5afbea;color: #0b0c0d;}" + + ".type-view .btn.focus, .type-view .btn:focus, .type-view .btn:hover {color: unset;}" + + ".type-view .btn.active.focus, .type-view .btn.active:focus, .type-view .btn.active:hover {color: #ebbc4a;}" + + ".type-view .bordered-panel p {font-size: 20px;}" + + ".stopthat {color: red; font-weight: bold;}" + + "input.form-control, textarea.form-control {border: 1px solid #5afbea; background: none; border-radius: 0; color: white;}" + + ".upload-logo .input-row .upload-label {display: block;padding: 0 0 10px;}" + + ".upload-logo .input-row {display: block;}" + + ".upload-logo .input-row .upload-logo-cell, .upload-logo .input-row .clear-logo-button {display: inline-block;padding: 0; max-width: 50%;}" + + ".preview-mission .mission-header {margin: 0; width: 65%; float: left;)}" + + ".preview-mission .mission-stats, .preview-mission .mission-description {max-width: 35%;float: right; display: inline-block;}" + + "#previewMissionModel .loading-screen { top: 0; right: 0; position: relative; height: 40px;}" + + "#previewMissionModel .loading.spin { position: fixed; left: 50%; top: 80px; }" + + ""; $("head").append(newCssRules); }); @@ -217,13 +217,11 @@ function init() { //Replace breadcrumb with something a bit clearer $(".view").empty(); var newBreadcrumb = ""; + + "Mission Type" + + "Mission Details" + + "Waypoints" + + "Preview" + + ""; var compiledBread = $compile(newBreadcrumb)(editScope); $(".view").append(compiledBread); @@ -231,31 +229,28 @@ function init() { if (editStep == editScope.EditorScreenViews.TYPE) { //Overhauled UI on Mission Type page, including more editorialising on non-linear missions in banners $(".type-view .bordered-panel").empty().addClass('ready'); - var editCode = "
"; - - editCode += "
"; - editCode += "
"; - editCode += "
"; - - editCode += "

"; - - editCode += "

Agents visit portals and field trip markers in a set order.

Best suited to missions in a banner series, or one-offs with a pre-determined route.

" - editCode += "

Agents visit portals and field trip markers in a set order, but the location of every waypoint beyond the first is hidden, meaning players rely on clues in the waypoint text.

Good for more puzzle-based missions, but please ensure you provide adequate clues for agents to find all the waypoints.

" - editCode += "

Agents visit portals and field trip markers in any order. Excellent for one-off missions where a specific route isn't required, but terrible for missions in banner serieses.

It is strongly advised that if you are making missions for a banner, you set them as Sequential missions - your rating on IngressMosaik will thank you!

" + var editCode = "
" + + "
" + + "
" + + "
" + + "

" + + "

Agents visit portals and field trip markers in a set order.

Best suited to missions in a banner series, or one-offs with a pre-determined route.

" + + "

Agents visit portals and field trip markers in a set order, but the location of every waypoint beyond the first is hidden, meaning players rely on clues in the waypoint text.

Good for more puzzle-based missions, but please ensure you provide adequate clues for agents to find all the waypoints.

" + + "

Agents visit portals and field trip markers in any order. Excellent for one-off missions where a specific route isn't required, but terrible for missions in banner serieses.

It is strongly advised that if you are making missions for a banner, you set them as Sequential missions - your rating on IngressMosaik will thank you!

"; var compiledContent = $compile(editCode)(editScope); $(".type-view .bordered-panel").append(compiledContent); } else if (editStep == editScope.EditorScreenViews.NAME) { //Overhauled UI on Mission Name/Image pages $(".name-view .bordered-panel").empty().addClass('ready'); - var editCode = "
"; - editCode += ""; - editCode += "
"; - editCode += "
"; - editCode += ""; - editCode += "
"; - editCode += "
Mission Name" + + "
" + + "
" + + "" + + "
" + + "
" + + ""; var compiledContent = $compile(editCode)(editScope); $(".name-view .bordered-panel").append(compiledContent); } @@ -302,52 +297,46 @@ function init() { return dfd.promise; } + missionScope.categoryContent = []; + missionScope.categorisedMissions = []; + missionScope.uncategorisedMissions = []; + missionScope.uncategorisedSort = 'initial'; missionScope.missions = w.$filter("orderBy")(missionScope.missions, 'definition.name'); missionScope.loadingPreview = false; - //missionScope.getFullMissionData(missionScope.missions).then(function(data){ - //for (var i=0;i 0) { - missionScope.categoryContent = []; - //create uncategorised mission bucket, that categories will take missions from. Add position in initial array - for (var i = 0; i < missionScope.missions.length; i++) { - missionScope.missions[i].position = i; - } - missionScope.uncategorisedMissions = angular.copy(missionScope.missions); - - //loop through each category of GUIDs, and add actual missions to scope - categoryGUIDs.forEach(function(category) { - var catobj = []; - category.forEach(function(guid) { - for (var i = 0; i < missionScope.uncategorisedMissions.length ; i++) { - //once the right mission is found, add position, push it to the holding array and remove from uncategorised - if (missionScope.uncategorisedMissions[i].mission_guid == guid) { - catobj.push(missionScope.uncategorisedMissions[i]); - missionScope.uncategorisedMissions.splice(i, 1); - break; - } - } - }) - missionScope.categoryContent.push(catobj) - }) + missionScope.unsortedCollapse = {collapse: w.localStorage.getItem('unsortedCollapse') || true}; + + //handling for legacy data format + if (!!w.localStorage.getItem('categoryNames')){ + let oldegoriesLength = parseInt(w.localStorage.getItem('categoriesLength')) || 0, + categoryNames = w.localStorage.getItem('categoryNames') ? w.localStorage.getItem('categoryNames').split(',') : [], + thisCategory; + //create categories in new format + for (var i= 0; i < oldegoriesLength; i++){ + thisCategory = { + id: i, + name: categoryNames[i], + missions: w.localStorage.getItem('categoryContent' + i) ? w.localStorage.getItem('categoryContent' + i).split(',') : [], + collapse: true, + sortCriteria: 'initial' + }; + missionScope.categoryContent.push(thisCategory); + w.localStorage.removeItem('categoryContent' + i); } + w.localStorage.setItem('allCategories', JSON.stringify(missionScope.categoryContent)); - //}) + //now tidy up the legacy data + w.localStorage.removeItem('categoryNames'); + w.localStorage.removeItem('categoriesLength'); + } + + //get data for all categories + missionScope.categoryContent = JSON.parse(w.localStorage.getItem('allCategories')) || []; + missionScope.selectedCategoryMissionId = null; + + //Add position in initial array + for (var i = 0; i < missionScope.missions.length; i++) { + missionScope.missions[i].position = i; + } //function to calculate distances between two sets of coordinates taken from geodatasource.com missionScope.distance = function(lat1, lon1, lat2, lon2, unit) { @@ -385,8 +374,8 @@ function init() { distance += missionScope.distance( mission.definition.waypoints[i-1]._poi.location.latitude, mission.definition.waypoints[i-1]._poi.location.longitude, - mission.definition.waypoints[i]._poi.location.latitude, - mission.definition.waypoints[i]._poi.location.longitude, + mission.definition.waypoints[i]._poi.location.latitude, + mission.definition.waypoints[i]._poi.location.longitude, "K") } @@ -410,10 +399,10 @@ function init() { missionScope.previewBanner = function(category) { $('#previewMissionModel .modal-body .notloading').empty(); missionScope.loadingPreview = true; - missionScope.getFullMissionData(missionScope.categoryContent[category]).then(function(data){ + missionScope.getFullMissionData(missionScope.categorisedMissions[category]).then(function(data){ missionScope.banner = { definition: { - name: categoryNames[category], + name: missionScope.categoryContent[category].name, author_nickname: data[0].author_nickname, description: data[0].description, _sequential: data[0]._sequential, @@ -421,14 +410,14 @@ function init() { waypoints: [] }, stats: { - num_completed: missionScope.categoryContent[category][data.length -1].stats ? missionScope.categoryContent[category][data.length -1].stats.num_completed : 0, + num_completed: missionScope.categorisedMissions[category][data.length -1].stats ? missionScope.categorisedMissions[category][data.length -1].stats.num_completed : 0, rating: 0, median_completion_time: 0 }, }; - for (var i = 0; i < missionScope.categoryContent[category].length; i++){ - missionScope.banner.stats.rating += missionScope.categoryContent[category][i].stats ? missionScope.categoryContent[category][i].stats.rating : 0; - missionScope.banner.stats.median_completion_time += missionScope.categoryContent[category][i].stats ? missionScope.categoryContent[category][i].stats.median_completion_time : 0; + for (var i = 0; i < missionScope.categorisedMissions[category].length; i++){ + missionScope.banner.stats.rating += missionScope.categorisedMissions[category][i].stats ? missionScope.categorisedMissions[category][i].stats.rating : 0; + missionScope.banner.stats.median_completion_time += missionScope.categorisedMissions[category][i].stats ? missionScope.categorisedMissions[category][i].stats.median_completion_time : 0; data[i].waypoints.forEach(function(wp){ missionScope.banner.definition.waypoints.push(wp) }) @@ -470,32 +459,21 @@ function init() { $(".modal-backdrop.fade").remove(); $("body").removeClass("modal-open"); var categoryID = missionScope.selectedCategoryID; - categoryGUIDs[categoryID].push(missionScope.selectedCategoryMissionId); - //find mission in uncategorised missions - for (var i = 0; i < missionScope.uncategorisedMissions.length; i++) { - if (missionScope.uncategorisedMissions[i].mission_guid == missionScope.selectedCategoryMissionId) { - missionScope.categoryContent[categoryID].push(missionScope.uncategorisedMissions[i]); - missionScope.uncategorisedMissions.splice(i, 1); - break; - } - } + missionScope.categoryContent[categoryID].missions.push(missionScope.selectedCategoryMissionId); + missionScope.categoryContent[categoryID].collapse = false; missionScope.selectedCategoryMissionId = null; - w.localStorage.setItem('categoryContent' + categoryID, categoryGUIDs[categoryID]); - missionScope.categoryCollapse[categoryID] = true; missionScope.selectedCategoryID = null; + w.localStorage.setItem('allCategories', JSON.stringify(missionScope.categoryContent)); generateAllMissions(); } missionScope.removeFromCategory = function(category, mission) { - for (var i = 0; i < categoryGUIDs[category].length; i++) { - if (categoryGUIDs[category][i] == mission.mission_guid) { - missionScope.uncategorisedMissions.push(mission); - missionScope.categoryContent[category].splice(i, 1); - categoryGUIDs[category].splice(i, 1); + for (var i = 0; i < missionScope.categoryContent[category].missions.length; i++) { + if (missionScope.categoryContent[category].missions[i] == mission.mission_guid) { + missionScope.categoryContent[category].missions.splice(i, 1); } } - w.localStorage.setItem('categoryContent' + category, categoryGUIDs[category]); - missionScope.categoryCollapse[category] = true; + w.localStorage.setItem('allCategories', JSON.stringify(missionScope.categoryContent)); generateAllMissions(); } @@ -504,61 +482,58 @@ function init() { if (categoryName == null || categoryName == "") { //no result } else { - //create category elements in various places - categoriesLength++; - w.localStorage.setItem('categoriesLength', categoriesLength); - categoryNames.push(categoryName); - w.localStorage.setItem('categoryNames', categoryNames); - missionScope.categoryContent = missionScope.categoryContent || []; - categoryGUIDs.push([]); - missionScope.categoryContent.push([]); - w.localStorage.setItem('categoryContent' + (categoriesLength - 1), []); + //create category elements + var newCategory = { + id: missionScope.categoryContent.length, + name: categoryName, + missions: [], + collapse: false, + sortCriteria: 'initial' + }; + missionScope.categoryContent.push(newCategory); + w.localStorage.setItem('allCategories', JSON.stringify(missionScope.categoryContent)); generateAllMissions(); } } + missionScope.nukeCategories = function() { - w.localStorage.clear(); + missionScope.categoryContent = []; + w.localStorage.setItem('allCategories', []); generateAllMissions(); } missionScope.deleteCategory = function(category) { - if (confirm("Are you sure you want to delete the " + categoryNames[category] + " category? Any missions you've placed in this category will be retured to Unsorted missions.")) { - //remove cateory from GUID list, move scope missions out, nuke localStorage categories - categoryGUIDs.splice(category, 1); + if (confirm("Are you sure you want to delete the " + missionScope.categoryContent[category].name + " category? Any missions you've placed in this category will be retured to Unsorted missions.")) { + //move scope missions out, nuke localStorage categories missionScope.categoryContent[category].forEach(function(mission) { missionScope.uncategorisedMissions.push(mission); }) missionScope.categoryContent.splice(category, 1); - for (var i = 0; i < categoriesLength; i++) { - w.localStorage.removeItem('categoryContent' + i); - } - //remove other mission data - categoriesLength--; - w.localStorage.setItem('categoriesLength', categoriesLength); - categoryNames.splice(category, 1); - w.localStorage.setItem('categoryNames', categoryNames); - missionScope.categoryCollapse.splice(category, 1); - //then rebuild localStorage - for (var i = 0; i < categoriesLength; i++) { - w.localStorage.setItem('categoryContent' + i, categoryGUIDs[i]); - } + w.localStorage.setItem('allCategories', JSON.stringify(missionScope.categoryContent)); generateAllMissions(); } } - missionScope.sortCategory = function(category, criteria){ + missionScope.sortCategory = function(category){ if (category == 'all'){ - missionScope.missions = w.$filter("orderBy")(missionScope.missions, missionScope.sortCriteria[0]); + missionScope.missions = w.$filter("orderBy")(missionScope.missions, missionScope.sortCriteria[0] == 'initial' ? 'position' : missionScope.sortCriteria[0]); } else if (category == 'unsorted'){ - missionScope.uncategorisedMissions = w.$filter("orderBy")(missionScope.uncategorisedMissions, missionScope.sortCriteria[categoriesLength]); + missionScope.uncategorisedSort = missionScope.sortCriteria[missionScope.categoryContent.length]; } else { - missionScope.categoryContent[category] = w.$filter("orderBy")(missionScope.categoryContent[category], missionScope.sortCriteria[category]); + missionScope.categoryContent[category].sortCriteria = missionScope.sortCriteria[category]; } generateAllMissions(); } + missionScope.toggleCollapse = function(collapse, unsorted){ + collapse.collapse = !collapse.collapse; + unsorted ? w.localStorage.setItem('unsortedCollapse', collapse.collapse) + : w.localStorage.setItem('allCategories', JSON.stringify(missionScope.categoryContent)); + } + var generateSort = function (category){ var criteria = [ + {name: "Initial", value: "initial"}, {name: "Alphabetical (ascending)", value: "definition.name"}, {name: "Alphabetical (descending)", value: "-definition.name"}, {name: "Creation order", value: "created_ms"}, @@ -571,7 +546,7 @@ function init() { sortContent += "0"; break; case "unsorted": - sortContent += categoriesLength; + sortContent += missionScope.categoryContent.length; break; default: sortContent += category; @@ -588,13 +563,13 @@ function init() { var generateMission = function(mission, id, selectedCategory) { var missionState = mission.missionListState.toLowerCase(); - var newMissionCode = "
"; - newMissionCode += "
"; - newMissionCode += ""; - newMissionCode += "
"; - newMissionCode += "" + mission.definition.name + ""; - newMissionCode += "
"; - newMissionCode += "
" + + "
" + + "" + + "
" + + "" + mission.definition.name + "" + + "
" + + "" + missionScope.getInfoTime(mission) + ""; - newMissionCode += "" + + "" + missionScope.getInfoTime(mission) + "" + + "
"; - newMissionCode += ""; - newMissionCode += ""; + newMissionCode += "" + + "" + + ""; } - newMissionCode += "
" + missionScope.getMissionRatingString(mission) + " " + mission.stats.num_completed + " " + missionScope.getMissionTimeString(mission) + " " + missionScope.getMissionRatingString(mission) + " " + mission.stats.num_completed + "
"; - newMissionCode += "
"; - newMissionCode += "
"; return newMissionCode; } + var generateAllMissions = function() { $(".missions-list").empty(); - if (categoriesLength == 0) { + if (missionScope.categoryContent.length == 0) { $(".missions-list").addClass("row"); } missionScope.sortCriteria = []; w.$injector.invoke(function($compile) { var missionContent = ""; - if (categoriesLength > 0) { - //if there are user-defined categories, loop over them + if (missionScope.categoryContent.length > 0) { + //if there are user-defined categories, first sort the categorised/uncategorised missions + missionScope.categorisedMissions = []; + missionScope.uncategorisedMissions = angular.copy(missionScope.missions); + + //loop through each category of GUIDs, and add actual missions to scope + missionScope.categoryContent.forEach(function(category) { + var catobj = []; + category.missions.forEach(function(guid) { + //TODO: Do this with filters, not loops + for (var i = 0; i < missionScope.uncategorisedMissions.length ; i++) { + //once the right mission is found, add position, push it to the holding array and remove from uncategorised + if (missionScope.uncategorisedMissions[i].mission_guid == guid) { + catobj.push(missionScope.uncategorisedMissions[i]); + missionScope.uncategorisedMissions.splice(i, 1); + break; + } + } + }) + missionScope.categorisedMissions.push(catobj); + }) + + //then get the categories sorted + missionScope.categoryContent.forEach(function(category) { + if (category.sortCriteria != 'initial') {missionScope.categorisedMissions[category.id] = w.$filter("orderBy")(missionScope.categorisedMissions[category.id], category.sortCriteria);} + }) + if (missionScope.uncategorisedSort != 'initial') {missionScope.uncategorisedMissions = w.$filter("orderBy")(missionScope.uncategorisedMissions, missionScope.uncategorisedSort);} + + //once all the categorisation is done, create the HTML for the categories! missionContent += "
"; - for (var i = 0; i < categoriesLength; i++) { - missionContent += "
"; - missionContent += "
"; - missionContent += generateSort(i); - missionContent += ""; - if (!missionScope.categoryContent[i] || missionScope.categoryContent[i].length == 0) { + for (var i = 0; i < missionScope.categoryContent.length; i++) { + missionContent += "
" + + "
" + + generateSort(i) + + ""; + if (!missionScope.categoryContent[i].missions || missionScope.categoryContent[i].missions.length == 0) { //no missions so far! missionContent += "
No missions added to the category yet
"; } else { - missionContent += ""; - missionContent += "
"; - var bannerModal = "