I'm working on a project with a javascript library YUI and JSP.
I'm trying to manipulate a YUI datatable, some cells of the table are select options and input text:
What I'm trying to do is to manipulate the options of the select options input dynamically at runtime:
First, this is the declaration of the datatable:
var CustomSelectCellEditor = Y.Component.create({
NAME: 'CustomSelectCellEditor',
ATTRS: {
multiple: {
value: false,
validator: Y.Lang.isBoolean
},
strings: {
value: {
edit: 'Edit',
save: 'OK',
cancel: 'Annuler'
}
}
},
EXTENDS: Y.BaseOptionsCellEditor,
UI_ATTRS: ['multiple'],
prototype: {
ELEMENT_TEMPLATE: '<select class="celleditor-element error-field"></select>',...
var ruleTypeCreateColumns = [{editor: new CustomSelectCellEditor({editable: false,options: types}), ...
var newRulesTable = new Y.DataTable({
columns : ruleTypeCreateColumns,
width: "80%",
editable: true,
editEvent: 'click'
});
the datatable will look like, a datatable with input cells, the input editor appears in a click event:
At runtime, I tried to change the editor, for example from select options to input text, according to the input of the first column:
newRulesTable.after('*:criteriaTypeChange', function(o){
for(var i=0; i<newRulesTable.data.size();i++) {
if(newRulesTable.data.item(i).get('criteriaType') == getTypes().date) {
// TODO HERE
}
}
});
After many attempts, I couldn't reach my goal, so I need to know which object should I change?
manipulating data in runtime is a hinder when using native JavaScript, unlike famous libraries like angular , react that updates automatically your view when your data change ( two ways binding) , in native JavaScript you should implement this logic manually via listeners and pure code:
Here a simple example
we want to update our select option when we click on the button
<!DOCTYPE html>
<html lang="en" xml:lang="en">
<head>
<title>an example </title>
<meta content="text/html; charset=utf-8" />
</head>
</div>
<body>
<h1>
This is a dynamic select
</h1>
<div id="select-container">
<button id="button">Change Select Dynamiclly</button>
<select id="select" name="pets" id="pet-select">
<option value="dog">Dog</option>
<option value="cat">Cat</option>
</select>
</div>
<script>
const button = document.querySelector("#button");
button.addEventListener("click", event => {
window.alert('Content has been changed !')
changeContent();
});
var changeContent = function () {
var animals = ["Fish","Horse","Pig"]
const select = document.querySelector("#select");
for (var i = 0; i < animals.length; i++) {
var opt = document.createElement('option');
opt.value = animals[i];
opt.innerHTML = animals[i];
select.appendChild(opt);
}
}
</script>
</body>
</html>
idon't really know how YUI library work but i hope this will help you a little.
Related
I am trying to load options into a select box from a Google Sheet. My code currently almost works, however, the initial select option is not loading the corresponding value into the text input box when the page first displays. When the select box option is changed, the value is properly loaded into the text box. How can I load both the option and value on the initial page load?
Code.gs
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu("Sidebar")
.addItem("Show sidebar", "showSidebar")
.addToUi();
}
function showSidebar() {
var htmlWidget = HtmlService.createHtmlOutputFromFile('Test')
SpreadsheetApp.getUi().showSidebar(htmlWidget);
}
function getList() {
var items = SpreadsheetApp.getActive().getRange("Sheet1!A1:B3").getValues();
return items;
}
Test.html
<!DOCTYPE html>
<html>
<script>
function loadSelectBox() {
google.script.run.withSuccessHandler(function(ar)
{
var itemList = document.getElementById("itemSelectBox");
ar.forEach(function(item, index)
{
var option = document.createElement("option");
option.value = item[1];
option.text = item[0];
itemList.appendChild(option);
});
}).getList();
getPath();
}
function getPath()
{
var path = document.getElementById("itemSelectBox").value;
document.getElementById("itemPath").value = path;
}
</script>
<head>
<base target="_top">
</head>
<body>
<select id="itemSelectBox" onchange="getPath()" style="width: 60%"></select>
<br>
<input type="text" id="itemPath" style="width: 60%">
<script>
loadSelectBox();
</script>
</body>
</html>
In your script, how about the following modification?
Modified script:
Please modify loadSelectBox() as follows.
function loadSelectBox() {
google.script.run.withSuccessHandler(function (ar) {
var itemList = document.getElementById("itemSelectBox");
ar.forEach(function (item, index) {
var option = document.createElement("option");
option.value = item[1];
option.text = item[0];
itemList.appendChild(option);
});
getPath(); // <--- Modified
}).getList();
}
In your showing script, getPath(); is put outside of google.script.run. google.script.run is run with the asynchronous process. By this, before withSuccessHandler is run, getPath() is run. I thought that this is the reason for your issue.
Reference:
Class google.script.run (Client-side API)
I think the problem is that you have the javascript in the header and thus it's run before the dom (html) is created.
You can
a) move your javascript into a in the end
b) trigger your code once https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event is fired.
alternative a might work better but it's not pretty to have html and JS mixed unless you really have to.
Goal: The purpose is that a sheet will contain information, this information is placed inside a namedrange, the namedrange will be dynamic (the entire column is given a namedrange).
I created a html popup which contains a dropdown list. This dropdown list must contain the list of information from the namedrange.
I am unable to understand how this is to be done. Here is the code below:
function fncOpenMyDialog() {
var htmlDlg = HtmlService.createHtmlOutputFromFile('HTML_myHtml')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(200)
.setHeight(150);
SpreadsheetApp.getUi()
.showModalDialog(htmlDlg, 'New File');
};
function onInstall(e) {
onOpen(e);
}
function onOpen(e) {
var ui = SpreadsheetApp.getUi();
ui.createMenu('New')
.addItem('New Save File Extension','fncOpenMyDialog')
.addToUi();
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<select name="nameYouWant" placeholde="File Type">
<option value="something">Word</option>
<option value="anything">MS Excel</option>
<option value="anything">MS Powerpoint</option>
<option value="anything">MS Slides</option>
</select>
<hr/>
<p>Choose a file, which will then be saved into your Google Drive.</p>
<button onmouseup="closeDia()">Close</button>
<button onmouseup="onOpen()">Save</button>
<script>
window.closeDia = function() {
google.script.host.close();
};
window.saveDia = function() {
onOpen();
};
</script>
</body>
</html>
As you can see in my html file, that the extensions are currently hardcoded.
I am trying to make this dynamic, how do I achieve this?
I believe your goal as follows.
You want to put the values to the dropdown list by retrieving from the named range of the Spreadsheet.
In this case, is the named range the same with this thread?
For this, how about this answer?
Modification points:
From google.script.host.close(), I understood that the HTML file of HTML_myHtml is included in the Google Apps Script project. By this, I would like to propose to achieve your goal using google.script.run.
If the named range is the same with your previous question, you can use it by modifying a little.
When above points are reflected to your script, it becomes as follows.
Modified script:
HTML and JavaScript side: HTML_myHtml
Please modify HTML_myHtml as follows.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<select id="select" name="nameYouWant" placeholde="File Type"></select>
<hr />
<p>Choose a file, which will then be saved into your Google Drive.</p>
<button onmouseup="closeDia()">Close</button>
<button onmouseup="onOpen()">Save</button>
<script>
google.script.run.withSuccessHandler(v => {
const obj = document.getElementById("select");
v.forEach(e => {
const option = document.createElement("option");
option.text = e;
option.value = e;
obj.appendChild(option);
});
}).readNamedRange();
window.closeDia = function() {
google.script.host.close();
};
window.saveDia = function() {
onOpen();
};
</script>
</body>
</html>
Google Apps Script side: Code.gs
At above HTML, readNamedRange() is used. So please put the following script. If you have the same function names, please modify them. In this script, the values are retrieved from the named range of listDown, and sent to HTML side using google.script.run.
function readNamedRange() {
var activeSheet = SpreadsheetApp.getActiveSheet();
var result = activeSheet.getRange("listDown").getValues();
var end = activeSheet.getLastRow();
var values = [];
for (var i = 0; i < end; i++) {
if (result[i][0] != "") {
values.push(result[i][0]);
}
}
return values;
}
Note:
About window.saveDia = function() {onOpen()};, unfortunately, I couldn't understand about what you want to do.
Reference:
Class google.script.run
This question already has an answer here:
Odd behavior of datatables.search function after modifying it
(1 answer)
Closed 4 years ago.
There are already several questions here on SO on this subject, however none is about my exact situation.
I have a datatable with 2 columns, one contains text input field and the other a select. The current behavior of datatables' search functionality is to search in the entire select HTML. The behvior I want is search only the chosen option.
I'm aware we can override/intercept the search/filter events, ie
$('#mapping-table_filter input', data_table.table().container())
.off('.DT')
.on('keyup.DT cut.DT paste.DT input.DT search.DT', function (e) {
data_table.search(...).draw();
});
// or
data_table.on('search.dt', function () {
});
But this does not help since .search does not accept a callback.
JSFiddle
https://jsfiddle.net/0oabx2mr/
If you search for any of "first", "second" or "third" both rows are still visible. I want to be able to search for "second" and "third" and only get the relevant row.
With slight architecture changes, your example may look like that:
var srcData = [
['firstOption', 'secondOption', 'thirdOption'],
['firstOption', 'secondOption', 'thirdOption'],
['firstOption', 'secondOption', 'thirdOption'],
['firstOption', 'secondOption', 'thirdOption']
];
var dataTable = $('#mytable').DataTable({
sDom: 't',
data: srcData,
columns: [{
title: 'Options',
render: (data, type, row) => '<select>'+row.reduce((options, option) => options += `<option value="${option}">${option}</option>`,'')+'</select>'
}]
});
var needle = null;
$.fn.DataTable.ext.search.push(
(settings, row, index) => $(dataTable.cell(`:eq(${index})`,':eq(0)').node()).find('select').val().match(needle) || !needle
);
$('#search').on('keyup', event => {
needle = $(event.target).val();
dataTable.draw();
});
<!doctype html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
<input id="search"></input>
<table id="mytable"></table>
</body>
</html>
I need to get data from Materialize CSS chips, but I don't know, how.
$('.chips-placeholder').material_chip({
placeholder: 'Stanici přidíte stisknutím klávesy enter',
secondaryPlaceholder: '+Přidat',
});
function Show(){
var data = $('.chips-placeholder').material_chip('data');
document.write(data);
}
<!-- Added external styles and scripts -->
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/js/materialize.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/css/materialize.min.css">
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- HTML body -->
<div class="chips chips-placeholder"></div>
<button onclick="Show()" type="button">Show</button>
So, to access to the data's chip you just have to do this:
var data = $('#id of your chips div').material_chip('data');
alert(data[0].tag);`
'0' is the index of your data (0, 1, 2 , 3, ...).
'tag' is the chip content. You can also get the id of your data with '.id'.
To get data from Materialize CSS chips, use the below code.
$('#button').click(function(){
alert(JSON.stringify(M.Chips.getInstance($('.chips')).chipsData));
});
They appear to have changed the method available in the latest version.
The documentation suggests that you should be able to access the values as properties of the object, but I’ve spent an hour looking, not getting anywhere.
Until the following happened
$('.chips-placeholder').chips({
placeholder: 'Enter a tag',
secondaryPlaceholder: '+Tag',
onChipAdd: (event, chip) => {
console.log(event[0].M_Chips.chipsData);
},
During the onChipAdd event I was able to access the event. Within this object was an array of tags.
I know this isn't the documented way, however there is only so much time a client will accept when it comes billing and I must move on.
This worked great for me
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.chips');
var instances = M.Chips.init(elems, {
placeholder: "Ajouter des Tags",
secondaryPlaceholder: "+tag",
onChipAdd: chips2Input,
onChipDelete: chips2Input,
Limit: 10,
minLength: 1
});
function chips2Input(){
var instance = M.Chips.getInstance(document.getElementById('chip1')), inpt = document.getElementById('myInputField');
inpt.value = null;
for(var i=0; i<instance.chipsData.length; i++){
if(inpt.value == null)
inpt.value = instance.chipsData[i].tag;
else{
inpt.value += ','+instance.chipsData[i].tag; //csv
}
}
console.log('new value: ', inpt.value);
}
});
</script>
I'm trying to change a text color, using the Select object, trying to get the color I selected and setting it to the text. There are two functions commented on my script, both were my attempts to get it done, but failed. Not asking for a complete answer/code, just want to know what is wrong.
This is the code and thanks for your time:
<!DOCTYPE HTML>
<html>
<head>
<title>Hola Mundo Controles</title>
<meta name="author" content="José Del Valle Cordero"/>
<meta charset="utf-8" />
</head>
<body>
<div class="main">
<div class="subject" id="subject">
<span id="salute">¡Hello!</span>
</div>
<div id="control">
<div class="color_option">
Color:
<select name="color_list" id="colors" >
<option value="cl_option1" checked="checked">Red </option>
<option value="cl_option2">Blue </option>
<option value="cl_option3">Yellow </option>
<option value="cl_option4">Black </option>
</select>
</div>
</div>
</div>
<script type="text/javascript">
var item,cl;
var colorsMap = {
'cl_option1' : "red",
'cl_option2' : "blue",
'cl_option3' : "yellow",
'cl_option4' : "black"
};
/*colors.onchange=function() {
var salute = document.getElementById("salute");
var item = document.getElementById("colors").selectedIndex;
var color = colorsMap[item];
salute.style.color = color;
};*/
/*$('#colors').change(function(){
var salute = document.getElementById("salute");
item=$(this).val();
cl = colorsMap[item];
salute.style.color = cl;
});*/
</script>
</body>
You're close. Include jQuery in <head>:
<script src="//code.jquery.com/jquery-latest.js"></script>
Then in your JS:
<script type="text/javascript">
var colorsMap = {
'cl_option1' : "red",
'cl_option2' : "blue",
'cl_option3' : "yellow",
'cl_option4' : "black"
};
$('#colors').change(function(){
$("#salute").css('color', colorsMap[$(this).val()]);
});
</script>
The original script is too clumsy & mixing up non-jQuery & jQuery functions.
The biggest issue I see, besides your lack of jQuery being included in the page, is your js is being executed right away. Both of your attempts use js to talk to the DOM where those html nodes are, however, the DOM my not be ready with those nodes when your scripts are running.
jQuery offers a way to do this with a single line, if you prefer to go that route. If you want to learn native js, which I highly recommend, you'll want to read up on listening for when the window is ready.
To answer your questions:
The first code block (non-jQuery) was using selectedIndex for your select element, which was returning a numerical value (the index value) of the selected item. You wanted the string value to check against your map of colors. Updating your code so it looks something like:
var colors = document.getElementById('colors');
colors.onchange=function(){
var salute = document.getElementById("salute");
var item = document.getElementById("colors").value;
var color = colorsMap[item];
salute.style.color = color;
}
will work.
Updated fiddle: http://jsfiddle.net/pH4wW/2/
The second one, you just need jQuery :)
There are so many thing has to be changed in the code.
If you are doing it with js
colors.onchange=function(){
var salute = document.getElementById("salute");
var item = document.getElementById("colors").selectedIndex;
var color = colorsMap[item];
salute.style.color = color;
};
has to be changed to
document.getElementById("colors").onchange=function(){
var salute = document.getElementById("salute");
var item = document.getElementById("colors").value;
var color = colorsMap[item];
document.getElementById("salute").style.color = color;
};
you have to attach onchange event using document.getElementById
if jquery
$('#colors').change(function(){
var salute = document.getElementById("salute");
item=$(this).val();
cl = colorsMap[item];
$('#salute').css('color', cl);
});
Also you are missing jquery library.