How to use javascript with accelerated mobile page(AMP)? - javascript

I am trying to create an accelerated mobile page(AMP) using Javascript.
The AMP validator shows an error called "Custom JavaScript is not allowed".
I have tried below code.
<!doctype html>
<html amp>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="amp-script-src" content="sha384-vk5WoKIaW_vJyUAd9n_wmopsmNhiy-L2Z-SBxGYnUkunIxVxAv_UtMOhba_xskxh">
<title>Document</title>
<link rel="canonical" href="/" />
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script async custom-element="amp-script" src="https://cdn.ampproject.org/v0/amp-script-0.1.js"></script>
<style amp-boilerplate>
body {
-webkit-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-moz-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-ms-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
animation: -amp-start 8s steps(1, end) 0s 1 normal both
}
#-webkit-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#-moz-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#-ms-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#-o-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
</style>
<noscript>
<style amp-boilerplate>
body {
-webkit-animation: none;
-moz-animation: none;
-ms-animation: none;
animation: none
}
</style>
</noscript>
</head>
<body>
<amp-script script="local-script">
<button>Hello amp-script!</button>
</amp-script>
<script target="amp-script" type="text/plain" id="local-script">
console.log('js added')
</script>
</body>
</html>
I need to find some possible solution to work AMP with Javascript.
The AMP validator needs to be clean as it shows 1 error "Custom JavaScript is not allowed" which I am unable to find the cause from the above code.

Related

AMP - manual trigger action on component

Is there any way to manual trigger action on AMP?
For example I have a carousel and I would like to manually change slide index
https://amp.dev/documentation/components/amp-carousel/?format=websites#gotoslide(index=integer)
there is a goToSlide action, but I only found execution on amp elements, but what if I would like to do this with VUE or VanillaJS? e.g.
<amp-carousel type="slides"
width="450"
height="300"
controls
loop
autoplay
delay="3000" data-next-button-aria-label="Go to next slide"
data-previous-button-aria-label="Go to previous slide"
role="region"
aria-label="Looping carousel">
<amp-img src="/static/inline-examples/images/image1.jpg"
width="450"
height="300"></amp-img>
<amp-img src="/static/inline-examples/images/image2.jpg"
width="450"
height="300"></amp-img>
<amp-img src="/static/inline-examples/images/image3.jpg"
width="450"
height="300"></amp-img>
</amp-carousel>
<button id="test">Change<button>
And JS Code:
const index = 10;
const button = document.querySelector('#button');
button.addEventListener('click', () => {
// trigger `goToSlide` with index arg
})
but what if I would like to do this with VUE or VanillaJS?
Then you should have tried amp-script right away.
My solution is not to use the goToSlide method, but to use the [slide] attribute(enabling amp-bind).
We create a local variable(amp-state), then use amp-script to change the value of this variable. For the carousel, the [slide] attribute will take the value of our local variable.
<!DOCTYPE html>
<html amp lang="en">
<head>
<meta charset="utf-8" />
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
<script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.2.js"></script>
<script async custom-element="amp-script" src="https://cdn.ampproject.org/v0/amp-script-0.1.js"></script>
<meta name="amp-script-src" content="sha384-4UtnPtFFgGH7cYZgZV7ayJB7EQ9O4lK09yk4JpoBdinMiCGpq5M3nY0BaQ3NMhIR" />
<title>Hello, AMPs</title>
<link rel="canonical" href="https://amp.dev/documentation/guides-and-tutorials/start/create/basic_markup/" />
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
<style amp-boilerplate>
body {
-webkit-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-moz-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-ms-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
animation: -amp-start 8s steps(1, end) 0s 1 normal both;
}
#-webkit-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
#-moz-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
#-ms-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
#-o-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
#keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
</style>
<noscript>
<style amp-boilerplate>
body {
-webkit-animation: none;
-moz-animation: none;
-ms-animation: none;
animation: none;
}
</style>
</noscript>
<style amp-custom>
</style>
</head>
<body>
<amp-state id="carouselState">
<script type="application/json">
{
"activeSlide": "1"
}
</script>
</amp-state>
<amp-script script="mySuperScript" layout="container">
<amp-carousel id="myCarousel" [slide]="carouselState.activeSlide" width="450" height="300" layout="fixed" type="slides" role="region" aria-label="Basic carousel">
<amp-img src="https://amp.dev/static/samples/img/image1.jpg" width="450" height="300"></amp-img>
<amp-img src="https://amp.dev/static/samples/img/image2.jpg" width="450" height="300"></amp-img>
<amp-img src="https://amp.dev/static/samples/img/image3.jpg" width="450" height="300"></amp-img>
</amp-carousel>
<button id="carouselBtn">Change Slide<button>
</amp-script>
<script id="mySuperScript" type="text/plain" target="amp-script">
let index = 2;
const button = document.querySelector('#carouselBtn');
button.addEventListener('click', () => {
AMP.setState({carouselState: {activeSlide: index } });
index = (index < 2 ? index + 1 : index - 2 );
});
</script>
</body>
</html>

how can I create css news ticker for AMP-HTML?

here is a good example with jquery but it is not valid jQuery for AMP
$(document).ready(function() {
try {
var ticker_holder = $('.ticker-holder').get(0);
var ticker_text = $('.ticker').get(0);
var ticker_pos = ticker_text.parentNode.offsetWidth;
var ticker_data = $(ticker_holder).html();
$(ticker_text).parent().html('<marquee scrollamount="10" scrolldelay="">' + ticker_data + '</marquee>');
$('.emergencyalert').hover(
function() {
$('marquee', this).get(0).stop();
}, function() {
$('marquee', this).get(0).start();
});
}
catch (o) {}
});
Is there any component in AMP to do something like that?
<marquee> element was removed from HTML5. I suggest you can achieve marquee effect from css animations. AMP doesn't have any such component which has functionality like marquee. Here is code i tested in AMP playground and adds marquee like effect. You can modify it further to achieve exact same effect you looking for.
<!doctype html>
<html ⚡>
<head>
<meta charset="utf-8">
<link rel="canonical" href="https://amp.dev/documentation/examples/components/amp-autocomplete/index.html">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<script async src="https://cdn.ampproject.org/v0.js"></script>
<title>amp-autocomplete</title>
<style amp-custom>
.wrap{
position: relative;
}
.ul-list{
list-style: none;
}
.li-list{
display: inline-block;
padding: 1em 2em;
font-size: 1.2em;
}
.spot-anim {
position: absolute;
right: -1em;
transform: translateX(-100%);
will-change: transform;
animation-duration: 30s;
animation-timing-function: linear;
animation-iteration-count: infinite;
-webkit-animation-name: marquee;
-moz-animation: marquee;
-o-animation-name: marquee;
animation-name: marquee;
}
</style>
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}#-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
</head>
<body>
<div class="wrap">
<ul class="ul-list spot-anim">
<li class="li-list"> News number 1</li>
<li class="li-list"> News number 2</li>
<li class="li-list"> News number 3</li>
<li class="li-list"> News number 4</li>
</ul>
</div>
<style amp-keyframes>
#keyframes marquee {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(-150%);
}
}
</style>
</body></html>
You may also use amp-script with layout="fixed-height" here to achieve same animations with stop functionality on mouse over event with javascript.

Can i use web components in AMP pages

I am trying to use web components in AMP page with amp-script but it's not working.
I am trying to add following code in index.html
<amp-script width="200" height="50" script="app-render">
<div id="app">loading...</div>
</amp-script>
<script id="app-render" type="text/plain" target="amp-script">
const app = document.getElementById('app');
app.innerHTML = <amp-news-container id="amp-news-container"></amp-news-container>;
</script>
But not working.
I also tried to add custom component into page but that creates error as custom component not allowed.
Is there any way i can use web components in AMP pages? no content or example found to user web components in AMP.
Adding whole index page -
<!DOCTYPE html>
<html ⚡️ lang="en" dir="ltl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script async src="https://cdn.ampproject.org/v0.js"></script>
<title>AMP Web Components</title>
<link rel="canonical" href="https://amp.dev/documentation/guides-and-tutorials/start/create/basic_markup/">
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "NewsArticle",
"headline": "Open-source framework for publishing content",
"datePublished": "2015-10-07T12:02:41Z",
"image": [
"logo.jpg"
]
}
</script>
<style amp-boilerplate>
body {
-webkit-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-moz-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-ms-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
animation: -amp-start 8s steps(1, end) 0s 1 normal both
}
#-webkit-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#-moz-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#-ms-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#-o-keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
#keyframes -amp-start {
from {
visibility: hidden
}
to {
visibility: visible
}
}
</style><noscript>
<style amp-boilerplate>
body {
-webkit-animation: none;
-moz-animation: none;
-ms-animation: none;
animation: none
}
</style>
</noscript>
<meta name="amp-script-src" content="sha384-N4a96F4jCQXTuaWhxfKGHDf9ZQmsqohVQd4GoJxNFVi1PznNK-wtSZXZuJTCettD" />
<script custom-element="amp-script" src="https://cdn.ampproject.org/v0/amp-script-0.1.js" async=""></script>
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:wght#500;700&display=swap" rel="stylesheet">
</head>
<body class="news">
<amp-script width="200" height="50" script="app-render">
<div id="app">loading...</div>
</amp-script>
<script id="app-render" type="text/plain" target="amp-script">
const app = document.getElementById('app');
app.innerHTML = <amp-news-container id="amp-news-container"></amp-news-container>;
</script>
</body>
</html>
Here is my - amp-news-container.js
const ampNewsContainer = document.createElement('ampNewsContainer');
ampNewsContainer.innerHTML = `
<style>
</style>
<div class="amp-news-container">
<amp-news-header class="amp-news-header"></amp-news-header>
</div>
`;
class AmpNewsContainer extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(ampNewsContainer.cloneNode(true));
}
}
window.customElements.define('amp-news-container', AmpNewsContainer);
and
const ampNewsHeader = document.createElement('ampNewsHeader');
ampNewsHeader.innerHTML = `
<style>
</style>
<div class="amp-news-header">
<h1>Page header</h1>
</div>
`;
class AmpNewsHeader extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(ampNewsHeader.cloneNode(true));
}
}
window.customElements.define('amp-news-container', AmpNewsHeader);
But i am facing error while i am trying add/bind amp-news-container to body or div tag.
I can't use custom component directly in body as follow, it's giving AMP validation error as custom component not allowed.
The way i use web component in normal projects, add custom container component in index.html and import other sub models into same index page but no similar way found to use them in AMP.
Example of trying custom component in body -
<body class="afc-champions-league-news">
<div id="amp-news-container">
<amp-news-container id="amp-news-container"></amp-news-container>
</div>
<amp-script type="module" src="js/modules/news/components/amp-news-header.js" width="300" height="100">
</amp-script>
<amp-script type="module" src="js/modules/news/components/amp-news-container.js" width="300" height="100">
</amp-script> -->
</body>
no Clue if is there any way i can have these two integrated together.

Slide in and slide out a button on page scroll

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style>
.container{
height: 2000px;
background:green;
padding:10px;
}
.btn{
position:fixed;
top:50%;
right:-50%;
transition:all 600ms ease-out;
}
.slideIn{
animation: 600ms ease-in 0s slideIn;
animation-fill-mode: forwards;
}
.slideOut{
animation: 600ms ease-out 0s slideOut;
animation-fill-mode: forwards;
}
#keyframes slideIn {
from{
right:-50%;
}
to{
right:0%;
}
}
#keyframes slideOut {
from{
right:0%;
}
to{
right:-50%;
}
}
</style>
</head>
<body>
<div id="container" class="container">
<div style="height: 200px;background:red;"></div>
<div style="height: 200px;background:yellow;"></div>
<div id="someEle" style="height: 200px;background:blue;"></div>
<div style="height: 200px;background:red;"></div>
<div style="height: 200px;background:yellow;"></div>
</div>
<button id="btn" class="btn">GET API ACCESS</button>
<script>
function init(){
var parent = document.getElementById("container");
window.addEventListener('scroll',function(e){
var parentScrollHeight = parent.scrollHeight;
var parentScrollTop = document.documentElement.scrollTop;
var startPoint = (parentScrollHeight/100) * 10;
var endPoint = (parentScrollHeight/100) * 70;
console.log(parentScrollTop,startPoint,endPoint)
try{
var ele = document.getElementById("btn");
if(parentScrollTop > startPoint && parentScrollTop < endPoint){
console.log("added")
ele.classList.add("slideIn");
}else{
console.log("removed");
ele.classList.remove("slideIn");
}
}catch(e){
console.log(e);
}
});
}
init();
</script>
</body>
</html>
how to slide in and slide out a button while scrolling a page. slide in is working slide out not working.
you should add animation for btn
css
.btn{
position:fixed;
top:50%;
right:-50%;
transition:all 600ms ease-out;
animation: 600ms ease-out 0s slideOut;
animation-fill-mode: forwards;
}

how to revert css3 keyframe animation from current frame on mouse out?

I want tot revert back to my first position from the current frame of animation.
Here in this code I have written a simple css3 keyframe animation and its working on hover. while mouse is out, I want this element to revert back to its first position with animation.
// html
------------------------------------
<div class="wrapper">
<div class="test"></div>
</div>
Css
.wrapper {width: 300px; height: 400px; position: relative;}
.test {width:40px; height: 40px; background-color: #0c6; border-radius: 40px; position: absolute; top:100px; left: 100px;}
.wrapper:hover .test{
animation-name:testin ; -webkit-animation-name:testin;
animation-duration: 2s; -webkit-animation-duration: 2s;
animation-timing-function: ease; -webkit-animation-timing-function:ease;
animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite;
animation-direction: normal; -webkit-animation-direction: normal;
animation-delay: 0s; -webkit-animation-delay:0s;
animation-play-state: running; -webkit-animation-play-state: running;
animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards;
}
#keyframes testin {
0%{top:100px; left:100px;}
20%{top:150px; left:150px;}
40%{top:200px; left:50px;}
60%{top:250px; left:150px;}
80%{top:300px; left:50px;}
100%{top:350px; left:150px;}
}
#-webkit-keyframes testin {
0%{top:100px; left:100px;}
20%{top:150px; left:150px;}
40%{top:200px; left:50px;}
60%{top:250px; left:150px;}
80%{top:300px; left:50px;}
100%{top:350px; left:150px;}
}
Please tell me if there is any javascript / jquery help or library for this kind of effects.
Thanks
what you want to achieve can be done with JavaScript or JQuery. These two are the ones that triggers functionality in a web page, so in your example the functionality of ":hover" (which is CSS) can also be achieved with JS libraries. In this case a simple one to use is hover(), so let's say we use JQuery library for this, and we'll start off by setting the appropiate scripts and markup in HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1">
<title>Document</title>
<link rel="stylesheet" href="css/main.css" />
</head>
<body>
<div class="wrapper">
<div class="test"></div>
</div>
<script type= "text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
Once you have that, we will need to create the other keyframe animation which will be the opposite, something like this:
#keyframes testinBack {
0%{top:350px; left:150px;}
20%{top:300px; left:50px;}
40%{top:250px; left:150px;}
60%{top:200px; left:50px;}
80%{top:150px; left:150px;}
100%{top:100px; left:100px;}
}
#-webkit-keyframes testinBack {
0%{top:350px; left:150px;}
20%{top:300px; left:50px;}
40%{top:250px; left:150px;}
60%{top:200px; left:50px;}
80%{top:150px; left:150px;}
100%{top:100px; left:100px;}
}
Now for the JS part, what we will do is to create a class in CSS from the one you already had, and create two classes, one with the keyframe animation-name: "testin", and the other with "testinBack":
.animationTest{
animation-name: testin; -webkit-animation-name:testin;
animation-duration: 2s; -webkit-animation-duration: 2s;
animation-timing-function: ease; -webkit-animation-timing-function:ease;
animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite;
animation-direction: normal; -webkit-animation-direction: normal;
animation-delay: 0s; -webkit-animation-delay:0s;
animation-play-state: running; -webkit-animation-play-state: running;
animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards;
}
.animationTestBack{
animation-name: testinBack; -webkit-animation-name:testinBack;
animation-duration: 2s; -webkit-animation-duration: 2s;
animation-timing-function: ease; -webkit-animation-timing-function:ease;
animation-iteration-count: infinite; -webkit-animation-iteration-count: infinite;
animation-direction: normal; -webkit-animation-direction: normal;
animation-delay: 0s; -webkit-animation-delay:0s;
animation-play-state: running; -webkit-animation-play-state: running;
animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards;
}
With that created, now the JS part should end up like this:
$( ".wrapper" ).hover(function() {
$('.test').addClass('animationTestin');
$('.test').removeClass('animationTestinBack');
},function(){
$('.test').removeClass('animationTestin');
$('.test').addClass('animationTestinBack');
});
So that when you hover on the wrapper you add the class that has the animation going down, and when you hover out, you remove that class and then add the animation going up.
Here is a fiddle:
https://jsfiddle.net/n1k5hkff/
Hope it helps,
Leo.

Categories