GTM - Exit Intent for scroll - Custom HTML - json

I'm looking for some help with coding a function for exit-intent on my website, but instead of classic function like someone moves a cursor away from website I'd like to implement a fast scroll up as a exit-intent. Is it even possible?
I found code like this but it doesn't work for me.
<script>
setTimeout(() => {
document.addEventListener("scroll", scrollSpeed);
}, 10000);
scrollSpeed = () => {
lastPosition = window.scrollY;
setTimeout(() => {
newPosition = window.scrollY;
}, 100);
currentSpeed = newPosition - lastPosition;
console.log(currentSpeed);
if (currentSpeed > 160) {
userengage('event.exit-intent-mobile');
document.removeEventListener("scroll", scrollSpeed);
}
};
</script>
I'm getting this error message:
Error at line 2, character 12: This language feature is only supported for ECMASCRIPT_2015 mode or better: arrow function.JavaScript compiler errorUser.com - Exit Intent Mobile
Error at line 5, character 15: This language feature is only supported for ECMASCRIPT_2015 mode or better: arrow function.JavaScript compiler errorUser.com - Exit Intent Mobile
Error at line 7, character 14: This language feature is only supported for ECMASCRIPT_2015 mode or better: arrow function.
Any ideas on how to implement that?

You are using arrow function in Google Tag Manager which is not allowed.
Need to change it into function(args){}
<script>
setTimeout(function(){
document.addEventListener("scroll", scrollSpeed);
}, 10000);
var scrollSpeed = function(){
lastPosition = window.scrollY;
setTimeout(function(){
newPosition = window.scrollY;
}, 100);
currentSpeed = newPosition - lastPosition;
console.log(currentSpeed);
if (currentSpeed > 160) {
userengage('event.exit-intent-mobile');
document.removeEventListener("scroll", scrollSpeed);
}
};
</script>
But when I test this code.
There will be error : userengage is not defined
Can you track back where this code coming from. You might miss some piece of it.

Related

variable insert to a blink function

I'm new to HTML and ajax. I'm trying to insert a ip list from flask , to the ajax and trigger the js function to blink.
but somehow I can't find a way to insert the ip variable (response[i]) into the function value column in a right way.
it is to trigger the blink on the required ip tab in html.
function ajaxForm(){
// var form= new FormData(document.getElementById("myform2"));
var data = {"name":"John Doe"}
$.ajax({
url:"{{ url_for('Submit_form') }}",
type:"post",
contentType:'application/json',
data:JSON.stringify(data),
dataType: "json",
processData:false,
// async: false
success:function(response){
// alert(response)
if (response == "success")
{alert("Success !!!" );}
else {
for(i in response)
{
BLINK(response[i]);
}
}
},
// #time out 也进入 error
error:function(e){
// alert(e.)
alert("Failed submit form trigger!!!!");
}
})
}
<script type="text/javascript">
function BLINK(){
var t = null;
function blink() {
var obj = $('input[id="IP"][value=response[i]]') . <---- here
obj.addClass("blink-class");
t = setTimeout(function () {
obj.removeClass("blink-class");
t = setTimeout(function () {
blink(IP);
}, 550);
}, 550);
}
blink(IP);
t = setTimeout(function () {
clearTimeout(t);
}, 5000);
}
At first, you shoul always provide the HTML code too :) because now we dont know if the issue is there.
So let's try to solve the problem blindly :)
if i see this correctly, you just go wrong on the element and make it even more complicated than it is since you're using jquery, because if u have an ID on your elem, check this out:
// change this:
var obj = $('input[id="IP"][value=response[i]]') . <---- here // .. is your problem :)
obj.addClass("blink-class");
// with the dot you add this obj, which is it self, on it self :) that cant work :)
// you can try:
var obj = $('input[value="' + response[i] + '"]') // with NO dot and no fixed ID!
obj.addClass("blink-class");
// or try this
var obj = $('#' + response[i]);
obj.addClass("blink-class");
// and put the IP into the ID attraktion of your input element.
Second Problem is you are using an undefined variable "ID":
blink(IP); // in your timeout function
but you didnt declare this var, so if i understand your code right then your response[i] should be the IP?
Your function should look like this:
function BLINK(IP) { // <-- here you need the ip as parameter for your: BLINK(response[i]) from ajax
var t = null;
function blink() {
var obj = $('#' + IP) // and put IP in the id from input
obj.addClass("blink-class")
t = setTimeout(function () {
obj.removeClass("blink-class");
t = setTimeout(function () {
blink(IP);
}, 550);
}, 550);
}
blink(IP);
t = setTimeout(function () {
clearTimeout(t);
}, 5000);
}
try this, if its doesnt work please provide complete html and your css code too, also we could need an eventually error message from console, you can see that by pressing F12 in FireFox or Chrome and then switch to the console tab, press F5 then to reload the page and see errors, post it too please.
Or try out my jsfiddle for you:
https://jsfiddle.net/AIQIA/tjg659sr/17/
You have to remove dots from your IP and put it as id in your elem you wants get to blink, further you need to remove the dots from the response[i] or in your php code before, easy use $ip = preg_replace('/\./','',$ip);
Or use this to use only the complete IP in your input value, then you dont need to remove dots:
https://jsfiddle.net/AIQIA/tjg659sr/21/
greetz Toxi

WebGL pink error in chrome

I am trying to write simple 'game' from this side using pixie.js.
I tried to run it via google chrome, however I am getting strange error:
What can I do to solve it?
EDIT
Error in index.js:225 stands for this:
isWebGLSupported: function ()
{
var contextOptions = { stencil: true };
try
{
if (!window.WebGLRenderingContext)
{
return false;
}
var canvas = document.createElement('canvas'),
gl = canvas.getContext('webgl', contextOptions) || canvas.getContext('experimental-webgl', contextOptions);
return !!(gl && gl.getContextAttributes().stencil);
}
catch (e)
{
return false;
}
},
It's not an error, as another user stated. It's the welcome message that appears by default on any page with the pixi.js library loaded.
If you want to hide that message, you can add this to your page:
<script>
PIXI.utils._saidHello = true;
</script>

dc.js : how to wait for complete barchart redraw?

Hy everybody,
I'm working with dc.js and I think it's a genious tool ! However I have a issue I can't solve.
I'm using a dc.barchart and I want to launch a function of mine after a click on one bar, but I need to wait the end of the redraw of the barchart.
Order :
- my barchart is displayed
- I click on one bar
-> the barchart is redraw
-> only after the complete redraw, my function is launched
Where can I put my callback ? I can't find the corresponding code.
_chart.onClick = function (d) {
var filter = _chart.keyAccessor()(d);
dc.events.trigger(function () {
_chart.filter(filter);
_chart.redrawGroup();
alert("here is not working");
});
};
(...)
dc.redrawAll = function(group) {
var charts = dc.chartRegistry.list(group);
for (var i = 0; i < charts.length; ++i) {
charts[i].redraw();
}
alert("neither here");
if(dc._renderlet !== null)
dc._renderlet(group);
};
dc.events.trigger = function(closure, delay) {
if (!delay){
closure();
alert("neither neither here");
return;
}
dc.events.current = closure;
setTimeout(function() {
if (closure == dc.events.current)
closure();
}, delay);
};
Any idea ? I'm completely blocked right now :(
Thanks a lot for your help,
vanessa
If _chart is the name of your chart and you want to execute some function named my_function after finishing drawing, use the following piece of code after the declaration of the chart itself:
_chart.on("postRedraw", my_function);
Hope this is what you were looking for.

Getting the list of voices in speechSynthesis (Web Speech API)

Following HTML shows empty array in console on first click:
<!DOCTYPE html>
<html>
<head>
<script>
function test(){
console.log(window.speechSynthesis.getVoices())
}
</script>
</head>
<body>
Test
</body>
</html>
In second click you will get the expected list.
If you add onload event to call this function (<body onload="test()">), then you can get correct result on first click. Note that the first call on onload still doesn't work properly. It returns empty on page load but works afterward.
Questions:
Since it might be a bug in beta version, I gave up on "Why" questions.
Now, the question is if you want to access window.speechSynthesis on page load:
What is the best hack for this issue?
How can you make sure it will load speechSynthesis, on page load?
Background and tests:
I was testing the new features in Web Speech API, then I got to this problem in my code:
<script type="text/javascript">
$(document).ready(function(){
// Browser support messages. (You might need Chrome 33.0 Beta)
if (!('speechSynthesis' in window)) {
alert("You don't have speechSynthesis");
}
var voices = window.speechSynthesis.getVoices();
console.log(voices) // []
$("#test").on('click', function(){
var voices = window.speechSynthesis.getVoices();
console.log(voices); // [SpeechSynthesisVoice, ...]
});
});
</script>
<a id="test" href="#">click here if 'ready()' didn't work</a>
My question was: why does window.speechSynthesis.getVoices() return empty array, after page is loaded and onready function is triggered? As you can see if you click on the link, same function returns an array of available voices of Chrome by onclick triger?
It seems Chrome loads window.speechSynthesis after the page load!
The problem is not in ready event. If I remove the line var voice=... from ready function, for first click it shows empty list in console. But the second click works fine.
It seems window.speechSynthesis needs more time to load after first call. You need to call it twice! But also, you need to wait and let it load before second call on window.speechSynthesis. For example, following code shows two empty arrays in console if you run it for first time:
// First speechSynthesis call
var voices = window.speechSynthesis.getVoices();
console.log(voices);
// Second speechSynthesis call
voices = window.speechSynthesis.getVoices();
console.log(voices);
According to Web Speech API Errata (E11 2013-10-17), the voice list is loaded async to the page. An onvoiceschanged event is fired when they are loaded.
voiceschanged: Fired when the contents of the SpeechSynthesisVoiceList, that the getVoices method will return, have changed. Examples include: server-side synthesis where the list is determined asynchronously, or when client-side voices are installed/uninstalled.
So, the trick is to set your voice from the callback for that event listener:
// wait on voices to be loaded before fetching list
window.speechSynthesis.onvoiceschanged = function() {
window.speechSynthesis.getVoices();
...
};
You can use a setInterval to wait until the voices are loaded before using them however you need and then clearing the setInterval:
var timer = setInterval(function() {
var voices = speechSynthesis.getVoices();
console.log(voices);
if (voices.length !== 0) {
var msg = new SpeechSynthesisUtterance(/*some string here*/);
msg.voice = voices[/*some number here to choose from array*/];
speechSynthesis.speak(msg);
clearInterval(timer);
}
}, 200);
$("#test").on('click', timer);
After studying the behavior on Google Chrome and Firefox, this is what can get all voices:
Since it involves something asynchronous, it might be best done with a promise:
const allVoicesObtained = new Promise(function(resolve, reject) {
let voices = window.speechSynthesis.getVoices();
if (voices.length !== 0) {
resolve(voices);
} else {
window.speechSynthesis.addEventListener("voiceschanged", function() {
voices = window.speechSynthesis.getVoices();
resolve(voices);
});
}
});
allVoicesObtained.then(voices => console.log("All voices:", voices));
Note:
When the event voiceschanged fires, we need to call .getVoices() again. The original array won't be populated with content.
On Google Chrome, we don't have to call getVoices() initially. We only need to listen on the event, and it will then happen. On Firefox, listening is not enough, you have to call getVoices() and then listen on the event voiceschanged, and set the array using getVoices() once you get notified.
Using a promise makes the code more clean. Everything related to getting voices are in this promise code. If you don't use a promise but instead put this code in your speech routine, it is quite messy.
You can write a voiceObtained promise to resolve to a voice you want, and then your function to say something can just do: voiceObtained.then(voice => { }) and inside that handler, call the window.speechSynthesis.speak() to speak something. Or you can even write a promise speechReady("hello world").then(speech => { window.speechSynthesis.speak(speech) }) to say something.
heres the answer
function synthVoice(text) {
const awaitVoices = new Promise(resolve=>
window.speechSynthesis.onvoiceschanged = resolve)
.then(()=> {
const synth = window.speechSynthesis;
var voices = synth.getVoices();
console.log(voices)
const utterance = new SpeechSynthesisUtterance();
utterance.voice = voices[3];
utterance.text = text;
synth.speak(utterance);
});
}
At first i used onvoiceschanged , but it kept firing even after the voices was loaded, so my goal was to avoid onvoiceschanged at all cost.
This is what i came up with. It seems to work so far, will update if it breaks.
loadVoicesWhenAvailable();
function loadVoicesWhenAvailable() {
voices = synth.getVoices();
if (voices.length !== 0) {
console.log("start loading voices");
LoadVoices();
}
else {
setTimeout(function () { loadVoicesWhenAvailable(); }, 10)
}
}
setInterval solution by Salman Oskooi was perfect
Please see https://jsfiddle.net/exrx8e1y/
function myFunction() {
dtlarea=document.getElementById("details");
//dtlarea.style.display="none";
dtltxt="";
var mytimer = setInterval(function() {
var voices = speechSynthesis.getVoices();
//console.log(voices);
if (voices.length !== 0) {
var msg = new SpeechSynthesisUtterance();
msg.rate = document.getElementById("rate").value; // 0.1 to 10
msg.pitch = document.getElementById("pitch").value; //0 to 2
msg.volume = document.getElementById("volume").value; // 0 to 1
msg.text = document.getElementById("sampletext").value;
msg.lang = document.getElementById("lang").value; //'hi-IN';
for(var i=0;i<voices.length;i++){
dtltxt+=voices[i].lang+' '+voices[i].name+'\n';
if(voices[i].lang==msg.lang) {
msg.voice = voices[i]; // Note: some voices don't support altering params
msg.voiceURI = voices[i].voiceURI;
// break;
}
}
msg.onend = function(e) {
console.log('Finished in ' + event.elapsedTime + ' seconds.');
dtlarea.value=dtltxt;
};
speechSynthesis.speak(msg);
clearInterval(mytimer);
}
}, 1000);
}
This works fine on Chrome for MAC, Linux(Ubuntu), Windows and Android
Android has non-standard en_GB wile others have en-GB as language code
Also you will see that same language(lang) has multiple names
On Mac Chrome you get en-GB Daniel besides en-GB Google UK English Female and n-GB Google UK English Male
en-GB Daniel (Mac and iOS)
en-GB Google UK English Female
en-GB Google UK English Male
en_GB English United Kingdom
hi-IN Google हिन्दी
hi-IN Lekha (Mac and iOS)
hi_IN Hindi India
Another way to ensure voices are loaded before you need them is to bind their loading state to a promise, and then dispatch your speech commands from a then:
const awaitVoices = new Promise(done => speechSynthesis.onvoiceschanged = done);
function listVoices() {
awaitVoices.then(()=> {
let voices = speechSynthesis.getVoices();
console.log(voices);
});
}
When you call listVoices, it will either wait for the voices to load first, or dispatch your operation on the next tick.
I used this code to load voices successfully:
<select id="voices"></select>
...
function loadVoices() {
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
}
function populateVoiceList() {
var allVoices = speechSynthesis.getVoices();
allVoices.forEach(function(voice, index) {
var option = $('<option>').val(index).html(voice.name).prop("selected", voice.default);
$('#voices').append(option);
});
if (allVoices.length > 0 && speechSynthesis.onvoiceschanged !== undefined) {
// unregister event listener (it is fired multiple times)
speechSynthesis.onvoiceschanged = null;
}
}
I found the 'onvoiceschanged' code from this article: https://hacks.mozilla.org/2016/01/firefox-and-the-web-speech-api/
Note: requires JQuery.
Works in Firefox/Safari and Chrome (and in Google Apps Script too - but only in the HTML).
async function speak(txt) {
await initVoices();
const u = new SpeechSynthesisUtterance(txt);
u.voice = speechSynthesis.getVoices()[3];
speechSynthesis.speak(u);
}
function initVoices() {
return new Promise(function (res, rej){
speechSynthesis.getVoices();
if (window.speechSynthesis.onvoiceschanged) {
res();
} else {
window.speechSynthesis.onvoiceschanged = () => res();
}
});
}
While the accepted answer works great but if you're using SPA and not loading full-page, on navigating between links, the voices will not be available.
This will run on a full-page load
window.speechSynthesis.onvoiceschanged
For SPA, it wouldn't run.
You can check if it's undefined, run it, or else, get it from the window object.
An example that works:
let voices = [];
if(window.speechSynthesis.onvoiceschanged == undefined){
window.speechSynthesis.onvoiceschanged = () => {
voices = window.speechSynthesis.getVoices();
}
}else{
voices = window.speechSynthesis.getVoices();
}
// console.log("voices", voices);
I had to do my own research for this to make sure I understood it properly, so just sharing (feel free to edit).
My goal is to:
Get a list of voices available on my device
Populate a select element with those voices (after a particular page loads)
Use easy to understand code
The basic functionality is demonstrated in MDN's official live demo of:
https://github.com/mdn/web-speech-api/tree/master/speak-easy-synthesis
but I wanted to understand it better.
To break the topic down...
SpeechSynthesis
The SpeechSynthesis interface of the Web Speech API is the controller
interface for the speech service; this can be used to retrieve
information about the synthesis voices available on the device, start
and pause speech, and other commands besides.
Source
onvoiceschanged
The onvoiceschanged property of the SpeechSynthesis interface
represents an event handler that will run when the list of
SpeechSynthesisVoice objects that would be returned by the
SpeechSynthesis.getVoices() method has changed (when the voiceschanged
event fires.)
Source
Example A
If my application merely has:
var synth = window.speechSynthesis;
console.log(synth);
console.log(synth.onvoiceschanged);
Chrome developer tools console will show:
Example B
If I change the code to:
var synth = window.speechSynthesis;
console.log("BEFORE");
console.log(synth);
console.log(synth.onvoiceschanged);
console.log("AFTER");
var voices = synth.getVoices();
console.log(voices);
console.log(synth);
console.log(synth.onvoiceschanged);
The before and after states are the same, and voices is an empty array.
Solution
Although i'm not confident implementing Promises, the following worked for me:
Defining the function
var synth = window.speechSynthesis;
// declare so that values are accessible globally
var voices = [];
function set_up_speech() {
return new Promise(function(resolve, reject) {
// get the voices
var voices = synth.getVoices();
// get reference to select element
var $select_topic_speaking_voice = $("#select_topic_speaking_voice");
// for each voice, generate select option html and append to select
for (var i = 0; i < voices.length; i++) {
var option = $("<option></option>");
var suffix = "";
// if it is the default voice, add suffix text
if (voices[i].default) {
suffix = " -- DEFAULT";
}
// create the option text
var option_text = voices[i].name + " (" + voices[i].lang + suffix + ")";
// add the option text
option.text(option_text);
// add option attributes
option.attr("data-lang", voices[i].lang);
option.attr("data-name", voices[i].name);
// append option to select element
$select_topic_speaking_voice.append(option);
}
// resolve the voices value
resolve(voices)
});
}
Calling the function
// in your handler, populate the select element
if (page_title === "something") {
set_up_speech()
}
Android Chrome - turn off data saver. It was helpfull for me.(Chrome 71.0.3578.99)
// wait until the voices load
window.speechSynthesis.onvoiceschanged = function() {
window.speechSynthesis.getVoices();
};
let voices = speechSynthesis.getVoices();
let gotVoices = false;
if (voices.length) {
resolve(voices, message);
} else {
speechSynthesis.onvoiceschanged = () => {
if (!gotVoices) {
voices = speechSynthesis.getVoices();
gotVoices = true;
if (voices.length) resolve(voices, message);
}
};
}
function resolve(voices, message) {
var synth = window.speechSynthesis;
let utter = new SpeechSynthesisUtterance();
utter.lang = 'en-US';
utter.voice = voices[65];
utter.text = message;
utter.volume = 100.0;
synth.speak(utter);
}
Works for Edge, Chrome and Safari - doesn't repeat the sentences.

Multiplayer HTML5, Node.js, Socket.IO

I trying create simple Multi-player with HTML5 Canvas, JavaScript(too using John Resig simple Inheritance library) and Node.js with Socket.IO.
My client code:
var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
var socket = new io.Socket('127.0.0.1', {port: 8080});
var player = null;
var UP = 'UP',
LEFT = 'LEFT',
DOWN = 'DOWN',
RIGHT = 'RIGHT';
socket.connect();
socket.on('connect', function() {socket.send();
console.log('Connected!');
player = new Player(50, 50);
});
socket.on('message', function(msg) {
if(msg == 'UP') {
player.moveUP();
} else if(msg == 'LEFT') {
player.moveLEFT();
} else if(msg == 'DOWN') {
player.moveDOWN();
} else if(msg == 'RIGHT') {
player.moveRIGHT();
} else {
}
});
socket.on('disconnect', function() {
console.log('Disconnected!');
});
var Player = Class.extend({
init : function(x, y) {
this.x = x;
this.y = y;
},
setX : function(x){
this.x = x;
},
getX : function(){
return this.x;
},
setY : function(y){
this.y = y;
},
getY : function(){
return this.y;
},
draw : function(){
context.clearRect(0, 0, 350, 150);
context.fillRect(this.x, this.y, 15, 15);
},
move : function() {
this.x += 1;
this.y += 1;
},
moveUP : function() {
this.y--;
},
moveLEFT : function() {
this.x--;
},
moveDOWN : function() {
this.y++;
},
moveRIGHT : function() {
this.x++;
}
});
function checkKeyCode(event) {
var keyCode;
if(event == null) {
keyCode = window.event.keyCode;
} else {
keyCode = event.keyCode;
}
switch(keyCode) {
case 38: // UP
player.moveUP();
socket.send(UP);
break;
case 37: // LEFT
player.moveLEFT();
socket.send(LEFT);
break;
case 40: //DOWN
player.moveDOWN();
socket.send(DOWN);
break;
case 39: // RIGHT
player.moveRIGHT();
socket.send(RIGHT);
break;
default:
break;
}
}
function update() {
player.draw();
}
var FPS = 30;
setInterval(function() {
update();
player.draw();
}, 1000/FPS);
function init() {
document.onkeydown = checkKeyCode;
}
init();
And server code:
var http = require('http'),
io = require('socket.io'),
buffer = new Array(),
server = http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<h1>Hello world</h1>');
});
server.listen(8080);
var socket = io.listen(server);
socket.on('connection', function(client){
client.on('message', function(message){
console.log(message);
client.broadcast(message);
})
client.on('disconnect', function(){
})
});
And when I run two client's I with first client can move second client Rect and with second client move first client rect and something like with third client can move first and second client rect's.
I have question how to create real Multi-Player? something like:
Open three client's and first client get rect1, second rect2 and last rect3. First client only can move rect1, client third can move only rect3.
Maybe anyone have idea? I search in Google but don't find answer.
Sorry for my English language.
First, check out http://www.google.com/events/io/2011/sessions/super-browser-2-turbo-hd-remix-introduction-to-html5-game-development.html
it explains how to use requestAnimationFrame among other things.
Second, the game state should exist on the server and be mirrored on the clients.
When a player clicks down, the client should only send a message. The server should then send a message to all the clients, including the client that took the action.
Each player should exist as an object on the server. When a player logs in they should be brought up to date about the status of each player already on the server.
modified client code: http://codr.cc/s/d0154536/js
modified server code: http://codr.cc/s/f96ce1d2/js
Glenn Fiedler's What every programmer needs to know about game networking -article is good read for anyone who wants get into game networking. It explains the basics in very high level so that it is adaptable for JS and Socket.io.
In case anyone stumbles across this question as I have just now, I wanted to add this link as an example.
I was following the same path as the op several months ago and read every article I could find on the authoritative server model (including the one referenced in the answer by #Epeli), and how to implement it with nodejs/socketio.
The result of my research manifested itself in the github project located at the link provided above (there is also a live demo). Hope this helps someone.
There is now an open-source multiplayer realtime javascript server (and client library) called Lance.gg, which provides, as you say,
a real multiplayer experience
It handles client-side prediction, step drift, bending, and basic physics.
Disclaimer: I am one of the contributors