diff --git a/docs/api/responses/manifest.md b/docs/api/responses/manifest.md
index bc8f4b6..148fd23 100755
--- a/docs/api/responses/manifest.md
+++ b/docs/api/responses/manifest.md
@@ -108,7 +108,7 @@ When setting the `manifest.config` property, the landing page will redirect to `
``key`` - _required_ - string, a key that will identify the user chosen value
-``type`` - _required_ - string, can be "text", "number", "password", "checkbox" or "select"
+``type`` - _required_ - string, can be "text", "number", "password", "checkbox", "select" or "multiselect"
``default`` - _optional_ - string, the default value, for `type: "boolean"` this can be set to "checked" to default to enabled
diff --git a/src/landingTemplate.js b/src/landingTemplate.js
index 1f9a619..6c5bc23 100644
--- a/src/landingTemplate.js
+++ b/src/landingTemplate.js
@@ -163,6 +163,78 @@ button:active {
.full-width {
width: 100%;
}
+
+.custom-dropdown {
+ position: relative;
+ display: inline-block;
+ width: 100%;
+}
+
+.custom-dropdown .dropdown-content {
+ top: 100%;
+ left: 0;
+}
+
+.dropdown-button {
+ background-color: #8A5AAB;
+ color: white;
+ padding: 1.2vh 3.5vh;
+ text-align: center;
+ cursor: pointer;
+ width: 100%;
+ border: none;
+ font-size: 2.2vh;
+ font-weight: 600;
+ box-shadow: 0 0.5vh 1vh rgba(0, 0, 0, 0.2);
+}
+
+.dropdown-button:hover {
+ box-shadow: none;
+}
+
+.dropdown-content {
+ display: none;
+ position: absolute;
+ background-color: #f9f9f9;
+ min-width: 100%;
+ box-shadow: 0 1vh 2vh rgba(0, 0, 0, 0.2);
+ z-index: 1;
+ max-height: 30vh;
+ overflow-y: auto;
+}
+
+.dropdown-content label {
+ display: block;
+ padding: 1vh;
+ cursor: pointer;
+ color: black;
+}
+
+.dropdown-content input {
+ margin-right: 1vh;
+}
+
+.show {
+ display: block !important;
+}
+
+.selected-items {
+ margin-top: 1vh;
+ padding: 1vh;
+ background-color: #333;
+ color: white;
+ border-radius: 0.5vh;
+}
+
+.selected-item {
+ display: inline-block;
+ background-color: #8A5AAB;
+ color: white;
+ padding: 0.5vh 1vh;
+ margin-right: 1vh;
+ margin-bottom: 1vh;
+ border-radius: 0.5vh;
+}
`
function landingTemplate(manifest) {
@@ -203,6 +275,30 @@ function landingTemplate(manifest) {
`
+ } else if (elem.type === 'multiselect') {
+ options += `
+
+ `
} else if (elem.type === 'select') {
const defaultValue = elem.default || (elem.options || [])[0]
options += `
@@ -215,8 +311,8 @@ function landingTemplate(manifest) {
options += ``
})
options += `
-
- `
+
+ `
}
})
if (options.length) {
@@ -231,10 +327,65 @@ function landingTemplate(manifest) {
installLink.onclick = () => {
return mainForm.reportValidity()
}
+
+ const updateSelectedItems = (selectElement, selectedItemsContainer) => {
+ selectedItemsContainer.innerHTML = ''
+ const selectedOptions = []
+ selectElement.querySelectorAll('input[type="checkbox"]').forEach(checkbox => {
+ if (checkbox.checked) {
+ selectedOptions.push(checkbox.value)
+ const itemDiv = document.createElement('div')
+ itemDiv.classList.add('selected-item')
+ itemDiv.textContent = checkbox.value
+ selectedItemsContainer.appendChild(itemDiv)
+ }
+ })
+ return selectedOptions
+ }
+
const updateLink = () => {
- const config = Object.fromEntries(new FormData(mainForm))
+ const config = Object.fromEntries(new FormData(mainForm).entries())
+ const multiSelects = Array.from(mainForm.querySelectorAll('.custom-dropdown'))
+ multiSelects.forEach(select => {
+ const selectId = select.querySelector('.dropdown-button').id.replace('-dropdown', '')
+ const selectedValues = updateSelectedItems(select.querySelector('.dropdown-content'), document.getElementById(selectId + '-selected-items'))
+ config[selectId] = selectedValues
+ })
installLink.href = 'stremio://' + window.location.host + '/' + encodeURIComponent(JSON.stringify(config)) + '/manifest.json'
}
+
+ document.querySelectorAll('.dropdown-button').forEach(button => {
+ const selectElement = document.getElementById(button.id.replace('-dropdown', '-options'))
+ const selectedItemsContainer = document.getElementById(button.id.replace('-dropdown', '-selected-items'))
+ button.onclick = (event) => {
+ event.stopPropagation()
+ selectElement.classList.toggle('show')
+ const dropdownRect = selectElement.getBoundingClientRect()
+ const dropdownHeight = dropdownRect.height
+
+ if (dropdownRect.bottom > window.innerHeight) {
+ selectElement.style.top = "-" + dropdownHeight + "px"
+ } else {
+ selectElement.style.top = '100%'
+ }
+ }
+ selectElement.querySelectorAll('input[type="checkbox"]').forEach(checkbox => {
+ checkbox.onchange = () => {
+ updateSelectedItems(selectElement, selectedItemsContainer)
+ updateLink()
+ }
+ })
+ })
+
+ document.onclick = (event) => {
+ const isDropdownButton = event.target.classList.contains('dropdown-button')
+ document.querySelectorAll('.dropdown-content').forEach(dropdown => {
+ if (!dropdown.contains(event.target) && !isDropdownButton) {
+ dropdown.classList.remove('show')
+ }
+ })
+ }
+
mainForm.onchange = updateLink
`
}
@@ -292,3 +443,4 @@ function landingTemplate(manifest) {
}
module.exports = landingTemplate
+