Newline in Google spreadsheet not outputting in Google chart table - google-sheets

This code works perfectly except for a small formatting issue I can't find an easy way to fix. The google spreadsheet as the datasource has newline in the columns. However, in the table it looks as if they are simply formatted by spaces. I've tried using the allowHthml option in the data table (after converting the newlines to tags) but that then removes all formatting and makes the table look terrible. I've also tried the "Formatter" class but that seems more driven to concatenation of fields and also lives by the same no-html rule.
Anyone know of something i'm missing here that can get the newline to show properly in the table without breaking the formatting. I want to simply add the newlines into the fields so they display properly.
You can copy/paste this right into jsLint and it will run and show you what i'm talking about.
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1', {packages: ['table']});
</script>
<script type="text/javascript">
function drawVisualization() {
var opts = {dataType:'jsonp'};
var query = new google.visualization.Query('https://docs.google.com/spreadsheet/pub?key=0AiEVKSSB6IaqdDZBTGJqV0lLZEV3YS0teXZkOWR4M3c&output=html', opts);
query.setQuery("select * ");
// Send the query with a callback function.
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
// Create and populate the data table.
var data = response.getDataTable();
// Create and draw the visualization.
visualization = new google.visualization.Table(document.getElementById('table'));
visualization.draw(data, null);
}
google.setOnLoadCallback(drawVisualization);
​

This may be a bit of a hacky solution but how about using a JavaScript method to replace all line breaks in a string with <br /> tags? I also added a small amount of CSS so that the new table has bottom vertical alignment (like the original Spreadsheet would have).
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1', {packages: ['table']});
</script>
<script type="text/javascript">
function drawVisualization() {
var opts = {dataType:'jsonp'};
var query = new google.visualization.Query('https://docs.google.com/spreadsheet/pub?key=0AiEVKSSB6IaqdDZBTGJqV0lLZEV3YS0teXZkOWR4M3c&output=html', opts);
query.setQuery("select * ");
// Send the query with a callback function.
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
// Create and populate the data table.
var data = new google.visualization.DataTable(
response.getDataTable().toJSON().split("\\n").join("<br />"));
var opts = {'allowHtml': true};
// Create and draw the visualization.
visualization = new google.visualization.Table(document.getElementById('table'));
visualization.draw(data, opts);
}
google.setOnLoadCallback(drawVisualization);
</script>
<style type="text/css">
.google-visualization-table-td{
vertical-align: bottom;
}
</style>
<div id="table"></div>

Related

vaadin-grid-filter for an Array of Strings not working

I am using the vaadin-grid-filter with Polymer 2.x and I am facing the following problem.
I have a vaadin-grid-column as following,
<vaadin-grid-column width="15em">
<template class="header">
<vaadin-grid-filter aria-label="Inventory" path="" value="[[_filterItems]]">
<vaadin-text-field slot="filter" placeholder="Item" value="{{_filterItems}}" focus-target></vaadin-text-field>
</vaadin-grid-filter>
</template>
<template>[[item]]</template>
</vaadin-grid-column>
[[item]] is an array of strings and the filtering doesn't work when the path is set to an empty string.
If I put each string inside a Json object and access it as in the documentation, then it works fine.
But I am wondering whether there is a way I can filter this as it is.
Thank you in advance.
I did some digging into the vaadin-grid source code and found some less than ideal answers. Unfortunately there doesn't seem to be any "magic" placeholders for the path property value that will get you what you want in the context of using the "x-array-data-provider" component for [[item]]. Here are a couple values I tried and their results:
"" : the filtering mechanism attempts to retrieve the item[""] property for string comparison. Unfortunately item[""] will be undefined and the comparison will fail to match.
null/undefined : there is a check for this very early on in the logic that will abort any filtering process as a whole.
So unfortunately due to the lack of any self-referencing object property (that I'm aware of) available in the default JS objects, I was unable to circumvent the property accessor in a way to get what you want.
I did however find a potential workaround in the context of using a server data provider. Using the vaadin-grid-filter example (from vaadin) here, it appears as though the filtering request can be serialized and sent to the server. If you have full control over the internals of the remote server data provider code then you could write your own custom filtering mechanism there to accomplish what you want. Here is the code from the example (in case of removal):
<x-remote-filtering-example></x-remote-filtering-example>
<dom-module id="x-remote-filtering-example">
<template>
<vaadin-grid aria-label="Filtering with Data Provider Example" id="grid">
<vaadin-grid-column width="50px" flex-grow="0">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template class="header">
<vaadin-grid-filter aria-label="Fist Name" path="firstName" value="[[_filterFirstName]]">
<input placeholder="First Name" value="{{_filterFirstName::input}}" focus-target>
</vaadin-grid-filter>
</template>
<template>[[item.firstName]]</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template class="header">
<vaadin-grid-filter aria-label="Last Name" path="lastName" value="[[_filterLastName]]">
<input placeholder="Last Name" value="{{_filterLastName::input}}" focus-target>
</vaadin-grid-filter>
</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
</vaadin-grid>
</template>
<script>
addEventListener('WebComponentsReady', function() {
Polymer({
is: 'x-remote-filtering-example',
ready: function() {
var grid = this.$.grid;
grid.size = 200;
grid.dataProvider = function(params, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var response = JSON.parse(xhr.responseText);
// Number of items changes after filtering. We need
// to update the grid size based on server response.
grid.size = response.size;
callback(response.result);
};
var index = params.page * params.pageSize;
var url = 'https://demo.vaadin.com/demo-data/1.0/people?index=' + index + '&count=' + params.pageSize;
// `params.filters` format: [{path: 'lastName', direction: 'asc'}, ...];
params.filters.forEach(function(filter) {
url += '&filters[' + filter.path + ']=' + encodeURIComponent(filter.value);
});
xhr.open('GET', url, true);
xhr.send();
};
}
});
});
</script>
</dom-module>

How do I pass a JSON array to a JavaScript variable on my GSP page?

I have the following Controller Action:
def doSomething() {
[data: data as JSON]
}
On my GSP I can output the data params with:
${data}
Since data represents valid JSON I want to use it inside a JavaScript block on my GSP.
<script type="text/javascript">
var data = [
{ Date: "2015-09-14", DayOfMonth: 14, Type: "Views", Amount: 0, y1: 10, }
];
</script>
To replace a hard coded JSON variable. I know I can do the replacement with Strings like this:
<script type="text/javascript">
var data = "${data}";
</script>
or
<script type="text/javascript">
var data = "${raw(data)}";
</script>
The former works fine work primitive types like Strings but if I pass the JSON Array to the JavaScript variable it fails. When I print the content of the JavaScript data variable in the console I get:
[{"Date":"2015-09-13T22:00:00Z","DayOfMonth":14,"Type":"Views","Amount":1}]
How do I pass a JSON array to a JavaScript variable on my GSP page?
It appears to be an encoding problem that has yet to be resolved.
Solution 1 - disable encoder locally
<g:applyCodec encodeAs="none">
var data = ${data};
</g:applyCodec>
Solution 2 - Affects the whole page
<%#page defaultCodec="none" %>
Solution 3 - Use a custom tag
class MyTagLib {
static defaultEncodeAs = [taglib:'none']
def writeWithoutEncoding = {attrs ->
out << attrs.input
}
}
and in the GSP page:
var data = <g:writeWithoutEncoding input="${data}"/>;
References: https://jira.grails.org/browse/GRAILS-11829 and http://aruizca.com/how-to-render-json-properly-without-escaping-quotes-inside-a-gsp-script-tag/

Absolute paths to Trigger.io assets?

We're building a Trigger app with Chaplin underneath. It would be nice, for development purposes, if we could use absolute paths to our assets, a la:
<link rel="stylesheet" href="/_forge/stylesheets/app.css">
<script src="/_forge/javascripts/vendor.js"></script>
<script src="/_forge/javascripts/app.js"></script>
Is it possible to do this in Trigger?
Unfortunately different platforms have different URLs on Trigger (due to them having their own features and limitations).
If you want to get absolute paths you can use the file module and do something along the lines of:
forge.file.getLocal("js/app.js", function (file) {
forge.file.URL(file, function (url) {
$('body').append('<script src="'+url+'"></script>');
});
});
I'm not sure why an absolute path is useful though, I would recommend only using one html page (index.html) as navigating to a new page is slower on the phone than changing the dom using javascript. In which case all of your relative paths should always be the same.
The easiest thing might be to detect the whether or not forge is present in your index.html and load the javascript accordingly:
<script type="text/javascript">
function addScript(src, callback) {
var tag = document.createElement('script');
tag.type = 'text/javascript';
tag.src = src;
tag.onload = callback;
document.getElementsByTagName('head')[0].appendChild(tag);
}
var vendor = "javascripts/vendor.js";
var app = "javascripts/app.js";
if(window.forge === undefined) {
vendor = "/"+vendor;
app = "/"+app;
}
addScript(vendor, function() {
addScript(app, function() {
require('initialize');
});
});
</script>

Phonegap and jquery mobile : a href -> Origin null is not allowed by Access-Control-Allow-Origin

Im trying to use jquery mobile with phonegap, in a multi-page document.
Tring to use basic href links within the document, gives the Origin null is not allowed by Access-Control-Allow-Origin error which is quite annoying.
This is because the index page is refered to via file:// rather than http:// which webkit interprets as origin null. Has anyone got jquery mobile and phonegap to work in a multi page environment? if so how can you do it? If you add rel=external to the href tags the links work, but of course all the transitions are lost.
Cant find any info on this specific problem on stack overflow or teh internetz.
<!DOCTYPE HTML>
<html>
<head>
<title>PhoneGap</title>
<script type="text/javascript" charset="utf-8" src="phonegap-1.2.0.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script>
$(document).bind( "mobileinit", function(){
//alert("mobileinit fired");
$.support.cors = true;
$.mobile.allowCrossDomainPages = true;
});
</script>
<script src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script>
<script type="text/javascript">
function onDeviceReady() {
navigator.network.isReachable("google.com", reachableCallback, {});
}
// Check network status
function reachableCallback(reachability) {
// There is no consistency on the format of reachability
var networkState = reachability.code || reachability;
var states = {};
states[NetworkStatus.NOT_REACHABLE] = 'No network connection';
states[NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK] = 'Carrier data connection';
states[NetworkStatus.REACHABLE_VIA_WIFI_NETWORK] = 'WiFi connection';
if (networkState != 0) online = true;
}
var online = navigator.onLine || false;
$(document).ready(function() {
$(document).bind('deviceready', function(){
onDeviceReady()
})
// Your main code
})
//Now if you about to make an AJAX call to load up some dynamic data, you can easily check to see if you're online
if(online) {
} else {
}
</script>
</head>
<body>
<h1>Welcome to PhoneGap</h1>
Edit html
</body>
</html>
Here's the official documentation on how to do just what you are looking for...
Hope this helps!
Leon's comment is the correct answer - you need to add rel="external" to static links.
To Test
Download mongoose http server
copy mongoose_xxxxxxx.exe file to your assets/www
Now you can design your html pages for jquery mobile without Access-Control-Allow-Origin
I think you can find the solution here: http://view.jquerymobile.com/master/demos/faq/how-configure-phonegap-cordova.php
$.mobile.allowCrossDomainPages = true;
$.support.cors = true;
$.mobile.phonegapNavigationEnabled = true
Although I have not gotten it to work, I think that here are the solution.
if you are targeting app above JELLY_BEAN(API Level 16), here is what you can add to MainActivity class.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
super.appView.getSettings().setAllowUniversalAccessFromFileURLs(true);
}
Which will allow null origin XHR requests.

How to add upload utility to wmd editor?

Has anyone succeeded to do this?
I accomplished this by replacing Util.prompt with my own jquery.dialog method. The prompt function takes a parameter as a callback, making it easy to create a drop-in replacement.
if (isImage) {
// OLD: util.prompt(imageDialogText, imageDefaultText, makeLinkMarkdown);
// WMD_IMAGE_GALLERY_URL loaded from a global settings elsewhere
util.imageGallery(WMD_IMAGE_GALLERY_URL, makeLinkMarkdown);
}
else {
util.prompt(linkDialogText, linkDefaultText, makeLinkMarkdown);
}
If you're interested, I wrote a blog entry about it (with pictures!) which has some more sample code as well as some of the problems/solutions I encountered in implementing this.
The following hack requires use of jQuery, jQuery UI and Mike Alsup's jQuery Form Plugin for performing AJAX file uploads. The hack works with the linked versions (jQ 1.7.2 and jQUI 1.8.20). I can't guarantee compatibility with other versions.
In your <head>, you'll need to include the dependencies:
<script type='text/javascript' src='jquery.min.js'></script>
<link href='theme/jquery-ui.css' rel='stylesheet' type='text/css' />
<script type='text/javascript' src='jquery-ui.js'></script>
<script type='text/javascript' src='wmd/showdown.js'></script>
<script type='text/javascript' src='wmd/wmd.js'></script>
<link type='text/css' rel='stylesheet' href='wmd/wmd.css'/>
<script type='text/javascript' src='jquery.form.js'></script>
We actually need to make a single change to wmd.js.
Go on in there and search (ctrl+f) for var form = doc.createElement("form");
Immediately following this line, assign the form an id, dialogform will do: form.id = "dialogform";
Now on the front end, run:
$(document).ready(function(){
$("#wmd-image-button").live("click",function(){
setTimeout(function(){
$(".wmd-prompt-dialog").css({"opacity": "0", display: "none"});
}, 100);
var $div = $("<div>");
var $form = $("<form>").attr({action: "submit_image.php", method: "post"})
var $file = $("<input/>").attr({type: "file", name: "image"});
var $name = $("<input/>").attr({type: "text", name: "name", placeholder: "Name"});
var $submit = $("<input/>").attr("type", "submit");
$form.append($name, $file, $submit).ajaxForm(function(r) {
r = $.parseJSON(r);
if(r.success){
$("#dialogform input[type='text']").val(r.filename);
$("#dialogform input[value='OK']").trigger("click");
$div.dialog("close");
}
});
$div.append($form).dialog({title: "Upload Image"});
});
$("#wmd-link-button").live("click", function(){
setTimeout(function(){
$(".wmd-prompt-dialog").css("opacity", "1");
}, 100);
});
});
Remember, the post was written for jQuery 1.7.2, and live() has since been deprecated. Please switch to on() if you're using a more recent version of jQuery
And on the backend, in submit_image.php:
$f = $_FILES['image'];
$p = $_POST;
$allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF);
$detectedType = exif_imagetype($f['tmp_name']);
if(in_array($detectedType, $allowedTypes)){
$pi = pathinfo($f['name']);
$ext = $pi['extension'];
$target = "img/" . strtolower(str_replace(" ", "-", $p['name'])) . "." . $ext;
if(move_uploaded_file($f['tmp_name'], $target)){
$returnArr = array(
"success" => true,
"filename" => site_url($target)
);
echo json_encode($returnArr);
}
else echo json_encode(array("success" => false));
}
else echo json_encode(array("success" => false, "msg" => "Invalid File Type."));
Hopefully that will get you started. This was written a couple of years ago, when my javascript skills were sub-par! Haha. I previously had this on a blog (which is now dead), with step-by-step instructions and explanations; lots of unnecessary fluff. Thanks #Kamiccolo for bringing this link to my attention. I had to consult the way-back-machine in order to revive it.
Add a button to the control panel of WMD.
Search for the following string to find the place where buttons are being added:
italicButton.XShift
In my version, the function is in class SpritedButtonRow and is called build.
Ignore the setup and textOp attributes. XShift is the position of the button image in the css sprite that comes with WMD, Instead of that, give the button a class and in the class specify the background image. Then Just add an onclick event to the button
that will do what you need it to do.
But, I don't think an upload button should be inside a text editor, does not make sense.

Resources