How do you call a different function when a line of text from a TextField/TextArea is clicked?
I already have a function which retrieves a description when any point of the TextField is clicked:
list.text = "chicken";
list.addEventListener(MouseEvent.CLICK, getter);
var descriptionArray:Array = new Array();
descriptionArray[0] = ["potato","chicken","lemon"];//words
descriptionArray[1] = ["Round and Brown","Used to be alive","Yellow"];//descriptions
function getter(e:MouseEvent):void
{
for (var i:int = 0; i < descriptionArray.length; i++)
{
var str:String = e.target.text;//The text from the list textfield
if (str == descriptionArray[0][i]) //if the text from List is in the array
{
trace("found it at index: " + i);
description.text = descriptionArray[1][i];//displays "Used to be alive".
}
else
{
trace(str+" != "+descriptionArray[0][i]);
}
}
}
It works fine, and returns the correct description.
But I want it to instead retrieve a different description depending on what line in the TextField/TextArea was clicked, like, if I used list.text = "chicken\npotato"
I know I can use multiple textfields to contain each word, but the list might contain over 100 words, and I want to use the TextArea's scrollbar to scroll through the words in the list, and if I used multiple textfields/areas, each one would have its own scrollbar, which is pretty pointless.
So, how do I call a different function depending on what line I clicked?
PS: It's not technically a different function, it's detecting the string in the line that was clicked, I just put it that way for minimal confusion.
There are a few built-in methods that should make your life easier:
function getter(e:MouseEvent):void
{
// find the line index at the clicked point
var lineIndex:int = list.getLineIndexAtPoint(e.localX, e.localY);
// get the text at that line index
var itemText:String = list.getLineText(lineIndex).split("\n").join("").split("\r").join("");
// find the text in the first array (using indexOf instead of looping)
var itemIndex:int = descriptionArray[0].indexOf(itemText);
// if the item was found, you can use the sam index to
// look up the description in the second array
if(itemIndex != -1)
{
description.text = descriptionArray[1][itemIndex];
}
}
Related
I have a Kendo grid that uses Export-to-excel and Export-to-pdf.
One particular column consists of data with padded zeros (so that column sorting works). Then, this column uses a template to display the data without the padded zeros (a business requirement). This is perfect for the grid.
Now, the export functions do not export the template, they export the underlying data (this is documented in the Known Limitations). So my exports show the data with padded-zeros. But... I need to show the data without padded zeros. So I have been looking for a workaround.
Workaround attempt A)
I created two columns padded and non-padded. The idea was this:
Column i/ Data = padded; Grid view = non-padded; do not export.
Column ii/ Data = non-padded; Grid view = hidden; export.
However, this doesn't work for two reasons.
Column i/ columns: exportable: { pdf: false, excel: false } doesn't actually seem to work(!!!)
Column ii/ This isn't legal anyway. If you hide the data in the grid you can't export it anyway.
Workaround attempt B)
In the excelExport() function I did this:
excelExport: function (e) {
for (var j = 0; j < e.data.length; j++) {
e.data[j].padded_column = e.data[j].non-padded_column;
}
},
In the console this appears to work fine, that is I replace the value of the padded column with the data of the non-padded column. However, it makes no difference to what appears on the spreadsheet. My guess is that this is because the spreadsheet has already been generated before excelExport() modifies the data.
So, I need a new approach. Can anybody help?
ADDITIONAL INFO
For further reference, here is the code for the column:
columns: [{
field: 'sys_id_sorted',
title: 'File ref',
hidden: false,
template: function (dataItem) {
var ctyClass = '';
switch (dataItem.cty_id) {
case '1':
ctyClass = 'CHAP';
break;
case '2':
ctyClass = 'EU-PILOT';
break;
case '3':
ctyClass = 'NIF';
break;
case '4':
ctyClass = 'OTHER';
break;
default:
ctyClass = 'default';
break;
}
return '<div class="label label-' + ctyClass + ' origin">' + dataItem.sys_id + '</div>';
}
},
'sys_id_sorted' is the field that has padded zeros.
'dataItem.sys_id' is the field with no padded zeros.
In the excelExport event you have access to the workbook, thus, you could modify it as follows:
var sheet = e.workbook.sheets[0];
for (var i = 1; i < sheet.rows.length; i++) {
var row = sheet.rows[i];
row.cells[0].value = row.cells[0].value.replace(/^0+/, '')
}
You can test the same in the following sample:
https://dojo.telerik.com/ADIfarOp
Kudos to Georgi Yankov for pointing me in the right direction. The solution is to manipulate the values found in e.workbook, not e.data. Here is my (simplified for brevity) solution. The four vars inside the loop are simply manipulating the string to create my non-padded version. 'row.cells[0].value' is the original zero-padded string. The data-replacement happens on the last line:
excelExport: function (e) {
var sheet = e.workbook.sheets[0];
for (var k = 1; k < sheet.rows.length; k++) {
var row = sheet.rows[k];
var sys_id_sorted = row.cells[0].value;
var caseNum = sys_id_sorted.substring(9);
var caseNumTrimmed = caseNum.replace(/^0+/, '');
row.cells[0].value = sys_id_sorted.substring(0,9) + caseNumTrimmed;
}
},
I'm new to office.js and making add ins and I'm trying to make an add in for Excel. I've run into an issue for one thing that seems like it should be very easy, but isn't. I'm just trying to get the background color of the selected cells. From what I can tell, I'll need to loop through each selected cell and check the fill.color value individually, which is fine, except I keep getting an error when trying to read this property.
Error PropertyNotLoaded: The property 'color' is not available. Before reading the property's value, call the load method on the containing object and call "context.sync()" on the associated request context.
I don't quite understand why I would have to run the context.sync() for this, when it's already being run and I'm trying to use the code that was already generated by Visual Studio for the add in.
The error is confusing because I'm able to set the color like this without any issues. Here is the code I've added trying to get the fill color. The first line is commented out, but adds an orange fill to the selected cells no problem. I only added this to see if I could read out a value I knew was already set. I'm trying to get the user defined fill for a selected range though. The second line is where the error gets thrown.
//sourceRange.getCell(i, j).format.fill.color = "orange"; // this sets the color no problem when uncommented
$('#fa-output').append("color: " + sourceRange.getCell(i,j).format.fill.color + "<br>"); //this is where it can't get the fill color
I'm using the example that Visual Studio generates where it will randomly generate 9 cells of random numbers and highlight the highest number in the selected range. Here is the full code for this method:
// Run a batch operation against the Excel object model
Excel.run(function (ctx) {
// Create a proxy object for the selected range and load its properties
var sourceRange = ctx.workbook.getSelectedRange().load("values, rowCount, columnCount, format");
// Run the queued-up command, and return a promise to indicate task completion
return ctx.sync()
.then(function () {
var highestRow = 0;
var highestCol = 0;
var highestValue = sourceRange.values[0][0];
// Find the cell to highlight
for (var i = 0; i < sourceRange.rowCount; i++) {
for (var j = 0; j < sourceRange.columnCount; j++) {
//sourceRange.getCell(i, j).format.fill.color = "orange"; // this sets the color no problem when uncommented
$('#fa-output').append("color: " + sourceRange.getCell(i,j).format.fill.color + "<br>"); //this is where it can't get the fill color
if (!isNaN(sourceRange.values[i][j]) && sourceRange.values[i][j] > highestValue) {
highestRow = i;
highestCol = j;
highestValue = sourceRange.values[i][j];
}
}
}
cellToHighlight = sourceRange.getCell(highestRow, highestCol);
sourceRange.worksheet.getUsedRange().format.font.bold = false;
// Highlight the cell
cellToHighlight.format.font.bold = true;
$('#fa-output').append("<br>The highest value is " + highestValue);
})
.then(ctx.sync);
})
.catch(errorHandler);
You have a lot of commented out code in your code that makes it hard to read.
At any rate, this is expected behavior. You have to load() and then sync() when you want to read a property of an object in the workbook. It's the load-and-sync that brings the value of the property from the workbook to the JavaScript in your add-in so you can read it. Your code is trying to read a property that it hasn't first loaded. The following is a simple example:
const cell = context.workbook.getActiveCell();
cell.load('format/fill/color');
await context.sync();
console.log(cell.format.fill.color);
ES5 version:
const cell = context.workbook.getActiveCell();
cell.load('format/fill/color');
return context.sync()
.then(function () {
console.log(cell.format.fill.color);
});
You should also take a look at the Range.getCellProperties() method, which is a kind of wrapper around the load.
I have a Google Apps script which replaces placeholders in a copy of a template document with some text by calling body.replaceText('TextA', 'TextB');.
Now I want to extend it to contain images. Does anybody have idea how to do this?
Thank you,
Andrey
EDIT: Just to make it clear what my script does. I have a Google form created in a spreadsheet. I've created a script which runs upon form submission, traverses a sheet corresponding to the form, find unprocessed rows, takes values from corresponding cells and put them into a copy of a Google document.
Some fields in the Google form are multi-line text fields, that's where '\r\r' comes from.
Here's a workaround I've come up with by now, not elegant, but it works so far:
// replace <IMG src="URL"> with the image fetched from URL
function processIMG_(Doc) {
var totalElements = Doc.getNumChildren();
for( var j = 0; j < totalElements; ++j ) {
var element = Doc.getChild(j);
var type = element.getType();
if (type =='PARAGRAPH'){
var par_text = element.getText();
var start = par_text.search(new RegExp('<IMG'));
var end = par_text.search(new RegExp('>'));
if (start==-1)
continue;
// Retrieve an image from the web.
var url = getURL_(par_text.substring(start,end));
if(url==null)
continue;
// Before image
var substr = par_text.substring(0,start);
var new_par = Doc.insertParagraph(++j, substr);
// Insert image
var resp = UrlFetchApp.fetch(url);
new_par.appendInlineImage(resp.getBlob());
// After image
var substr = par_text.substring(end+1);
Doc.insertParagraph(++j, substr);
element.removeFromParent();
j -= 2; // one - for latter increment; another one - for increment in for-loop
totalElements = Doc.getNumChildren();
}
}
}
Here is a piece of code that does (roughly) what you want.
(there are probably other ways to do that and it surely needs some enhancements but the general idea is there)
I have chosen to use '###" in the doc to mark the place where the image will be inserted, the image must be in your google drive (or more accurately in 'some' google drive ).
The code below uses a document I shared and an image I shared too so you can try it.
here is the link to the doc, don't forget to remove the image and to put a ### somewhere before testing (if ever someone has run the code before you ;-)
function analyze() { // just a name, I used it to analyse docs
var Doc = DocumentApp.openById('1INkRIviwdjMC-PVT9io5LpiiLW8VwwIfgbq2E4xvKEo');
var image = DocsList.getFileById('0B3qSFd3iikE3cF8tSTI4bWxFMGM')
var totalElements = Doc.getNumChildren();
var el=[]
for( var j = 0; j < totalElements; ++j ) {
var element = Doc.getChild(j);
var type = element.getType();
Logger.log(j+" : "+type);// to see doc's content
if (type =='PARAGRAPH'){
el[j]=element.getText()
if(el[j]=='###'){element.removeFromParent();// remove the ###
Doc.insertImage(j, image);// 'image' is the image file as blob
}
}
}
}
EDIT : for this script to work the ### string MUST be alone in its paragraph, no other character before nor after... remember that each time one forces a new line with ENTER the Document creates a new paragraph.
I have a text field and a background and want to apply color using
myColorPicker. Either the text field or background can be selected using
radioGroup1. When either radio button is selected the trace statement
traces the variable obj2Clr exactly. However when I use that variable
with Transform, I can't apply color. If I hard code and use the actual
object then it works.
Can I not use a variable with Transform or is something else missing?
My code is below:
var radioGroup1:RadioButtonGroup = new RadioButtonGroup("selObj");
bkg_rb.label = "Background";
text_rb.label = "Text";
bkg_rb.group = radioGroup1;
text_rb.group = radioGroup1;
var obj2Clr;//which object to apply color to
radioGroup1.addEventListener(MouseEvent.CLICK, getObj);
function getObj(e:MouseEvent):void {
if (bkg_rb.selected == true) {
obj2Clr = "MovieClip(parent).design_mc.bkg_mc";
trace(obj2Clr);
} else if (text_rb.selected == true) {
obj2Clr = "MovieClip(parent).design_mc.info_txt";
trace(obj2Clr);
}
}
var colorTrans:ColorTransform = new ColorTransform();
var trans:Transform = new Transform(obj2Clr);
//var trans:Transform = new Transform(MovieClip(parent).design_mc.info_txt);
myColorPicker.addEventListener(ColorPickerEvent.CHANGE, changeColor);
function changeColor(event:ColorPickerEvent):void {
var myColor = "0x" + event.target.hexValue;
colorTrans.color = myColor;
trans.colorTransform = colorTrans;
trace("color selected is " + myColor);
}
Thanks for your help in advance:)
Debbie D
According to this code, obj2Clr is being initialized with a string literal?
For example, shouldn't this snippet:
if (bkg_rb.selected == true) {
obj2Clr = "MovieClip(parent).design_mc.bkg_mc";
trace(obj2Clr);
}
be:
if (bkg_rb.selected == true) {
obj2Clr = MovieClip(parent).design_mc.bkg_mc;
trace(obj2Clr);
}
?
Thanks, yes I thought I had to use a string literal with Transform because tracing out the variable without quotes that make it a literal resulted in [object MovieClip] and [object TextField].
So I removed the quotes and Transform still is not receiving the new Transform object. Yet when I hard code (which was commented out in the above example) everything is fine. Any other area I should check?
Debbie D :)
Clicking on the second cell (any row) in the datatable causes the cell editor to display. But, I am trying to display the cell editor from code. The code looks like the following:
var firstEl = oDataTable.getFirstTdEl(rowIndex);
var secondCell = oDataTable.getNextTdEl(firstEl);
oDataTable.showCellEditor(secondCell);
When I debug into the datatable.js code (either with a click or from the code above) it follows the same path through the showCellEditor function but the above code will not display the editor.
I am using YUI version 2.8.0r4.
I think this is blur events issue.
So, for example, I have link that must add record to datatable, and show its editor.
var mymethod = function (e) {
YAHOO.util.Event.stopEvent(e);
var r = {};
r.id = 0;
r.value = 'hello world';
myDataTable.addRow(r);
var cell = myDataTable.getLastTrEl().cells[0];
myDataTable.showCellEditor(cell);
}
YAHOO.util.Event.addListener('mylink2addrecord_ID', 'click', mymethod);
Without stopEvent you will never see editor, because there is tableBlur event called when you click on yourlink....
You can try this - this is ONLY a snippet from a larger piece of an event handler set of code I have. EditNext is the function that moves over a cell and displays the editor, if the cell has one:
this.myDataTable.subscribe("editorKeydownEvent",function(oArgs) {
var self = this,
ed = this._oCellEditor, // Should be: oArgs.editor, see: http://yuilibrary.com/projects/yui2/ticket/2513909
ev = oArgs.event,
KEY = YAHOO.util.KeyListener.KEY,
Textbox = YAHOO.widget.TextboxCellEditor,
Textarea = YAHOO.widget.TextareaCellEditor,
DCE = YAHOO.widget.DateCellEditor,
cell = ed.getTdEl(),
col = ed.getColumn(),
row,rec,
editNext = function(cell) {
cell = self.getNextTdEl(cell);
while (cell && !self.getColumn(cell).editor) {
cell = self.getNextTdEl(cell);
}
if (cell) {
self.showCellEditor(cell);
}
},
As mac said, you need to stop the previous event. For some reason it (the tableBlur event) conflicts with the showCellEditor function. This is the first place which had a resolution to the problem.
To sum it up, all I did was:
YAHOO.util.Event.stopEvent(window.event);<br/>
dt.showCellEditor(td); // dt = yui datatable obj, td = {record: yuirecord, column: yuicolumn}
Of course if you have the event object readily available as mac's post does, you can pass it to stopEvent(e) like he did.