238 lines
8 KiB
HTML
238 lines
8 KiB
HTML
---
|
|
layout: page
|
|
title: "Components"
|
|
description: "List of the built-in components of Home Assistant."
|
|
date: 2014-12-21 13:35
|
|
sidebar: false
|
|
comments: false
|
|
sharing: true
|
|
footer: true
|
|
is_homepage: true
|
|
hide_github_edit: true
|
|
body_id: components-page
|
|
regenerate: true
|
|
---
|
|
|
|
{% assign count = site.components | size %}
|
|
{% assign nocat = site.components | where: 'ha_category', null | size %}
|
|
{% assign tot = count | minus: nocat %}
|
|
{% assign components = site.components | sort: 'title' %}
|
|
{% assign categories = components | sort: 'ha_category' | map: 'ha_category' | uniq %}
|
|
{% capture current_version %}{{ site.current_major_version }}.{{ site.current_minor_version }}{% endcapture %}
|
|
{% assign added_one_ago_minor_version = site.current_minor_version|minus: 1 %}
|
|
{% capture added_one_ago_version %}{{ site.current_major_version }}.{{ added_one_ago_minor_version }}{% endcapture %}
|
|
{% assign added_two_ago_minor_version = site.current_minor_version|minus: 2 %}
|
|
{% capture added_two_ago_version %}{{ site.current_major_version }}.{{ added_two_ago_minor_version }}{% endcapture %}
|
|
{% assign current_version_components_count = site.components | where: 'ha_release', current_version | size %}
|
|
{% assign one_ago_version_components_count = site.components | where: 'ha_release', added_one_ago_version | size %}
|
|
{% assign two_ago_version_components_count = site.components | where: 'ha_release', added_two_ago_version | size %}
|
|
|
|
<p class='note'>
|
|
Support for these components is provided by the Home Assistant community.
|
|
</p>
|
|
<div class="grid">
|
|
<div class="grid__item one-sixth lap-one-whole palm-one-whole">
|
|
|
|
<div class="filter-button-group">
|
|
<a href='#all' class="btn">All ({{tot}})</a>
|
|
<a href='#featured' class="btn featured">Featured</a>
|
|
<a href='#added_in_current_version' class="btn added_in_current_version">Added in {{ current_version }} ({{ current_version_components_count }})</a>
|
|
<a href='#added_one_version_ago' class="btn added_one_version_ago">Added in {{ added_one_ago_version }} ({{ one_ago_version_components_count }})</a>
|
|
<a href='#added_two_versions_ago' class="btn added_two_versions_ago">Added in {{ added_two_ago_version }} ({{ two_ago_version_components_count }})</a>
|
|
|
|
{% for category in categories %}
|
|
{% if category and category != 'Other' %}
|
|
<a href='#{{ category | slugify }}' class="btn">
|
|
{{ category }}
|
|
({{ components | where: 'ha_category', category | size }})
|
|
</a>
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
<a href='#other' class="btn">Other</a>
|
|
</div>
|
|
</div>
|
|
<div class="grid__item five-sixths lap-one-whole palm-one-whole">
|
|
<div class="component-search">
|
|
<form onsubmit="event.preventDefault(); return false">
|
|
<input type="text" name="search" id="search" class="search" placeholder="Search components...">
|
|
</form>
|
|
</div>
|
|
<div class="hass-option-cards" id="componentContainer">
|
|
{% for component in components %}
|
|
{% if component.ha_category %}
|
|
{% assign sliced_version = component.ha_release | split: '.' %}
|
|
{% assign minor_version = sliced_version[1]|plus: 0 %}
|
|
<a href='{{ component.url }}'
|
|
class='option-card {{ component.ha_category | slugify }}{% if minor_version == site.current_minor_version %} added_in_current_version{% elsif minor_version == added_one_ago_minor_version %} added_one_version_ago{% elsif minor_version == added_two_ago_minor_version %} added_two_versions_ago{% endif %}{% if component.featured %} featured{% endif %}'
|
|
data-title="{{component.title| downcase}}"
|
|
data-ha_category="{{component.ha_category | downcase}}"
|
|
{% unless component.featured %}style='display: none'{% endunless %}>
|
|
<div class='img-container'>
|
|
{% if component.logo %}
|
|
<img src='/images/supported_brands/{{ component.logo }}'>
|
|
{% endif %}
|
|
</div>
|
|
<div class='title'>{{ component.title }}</div>
|
|
<div class='category'>{{ component.ha_category }}</div>
|
|
</a>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% comment %}
|
|
## Pages without categories
|
|
{% for component in components %}
|
|
{% unless component.ha_category %}
|
|
<p>{{ component.title }}</p>
|
|
{% endunless %}
|
|
{% endfor %}
|
|
{% endcomment %}
|
|
|
|
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
|
|
<script>
|
|
// undo initial hiding of non-featured cards
|
|
(function(){
|
|
var hash = location.hash;
|
|
if (hash !== '') {
|
|
if (hash === '#all' || hash.indexOf('#search/') === 0) {
|
|
jQuery('#componentContainer a').show();
|
|
} else {
|
|
jQuery('#componentContainer .featured').hide();
|
|
jQuery('#componentContainer .' + hash.substr(1)).show();
|
|
}
|
|
|
|
if (hash.indexOf('#search/') === 0) {
|
|
// set default value in search from URL
|
|
jQuery('.component-search input').val(decodeURIComponent(hash).substring(8));
|
|
}
|
|
}
|
|
})();
|
|
</script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.isotope/2.2.2/isotope.pkgd.min.js"></script>
|
|
<script>
|
|
$(window).load(function(){
|
|
var $isotope = $('#componentContainer').isotope({
|
|
filter: '.featured',
|
|
animationOptions: {
|
|
duration: 750,
|
|
easing: 'linear',
|
|
queue: false
|
|
},
|
|
masonry: {
|
|
columnWidth: 210
|
|
},
|
|
getSortData: {
|
|
title: function( itemElem ) {
|
|
var title = $( itemElem ).find('.title').text();
|
|
return title ? title.toLowerCase() : '';
|
|
}
|
|
},
|
|
sortBy: 'title'
|
|
});
|
|
|
|
/**
|
|
* update the browser location hash. This enables users to use the browser-history
|
|
*/
|
|
function updateHash(newHash) {
|
|
if ('replaceState' in history) {
|
|
history.replaceState('', '', newHash);
|
|
} else {
|
|
location.hash = newHash;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* filter all components, based on the location's hash
|
|
*/
|
|
function applyFilter() {
|
|
var hash = location.hash;
|
|
var filter;
|
|
|
|
if (hash == '') {
|
|
filter = '.featured';
|
|
hash = '#featured';
|
|
|
|
} else if (hash === '#all') {
|
|
// show all elements
|
|
filter = '*';
|
|
|
|
} else if (hash.indexOf('#search/') === 0) {
|
|
// search for the given string
|
|
var text = decodeURIComponent(hash).substring(8).toLowerCase();
|
|
text = text.replace(/[(\?|\&\{\}\(\))]/gi, '').toLowerCase();
|
|
|
|
if(text && text.length === 0){
|
|
filter = '*';
|
|
} else {
|
|
filter = function() {
|
|
var title = $(this).data('title');
|
|
var cat = $(this).data('ha_category');
|
|
return title.indexOf(text) != -1 || cat.indexOf(text) != -1;
|
|
};
|
|
}
|
|
|
|
} else {
|
|
filter = '.' + hash.substr(1);
|
|
}
|
|
|
|
if (!hash.indexOf('#search/') === 0) {
|
|
// reset the search field when no longer searching
|
|
$('.component-search input').val(null);
|
|
}
|
|
|
|
$('.filter-button-group a.current').removeClass('current');
|
|
$('.filter-button-group a[href="'+hash+'"]').addClass('current');
|
|
|
|
$isotope.isotope({
|
|
filter: filter
|
|
});
|
|
}
|
|
|
|
// update view by filter selection
|
|
jQuery('.filter-button-group a').click(function() {
|
|
updateHash(this.getAttribute('href'));
|
|
applyFilter();
|
|
|
|
return false;
|
|
});
|
|
|
|
/**
|
|
* Simple debounce implementation, based on http://davidwalsh.name/javascript-debounce-function
|
|
*/
|
|
function debounce(func, wait, immediate) {
|
|
var timeout;
|
|
return function() {
|
|
var context = this, args = arguments;
|
|
var later = function() {
|
|
timeout = null;
|
|
if (!immediate) {
|
|
func.apply(context, args);
|
|
}
|
|
};
|
|
var callNow = immediate && !timeout;
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(later, wait);
|
|
if (callNow) {
|
|
func.apply(context, args);
|
|
}
|
|
};
|
|
};
|
|
|
|
// update view by search text
|
|
$('.component-search input').keyup(debounce(function() {
|
|
var text = $(this).val();
|
|
// sanitize input
|
|
text = text.replace(/[(\?|\&\{\}\(\))]/gi, '');
|
|
updateHash('#search/' + text);
|
|
applyFilter();
|
|
}, 500));
|
|
|
|
window.addEventListener('hashchange', applyFilter);
|
|
|
|
// initialize from URL
|
|
applyFilter();
|
|
});
|
|
</script>
|