JSFiddle - React, Tailwind, and code Playground

Notification Permission Request (iOS)

by tonytlwu

HTML

<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/animate.css/3.3.0/animate.min.css">
<script src="http://f.cl.ly/items/1m3B0x262L1y121S461R/pv.js"></script>
<script type="text/html" id="notificationRequestTitle">App updates and notifications</script>

<script type="text/html" id="notificationRequestContent">
    <p>You will receive notifications when app updates are available.</p>
    <p>Please tap on <strong>Allow Notifications</strong> below to receive notifications on the updates.</p>
</script>

<script type="text/html" id="notificationRequestButtons">
    <hr />
    <div class="row">
        <div class="col-sm-4 col-sm-push-8">
            <a class="btn btn-primary btn-lg btn-block flNotificationButton" data-allow="1" href="#">Allow Notifications</a>
        </div>
        <div class="col-sm-4">
            <br class="visible-xs-block" />
            <a class="btn btn-default btn-lg btn-block flNotificationButton" data-allow="0" href="#">Don't Allow</a>
        </div>
        <div class="col-sm-4 col-sm-pull-8">
            <br class="visible-xs-block" />
            <a class="btn btn-default btn-lg btn-block flNotificationButton" data-allow="-1" href="#">Later</a>
        </div>
    </div>
</script>

CSS

.flNotificationButton {
    font-size: 13px;
}

/*
===========================
CONTENTS:

01 Overlay 
===========================
*/

/* ---------------------------------------------------------------------------------------------------------- 
01 Overlay --------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------- */
body.overlayIsActive {
    overflow: hidden;
}

body.overlayIsActive > :not(.overlay),
body.overlayIsActive > :not(.overlay) * {
	pointer-events: none;
}

.overlay {
	position: fixed;
	top: 0;
	left: 0;
	bottom: 0;
	right: 0;
	background: none;
	width: 100%;
	height: 100%;
	z-index: 1000;
	-webkit-transform: translate3d(0,0,0);
    pointer-events: none;
}

.overlay.active {
	pointer-events: all;
}

.overlayPanelScreen {
	width: 100%;
	height: 100%;
	position: absolute;
	top: 0;
	left: 0;
	z-index: 19999;
	background: rgba(0,0,0,0.7);
	-webkit-transform: translate3d(0,0,0);
    transform: translate3d(0,0,0);
	opacity: 0;
	pointer-events: none;
	-webkit-transition-property: opacity;
	-webkit-transition-duration: 0.3s;
	-webkit-transition-timing-function: ease-out;
	transition-property: opacity;
	transition-duration: 0.3s;
	transition-timing-function: ease-out;
}

.overlay.active .overlayPanelScreen {
	opacity: 1;
	pointer-events: all;
}

.overlayPanel {
	position: absolute;
    top: 6px;
    left: 6px;
    right: 6px;
    bottom: 6px;
	background: rgba(0,0,0,0.3);
	z-index: 20000;
	padding: 0px;
	-webkit-border-radius: 5px;
 	-webkit-transform: translate3d(0,0,0) scale(0);
 	transform: translate3d(0,0,0) scale(0);
}

.overlay.active .overlayPanel {
 	-webkit-transform: translate3d(0,0,0);
	transform: translate3d(0,0,0);
}

.overlay-sm .overlayPanel {
    width: 70%;
    left: 15%;
    right: 15%;
    top: 15%;
    bottom: 15%;
}

@media screen and (min-width: 640px) {
	.overlayPanel {
		width: 62%;
		top:...

JavaScript

var appId = "haWbG80ozhshi4QjQdKpuvh03FCpdTsmH3EHTpyM",
	clientKey = "Gv8wfXUsVpn2PK3VHU07tc88lmENrhLXHAhz3WKk"
	channel = "TechnoTrends";

var subscribeNotificationChannel = function(appId, clientKey, channel, successCallback, errorCallback){
    if ( typeof window.parsePlugin === 'object' ) {
        window.parsePlugin.initialize(appId, clientKey, function () {
            window.parsePlugin.subscribe(channel, function () {
                if (typeof successCallback === 'function') {
                    successCallback();
                }
            }, function (e) {
                if (typeof errorCallback === 'function') {
                    errorCallback();
                }
            });
        }, function (e) {
            if (typeof errorCallback === 'function') {
                errorCallback();
            }
        });
    } else {
        if (typeof errorCallback === 'function') {
            errorCallback();
        }
    }
};

var initialiseNotificationRequestOverlay = function(){
    var flNotificationButtons = document.querySelectorAll('.flNotificationButton');
    for ( var i = 0, l = flNotificationButtons.length; i < l; i++ ) {
        var button = flNotificationButtons[i];
        button.addEventListener( 'click', function(e){
            e.preventDefault();
            switch ( this.getAttribute('data-allow') ) {
                case '0':
                    flNotificationSettings.data.requestDisabled = true;
                    flNotificationSettings.updateDevicePV();
                    break;
                case '1':
                    flNotificationSettings.data.permissionRequested = true;
                    flNotificationSettings.updateDevicePV();

                    subscribeNotificationChannel( appId, clientKey, channel );
                    break;
            }
            flNotificationRequestOverlay.close();
        } );
    }
};

var flNotificationSettingsDataStruct = {
    permissionRequested : false,
    requestDisabled...