Is there anyway to obtain the node list index offset, of a class element, that triggered a 'dragstart' event handler, from within that handler? I require this information so that I may set a data transfer object with that index for use later in a 'dragend' event handler.
<div id="div1">
<div draggable="true" class="thetiles">goo</div>
<div draggable="true" class="thetiles">hoo</div>
<div draggable="true" class="thetiles">zoo</div>
</div>
function registerSource() {
var matches = document.querySelectorAll('div.thetiles');
for (var i = 0; i < matches.length; i++) {
matches[i].addEventListener('dragstart', handleDragStart, false);
}
}
function handleDragStart(e) {
this.style.opacity = '0.3';
e.dataTransfer.effectAllowed = 'move';
/* need to get index of the class element that triggered this
for the following data transfer object set */
e.dataTransfer.setData('text/html', ????);
}
function registerSource() {
var matches = document.querySelectorAll('div.thetiles');
for (var i = 0; i < matches.length; i++) {
matches[i].addEventListener('dragstart', handleDragStart, false);
matches[i].addEventListener('dragstart', handleDragEnd, false);
}
}
var index
function handleDragStart(e) {
this.style.opacity = '0.3';
// Here is your index
index = Array.prototype.indexOf.call(e.target.parentNode.children, e.target)
e.dataTransfer.effectAllowed = 'move';
//e.dataTransfer.setData('text/html', ????);
}
function handleDragEnd(e) {
e.target.style.opacity = "";
console.log(index) // Quick confirmation
}
registerSource()
jsfiddle
Is this what you need?
Related
I am trying to make a basic search function. if input.value does exist in array alert message, if not, push it to array ans show in HTML. I think I have already most of work done, but there is somewhere a mistake. Thank you in advance for your help guys .)
<div id="main">
<input id="inputForMyDict">
<button id="ButtonForInputSave" onclick="buttonSave()">Speichern</button>
<p id="demo"></p>
</div>
<script>
var myDict = [];
var buttonSave = function() {
for (var i = 0; i < myDict.length; i++) {
if (document.getElementById("inputForMyDict").value = myDict[i]) {
alert("your input is already in your list");
} else {
myDict.push(document.getElementById("inputForMyDict").value);
document.getElementById("demo").innerHTML = myDict;
}
}
}
In javascript, there are 2 ways to do a comparison.
Strict Equality Operator === strict equality operator.
If you are not sure about the exact datatype for the values being compared, then you can use the == for comparison.
The line document.getElementById("inputForMyDict").value = myDict[i] needs comparison operator and not the assignment operator (=). So you need to replace the = with either == or ===.
so your javascript code should look like
var buttonSave = function() {
for (var i = 0; i < myDict.length; i++) {
if (document.getElementById("inputForMyDict").value == myDict[i]) {
// If you know exact data type, then use the below line instead and comment the above line if (document.getElementById("inputForMyDict").value === myDict[i]) {
alert("your input is already in your list");
} else {
myDict.push(document.getElementById("inputForMyDict").value);
document.getElementById("demo").innerHTML = myDict;
}
}
}
Update1: Based on the clarification, provided by comments, you don't need to have a for loop to check for existence of element in array. Javascript provides a convenient way by indexOf method on an array. indexOf method check for the existence of an element in an array and returns the index of the element in the Array. However, if the element is not found then it returns -1.
Full code below which should work.
<!DOCTYPE html>
<html>
<body>
<div id="main">
<input id="inputForMyDict">
<button id="ButtonForInputSave" onclick="buttonSave()">Speichern</button>
<p id="demo"></p>
</div>
<script>
var myDict = [];
var buttonSave = function() {
//for (var i = 0; i < myDict.length; i++) {
var valueInTextbox = document.getElementById("inputForMyDict").value;
if(myDict.indexOf(valueInTextbox) > -1){
alert("your input is already in your list");
} else {
myDict.push(valueInTextbox);
document.getElementById("demo").innerHTML = myDict;
}
}
//}
</script>
</body>
</html>
I am trying to make a google script web app that takes input from an HTML form and passes the input to a script. Right now, the function is failing because document.getelementbyId('text') returns null instead of the actual form value. How can I fix this?
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
// Prevent forms from submitting.
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener('load', preventFormSubmit);
function handleFormSubmit() {
var formObject = document.getElementById('text');
google.script.run.withSuccessHandler(setTable).getSportData(formObject);
console.log(formObject);
}
function setTable(data) {
var div = document.getElementById('output');
div.innerHTML = createTable(data);
}
/**
* Adds an html table
*/
function createTable(tableData) {
var table = document.createElement('table');
var tableBody = document.createElement('tbody');
tableData.forEach(function(rowData) {
var row = document.createElement('tr');
rowData.forEach(function(cellData) {
var cell = document.createElement('td');
cell.appendChild(document.createTextNode(cellData));
row.appendChild(cell);
});
tableBody.appendChild(row);
});
table.appendChild(tableBody);
document.body.appendChild(table);
}
</script>
</head>
<body>
<form id="myForm" onsubmit="handleFormSubmit()">
<input name="text" type="text" />
<input type="submit" value="Submit" />
</form>
<div id="output"></div>
</body>
</html>
Code.gs
//Initalization of global variables for use by the script's custom functions
var ss = SpreadsheetApp.openById("spreadsheetID");
var sheet = ss.getSheetByName("Sheet1");
var sportsFromSheet = sheet.getRange("D4:D12");
var namesFromSheet = sheet.getRange("B4:B12").getValues();
var timesFromSheet = sheet.getRange("A4:A12").getValues();
var NAMES = [];
var TIMES = [];
/**
* Handles HTTP GET requests to the published web app.
* #return {HtmlOutput} The HTML page to be served.
*/
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
/**
* Gets both names and Times of checked-in people from the spreadsheet from the private function getOutput.
* #return {HtmlOutput} A 2D array containing the names and times.
*/
function getSportData(formObject) {
getNamesInSport(formObject);
getTimesInSport(formObject);
var OUTPUT = [
[NAMES],
[TIMES]
];
return OUTPUT;
}
//Puts the names of every person from an inputted sport into an array.
function getNamesInSport(input) {
var data = sportsFromSheet.getValues();
for (var i = 0; i < data.length; i++) {
if(data[i] == input){
NAMES.push(namesFromSheet[i][0]);
}
}
}
//Puts the times of every person from an inputted sport into an array.
function getTimesInSport(input){
var data = sportsFromSheet.getValues();
for (var i = 0; i < data.length; i ++) {
if(data[i] == input){
TIMES.push(timesFromSheet[i][0]);
}
}
}
Duplicate of Why does jQuery or a DOM method such as getElementById not find the element?.
You appear to have answered your own question.
document.getElementById('text') returns null because...
You don't have an element with an id="text".
document.getElementById will return null
if an element with the specified ID is not in the document. (Mozilla Developer Network)
The solution, is <input type="text" name="text" id="text">
This may be a naive question, sorry for that, but I'm trying to sort out a potential concurrency issue. I have a registration procedure which begins with the user selecting their category from a drop down menu. That triggers a query to a particular page in a google sheet where it retrieves an available ID number that is displayed to the user. There are a couple steps required before the final submit button is pressed. This (I think) creates a chance for more than one person to retrieve the same ID. I do use google's lockservice but on the function which writes the form information to my spreadsheet (based on a script of Martin Hawksley). If it was possible to determine how many people were currently viewing the registration page I could use that value in the query with an if statement such that a different row number is retrieved. This would eliminate the chance of duplicates.
Does that sound reasonable? Perhaps there is a much better way.
Any advice would be most appreciated.
If it was possible to determine how many people were currently viewing
the registration page
If you don't want to use Google Analytics. Here is a simple example of how you can poll with a client to maintain a session, and count how many users are active.
NOTE: I threw this together, it could be refactored a bit to be prettier, but it should get the gist of it across
Working Example Open this a couple times, you will see your session IDs in each and a count. Sessions expire after 60 seconds of no activity, and auto-end if you close the page.
Project file structure:
Code.gs
index.html
javascript.html
Apps Script
var sessionTimeout = 60; //60 seconds
//Triggered when the page is navigated to, serves up HTML
function doGet(){
var template = HtmlService.createTemplateFromFile('index');
template.userID = NewSession();
return template.evaluate()
.setTitle('Active Users')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
/*================ Polling ================*/
//Client calls this function to poll, updates cache, returns active users
function ClientPoll(id){
var scriptCache = CacheService.getScriptCache();
UpdateScriptCache(id, 0, scriptCache, true);
var activeIDs = GetActiveIDs(scriptCache);
return activeIDs;
}
function EndSession(id){
var scriptCache = CacheService.getScriptCache();
scriptCache.remove(id);
var activeIDs = GetActiveIDs(scriptCache);
activeIDs.splice(activeIDs.indexOf(id), 1);
UpdateScriptCache('ActiveIDs', activeIDs, scriptCache, false);
}
//Server calls every minute to check for inactive sessions
function CheckForInactiveSessions(){
var scriptCache = CacheService.getScriptCache();
var activeIDs = GetActiveIDs(scriptCache);
var allSessions = scriptCache.getAll(activeIDs);
if(Object.keys(allSessions).length > 0){
var keys = Object.keys(allSessions);
var newActiveIDs = [];
for(var i = 0; i < keys.length; i++){
newActiveIDs.push(keys[i]);
}
Logger.log(keys.length);
UpdateScriptCache('ActiveIDs', newActiveIDs, scriptCache, false);
}
}
/*================ Session Creation & Cache ================*/
//Handles setting up a new session, called when page is opened
function NewSession(){
var id = GenerateUID();
AddNewActiveID(id);
return id;
}
//Gets a list of all active IDs
function GetActiveIDs(scriptCache){
if(!scriptCache){
scriptCache = CacheService.getScriptCache();
}
var active = scriptCache.get('ActiveIDs');
if(active !== null){
return JSON.parse(active);
}
return [];
}
//Adds a new ID to the cache
function AddNewActiveID(id){
var scriptCache = CacheService.getScriptCache();
var activeIDs = JSON.parse(scriptCache.get('ActiveIDs'));
if(activeIDs == null){
activeIDs = [];
}
activeIDs.push(id);
//Update the Active ID List
UpdateScriptCache('ActiveIDs', activeIDs, scriptCache, false);
//Add new ID to cache
UpdateScriptCache(id, 0, scriptCache, true);
}
//Handles updating the Active IDs cache and prevents race conditions or collisions
function UpdateScriptCache(key, data, cache, timeout){
var lock = LockService.getScriptLock();
lock.waitLock(15000);
if(timeout){
cache.put(key, JSON.stringify(data), sessionTimeout);
} else {
cache.put(key, JSON.stringify(data), 21600)
}
lock.releaseLock();
}
/*================ ID Generation ================*/
//Handles generating and returning a new ID
function GenerateUID(){
var generator = new IDGenerator();
var id = generator.generate();
return id;
}
//Generates a random(ish) ID;
function IDGenerator() {
this.length = 10;
this.timestamp = new Date().getTime();
var getRandomInt = function( min, max ) {
return Math.floor( Math.random() * ( max - min + 1 ) ) + min;
}
this.generate = function(){
var timestamp = this.timestamp.toString();
var parts = timestamp.split('').reverse();
var id = '';
for(var i = 0; i < this.length; i++){
var index = getRandomInt(0, parts.length - 1);
id += parts[index];
}
return id;
}
}
JavaScript:
<script>
//Initilization
$(function(){
//Set the users ID in HTML
$('#userID').text(userID);
//Setup handler to end the session before the page closes
$(window).bind('beforeunload', function(){
EndSession();
});
//Start the timer
var deadline = new Date(Date.parse(new Date()) + 5000);
initializeTimer('pollingIn', deadline);
});
//Polls the server to update session and get active users
function PollServer(){
console.log('Polling server');
google.script.run.withSuccessHandler(UpdateActiveUsers).ClientPoll(userID);
var deadline = new Date(Date.parse(new Date()) + 5000);
initializeTimer('pollingIn', deadline);
}
//Ends the session right before the page closes
function EndSession(){
google.script.run.withSuccessHandler().EndSession(userID);
}
//Updates the active users div
function UpdateActiveUsers(users){
console.log(users)
var userText = '';
for(var i = 0; i < users.length; i++){
if(i == 0){
userText += users[i];
continue;
}
userText += ', ' + users[i];
}
$('#activeUsersCount').text(users.length);
$('#activeUsers').text(userText);
}
//Initilizes the timer
function initializeTimer(id, endtime) {
var timer = $('#'+id);
function updateTimer() {
var time = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((time / 1000) % 60);
timer.text(seconds);
if (time <= 0) {
clearInterval(timeInterval);
PollServer();
}
}
updateTimer();
var timeInterval = setInterval(updateTimer, 1000);
}
</script>
HTML:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link href="https://ssl.gstatic.com/docs/script/css/add-ons1.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
</head>
<body>
<div id="mainForm">
<h1>Active Users</h1>
<div class="box">
Active Users Count:
<span id="activeUsersCount">0</span>
</div>
<div class="box">
Active Users:
<span id="activeUsers"></span>
</div>
<div class="box">
Polling in:
<span id="pollingIn"></span>
</div>
<div class="box">
You Are:
<span id="userID"></span>
</div>
</div>
<?!= HtmlService.createHtmlOutputFromFile('javascript').getContent(); ?>
<script>
var userID = <?= userID ?>;
</script>
</body>
</html>
<style>
.box {
display: block;
padding: 0.5em;
}
body {
padding: 1em;
}
</style>
could someone please help me to find out why this won't work on safari browser? It seems to work really well in all other browsers apart from Safari. I really could not work it out.
Any help will be most appreciated.
function loadPlayer()
{
var audioPlayer = new Audio();
audioPlayer.controls="";
audioPlayer.setAttribute("data-index", -1); //set default index to -1.
audioPlayer.addEventListener('ended',nextSong,false);
audioPlayer.addEventListener('error',errorFallback,true);
document.getElementById("player").appendChild(audioPlayer);
}
function nextSong(index, e)
{
var next;
var audioPlayer = document.getElementsByTagName('audio')[0];
//check for index. If so load from index. If not, index is defined auto iterate to next value.
if (index >= 0)
{
next = index;
}
else
{
next = parseInt(audioPlayer.getAttribute("data-index"))+1;
next >= urls.length ? next = 0 : null;
}
audioPlayer.src=urls[next][0]; //load the url.
audioPlayer.setAttribute("data-index", next);
//disable the player.
var audioPlayerControls = document.getElementById("playerControls");
audioPlayer.removeEventListener('canplay',enablePlayerControls,false);
audioPlayerControls.setAttribute("disabled", true);
audioPlayer.addEventListener('canplay',enablePlayerControls,false);
audioPlayer.load();
//show the image:
var image = document.getElementById("playerList").querySelectorAll("a")[next].querySelector("img").cloneNode();
image.style.width = "30px";
if(audioPlayerControls.querySelector("img"))
{
audioPlayerControls.replaceChild(image, audioPlayerControls.querySelector("img"));
}
else
{
audioPlayerControls.insertBefore(image, audioPlayerControls.querySelector("a"));
}
}
function enablePlayerControls()
{
//File has loaded, so we can start playing the audio.
//Enable the player options.
var audioPlayer = document.getElementsByTagName('audio')[0];
audioPlayer.removeEventListener('canplay',enablePlayerControls,false);
document.getElementById("playerControls").removeAttribute("disabled");
audioPlayer.play();
}
function errorFallback() {
nextSong();
}
function playPause()
{
var audioPlayer = document.getElementsByTagName('audio')[0];
if (audioPlayer.paused)
{
audioPlayer.play();
} else
{
audioPlayer.pause();
}
}
function pickSong(e)
{
//we want the correct target. Select it via the event (e).
var target;
//pickSong does the selecting:
if (e && e.target && e.target.tagName && e.target.tagName.toLowerCase() == "img")
{
//The event target = the img element.
target = e.target.parentElement;
}
else
{
//the event target is the a element
target = e.target;
}
var index = target.getAttribute("data-index"); //get the song index stored in the data-index attribute.
nextSong(index);
}
var urls = new Array();
urls[0] = ['http://mp3lg4.tdf-cdn.com/9079/jet_143844.mp3', 'http://radio-maghreb.net/radio/radio almazighia.png'];
urls[1] = ['http://mp3lg4.tdf-cdn.com/9077/jet_143651.mp3', "http://radio-maghreb.net/radio/alwatania.png"];
urls[2] = ['http://mp3lg4.tdf-cdn.com/9080/jet_144136.mp3', "http://radio-maghreb.net/radio/inter.jpg"];
function startAudioPlayer()
{
loadPlayer();
for (var i = 0; i < urls.length; ++i)
{
//this for loop runs through all urls and appends them to the player list. This smooths the adding off new items. You only have
//to declare them in the array, the script does the rest.
var link = document.createElement("a");
link.href = "javascript: void(0)";
link.addEventListener("click", pickSong, false);
link.setAttribute("data-index", i);
link.img = document.createElement("img");
link.img.src = urls[i][1];
link.appendChild(link.img);
document.getElementById("playerList").appendChild(link);
}
}
//Event that starts the audio player.
window.addEventListener("load", startAudioPlayer, false);
#playerControls[disabled=true] > a{
color: #c3c3c3;
}
<span id="playerControls" disabled="true">
Play
Stop
</span>
Next Track
<!-- player ends -->
<br>
<br>
<!-- img links start -->
<div id="playerList">
</div>
I wanted reload a core-list element to show new data, but it´s not refreshing.
I re-call the JS function thats generate the data but doesn t work... and reload like a 'normal' div doesn t work either! The list only shows the new data if i reload the entire page...
function values(sender, textomsg, datacriacao, senderfoto){
var sender2 = sender.split(",");
var textomsg2 = textomsg.split(",");
var datacriacao2 = datacriacao.split(",");
var senderfoto2 = senderfoto.split(",");
var namegen = {
generateString: function (inLength) {
var s = '';
for (var i = 0; i < inLength; i++) {
s += String.fromCharCode(Math.floor(Math.random() * 26) + 97);
}
return s;
},
generateName: function (inMin, inMax) {
return this.generateString(Math.floor(Math.random() * (inMax - inMin + 1) + inMin));
}
};
Polymer('list-test', {
count: sender.length,
ready: function () {
this.data = this.generateData();
},
generateData: function () {
var names = [], data = [];
for (var i = 0; i < this.count; i++) {
names.push(namegen.generateName(4, 8));
}
names.sort();
for (var i = 0; i < this.count; i++) {
data.push({
index: i,
sender: sender2[i],
textomsg: textomsg2[i],
datacriacao: datacriacao2[i],
senderfoto: senderfoto2[i]
});
}
return data;
},
tapAction: function (e) {
console.log('tap', e);
}
});
}
<%----%>
<template id="templateConversas" runat="server">
<div id="item" class="item {{ {selected: selected} | tokenList }}" ><%--onClick="conversa('{{name}}');"--%>
<div class="message" style="background-image: url({{senderfoto}});">
<span class="from"><br/>{{sender}}</span>
<span class="timestamp">{{datacriacao}}</span>
<div class="subject"><br/>{{textomsg}} </div><%--------Infinite List. {{index}}--%>
<%--<div class="body"><br/>Mensagem de teste...........</div>--%>
</div>
</div>
</template>
The problem is also reload the 'list-test'. if i call the js function after the list is loaded it doesn't apply the new data...
Your code isn't complete so it is hard to understand but I think that the problem is that you don't assign the result of the generateData() function to the template's model. Try following script for your component
Polymer('list-test', {
created: function () {
this.data = [];
},
refresh: function () {
this.data = this.generateData();
},
generateData: function () {
// your original code here
}
});
Now the list content should be updated with newly generated data when you call refresh() of the list-test element. To fill the list when element is created add
ready: function () {
this.refresh();
},