diff --git a/docs/getting-started.md b/docs/getting-started.md
index ec49e5c13..824a1b550 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -51,12 +51,12 @@ please [open an issue on GitHub](/support){: .alert-link}.
diff --git a/download.md b/download.md
index 458bc6ed0..916b1544e 100644
--- a/download.md
+++ b/download.md
@@ -28,9 +28,9 @@ no-wrapper: true
the primary focus of development.
-
+
- Download for EV3
+ LEGO MINDSTORMS EV3
@@ -48,15 +48,15 @@ no-wrapper: true
@@ -75,9 +75,9 @@ no-wrapper: true
diff --git a/javascripts/api-cache.js b/javascripts/api-cache.js
index 119e4476d..6179a1ec9 100644
--- a/javascripts/api-cache.js
+++ b/javascripts/api-cache.js
@@ -8,18 +8,20 @@ function supportsHtml5Storage() {
}
}
-function getApiValue(endpointUrl, cacheTime, callback) {
- try {
- var cacheData = supportsHtml5Storage() ? JSON.parse(localStorage[cacheKey]) : null;
- // This does an exact match for the URL given. Different spacing, duplicate slashes,
- // alternate caps, etc. will result in the cache being bypassed.
- if (cacheData && cacheData[endpointUrl] && Date.now() - cacheData[endpointUrl].dateRetrieved < cacheTime) {
- callback(cacheData[endpointUrl].requestResult);
- return;
+function getApiValue(endpointUrl, cacheTime, callback, clearCache) {
+ if(clearCache != true) {
+ try {
+ var cacheData = supportsHtml5Storage() ? JSON.parse(localStorage[cacheKey]) : null;
+ // This does an exact match for the URL given. Different spacing, duplicate slashes,
+ // alternate caps, etc. will result in the cache being bypassed.
+ if (cacheData && cacheData[endpointUrl] && Date.now() - cacheData[endpointUrl].dateRetrieved < cacheTime) {
+ callback(cacheData[endpointUrl].requestResult);
+ return;
+ }
+ }
+ catch (e) {
+ // Ignore the error; if the saved JSON is invalid, we'll just request it from the server.
}
- }
- catch (e) {
- // Ignore the error; if the saved JSON is invalid, we'll just request it from the server.
}
console.log('No cached copy of API data for endpoint "' + endpointUrl + '" found. Downloading from remote server.');
diff --git a/javascripts/releases.js b/javascripts/releases.js
index fc58d256f..51f0b6021 100644
--- a/javascripts/releases.js
+++ b/javascripts/releases.js
@@ -1,54 +1,89 @@
-// Cache will time out after 20 minutes
-var releaseCacheTimeMillis = 20 * 60 * 1000;
+// Cache will time out after five minutes
+var releaseCacheTimeMillis = 5 * 60 * 1000;
var releasePlatformRegexes = {
- ev3: "ev3dev-jessie-ev3-generic-[\\d-]+\\.zip",
- rpi: "ev3dev-jessie-rpi-generic-[\\d-]+\\.zip",
- rpi2: "ev3dev-jessie-rpi2-generic-[\\d-]+\\.zip",
- bone: "ev3dev-jessie-bone-generic-[\\d-]+\\.zip",
+ ev3: /ev3dev-jessie-ev3-generic-[\d-]+\.zip/,
+ rpi: /ev3dev-jessie-rpi-generic-[\d-]+\.zip/,
+ rpi2: /ev3dev-jessie-rpi2-generic-[\d-]+\.zip/,
+ bone: /ev3dev-jessie-bone-generic-[\d-]+\.zip/,
}
-function initDownloadLinks() {
- getApiValue('https://api.github.com/repos/ev3dev/ev3dev/releases', releaseCacheTimeMillis, function (releases, error) {
- if(error) {
- console.error("Download links not available! Falling back to static content.");
- $('.release-link-container').hide();
- $('.release-link-alt').show();
-
+function loadReleasesByPlatform(successCallback, errorCallback) {
+ getApiValue('https://api.github.com/repos/ev3dev/ev3dev/releases', releaseCacheTimeMillis, function (releasesApiData, error) {
+ if (error) {
+ errorCallback(error);
return;
}
-
- releases.sort(function (a, b) {
- if (Date.parse(a['created_at']) < Date.parse(b['created_at']))
- return 1;
- if (Date.parse(a['created_at']) > Date.parse(b['created_at']))
- return -1;
-
- return 0;
+
+ var releaseMap = {};
+ releasesApiData.forEach(function (releaseApiData) {
+ releaseApiData['assets'].forEach(function (assetApiData) {
+ var assetPlatform = $.grep(Object.keys(releasePlatformRegexes), function (platId) {
+ return releasePlatformRegexes[platId].test(assetApiData['name']);
+ })[0];
+
+ if (!assetPlatform)
+ return true;
+
+ if (!Array.isArray(releaseMap[assetPlatform]))
+ releaseMap[assetPlatform] = [];
+
+ releaseMap[assetPlatform].push({
+ releaseName: releaseApiData['name'],
+ assetName: assetApiData['name'],
+ creationDate: Date.parse(releaseApiData['created_at']),
+ platform: assetPlatform,
+ size: assetApiData['size'],
+ downloadUrl: assetApiData['browser_download_url']
+ });
+ });
});
- $('a[data-release-link-platform]').each(function (i, element) {
+ Object.keys(releaseMap).forEach(function (platformId) {
+ releaseMap[platformId].sort(function (a, b) {
+ return (b.creationDate > a.creationDate) - (b.creationDate < a.creationDate);
+ });
+ })
+
+ successCallback(releaseMap);
+ });
+}
+
+function initDownloadLinks() {
+ loadReleasesByPlatform(function (releaseMap) {
+
+ $('a[data-download-button-platform]').each(function (i, element) {
var $linkElem = $(element);
- var targetReleasePlatform = $linkElem.data('release-link-platform');
- if (!releasePlatformRegexes[targetReleasePlatform]) {
- console.error('"' + targetReleasePlatform + '" is an invalid release target.');
+ var targetReleasePlatform = $linkElem.data('download-button-platform');
+ var targetRelease = (releaseMap[targetReleasePlatform] || [])[0];
+
+ if (!targetRelease) {
+ console.error('"' + targetReleasePlatform + '" is an invalid release target or no releases for the given platform exist.');
return true;
}
- var platformRegex = new RegExp(releasePlatformRegexes[targetReleasePlatform]);
-
- for (var releaseIndex in releases) {
- var releaseAssets = releases[releaseIndex].assets;
- for (var assetIndex in releaseAssets) {
- if (platformRegex.test(releaseAssets[assetIndex].name)) {
- $linkElem.attr('href', releaseAssets[assetIndex]['browser_download_url']);
- var fileSize = releaseAssets[assetIndex]['size'] >> 20;
- $('').text(' (' + fileSize + ' MiB)').appendTo($linkElem);
- return true;
- }
- }
+ $linkElem.attr('href', targetRelease.downloadUrl);
+ $linkElem.addClass('btn-group-vertical download-button-container');
+
+ var $upperSection = $linkElem.children('.download-button-upper');
+ if($upperSection.length <= 0) {
+ var $contents = $linkElem.contents();
+ $upperSection = $('').addClass('btn btn-primary download-button-upper').appendTo($linkElem);
+ $contents.appendTo($upperSection);
}
+
+ $linkElem.children('.download-button-lower').remove();
+ var $lowerSection = $('').addClass('btn download-button-lower').text(targetRelease.assetName).appendTo($linkElem);
+
+ var fileSize = targetRelease.size >> 20;
+ $('').addClass('download-info-label badge').text(fileSize + ' MiB').appendTo($lowerSection);
+
});
+ },
+ function (error) {
+ console.error("Download links not available! Falling back to static content.");
+ $('.release-link-container').hide();
+ $('.release-link-alt').show();
});
}
@@ -57,8 +92,8 @@ $(document).ready(function () {
// We do this as soon as the document loads so that the page flash is minimal.
$('.release-link-alt').hide();
$('.release-link-container').show();
-
- if ($('a[data-release-link-platform]').length > 0) {
+
+ if ($('a[data-download-button-platform]').length > 0) {
initDownloadLinks();
}
});
\ No newline at end of file
diff --git a/stylesheets/page-content.scss b/stylesheets/page-content.scss
index a8563ef3a..3f9f640f1 100644
--- a/stylesheets/page-content.scss
+++ b/stylesheets/page-content.scss
@@ -30,8 +30,10 @@
margin: 5px 0 5px !important;
}
-.download-button-small {
- margin: 0 6px;
+.stacked-download-button {
+ margin-top: 7px;
+ margin-left: 15px;
+ margin-right: 15px;
}
.dark-bg {
diff --git a/stylesheets/site-structure.scss b/stylesheets/site-structure.scss
index 04fa6faa4..8c83717ea 100644
--- a/stylesheets/site-structure.scss
+++ b/stylesheets/site-structure.scss
@@ -152,6 +152,143 @@ ul + p, ol + p {
font-size: 22px;
}
+.download-button-container {
+ text-decoration: none !important;
+ cursor: pointer;
+ touch-action: manipulation;
+
+ * {
+ pointer-events: none;
+ }
+
+ // The following styles are an adaptation of those for standard buttons; from mixins/_buttons.scss
+ // Darken percentages for the lower half are lessened manually because the lower half is already dark
+ &:focus,
+ &.focus {
+ .download-button-upper {
+ background-color: darken($brand-primary, 10%);
+ border-color: darken($brand-primary, 25%);
+ }
+
+ .download-button-lower {
+ background-color: darken($gray, 7%);
+ border-color: darken($gray, 15%);
+ }
+ }
+ &:hover {
+ .download-button-upper {
+ background-color: darken($brand-primary, 10%);
+ border-color: darken($brand-primary, 12%);
+ }
+
+ .download-button-lower {
+ background-color: darken($gray, 7%);
+ border-color: darken($gray, 9%);
+ }
+ }
+
+ &:active,
+ &.active,
+ .open > &.dropdown-toggle {
+ .download-button-upper {
+ background-color: darken($brand-primary, 10%);
+ border-color: darken($brand-primary, 12%);
+ }
+ .download-button-lower {
+ background-color: darken($gray, 7%);
+ border-color: darken($gray, 9%);
+ }
+
+ &:hover,
+ &:focus,
+ &.focus {
+ .download-button-upper {
+ background-color: darken($brand-primary, 17%);
+ border-color: darken($brand-primary, 25%);
+ }
+ .download-button-lower {
+ background-color: darken($gray, 13%);
+ border-color: darken($gray, 15%);
+ }
+ }
+ }
+ &.disabled,
+ &[disabled],
+ fieldset[disabled] & {
+ &,
+ &:hover,
+ &:focus,
+ &.focus,
+ &:active,
+ &.active {
+ .download-button-upper {
+ background-color: $brand-primary;
+ border-color: $brand-primary;
+ }
+
+ .download-button-lower {
+ background-color: $gray;
+ border-color: $gray;
+ }
+ }
+ }
+
+ .download-button-upper {
+ font-weight: bold;
+ }
+
+ .download-button-lower {
+ background-color: $gray;
+ color: white;
+
+ padding-top: 4px;
+ padding-bottom: 4px;
+
+ .badge {
+ color: $gray;
+ background-color: white;
+
+ padding: 2px 5px;
+ }
+ }
+
+ &.btn-group-lg {
+ .download-button-upper {
+ font-size: 25px;
+ }
+
+ .download-button-lower {
+ font-size: 85%;
+ height: 30px;
+
+ .badge {
+ font-size: 11px;
+ margin-right: -10px;
+ margin-left: 10px;
+ }
+ }
+ }
+
+ &.btn-group-md {
+ .download-button-upper {
+ font-size: 17px;
+ }
+
+ .download-button-lower {
+ font-size: 75%;
+ height: 25px;
+
+ .badge {
+ font-size: 10px;
+ margin-right: -10px;
+ margin-left: 10px;
+ }
+ }
+ }
+
+ // small and extra-small download buttons are not used
+}
+
// thanks http://stackoverflow.com/a/32490429/1976323
$margins: (xs: 0.5rem, sm: 1rem, md: 1.5rem, lg: 2rem, xl: 2.5rem);