├── open_demo.png ├── screenshot.png ├── .gitignore ├── Dockerfile ├── public ├── appcache.manifest ├── localization.js ├── edit.js ├── style.css ├── swiper.js ├── newsapi.js ├── picker.js ├── client.js └── cobi-style.css ├── package.json ├── LICENSE ├── server.js ├── views └── index.html └── README.md /open_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cobi-bike/Module-News/HEAD/open_demo.png -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cobi-bike/Module-News/HEAD/screenshot.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Ignore node, git and file system files 3 | /node_modules 4 | /.bashrc 5 | /.config 6 | /.data 7 | .DS_Store 8 | /.env 9 | /.glitch-assets 10 | /.gitconfig 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:carbon-alpine 2 | 3 | # Create app directory 4 | WORKDIR /usr/src/app 5 | 6 | ENV PORT=3000 7 | 8 | COPY package.json . 9 | 10 | RUN npm install --production 11 | 12 | COPY . . 13 | 14 | EXPOSE 3000 15 | CMD [ "npm", "start" ] 16 | -------------------------------------------------------------------------------- /public/appcache.manifest: -------------------------------------------------------------------------------- 1 | CACHE MANIFEST 2 | # Version 49 3 | 4 | CACHE: 5 | # Defines resources to be cached: 6 | client.js 7 | cobi-style.css 8 | edit.js 9 | localization.js 10 | newsapi.js 11 | picker.js 12 | style.css 13 | swiper.js 14 | 15 | NETWORK: 16 | * 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cobi-module-news", 3 | "version": "0.0.1", 4 | "description": "The News DevKit module displays the latest news headlines and allows to add them to your read later list.", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "node server.js" 8 | }, 9 | "license": "MIT", 10 | "dependencies": { 11 | "express": "^4.16.3", 12 | "request": "^2.88.0" 13 | }, 14 | "engines": { 15 | "node": "6.9.1" 16 | }, 17 | "repository": { 18 | "url": "https://github.com/cobi-bike/Module-News" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 COBI.bike 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | // init project 2 | var express = require('express'); 3 | var request = require('request'); 4 | var app = express(); 5 | 6 | // Set port from environment variable or default 7 | var port = process.env.PORT || 3000; 8 | 9 | // Set environment variables 10 | var newsapi_key = process.env.NEWSAPI_KEY; 11 | 12 | // If env variables are not set, quit application with error exit code 13 | if (!newsapi_key) { 14 | console.log("Error: Missing environment variables") 15 | process.exit(1); 16 | } 17 | 18 | // http://expressjs.com/en/starter/static-files.html 19 | app.use(express.static('public')); 20 | 21 | // http://expressjs.com/en/starter/basic-routing.html 22 | app.get('/', function(req, resp) { 23 | resp.sendFile(__dirname + '/views/index.html'); 24 | }); 25 | 26 | // Serve a proxy to the newsapi backend 27 | app.get('/news/:source', function(req, resp) { 28 | var url = 'https://newsapi.org/v2/top-headlines?sources=' + req.params.source + '&apiKey=' + newsapi_key; 29 | request.get(url).pipe(resp); 30 | }); 31 | 32 | // listen for requests :) 33 | var listener = app.listen(port, function() { 34 | console.log('Your app is listening on port ' + listener.address().port); 35 | }); 36 | -------------------------------------------------------------------------------- /public/localization.js: -------------------------------------------------------------------------------- 1 | // Initialize localization with language set by cobi parameter 2 | i18next.init( 3 | { 4 | lng: COBI.parameters.language(), 5 | fallbackLng: ['en', 'de'], 6 | whitelist: ['en', 'de'], 7 | resources: { 8 | en: { 9 | translation: { 10 | 'read-later': 'Added to Reading List 👌', 11 | 'read-later-tts': 'Added to your reading list', 12 | 'hidden-title': '💬', 13 | 'connection-error': 'Connection to server has failed.', 14 | business: 'Business', 15 | entertainment: 'Entertainment', 16 | general: 'General', 17 | technology: 'Technology', 18 | sport: 'Sport' 19 | } 20 | }, 21 | de: { 22 | translation: { 23 | 'read-later': 'Auf Leseliste hinzugefügt 👌', 24 | 'read-later-tts': 'Auf deine Leseliste hinzugefügt', 25 | 'hidden-title': '💬', 26 | 'connection-error': 'Verbindung zum Server fehlgeschlagen.', 27 | business: 'Business', 28 | entertainment: 'Unterhaltung', 29 | general: 'Allgemein', 30 | technology: 'Technologie', 31 | sport: 'Sport' 32 | } 33 | } 34 | } 35 | }, 36 | function(err, t) {} 37 | ); 38 | -------------------------------------------------------------------------------- /public/edit.js: -------------------------------------------------------------------------------- 1 | var localStorageKeyArticleDescription = 'readlater-articledescription'; 2 | var localStorageKeyJumpCategory = 'readlater-jumpcategory'; 3 | var localStorageKeyCategory = 'category'; 4 | 5 | // UI Switcher 6 | if (COBI.parameters.context() == COBI.context.offRideSettings || COBI.parameters.context() == COBI.context.onRideSettings) { 7 | document.getElementById('experience').style.display = 'none'; 8 | } else { 9 | document.getElementById('edit').style.display = 'none'; 10 | } 11 | 12 | // Manage Settings 13 | 14 | // Setting: Article Description 15 | 16 | var articleDescriptionToggle = document.getElementById('articleDescriptionToggle'); 17 | articleDescriptionToggle.checked = getArticleDescriptionSetting(); 18 | articleDescriptionToggle.onchange = function() { 19 | setArticleDescriptionSetting(articleDescriptionToggle.checked); 20 | }; 21 | 22 | function getArticleDescriptionSetting() { 23 | var value = JSON.parse(localStorage.getItem(localStorageKeyArticleDescription)); 24 | if (value === null) { 25 | return false; 26 | } else { 27 | return value; 28 | } 29 | } 30 | 31 | function setArticleDescriptionSetting(value) { 32 | localStorage.setItem(localStorageKeyArticleDescription, JSON.stringify(value)); 33 | } 34 | 35 | // Setting: Jump Category 36 | 37 | var jumpCategoryToggle = document.getElementById('jumpCategoryToggle'); 38 | jumpCategoryToggle.checked = getJumpCategorySetting(); 39 | jumpCategoryToggle.onchange = function() { 40 | setJumpCategorySetting(jumpCategoryToggle.checked); 41 | }; 42 | 43 | function getJumpCategorySetting() { 44 | var value = JSON.parse(localStorage.getItem(localStorageKeyJumpCategory)); 45 | if (value === null) { 46 | return true; 47 | } else { 48 | return value; 49 | } 50 | } 51 | 52 | function setJumpCategorySetting(value) { 53 | localStorage.setItem(localStorageKeyJumpCategory, JSON.stringify(value)); 54 | } 55 | 56 | // Getter & Setter for last viewed category 57 | function getLastCategory() { 58 | var value = JSON.parse(localStorage.getItem(localStorageKeyCategory)); 59 | return value; 60 | } 61 | 62 | function setLastCategory(value) { 63 | localStorage.setItem(localStorageKeyCategory, JSON.stringify(value)); 64 | } 65 | 66 | // Getter & Setter for if a news source is enabled 67 | function getSourceEnabled(sourceId) { 68 | var value = localStorage.getItem(sourceId); 69 | if (value === null) { 70 | return null; 71 | } else { 72 | return JSON.parse(value); 73 | } 74 | } 75 | 76 | function setSourceEnabled(sourceId, value) { 77 | localStorage.setItem(sourceId, JSON.stringify(value)); 78 | } 79 | -------------------------------------------------------------------------------- /public/style.css: -------------------------------------------------------------------------------- 1 | /* styles */ 2 | /*@import url(https://cdn.cobi.bike/static/fonts/UniSansLight.css);*/ 3 | @import url(https://cdn.cobi.bike/static/fonts/UniSansRegular.css); 4 | @import url(https://cdn.cobi.bike/static/fonts/UniSansSemiBold.css); 5 | @import url(https://cdn.cobi.bike/static/fonts/UniSansBook.css); 6 | @import url(https://fonts.googleapis.com/css?family=Open+Sans:400,300,600,700,600italic,400italic,300italic,700italic,800,800italic); 7 | @import url(https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.1/css/swiper.min.css); 8 | @import url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css); 9 | 10 | html, body { 11 | position: relative; 12 | width: 100%; 13 | height: 100%; 14 | font-familly: 'UniSansBold'; 15 | } 16 | body { 17 | background: #2d2d37 !important; 18 | font-familly: 'UniSansBold'; 19 | font-size: 14px; 20 | 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | #toast-container { 26 | top: auto !important; 27 | right: auto !important; 28 | bottom: 25%; 29 | left:0%; 30 | } 31 | 32 | /* Materialize blinking cursor fix on iOS */ 33 | input.select-dropdown { 34 | -webkit-user-select:none; 35 | -moz-user-select:none; 36 | -ms-user-select:none; 37 | -o-user-select:none; 38 | user-select:none; 39 | } 40 | 41 | #settings { 42 | position: fixed; 43 | left: 0; 44 | right: 0; 45 | top: 0; 46 | bottom: 0; 47 | height: 100%; 48 | width: 100%; 49 | z-index: 5; 50 | background: rgba(0, 0, 0, 0.5); 51 | } 52 | 53 | .swiper-container { 54 | width: 100vw; 55 | height: 100vh; 56 | z-index:3; 57 | 58 | } 59 | 60 | .swiper-slide { 61 | display: -webkit-box; 62 | display: -ms-flexbox; 63 | display: -webkit-flex; 64 | display: flex; 65 | -webkit-box-pack: center; 66 | -ms-flex-pack: center; 67 | -webkit-justify-content: center; 68 | justify-content: center; 69 | -webkit-box-align: center; 70 | -ms-flex-align: center; 71 | -webkit-align-items: center; 72 | align-items: center; 73 | } 74 | 75 | .background-image { 76 | width: 100vw; 77 | height: 100vh; 78 | background: no-repeat center center; 79 | background-size: cover; 80 | filter: grayscale(92%) blur(3px); 81 | opacity:.25; 82 | } 83 | 84 | .content-app { 85 | position: absolute; 86 | left: 0; 87 | right: 0; 88 | text-align: center; 89 | font-familly: 'UniSansBold'; 90 | } 91 | 92 | .content-app p { 93 | font-family: 'UniSans' !important; 94 | font-weight: 500 !important; 95 | color: #fff !important; 96 | font-weight: 800; 97 | font-size: 6.5vw; 98 | margin: auto 10vw auto 10vw !important; 99 | letter-spacing: 1; 100 | line-height: 8vw; 101 | } 102 | 103 | .swiper-pagination{ 104 | display:none; 105 | } 106 | 107 | .select-wrapper input.select-dropdown { 108 | color: #fff; 109 | } 110 | 111 | 112 | p { 113 | 114 | } 115 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |News reads latest headlines & adds articles to your reading list.
29 |Powered by NewsAPI.org — Sourcecode on Github
36 |
9 |
10 | ## Quickstart: Interactive Demo
11 |
12 | The quickest way to test the module via [Glitch.com](https://glitch.com):
13 |
14 | [
](https://glitch.com/edit/#!/import/github/cobi-bike/Module-News)
15 |
16 | Glitch.com allows you to edit, host and fork Node.js applications for quick prototyping.
17 | Follow the [installation step 2 to 3](#installation-and-setup) and copy the environment variables to the: `.env` file on Glitch.com
18 |
19 | ## Overview
20 | This module utilizes [Newsapi.org](https://newsapi.org/register) to poll the latest news from various news outlets.
21 | The Node.js backend acts as a Newsapi.org proxy and serves a static page to the client, which allows the user to switch between headlines, read its description and add it to his read-later list.
22 |
23 | ## Installation and Setup
24 |
25 | You can easily deploy the module on your own:
26 |
27 | ### Step 1: Clone repository
28 |
29 | Clone this repository and install Node.js dependencies with:
30 |
31 | ``` bash
32 | npm install
33 | ```
34 |
35 | ### Step 2: Create a Newsapi.org account
36 |
37 | This module relies on [Newsapi.org](https://newsapi.org/register) to poll the latest news from various news outlets. Create an account and retrieve your api key.
38 |
39 | ### Step 3: Set environment variables
40 |
41 | Set the environment variable `NEWSAPI_KEY` with your credentials for newsapi.org
42 |
43 |
44 | ### Step 4: Run Node.js server
45 |
46 | The module is accessible under [localhost:3000](http://localhost:3000/) after starting the Node.js server with:
47 | ``` bash
48 | NEWSAPI_KEY=... node server.js
49 | ```
50 | The settings menu can be accessed with the [?state=edit](http://localhost:3000/?state=edit) suffix.
51 |
52 | ### _Optional_: Install COBI.bike DevKit Simulator
53 |
54 | Follow the [instructions](https://github.com/cobi-bike/DevKit#-test-your-module) to install the COBI.bike Google Chrome Simulator and get familiar with the basics of module development on the COBI plattform.
55 |
56 | ## Useful DevKit links
57 |
58 | * [Debugging Tips & Tricks](https://github.com/cobi-bike/DevKit#debugging-tips--tricks)
59 | * [Inspiration & Examples](https://github.com/cobi-bike/DevKit#inspiration--examples)
60 | * [Interface Guidelines](https://github.com/cobi-bike/DevKit#interface-guidelines)
61 | * [More DevKit Resources](https://github.com/cobi-bike/DevKit#inspiration--examples)
62 | * [Other Tools & Resources](https://github.com/cobi-bike/DevKit#other-tools--resources)
63 |
64 |
65 | ## Contributing to this project
66 |
67 | Anyone and everyone is welcome to contribute to this project, the [DevKit Simulator](https://github.com/cobi-bike/DevKit-Simulator) and the [DevKit UI Components](https://github.com/cobi-bike/DevKit-UI). Please take a moment to review the [guidelines for contributing](https://github.com/cobi-bike/DevKit/blob/master/CONTRIBUTING.md).
68 |
69 | * [Bug reports](https://github.com/cobi-bike/DevKit/blob/master/CONTRIBUTING.md#bugs)
70 | * [Feature requests](https://github.com/cobi-bike/DevKit/blob/master/CONTRIBUTING.md#features)
71 | * [Pull requests](https://github.com/cobi-bike/DevKit/blob/master/CONTRIBUTING.md#pull-requests)
72 |
73 | Copyright © 2018 COBI.bike GmbH
74 |
75 |
76 | ## License
77 | [](https://app.fossa.io/projects/git%2Bgithub.com%2Fcobi-bike%2FModule-News?ref=badge_large)
--------------------------------------------------------------------------------
/public/picker.js:
--------------------------------------------------------------------------------
1 | var categoryPicker = document.getElementById('categoryPicker');
2 | var sourcePicker = document.getElementById('sourcePicker');
3 |
4 | // https://www.i18next.com/overview/api#languages
5 | var language = i18next.languages[0];
6 |
7 | // Returns array of categories by language identifier (e.g. "de-DE")
8 | function getCategoriesByLanguage(language) {
9 | return sources[language.substr(0, 2)];
10 | }
11 |
12 | // Gets called when user picks category
13 | function didPickCategory() {
14 | clearContents();
15 | reloadContents();
16 | populateSourcePicker();
17 | }
18 |
19 | // Get called when user picks news source
20 | function didPickSources() {
21 | saveSourcePreferences();
22 | clearContents();
23 | reloadContents();
24 | }
25 |
26 | // Fills category picker with all categories in the user's language
27 | function populateCategoryPicker() {
28 | var categories = getCategoriesByLanguage(language);
29 | removeAllOptions(categoryPicker);
30 |
31 | for (var i = 0; i < categories.length; i++) {
32 | var option = document.createElement('option');
33 | option.value = categories[i].key;
34 | option.innerHTML = i18next.t(categories[i].key);
35 | categoryPicker.appendChild(option);
36 | }
37 | $('select').material_select();
38 | }
39 |
40 | // Fills news source picker with all sources for the selected category
41 | function populateSourcePicker() {
42 | var categorySources = getCategoriesByLanguage(language)[categoryPicker.selectedIndex].sources;
43 |
44 | removeAllOptions(sourcePicker);
45 | for (var i = 0; i < categorySources.length; i++) {
46 | var categorySource = categorySources[i].key;
47 | var option = document.createElement('option');
48 | option.value = categorySource;
49 | option.innerHTML = categorySources[i].name;
50 | // Set default value
51 | if (getSourceEnabled(categorySource) === null) {
52 | setSourceEnabled(categorySource, categorySources[i].defaultOn === true);
53 | }
54 | option.selected = getSourceEnabled(categorySource) === true;
55 | sourcePicker.appendChild(option);
56 | }
57 | $('select').material_select();
58 | }
59 |
60 | // Initializes category picker with last picked category from local storage
61 | function restoreCategoryPicker() {
62 | var lastSelectedCategory = getLastCategory();
63 | // Call array.map on picker element
64 | var index = [].map
65 | .call(categoryPicker, function(option) {
66 | return option.value;
67 | })
68 | .indexOf(lastSelectedCategory);
69 |
70 | if (index > -1) categoryPicker.selectedIndex = index;
71 | }
72 |
73 | // Rotates category
74 | function selectNextCategory() {
75 | if (categoryPicker.selectedIndex < categoryPicker.options.length - 1) {
76 | categoryPicker.selectedIndex = categoryPicker.selectedIndex + 1;
77 | } else {
78 | categoryPicker.selectedIndex = 0;
79 | }
80 | didPickCategory();
81 | }
82 |
83 | /* Preferences */
84 | // Creates local storage entries for the visibility of each news outlet
85 | function initSourcePreferences() {
86 | for (var locale in sources) {
87 | for (var i = 0; i < sources[locale].length; i++) {
88 | for (var j = 0; j < sources[locale][i].sources.length; j++) {
89 | var categorySource = sources[locale][i].sources[j];
90 | if (getSourceEnabled(categorySource.key) === null) {
91 | setSourceEnabled(categorySource.key, categorySource.defaultOn === true);
92 | }
93 | }
94 | }
95 | }
96 | }
97 |
98 | // Stores selected news outlets in local storage
99 | function saveSourcePreferences() {
100 | for (var i = 0; i < sourcePicker.options.length; i++) {
101 | localStorage.setItem(sourcePicker.options[i].value, JSON.stringify(sourcePicker.options[i].selected));
102 | }
103 | }
104 |
105 |
106 | /* Helper Methods */
107 |
108 | // Removes all elements of select picker
109 | function removeAllOptions(select) {
110 | var i;
111 | for (i = select.options.length - 1; i >= 0; i--) {
112 | select.remove(i);
113 | }
114 | }
115 |
116 | // Removes element by id from select picker
117 | function sourceNameById(sourceId) {
118 | var categories = getCategoriesByLanguage(language);
119 | for (var k = 0; k < categories.length; k++) {
120 | var categorySources = categories[k].sources;
121 | for (var i = 0; i < categorySources.length; i++) {
122 | if (categorySources[i].key == sourceId) return categorySources[i].name;
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/public/client.js:
--------------------------------------------------------------------------------
1 | /* Init */
2 |
3 | var articles, index, step, lastIsRiding;
4 |
5 | COBI.init('token');
6 | COBI.devkit.overrideThumbControllerMapping.write(true);
7 | COBI.app.clockVisible.write(false);
8 |
9 | // Initialize slider if in experience or overview mode (therefore not in edit menu)
10 | if (COBI.parameters.context() == COBI.context.onRide || COBI.parameters.context() == COBI.context.offRide) {
11 | createSwiper();
12 | initSourcePreferences();
13 | populateCategoryPicker();
14 | restoreCategoryPicker();
15 | clearContents();
16 | reloadContents();
17 | populateSourcePicker();
18 |
19 | // Apply material design to select pick ups
20 | $(document).ready(function() {
21 | $('select').material_select();
22 | });
23 | }
24 |
25 | /* Swiper Contents */
26 |
27 | // Gets called with json data of article and adds a slider item
28 | function buildArticles(jsonString) {
29 | var json = JSON.parse(jsonString);
30 | for (var i = 0; i < json.articles.length; i++) {
31 | var article = json.articles[i];
32 | var index = articles.length;
33 | article.sourceName = sourceNameById(article.source.id);
34 | articles.push(article);
35 | if (article.title.length > 85) {
36 | article.title = article.title.substring(0, 84) + '...';
37 | }
38 | createSwiperItem(index, article.title, article.description, article.urlToImage);
39 | }
40 | swiper.init();
41 | selectArticle(0);
42 | }
43 |
44 | // Load and display content for news category
45 | function reloadContents() {
46 | var category = categoryPicker.options[categoryPicker.selectedIndex].value;
47 |
48 | setLastCategory(category);
49 | console.log('Reload Contents: ' + i18next.language + ' with category ' + category);
50 |
51 | var localSources = getCategoriesByLanguage(language)[categoryPicker.selectedIndex].sources;
52 | var selectedSources = [];
53 |
54 | for (var i = 0; i < localSources.length; i++) {
55 | if (getSourceEnabled(localSources[i].key)) {
56 | selectedSources.push(localSources[i].key);
57 | }
58 | }
59 | // Fetch news for aggregated news outlets
60 | if (selectedSources.length > 0) {
61 | fetchNews(selectedSources, buildArticles);
62 | }
63 |
64 | }
65 |
66 | // Remove slider items
67 | function clearContents() {
68 | var contentContainer = document.getElementById('item-container');
69 | while (contentContainer.firstChild) {
70 | contentContainer.removeChild(contentContainer.firstChild);
71 | }
72 | articles = [];
73 | step = 0;
74 | index = -1;
75 | }
76 |
77 | /* Article & Category Browsing */
78 |
79 | // Jumps to next article or category depending on settings
80 | function nextArticle() {
81 | if (this.index < articles.length - 1) {
82 | selectArticle(this.index + 1);
83 | } else if (getJumpCategorySetting()) {
84 | selectNextCategory();
85 | } else {
86 | selectArticle(0);
87 | }
88 | }
89 |
90 | // Jumps to previous article
91 | function prevArticle() {
92 | if (this.index > 0) {
93 | selectArticle(this.index - 1);
94 | }
95 | }
96 |
97 | // Swipes to desired article id
98 | function selectArticle(index) {
99 | if (this.index != index) {
100 | console.log('Select Article: ' + index + ' / Riding: ' + lastIsRiding);
101 |
102 | this.index = index;
103 | this.step = 0;
104 |
105 | swiper.slideTo(index);
106 | showHideSwiperItemContents(index, lastIsRiding);
107 |
108 | nextStep();
109 | }
110 | }
111 |
112 | // Reads article title, descripton or adds it to reading list depending on state and setting
113 | function nextStep() {
114 | var article = articles[index];
115 |
116 | // Loop through steps
117 | if (this.step >= 3) this.step = 0;
118 |
119 | // Next step
120 | this.step++;
121 |
122 | // Should Read Description?
123 | if (this.step == 2 && !getArticleDescriptionSetting()) {
124 | // Nope -> Go to Reading List
125 | this.step = 3;
126 | }
127 |
128 | // Read Title
129 | if (this.step == 1) {
130 | console.log('Read Title: ' + article.title);
131 | COBI.app.textToSpeech.write({ content: article.title, language: i18next.language });
132 | } else if (this.step == 2) {
133 | // Read Description
134 | console.log('Read Description: ' + article.description);
135 | COBI.app.textToSpeech.write({ content: article.description, language: i18next.language });
136 | } else if (this.step == 3) {
137 | // Add to Read Later List on Safari
138 | console.log('Read Later: ' + article.url);
139 | COBI.app.readLater.write({ title: article.title, url: article.url });
140 | COBI.app.textToSpeech.write({ content: i18next.t('read-later-tts'), language: i18next.language });
141 | Materialize.toast(i18next.t('read-later'), 5 * 1000, 'rounded white');
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/public/cobi-style.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:0.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}@font-face{font-family:'UniSans';src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Light/UniSansLight.eot");src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Light/UniSansLight.eot?#iefix") format("embedded-opentype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Light/UniSansLight.woff2") format("woff2"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Light/UniSansLight.woff") format("woff"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Light/UniSansLight.ttf") format("truetype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Light/UniSansLight.svg#uni_sansbook") format("svg");font-weight:200;font-style:normal}@font-face{font-family:'UniSans';src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Book/UniSansBook.eot");src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Book/UniSansBook.eot?#iefix") format("embedded-opentype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Book/UniSansBook.woff2") format("woff2"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Book/UniSansBook.woff") format("woff"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Book/UniSansBook.ttf") format("truetype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Book/UniSansBook.svg#uni_sansbook") format("svg");font-weight:300;font-style:normal}@font-face{font-family:'UniSans';src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Regular/UniSansRegular.eot");src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Regular/UniSansRegular.eot?#iefix") format("embedded-opentype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Regular/UniSansRegular.woff2") format("woff2"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Regular/UniSansRegular.woff") format("woff"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Regular/UniSansRegular.ttf") format("truetype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Regular/UniSansRegular.svg#uni_sansbook") format("svg");font-weight:400;font-style:normal}@font-face{font-family:'UniSans';src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/SemiBold/UniSansSemiBold.eot");src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/SemiBold/UniSansSemiBold.eot?#iefix") format("embedded-opentype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/SemiBold/UniSansSemiBold.woff2") format("woff2"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/SemiBold/UniSansSemiBold.woff") format("woff"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/SemiBold/UniSansSemiBold.ttf") format("truetype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/SemiBold/UniSansSemiBold.svg#uni_sansHeavy") format("svg");font-weight:500;font-style:normal}@font-face{font-family:'UniSans';src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Bold/UniSansBold.eot");src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Bold/UniSansBold.eot?#iefix") format("embedded-opentype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Bold/UniSansBold.woff2") format("woff2"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Bold/UniSansBold.woff") format("woff"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Bold/UniSansBold.ttf") format("truetype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Bold/UniSansBold.svg#uni_sansBold") format("svg");font-weight:700;font-style:normal}@font-face{font-family:'UniSans';src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Heavy/UniSansHeavy.eot");src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Heavy/UniSansHeavy.eot?#iefix") format("embedded-opentype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Heavy/UniSansHeavy.woff2") format("woff2"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Heavy/UniSansHeavy.woff") format("woff"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Heavy/UniSansHeavy.ttf") format("truetype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/UniSans/Heavy/UniSansHeavy.svg#uni_sansHeavy") format("svg");font-weight:900;font-style:normal}@font-face{font-family:'OpenSans';src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Light/OpenSans-Light.eot?v=1.1.0");src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Light/OpenSans-Light.eot?#iefix&v=1.1.0") format("embedded-opentype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Light/OpenSans-Light.woff2?v=1.1.0") format("woff2"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Light/OpenSans-Light.woff?v=1.1.0") format("woff"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Light/OpenSans-Light.ttf?v=1.1.0") format("truetype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Light/OpenSans-Light.svg?v=1.1.0#Light") format("svg");font-weight:300;font-style:normal}@font-face{font-family:'OpenSans';src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Regular/OpenSans-Regular.eot?v=1.1.0");src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Regular/OpenSans-Regular.eot?#iefix&v=1.1.0") format("embedded-opentype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Regular/OpenSans-Regular.woff2?v=1.1.0") format("woff2"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Regular/OpenSans-Regular.woff?v=1.1.0") format("woff"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Regular/OpenSans-Regular.ttf?v=1.1.0") format("truetype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Regular/OpenSans-Regular.svg?v=1.1.0#Regular") format("svg");font-weight:normal;font-style:normal}@font-face{font-family:'OpenSans';src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Semibold/OpenSans-Semibold.eot?v=1.1.0");src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Semibold/OpenSans-Semibold.eot?#iefix&v=1.1.0") format("embedded-opentype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Semibold/OpenSans-Semibold.woff2?v=1.1.0") format("woff2"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Semibold/OpenSans-Semibold.woff?v=1.1.0") format("woff"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Semibold/OpenSans-Semibold.ttf?v=1.1.0") format("truetype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Semibold/OpenSans-Semibold.svg?v=1.1.0#Semibold") format("svg");font-weight:600;font-style:normal}@font-face{font-family:'OpenSans';src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Bold/OpenSans-Bold.eot?v=1.1.0");src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Bold/OpenSans-Bold.eot?#iefix&v=1.1.0") format("embedded-opentype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Bold/OpenSans-Bold.woff2?v=1.1.0") format("woff2"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Bold/OpenSans-Bold.woff?v=1.1.0") format("woff"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Bold/OpenSans-Bold.ttf?v=1.1.0") format("truetype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/OpenSans/Bold/OpenSans-Bold.svg?v=1.1.0#Bold") format("svg");font-weight:bold;font-style:normal}h1,h2,h3,h4,h5,h6{font-family:'UniSans';font-weight:300;margin-top:0;margin-bottom:10px;line-height:1}h1,.h1{font-size:36px;margin-top:20px;margin-bottom:10px}h2,.h2{font-size:30px;margin-top:20px;margin-bottom:10px}h3,.h3{font-size:24px;margin-top:20px;margin-bottom:10px}h4,.h4{font-size:18px;margin-top:10px;margin-bottom:10px}h5,.h5{font-size:14px;margin-top:10px;margin-bottom:10px}h6,.h6{font-size:12px;margin-top:10px;margin-bottom:10px}p{font-family:'OpenSans';font-weight:200;line-height:26px;margin-top:0;margin-bottom:10px;font-size:17px;color:#2D2D37;padding:0 0 0 0px}.text-center{text-align:center}.bar{position:fixed;right:0;left:0;z-index:30;height:54px;padding-right:10px;padding-left:10px;padding-top:10px;background-color:#00C8E6;-webkit-backface-visibility:hidden;backface-visibility:hidden}.bar.light{background-color:#fff}.bar.gray{background-color:#F7F7F7}.bar.push{margin-top:-54px;z-index:99}.bar ~ .content-blue{padding-top:54px}.bar ~ .content{padding-top:54px}.bar-header-secondary{top:54px}.bar-footer{bottom:0}.bar-footer-secondary{bottom:54px}.bar-footer-secondary-tab{bottom:50px}.bar-footer,.bar-footer-secondary,.bar-footer-secondary-tab{border-top:1px solid #E0E0E0;border-bottom:0}.bar-nav{top:0}.title{position:absolute;display:block;width:100%;padding:0;margin:0 -10px;font-size:17px;font-weight:400;line-height:44px;color:#000;text-align:center;white-space:nowrap}.title a{color:inherit}.bar-tab{display:table;bottom:0;width:100%;height:50px;padding:0;table-layout:fixed;border-top:1px solid #E0E0E0;border-bottom:0}.bar-tab .tab-item{display:table-cell;width:1%;height:50px;color:#929292;text-align:center;vertical-align:middle}.bar-tab .tab-item.active,.bar-tab .tab-item:active{color:#428bca}.bar-tab .tab-item .icon{top:3px;width:24px;height:24px;padding-top:0;padding-bottom:0}.bar-tab .tab-item .icon ~ .tab-label{display:block;font-size:11px}.bar .btn{position:relative;top:7px;z-index:20;padding:6px 12px 7px;margin-top:0;font-weight:400}.bar .btn.pull-right{margin-left:10px}.bar .btn.pull-left{margin-right:10px}.bar .btn-link{top:0;padding:0;font-size:16px;line-height:54px;color:#2D2D37;border:0}.bar .btn-link:active,.bar .btn-link.active{color:#16161b}.bar .btn-block{top:6px;padding:7px 0;margin-bottom:0;font-size:16px}.bar .btn-nav.pull-left{margin-left:-5px}.bar .btn-nav.pull-left .icon-left-nav{margin-right:-3px}.bar .btn-nav.pull-right{margin-right:-5px}.bar .btn-nav.pull-right .icon-right-nav{margin-left:-3px}.bar .icon{position:relative;z-index:20;padding-top:10px;padding-bottom:10px;font-size:24px}.bar .btn .icon{top:3px;padding:0}.bar .title .icon{padding:0}.bar .title .icon.icon-caret{top:4px;margin-left:-5px}.bar input[type="search"]{height:29px;margin:6px 0}.bar .segmented-control{top:7px;margin:0 auto}@font-face{font-family:Icons;font-weight:normal;font-style:normal;src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/Icons/icons.eot");src:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/Icons/icons.eot?#iefix") format("embedded-opentype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/Icons/icons.woff") format("woff"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/Icons/icons.ttf") format("truetype"),url("https://cdn.cobi.bike/devkit/v1.0.0/resources/fonts/Icons/icons.svg#svgFontName") format("svg")}.icon{display:inline-block;font-family:Icons;font-size:24px;line-height:1;text-decoration:none;-webkit-font-smoothing:antialiased}.icon-back:before{content:'\e80a'}.icon-bars:before{content:'\e80e'}.icon-caret:before{content:'\e80f'}.icon-check:before{content:'\e810'}.icon-close:before{content:'\e811'}.icon-code:before{content:'\e812'}.icon-compose:before{content:'\e813'}.icon-download:before{content:'\e815'}.icon-edit:before{content:'\e829'}.icon-forward:before{content:'\e82a'}.icon-gear:before{content:'\e821'}.icon-home:before{content:'\e82b'}.icon-info:before{content:'\e82c'}.icon-list:before{content:'\e823'}.icon-more-vertical:before{content:'\e82e'}.icon-more:before{content:'\e82f'}.icon-pages:before{content:'\e824'}.icon-pause:before{content:'\e830'}.icon-person:before{content:'\e832'}.icon-play:before{content:'\e816'}.icon-plus:before{content:'\e817'}.icon-refresh:before{content:'\e825'}.icon-search:before{content:'\e819'}.icon-share:before{content:'\e81a'}.icon-sound:before{content:'\e827'}.icon-sound2:before{content:'\e828'}.icon-sound3:before{content:'\e80b'}.icon-sound4:before{content:'\e80c'}.icon-star-filled:before{content:'\e81b'}.icon-star:before{content:'\e81c'}.icon-stop:before{content:'\e81d'}.icon-trash:before{content:'\e81e'}.icon-up-nav:before{content:'\e81f'}.icon-up:before{content:'\e80d'}.icon-right-nav:before{content:'\e818'}.icon-right:before{content:'\e826'}.icon-down-nav:before{content:'\e814'}.icon-down:before{content:'\e820'}.icon-left-nav:before{content:'\e82d'}.icon-left:before{content:'\e822'}a.btn{display:inline-block}.btn{position:relative;display:block;padding:14px 35px 14px 35px;margin:10px auto;font-size:20px;font-family:'UniSans';font-weight:300;font-size:18px;line-height:1;color:#2D2D37;text-align:center;white-space:nowrap;vertical-align:top;cursor:pointer;background-color:#fff;border:0px;border-radius:40px}.btn:active,.btn.active{color:inherit;background-color:#fff}.btn:disabled,.btn.disabled{background-color:#E0E0E0;color:#AAAAAD}.btn.blue{background-color:#00C8E6;box-shadow:0 2px 0 0 #007D90}.btn.tarmac{background-color:#2D2D37;color:#fff}.btn-block{padding:14px 60px 14px 60px}.btn .icon{font-size:inherit;margin-left:10px}.modal{position:fixed;top:0;left:0;z-index:20;width:100%;min-height:100%;overflow:hidden;background-color:#fff;opacity:0;-webkit-transition:-webkit-transform .25s, opacity 1ms .25s;-moz-transition:-moz-transform .25s, opacity 1ms .25s;transition:transform .25s, opacity 1ms .25s;-webkit-transform:translate3d(0, 100%, 0);-ms-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}.modal.active{height:100%;opacity:1;-webkit-transition:-webkit-transform .25s;-moz-transition:-moz-transform .25s;transition:transform .25s;-webkit-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}.table-view{padding-left:0;margin-top:0;margin-bottom:0;list-style:none;background-color:#fff;border-top:1px solid #E0E0E0}.table-view-cell{font-weight:300;position:relative;padding:18px 65px 18px 15px;overflow:hidden;border-bottom:1px solid #E0E0E0}.table-view-cell:last-child{border-bottom:0}.table-view-cell>a:not(.btn){position:relative;display:block;padding:inherit;margin:-18px -65px -18px -15px;overflow:hidden;color:inherit}.table-view-cell>a:not(.btn):active{background-color:#eee}.table-view-cell p{margin-bottom:0}.table-view-divider{padding-top:35px;padding-bottom:6px;padding-left:15px;margin-top:-1px;margin-left:0;font-family:'UniSans';color:#2D2D37;background-color:#EBEAE6;border-top:1px solid #E0E0E0;border-bottom:1px solid #E0E0E0}.table-view .media,.table-view .media-body{overflow:hidden}.table-view .media-object.pull-left{margin-right:10px}.table-view .media-object.pull-right{margin-left:10px}.table-view-cell>.btn,.table-view-cell>.badge,.table-view-cell>.toggle,.table-view-cell>a>.btn,.table-view-cell>a>.badge,.table-view-cell>a>.toggle{position:absolute;top:50%;right:15px;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.table-view-cell .navigate-left>.btn,.table-view-cell .navigate-left>.badge,.table-view-cell .navigate-left>.toggle,.table-view-cell .navigate-right>.btn,.table-view-cell .navigate-right>.badge,.table-view-cell .navigate-right>.toggle,.table-view-cell .push-left>.btn,.table-view-cell .push-left>.badge,.table-view-cell .push-left>.toggle,.table-view-cell .push-right>.btn,.table-view-cell .push-right>.badge,.table-view-cell .push-right>.toggle,.table-view-cell>a .navigate-left>.btn,.table-view-cell>a .navigate-left>.badge,.table-view-cell>a .navigate-left>.toggle,.table-view-cell>a .navigate-right>.btn,.table-view-cell>a .navigate-right>.badge,.table-view-cell>a .navigate-right>.toggle,.table-view-cell>a .push-left>.btn,.table-view-cell>a .push-left>.badge,.table-view-cell>a .push-left>.toggle,.table-view-cell>a .push-right>.btn,.table-view-cell>a .push-right>.badge,.table-view-cell>a .push-right>.toggle{right:35px}.content>.table-view:first-child{margin-top:15px}.toggle{position:relative;display:inline-block;width:55px;height:33px}.toggle input{display:none}.slider-circle{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#E0E0E0;-webkit-transition:.2s;transition:.2s}.slider-circle:before{position:absolute;content:"";height:27px;width:27px;left:3px;bottom:3px;background-color:#fff;-webkit-transition:.2s;transition:.2s}input:checked+.slider-circle{background-color:#00C8E6}input:focus+.slider-circle{box-shadow:0 0 1px #00C8E6}input:checked+.slider-circle:before{-webkit-transform:translateX(22px);-ms-transform:translateX(22px);transform:translateX(22px)}.slider-circle.round{border-radius:35px}.slider-circle.round:before{border-radius:50%}input,textarea,button,select{font-family:"UniSans";font-size:17px}select,textarea,input[type="text"],input[type="search"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="tel"],input[type="color"]{width:100%;height:35px;-webkit-appearance:none;padding:0 15px;margin-bottom:15px;font-weight:300;line-height:21px;border:1px solid #E0E0E0;border-radius:3px;outline:none;overflow:scroll;color:#2D2D37}input:focus::-webkit-input-placeholder{color:transparent !important}input::-webkit-input-placeholder{color:#E0E0E0}input[type="search"]{padding:0 10px;font-size:16px;border-radius:20px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]:focus{text-align:left}input[type="date"]:focus{margin-right:0;padding:0;float:right;text-align:right}input[type=date]{display:block;-webkit-appearance:button;-moz-appearance:button;appearance:button}@media only screen and (orientation: portrait){input[type="date"]:before{content:'dd.mm.yyyy';margin-top:5px;float:right}input[type="date"]:focus:before{content:''}input[type="date"]:valid:before{content:''}input[type="date"]:focus{content:'';overflow:scroll;margin-top:5px;float:right}input[type="date"]:valid{content:'';overflow:scroll;margin:10px 0;padding:0;float:right}}textarea{height:auto}select{height:auto;font-size:14px;background-color:#f8f8f8;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.1);box-shadow:inset 0 1px 1px rgba(0,0,0,0.1)}.input-group input,.input-group textarea{margin-bottom:0;background-color:transparent;border-top:0;border-right:0;border-left:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.input-row{background-color:#fff;overflow:hidden;height:65px;padding-top:13px;border-bottom:1px solid #E0E0E0}.input-row:first-child{border-top:1px solid #E0E0E0}.input-row label{float:left;width:50%;padding:9px 15px;font-family:"UniSans";font-weight:300;line-height:1.1}.input-row input{text-align:right;float:right;width:50%;padding-left:0;margin-bottom:0;border:0;overflow:scroll}.input-transparent{overflow:hidden;text-align:center;height:40px;width:240px;margin:0 auto;margin-bottom:20px;padding-top:7px;border-bottom:1px solid #fff}.input-transparent input{text-align:center;background-color:transparent;border:0px;color:#fff;font-size:24px;font-family:'UniSans';font-weight:200;padding-bottom:10px}.input-transparent input:focus{outline:none}.input-transparent input::-webkit-input-placeholder{color:#007D90}.input-transparent input::-moz-placeholder{color:#007D90}.input-transparent input:-ms-input-placeholder{color:#007D90}.input-transparent input:-moz-placeholder{color:#007D90}.input-icon{overflow:hidden;text-align:left;height:40px;width:270px;margin:0 auto;margin-bottom:20px;padding-top:7px;border-bottom:1px solid #9B9B9B}.input-icon:focus{border-bottom:1px solid #00C8E6}.input-icon input{text-align:left;background-color:transparent;border:0px;color:#2D2D37;font-size:18px;font-family:'UniSans';font-weight:300;padding-bottom:10px;margin-top:-27px;float:left;margin-left:31px}.input-icon input:focus{outline:none}.input-icon input::-webkit-input-placeholder{color:#AAAAAD}.input-icon input::-moz-placeholder{color:#AAAAAD}.input-icon input:-ms-input-placeholder{color:#AAAAAD}.input-icon input:-moz-placeholder{color:#AAAAAD}.content.fade{left:0;opacity:0}.content.fade.in{opacity:1}.content.sliding{z-index:2;-webkit-transition:-webkit-transform .4s;-moz-transition:-moz-transform .4s;transition:transform .4s;-webkit-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}.content.sliding.left{z-index:1;-webkit-transform:translate3d(-100%, 0, 0);-ms-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0)}.content.sliding.right{z-index:3;-webkit-transform:translate3d(100%, 0, 0);-ms-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0)}.navigate-left:after,.navigate-right:after,.push-left:after,.push-right:after{position:absolute;top:50%;display:inline-block;font-family:Icons;font-size:inherit;line-height:1;color:#2D2D37;text-decoration:none;-webkit-font-smoothing:antialiased;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.navigate-left:after,.push-left:after{left:15px;content:'\e822'}.navigate-right:after,.push-right:after{right:15px;content:'\e826'}.img-slider{position:relative;width:100%;height:auto}.img-slider{overflow:hidden}.img-slider .slide-group{position:relative;font-size:0;white-space:nowrap;-webkit-transition:all 0s linear;-moz-transition:all 0s linear;transition:all 0s linear}.img-slider .slide-group .slide{display:inline-block;width:100%;height:100%;font-size:14px;vertical-align:top}.img-slider .slide-group .slide img{display:block;margin:0 auto;width:80%;height:auto}.img-slider .indicators-group{position:relative;display:flex}.img-slider .indicators-group .indicators{display:inline-block;width:auto;height:100%;vertical-align:top;margin:0 auto;padding:0}.img-slider .indicators-group .indicators .dot-style{float:left;margin-left:10px;list-style:none}.img-slider .indicators-group .indicators .dot-style.active::before{background-color:black}.img-slider .indicators-group .indicators .dot-style::before{display:inline-block;content:"";width:6px;height:6px;background-color:#007D90;border-radius:10px}#toast-container{z-index:10000;position:absolute;left:50%;width:auto;transform:translateX(-50%)}.toast{font-family:'UniSans';font-weight:200;border-radius:2px;top:100px;width:auto;margin-top:40px;margin-left:10px;margin-right:10px;position:relative;max-width:100%;height:auto;min-height:48px;line-height:1.5em;word-break:break-all;background-color:#323232;padding:10px 25px;font-size:1.1rem;color:#fff;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;cursor:default}.toast.rounded{border-radius:24px}.toast.white{color:#2D2D37;background-color:#fff;border:2px #2D2D37 solid}@media only screen and (max-width: 600px){#toast-container{min-width:0 !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-tap-highlight-color:rgba(255,255,255,0)}body{position:fixed;top:0;right:0;bottom:0;left:0;font-family:"UniSans";font-size:17px;line-height:21px;font-weight:400;color:#2D2D37;background-color:#F7F7F7;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}a{color:#2D2D37;text-decoration:none;-webkit-tap-highlight-color:transparent}a:active{color:#16161b}.content{position:absolute;top:0;right:0;bottom:0;left:0;overflow:auto;background-color:#fff;-webkit-overflow-scrolling:touch}.content .content-bg{position:absolute;bottom:0;width:100%;height:auto;z-index:0}.content.blue{background-color:#00C8E6}.content.gray{background-color:#F7F7F7}.content>*{-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0)}.bar-nav ~ .content{padding-top:54px}.bar-header-secondary ~ .content{padding-top:108px}.bar-footer ~ .content{padding-bottom:54px}.bar-footer-secondary ~ .content{padding-bottom:108px}.bar-tab ~ .content{padding-bottom:50px}.bar-footer-secondary-tab ~ .content{padding-bottom:104px}.content-padded{margin:0;padding:15px 15px 10px 15px}.pull-left{float:left}.pull-right{float:right}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix:after{clear:both}.app-info-header{display:block;width:100%;padding:0;margin:0;z-index:1;margin-bottom:0px;margin-top:25px}.app-info-header::after{position:absolute;left:50%;margin-left:-188px;content:url("https://cdn.cobi.bike/devkit/v1.0.0/resources/images/header.svg");z-index:99;top:0}.app-info-header .app-icon{display:block;width:110px;position:relative;margin:0 auto;padding-top:35px}@keyframes dash{to{stroke-dashoffset:3000}}#infinity_loader{display:none;margin:0px auto;padding-top:5px;stroke-dasharray:60,200;animation:dash 10s linear infinite}
2 | /*# sourceMappingURL=cobi-style.css.map */
3 |
--------------------------------------------------------------------------------