diff --git a/plugins/missions.css b/plugins/missions.css
new file mode 100644
index 00000000..0e178c1e
--- /dev/null
+++ b/plugins/missions.css
@@ -0,0 +1,119 @@
+.plugin-mission-summary {
+ padding: 5px;
+ border-top: black solid 1px;
+ min-height: 50px;
+ position: relative;
+ clear: left;
+}
+.plugin-mission-summary.checked::after {
+ content: "✓";
+ display: block;
+ pointer-events: none;
+ position: absolute;
+ text-align: center;
+ color: rgba(255, 187, 0, 0.3);
+ left: 5px;
+ top: 5px;
+ font-size: 50px;
+ line-height: 50px;
+ width: 50px;
+}
+.plugin-mission-summary:first-child {
+ border-top-width: 0px;
+}
+
+.plugin-mission-summary.checked {
+ background-color: rgba(255, 187, 0, 0.3);
+}
+
+.plugin-mission-summary > img {
+ float: left;
+ cursor: pointer;
+ width: 50px;
+ margin-right: 10px;
+ margin-bottom: 10px;
+}
+
+.plugin-mission-summary > a, .plugin-mission-summary > h4 {
+ display: block;
+ font-weight: bold;
+ font-size: 1.3em;
+ margin: 0 0 2px 60px;
+}
+
+.plugin-mission-summary > br {
+ margin-bottom: 2px;
+}
+
+.plugin-mission-info img {
+ height: 14px;
+ margin-right: 8px;
+ vertical-align: top;
+}
+
+.plugin-mission-summary description {
+ white-space: pre;
+ margin-left: 110px;
+}
+
+.plugin-mission-details .plugin-mission-summary.checked::after {
+ left: 0px;
+ top: 0px;
+ font-size: 100px;
+ line-height: 100px;
+ width: 100px;
+}
+
+.plugin-mission-details .plugin-mission-summary {
+ padding: 0;
+ background-color: transparent;
+}
+
+.plugin-mission-details .plugin-mission-summary > img {
+ width: 100px;
+}
+
+.plugin-mission-details ol {
+ clear: left;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.plugin-mission-portal-indicator {
+ position: relative;
+ text-align: center;
+ float: left;
+ line-height: 18px;
+ height: 18px;
+ width: 18px;
+ margin-right: 5px;
+}
+
+.plugin-mission-portal-indicator div {
+ border-color: currentcolor transparent transparent;
+ border-style: solid;
+ border-width: 2px 1px;
+ box-sizing: border-box;
+ height: 0;
+ left: 6px;
+ position: absolute;
+ top: 0;
+ transform-origin: 4px 9px 0;
+ width: 8px;
+}
+
+.plugin-mission-waypoint .title {
+ font-size: 18px;
+ font-weight: bold;
+}
+.plugin-mission-waypoint label {
+ clear: left;
+ display: block;
+}
+.plugin-mission-waypoint input {
+ box-sizing: border-box;
+ margin: 3px 5px 8px 0;
+ width: 18px;
+}
+
diff --git a/plugins/missions.user.js b/plugins/missions.user.js
index 9e849359..48d69d18 100644
--- a/plugins/missions.user.js
+++ b/plugins/missions.user.js
@@ -249,168 +249,182 @@ window.plugin.missions = {
},
renderMissionList: function(missions) {
- return missions.map(this.renderMissionSummary, this).join(' ');
+ var container = document.createElement('div');
+ missions.forEach(function(mission) {
+ container.appendChild(this.renderMissionSummary(mission));
+ }, this);
+ return container;
},
renderMissionSummary: function(mission) {
var cachedMission = this.getMissionCache(mission.guid);
- var html = '';
var checked = this.settings.checkedMissions[mission.guid];
- html += '
';
- html += '

';
- html += '
';
- if (cachedMission) {
- html += '
' + cachedMission.authorNickname + '';
- html += '
';
+ var container = document.createElement('div');
+ container.className = 'plugin-mission-summary mc-' + mission.guid;
+ if(checked)
+ container.classList.add('checked');
+
+ var img = container.appendChild(document.createElement('img'));
+ img.src = mission.image;
+ img.addEventListener('click', function(ev) {
+ plugin.missions.toggleMission(mission.guid);
+ }, false);
+
+ var title = container.appendChild(document.createElement('a'));
+ title.textContent = mission.title;
+ title.href = '/mission/' + mission.guid; // TODO make IITC load on mission permalinks as well
+ title.addEventListener('click', function(ev) {
+ plugin.missions.openMission(mission.guid);
+ // prevent browser from following link
+ ev.preventDefault();
+ return false;
+ }, false);
+
+ if(cachedMission) {
+ var span = container.appendChild(document.createElement('span'));
+ span.className = 'nickname ' + (cachedMission.authorTeam === 'R' ? 'res' : 'enl')
+ span.textContent = cachedMission.authorNickname;
}
- html += '

' +
- timeToRemaining((mission.medianCompletionTimeMs / 1000) | 0);
- html += '

' +
- (((mission.ratingE6 / 100) | 0) / 100) + '%';
-
+
+ container.appendChild(document.createElement('br'));
+
+ var infoTime = container.appendChild(document.createElement('span'));
+ infoTime.className = 'plugin-mission-info time';
+ infoTime.textContent = timeToRemaining((mission.medianCompletionTimeMs / 1000) | 0) + ' ';
+ img = infoTime.insertBefore(document.createElement('img'), infoTime.firstChild);
+ img.src = 'https://commondatastorage.googleapis.com/ingress.com/img/tm_icons/time.png';
+
+ var infoRating = container.appendChild(document.createElement('span'));
+ infoRating.className = 'plugin-mission-info rating';
+ infoRating.textContent = (((mission.ratingE6 / 100) | 0) / 100) + '%' + ' ';
+ img = infoRating.insertBefore(document.createElement('img'), infoRating.firstChild);
+ img.src = 'https://commondatastorage.googleapis.com/ingress.com/img/tm_icons/like.png';
+
if (cachedMission) {
- html += '

' +
- cachedMission.numUniqueCompletedPlayers;
- html += '

' +
- cachedMission.waypoints.length;
+ var infoPlayers = container.appendChild(document.createElement('span'));
+ infoPlayers.className = 'plugin-mission-info players';
+ infoPlayers.textContent = cachedMission.numUniqueCompletedPlayers + ' ';
+ img = infoPlayers.insertBefore(document.createElement('img'), infoPlayers.firstChild);
+ img.src = 'https://commondatastorage.googleapis.com/ingress.com/img/tm_icons/players.png';
+
+ var infoWaypoints = container.appendChild(document.createElement('span'));
+ infoWaypoints.className = 'plugin-mission-info waypoints';
+ infoWaypoints.textContent = cachedMission.waypoints.length + ' ';
+ img = infoWaypoints.insertBefore(document.createElement('img'), infoWaypoints.firstChild);
+ img.src = 'https://commondatastorage.googleapis.com/ingress.com/img/map_icons/linkmodeicon.png';
}
- html += '
';
- html += '
';
- return html;
+
+ return container;
},
renderMission: function(mission) {
- var me = this;
- var checked = this.settings.checkedMissions[mission.guid];
- //commondatastorage.googleapis.com/ingress.com/img/map_icons/linkmodeicon.png
- var html = '';
- html += '
';
- html += '✓';
- html += '
';
- html += '';
- html += '
' + mission.title + '
';
- html += '
' + mission.authorNickname + '';
- html += '
';
- html += '
';
- html += '

' +
- timeToRemaining((mission.medianCompletionTimeMs / 1000) | 0);
- html += '

' +
- (((mission.ratingE6 / 100) | 0) / 100) + '%';
- html += '

' +
- mission.numUniqueCompletedPlayers;
- html += '

' +
- mission.waypoints.length;
- html += '
';
- html += '
';
- html += mission.description;
- html += '
';
- html += '
';
- html += mission.waypoints.map(function(waypoint, index) {
- return me.renderMissionWaypoint(waypoint, index, mission);
- }).join(' ');
- return html;
+ var container = document.createElement('div');
+ container.className = 'plugin-mission-details';
+
+ var summary = container.appendChild(this.renderMissionSummary(mission));
+
+ // replace link with heading
+ var title = summary.getElementsByTagName('a')[0];
+ var newtitle = document.createElement('h4');
+ newtitle.textContent = mission.title;
+ title.parentNode.replaceChild(newtitle, title);
+
+ var desc = summary.appendChild(document.createElement('p'));
+ desc.className = 'description';
+ desc.textContent = mission.description;
+
+
+ var list = container.appendChild(document.createElement('ol'))
+ mission.waypoints.forEach(function(waypoint, index) {
+ list.appendChild(this.renderMissionWaypoint(waypoint, index, mission));
+ }, this);
+
+ return container;
},
renderMissionWaypoint: function(waypoint, index, mission) {
- var html = '';
- html += '';
- html += '
';
+ var container = document.createElement('li');
+ container.className = 'plugin-mission-waypoint';
+
if (waypoint.portal) {
- var color = 'white';
- if (waypoint.portal.team === 'R') { // Yay
- color = '#00c2ff';
- } else if (waypoint.portal.team === 'E') { // Booo
- color = '#28f428';
- }
- var realHealth = (waypoint.portal.resCount / 8) * (waypoint.portal.health / 100);
- html += this.renderPortalCircle(color, waypoint.portal.level, realHealth);
- /*
- var radius = ((realHealth * 360) | 0);
- html += '
';
- html += '
';
- html += '
'; // 360 + 45
- html += '
' + waypoint.portal.level + '
';
- html += '
';
- */
- }
- if (waypoint.portal) {
- html += '
';
- }
- if (waypoint.title) {
- html += waypoint.title;
+ container.appendChild(this.renderPortalCircle(waypoint.portal));
+
+ var title = container.appendChild(document.createElement('a'));
+
+ var lat = waypoint.portal.latE6/1E6;
+ var lng = waypoint.portal.lngE6/1E6;
+ var perma = '/intel?ll='+lat+','+lng+'&z=17&pll='+lat+','+lng;
+
+ title.href = perma;
+ title.addEventListener("click", function(ev) {
+ renderPortalDetails(waypoint.portal.guid);
+ ev.preventDefault();
+ return false;
+ }, false);
+ title.addEventListener("dblclick", function(ev) {
+ zoomToAndShowPortal(waypoint.portal.guid, [lat, lng]);
+ ev.preventDefault();
+ return false;
+ }, false);
} else {
- html += 'Unknown';
+ var title = container.appendChild(document.createElement('span'));
}
- if (waypoint.portal) {
- html += '';
- }
- html += '
';
- /*
- checkbox_grey
- checkbox_orange
- checkbox_cyan
- */
- var img = 'cyan';
- if (index === 0) {
- img = 'orange';
- } else if (!waypoint.objective) {
- img = 'grey';
- }
- // ✓
+
+ title.className = 'title';
+ if(waypoint.title)
+ title.textContent = waypoint.title;
+ else if(waypoint.portal && waypoint.portal.title)
+ title.textContent = waypoint.portal.title;
+ else
+ title.textContent = 'Unknown';
+
var mwpid = mission.guid + '-' + waypoint.guid;
var checked = this.settings.checkedWaypoints[mwpid];
-
- html += '';
- html += '✓';
-
- html += '
';
- html += '';
- html += (waypoint.objective ? waypoint.objective : '?');
- html += '';
- return html;
+
+ var label = container.appendChild(document.createElement('label'));
+
+ var checkbox = label.appendChild(document.createElement('input'));
+ checkbox.type = 'checkbox';
+ checkbox.addEventListener('change', function() {
+ plugin.missions.toggleWaypoint(mission.guid, waypoint.guid);
+ }, false);
+ checkbox.className = 'wp-' + mwpid;
+
+ var objective = label.appendChild(document.createElement('span'));
+ objective.textContent = waypoint.objective ? waypoint.objective : '?';
+
+ return container;
},
- renderPortalCircle: function(portalColor, portalLevel, portalHealth) {
- var s = 20,
- bg = '#999',
- c = portalColor,
- i = 14,
- ic = '#555',
- s2 = ((s / 2) | 0),
- si = (((s - i) / 2) | 0),
- d = (portalHealth * 180) | 0,
- num = portalLevel;
- var html = '';
- html += '
';
- html += '
';
- html += '
';
- html += '
';
- html += '
';
- html += '
';
- html += '
';
- html += '
';
- html += '
';
- html += '
';
- html += '
';
- html += '
';
- html += '
' + num;
- html += '
';
- html += '
';
- return html;
+
+ renderPortalCircle: function(portal) {
+ var team = TEAM_TO_CSS[getTeam(portal)];
+ var resCount = portal.resCount;
+ var level = resCount == 0 ? 0 : portal.level; // we want neutral portals to be level 0
+
+ var container = document.createElement('div');
+ container.className = 'plugin-mission-portal-indicator help ' + team;
+ container.textContent = level;
+ container.title = 'Level:\t'+level+'\nResonators:\t'+resCount+'\nHealth:\t'+portal.health+'%';
+
+ for(var i = 0; i< resCount; i++) {
+ var resonator = container.appendChild(document.createElement('div'));
+ resonator.style.transform = 'rotate(' + i*45 + 'deg)';
+ }
+ return container;
},
toggleWaypoint: function(mid, wpid, dontsave) {
var mwpid = mid + '-' + wpid;
var el = document.getElementsByClassName('wp-' + mwpid);
- if (!this.settings.checkedWaypoints[mwpid]) {
+ if(!this.settings.checkedWaypoints[mwpid]) {
this.settings.checkedWaypoints[mwpid] = true;
window.runHooks('waypointFinished', { mission: this.getMissionCache(mid), waypointguid: wpid });
- $(el).show();
} else {
delete this.settings.checkedWaypoints[mwpid];
- $(el).hide();
}
+ $(el).prop('checked', !!this.settings.checkedWaypoints[mwpid]);
if (!dontsave) {
this.saveData();
}
@@ -431,7 +445,7 @@ window.plugin.missions = {
}
}, this);
$(el).show();
- $(sumel).css('background-color', 'rgba(255, 187, 0, 0.3)');
+ $(sumel).addClass('checked');
window.runHooks('missionFinished', { mission: mission });
} else {
delete this.settings.checkedMissions[mid];
@@ -441,7 +455,7 @@ window.plugin.missions = {
}
}, this);
$(el).hide();
- $(sumel).css('background-color', '');
+ $(sumel).removeClass('checked');
}
this.saveData();
},
@@ -622,6 +636,7 @@ window.plugin.missions = {
this.settings.checkedMissions = {};
}
+ $('