dynamically making textarea ckeditor - textarea

When i try to make these dynamically made textareas into CEditor fields i get the error:
TypeError: b is undefined
my code:
var input = $("<textarea>").addClass("textAreaClassTest");
//input.setAttribute("id", "como");
//input.setIdAttribute("id", "como");
//input.ID = 'como';
CKEDITOR.replace('como');
item.append(input);
//CKEDITOR.replace('como');
return item;
i cant seem to give the textarea an id - any id's :)

I'm assuming you're using jQuery and only working with 1 or more text areas at a time. So you can get the text areas and assign them ids and use them as below.
//select all text areas
var input = $("textarea");
var list = new Array();
var count = 0;
input.each(function () {
count++;
$this = $(this);
$this.attr("id", "como" + count);
console.log('id is "' + $this.attr("id") + '" and text is "' + $this.text() + '"');
CKEDITOR.replace($this.attr("id"));
list.push($this.attr("id"));
});
//return the list of replaced text area ids
return list;

Related

Splitting Google Sheets Script?

function doGet(e){
Logger.log("--- doGet ---");
var tag = "",
value = "";
try {
// this helps during debuggin
if (e == null){e={}; e.parameters = {tag:"test",value:"-1"};}
tag = e.parameters.tag;
value = e.parameters.value;
// save the data to spreadsheet
save_data(tag, value);
return ContentService.createTextOutput("Wrote:\n tag: " + tag + "\n value: " + value);
} catch(error) {
Logger.log(error);
return ContentService.createTextOutput("oops...." + error.message
+ "\n" + new Date()
+ "\ntag: " + tag +
+ "\nvalue: " + value);
}
}
// Method to save given data to a sheet
function save_data(tag, value){
Logger.log("--- save_data ---");
try {
var dateTime = new Date();
// Paste the URL of the Google Sheets starting from https thru /edit
// For e.g.: https://docs.google.com/..../edit
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1HYJRHfJVgZp16xYt4fipR1bH2BudhuQ4UrDhAf1rBKw/edit");
var dataLoggerSheet = ss.getSheetByName("Datalogger");
// Get last edited row from DataLogger sheet
var row = dataLoggerSheet.getLastRow() + 1;
// Start Populating the data
dataLoggerSheet.getRange("A" + row).setValue(row -1); // ID
dataLoggerSheet.getRange("B" + row).setValue(dateTime); // dateTime
dataLoggerSheet.getRange("C" + row).setValue(tag); // tag
dataLoggerSheet.getRange("D" + row).setValue(value); // value
//dataLoggerSheet.getRange("E" + row).setValue(value); // value
//dataLoggerSheet.getRange("F" + row).setValue(value); // value
// Update summary sheet
summarySheet.getRange("B1").setValue(dateTime); // Last modified date
// summarySheet.getRange("B2").setValue(row - 1); // Count
}
catch(error) {
Logger.log(JSON.stringify(error));
}
Logger.log("--- save_data end---");
}
In the example above, inside the value of "tag" there is data in the format "12345678912 | ABCDEFGHIJ". "Tag" data in column C; I want to print with the first 11 characters in column D. The "tag" data in column C; I want to print it with column E after 12 characters. How can I do that?
To see my overall objective, these two screenshots should show it.
Original Spreadsheet from Form:
enter image description here
Formatted Version of Spreadsheet:
enter image description here
Thank you in advance for your help.
You will have to manipulate the tag string in order to get the values you want.
In order to do this you will have change this:
dataLoggerSheet.getRange("C" + row).setValue(tag); // tag
To this:
dataLoggerSheet.getRange("C" + row).setValue(tag.slice(0,tag.indexOf('|')); //first part of tag
dataLoggerSheet.getRange("D" + row).setValue(tag.slice(tag.indexOf('|') + 2)); // second part of tag
dataLoggerSheet.getRange("E" + row).setValue(value); // value
Explanation
The above snippet makes use of the indexOf and slice methods from JavaScript in order to get the index of the | character in order to be able to split the tag string into two different strings.
Reference
JavaScript Array.prototype.slice();
JavaScript Array.prototype.indexOf().

Create jQuery ui dialog box for each row in a table

I am trying to append rows to a table using an array called searchResults. Everything works as expected until I introduce the jQuery UI dialog box. The problem is I need a new dialog box for each row in the first column. I'm pretty new to all of this so I'm pretty sure I'm using the index incorrectly at times. This is just to give you an idea of what I'm trying to accomplish. Any ideas how to do this correctly?
for (var i = 0; i < searchResults.length; i++)
{
$('#patientFileDialog[i]').dialog();
$'#openPFDialog[i]').click(function() {
$('#patientFileDialog[i]').dialog('open');
});
var dialog[i] = $(`<div id="patientFileDialog[i]" title="Patient File">${searchResults[i].patientWebLink}</div>`);
body.append('<tr>'+
`<td><button id="openPFDialog[i]">Click Here</button></td>` +
`<td>${searchResults[i].patientFirstName}</td>` +
`<td>${searchResults[i].patientLastName}</td>` +
`<td>${searchResults[i].patientDateOfBirth}</td>` +
`<td>${searchResults[i].patientDataPulseID}</td>` +
`<td>${searchResults[i].patientLaserFicheID}</td>` +
'</tr>')
}
After looking at your code a bit more I think I can see what you are trying to do. Working JSFiddle, with some faked searchResults so we can see it in action.
There are a few problems with the code in your question:
Using selectors like $('#patientFileDialog[i]') and $'#openPFDialog[i]') will try to match elements on the page with those IDs. AFAICT those don't actually exist yet, you are trying to create them.
var dialog[i] = ... sets up some divs as strings, but those are never added to the page;
As I mentioned in my comment, there are some syntax errors, maybe just typos and mixed up formatting here on SO;
Here's an updated version of the code. Notable changes:
Instead of adding an event handler for every individual openPFDialog button, it is better practice to add just one which matches them all. That single handler can then work out which button was clicked, and take the right action for just that one, not all of them. In this case if you have all your buttons use IDs that match openPFDialog-X, where X is a number, you can target anything matching that pattern (using a starts with selector, and find the X by removing the openPFDialog- part with replace.
There's an added complication with the above though. Selectors parsed at page load will only match elements that exist at that time. In this case, you're adding new elements to the page, and a selector defined at page load won't match them. The solution is to select instead some parent element which does exist at page load, and filter. This is called event delegation (search for the paragraph starting with "Delegated event handlers").
Working from what you have, I am guessing the patientFileDialogs you create should be placed inside some parent element which is not displayed on the page? That's what I've done.
Here's the code (and working JSFiddle):
var dialog, i;
// Single click handler for anything that starts with "openPFDialog-".
// Since those elements don't exist on the page yet, we need to instead
// select a parent object, say the body, and filter for clicks on our
// elements starting with our pattern
$('body').on('click', '[id^=openPFDialog]', function() {
// We need to find the "i"
i = $(this).attr('id').replace(/openPFDialog-/,'');
console.log('clicked on id', i);
$('#patientFileDialog-' + i).dialog();
});
for (var i = 0; i < searchResults.length; i++) {
// Create a new div with ID like "patientFileDialog-1", using the current
// search result
dialog = $('<div id="patientFileDialog-' + i + '" title="Patient File">' + searchResults[i].patientWebLink + '</div>');
// Add it to the page. I've use a div with ID dialogs which is hidden
$('#dialogs').append(dialog);
$('table').append('<tr>'+
'<td><button id="openPFDialog-' + i + '">Click Here</button></td>' +
'<td>' + searchResults[i].patientFirstName + '</td>' +
'<td>' + searchResults[i].patientLastName + '</td>' +
'<td>' + searchResults[i].patientDateOfBirth + '</td>' +
'<td>' + searchResults[i].patientDataPulseID + '</td>' +
'<td>' + searchResults[i].patientLaserFicheID + '</td>' +
'</tr>');
}
Update
One last suggestion - manipulating the DOM by adding/removing elements is slow. If you need to do that for each element in an array, it is best to avoid actually adding your content on each iteration, and rather just build up a string. Then once you're done iterating, just add the big single string, so you're chaning the DOM just once. Here's the basic changes needed to do that:
// Add some new variables to hold our big strings
var dialog, dialogs, row, rows, i;
// ... your code ...
for (var i = 0; i < searchResults.length; i++) {
// Create the dialog ...
dialog = ...
// Append it to our big string of all dialogs
dialogs += dialog;
// Same approach for rows
row = '<tr>'+ ... all that stuff
rows += row;
}
// Finished iterating, nothing added to DOM yet. Do it all at once::
$('#dialogs').append(dialogs);
$('table').append(rows);
Here is what I finally ended up having to do:
$(document).ready(function(){
if ($('[attr="searchResultsJson"]').length)
{
$('.approval-outer-wrap').prepend(drawTable());
$('.approval-outer-wrap').append('<div id="result-details" title="Search Result Detail"><p></p></div>')
}
$('body').on('click', '[id^=openPFDialog]', function() {
var result = $(this).parents('tr').data('result');
$('#result-details p').html(result.patientFirstName);
$('#result-details').dialog();
});
});
function drawTable(){
var table = $('<table id="search-results" />');
var header = $('<thead />');
table.append(header);
header.append('<tr><th>Patient File</th><th>First Name</th><th>Last Name</th><th>Date of Birth</th><th>Data Pulse ID</th><th>Laserfiche ID</th></tr>');
var body = $('<tbody />');
table.append(body);
var json = $('[attr="searchResultsJson"] [type="text"]').text();
var searchResults = JSON.parse(json);
for (var i = 0; i < searchResults.length; i++) {
body.append(`<tr data-result='${JSON.stringify(searchResults[i])}'>`+
`<td><button id="openPFDialog-` + i + `">🔍</button></td>` +
`<td>${searchResults[i].patientFirstName}</td>` +
`<td>${searchResults[i].patientLastName}</td>` +
`<td>${searchResults[i].patientDateOfBirth}</td>` +
`<td>${searchResults[i].patientDataPulseID}</td>` +
`<td>${searchResults[i].patientLaserFicheID}</td>` +
'</tr>');
}
return table;
}
Consider the following code.
function showPatientDialog(cnt){
$("#patient-file-dialog").html(cnt).dialog("open");
}
var d = $("<div>", {
id: "patient-file-dialog",
title: "Patient File"
})
.appendTo("body")
.dialog({
autoOpen: false
});
$.each(searchResults, function(i, result) {
var row = $("<tr>").appendTo(body);
$("<td>").appendTo(row).html($("<button>", {
id: "open-pdf-dialog-" + i
}).click(function() {
showPatientDialog(result.patientWebLink);
}));
$("<td>").appendTo(row).html(result.patientFirstName);
$("<td>").appendTo(row).html(result.patientLastName);
$("<td>").appendTo(row).html(result.patientDateOfBirth);
$("<td>").appendTo(row).html(result.patientDataPulseID);
$("<td>").appendTo(row).html(result.patientLaserFicheID);
});

Extract URL from copied text in Google Sheets [duplicate]

I have a sheet where hyperlink is set in cell, but not through formula. When clicked on the cell, in "fx" bar it only shows the value.
I searched on web but everywhere, the info is to extract hyperlink by using getFormula().
But in my case there is no formula set at all.
I can see hyperlink as you can see in image, but it's not there in "formula/fx" bar.
How to get hyperlink of that cell using Apps Script or any formula?
When a cell has only one URL, you can retrieve the URL from the cell using the following simple script.
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var url = sheet.getRange("A2").getRichTextValue().getLinkUrl(); //removed empty parentheses after getRange in line 2
Source: https://gist.github.com/tanaikech/d39b4b5ccc5a1d50f5b8b75febd807a6
When Excel file including the cells with the hyperlinks is converted to Google Spreadsheet, such situation can be also seen. In my case, I retrieve the URLs using Sheets API. A sample script is as follows. I think that there might be several solutions. So please think of this as one of them.
When you use this script, please enable Sheets API at Advanced Google Services and API console. You can see about how to enable Sheets API at here.
Sample script:
var spreadsheetId = "### spreadsheetId ###";
var res = Sheets.Spreadsheets.get(spreadsheetId, {ranges: "Sheet1!A1:A10", fields: "sheets/data/rowData/values/hyperlink"});
var sheets = res.sheets;
for (var i = 0; i < sheets.length; i++) {
var data = sheets[i].data;
for (var j = 0; j < data.length; j++) {
var rowData = data[j].rowData;
for (var k = 0; k < rowData.length; k++) {
var values = rowData[k].values;
for (var l = 0; l < values.length; l++) {
Logger.log(values[l].hyperlink) // You can see the URL here.
}
}
}
}
Note:
Please set spreadsheetId.
Sheet1!A1:A10 is a sample. Please set the range for your situation.
In this case, each element of rowData is corresponding to the index of row. Each element of values is corresponding to the index of column.
References:
Method: spreadsheets.get
If this was not what you want, please tell me. I would like to modify it.
Hey all,
I hope this helps you save some dev time, as it was a rather slippery one to pin down...
This custom function will take all hyperlinks in a Google Sheets cell, and return them as text formatted based on the second parameter as either [JSON|HTML|NAMES_ONLY|URLS_ONLY].
Parameters:
cellRef : You must provide an A1 style cell reference to a cell.
Hint: To do this within a cell without hard-coding
a string reference, you can use the CELL function.
eg: "=linksToTEXT(CELL("address",C3))"
style : Defines the formatting of the output string.
Valid arguments are : [JSON|HTML|NAMES_ONLY|URLS_ONLY].
Sample Script
/**
* Custom Google Sheet Function to convert rich-text
* links into Readable links.
* Author: Isaac Dart ; 2022-01-25
*
* Params
* cellRef : You must provide an A1 style cell reference to a cell.
* Hint: To do this within a cell without hard-coding
* a string reference, you can use the CELL function.
* eg: "=linksToTEXT(CELL("address",C3))"
*
* style : Defines the formatting of the output string.
* Valid arguments are : [JSON|HTML|NAMES_ONLY|URLS_ONLY].
*
*/
function convertCellLinks(cellRef = "H2", style = "JSON") {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var cell = sheet.getRange(cellRef).getCell(1,1);
var runs = cell.getRichTextValue().getRuns();
var ret = "";
var lf = String.fromCharCode(10);
runs.map(r => {
var _url = r.getLinkUrl();
var _text = r.getText();
if (_url !== null && _text !== null) {
_url = _url.trim(); _text = _text.trim();
if (_url.length > 0 && _text.length > 0) {
switch(style.toUpperCase()) {
case "HTML": ret += '' + _text + '}' + lf; break;
case "TEXT": ret += _text + ' : "' + _url + '"' + lf; break;
case "NAMES_ONLY" : ret += _text + lf; break;
case "URLS_ONLY" : ret += _url + lf; break;
//JSON default : ...
default: ret += (ret.length>0?(','+ lf): '') +'{name : "' + _text + '", url : "' + _url + '"}' ; break;
}
ret += lf;
}
}
});
if (style.toUpperCase() == "JSON") ret = '[' + ret + ']';
//Logger.log(ret);
return ret;
}
Cheers,
Isaac
I tried solution 2:
var urls = sheet.getRange('A1:A10').getRichTextValues().map( r => r[0].getLinkUrl() ) ;
I got some links, but most of them yielded null.
I made a shorter version of solution 1, which yielded all the links.
const id = SpreadsheetApp.getActive().getId() ;
let res = Sheets.Spreadsheets.get(id,
{ranges: "Sheet1!A1:A10", fields: "sheets/data/rowData/values/hyperlink"});
var urls = res.sheets[0].data[0].rowData.map(r => r.values[0].hyperlink) ;

Possible to iterate through markers after applying a query in a FusionTablesLayer?

I currently have a filter working on a fusion table rendered as a Map Layer, and I want to zoom to best fit all of the data whenever the filter is changed.
I figure I need to wait until the query is applied and then iterate through the markers to find the min/max x & y locations and pan to that rectangle, but I don't see a way in the Maps api to access the markers of a layer.
Anyone have an idea how to do this?
The short answer is no. To me this is one of the shortcomings of dealing with Fusion Tables via the Maps API. E.g. wanting to display a count of the results of my most recent query. But there is a work-around through the "undocumented" JSONP API to Fusion Tables. I've had great success using it but I must credit Robin Kraft with informing me about this API.
http://www.reddmetrics.com/2011/08/10/fusion-tables-javascript-query-maps.html.
Here's some code which allows you to re-execute your most recent query via an AJAX JSONP request and do what you want with the results, such as calculating the bounding-box. Note: this example uses Jquery for the AJAX JSONP calls. This example creates a <table> display but can be modified as needed.
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
// Example call
getFTData(tableid, 'latitude,longitude', example_dataHandler);
<script>
// Globals same for all requests
var queryUrlHead = 'https://fusiontables.googleusercontent.com/fusiontables/api/query?sql=';
var queryUrlTail = '&jsonCallback=?'; // ? could be a function name
// getFTData()
// table_id - Fusion Table id MUST have public permissions
// col_list - comma separated list of FT column names
// successFunction - function to parse the CSV results (see exampleParser below)
//////////////////////////////
function getFTData(table_id, col_list, successFunction) {
var query = "SELECT " + col_list + " FROM " + table_id;
var queryurl = encodeURI(queryUrlHead + query + queryUrlTail);
$.ajax({
type: "GET",
url: queryurl,
dataType: "jsonp", // return CSV FustionTable response as JSON
success: successFunction,
error: function () {alert("AJAX ERROR for " + queryurl ); }
});
}
function example_dataHandler(d) {
// get the actual data out of the JSON object
var cols = d.table.cols;
var rows = d.table.rows;
var row_count = 0;
var results = '<table border="1" cellpadding="4">';
results += '<tr>';
for (var i = 0; i < cols.length; i++) {
results += '<th>' + cols[i] + '</th>';
}
results += '</tr>';
// loop through all rows to add them to the map
for (var i = 0; i < rows.length; i++) {
// Per the expected columns
results += '<tr>';
for(j=0; j < rows[i].length; j++)
{
results += '<td>' + rows[i][j] + '</td>';
}
results += '</tr>';
row_count++;
}
results += '</table>';
results += '<br />';
results += 'Row Count: ' + row_count + '<br />';;
document.getElementById("program_select").innerHTML = results;
}
</script>
Since retrieving the count of recent Fusion Table rows returned is common, I'm adding a snippet of how to do that.
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
var tableid = 3167783
var where = "WHERE type = 9";
getFTCount(current_table_id, where, displayCount);
// Globals same for all request
var queryUrlHead = 'https://fusiontables.googleusercontent.com/fusiontables/api/query?sql=';
var queryUrlTail = '&jsonCallback=?'; // ? could be a function name
///////////////////////////////
// Get Counts from Fusion Tables.
// table_id required
// where optional "WHERE column == 'value' " where clause for count()
// successFunction callback required
///////////////////////////////
function getFTCount(table_id, where, successFunction) {
if(!table_id){
alert("table_id required.");
return;
}
if(!successFunction){
alert("successFunction callback required.");
return;
}
var query = "SELECT count() FROM " + table_id;
if(where){
query += ' ' + where;
}
var queryurl = encodeURI(queryUrlHead + query + queryUrlTail);
$.ajax({
type: "GET",
url: queryurl,
dataType: "jsonp", // return CSV FustionTable response as JSON
success: successFunction,
error: function () {alert("AJAX ERROR for " + queryurl ); }
});
}
function displayCount(d) {
var count = d.table.rows[0];
alert(count);
}
</script>
If your data is in a fusion table, then use the fusion table's sql api to find the Max/Min val for Lat and Lng respectively:
https://www.googleapis.com/fusiontables/v1/query?sql=SELECT
MINIMUM(Lat) AS MinLat, MAXIMUM(Lat) AS MaxLat,
MINIMUM(Long) AS MinLong, MAXIMUM(Long) AS MaxLong
FROM <table_id>
See here for full details on api: https://developers.google.com/fusiontables/docs/v1/sql-reference. (One thing to remember is to ecodeURI this sql statement)
This returns those for value to json array. And as I'm sure your aware, use these values to set your map's 'center' and 'zoom' parameters.

JQuery Mobile - Dynamic Count Bubbles

I am creating a JQuery Mobile application that has a listview. I am populating that listview with the results of a web service. Because of this, the items in the list view are being populated as shown here:
$.each(results, function (i, result) {
var s = "<li><h2 style='padding-left:40px;'>" + result.title + "</h2><p style='padding-left:40px;'>";
s += result.subTitle;
s += "</p><span class='ul-li-count'>" + result.count + "</span></li>";
$("#resultListView").append(s);
});
$("#resultListView").listview("refresh");
My listview is being populated correctly. The value for the count bubble is showing. However, the UI does not render the bubble. Is there a way to dynamically build a result set with count bubbles in a list view? If so, how?
Thank you!
Your way should work. The only thing I can think of is that the HTML is not valid.
Anyway, I created a simple version to show that it's possible. http://jsfiddle.net/kiliman/HDUqp/
Basically, just build up the HTML for <li/> and append to the list, then call .listview('refresh')
$('#page1').bind('pageinit', function(e, data) {
var n = 0;
$('#addResult').click(function(e) {
var $list = $('#resultListView');
n++;
$('<li/>')
.append($('<h2>', { text: 'Title ' + n }))
.append($('<p>', { text: 'SubTitle ' + n }))
.append($('<span />', { text: n, class: 'ui-li-count'}))
.appendTo($list);
$list.listview('refresh');
});
});

Resources