I am working on displaying the Json output of a generated flowchart. I have stored the dropped elements' details in an array called finalArray and am simply adding it to the Json display. All the details seem to be properly displayed except for the attribute names and their attribute types that are retrieved from another array.
I've commented the part that doesn't work in the following code segment
Code in Context
function saveFlowchart(){
var nodes = [];
var matches = [];
var searchEles = document.getElementById("container").children;
for(var i = 0; i < searchEles.length; i++)
{
matches.push(searchEles[i]);
var idOfEl = searchEles[i].id;
if(searchEles[i].id !=null || searchEles[i].id !="")
{
var $element = $("#" + searchEles[i].id);
var dropElem = $("#" + searchEles[i].id).attr('class');
var position = $element.position();
position.bottom = position.top + $element.height();
position.right = position.left + $element.width();
//alert("class:"+dropElem+"\nTop position: " + position.top + "\nLeft position: " + position.left + "\nBottom position: " + position.bottom + "\nRight position: " + position.right);
finalArray[i] = [];
finalArray[idOfEl-1][0]= idOfEl;
finalArray[idOfEl-1][1]= dropElem;
finalArray[idOfEl-1][2]= [];
finalArray[idOfEl-1][2][0] = position.top;
finalArray[idOfEl-1][2][1] = position.left;
finalArray[idOfEl-1][2][2] = position.bottom;
finalArray[idOfEl-1][2][3] = position.right;
var elId = parseInt(idOfEl);
if (dropElem=="streamdrop ui-draggable")
{
for(var count=0;count<100;count++)
{
if(createdImportStreamArray[count][0]==idOfEl)
{
finalArray[elId-1][3]= createdImportStreamArray[count][1]; //Selected Stream from Predefined Streams
finalArray[elId-1][4]= createdImportStreamArray[count][2]; //asName
//alert("createdImportStreamArray[count][0]==elId\n"+count);
}
else if(createdExportStreamArray[count][0]==idOfEl)
{
finalArray[elId-1][3]= createdExportStreamArray[count][1]; //Selected Stream from Predefined Streams
finalArray[elId-1][4]= createdExportStreamArray[count][2]; //asName
}
else if(createdDefinedStreamArray[count][0]==idOfEl)
{
finalArray[elId-1][3]= createdDefinedStreamArray[count][1]; //Stream Name
finalArray[elId-1][4]= createdDefinedStreamArray[count][4]; //Number of Attributes
finalArray[elId-1][5]=[];
for(var f=0;f<createdDefinedStreamArray[count][4].length;f++)
{
finalArray[elId-1][5][f]=[];
The following two are not displayed individually. Instead only "[]" is shown
finalArray[elId-1][5][f][0]=createdDefinedStreamArray[count][2][f][0]; //Attribute Name
finalArray[elId-1][5][f][1]=createdDefinedStreamArray[count][2][f][1]; // Attribute Type
}
}
}
}
else if (dropElem=="wstream ui-draggable")
{
finalArray[elId-1][3]= createdWindowStreamArray[elId-1][1]; // Window Name
finalArray[elId-1][4]= createdImportStreamArray[elId-1][2]; //Selected Stream Index
finalArray[elId-1][4]= createdImportStreamArray[elId-1][3]; //Selected Stream
finalArray[elId-1][5]= [];
var AttributeNumber = createdWindowStreamArray[elId-1][4].length;
for(var attrFill=0;attrFill<AttributeNumber;attrFill++)
{
finalArray[elId-1][5][attrFill]=[];
finalArray[elId-1][5][attrFill][0]=createdWindowStreamArray[elId-1][4][attrFill][0];
finalArray[elId-1][5][attrFill][1]=createdWindowStreamArray[elId-1][4][attrFill][1];
}
//alert("createdImportStreamArray[count][0]==elId\n"+count);
}
else if (dropElem=="squery ui-draggable")
{
ElementType="squery";
}
else if (dropElem=="wquery ui-draggable")
{
ElementType="wquery";
}
else if (dropElem=="joquery ui-draggable")
{
ElementType="joquery";
}
else if(dropElem=="stquery ui-draggable")
{
ElementType="stquery";
}
else if(dropElem=="partitiondrop ui-draggable")
{
ElementType="partitiondrop";
}
}
}
alert(finalArray);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
$(".node").each(function (idx, elem) {
var $elem = $(elem);
var endpoints = jsPlumb.getEndpoints($elem.attr('id'));
console.log('endpoints of '+$elem.attr('id'));
console.log(endpoints);
nodes.push({
blockId: $elem.attr('id'),
nodetype: $elem.attr('data-nodetype'),
positionX: parseInt($elem.css("left"), 10),
positionY: parseInt($elem.css("top"), 10)
});
});
var connections = [];
$.each(jsPlumb.getConnections(), function (idx, connection) {
connections.push({
connectionId: connection.id,
pageSourceId: connection.sourceId,
pageTargetId: connection.targetId
});
});
var flowChart = {};
flowChart.nodes = nodes;
flowChart.connections = connections;
flowChart.elements =finalArray;
flowChart.numberOfElements = finalArray.length;
var flowChartJson = JSON.stringify(flowChart);
//console.log(flowChartJson);
$('#jsonOutput').val(flowChartJson);
}
Current Json Output
Basic Interface
createdDefinedStream Array
//Array that stores all Defined stream data
var createdDefinedStreamArray = [];
for(var x = 0; x < 100; x++){
createdDefinedStreamArray[x] = [];
for(var y = 0; y < 5; y++){
createdDefinedStreamArray[x][y] = null
}
}
function storeDefinedStreamInfo(newAgent,i,e,kind)
{
var StrName= document.getElementById("StreamNameInput").value;
var StreamElementID = i;
var table = document.getElementById('attrtable');
var tblerows = (table.rows.length);
createdDefinedStreamArray[i][2]=new Array(tblerows);
for (r = 1; r < tblerows; r++) {
for(var c=0; c<1;c++) {
var attrNm = table.rows[r].cells[c].innerHTML;
var attrTp = table.rows[r].cells[1].innerHTML;
createdDefinedStreamArray[i][2][r-1]= new Array(2);
createdDefinedStreamArray[i][2][r-1][0]=attrNm;
createdDefinedStreamArray[i][2][r-1][1]=attrTp;
}
}
createdDefinedStreamArray[i][0]=StreamElementID;
createdDefinedStreamArray[i][1]=StrName;
createdDefinedStreamArray[i][3]="Defined Stream";
createdDefinedStreamArray[i][4]= tblerows;
var prop = $('<a onclick="doclickDefine(this)"><b><img src="../Images/settings.png" class="settingsIconLoc"></b></a> ').attr('id', (i+'-prop'));
var conIcon = $('<img src="../Images/connection.png" onclick="connectionShowHideToggle(this)" class="showIconDefined"></b></a> ').attr('id', (i+'vis'));
newAgent.text(StrName).append('<a class="boxclose" id="boxclose"><b><img src="../Images/Cancel.png"></b></a> ').append(conIcon).append(prop);
dropCompleteElement(newAgent,i,e,kind);
}
Could you please try running this code on your data to see if I missed anything and if the problem is solved? I replaced all of the loops with maps, so it's a little bit clearer which data gets selected where.
function saveFlowchart(){
var nodes = [],
searchElements = Array.prototype.slice.call(document.querySelector('#container').childNodes),
matches = searchElements.slice(),
finalArray,
ElementType, // this was global in the example and is currently not used in the sample code.
map = function map( ary, field ) {
return ary.reduce(function( map, element ) {
map[element[field]] = element;
return map;
}, {});
},
// Let's create a bunch of maps so we can reference each id directly instead of having to loop Each array for each element several times.
// This results in easier to understand code and runs faster, since nested arrays several levels deep can cause confusion.
// Noted the signature of each provided array.
// importStreamMap: [ id, selected stream, asName ]
importStreamMap = map(createdImportStreamArray, 0),
// exportStreamMap: [ id, selected stream, asName ]
exportStreamMap = map(createdExportStreamArray, 0),
// definedStreamMap: [ id, stream name, [ [attr1 name, attr1 type], [attr2 name, attr2 type], ... ], ???, attr count ]
definedStreamMap = map(createdDefinedStreamArray, 0),
// windowStreamMap: [ id, window name, selected stream index, selected stream (name?) ]
windowStreamMap = map(createdWindowStreamArray, 0),
classHandlers = {
'streamdrop ui-draggable' : function( id, result ) {
if (importStreamMap.hasOwnProperty(id)) {
result.push(importStreamMap[id][1]); // selected stream
result.push(importStreamMap[id][2]); // asName
}
else if (exportStreamMap.hasOwnProperty(id)) {
result.push(exportStreamMap[id][1]); // selected stream
result.push(exportStreamMap[id][2]); // asName
}
else if (definedStreamMap.hasOwnProperty(id)) {
result.push(definedStreamMap[id][1]); // stream name
result.push(definedStreamMap[id][4]); // attr count
result.push(definedStreamMap[id][2].slice()); // just clone the entire array of key/value pairs, no need to recreate it since they are strings.
}
},
'wstream ui-draggable' : function( id, result ) {
result.push(windowStreamMap[id][1]); // window name
// one of these two is obsolete, since the second overwrites the first. Selected stream according to the array signature ????
// result.push(importStreamMap[id][2]);
result.push(importStreamMap[id][3]);
result.push(windowStreamMap[id][4].slice()); // clone the array again.
},
'wquery ui-draggable' : function( id, result ) {
ElementType = 'wquery';
},
'joquery ui-draggable' : function( id, result ) {
ElementType = 'joquery';
},
'stquery ui-draggable' : function( id, result ) {
ElementType = 'stquery';
},
'partitiondrop ui-draggable' : function( id, result ) {
ElementType = 'partitiondrop';
}
};
finalArray = searchElements.reduce(function( ary, element ) {
var id = parseInt(element.id, 10),
$element,
dropCls,
position,
result;
if (id) {
$element = element.querySelector('#' + id);
dropCls = $element.className;
position = $element.position();
position.bottom = position.top + $element.height();
position.right = position.left + $element.width();
result = [ id, dropCls, [ position.top, position.left, position.bottom, position.right ] ];
classHandlers[dropCls](id, result);
ary.push(result);
}
return ary;
}, []);
////////////////////////////////////////////////////////////////////
// Rest of the code stays the same. If the attributes aren't showing up yet, check if the array is correct and if the indexes are ok.
// From the array signatures, we get that the createdDefinedStreamArray contains the attributes instead of the createdWindowStreamArray.
// For the record, it'd be easier to just use key-value pairs and objects in the JSON, if the API allows that.
}
Related
From my data source I am getting values like;
USA |Arizona
USA |Florida
UK |England |Northamptonshire
UK |England |Derbyshire
UK |Wales |Powys
Switzerland|Lucern
These are flat text values that repeat in a column.
I need to build them dynamically into nested array
source: [
{title: "USA", children: [
{title: "Arizona"},
{title: "Florida"}
]}
],
As per https://github.com/mar10/fancytree/wiki/TutorialLoadData
Unfortunately my brain has stopped working today I am can't see a elegant way.
Any pointers would be most gratefully appreciated.
So I solved this eventually using a post from Oskar
function getNestedChildren(arr, parent) {
var out = []
for(var i in arr) {
if(arr[i].parent == parent) {
var children = getNestedChildren(arr, arr[i].id)
if(children.length) {
arr[i].children = children
}
out.push(arr[i])
}
}
return out
}
http://oskarhane.com/create-a-nested-array-recursively-in-javascript/
This builds the nested array.
To ensure inferred values were present (e.g. USA which is in the hierarchy but is not a unique value).
var CountryArray = CountryText.split("|");
// Variables to hold details of each section of the Country path being iterated
var CountryId = '';
var CountryParentPrefix = '';
var CountryParent = '';
// Iterate each section of the delimeted Country path and ensure that it is in the array
for(var i in CountryArray)
{
var CountryId = CountryParentPrefix+CountryArray[i];
// Find the Country id in the array / add if necessary
var result = FlatSource.filter(function (Country) { return Country.id == CountryId });
if (result.length == 0) {
// If the Country is not there then we should add it
var arrCountry = {title:CountryArray[i], parent:CountryParent, id:CountryId};
FlatSource.push(arrCountry);
}
// For the next path of the heirarchy
CountryParent = CountryId;
CountryParentPrefix = CountryId+'|';
}
I did not use Sven's suggestion but I suspect that it is equally valid.
Turn it to JSON:
var str = '"USA|Arizona","USA|Florida","UK|LonelyIsland","UK|England|Northamptonshire","UK|England|Derbyshire","UK|Wales|Powys","UK|England|London|Soho","Switzerland|Lucern';
var jsonStr = "[[" + str.replace(/,/g,'],[') + "\"]]";
jsonStr = jsonStr.replace(/\|/g,'","');
var nested = JSON.parse(jsonStr);
Then play with parents and children.
function findObject(array, key, value) {
for (var i=0; i<array.length; i++) {
if (array[i][key] === value) {
return array[i];
}
}
return null;
}
function obj(arr){
this.title = arr.shift();
}
obj.prototype.addChild = function(arr){
var tmp = new obj(arr);
if(typeof this.children === 'undefined'){
this.children = new Array();
result = this.children[this.children.push(tmp)-1];
}else{
result = findObject(this.children, 'title', tmp.title);
if(!result)
result = this.children[this.children.push(tmp)-1];
}
return result;
}
obj.prototype.addChildren = function(arr){
var obje = this;
while(arr.length>0)
obje = obje.addChild(arr);
}
var finArr = [];
for(i=0; i<nested.length; i++){
var recc = new obj(nested[i]);
if(oldObj = findObject(finArr, 'title', recc.title)){
oldObj.addChildren(nested[i]);
}else{
if(nested[i].length>0)
recc.addChildren(nested[i]);
finArr.push(recc);
}
}
console.log('------------------------------------------')
console.log(JSON.stringify(finArr));
console.log('--------------------The End---------------')
I have this code below to search for a string of search string_search_* matched.
I'm wondering if there's any easier way to do this like maybe add multiple search term in indexof? is that possible?
My goal: just add variable string:
string_search4, 5, 6 and so on..
string = "this is a .bigcommerce.com site";
var string_search1 = 'cdn.shopify.com/s';
var string_search2 = '.bigcommerce.com/';
var string_search3 = 'woocommerce/';
// start checkig with SHOPIFY first
var s = string.indexOf(string_search1 );
var found_s = String(s);
// IF FOUND - look for the full url hubspot - like the mp4 url
if (found_s != '-1') {
var result = 'SHOPIFY'
return result;
}
// if NOT FOUND, check with BIGCOMMERCE
else {
var b = html.indexOf(string_search2);
var found_b = String(b);
if (found_b != '-1') {
var result = 'BIGCOMMERCE'
return result;
}
else {
var w = html.indexOf(string_search3);
var found_w = String(w);
if (found_w != '-1') {
var result = 'WOO COMMERCE'
return result;
}
else {
var result = 'CANNOT INDENTIFY CMS'
return result
}
}
}
This may look a little long, but is very expandable.
// Our "key" object and defaults
var sObj = function(id){
this.id = id;
this.found = false;
};
// Our self-contained object with search and result
// functions. This is were and how we can expand quickly
var s = {
'ob': [],
'find': function(haystack) {
if (this.ob) {
for(var x in this.ob) {
this.ob[x].found = (haystack.indexOf(this.ob[x].id) > -1);
}
}
},
'result': function() {
var r = "";
if (this.ob) {
for(var x in this.ob) {
if (this.ob[x].found) {
r += ","+this.ob[x].id;
}
}
}
return (r == "") ? r : r.substr(1);
}
};
// Create the object array with the "id"
// Add as many as you want.
s.ob.push(new sObj('shopify.com'));
s.ob.push(new sObj('bigcommerce.com'));
s.ob.push(new sObj('woocommerce.com'));
// quick debug for testing
//for(var x in s.ob) {
// console.log('x:['+ x +']['+ s.ob[x].id +']['+ s.ob[x].found +']');
//}
// Our string to be tested
var data = "this is a .bigcommerce.com site";
// check if the data matches one of the sObj ids
s.find(data);
// get the results
console.log('result:['+ s.result() +']');
// And for a second test (2 results)
data = "can you shopify.com or woocommerce.com me?";
s.find(data);
console.log('result:['+ s.result() +']');
I added the code you suggested, thanks, but still not seeing anything on the targeted wordpress page- http://rpssolar.com/?page_id=1822. I think I am missing login information= or something else??
This is the code now:
// Includes functions for exporting active sheet or all sheets as JSON object (also Python object syntax compatible).
// Tweak the makePrettyJSON_ function to customize what kind of JSON to export.
var FORMAT_ONELINE = 'One-line';
var FORMAT_MULTILINE = 'Multi-line';
var FORMAT_PRETTY = 'Pretty';
var LANGUAGE_JS = 'JavaScript';
var LANGUAGE_PYTHON = 'Python';
var STRUCTURE_LIST = 'List';
var STRUCTURE_HASH = 'Hash (keyed by "id" column)';
/* Defaults for this particular spreadsheet, change as desired */
var DEFAULT_FORMAT = FORMAT_PRETTY;
var DEFAULT_LANGUAGE = LANGUAGE_JS;
var DEFAULT_STRUCTURE = STRUCTURE_LIST;
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [
{name: "Export JSON for this sheet", functionName: "exportSheet"},
{name: "Export JSON for all sheets", functionName: "exportAllSheets"},
{name: "Configure export", functionName: "exportOptions"},
];
ss.addMenu("Export JSON", menuEntries);
}
function exportOptions() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var app = UiApp.createApplication().setTitle('Export JSON');
var grid = app.createGrid(4, 2);
grid.setWidget(0, 0, makeLabel(app, 'Language:'));
grid.setWidget(0, 1, makeListBox(app, 'language', [LANGUAGE_JS, LANGUAGE_PYTHON]));
grid.setWidget(1, 0, makeLabel(app, 'Format:'));
grid.setWidget(1, 1, makeListBox(app, 'format', [FORMAT_PRETTY, FORMAT_MULTILINE, FORMAT_ONELINE]));
grid.setWidget(2, 0, makeLabel(app, 'Structure:'));
grid.setWidget(2, 1, makeListBox(app, 'structure', [STRUCTURE_LIST, STRUCTURE_HASH]));
grid.setWidget(3, 0, makeButton(app, grid, 'Export Active Sheet', 'exportSheet'));
grid.setWidget(3, 1, makeButton(app, grid, 'Export All Sheets', 'exportAllSheets'));
app.add(grid);
doc.show(app);
}
function makeLabel(app, text, id) {
var lb = app.createLabel(text);
if (id) lb.setId(id);
return lb;
}
function makeListBox(app, name, items) {
var listBox = app.createListBox().setId(name).setName(name);
listBox.setVisibleItemCount(1);
var cache = CacheService.getPublicCache();
var selectedValue = cache.get(name);
Logger.log(selectedValue);
for (var i = 0; i < items.length; i++) {
listBox.addItem(items[i]);
if (items[1] == selectedValue) {
listBox.setSelectedIndex(i);
}
}
return listBox;
}
function makeButton(app, parent, name, callback) {
var button = app.createButton(name);
app.add(button);
var handler = app.createServerClickHandler(callback).addCallbackElement(parent);;
button.addClickHandler(handler);
return button;
}
function makeTextBox(app, name) {
var textArea = app.createTextArea().setWidth('100%').setHeight('200px').setId(name).setName(name);
return textArea;
}
function exportAllSheets(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sheetsData = {};
for (var i = 0; i < sheets.length; i++) {
var sheet = sheets[i];
var rowsData = getRowsData_(sheet, getExportOptions(e));
var sheetName = sheet.getName();
sheetsData[sheetName] = rowsData;
}
var json = makeJSON_(sheetsData, getExportOptions(e));
return displayText_(json);
}
function exportSheet(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var rowsData = getRowsData_(sheet, getExportOptions(e));
var json = makeJSON_(rowsData, getExportOptions(e));
return displayText_(json);
}
function getExportOptions(e) {
var options = {};
options.language = e && e.parameter.language || DEFAULT_LANGUAGE;
options.format = e && e.parameter.format || DEFAULT_FORMAT;
options.structure = e && e.parameter.structure || DEFAULT_STRUCTURE;
var cache = CacheService.getPublicCache();
cache.put('language', options.language);
cache.put('format', options.format);
cache.put('structure', options.structure);
Logger.log(options);
return options;
}
function makeJSON_(object, options) {
if (options.format == FORMAT_PRETTY) {
var jsonString = JSON.stringify(object, null, 4);
} else if (options.format == FORMAT_MULTILINE) {
var jsonString = Utilities.jsonStringify(object);
jsonString = jsonString.replace(/},/gi, '},\n');
jsonString = prettyJSON.replace(/":\[{"/gi, '":\n[{"');
jsonString = prettyJSON.replace(/}\],/gi, '}],\n');
} else {
var jsonString = Utilities.jsonStringify(object);
}
if (options.language == LANGUAGE_PYTHON) {
// add unicode markers
jsonString = jsonString.replace(/"([a-zA-Z]*)":\s+"/gi, '"$1": u"');
}
return jsonString;
}
var JSON_DESTINATION_URL = 'http://rpssolar.com/?page_id=1822';
function sendJson_(json) {
var options = {
"contentType":"application/json",
"method" : "post",
"payload" : json
};
UrlFetchApp.fetch(JSON_DESTINATION_URL, options);
}function displayText_(text) {
var app = UiApp.createApplication().setTitle('Exported JSON');
app.add(makeTextBox(app, 'json'));
app.getElementById('json').setText(text);
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.show(app);
return app;
}
// getRowsData iterates row by row in the input range and returns an array of objects.
// Each object contains all the data for a given row, indexed by its normalized column name.
// Arguments:
// - sheet: the sheet object that contains the data to be processed
// - range: the exact range of cells where the data is stored
// - columnHeadersRowIndex: specifies the row number where the column names are stored.
// This argument is optional and it defaults to the row immediately above range;
// Returns an Array of objects.
function getRowsData_(sheet, options) {
var headersRange = sheet.getRange(1, 1, sheet.getFrozenRows(), sheet.getMaxColumns());
var headers = headersRange.getValues()[0];
var dataRange = sheet.getRange(sheet.getFrozenRows()+1, 1, sheet.getMaxRows(), sheet.getMaxColumns());
var objects = getObjects_(dataRange.getValues(), normalizeHeaders_(headers));
if (options.structure == STRUCTURE_HASH) {
var objectsById = {};
objects.forEach(function(object) {
objectsById[object.id] = object;
});
return objectsById;
} else {
return objects;
}
}
// getColumnsData iterates column by column in the input range and returns an array of objects.
// Each object contains all the data for a given column, indexed by its normalized row name.
// Arguments:
// - sheet: the sheet object that contains the data to be processed
// - range: the exact range of cells where the data is stored
// - rowHeadersColumnIndex: specifies the column number where the row names are stored.
// This argument is optional and it defaults to the column immediately left of the range;
// Returns an Array of objects.
function getColumnsData_(sheet, range, rowHeadersColumnIndex) {
rowHeadersColumnIndex = rowHeadersColumnIndex || range.getColumnIndex() - 1;
var headersTmp = sheet.getRange(range.getRow(), rowHeadersColumnIndex, range.getNumRows(), 1).getValues();
var headers = normalizeHeaders_(arrayTranspose_(headersTmp)[0]);
return getObjects(arrayTranspose_(range.getValues()), headers);
}
// For every row of data in data, generates an object that contains the data. Names of
// object fields are defined in keys.
// Arguments:
// - data: JavaScript 2d array
// - keys: Array of Strings that define the property names for the objects to create
function getObjects_(data, keys) {
var objects = [];
for (var i = 0; i < data.length; ++i) {
var object = {};
var hasData = false;
for (var j = 0; j < data[i].length; ++j) {
var cellData = data[i][j];
if (isCellEmpty_(cellData)) {
continue;
}
object[keys[j]] = cellData;
hasData = true;
}
if (hasData) {
objects.push(object);
}
}
return objects;
}
// Returns an Array of normalized Strings.
// Arguments:
// - headers: Array of Strings to normalize
function normalizeHeaders_(headers) {
var keys = [];
for (var i = 0; i < headers.length; ++i) {
var key = normalizeHeader_(headers[i]);
if (key.length > 0) {
keys.push(key);
}
}
return keys;
}
// Normalizes a string, by removing all alphanumeric characters and using mixed case
// to separate words. The output will always start with a lower case letter.
// This function is designed to produce JavaScript object property names.
// Arguments:
// - header: string to normalize
// Examples:
// "First Name" -> "firstName"
// "Market Cap (millions) -> "marketCapMillions
// "1 number at the beginning is ignored" -> "numberAtTheBeginningIsIgnored"
function normalizeHeader_(header) {
var key = "";
var upperCase = false;
for (var i = 0; i < header.length; ++i) {
var letter = header[i];
if (letter == " " && key.length > 0) {
upperCase = true;
continue;
}
if (!isAlnum_(letter)) {
continue;
}
if (key.length == 0 && isDigit_(letter)) {
continue; // first character must be a letter
}
if (upperCase) {
upperCase = false;
key += letter.toUpperCase();
} else {
key += letter.toLowerCase();
}
}
return key;
}
// Returns true if the cell where cellData was read from is empty.
// Arguments:
// - cellData: string
function isCellEmpty_(cellData) {
return typeof(cellData) == "string" && cellData == "";
}
// Returns true if the character char is alphabetical, false otherwise.
function isAlnum_(char) {
return char >= 'A' && char <= 'Z' ||
char >= 'a' && char <= 'z' ||
isDigit_(char);
}
// Returns true if the character char is a digit, false otherwise.
function isDigit_(char) {
return char >= '0' && char <= '9';
}
// Given a JavaScript 2d Array, this function returns the transposed table.
// Arguments:
// - data: JavaScript 2d Array
// Returns a JavaScript 2d Array
// Example: arrayTranspose([[1,2,3],[4,5,6]]) returns [[1,4],[2,5],[3,6]].
function arrayTranspose_(data) {
if (data.length == 0 || data[0].length == 0) {
return null;
}
var ret = [];
for (var i = 0; i < data[0].length; ++i) {
ret.push([]);
}
for (var i = 0; i < data.length; ++i) {
for (var j = 0; j < data[i].length; ++j) {
ret[j][i] = data[i][j];
}
}
return ret;
}
Instead of displaying the text via the displayText_() function, define a new function which POSTS the JSON to your destination.
var JSON_DESTINATION_URL = 'http://requestb.in/1gngj131';
function sendJson_(json) {
var options = {
"contentType":"application/json",
"method" : "post",
"payload" : json
};
UrlFetchApp.fetch(JSON_DESTINATION_URL, options);
}
If you still want to see the popup of text, just call this function before you call displayText_().
I'm assuming you want to POST this data. If you want to use another HTTP method, see the "method" section and related examples in the docs:
https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app
I'm really new to JS, and I'm now stuck on a task, hope someone can guide me through it.
I have an Array of Objects, like this one:
var labels = [
// labels for pag 1
{pageID:1, labels: [
{labelID:0, content:[{lang:'eng', text:'Txt1 Eng'}, {lang:'de', text:'Txt1 De:'}]},
{labelID:1, content:[{lang:'eng', text:'Txt 2 Eng:'}, {lang:'de', text:'Txt2 De:'}]},
{labelID:2, content:[{lang:'eng', text:'Txt 3 Eng:'},{lang:'de', text:'Txt 3 De:'}]}
]},
// labels for pag 2
{pageID:2, labels: [
{labelID:0, content:[{lang:'eng', text:'Txt1 Eng'}, {lang:'de', text:'Txt1 De:'}]},
{labelID:1, content:[{lang:'eng', text:'Txt 2 Eng:'}, {lang:'de', text:'Txt2 De:'}]},
{labelID:2, content:[{lang:'eng', text:'Txt 3 Eng:'},{lang:'de', text:'Txt 3 De:'}]}
]}
]
What I am trying to do is write a function to return me an array of labels (Objects) for a specific page and a specific lang. By calling this function specifying pageID 1 and lang eng, I'm basically trying to build an array like this one:
var desideredArray = [
{labelID:0, text:'Txt1 Eng'},
{labelID:1, text:'Txt1 Eng'},
{labelID:2, text:'Txt2 Eng'}
]
Now, I'm trying to write the function to retrieve/build the new array:
this.getLabelsForPageAndLang = function (numPage, lang) {
// this part filters the main object and selects the object with pageID == numPage
var result = labels.filter(function( obj ) {
return obj.pageID == numPage;
});
var tempResult = result[0].labels;
var desiredResults = []; // here I want to store the new objects
for (var i=0; i<tempResult.length; i++) {
var simpleLabelObject = {};
simpleLabelObject.labelID = tempResult[i].labelID;
// simpleLabelObject.text = ?????
results[i] = simpleLabelObject;
}
console.log (results);
};
...but how can I access the right value (the one corresponding the lang selected) in the content property?
You can use the same technique as the one used to keep the matching page: the filter method.
this.getLabelsForPageAndLang = function (numPage, lang) {
// this part filters the main object and selects the object with pageID == numPage
var result = labels.filter(function( obj ) {
return obj.pageID == numPage;
});
var contentFilter = function(obj){ return obj.lang === lang};
var tempResult = result[0].labels;
var desiredResults = []; // here I want to store the new objects
for (var i=0; i<tempResult.length; i++) {
var simpleLabelObject = {};
simpleLabelObject.labelID = tempResult[i].labelID;
var matching = tempResult[i].content.filter(contentFilter);
simpleLabelObject.text = matching[0].text;
desiredResults[i] = simpleLabelObject;
}
console.log (desiredResults);
};
I didn't do bound checks because in your code you assumed there is always a matching element, but it would probably be wise to do it.
And if you want to avoid creating two closures each time the function is called, you can prototype an object for that:
var Filter = function(numPage, lang) {
this.numPage = numPage;
this.lang = lang;
};
Filter.prototype.filterPage = function(obj) {
return obj.pageID === this.numPage;
}
Filter.prototype.filterLang = function(obj) {
return obj.lang === this.lang;
}
Filter.prototype.filterLabels = function(labels) {
var result = labels.filter(this.filterPage, this);
var tempResult = result[0].labels;
var desiredResults = []; // here I want to store the new objects
for (var i=0; i<tempResult.length; i++) {
var simpleLabelObject = {};
simpleLabelObject.labelID = tempResult[i].labelID;
var matching = tempResult[i].content.filter(this.filterLang, this);
simpleLabelObject.text = matching[0].text;
desiredResults[i] = simpleLabelObject;
}
return desiredResults;
}
console.log(new Filter(1, "eng").filterLabels(labels));
Just filter again:
var getLabelsForPageAndLang = function (numPage, lang) {
// this part filters the main object and selects the object with pageID == numPage
var result = labels.filter(function (obj) {
return obj.pageID == numPage;
});
var tempResult = result[0].labels;
var desiredResults = []; // here I want to store the new objects
for (var i = 0; i < tempResult.length; i++) {
var simpleLabelObject = {};
simpleLabelObject.labelID = tempResult[i].labelID;
var lg = tempResult[i].content.filter(function (lg) {
return lg.lang == lang;
});
simpleLabelObject.text = lg[0].text;
desiredResults.push(simpleLabelObject);
}
console.log(desiredResults);
};
http://jsfiddle.net/9q5zF/
A rather 'safe' implementation for cases when pages have the same pageID and multiple contents with the same lang:
this.getLabelsForPageAndLang = function(numPage, lang) {
var result = [];
var pages = labels.filter(function( obj ) {
return obj.pageID === numPage;
});
for (var p = pages.length - 1; p >= 0; p--) {
var page = pages[p];
for(var i = page.labels.length - 1; i >= 0; i--) {
var labelId = page.labels[i].labelID;
for (var j = page.labels[i].content.length - 1; j >= 0; j--){
if (page.labels[i].content[j].lang === lang) {
result.push({labelID: labelId, test: page.labels[i].content[j].text});
}
}
}
}
console.log(result);
}
Fiddle: http://jsfiddle.net/6VQUm/
I've been playing around with javascript and casperjs. I have the following lines of code.
casper.thenOpen('somesite', function() {
console.log('clicked ok, new location is ' + this.getCurrentUrl());
// Get info on all elements matching this CSS selector
var town_selector = 'div tr';
var town_names_info = this.getElementsInfo(town_selector); // an array of object literals
// Pull out the town name text and push into the town_names array
var town_names = [];
for (var i = 0; i < town_names_info.length; i++) {
town_names.push(town_names_info[i].text.trim());}
// Dump the town_names array to screen
utils.dump(town_names);
casper.capture('capture5.png');
});
my output is this.
[
"Address:\n \n address",
"City:\n \ncity",
"State:\n \nstate",
"Zip:\n \nzip",
]
how can I make it json? like this.
{
"Address":"address",
"City":"city",
"State":"state",
"Zip":"zip"
}
Thanks in advance.
You can use something like this:
function arrayToObject(arr) {
var out = {};
arr.forEach(function (element) {
var keyvalue = element.replace(/[\n\s]+/, '').split(':');
var key = keyvalue[0];
var value = keyvalue[1];
out[key] = value;
});
return out;
}
then you can do:
var json = JSON.stringify(arrayToObject(myArray));
Update:
> How can I change this to split only the first occurrence of colon?
Use this:
arr.forEach(function (element) {
var keyvalue = element.replace(/[\n\s]+/, '');
var key = keyvalue.substring(0, element.indexOf(':'));
var value = keyvalue.substring(key.length + 1);
out[key] = value;
});