Skip to content

Commit

Permalink
Support ESLint. Page Visibility API page.
Browse files Browse the repository at this point in the history
  • Loading branch information
Vasyl Stokolosa committed Nov 29, 2017
1 parent 5d49223 commit da16fe5
Show file tree
Hide file tree
Showing 19 changed files with 165 additions and 20 deletions.
2 changes: 2 additions & 0 deletions .eslintignore
@@ -0,0 +1,2 @@
app/tests
app/vendor
23 changes: 23 additions & 0 deletions .eslintrc
@@ -0,0 +1,23 @@
{
"parser": "babel-eslint",
"extends": "eslint:recommended",
"env": {
"browser": true,
"node": true,
"es6": true,
"jquery": true
},
"globals": {
"app": true
},
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"rules": {
"no-console": "error",
"curly": "error",
"semi": ["error", "always"],
"no-empty": ["error", { "allowEmptyCatch": true }]
}
}
4 changes: 2 additions & 2 deletions app/actions/alert.js
Expand Up @@ -11,7 +11,7 @@ export function showAlert(message) {
return {
type: SHOW_ALERT,
message
}
};
}

/**
Expand All @@ -20,5 +20,5 @@ export function showAlert(message) {
export function hideAlert() {
return {
type: HIDE_ALERT
}
};
}
6 changes: 3 additions & 3 deletions app/actions/weather.js
Expand Up @@ -17,7 +17,7 @@ export function pushWeather(weather) {
return {
type: PUSH_WEATHER,
weather
}
};
}

/**
Expand All @@ -26,7 +26,7 @@ export function pushWeather(weather) {
export function requestWeather() {
return {
type: REQUEST_WEATHER
}
};
}

/**
Expand All @@ -35,7 +35,7 @@ export function requestWeather() {
export function receiveWeather() {
return {
type: RECEIVE_WEATHER
}
};
}

/**
Expand Down
4 changes: 2 additions & 2 deletions app/actions/weather_list.js
Expand Up @@ -11,7 +11,7 @@ export function pushWeatherList(weather) {
return {
type: PUSH_WEATHER_LIST,
weather
}
};
}

/**
Expand All @@ -22,7 +22,7 @@ export function removeWeatherFromList(index) {
return {
type: REMOVE_WEATHER_FROM_LIST,
index
}
};
}


Expand Up @@ -14,5 +14,5 @@ export const parseWeatherResponseForUI = function (weather) {
temperature: `${weather.main.temp}°С`,
wind: `wind ${weather.wind.speed} m/s`,
clouds: `clouds ${weather.clouds.all} %`
}
};
};
2 changes: 1 addition & 1 deletion app/components/dumb/Resize_SubPub_Action.jsx
Expand Up @@ -11,7 +11,7 @@ export default class Resize_SubPub_Action extends Component {

this.resizeSubKey = 0;

this.updateSizes = this.updateSizes.bind(this)
this.updateSizes = this.updateSizes.bind(this);
}

updateSizes() {
Expand Down
44 changes: 43 additions & 1 deletion app/components/dumb/Show_Page_Visibility_API.jsx
Expand Up @@ -2,18 +2,60 @@

import React, { Component } from 'react';
import { Show_Page_Visibility_API_Interface } from './../../helpers/interfaces';
import { Interval } from './../../helpers/constructors';
import store from './../../store';
import { showAlert } from './../../actions/alert';

export default class Show_Page_Visibility_API extends Component {
constructor() {
super();

this.state = Show_Page_Visibility_API_Interface;
this.visibilityChangeSubKey = 0;

this.handleVisibilityChange = this.handleVisibilityChange.bind(this);
this.simulateHTTPRequest = this.simulateHTTPRequest.bind(this);

this.getAmountOfNewUsers_Interval = new Interval(this.simulateHTTPRequest, 1000);
}

simulateHTTPRequest() {
setTimeout(() => {
if (!this.unmount) {
this.setState({amountOfNewUsers: ++this.state.amountOfNewUsers});
}
}, 500);
}

/**
* @param {Object} event
* @param {String} action
*/
handleVisibilityChange(event, action) {
if (action === 'continue') {
this.getAmountOfNewUsers_Interval.start(this.simulateHTTPRequest, 1000);
store.dispatch(showAlert('Seems like the page was not visible. Do not worry, we keep working :)'));
} else {
this.getAmountOfNewUsers_Interval.clear();
}
}

componentDidMount() {
this.getAmountOfNewUsers_Interval.start();
this.visibilityChangeSubKey = app.visibilityChangeEvent.subscribe(this.handleVisibilityChange);
}

componentWillUnmount() {
this.unmount = true;
this.getAmountOfNewUsers_Interval.clear();
app.resizeEvent.unsubscribe(this.visibilityChangeSubKey);
}

render() {
return <div className="app-show-page-visibility-api">

<div>Amount of new users: {this.state.amountOfNewUsers}</div>
<br/>
<h2>Amount of new users: {this.state.amountOfNewUsers}</h2>

</div>
}
Expand Down
6 changes: 4 additions & 2 deletions app/helpers/appGlobal.js
Expand Up @@ -16,10 +16,12 @@ var app = app || {};

return this.key++;
},
publish: function(args) {
publish: function() {
var args = Array.prototype.slice.call(arguments);

for (var sub in this.subscribers) {
try {
this.subscribers[sub](args);
this.subscribers[sub](args[0], args[1]);
} catch(ignore) {}
}
},
Expand Down
21 changes: 21 additions & 0 deletions app/helpers/constructors.js
@@ -0,0 +1,21 @@
'use strict';

/**
* @param {Function} instanceFn
* @param {Number} instanceInterval
* @constructor
**/
export function Interval(instanceFn, instanceInterval) {
let timer;

this.start = (fn = instanceFn , interval = instanceInterval) => {
if (!timer) {
timer = setInterval(() => { fn() }, interval);
}
};

this.clear = () => {
clearInterval(timer);
timer = void 0;
};
}
36 changes: 35 additions & 1 deletion app/helpers/domReady.js
Expand Up @@ -10,6 +10,9 @@
var toTopBtn = $('#toTop');


// Window Visibilitychange Listener
initPageVisibilityAPI();

// Window Scroll Listener
$(window).scroll(function() {
showHideToTopBtn();
Expand All @@ -32,6 +35,37 @@
toTopBtn.fadeIn();
}
}
});

function initPageVisibilityAPI() {
var hidden, visibilityChange;

// Opera 12.10 and Firefox 18 and later support
if (typeof document.hidden !== 'undefined') {
hidden = 'hidden';
visibilityChange = 'visibilitychange';
} else if (typeof document.msHidden !== 'undefined') {
hidden = 'msHidden';
visibilityChange = 'msvisibilitychange';
} else if (typeof document.webkitHidden !== 'undefined') {
hidden = 'webkitHidden';
visibilityChange = 'webkitvisibilitychange';
}

// Warn if the browser doesn't support addEventListener or the Page Visibility API
if (typeof document.addEventListener === 'undefined' || typeof document.hidden === 'undefined') {
alert('This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.');
} else {
document.addEventListener(visibilityChange, _handleVisibilityChange, false);
}

function _handleVisibilityChange(event) {
if (document[hidden]) {
app.visibilityChangeEvent.publish(event);
} else {
// page is visible you may continue doing what was stopped
app.visibilityChangeEvent.publish(event, 'continue');
}
}
}
});
}(jQuery));
2 changes: 1 addition & 1 deletion app/helpers/validation.js
Expand Up @@ -9,6 +9,6 @@
* @param {String} email
*/
export const isEmailValid = email => {
const reqExp = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
const reqExp = /[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$/;
return reqExp.test(email);
};
3 changes: 3 additions & 0 deletions app/pages/App.jsx
Expand Up @@ -7,6 +7,7 @@ import { connect } from 'react-redux';
import Home from './Home/Home';
import About from './About/About';
import Resize_SubPub from './Resize_SubPub/Resize_SubPub';
import Page_Visibility_API from './Page_Visibility_API/Page_Visibility_API';

function mapStateToProps(store, props) {
return {
Expand All @@ -28,11 +29,13 @@ class App extends Component {
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/resize">Resize_SubPub</Link></li>
<li><Link to="/visibility">Page_Visibility_API</Link></li>
</ul>


<Route exact path="/" render={() => <Home {...this.props} /> } />
<Route path="/about" render={() => <About {...this.props} /> } />
<Route path="/visibility" render={() => <Page_Visibility_API {...this.props} /> } />
<Route path="/resize" component={Resize_SubPub} />
</div>
}
Expand Down
12 changes: 10 additions & 2 deletions app/pages/Page_Visibility_API/Page_Visibility_API.jsx
Expand Up @@ -2,23 +2,31 @@

import React, { Component } from 'react';
import Show_Page_Visibility_API from './../../components/dumb/Show_Page_Visibility_API';
import Alert from './../../services/Alert';

export default class Page_Visibility_API extends Component {
constructor() {
super();
}

render() {
let alertStore = this.props.alert;

return <div className="app-page-visibility-api">
<h1>Page Visibility API</h1>

<p>
<em>For more details about counter here read this article - https://codeburst.io/clearintervals-when-user-has-a-nap-3bf8010c986b</em>
<em>For more details about counter here read this
<a href="https://codeburst.io/clearintervals-when-user-has-a-nap-3bf8010c986b"
title="clearIntervals() when user has a nap" target="_blank"> article</a>
</em>
</p>

<p>Do you still perform unnecessary tasks when the webpage is not visible?</p>

<Show_Page_Visibility_API />
<Show_Page_Visibility_API alert={alertStore} />

<Alert alert={alertStore} />
</div>
}
}
2 changes: 1 addition & 1 deletion app/resources/ajax.js
Expand Up @@ -30,4 +30,4 @@ export default function (method, url, data, config) {
.done(response => resolve(response))
.fail(errResponse => reject(errResponse));
});
};
}
2 changes: 1 addition & 1 deletion app/store.js
Expand Up @@ -3,7 +3,7 @@
import { createStore, applyMiddleware } from 'redux';
import promise from 'redux-promise';
import thunk from 'redux-thunk';
import logger from 'redux-logger'
import logger from 'redux-logger';
import rootReducer from './reducers';

let middleware;
Expand Down
4 changes: 4 additions & 0 deletions app/styles/_main.scss
Expand Up @@ -11,6 +11,10 @@ button {
outline-style: none;
}

h1 {
text-align: center;
}

.app {
max-width: 960px;
margin: 0 auto;
Expand Down
6 changes: 4 additions & 2 deletions package.json
Expand Up @@ -27,11 +27,12 @@
"e2e": "run-p --race dev server:e2e cypress:run",
"cypress:open": "cypress open",
"cypress:run": "cypress run --spec ./app/tests/e2e/cypress/integration/create_react_redux_app_structure_spec.js",
"open-localhost": "opn http://localhost:8080/"
"open-localhost": "opn http://localhost:8080/",
"eslint": "./node_modules/.bin/eslint app/"
},
"config": {
"ghooks": {
"pre-commit": "npm run test"
"pre-commit": "npm run test && npm run eslint"
}
},
"jest": {
Expand Down Expand Up @@ -92,6 +93,7 @@
"cypress": "^1.0.1",
"enzyme": "^3.1.0",
"enzyme-adapter-react-16": "^1.0.1",
"eslint": "^4.12.0",
"ghooks": "^2.0.0",
"grunt": "^1.0.1",
"grunt-cache-busting": "^0.0.11",
Expand Down
4 changes: 4 additions & 0 deletions server/routes/index.js
Expand Up @@ -16,6 +16,10 @@ module.exports = function (app) {
res.sendFile(path.resolve(__dirname, './../../index.html'));
});

app.get('/visibility', function (req, res) {
res.sendFile(path.resolve(__dirname, './../../index.html'));
});

app.get('/weather/:queryExpression', function (req, res) {
fetch(`${ROUTES.WEATHER_BASE_URL}weather?${req.params.queryExpression}`)
.then(response => response.json())
Expand Down

0 comments on commit da16fe5

Please sign in to comment.