diff --git a/_config.yml b/_config.yml
index 09559bcba..0109e3b94 100644
--- a/_config.yml
+++ b/_config.yml
@@ -73,6 +73,12 @@ defaults:
type: "posts"
values:
layout: "news"
+ -
+ scope:
+ path: "javascripts"
+ type: "pages"
+ values:
+ layout: "none"
kramdown:
toc_levels: "2,3"
diff --git a/_data/platform-attributes.json b/_data/platform-attributes.json
new file mode 100644
index 000000000..26dbab6e4
--- /dev/null
+++ b/_data/platform-attributes.json
@@ -0,0 +1,53 @@
+{
+ "client-platform": {
+ "values": {
+ "android": {
+ "title": "Android",
+ "uaPlatform": "Android"
+ },
+ "osx": {
+ "title": "OS X",
+ "uaPlatform": "Mac OS"
+ },
+ "ubuntu": {
+ "title": "Ubuntu",
+ "uaPlatform": "Ubuntu"
+ },
+ "windows": {
+ "title": "Windows",
+ "uaPlatform": "Windows"
+ }
+ },
+ "autodetectFunction": "autodetectClientPlatform"
+ },
+ "client-windows-version": {
+ "values": {
+ "win7": {
+ "title": "Windows 7",
+ "uaVersion": "7"
+ },
+ "win8": {
+ "title": "Windows 8",
+ "uaVersion": "8"
+ },
+ "win10": {
+ "title": "Windows 10",
+ "uaVersion": "10"
+ }
+ },
+ "autodetectFunction": "autodetectClientWindowsVersion"
+ },
+ "ev3dev-hardware-platform": {
+ "values": {
+ "ev3": {
+ "title": "EV3 Brick"
+ },
+ "brickpi": {
+ "title": "BrickPi"
+ },
+ "pistorms": {
+ "title": "PiStorms"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/_includes/head.html b/_includes/head.html
index ed50fedb0..d36aaf907 100644
--- a/_includes/head.html
+++ b/_includes/head.html
@@ -25,10 +25,10 @@
-
-
-
-
+
+
+
+
@@ -36,6 +36,7 @@
+
diff --git a/_layouts/none.html b/_layouts/none.html
new file mode 100644
index 000000000..e0f6bfe54
--- /dev/null
+++ b/_layouts/none.html
@@ -0,0 +1,5 @@
+---
+
+---
+
+{{ content }}
\ No newline at end of file
diff --git a/docs/tutorials/platform-test-page.md b/docs/tutorials/platform-test-page.md
new file mode 100644
index 000000000..84844483a
--- /dev/null
+++ b/docs/tutorials/platform-test-page.md
@@ -0,0 +1,43 @@
+---
+title: Platform test page
+subject: Website
+---
+
+This is a test page.
+
+* {: data-platform-attribute-value-id="android"}
+ 1. This is the first step for Android.
+
+ 2. This is the second step for Android.
+
+* {: data-platform-attribute-value-id="osx"}
+
+ 1. Another step! This one's for Mac.
+
+ 2. ...And another for Mac.
+
+* {: data-platform-attribute-value-id="ubuntu"}
+
+ 1. Even more steps! Now featuring 100% more Ubuntu.
+
+ 2. Steps continued.
+
+* {: data-platform-attribute-value-id="windows"}
+ * {: data-platform-attribute-value-id="win7"} This is for Windows 7!
+
+ * {: data-platform-attribute-value-id="win8"} This is for Windows 8!
+
+ * {: data-platform-attribute-value-id="win10"} This is for Windows 10!
+ {: data-platform-select-list-attribute="client-windows-version"}
+{: data-platform-select-list-attribute="client-platform" }
+
+* {: data-platform-attribute-value-id="ev3"}
+ On the EV3, do a thing in this specific way.
+
+* {: data-platform-attribute-value-id="brickpi"}
+ The BrickPi is a little different. You actually need to do this other thing.
+
+* {: data-platform-attribute-value-id="pistorms"}
+ The PiStorms doesn't support this portion of the functionality.
+ You need to take this into consideration.
+{: data-platform-select-list-attribute="ev3dev-hardware-platform" }
\ No newline at end of file
diff --git a/javascripts/jquery.getUrlParam.js b/javascripts/libs/jquery.getUrlParam.js
similarity index 100%
rename from javascripts/jquery.getUrlParam.js
rename to javascripts/libs/jquery.getUrlParam.js
diff --git a/javascripts/jquery.loadTemplate-1.4.4.min.js b/javascripts/libs/jquery.loadTemplate-1.4.4.min.js
similarity index 100%
rename from javascripts/jquery.loadTemplate-1.4.4.min.js
rename to javascripts/libs/jquery.loadTemplate-1.4.4.min.js
diff --git a/javascripts/respond.js b/javascripts/libs/respond.js
similarity index 100%
rename from javascripts/respond.js
rename to javascripts/libs/respond.js
diff --git a/javascripts/libs/ua-parser.min.js b/javascripts/libs/ua-parser.min.js
new file mode 100644
index 000000000..faf7e19b7
--- /dev/null
+++ b/javascripts/libs/ua-parser.min.js
@@ -0,0 +1,8 @@
+/**
+ * UAParser.js v0.7.10
+ * Lightweight JavaScript-based User-Agent string parser
+ * https://github.com/faisalman/ua-parser-js
+ *
+ * Copyright © 2012-2015 Faisal Salman
+ * Dual licensed under GPLv2 & MIT
+ */(function(e,t){"use strict";var n="0.7.10",r="",i="?",s="function",o="undefined",u="object",a="string",f="major",l="model",c="name",h="type",p="vendor",d="version",v="architecture",m="console",g="mobile",y="tablet",b="smarttv",w="wearable",E="embedded",S={extend:function(e,t){for(var n in t)"browser cpu device engine os".indexOf(n)!==-1&&t[n].length%2===0&&(e[n]=t[n].concat(e[n]));return e},has:function(e,t){return typeof e=="string"?t.toLowerCase().indexOf(e.toLowerCase())!==-1:!1},lowerize:function(e){return e.toLowerCase()},major:function(e){return typeof e===a?e.split(".")[0]:t}},x={rgx:function(){var e,n=0,r,i,a,f,l,c,h=arguments;while(n0?f.length==2?typeof f[1]==s?e[f[0]]=f[1].call(this,c):e[f[0]]=f[1]:f.length==3?typeof f[1]===s&&(!f[1].exec||!f[1].test)?e[f[0]]=c?f[1].call(this,c,f[2]):t:e[f[0]]=c?c.replace(f[1],f[2]):t:f.length==4&&(e[f[0]]=c?f[3].call(this,c.replace(f[1],f[2])):t):e[f]=c?c:t}n+=2}return e},str:function(e,n){for(var r in n)if(typeof n[r]===u&&n[r].length>0){for(var s=0;s')
+ .data('target-platform-attribute-name', platformAttributeId);
+ $platNav.insertAfter($('.page-header'));
+ }
+ else if ($platNav.children().filter(getFilterByData('platform-attribute-value-id', newAttributeValueId)).length > 0) {
+ // If there are any pills that have already been created for this value, we are done
+ return;
+ }
+
+ var $pillItem = $('')
+ .data('platform-attribute-value-id', newAttributeValueId)
+ .addClass('platform-select-link');
+
+
+ var platformAttributeMetadata = platformAttributes[platformAttributeId];
+ var newAttributeValueMetadata = platformAttributeMetadata.values[newAttributeValueId];
+ $('').text(newAttributeValueMetadata.title).appendTo($pillItem);
+
+ $pillItem.click(function () {
+ switchSelectedPlatformAttribute(platformAttributeId, newAttributeValueId);
+ })
+
+ $platNav.append($pillItem);
+}
+
+function addNestedPlatformNavItem(platformAttributeId, newAttributeValueId, parentAttributeId, parentAttributeValueId) {
+ addPlatformNavItem(parentAttributeId, parentAttributeValueId);
+
+ // TODO: Use dividers to handle multiple nested attributes
+ // ...or at least blow up loudly
+
+ var $parentPillLi = $('.platform-attribute-select-group')
+ .filter(getFilterByData('target-platform-attribute-name', parentAttributeId))
+ .children()
+ .filter(getFilterByData('platform-attribute-value-id', parentAttributeValueId));
+
+ var $selectGroupDropdown = $parentPillLi.children('ul.platform-nested-select-group');
+
+ if ($selectGroupDropdown.length <= 0) {
+ $parentPillLi.addClass('dropdown');
+
+ var $parentLinkAnchor = $parentPillLi.children('a')
+ .addClass('dropdown-toggle')
+ .attr('data-toggle', 'dropdown')
+ .attr('role', 'button')
+ .append('');
+
+ $selectGroupDropdown = $('')
+ .addClass('dropdown-menu')
+ .addClass('platform-nested-select-group')
+ .data('target-platform-attribute-name', platformAttributeId)
+ .insertAfter($parentLinkAnchor);
+ }
+ else if ($selectGroupDropdown.children('li.nested-platform-select-link').filter(getFilterByData('platform-attribute-value-id', newAttributeValueId)).length > 0) {
+ return;
+ }
+
+ var $newDropdownItem = $('')
+ .data('platform-attribute-value-id', newAttributeValueId)
+ .addClass('nested-platform-select-link')
+ .appendTo($selectGroupDropdown);
+
+ var platformAttributeMetadata = platformAttributes[platformAttributeId];
+ var newAttributeValueMetadata = platformAttributeMetadata.values[newAttributeValueId];
+
+ $('').text(newAttributeValueMetadata.title).appendTo($newDropdownItem);
+
+ $newDropdownItem.click(function () {
+ switchSelectedPlatformAttribute(platformAttributeId, newAttributeValueId);
+ })
+}
+
+function getInitialValueId(attributeId) {
+ var messageBase = "Selected value for property " + attributeId + " from ";
+
+ var htmlStorageValue, autodetectFunctionName, autodetectValue;
+ var urlParamValue = $(document).getUrlParam(cleanTextForId(attributeId));
+
+ if (urlParamValue && urlParamValue in platformAttributes[attributeId].values) {
+ console.log(messageBase + "URL param");
+
+ return urlParamValue;
+ }
+ else if (supportsHtml5Storage() && (htmlStorageValue = localStorage.getItem('platform-' + cleanTextForId(attributeId)))) {
+ console.log(messageBase + "HTML5 local storage");
+
+ return htmlStorageValue;
+ }
+ else if ((autodetectFunctionName = platformAttributes[attributeId].autodetectFunction)
+ && (autodetectValue = autodetectFunctions[autodetectFunctionName]())) {
+
+ console.log(messageBase + "autodetect function");
+
+ return autodetectValue;
+ }
+ else {
+ console.log(messageBase + "default first option");
+
+ return $('.platform-attribute-select-group, .platform-nested-select-group')
+ .filter(getFilterByData('target-platform-attribute-name', attributeId))
+ .children(':first')
+ .data('platform-attribute-value-id');
+ }
+}
+
+function expandPlatformSelectList($platformUl, parentInfo) {
+ var targetAttributeId = $platformUl.data('platform-select-list-attribute');
+
+ var $platformContentContainer = $('');
+ $platformContentContainer.insertBefore($platformUl);
+
+ if(!!parentInfo) {
+ $platformContentContainer.addClass("nested-platform-select");
+ }
+
+ $platformUl.detach();
+
+ // TODO: Either use the value data that has already been generated or don't generate it
+ $platformUl.children('li[data-platform-attribute-value-id]').each(function (i, platformLi) {
+ var $platformLi = $(platformLi);
+ var currentPlatformAttributeValueId = $platformLi.data('platform-attribute-value-id');
+
+ var $newPlatformContentItem = $('').addClass("platform-content-item");
+ $newPlatformContentItem.attr('id', 'plat-' + cleanTextForId(targetAttributeId) + '-' + cleanTextForId(currentPlatformAttributeValueId));
+ $newPlatformContentItem.data({
+ 'platform-attribute-name': targetAttributeId,
+ 'platform-attribute-value-id': currentPlatformAttributeValueId
+ });
+
+ $newPlatformContentItem.append($platformLi.contents().detach());
+ $newPlatformContentItem.appendTo($platformContentContainer);
+
+ if(!!parentInfo)
+ addNestedPlatformNavItem(targetAttributeId, currentPlatformAttributeValueId, parentInfo.attributeId, parentInfo.valueId);
+ else
+ addPlatformNavItem(targetAttributeId, currentPlatformAttributeValueId);
+ });
+}
+
+$(document).ready(function () {
+
+ var platformAttributeMapping = {};
+ var usedPlatformAttributes = [];
+
+ $('ul[data-platform-select-list-attribute]').each(function (i, platformUl) {
+ var $platformUl = $(platformUl);
+ var targetAttributeId = $platformUl.data('platform-select-list-attribute');
+
+ usedPlatformAttributes.push(targetAttributeId);
+
+ var $parentPlatformValueLi = $platformUl.parents('[data-platform-attribute-value-id]');
+ var $parentPlatformUl = $parentPlatformValueLi.parents('[data-platform-select-list-attribute]');
+ var isNestedContent = $parentPlatformUl.length > 0;
+
+ var attributeMappingObject;
+ if(isNestedContent) {
+ var parentAttributeId = $parentPlatformUl.data('platform-select-list-attribute');
+ var parentAttributeValueId = $parentPlatformValueLi.data('platform-attribute-value-id');
+
+ createObjectTree(platformAttributeMapping, parentAttributeId, "values", parentAttributeValueId, "nestedAttributes", targetAttributeId);
+
+ attributeMappingObject = platformAttributeMapping[parentAttributeId]
+ .values[parentAttributeValueId]
+ .nestedAttributes[targetAttributeId];
+ }
+ else {
+ if(!platformAttributeMapping[targetAttributeId])
+ platformAttributeMapping[targetAttributeId] = {};
+
+ attributeMappingObject = platformAttributeMapping[targetAttributeId];
+ }
+
+ $platformUl.attr('id', 'plat-' + cleanTextForId(targetAttributeId));
+ attributeMappingObject.domId = $platformUl.attr('id');
+ attributeMappingObject.values = {};
+
+ $platformUl.children('li[data-platform-attribute-value-id]').each(function (i, platformLi) {
+ var $platformLi = $(platformLi);
+ var currentPlatformAttributeValueId = $platformLi.data('platform-attribute-value-id');
+
+ $platformLi.attr('id', 'plat-' + cleanTextForId(targetAttributeId) + '-' + cleanTextForId(currentPlatformAttributeValueId));
+
+ attributeMappingObject.values[currentPlatformAttributeValueId] = {
+ domId: $platformLi.attr('id')
+ };
+ });
+ });
+
+ for (var attributeId in platformAttributeMapping) {
+ var attributeObj = platformAttributeMapping[attributeId];
+
+ var $platformUl = $('#' + attributeObj.domId);
+ expandPlatformSelectList($platformUl);
+
+ for (var valueId in attributeObj.values) {
+
+ if (!!attributeObj.values[valueId].nestedAttributes) {
+ for (var nestedAttributeId in attributeObj.values[valueId].nestedAttributes) {
+ var attributeObj = attributeObj.values[valueId].nestedAttributes[nestedAttributeId];
+
+ var $nestedPlatformUl = $('#' + attributeObj.domId);
+ expandPlatformSelectList($nestedPlatformUl, { attributeId: attributeId, valueId: valueId });
+ }
+ }
+ }
+ }
+
+ for(var i = 0; i < usedPlatformAttributes.length; i++) {
+ var attributeName = usedPlatformAttributes[i];
+ var initialValueId = getInitialValueId(attributeName);
+
+ switchSelectedPlatformAttribute(attributeName, initialValueId);
+ }
+});
diff --git a/javascripts/search.js b/javascripts/search.js
index e8df6eafe..b70bd9d01 100644
--- a/javascripts/search.js
+++ b/javascripts/search.js
@@ -10,7 +10,7 @@ $(document).ready(function () {
newsResultArea = $('#search-results-news > div');
miscResultArea = $('#search-results-misc > div');
- var searchQuery = getQueryParam("search");
+ var searchQuery = $(document).getUrlParam("search");
if (searchQuery != undefined && searchQuery != "") { //If a search query was provided in the query strings, execute the search
loadSearchData(function () {
searchUpdate();
@@ -118,14 +118,6 @@ function findResults(term) {
return result;
}
-//Function to read query parameters
-function getQueryParam(name) {
- name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
- var regex = new RegExp("[\\?&]" + name + "=([^]*)"),
- results = regex.exec(location.search);
- return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
-}
-
//Updates the search function as a whole, and manages the visuals as necessary
function searchUpdate() {
var searchString = $("#search-input").val();
diff --git a/javascripts/ua-parser.min.js b/javascripts/ua-parser.min.js
deleted file mode 100644
index a7c824c20..000000000
--- a/javascripts/ua-parser.min.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * UAParser.js v0.7.8
- * Lightweight JavaScript-based User-Agent string parser
- * https://github.com/faisalman/ua-parser-js
- *
- * Copyright © 2012-2015 Faisal Salman
- * Dual licensed under GPLv2 & MIT
- */
-(function(window,undefined){"use strict";var LIBVERSION="0.7.8",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",MAJOR="major",MODEL="model",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",EMBEDDED="embedded";var util={extend:function(regexes,extensions){for(var i in extensions){if("browser cpu device engine os".indexOf(i)!==-1&&extensions[i].length%2===0){regexes[i]=extensions[i].concat(regexes[i])}}return regexes},has:function(str1,str2){if(typeof str1==="string"){return str2.toLowerCase().indexOf(str1.toLowerCase())!==-1}else{return false}},lowerize:function(str){return str.toLowerCase()},major:function(version){return typeof version===STR_TYPE?version.split(".")[0]:undefined}};var mapper={rgx:function(){var result,i=0,j,k,p,q,matches,match,args=arguments;while(i0){if(q.length==2){if(typeof q[1]==FUNC_TYPE){result[q[0]]=q[1].call(this,match)}else{result[q[0]]=q[1]}}else if(q.length==3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){result[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{result[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length==4){result[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{result[q]=match?match:undefined}}}}i+=2}return result},str:function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j