I am trying to compare two foreach loop data and display relevant data in a div. As in the following script its comparing data for only first row.
More detail: I want to track a user arrival between two time ranges of the current date, I am fetching user name and,city and arrival time from one table. And expected time ranges of cities from other table as you can see in the response data, When Comparing user arrival time between two time ranges of the city it is comparing for only first row (user) ignoring other rows.
I want to display a button when comparing dates with relevant city of user. If a user arrival date is between city travel start time and end time then the button should be displayed with arrived label else with on the way label.
response = {
"result1": [{
"Name": "Mike",
"city": "London",
"arival_time": "2020-06-06 18:31:57"
}, {
"Name": "milan",
"city": "newyork",
"arival_time": "2020-06-06 20:21:44"
}],
"result2": [{
"city": "london",
"start_time": "08:00:00",
"end_time": "12:00:00"
}, {
"city": "newyork",
"start_time": "06:00:00",
"end_time": "12:00:00"
}]
}
response.result1.forEach(function(element) {
var city = element.city;
response.result2.forEach(function(e) {
const start = e.start_time;
const end = e.end_time;
const check = element.arival_time;
const [date, time] = check.split(" ");
const startDate = `${date} ${start}`;
const endDate = `${date} ${end}`;
const from = new Date(startDate).getTime();
const to = new Date(endDate).getTime();
const target = new Date(check).getTime();
const array = e.city;
const isInArray = array.includes(city);
if (isInArray == true) {
if (target >= from && target <= to) {
$('.action').append('<button type="button" class="med_action pull-right btn btn-success"> Arrived</button>');
} else {
$('.action').append('<button type="button" class="med_action pull-right btn btn-warning"> on the way</button>');
}
}
});
var html = '<div class="details">' +
'<h3><i class="fa fa-exclamation-circle"></i><span> ' + element.Name + '</span></h3>' +
'<div class="form-inline">' +
'<label> city : </label><span> ' + element.city + '</span>' +
'</div>' +
'</div>' +
'<div class="action"></div>' +
'</div>';
$('#container').append(html);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container"></div>
I see two problems with your code:
result1[0].city is 'London' (uppercase) but result2[0].city = 'london' (lowercase) so you won't see any button for Mike.
In the inner loop, the calls to $('.action').append(...) don't have any effect because <div class="action"> doesn't exist until the inner loop has finished.
Here is updated code that buffers the buttons and inserts them into <div class="action">:
response.result1.forEach(function(element) {
var city = element.city;
var buttons = ''; // buffer for buttons
response.result2.forEach(function(e) {
const start = e.start_time;
const end = e.end_time;
const check = element.arival_time;
const [date, time] = check.split(" ");
const startDate = `${date} ${start}`;
const endDate = `${date} ${end}`;
const from = new Date(startDate).getTime();
const to = new Date(endDate).getTime();
const target = new Date(check).getTime();
const array = e.city;
const isInArray = array.includes(city);
if (isInArray == true) {
if (target >= from && target <= to) {
buttons += ('<button type="button" class="med_action pull-right btn btn-success"> Arrived</button>'); // append to buttons var
} else {
buttons += ('<button type="button" class="med_action pull-right btn btn-warning"> on the way</button>'); // append to buttons var
}
}
});
var html = '<div class="details">' +
'<h3><i class="fa fa-exclamation-circle"></i><span> ' + element.Name + '</span></h3>' +
'<div class="form-inline">' +
'<label> city : </label><span> ' + element.city + '</span>' +
'</div>' +
'</div>' +
'<div class="action">' + buttons + '</div>' +
'</div>'; // Insert buttons
$('#container').append(html);
});
See my comments on the lines containing // for explanations of my changes.
Related
I am trying to get a value from a dropdown list. I have the dropdown list and I have the value that I want but I don't know how to link them to each other. So the value of the category should go in the dropdown list and then the image value from that string should be the outcome.
This is the JSON file array called ill.json
...
[{"id":"7","category":"Lente collectie 2021","image":"Teddy_bears_10.png"},{"id":"11","category":"Lente collectie 2021","image":"Individual_floral_elements_01.png"}
...
The category value goes into the dropdown list and then the outcome should be the image value:
This is my dropdown
...
const req = new XMLHttpRequest();
req.open('GET', 'ill.json', true);
req.send();
req.onload = function() {
const json = JSON.parse(req.responseText);
let dropdown = "";
let html = "";
//FILLING DROPDOWN WITH CATEGORYs
var result = json.reduce(function (r, a) {
r[a.category] = r[a.category] || [];
r[a.category].push(a);
return r;
}, Object.create(null));
let keys = Object.keys(result)
keys.forEach((key) => {
dropdown += "<select id='select'>"
dropdown += "<option value='" + key + "'>"
dropdown += key
dropdown += "</option>"
dropdown += "</select"
})
document.getElementsByClassName('dropdown')[0].innerHTML = dropdown;
...
And this is how I got the images
...
//get all images
json.forEach(function(val) {
html += "<div class='illustratie-item'>";
html += "<img class='dt-filelist-image' src='" + val.image + "'/>"
html += "</div><br>";
});
document.getElementsByClassName('illustratie-wrapper')[0].innerHTML = html;
...
If I get that right, it should be as easy as this:
var categorySelect = document.querySelector('.dropdown');
categorySelect.addEventListener('change', function(evt) {
var item = json.find(function(item) {
return item.id === evt.target.value;
});
console.log(item.image); // there's your image
});
Check the below snippet.
var images = [{"id":"7","category":"Lente collectie 2020","image":"Teddy_bears_10.png"},{"id":"11","category":"Lente collectie 2021","image":"Individual_floral_elements_01.png"}];
var dropdown = '';
dropdown += '<select id="select">';
Object.keys(images).forEach(function(key) {
dropdown += '<option value="' + images[key].id + '">';
dropdown += images[key].category;
dropdown += '</option>';
});
dropdown += '</select>';
document.getElementsByClassName('dropdown')[0].innerHTML = dropdown;
var categorySelect = document.querySelector('#select');
categorySelect.addEventListener('change', function(evt) {
var item = images.find(function(item) {
return item.id === evt.target.value;
});
console.log( item.image );
});
<div class="dropdown"></div>
I am having a list which is nothing but country flag, country name and country code which actually i derived from JSON
and i had written for loop to render the html elements like this
data =
[
{
"name": "INDIA ",
"code": "93",
"url": 'https://www.countryflags.io/in/flat/64.png'
}, {
"name": "JAPAN ",
"code": "355",
"url": 'https://www.countryflags.io/jp/flat/64.png'
}]
for (var i = 0; i < data.length; i++) {
var countryName = data[i].name;
var countrtDialCode = data[i].code;
var countryUrl = data[i].url;
var badge = document.createElement('div');
badge.className = 'badge';
badge.innerHTML =
'<div id="listSection">'+
'<div style="display:flex">'+
'<div id="flagSection">'+'<img style="height:10px;width:20px;margin-top:4px;" src='+countryUrl+'>'+'</div>'+' '+
'<div id="nameSection">' + countryName + '</div>' +' '+
'<div id="codeSection">' + countrtDialCode + '</div>'
+'</div>'+
'</div>'
document.getElementById('countries-list').appendChild(badge);
}
also i have a divs section
<div id="inputSection"> </div>
<div id="countries-list">
</div>
and i have done like when you click on input section the list will come and i can choose from the list and i need ONLY the flag should be shown
<script type="text/javascript">
$(document).ready(function(){
$('#countries-list').addClass('hideSection').removeClass('showSection')
});
$('#inputSection').click(function(){
$('#countries-list').addClass('showSection').removeClass('hideSection')
})
</script>
so when i click india JSON from list , i should display indian flag in inputSection again if i click input section list should come and again if i choose NEPAL, indian flag should be replaced with NEPAL flag.
Have 2 problem.First one i am unable to write click function in INNERHTML to identify which country clicked and second how to retrieve the flag section and show it in inputSection.
Any fiddle will be highly helpful and thankful
If all you need is a clone of the flag section in the input section, then this is all you need:
$('.listSection').on('click', function() {
$('#inputSection').html( $('.flagSection', this).clone() );
});
However, you have to convert every occurrence of id in the HTML in your JS to class, as in the working demo below. Id attribute values should be unique.
$(function() {
const data = [{
"name": "INDIA ",
"code": "93",
"url": 'https://www.countryflags.io/in/flat/64.png'
}, {
"name": "JAPAN ",
"code": "355",
"url": 'https://www.countryflags.io/jp/flat/64.png'
}];
for (var i = 0; i < data.length; i++) {
var countryName = data[i].name;
var countrtDialCode = data[i].code;
var countryUrl = data[i].url;
var badge = document.createElement('div');
badge.className = 'badge';
badge.innerHTML =
'<div class="listSection">'+
'<div style="display:flex">'+
'<div class="flagSection">'+'<img style="height:10px;width:20px;margin-top:4px;" src='+countryUrl+'>'+'</div>'+' '+
'<div class="nameSection">' + countryName + '</div>' +' '+
'<div class="codeSection">' + countrtDialCode + '</div>'
+'</div>'+
'</div>'
document.getElementById('countries-list').appendChild(badge);
}
$('.listSection').on('click', function() {
console.log( {name: $('.nameSection',this).text(), code: $('.codeSection', this).text()} );
$('#inputSection').html( $('.flagSection', this).clone() );
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="inputSection"> </div>
<div id="countries-list">
</div>
NOTE
Since there's not mention in the documentation of .html( jQueryObject ) even thought it works in the above demo, I'll provide an alternative that uses .empty() and .append() methods:
$('#inputSection').empty().append( $('.flagSection', this).clone() );
I got the data stored on my localStorage and display them in table format with each row having a button. What I want to do now is, when the button is clicked I want it to change the background color to another color and when the page refreshes the button persists its color state.
Here is my code
// here i will be the data in form of table
// my algorithm comes here
// this function will get data from the localstorage
const get_todos = ()=>{
let todos = new Array();
let todos_str = localStorage.getItem("todo");
if(todos_str !== null){
todos = JSON.parse(todos_str);
}
return todos;
}
//this function will show the data in the localstorage in table format
const show = ()=>{
let todos = get_todos();
let text = "";
for(let i = 0; i < todos.length; i++){
let allData = todos[i];
let eventName = allData.Eventname;
let location = allData.Location;
let date = allData.Date;
text += "<tr>";
text += "<td>" + eventName + "</td>";
text += "<td>" + location + "</td>";
text += "<td>" + date + "</td>";
text += "<td>" + "<button class='buttons' type='button'>Pending</button>" + "</td>";
text += "<td>" + "<i id='remove' class='fas fa-trash-alt btndelete'></i>" + "</td></tr>";
}
//the data gotten from the localstorage will be here
let table = document.querySelector("#table > tbody");
table.innerHTML = text;
//this is where the button background color will change
window.addEventListener("load", ()=>{
let thead = document.querySelector("#thead");
let buttons = Array.from(document.querySelectorAll(".buttons"));
thead.addEventListener("click", (e)=>{
if(e.target.className === "buttons"){
let index = buttons.indexOf(e.target);
changeBackground(e, index);
}
});
buttons.forEach(btn, index =>{
btn.className = sessionStorage.getItem('background${index}') || 'buttons';
});
});
const changeBackground = (e, index)=>{
e.target.className += "change";
sessionStorage.setItem(background${index}, e.target.className);
}
}
window.addEventListener("DOMContentLoaded", ()=>{
show();
});
There is few errors in your code:
First:
btn.className = sessionStorage.getItem('background${index}') || 'buttons';
Should be:
btn.className = sessionStorage.getItem(`background${index}`) || 'buttons';
because you are create a string using Template literals (Template strings)
Second:
e.target.className += "change";
Should be:
e.target.className += " change";
You have to add space when concatenate strings, or else in your case it will not provide the intended behavior, since your code will add change class name to the previous class as one word.
Third:
sessionStorage.setItem(background${index}, e.target.className);
Should be:
sessionStorage.setItem(`background${index}`, e.target.className);
In your question you are talking about localStorage but you are
using sessionStorage, Still not sure if this what you want, so if you want it to be localStorage just replace sessionStorage with localStorage
// here i will be the data in form of table
// my algorithm comes here
// this function will get data from the localstorage
const get_todos = ()=>{
let todos = new Array();
let todos_str = localStorage.getItem("todo");
if(todos_str !== null){
todos = JSON.parse(todos_str);
}
return todos;
}
//this function will show the data in the localstorage in table format
const show = ()=>{
let todos = get_todos();
let text = "";
for(let i = 0; i < todos.length; i++){
let allData = todos[i];
let eventName = allData.Eventname;
let location = allData.Location;
let date = allData.Date;
text += "<tr>";
text += "<td>" + eventName + "</td>";
text += "<td>" + location + "</td>";
text += "<td>" + date + "</td>";
text += "<td>" + "<button class='buttons' type='button'>Pending</button>" + "</td>";
text += "<td>" + "<i id='remove' class='fas fa-trash-alt btndelete'></i>" + "</td></tr>";
}
//the data gotten from the localstorage will be here
let table = document.querySelector("#table > tbody");
table.innerHTML = text;
//this is where the button background color will change
window.addEventListener("load", ()=>{
let thead = document.querySelector("#thead");
let buttons = Array.from(document.querySelectorAll(".buttons"));
thead.addEventListener("click", (e)=>{
if(e.target.className === "buttons"){
let index = buttons.indexOf(e.target);
changeBackground(e, index);
}
});
buttons.forEach(btn, index =>{
btn.className = localStorage.getItem(`background${index}`) || 'buttons';
});
});
const changeBackground = (e, index)=>{
e.target.className += " change";
localStorage.setItem(`background${index}`, e.target.className);
}
}
window.addEventListener("DOMContentLoaded", ()=>{
show();
});
I'm trying to take a range of cells and shift them all to the right by one cell. I'd like this to occur once per weekly automatically. I'm aware in the Script editor I can create a trigger for it to schedule weekly, but I'm not sure how to code it.
If someone can help provide a code that allows me to indicate which SHEET and CELL RANGE to shift to the right by one cell, I would appreciate it.
Basically, what I'm trying to accomplish is tracking data for a number of weeks. Each week the sheet will be updated, and I would like the older data to shift right one, basically indicating that the data has gotten a week older.
In addition, I'm only trying to keep data for like 6 weeks, so the data isn't ongoing forever.
A bit of an example: Column A = current week (updated manually).
Columns B-F = previous weeks (1-5 weeks ago).
Once a week, the data in columns A-E should be shifted right 1 to preserve the data. After the shift, data is manually updated in Column A to represent the current week. This would then result in showing data for the current week and 5 additional weeks... totaling 6 weeks of data.
I'd be interested if there is a way to just shift columns while excluding the header row, instead of a range, if possible.
Could try something like this?
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// This inserts 1 columns before the first column
sheet.insertColumnsBefore(1, 1);
// labels the weeks static
ss.getRange('A1').setFontWeight("bold").setValue("Week1").setBackground("#BBBBBB");
ss.getRange('B1').setFontWeight("bold").setValue("Week2").setBackground("#BBBBBB");
ss.getRange('C1').setFontWeight("bold").setValue("Week3").setBackground("#BBBBBB");
ss.getRange('D1').setFontWeight("bold").setValue("Week4").setBackground("#BBBBBB");
ss.getRange('E1').setFontWeight("bold").setValue("Week5").setBackground("#BBBBBB");
ss.getRange('F1').setFontWeight("bold").setValue("Week6").setBackground("#BBBBBB");
}
Copy or Cut and Paste
Based upon your last comment I decided to give you another solution. This solution will either copy or cut and paste any range of data from any sheet to a any other range with the same dimensions. The ranges can be on the same page or different pages and the ranges can overlap. Also once you copy a range the document will remember the source and destination ranges so that you can copy or cut and paste them again without having to set up the ranges. If you want to change the range just run the routine and it will give you the choice to clear the range and then you can just run it again and it will remember the new ranges.
The copy and cut selection on the menu runs the routine. The Display Properties selection displays you current setup. The clear ranges will just delete everything in DocumentProperties.
But the Copy and Cut selection will give you all of the same info.
function onOpen()
{
var ui = SpreadsheetApp.getUi();
ui.createMenu('My Tools')
.addItem('Copy or Cut', 'copyFromToSetupUi')
.addItem('Display Properties','dispProperties')
.addItem('Clear Ranges','clearCopyProperties')
.addToUi();
}
function dispProperties()
{
var copyProperties = PropertiesService.getDocumentProperties();
var srcShtNameStr = copyProperties.getProperty('SourceSheetName');
var srcShtRangeStr = copyProperties.getProperty('SourceSheetRange');
var desShtNameStr = copyProperties.getProperty('DestinationSheetName');
var desShtRangeStr = copyProperties.getProperty('DestinationSheetRange');
var title = 'Copy From To Sheets Properties';
var msg = 'Source Sheet Name = ' + srcShtNameStr + '<br />';
msg += 'Source Sheet Range = ' + srcShtRangeStr + '<br />';
msg += 'Destination Sheet Range = ' + desShtNameStr + '<br />';
msg += 'Destination Sheet Range = ' + desShtRangeStr + '<br />';
msg += '<input type="button" value="Exit" onClick="google.script.host.close();" />';
dispStatus(title,msg);
}
function copyFromToSheets()
{
var copyProperties = PropertiesService.getDocumentProperties();
var srcRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(copyProperties.getProperty('SourceSheetName')).getRange(copyProperties.getProperty('SourceSheetRange'));
var srcA = srcRange.getValues();
srcRange.setBackground('#ffffff');
var desRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(copyProperties.getProperty('DestinationSheetName')).getRange(copyProperties.getProperty('DestinationSheetRange'));
desRange.setValues(srcA);
desRange.setBackground('#ffffff');
}
function cutnpasteFromToSheets()
{
var copyProperties = PropertiesService.getDocumentProperties();
var srcRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(copyProperties.getProperty('SourceSheetName')).getRange(copyProperties.getProperty('SourceSheetRange'));
var srcA = srcRange.getValues();
srcRange.clearContent();
srcRange.setBackground('#ffffff');
var desRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(copyProperties.getProperty('DestinationSheetName')).getRange(copyProperties.getProperty('DestinationSheetRange'));
desRange.setValues(srcA);
desRange.setBackground('#ffffff');
}
function setCopySource()
{
var srcShtName = SpreadsheetApp.getActiveSheet().getName();
var srcShtRange = SpreadsheetApp.getActiveRange();
var copyProperties = PropertiesService.getDocumentProperties();
copyProperties.setProperty('SourceSheetRange', srcShtRange.getA1Notation());
copyProperties.setProperty('SourceSheetName', srcShtName);
srcShtRange.setBackground('#d9caa9');
}
function setCopyDestination()
{
var desShtName = SpreadsheetApp.getActiveSheet().getName();
var desShtRange = SpreadsheetApp.getActiveRange();
var copyProperties = PropertiesService.getDocumentProperties();
copyProperties.setProperty('DestinationSheetRange',desShtRange.getA1Notation());
copyProperties.setProperty('DestinationSheetName', desShtName);
desShtRange.setBackground('#c4df87');
}
function clearCopyProperties()
{
var copyProperties = PropertiesService.getDocumentProperties();
var srcShtNameStr = copyProperties.getProperty('SourceSheetName');
var srcShtRangeStr = copyProperties.getProperty('SourceSheetRange');
var desShtNameStr = copyProperties.getProperty('DestinationSheetName');
var desShtRangeStr = copyProperties.getProperty('DestinationSheetRange');
if(srcShtNameStr && srcShtRangeStr)
{
var srcShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(srcShtNameStr).getRange(srcShtRangeStr);
srcShtRange.setBackground('#ffffff');
}
else
{
SpreadsheetApp.getUi().alert('At least one of the Source String Properties is undefined in clearCopyProperties so background color cannot be reset.');
}
if(desShtNameStr && desShtRangeStr)
{
var desShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(desShtNameStr).getRange(desShtRangeStr);
desShtRange.setBackground('#ffffff');
}
else
{
SpreadsheetApp.getUi().alert('At least one of the Destination String Properties is undefined in clearCopyProperties so background color cannot be reset.');
}
copyProperties.setProperty('SourceSheetName', '');
copyProperties.setProperty('SourceSheetRange', '');
copyProperties.setProperty('DestinationSheetName', '');
copyProperties.setProperty('DestinationSheetRange', '');
}
function copyFromToSetupUi()
{
var copyProperties = PropertiesService.getDocumentProperties();
var srcShtNameStr = copyProperties.getProperty('SourceSheetName');
var srcShtRangeStr = copyProperties.getProperty('SourceSheetRange');
var desShtNameStr = copyProperties.getProperty('DestinationSheetName');
var desShtRangeStr = copyProperties.getProperty('DestinationSheetRange');
var title='No Title';
var msg = 'No Text';
if(!srcShtNameStr || !srcShtRangeStr ) //if !src
{
title = 'Select Source Range';
msg = '<p>Please select input range from <strong>Source Sheet.</strong> and then press "Source Range Selected" button below.</p>\
<br /><input type="button" value="Source Range Selected" onclick="google.script.run.copyFromToSetupHelper(1);google.script.host.close();" />';
msg += '<script>console.log(\'flag1\');</script>';
dispStatus(title, msg);
}
if ((srcShtNameStr && srcShtRangeStr) && (!desShtNameStr || !desShtRangeStr)) //if src and !des
{
var srcShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(srcShtNameStr).getRange(srcShtRangeStr);
title = 'Select Destination Range';
msg = '<p>Please select a destination range which is ' + srcShtRange.getNumRows() + ' rows by ' + srcShtRange.getNumColumns() + ' columns.</p>';
msg += '<br /><input type="button" value="Destination Range Selected" onclick="google.script.run.copyFromToSetupHelper(2);google.script.host.close();" />';
msg += '<br />Input Range: ' + srcShtRangeStr + '<br /><input type="button" value="Clear Ranges and Start Over" onClick="google.script.run.clearCopyProperties();google.script.host.close(); />';
dispStatus(title, msg);
}
if((srcShtNameStr && srcShtRangeStr) && (desShtNameStr && desShtRangeStr))//if src and des
{
var srcShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(srcShtNameStr).getRange(srcShtRangeStr);
var desShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(desShtNameStr).getRange(desShtRangeStr);
if((desShtRange.getWidth()===srcShtRange.getWidth()) && (desShtRange.getHeight()===srcShtRange.getHeight()))
{
title= 'Displaying Source and Destination Ranges';
msg = '<br />Source Sheet/Range: ' + srcShtNameStr + '/' + srcShtRangeStr + '<br />Destination Sheet/Range: ' + desShtNameStr + '/' + desShtRangeStr + '<br />';
msg += '<br /><input type="button" value="Perform Copy" onclick="google.script.run.copyFromToSheets();google.script.host.close();" />';
msg += '<br /><input type="button" value="Perform Cut & Paste" onclick="google.script.run.cutnpasteFromToSheets();google.script.host.close();" />';
msg += '<br /><input type="button" value="Keep both Ranges Defined" onclick="google.script.host.close();" />';
msg += '<br /><input type="button" value="Clear Ranges and Start Over" onclick="google.script.run.clearCopyProperties();google.script.host.close();" />';
dispStatus(title,msg);
}
else
{
var srcShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(srcShtNameStr).getRange(srcShtRangeStr);
var desShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(desShtNameStr).getRange(desShtRangeStr);
var newdesShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(desShtNameStr).getRange(desShtRange.getRow(), desShtRange.getColumn(), srcShtRange.getNumRows(), srcShtRange.getNumColumns());
desShtRange.setBackground('white');
newdesShtRange.setBackground('#c4df87');
copyProperties.setProperty('DestinationSheetRange', newdesShtRange.getA1Notation());
title = 'Destination Range Adjusted';
msg = 'Source Range and Destination Range Dimension did not Match. So it was assumed that the upper left corner of the Destination Range is correct';
msg += 'and that the Sheet Selections were correct. The Destination Range was modified to have the same dimensions as the Source Range. ';
msg += '<br />Source Sheet/Range: ' + srcShtNameStr + '/' + srcShtRangeStr + '<br />Destination Sheet/Range: ' + desShtNameStr + '/' + newdesShtRange.getA1Notation() + '<br />';
msg += '<br /><input type="button" value="Perform Copy" onclick="google.script.run.copyFromToSheets();google.script.host.close();" />';
msg += '<br /><input type="button" value="Perform Cut & Paste" onclick="google.script.run.cutnpasteFromToSheets();google.script.host.close();" />';
msg += '<br /><input type="button" value="Keep both Ranges Defined" onclick="google.script.host.close();" />';
msg += '<br /><input type="button" value="Clear Ranges and Start Over" onclick="google.script.run.clearCopyProperties();;google.script.host.close(); />';
dispStatus(title,msg);
}
}
}
function copyFromToSetupHelper(mode)
{
var mode = (typeof(mode) !== 'undefined')? mode : 0;
switch(mode)
{
case 1:
setCopySource();
copyFromToSetupUi();
break;
case 2:
setCopyDestination();
copyFromToSetupUi();
break;
default:
clearCopyProperties();
}
}
// Display a modeless dialog box with custom HtmlService content.
function dispStatus(title,html,width,height)
{
var title = typeof(title) !== 'undefined' ? title : 'No Title Provided';
var width = typeof(width) !== 'undefined' ? width : 400;
var height = typeof(height) !== 'undefined' ? height : 300;
var html = typeof(html) !== 'undefined' ? html : '<p>No html provided.</p>';
var htmlOutput = HtmlService
.createHtmlOutput(html)
.setWidth(width)
.setHeight(height);
SpreadsheetApp.getUi().showModelessDialog(htmlOutput, title);
}
Google Script: Moves active selection range any direction
This will shift any selected range any direction you wish and it can select the destination range as the active selection. I've only tried it for one cell step moves so far.
function rangeJog(hoffset,voffset,moveselection)
{
var hoffset = (typeof(hoffset) !== 'undefined')? hoffset : 1;
var voffset = (typeof(voffset) !== 'undefined')? voffset : 0;
var moveselection = (typeof(moveselection) != 'undefined')? moveselection : true;
var src = SpreadsheetApp.getActiveRange();
var srcA1 = src.getA1Notation();
var row = src.getRow() + voffset;
var col = src.getColumn() + hoffset;
var rows = src.getLastRow() - src.getRow() + 1;
var cols = src.getLastColumn() - src.getColumn() +1;
if((row<1) || (col<1))
{
//dispStatus('No More Room to Move','<p>Either the first row or the first column or both will be less than one. <input type="button" value="exit" onClick="google.script.host.close();" /></p>', 400, 200);
SpreadsheetApp.getUi().alert('No more room to move.');
}
else
{
var des = SpreadsheetApp.getActiveSheet().getRange(src.getRow() + voffset, src.getColumn() + hoffset, src.getLastRow() - src.getRow() + 1, src.getLastColumn() - src.getColumn() +1);
var srcA = src.getValues();
src.clearContent();
des.setValues(srcA);
if(moveselection)
{
SpreadsheetApp.getActiveSheet().setActiveSelection(des);
}
}
var end = "is near";
}
It works on the selected range for now but any range could work because all calculations are relative to the src range. I also modified it to move the selection if moveselection is true.
But the idea of inserting a new column to the left is perhaps a simpler way to go. Although I don't see any insert cells command so inserting a column will move your headers around as well.
I have the following markup:
<fieldset>
<legend>Headline Events...</legend>
<div style="width:100%; margin-top:10px;">
<div style="width:100%; float:none;" class="clear-fix">
<div style="width:400px; float:left; margin-bottom:8px;">
<div style="width:150px; float:left; text-align:right; padding-top:7px;">
Team Filter:
</div>
<div style="width:250px; float:left;">
<input id="teamFilter" style="width: 100%" />
</div>
</div>
<div style="width:400px; float:left; margin-bottom:8px;">
<div style="width:150px; float:left; text-align:right; padding-top:7px;">
Type Filter:
</div>
<div style="width:250px; float:left;">
<input id="typeFilter" style="width: 100%" />
</div>
</div>
</div>
</div>
<div id="diaryTable" name="diaryTable" class="clear-fix">
Getting latest Headlines...
</div>
</fieldset>
I also have the following scripts
<script>
function teamFilterChange(e) {
//alert(this.value());
setCookie('c_team', this.value(), 90);
$c1 = getCookie('c_team');
$c2 = getCookie('c_type');
var param = "true|" + $c1 + "|" + $c2;
outputHLDiaryEntries(param);
}
function typeFilterChange(e) {
//alert(this.value());
setCookie('c_type', this.value(), 90);
$c1 = getCookie('c_team');
$c2 = getCookie('c_type');
var param = "true|" + $c1 + "|" + $c2;
outputHLDiaryEntries(param);
}
// This optional function html-encodes messages for display in the page.
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
function outputHLDiaryEntries(param) {
var url = "Home/DiaryEntries/";
var data = "id=" + param;
$.post(url, data, function (json) {
var n = json.length;
alert(n + ' ' + json);
if(n == 0){
//json is 0 length this happens when there were no errors and there were no results
$('#diaryTable').replaceWith("<span style='color:#e00;'><strong>Sorry: </strong> There are no headline events found. Check your filters.</span>");
} else {
//json has a length so it may be results or an error message
//if jsom[0].dID is undefined then this mean that json contains the error message from an exception
if (typeof json[0].dID != 'undefined') {
//json[0].dDI has a value so we
//output the json formatted results
var out = "";
var i;
var a = "N" //used to change the class for Normal and Alternate rows
for (i = 0; i < json.length; i++) {
out += '<div class="dOuter' + a + '">';
out += '<div class="dInner">' + json[i].dDate + '</div>';
out += '<div class="dInner">' + json[i].dRef + '</div>';
out += '<div class="dInner">' + json[i].dTeam + '</div>';
out += '<div class="dInner">' + json[i].dCreatedBy + '</div>';
out += '<div class="dType ' + json[i].dType + '">' + json[i].dType + '</div>';
out += '<div class="dServer">' + json[i].dServer + '</div>';
out += '<div class="dComment">' + htmlEncode(json[i].dComment) + '</div></div>';
//toggle for normal - alternate rows
if (a == "N") {
a = "A";
} else {
a = "N";
}
}
//output our formated data to the diaryTable div
$('#diaryTable').replaceWith(out);
} else {
//error so output json string
$('#diaryTable').replaceWith(json);
}
}
}, 'json');
}
$(document).ready(function () {
//Set User Preferences
//First check cookies and if null or empty set to default values
var $c1 = getCookie('c_team');
if ($c1 == "") {
//team cookie does not exists or has expired
setCookie('c_team', 'ALL', 90);
$c1 = "ALL";
}
var $c2 = getCookie('c_type');
if ($c2 == "") {
//type cookie does not exists or has expired
setCookie('c_type', "ALL", 90);
$c2 = "ALL";
}
// create DropDownList from input HTML element
//teamFilter
$("#teamFilter").kendoDropDownList({
dataTextField: "SupportTeamText",
dataValueField: "SupportTeamValue",
dataSource: {
transport: {
read: {
dataType: "json",
url: "Home/SupportTeams?i=1",
}
}
}
});
var teamFilter = $("#teamFilter").data("kendoDropDownList");
teamFilter.bind("change", teamFilterChange);
teamFilter.value($c1);
//typeFilter
$("#typeFilter").kendoDropDownList({
dataTextField: "dTypeText",
dataValueField: "dTypeValue",
dataSource: {
transport: {
read: {
dataType: "json",
url: "Home/DiaryTypes?i=1",
}
}
}
});
var typeFilter = $("#typeFilter").data("kendoDropDownList");
typeFilter.bind("change", typeFilterChange);
typeFilter.value($c2);
// Save the reference to the SignalR hub
var dHub = $.connection.DiaryHub;
// Invoke the function to be called back from the server
// when changes are detected
// Create a function that the hub can call back to display new diary HiLights.
dHub.client.addNewDiaryHiLiteToPage = function (name, message) {
// Add the message to the page.
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + htmlEncode(message) + '</li>');
};
// Start the SignalR client-side listener
$.connection.hub.start().done(function () {
// Do here any initialization work you may need
var param = "true|" + $c1 + "|" + $c2;
outputHLDiaryEntries(param)
});
});
</script>
On initial page load the outputHLDiaryEntries function is called when the signalR hub is started. If I then change any of the dropdownlists this calls the outputHLDiaryEntries but the $('#diaryTable').replaceWith(); does not work. If I refresh the page the correct data is displayed.
UPDATE!
Based on A.Wolff's comments I fixed the issue by wrapping the content I needed with the same element I was replacing... by adding the following line at the beginning of the outputHLDiartEntries function...
var outStart = '<div id="diaryTable" name="diaryTable" class="clear-fix">';
var outEnd = '</div>';
and then changing each of the replaceWith so that they included the wrappers e.g.
$('#diaryTable').replaceWith(outStart + out + outEnd);
replaceWith() replaces element itself, so then on any next call to $('#diaryTable') will return empty matched set.
You best bet is to replace element's content instead, e.g:
$('#diaryTable').html("<span>New content</span>");
I had the same problem with replaceWith() not working when called a second time.
This answer helped me figure out what I was doing wrong.
The change I made was assigning the same id to the new table I was creating.
Then when I would call my update function again, it would create a new table, assign it the same id, grab the previous table by the id, and replace it.
let newTable = document.createElement('table');
newTable.id = "sameId";
//do the work to create the table here
let oldTable = document.getElementById('sameId');
oldTable.replaceWith(newTable);