youcount.github.io/index3.html

1034 lines
42 KiB
HTML

<!DOCTYPE html lang="en">
<head>
<title>YouCount: YouTube® LIVE Subscriber Count</title>
<link rel="shortcut icon" href="/favicon.ico"/>
<meta name="fragment" content="!">
<link rel="canonical" href="https://youcount.github.io/" />
<link rel="amphtml" href="https://youcount.github.io/amp">
<meta name="theme-color" content="#e52d27" />
<meta charset="utf-8">
<meta http-equiv="EXPIRES" content="Thu, 10 Jan 2030 12:00:00 GMT">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="description" content="See the LIVE growth of any YouTube® channel and achieving of milestones through their Realtime Subscriber Count(RSC) and Incredibly Useful Statistics(IUF)."/>
<meta property="og:title" content="YouCount: YouTube® LIVE Subscriber Count"/>
<meta property="og:description" content="See the LIVE growth of any YouTube® channel and achieving of milestones through their Realtime Subscriber Count(RSC) and Incredibly Useful Statistics(IUF)." />
<meta property="og:type" content="article"/>
<meta property="og:image" content="https://youcount.github.io/images/fblogo.jpg" />
<meta property="og:site_name" content="YouCount" />
<meta property="article:author" content="https://www.facebook.com/20manas"/>
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "Article",
"headline": "YouCount: YouTube® LIVE Subscriber Count",
"datePublished": "2015-10-07T12:02:41Z",
"publisher": {
"@type": "Organization",
"name":"YouCount",
"logo": {
"@type": "ImageObject",
"url": "https://youcount.github.io/images/amplogo.jpg",
"width": 600,
"height": 60
}
},
"author":"Manas Khurana",
"image": {
"@type": "ImageObject",
"url": "https://youcount.github.io/images/fblogo.jpg",
"width": 1203,
"height": 630
},
"description":"See the LIVE growth of any YouTube® channel and achieving of milestones through their Realtime Subscriber Count(RSC) and Incredibly Useful Statistics(IUF)."
}
</script>
<style>
/* Odometer */
.odometer.odometer-auto-theme,.odometer.odometer-auto-theme .odometer-digit,.odometer.odometer-theme-minimal,.odometer.odometer-theme-minimal .odometer-digit{display:inline-block;position:relative}.odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer,.odometer.odometer-theme-minimal .odometer-digit .odometer-digit-spacer{display:inline-block;visibility:hidden}.odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner,.odometer.odometer-theme-minimal .odometer-digit .odometer-digit-inner{text-align:left;display:block;position:absolute;top:0;left:0;right:0;bottom:0;overflow:hidden}.odometer.odometer-auto-theme .odometer-digit .odometer-ribbon,.odometer.odometer-theme-minimal .odometer-digit .odometer-ribbon{display:block}.odometer.odometer-auto-theme .odometer-digit .odometer-ribbon-inner,.odometer.odometer-theme-minimal .odometer-digit .odometer-ribbon-inner{display:block;-webkit-backface-visibility:hidden}.odometer.odometer-auto-theme .odometer-digit .odometer-value,.odometer.odometer-theme-minimal .odometer-digit .odometer-value{display:block;-webkit-transform:translateZ(0);transform:translateZ(0)}.odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value,.odometer.odometer-theme-minimal .odometer-digit .odometer-value.odometer-last-value{position:absolute}.odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner,.odometer.odometer-theme-minimal.odometer-animating-up .odometer-ribbon-inner{-webkit-transition:-webkit-transform .5s;transition:transform .5s}.odometer.odometer-auto-theme.odometer-animating-down .odometer-ribbon-inner,.odometer.odometer-auto-theme.odometer-animating-up.odometer-animating .odometer-ribbon-inner,.odometer.odometer-theme-minimal.odometer-animating-down .odometer-ribbon-inner,.odometer.odometer-theme-minimal.odometer-animating-up.odometer-animating .odometer-ribbon-inner{-webkit-transform:translateY(-100%);transform:translateY(-100%)}.odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner,.odometer.odometer-theme-minimal.odometer-animating-down.odometer-animating .odometer-ribbon-inner{-webkit-transition:-webkit-transform .5s;transition:transform .5s;-webkit-transform:translateY(0);transform:translateY(0)}
/*Odometer End*/
body {
background-color:rgb(250,250,250);
font-family: Arial, sans-serif;
outline:none;
margin:0;
-webkit-tap-highlight-color:rgba(0,0,0,0);
-webkit-transition: background-color 0.5s linear;
transition: background-color 0.5s linear;
}
img {
color:transparent;
}
ul {
list-style-type:none;
}
#menu {
position:fixed;
width:100%;
height:50px;
box-shadow: 0 0 20px -4px black;
left:0;
top:0;
z-index:1001;
background-color:rgb(229,45,39);
}
.navButtonsCover {
position:relative;
height:100%;
width:15vh;
min-height:40px;
float:right;
top:0;
cursor:pointer;
}
.navButtonsCover .navButtons {
position: relative;
top:10%;
left:50%;
-webkit-transform:translate(-50%,0);
transform:translate(-50%,0);
height:40px;
width:40px;
background-image: url(/images/menu.png);
background-size: auto 100%;
}
.navButtonsCover[data-child="logo"]{
float:left;
}
#logo {
width: 58px;
background-position: 0 0;
}
#helpButton {
background-position: 150 0;
}
#code {
background-position: 308 0;
}
#share {
background-position: 40px 0;
}
#sharebox {
position:fixed;
top:60px;
right:5px;
margin:0;
padding:0;
list-style-type:none;
}
.share {
height:40px;
width:40px;
border-radius:50%;
cursor:pointer;
display:none;
}
#pageUrl,#pageUrl input {
text-align:center;
width:80%;
left:10%;
border-radius:4px;
}
#pageUrl {
position:fixed;
top:20%;
z-index:1010;
background-color:white;
box-shadow: 0 0 20px -4px black;
padding:30px;
font-size:25px;
display:none;
}
#pageUrl input {
border:none;
outline:none;
font-family: Arial, sans-serif;
font-size:30px;
padding:10px;
background-color:gray;
color:white;
margin:20px;
}
#embedUrl {
font-size:20px;
}
#tutorial {
display: none;
z-index: 1003;
position:absolute;
height:300px;
max-height: 50%;
width:400px;
max-width: 100%;
padding-left: 30px;
padding-right: 30px;
background-color:rgba(0,0,0,0.7);
border-radius:10px;
top:700px;
left:50%;
-webkit-transform:translate(-50%,0);
transform:translate(-50%,0);
}
#pointer {
position: absolute;
bottom: 100%;
height:50px;
left:50%;
opacity: 0.7;
-webkit-transform:translate(-50%,0);
transform:translate(-50%,0);
}
#tutorial p, .tutStep2 {
color:white;
}
#tutStep1{
font-size:50px;
text-align:center;
font-weight:900;
}
#tutStep2 {
display: none;
}
#tutorial h3 {
font-size: 25px;
}
ol li {
padding-top: 5px;
padding-bottom: 5px;
}
.ball {
-webkit-transform: translate(100%, -100%);
transform: translate(100%, -100%);
border-radius: 50vmax;
opacity: 0;
}
#bg1 {
display: block;
overflow-x: hidden;
-webkit-transition: all 0.5s linear;
transition: all 0.5s linear;
min-height: 100%;
width: 100%;
right: 0;
top:0;
position: absolute;
background-color:white;
z-index:501;
}
#bg1 div {
margin-top: 60px;
-webkit-transition: all 0.5s;
transition: all 0.5s;
opacity: 0;
display: none;
}
#bg1 h2 {
text-align:center;
font-size:6vw;
margin:0;
font-family:Impact, Arial, sans-serif;
}
#bg1 p, #bg1 ol {
font-size:20px;
text-align:left;
margin-left:20px;
margin-right:20px;
}
#bg1 a {
color:rgb(229,45,39);
font-weight: 600;
}
#bg1 .extrabutton {
display: block;
}
#bg2 {
display: none;
left:0;
top:0;
background-color:rgba(0,0,0,0.5);
z-index: 1001;
height: 100%;
width: 100%;
position:fixed;
}
#mainPage {
position:absolute;
width:100%;
left:0;
bottom:0;
top:50px;
margin-left: auto;
margin-right: auto;
text-align: center;
}
.card {
position:relative;
width: 80% !important;
height:auto;
margin: 20px auto;
font-size:1vw;
box-shadow: 0 0 20px -4px black;
border-radius:4px !important;
background-color:white;
}
#prime {
padding-top:2vw;
padding-bottom:2vw;
}
#actualCount {
font-size: 11vw !important;
}
#totalViews, #totalVideos, #pubDate {
font-size:3vw !important;
line-height:1;
font-weight:400;
}
label[for="username"] {
display: inline-block;
}
#dp {
display: none;
height:8vw;
margin-right: 1vw;
border-radius:6vw; /*for both 8vw and 12vw sizes */
cursor:pointer;
}
#username,#input button{
border:none;
outline:none;
color:white;
}
#topPrime {
position: relative;
}
#input {
display: inline-block;
position: relative;
height:8vw;
margin-left:1vw;
width:75%;
background-color:rgb(200,200,200);
-webkit-transition:background-color 0.25s;
transition:background-color 0.25s;
border-radius:0.5vw;
}
#input button {
height:100%;
background-color:rgb(229,45,39);
width:8vw;
overflow:hidden;
cursor:pointer;
position:relative;
bottom: 100%;
float: right;
display:none;
padding: 0;
}
#username {
font-size:3vw;
font-family: Arial, sans-serif;
text-align:center;
float:left;
height:100%;
width:100%;
background-color:transparent;
-webkit-transition:width 0.25s;
transition:width 0.25s;
border-radius:0.5vw;
}
#search {
height:40px;
max-height: 60%;
}
#username:focus {
background-color:rgb(255,200,200);
width:87%;
border-bottom: 5px solid rgb(229,45,39);
}
#username:focus ~ #inputButton {
display: block;
}
#suggest {
position:absolute;
left:0;
top:8vw;
z-index:400;
width:70vw; /* 8vw + 1vw (margin) + 1vw (margin) + 75% of 80% */
left:50%;
transform: translate(-50%, 0);
display:none;
box-shadow:0 4px 10px -4px black;
list-style-type:none;
padding:0;
margin:0;
overflow: hidden;
background-color:white;
}
.suggest{
color:black;
cursor:pointer;
height:50px;
padding-bottom:10px;
padding-top:10px;
}
.suggest div{
font-size:2.5vw;
position:relative;
margin-left:10px;
left:50%;
top:50%;
-webkit-transform:translate(-50%,-50%);
transform:translate(-50%,-50%);
}
.suggest:hover {
background-color:rgb(229,45,39);
color:white;
}
.suggestImg {
float:left;
width:50px;
height:50px;
border-radius:50%;
margin-left:10px;
}
#bottomPrime {
width:100%;
position: relative;
}
#extra {
font-weight:400;
padding-top:15px;
padding-bottom:15px;
}
#extraContent {
display: none;
}
#extra table {
border-collapse: collapse;
font-size:2vw;
font-weight:100;
margin-left: auto;
margin-right: auto;
text-align: center;
}
#extra th, #extra td {
text-align: left;
vertical-align: center;
padding-top: 10px;
padding-bottom:10px;
padding-left:2vw;
padding-right:2vw;
border-bottom: 1px solid #ddd;
}
#milestoneBox {
font-size:3vw;
font-weight:100;
}
.myChart-wrapper {
width:80%;
margin-left:auto;
margin-right:auto;
}
#hideextra {
display:none;
}
.extrabutton {
border:none;
outline:none;
background-color:rgb(229,45,39);
color:white;
min-width: 150px;
height:4vw;
width:15vw;
margin-top: 20px;
margin-bottom: 20px;
margin-left:auto;
margin-right:auto;
font-size: 18px;
border-radius:4px;
font-weight:900;
cursor:pointer;
overflow:hidden;
z-index:2;
}
#vidsText {
font-size:25px;
}
#vids {
text-align:center;
width:5vw;
margin:1vw;
font-size:25px;
border:0;
border-bottom:0.5vw solid rgb(229,45,39);
background-color:rgba(200,200,200,0.3);
}
a {text-decoration:none;}
@media only screen and (max-width: 800px), screen and (orientation: portrait){
.navButtonsCover {
width:25%;
}
#bg1 h2 {
font-size: 12vw;
}
#pageUrl {
width:100%;
left:0;
}
.card {
width: 98% !important;
font-size:3vw;
}
#extra table {
font-size:5vw;
}
#milestoneBox {
font-size:8vw;
}
#actualCount {
font-size: 15vw !important;
}
#totalViews, #totalVideos, #pubDate {
font-size: 8vw !important;
}
#username:focus {
width:84%;
}
#username {
font-size:6vw;
}
#input, #dp {
height:12vw;
}
#suggest {
top:12vw;
width:87.5vw; /* 12vw + 1vw (margin) + 1vw (margin) + 75% of 98% */
}
#input button {
width:12vw;
}
.extrabutton {
height:8vw;
width:30vw;
}
.myChart-wrapper {
width:95%;
}
}
</style>
</head>
<body>
<section id="menu">
<div id="buttonBig">
<div class="navButtonsCover" data-child="logo" onClick="handleNavButtons(1)">
<div id="logo" class="navButtons" alt="YouCount Logo/Homepage"></div>
</div>
<div class="navButtonsCover" data-child="share" onClick="handleNavButtons(4)">
<div id="share" class="navButtons" alt="Share button"></div>
</div>
<div class="navButtonsCover" data-child="code" onClick="handleNavButtons(3)">
<div id="code" class="navButtons" alt="Get YouCount embed or widget"></div>
</div>
<div class="navButtonsCover" data-child="helpButton" onClick="handleNavButtons(2)">
<div id="helpButton" class="navButtons" alt="Help button"></div>
</div>
<ul id="sharebox">
<li><img id="fb" class="share" alt="Facebook Icon"></li>
<li><img id="tw" class="share" alt="Twitter Icon"></li>
<li><img id="lnkdIn" class="share" alt="LinkedIn Icon"></li>
<li><img id="tb" class="share" alt="Tumblr Icon"></li>
<li><img id="rdit" class="share" alt="Reddit Icon"></li>
<li><img id="link" class="share" alt="Link Icon"></li>
</ul>
</section>
<span id="pageUrl">
Select and copy the URL of this page below and use it to share this page anywhere!
<br><input type="text" value="" onclick="this.select()" readonly />
</span>
<div id="tutorial">
<img id="pointer">
<p id="tutStep1">Click Here</p>
<div id="tutStep2">
<h3 class="tutStep2">Search for a YouTube channel</h3>
<span class="tutStep2">For example, to see Fine Brothers Entertainment's live YouTube subscriber count, type in any one of these:</span>
<ol class="tutStep2">
<li><b>TheFineBros</b> (their username)</li>
<li><b>Fine Brothers Entertainment</b> (their YouTube channel name)</li>
<li><b></b> (their YouTube channel ID)</li>
<li><b>fine bros</b> (a search query)</li>
</ol>
</div>
</div>
<div class="bg ball" id="bg1">
<div id="helpArt">
<h2>About YouCount</h2>
<p>YouCount shows the LIVE growth of any YouTube® channel and achieving of milestones through their Realtime Subscriber Count (RSC) and Incredibly Useful Statistics (IUF).
Youtube updates the subscriber count after a long time.
On YouCount, the YouTube subscriber count is updated every second!</p>
<p>Furthermore, click on the "SHOW STATS" button to see other useful information related to the YouTube channel</p>
<p>YouCount has been specifically designed using the Material Design language to make it look awesome! It is also optimized for mobile devices and has been made to work even with older browsers.</p>
<p>To know more or to get in contact:
<ol>
<li><a href="//github.com/YouCount/youcount.github.io">Visit the GitHub Project site</a></li>
<li>Send an Email: <a id="email"></a></li>
</ol>
</p>
<p>Support the website by sharing it with your friends!</p>
<input type="button" class="extrabutton" value="How to Use" onclick="tutorial(0)">
</div>
<div id="codeArt">
<h2>Embed This!</h2>
<p>
Copy the code below and paste it where you want to embed this:
</p>
<code id="embedUrl"></code>
<p>
Adjust its size by changing the "height" and "width" attribute of the iframe.
The size will automatically adjust to the size of the iframe.
</p>
</div>
</div>
<div class="bg" id="bg2"></div>
<div id="mainPage">
<section id="prime" class="card">
<div id="topPrime">
<label for="username">
<img id="dp" alt="Channel Image">
</label>
<div id="input">
<input type="text" id="username" placeholder="Search for a YouTube channel" value="Loading..." onkeypress="trigenter(event)"/>
<button id="inputButton">
<img id="search" alt="Search Button to process the query">
</button>
<ul id="suggest">
<li class="suggest" id="suggest1"><img class="suggestImg"><div></div></li>
<li class="suggest"><img class="suggestImg"><div></div></li>
<li class="suggest"><img class="suggestImg"><div></div></li>
<li class="suggest"><img class="suggestImg"><div></div></li>
<li class="suggest"><img class="suggestImg"><div></div></li>
</ul>
</div>
</div>
<div id="bottomPrime">
<br>
<span id="actualCount">Loading...</span>
<br>
</div>
</section>
<section id="extra" class="card">
<button class="extrabutton" id="showextra">SHOW STATS</button>
<div id="extraContent">
<div class="myChart-wrapper">
<canvas width="400" height="200" id="myChart1"></canvas>
</div>
<br><br><br>
<span class="milestones" id="milestoneBox">
<span id="milestoneLeft">Loading...</span> left from <span id="milestoneTarget">Loading...</span>!
</span>
<br><br><br>
<table>
<tr>
<td>Total Views:</td>
<td><span id="totalViews">Loading...</span></td>
</tr>
<tr>
<td>Total Videos:</td>
<td><span id="totalVideos">Loading...</span></td>
</tr>
<tr>
<td>Since:</td>
<td><span id="pubDate">Loading...</span></td>
</tr>
</table>
<p id="vidsText">Last <input aria-label="Input box: Enter number of videos (1-25)" type="text" id="vids" placeholder="1-25" value="5"> videos</p><button class="extrabutton" onclick="upCharts();" id="upCharts">Update</button>
<div class="myChart-wrapper">
<canvas width="400" height="200" id="myChart2"></canvas>
<canvas width="400" height="200" id="myChart3"></canvas>
<canvas width="400" height="200" id="myChart4"></canvas>
</div>
</div>
<button class="extrabutton" id="hideextra">HIDE STATS</button>
</section>
</div>
<script>
//Odometer
(function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G=[].slice;q='<span class="odometer-value"></span>',n='<span class="odometer-ribbon"><span class="odometer-ribbon-inner">'+q+"</span></span>",d='<span class="odometer-digit"><span class="odometer-digit-spacer">8</span><span class="odometer-digit-inner">'+n+"</span></span>",g='<span class="odometer-formatting-mark"></span>',c="(,ddd).dd",h=/^\(?([^)]*)\)?(?:(.)(d+))?$/,i=30,f=2e3,a=20,j=2,e=.5,k=1e3/i,b=1e3/a,o="transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd",y=document.createElement("div").style,p=null!=y.transition||null!=y.webkitTransition||null!=y.mozTransition||null!=y.oTransition,w=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,l=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver,s=function(a){var b;return b=document.createElement("div"),b.innerHTML=a,b.children[0]},v=function(a,b){return a.className=a.className.replace(new RegExp("(^| )"+b.split(" ").join("|")+"( |$)","gi")," ")},r=function(a,b){return v(a,b),a.className+=" "+b},z=function(a,b){var c;return null!=document.createEvent?(c=document.createEvent("HTMLEvents"),c.initEvent(b,!0,!0),a.dispatchEvent(c)):void 0},u=function(){var a,b;return null!=(a=null!=(b=window.performance)?"function"==typeof b.now?b.now():void 0:void 0)?a:+new Date},x=function(a,b){return null==b&&(b=0),b?(a*=Math.pow(10,b),a+=.5,a=Math.floor(a),a/=Math.pow(10,b)):Math.round(a)},A=function(a){return 0>a?Math.ceil(a):Math.floor(a)},t=function(a){return a-x(a)},C=!1,(B=function(){var a,b,c,d,e;if(!C&&null!=window.jQuery){for(C=!0,d=["html","text"],e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(function(a){var b;return b=window.jQuery.fn[a],window.jQuery.fn[a]=function(a){var c;return null==a||null==(null!=(c=this[0])?c.odometer:void 0)?b.apply(this,arguments):this[0].odometer.update(a)}}(a));return e}})(),setTimeout(B,0),m=function(){function a(b){var c,d,e,g,h,i,l,m,n,o,p=this;if(this.options=b,this.el=this.options.el,null!=this.el.odometer)return this.el.odometer;this.el.odometer=this,m=a.options;for(d in m)g=m[d],null==this.options[d]&&(this.options[d]=g);null==(h=this.options).duration&&(h.duration=f),this.MAX_VALUES=this.options.duration/k/j|0,this.resetFormat(),this.value=this.cleanValue(null!=(n=this.options.value)?n:""),this.renderInside(),this.render();try{for(o=["innerHTML","innerText","textContent"],i=0,l=o.length;l>i;i++)e=o[i],null!=this.el[e]&&!function(a){return Object.defineProperty(p.el,a,{get:function(){var b;return"innerHTML"===a?p.inside.outerHTML:null!=(b=p.inside.innerText)?b:p.inside.textContent},set:function(a){return p.update(a)}})}(e)}catch(q){c=q,this.watchForMutations()}}return a.prototype.renderInside=function(){return this.inside=document.createElement("div"),this.inside.className="odometer-inside",this.el.innerHTML="",this.el.appendChild(this.inside)},a.prototype.watchForMutations=function(){var a,b=this;if(null!=l)try{return null==this.observer&&(this.observer=new l(function(){var a;return a=b.el.innerText,b.renderInside(),b.render(b.value),b.update(a)})),this.watchMutations=!0,this.startWatchingMutations()}catch(c){a=c}},a.prototype.startWatchingMutations=function(){return this.watchMutations?this.observer.observe(this.el,{childList:!0}):void 0},a.prototype.stopWatchingMutations=function(){var a;return null!=(a=this.observer)?a.disconnect():void 0},a.prototype.cleanValue=function(a){var b;return"string"==typeof a&&(a=a.replace(null!=(b=this.format.radix)?b:".","<radix>"),a=a.replace(/[.,]/g,""),a=a.replace("<radix>","."),a=parseFloat(a,10)||0),x(a,this.format.precision)},a.prototype.bindTransitionEnd=function(){var a,b,c,d,e,f,g=this;if(!this.transitionEndBound){for(this.transitionEndBound=!0,b=!1,e=o.split(" "),f=[],c=0,d=e.length;d>c;c++)a=e[c],f.push(this.el.addEventListener(a,function(){return b?!0:(b=!0,setTimeout(function(){return g.render(),b=!1,z(g.el,"odometerdone")},0),!0)},!1));return f}},a.prototype.resetFormat=function(){var a,b,d,e,f,g,i,j;if(a=null!=(i=this.options.format)?i:c,a||(a="d"),d=h.exec(a),!d)noInternet("Odometer: Unparsable digit format");return j=d.slice(1,4),g=j[0],f=j[1],b=j[2],e=(null!=b?b.length:void 0)||0,this.format={repeating:g,radix:f,precision:e}},a.prototype.render=function(a){var b,c,d,e,f,g,h,i,j,k,l,m;for(null==a&&(a=this.value),this.stopWatchingMutations(),this.resetFormat(),this.inside.innerHTML="",g=this.options.theme,b=this.el.className.split(" "),f=[],i=0,k=b.length;k>i;i++)c=b[i],c.length&&((e=/^odometer-theme-(.+)$/.exec(c))?g=e[1]:/^odometer(-|$)/.test(c)||f.push(c));for(f.push("odometer"),p||f.push("odometer-no-transitions"),f.push(g?"odometer-theme-"+g:"odometer-auto-theme"),this.el.className=f.join(" "),this.ribbons={},this.digits=[],h=!this.format.precision||!t(a)||!1,m=a.toString().split("").reverse(),j=0,l=m.length;l>j;j++)d=m[j],"."===d&&(h=!0),this.addDigit(d,h);return this.startWatchingMutations()},a.prototype.update=function(a){var b,c=this;return a=this.cleanValue(a),(b=a-this.value)?(v(this.el,"odometer-animating-up odometer-animating-down odometer-animating"),b>0?r(this.el,"odometer-animating-up"):r(this.el,"odometer-animating-down"),this.stopWatchingMutations(),this.animate(a),this.startWatchingMutations(),setTimeout(function(){return c.el.offsetHeight,r(c.el,"odometer-animating")},0),this.value=a):void 0},a.prototype.renderDigit=function(){return s(d)},a.prototype.insertDigit=function(a,b){return null!=b?this.inside.insertBefore(a,b):this.inside.children.length?this.inside.insertBefore(a,this.inside.children[0]):this.inside.appendChild(a)},a.prototype.addSpacer=function(a,b,c){var d;return d=s(g),d.innerHTML=a,c&&r(d,c),this.insertDigit(d,b)},a.prototype.addDigit=function(a,b){var c,d,e,f;if(null==b&&(b=!0),"-"===a)return this.addSpacer(a,null,"odometer-negation-mark");if("."===a)return this.addSpacer(null!=(f=this.format.radix)?f:".",null,"odometer-radix-mark");if(b)for(e=!1;;){if(!this.format.repeating.length){if(e)noInternet("Bad odometer format without digits");this.resetFormat(),e=!0}if(c=this.format.repeating[this.format.repeating.length-1],this.format.repeating=this.format.repeating.substring(0,this.format.repeating.length-1),"d"===c)break;this.addSpacer(c)}return d=this.renderDigit(),d.querySelector(".odometer-value").innerHTML=a,this.digits.push(d),this.insertDigit(d)},a.prototype.animate=function(a){return p&&"count"!==this.options.animation?this.animateSlide(a):this.animateCount(a)},a.prototype.animateCount=function(a){var c,d,e,f,g,h=this;if(d=+a-this.value)return f=e=u(),c=this.value,(g=function(){var i,j,k;return u()-f>h.options.duration?(h.value=a,h.render(),void z(h.el,"odometerdone")):(i=u()-e,i>b&&(e=u(),k=i/h.options.duration,j=d*k,c+=j,h.render(Math.round(c))),null!=w?w(g):setTimeout(g,b))})()},a.prototype.getDigitCount=function(){var a,b,c,d,e,f;for(d=1<=arguments.length?G.call(arguments,0):[],a=e=0,f=d.length;f>e;a=++e)c=d[a],d[a]=Math.abs(c);return b=Math.max.apply(Math,d),Math.ceil(Math.log(b+1)/Math.log(10))},a.prototype.getFractionalDigitCount=function(){var a,b,c,d,e,f,g;for(e=1<=arguments.length?G.call(arguments,0):[],b=/^\-?\d*\.(\d*?)0*$/,a=f=0,g=e.length;g>f;a=++f)d=e[a],e[a]=d.toString(),c=b.exec(e[a]),e[a]=null==c?0:c[1].length;return Math.max.apply(Math,e)},a.prototype.resetDigits=function(){return this.digits=[],this.ribbons=[],this.inside.innerHTML="",this.resetFormat()},a.prototype.animateSlide=function(a){var b,c,d,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,v,w,x,y,z,B,C,D,E;if(s=this.value,j=this.getFractionalDigitCount(s,a),j&&(a*=Math.pow(10,j),s*=Math.pow(10,j)),d=a-s){for(this.bindTransitionEnd(),f=this.getDigitCount(s,a),g=[],b=0,m=v=0;f>=0?f>v:v>f;m=f>=0?++v:--v){if(t=A(s/Math.pow(10,f-m-1)),i=A(a/Math.pow(10,f-m-1)),h=i-t,Math.abs(h)>this.MAX_VALUES){for(l=[],n=h/(this.MAX_VALUES+this.MAX_VALUES*b*e),c=t;h>0&&i>c||0>h&&c>i;)l.push(Math.round(c)),c+=n;l[l.length-1]!==i&&l.push(i),b++}else l=function(){E=[];for(var a=t;i>=t?i>=a:a>=i;i>=t?a++:a--)E.push(a);return E}.apply(this);for(m=w=0,y=l.length;y>w;m=++w)k=l[m],l[m]=Math.abs(k%10);g.push(l)}for(this.resetDigits(),D=g.reverse(),m=x=0,z=D.length;z>x;m=++x)for(l=D[m],this.digits[m]||this.addDigit(" ",m>=j),null==(u=this.ribbons)[m]&&(u[m]=this.digits[m].querySelector(".odometer-ribbon-inner")),this.ribbons[m].innerHTML="",0>d&&(l=l.reverse()),o=C=0,B=l.length;B>C;o=++C)k=l[o],q=document.createElement("div"),q.className="odometer-value",q.innerHTML=k,this.ribbons[m].appendChild(q),o===l.length-1&&r(q,"odometer-last-value"),0===o&&r(q,"odometer-first-value");return 0>t&&this.addDigit("-"),p=this.inside.querySelector(".odometer-radix-mark"),null!=p&&p.parent.removeChild(p),j?this.addSpacer(this.format.radix,this.digits[j-1],"odometer-radix-mark"):void 0}},a}(),m.options=null!=(E=window.odometerOptions)?E:{},setTimeout(function(){var a,b,c,d,e;if(window.odometerOptions){d=window.odometerOptions,e=[];for(a in d)b=d[a],e.push(null!=(c=m.options)[a]?(c=m.options)[a]:c[a]=b);return e}},0),m.init=function(){var a,b,c,d,e,f;if(null!=document.querySelectorAll){for(b=document.querySelectorAll(m.options.selector||".odometer"),f=[],c=0,d=b.length;d>c;c++)a=b[c],f.push(a.odometer=new m({el:a,value:null!=(e=a.innerText)?e:a.textContent}));return f}},null!=(null!=(F=document.documentElement)?F.doScroll:void 0)&&null!=document.createEventObject?(D=document.onreadystatechange,document.onreadystatechange=function(){return"compvare"===document.readyState&&m.options.auto!==!1&&m.init(),null!=D?D.apply(this,arguments):void 0}):document.addEventListener("DOMContentLoaded",function(){return m.options.auto!==!1?m.init():void 0},!1),"function"==typeof define&&define.amd?define(["jquery"],function(){return m}):typeof exports===!1?module.exports=m:window.Odometer=m}).call(this);
//Odometer End
//This contains the code within the html files which loads up and shows subscriber count. Somw of the comments have not been updated
//as the script was updated and they are also written in a vague manner as I had commented them to assist me and then later on,
//I had decided to upload this file as well.
//--------PRELUDE---------
//----Variables----
var APIkeys = ["AIzaSyBAb4nM48dVlty7LPHm_qrcWrhlQ1P205U"];
var username = '';
var rawInput = username;
var channelname;
var channeldate = '';
var popstatevar = 1;
var keyIndex = Math.round(Math.random()*(APIkeys.length-1)),
isLoaded = 0,
seconds = 0;
var actualCount;
var targets = [10, 25, 50, 1E2, 5E2, 1E3, 2.5E3, 5E3, 1E4, 2.5E4, 5E4, 1E5, 2.5E5, 5E5, 1E6, 2E6, 3E6, 4E6, 5E6, 6E6,7E6, 10E6, 15E6, 20E6, 25E6, 30E6, 40E6, 50E6, 70E6, 1E8, 1.5E8, 2E8, 3E8];
var myLineChart1;
var internet = 1;//change this to 1 when uploaded.
const developmentMode = 1;
//-----select APIkey randomly----
function getKey() {
++keyIndex;
if(keyIndex == APIkeys.length) keyIndex = 0;
return APIkeys[keyIndex];
}
// ------ Assigns forEach to NodeList if not already available (minimum requirement = ES5)------
if (window.NodeList && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = function (callback, thisArg) {
thisArg = thisArg || window;
for (var i = 0; i < this.length; i++) {
callback.call(thisArg, this[i], i, this);
}
};
}
//----AJAX function for code reusability----
function AJX(url, success, failure) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if(request.readyState == 4) {
if(request.status == 200) {
if(success)success(JSON.parse(request.responseText));
} else {
noInternet('AJX failed to load ' + url);
if(failure)failure(request.statusText);
}
}
};
request.open('GET', url);
request.send();
}
//----text changing function for code reusability----
function changeText(elem, changeVal) {
if('form' in elem) {
elem.value = changeVal;
} else {
elem.textContent = changeVal;
}
}
//--------MAIN PROGRAM---------
//----receives value inputted by user and sends it while input box is starts showing 'Loading...'----
var isTutorialOn = 0;
function getValueFromURL() {
if(location.hash.split("#!/")[1]) {//if something is there after #!/, make that the search query else set page as homepage.
getValue(location.hash.split("#!/")[1]);
} else {
try {
tutorial();
} catch (e) {
isTutorialOn = 1;
}
}
}
function getValue(value) {
if (!value)
value = document.getElementById('username').value;
value = value.trim();
if (!internet){
document.getElementById('username').value = 'Refresh the page';
return;
}
if (!value || value=="Not Found!" || value=="Loading..." || value=="Refresh the page")
return;
if (isTutorialOn) tutorial(3);
changeText(document.getElementById('username'), "Loading...");
document.getElementById("username").blur();
rawInput = value;
intervalId = setInterval(live, 1000);
queryName();
}
function noInternet(e) {
if (developmentMode) {
console.log('noInternet:' + e);
} else {
internet = 0;
document.getElementById('actualCount').innerHTML ="No Internet";
var arr = ["totalViews","totalVideos","pubDate","username"];
for(var x=0;x<arr.length;x++){
changeText(document.getElementById(arr[x]),"No Internet");
}
document.getElementById('username').value = 'Refresh the page';
document.getElementById('dp').style.display = 'none';
clearInterval(intervalId);
}
}
/*
function to:-
1. determine whether value inputted leads up to a youtube channel
2. get channel name, picture, total videos, total views, date of starting youtube, and changing url
*/
var isChart = 0,
notFound = 0,
firstload=0;
function queryName() {
try {
AJX("https://www.googleapis.com/youtube/v3/search?part=snippet&q=" + encodeURIComponent(rawInput) + "&type=channel&maxResults=1&key=" + getKey(), function(e) {
if(!e.items){
noInternet( "undef e.items in queryName");
return;
}
if(e.pageInfo.totalResults < 1) {//if no result found, show not found and hide stuff
document.getElementById('actualCount').style.display = "none";
document.getElementById('milestoneBox').style.display = "none";
document.getElementById('dp').style.display = "none";
document.getElementById('extra').style.display = "none";
clearInterval(intervalId);
notFound = 1;
return;
}//else
//show stuff
if(notFound == 1) {//show HTML elements if previously hidden
document.getElementById('actualCount').style.display = "inline-block";
document.getElementById('milestoneBox').style.display = "inline";
intervalId = setInterval(live, 1000);
notFound = 0;
}
document.getElementById("dp").style.display = 'block';
document.getElementById('extra').style.display = "block";
//set channel name in input box and title
channelname = e.items[0].snippet.title;
changeText(document.querySelector("#username"), channelname);
//sets username to channel id so that further requests to find out about the channel can be made
username = e.items[0].snippet.channelId.trim();
//resetting charts so it loads again.
if(isChart===2){
isChart = 1;
}
//running live manually to get updated info immediately
live();
//set date of starting youtube with months in text (jan, feb, etc)
var pubDate = e.items[0].snippet.publishedAt.split("T")[0];
pubDate = pubDate.split("-");
pubDate[1] = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'][(Number(pubDate[1])-1)];
channeldate = pubDate[2] + '-' + pubDate[1] + '-' + pubDate[0];
//sends request to find if customUrl is available. if available, uses it for setting url, otherwise uses title for setting url
//if pushState has to not be set during a queryName run, popstatevar is set to 0. It automatically resets to 1 after not running once.
var reqType = (username.length >= 24 && username.substr(0, 2).toUpperCase() == "UC") ? "id" : "forUsername";
if(popstatevar == 1) {
var urlCandidate, urlFinalName;
var url = "https://www.googleapis.com/youtube/v3/channels?part=snippet&" + reqType + "=" + username + "&fields=items/snippet&key=" + getKey();
AJX(url, function(e) {
if(e.items[0].snippet.customUrl) {
urlCandidate = e.items[0].snippet.customUrl.trim();
} else {
urlCandidate = channelname.trim().replace(/\s+/g, '+');
}
var url = "https://www.googleapis.com/youtube/v3/search?part=snippet&q=" + encodeURIComponent(urlCandidate) + "&type=channel&maxResults=1&key=" + getKey();
AJX(url, function(f) {
if((f.pageInfo.totalResults < 1) || (f.items[0].snippet.channelId.trim() != username)){
urlFinalName = username;
} else {
urlFinalName = urlCandidate;
}
history.pushState(null, null, "#!/" + urlFinalName);
//also sets iframe src url for embedding and url for sharing.
changeText(document.getElementById('embedUrl'), '<iframe src="https://youcount.github.io/e/#!/' + urlFinalName + '" height="100" width="250" frameborder="0"></iframe>');
changeText(document.querySelector('#pageUrl input'), 'https://youcount.github.io/#!/' + urlFinalName);
});
});
} else popstatevar = 1;//resetting of popstatevar
if(firstload){
var url = "https://www.googleapis.com/youtube/v3/channels?part=contentDetails&" + reqType + "=" + username + "&fields=items/contentDetails/relatedPlaylists/uploads&key=" + getKey();
AJX(url, function(e) {
var url = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=" + e.items[0].contentDetails.relatedPlaylists.uploads + "&maxResults=50&fields=items/snippet/resourceId/videoId&key=" + getKey();
AJX(url, function(e) {
for(var i=0; e.items[i]; i++){
var url = "https://www.googleapis.com/youtube/v3/videos?part=statistics&id=" + e.items[i].snippet.resourceId.videoId + "&fields=items/statistics/viewCount&key=" + getKey();
pushViews(url,i);
}
});
});
}
//set profile picture of channel
document.getElementById("dp").src = e.items[0].snippet.thumbnails.default.url;
/*
from https://developers.google.com/youtube/v3/docs/channels#properties
snippet.description - Channel description
*/
//ga("send","pageview",location.pathname);
}, noInternet);
} catch (e) {
noInternet(e);
}
}
var isLive = 0, myLineChart1Data, prevCounts = [[0],[0],[0],[0],[0]]
function live() {
var reqType = (username.length >= 24 && username.substr(0, 2).toUpperCase() == "UC") ? "id" : "forUsername";
var url = "https://www.googleapis.com/youtube/v3/channels?part=statistics&" + reqType + "=" + username + "&fields=items/statistics/subscriberCount&key=" + getKey();
try{
AJX(url, function(e) {
var prevCount = actualCount;
if(!e.items || !e.items[0].statistics.subscriberCount){
noInternet( "undef e.items or e.items[0].statistics.subscriberCount in live");
return;
} else {
actualCount = e.items[0].statistics.subscriberCount;//set actualCount to realtime subscribers
//get milestones
var target = 0;
for(var i = 0; i < targets.length; i++) {
if(actualCount <= targets[i]) {
target = targets[i];
break;
}
}
var subs_left = target - actualCount;
if((actualCount-prevCount)>0)document.body.style.backgroundColor = 'rgb(240,255,240)';
else if((actualCount-prevCount)===0)document.body.style.backgroundColor = 'rgb(250,250,250)';
else document.body.style.backgroundColor = 'rgb(255,240,240)';
//load chart if not already loaded and update it.
if(isChart === 1) {
myLineChart1Data = {
labels: [''],
datasets: [{
label: "Realtime Trend (30s)",
fill:false,
borderColor: "rgba(255,50,50,0.5)",
pointRadius:0,
data: [actualCount]
}]
};
myLineChart1 = new Chart(document.getElementById("myChart1").getContext("2d"), {
type:"line",
data: myLineChart1Data,
gridLines: {display:false},
responsive: true,
maintainAspectRatio: false
});
isChart = 2;
seconds=0;
}
++seconds;
prevCounts[seconds%5]=actualCount;
//send updated values of actualCount and milestones
if(!isLive) {
new Odometer({
el: document.getElementById("actualCount"),
value: actualCount,
format: '(,ddd)',
theme: 'minimal'
});
new Odometer({
el: document.getElementById("milestoneLeft"),
value: subs_left,
format: '(,ddd)',
theme: 'minimal'
});
isLive = 1;
} else {
changeText(document.getElementById("actualCount"), actualCount);
changeText(document.getElementById("milestoneLeft"), subs_left);
changeText(document.getElementById("milestoneTarget"), target.toLocaleString("en-US"));
if(subs_left<1&&subs_left>-1){
document.getElementById("milestoneBox").innerHTML = "Congratulations!";
}
//if chart is already loaded, the value of chart is updated here.
if(isChart===2&&seconds%5==0) {
for(var i=0;i<5;i++)myLineChart1.data.labels.push('');
for(i=0;i<5;i++)myLineChart1.data.datasets[0].data.push(prevCounts[i]);
if(seconds > 30) {//the max values of x axis is 30 seconds and after that limit is reached, starting values start getting destroyed.
for(i=0;i<5;i++){
myLineChart1.data.labels.shift();
myLineChart1.data.datasets[0].data.shift();
}
}
myLineChart1.update();
}
}
}
}, noInternet);
} catch (e) {
noInternet(e);
}
}
//this code below, which is not inside any function, starts in the very beginning.
if(!developmentMode) {
// 1. Check if iframe or http
if (window.top !== window.self || window.top.location != window.self.location) {
window.top.location = window.self.location;
} else if(window.location.hostname != 'youcount.github.io' || window.top.location.hostname != 'youcount.github.io') {
window.location.hostname = 'youcount.github.io';
} else if (window.location.protocol != "https:") {
try {
window.location.protocol = "https:";
} catch (err) {
window.location.protocol = "https";
}
} else {
// 2. this starts the processes in the beginning.
getValueFromURL();
}
} else {
// 2. this starts the processes in the beginning.
getValueFromURL();
}
window.onpopstate = function() {
popstatevar = 0;
getValueFromURL();
changeText(document.querySelector('#username'), "Loading...");
queryName();
};
//--------MAIN PROGRAM ENDS---------
function getScript(source,callback,prop,val) {//used to load jQuery (basically a replacement for $.getScript)
var script = document.createElement('script');
var prior = document.getElementsByTagName('script')[0];
script.async = 1;
prior.parentNode.insertBefore(script, prior);
script.onload = script.onreadystatechange = function( _, isAbort ) {
if(isAbort || !script.readyState || /loaded|compvare/.test(script.readyState) ) {
script.onload = script.onreadystatechange = null;
script = undefined;
if(!isAbort) { if(callback) callback(); }
else noInternet('getScript failed to load' + source);
}
};
if (prop&&val) {
for(var a=0;a<prop.length;a++){
if(prop[a])
script[prop[a]]= val[a];
}
}
script.src = source;
}
window.onload = function() {
getScript("js/script.js");
}
</script>
</body>
</html>