Implementing Search on a JqxTree using JqxdataAdapter Plugin..? - dataadapter

I am trying to implement a Search Over a JqxTree in which i am populating data with the help of JSON.
I want to implement the Search in a way that when i enter a string in a textbox the tree should expand till that component.
Can anyone help me out with this.
Following is my jsp code:-
<link rel="stylesheet" href="<%=request.getContextPath()%>/css/jqwidgets/styles/jqx.base.css" type="text/css" />
<script type="text/javascript" src="<%=request.getContextPath()%>/scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/scripts/demos.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxcore.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxdata.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxbuttons.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxscrollbar.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxpanel.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jqwidgets/jqxtree.js"></script>
</head>
<body>
<div id='content' style='float: right;'>
<script type="text/javascript">
$(document).ready(function () {
$('#ExpandAll').jqxButton({ height: '25px', width: '100px'});
$('#CollapseAll').jqxButton({ height: '25px', width: '100px'});
// Expand All
$('#ExpandAll').click(function () {
$('#jqxWidget').jqxTree('expandAll');
});
//Collapse All
$('#CollapseAll').click(function () {
$('#jqxWidget').jqxTree('collapseAll');
});
var data = <%=request.getAttribute("data")%>
// prepare the data
var source =
{
datatype: "json",
datafields: [
{ name: 'categoryId' },
{ name: 'parentId' },
{ name: 'categoryName' },
],
id: 'categoryId',
localdata: data
};
// create data adapter.
var dataAdapter = new $.jqx.dataAdapter(source);
// perform Data Binding.
dataAdapter.dataBind();
// Get the tree items.
//The 1st parameter is the item's id.
//The 2nd parameter is the parent item's id.
//The 'items' parameter represents the sub items collection name.
//Each jqxTree item has a 'label' property, but in the JSON data, we have a 'text' field.
//The last parameter specifies the mapping between the 'text' and 'label' fields.
var records = dataAdapter.getRecordsHierarchy('categoryId', 'parentId', 'items', [{ name: 'categoryName', map: 'label'}]);
$('#jqxWidget').jqxTree({ source: records, width: '500px'});
});
</script>
</div>
<!-- DIV COMPONENTS -->
<div style='margin-top: 10px;'>
<input type="button" id='ExpandAll' value="Expand All" />
</div>
<div style='margin-top: 10px;' >
<input type="button" id='CollapseAll' value="Collapse All" />
</div><br/>
<div id='jqxWidget'>
</div>
</body>
</html>
Please Help me out..!! :)

Here's how I achieved It
$("#btnSearchTree").on('click', function () {
//Setting current selected item as null
$('#jqxWidget').jqxTree('selectItem', null);
//collapsing tree(in case if user has already searched it )
$('#jqxWidget').jqxTree('collapseAll');
//Using span for highlighting text so finding earlier searched items(if any)
var previousHighlightedItems = $('#jqxWidget').find('span.highlightedText');
// If there are some highlighted items, replace the span with its html part, e.g. if earlier it was <span style="background-color:"Yellow">Te></span>st then it will replace it with "Te""st"
if (previousHighlightedItems && previousHighlightedItems.length > 0) {
var highlightedText = previousHighlightedItems.eq(0).html();
$.each(previousHighlightedItems, function (idx, ele) {
$(ele).replaceWith(highlightedText);
});
}
//Getting all items for jqxTree
var items = $('#jqxWidget').jqxTree("getItems");
//Getting value for input search box and converting it to lower for case insensitive(may change)
var searchedValue = $("#ipSearchTreeText").val().toLowerCase();
//Searching the text in items label
for (var i = 0; i < items.length; i++) {
if (items[i].label.toLowerCase().indexOf(searchedValue) > -1) {
//If found expanding the tree to that item
$('#jqxWidget').jqxTree('expandItem', items[i].parentElement);
//selecting the item : not necessary as it selects the last item if multiple occurrences are found
$('#jqxWidget').jqxTree('selectItem', items[i]);
//changing the innerhtml of found item and adding span with highlighted color
var itemLabelHTML = $(items[i].element).find('div').eq(0).html();
//splitting the item text so that only searched text
can be highlighted by appending span to it.
var splittedArray = itemLabelHTML.split(searchedValue);
var highlightedText = '';
//if there are multiple occurrences of same searched text then adding span accordingly
for (var j = 0; j < splittedArray.length; j++) {
if (j != splittedArray.length - 1)
highlightedText = highlightedText + splittedArray[j] + '<span class="highlightedText" style="background-color:yellow">' + searchedValue + '</span>';
else
highlightedText = highlightedText + splittedArray[j];
}
//var highlightedText = splittedArray[0] + '<span style="background-color:yellow">' + searchedValue + '</span>' + splittedArray[1];
//replacing the item html with appended styled span
$(items[i].element).find('div').eq(0).html(highlightedText);
}
};
});

Related

Convert Excel form window to Google Sheets window

As you've probably found, there appears to be no equivalent way to add the following Excel form and associated VBA code to Google Sheets or Scripts or Forms:
Is there some add-in that can be used to pop up this image and its controls? This has to be used many times in an accounting sheet to categorize expenditures at tax time.
It may not look exactly the same but I was able to construct a custom dialog in a short period of time to show how HTML service can be used to produce similar results.
First I construct an HTML template that contains the 2 combo boxes with multiple lines.
HTML_Test.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<?!= include('CSS_Test'); ?>
</head>
<body>
<div id="left">
<label for="expenseCategory">Expense Category</label><br>
<select id="expenseCategory" size="10">
</select>
</div>
<div id="middle">
<label for="expenseSubCategory">Expense Sub Category</label><br>
<select id="expenseSubCategory" size="10">
</select>
</div>
<?!= include('JS_Test'); ?>
</body>
</html>
Then a CSS file to contain all my element formatting.
CSS_Test.html
<style>
#expenseCategory {
width: 90%;
}
#expenseSubCategory {
width: 90%;
}
#left {
width: 25%;
float: left;
}
#middle {
width: 50%;
float: left;
}
</style>
And a javascript file for client side javascript. I've simply hard coded some data to show how the select elements are filled in but this could just as easily be done using template scripting, or google.script.run
<script>
var expenses = [["A","1","2","3"],
["B","4","5"],
["C","6","7","8","9","10"]
];
function expenseCategoryOnClick() {
try {
let expenseCategory = document.getElementById('expenseSubCategory');
expenseCategory.options.length = 0;
expenses[this.selectedIndex].forEach( (expense,index) => {
if( index > 0 ) {
let option = document.createElement("option");
let text = document.createTextNode(expense);
option.appendChild(text);
expenseCategory.appendChild(option);
}
}
);
}
catch(err) {
alert("Error in expenseCategoryOnClick: "+err)
}
}
(function () {
// load first expense
let expenseCategory = document.getElementById('expenseCategory');
expenseCategory.addEventListener("click",expenseCategoryOnClick);
expenses.forEach( expense => {
let option = document.createElement("option");
let text = document.createTextNode(expense[0]);
option.appendChild(text);
expenseCategory.appendChild(option);
}
);
expenseCategory = document.getElementById('expenseSubCategory');
expenses[0].forEach( (expense,index) => {
if( index > 0 ) {
let option = document.createElement("option");
let text = document.createTextNode(expense);
option.appendChild(text);
expenseCategory.appendChild(option);
}
}
);
}
)();
</script>
Then there is the server side code bound to a spreadsheet.
Code.gs
function onOpen(e) {
var menu = SpreadsheetApp.getUi().createMenu("Test");
menu.addItem("Show Test","showTest");
menu.addToUi();
}
// include(filename) required to include html files in the template
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
function showTest() {
var html = HtmlService.createTemplateFromFile("HTML_Test");
html = html.evaluate();
html.setWidth(800);
SpreadsheetApp.getUi().showModalDialog(html,"Test");
}
The dialog looks like this. Many more html elements can be added as needed. This just shows the basics. This may be more difficult than an wysiwig html editor but I find I have better control of the appearance and function of my pages this way. Notice I clicked "C" and the sub category is filled in automatically.

google charts - data from csv - date format

In a webpage I load data from a csv file that contains like (it can contains months of data) :
timestamp,open,high,low,close
2022-08-03,1.01554,1.02105,1.01210,1.01618
2022-08-02,1.02578,1.02939,1.01619,1.01625
2022-08-01,1.02182,1.02753,1.02040,1.02587
2022-07-29,1.01952,1.02544,1.01440,1.02248
2022-07-28,1.02005,1.02344,1.01120,1.01947
2022-07-27,1.01174,1.02209,1.00950,1.01998
2022-07-26,1.02210,1.02502,1.01060,1.01179
2022-07-25,1.02174,1.02579,1.01770,1.02200
The first column is a date, but I think the google chart treat it like a string while creating the chart.
This is the code in html page I use to load data from csv and to create the chart:
<!DOCTYPE html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="jquery.csv-0.71.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>
// load the visualization library from Google and set a listener
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
</script>
<script>
function drawVisualization() {
$.get("EURUSD.csv", function(csvString) {
// transform the CSV string into a 2-dimensional array
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar});
// this new DataTable object holds all the data
var data = new google.visualization.arrayToDataTable(arrayData);
var view = new google.visualization.DataView(data);
//view.setColumns([0,1]);
var options = {
legend: 'none',
title: 'EURUSD',
bar: { groupWidth: '100%' }, // Remove space between bars.
candlestick: {
fallingColor: { strokeWidth: 0, fill: '#a52714' }, // red
risingColor: { strokeWidth: 0, fill: '#0f9d58' } // green
}
};
var chart = new google.visualization.CandlestickChart(document.getElementById('chart_div'));
data.sort({column: 0, asc: true});
chart.draw(data, options);
});
}
google.setOnLoadCallback(drawVisualization)
</script>
<div id="chart_div" style="width: 900px; height: 500px;"></div>
enter code here
The chart I get is:
I would like to group by month or by year in the X asses, insted of everyday date printed there.
How can I do?
Thank You
Carlo
after you load the csv data...
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar});
convert the first column to a date...
arrayData = arrayData.map(function (row) {
row[0] = new Date(row[0]);
return row;
});

Google Visualization Chart Data Range

I have this code,
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", '1', {packages:['corechart']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var query = new google.visualization.Query(
'https://docs.google.com/spreadsheets/d/1ntnhvfMhYtFNwFjkoKu8cUZOQPCaT5_U1Z6piB_w0-E/edit#gid=0');
query.setQuery('order by A');
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var options = {
title: 'TEMP & HUMID',
hAxis: {
direction: -1
},
legend: 'none'
};
var data = response.getDataTable();
var chart = new google.visualization.LineChart(document.getElementById('columnchart'));
chart.draw(data, options);
}
</script>
<title>Data from a Spreadsheet</title>
</head>
<body>
<div id="columnchart" style="width: 900px; height: 500px"></div>
</body>
</html>
And here is my spreadsheet data: https://docs.google.com/spreadsheets/d/1ntnhvfMhYtFNwFjkoKu8cUZOQPCaT5_U1Z6piB_w0-E
What I want to do is to plot last 5 data. i.e) row 8 - 12 in my spreadsheet.
I tried the limit and range queries, but what I want to do is, if a new data comes in, I want the chart to refer the updated last 5 data i.e) row 9 -13
How could I achieve this?
I don't know if this is a best approach, but I work it out.
So, before drawing the table, I actually called the spreadsheet in JSON format and retrieve its column length.
Then I subtracted the column length by number of data I want to display (limit query) which will give me offset to start.
Then I made a string with the value of limit and offset to pass the query option to query.setQuery.
Here is the code for the part.
function drawChart() {
var query = new google.visualization.Query(
'https://docs.google.com/spreadsheets/d/1NSEbUWojJsMzhH0hi8kx8ic7Xxuq29z0c7BXs-inzb8/edit#gid=0');
$.getJSON("https://spreadsheets.google.com/feeds/list/1NSEbUWojJsMzhH0hi8kx8ic7Xxuq29z0c7BXs-inzb8/od6/public/basic?hl=en_US&alt=json", function(data) {
colLen = data.feed.entry.length;
console.log(colLen);
limit = 4;
var offset = colLen - limit;
console.log(offset);
queryOption = "limit "+limit+" offset "+offset;
console.log(queryOption);
query.setQuery(queryOption);
query.send(handleQueryResponse);
});
}

Add tooltips to a Google Line Chart with multiple data series - with simplified test case and screenshot

I have a Google Line Chart with 2 data series - Row A and Row B:
Here is the very simple test code - just open it in the browser and it will work:
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1','packages':['corechart']}]}"></script>
<script type="text/javascript">
var data = {"rows":[
{"c":[{"v":"C"},{"v":-43},{"v":-42}]},
{"c":[{"v":"D"},{"v":-49},{"v":-39}]},
{"c":[{"v":"E"},{"v":-49},{"v":-48}]},
{"c":[{"v":"F"},{"v":-50},{"v":-49}]},
{"c":[{"v":"G"},{"v":-57},{"v":-56}]}],
"cols":[
{"p":{"role":"domain"},"label":"MEASUREMENT","type":"string"},
{"p":{"role":"data"},"label":"Row A","type":"number"},
{"p":{"role":"data"},"label":"Row B","type":"number"}]};
function drawCharts() {
var x = new google.visualization.DataTable(data);
var options = {
title: 'How to add tooltips?',
width: 800,
height: 600
};
var chart = new google.visualization.LineChart(document.getElementById('test'));
chart.draw(x, options);
}
$(function() {
google.setOnLoadCallback(drawCharts);
});
</script>
</head>
<body>
<div id="test"></div>
</body>
</html>
I would like to add tooltips to each data point, which would for example display:
Row A: x=D y=-49
on mouse hover. And I can not use dataTable.addColumn, because my chart is generated at once by a perl script and I just use a data Object with cols and rows as above.
Does anybody please know, how to do it here?
You can use a DataView to create the tooltip columns for you. This code snippet will dynamically create a tooltip column in the DataView for every data series:
var columns = [0];
for (var i = 1; i < x.getNumberOfColumns(); i++) {
columns.push(i);
columns.push({
type: 'string',
properties: {
role: 'tooltip'
},
calc: (function (j) {
return function (dt, row) {
return dt.getColumnLabel(j) + ': x=' + dt.getValue(row, 0) + ' y=' + dt.getValue(row, j)
}
})(i)
});
}
var view = new google.visualization.DataView(x);
view.setColumns(columns);
See the working example here: http://jsfiddle.net/asgallant/xWwxP/

HTML5 Geolocation data loaded in a form to send towards database

i'm busy with a school project and I have to build a web app. One function that I want to use is Google Maps and HTML5 Geo Location to pin point what the location of the mobile user is.
I have found this HTML5 Geo Location function on http://merged.ca/iphone/html5-geolocation and works very well for me. However, I want the adress data to be placed into a form so that I can submit it to my database when a mobile user Geo locates his position. This causes the marker to be saved and can be viewed on a global website.
Who know how to get the "Your address:" data loaded into a input field of a form?
Below you can find my Html file. Maybe somebody got a better suggestion perhaps?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<title>HTML 5 Geolocation</title>
<style>
#map {
height:300px;
width:300px;
}
</style>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">google.load("jquery", "1"); google.load("jqueryui", "1");</script>
<script src="http://maps.google.com/maps?file=api&v=2&sensor=false&key=ABQIAAAAiUzO1s6QWHuyzxx-JVN7ABSUL8-Cfeleqd6F6deqY-Cw1iTxhxQkovZkaxsxgKCdn1OCYaq7Ubz3SQ" type="text/javascript"></script>
<script type="text/javascript" src="http://api.maps.yahoo.com/ajaxymap?v=3.8&appid=n2wY9mzV34Hsdslq6TJoeoJDLmAfzeBamSwJX7jBGLnjM7oDX7fU.Oe91KwUbOwqzvc-"></script>
<script type="text/javascript">
// Geolocation with HTML 5 and Google Maps API based on example from maxheapsize: http://maxheapsize.com/2009/04/11/getting-the-browsers-geolocation-with-html-5/
//
// This script is by Merge Database and Design, http://merged.ca/ -- if you use some, all, or any of this code, please offer a return link.
var map;
var mapCenter
var geocoder;
var fakeLatitude;
var fakeLongitude;
function initialize()
{
if (navigator.geolocation)
{
navigator.geolocation.getCurrentPosition( function (position) {
// Did we get the position correctly?
// alert (position.coords.latitude);
// To see everything available in the position.coords array:
// for (key in position.coords) {alert(key)}
mapServiceProvider(position.coords.latitude,position.coords.longitude);
}, // next function is the error callback
function (error)
{
switch(error.code)
{
case error.TIMEOUT:
alert ('Timeout');
break;
case error.POSITION_UNAVAILABLE:
alert ('Position unavailable');
break;
case error.PERMISSION_DENIED:
alert ('Permission denied');
break;
case error.UNKNOWN_ERROR:
alert ('Unknown error');
break;
}
}
);
}
else
{
alert("I'm sorry, but geolocation services are not supported by your browser or you do not have a GPS device in your computer. I will use a sample location to produce the map instead.");
fakeLatitude = 49.273677;
fakeLongitude = -123.114420;
//alert(fakeLatitude+', '+fakeLongitude);
mapServiceProvider(fakeLatitude,fakeLongitude);
}
}
function mapServiceProvider(latitude,longitude)
{
if (window.location.querystring['serviceProvider']=='Yahoo')
{
mapThisYahoo(latitude,longitude);
}
else
{
mapThisGoogle(latitude,longitude);
}
}
function mapThisYahoo(latitude,longitude)
{
var map = new YMap(document.getElementById('map'));
map.addTypeControl();
map.setMapType(YAHOO_MAP_REG);
map.drawZoomAndCenter(latitude+','+longitude, 3);
// add marker
var currentGeoPoint = new YGeoPoint( latitude, longitude );
map.addMarker(currentGeoPoint);
// Start up a new reverse geocoder for addresses?
// YAHOO Ajax/JS/Rest API does not yet support reverse geocoding (though they do support it via Actionscript... lame)
// So we'll have to use Google for the reverse geocoding anyway, though I've left this part of the script just in case Yahoo! does support it and I'm not aware of it yet
geocoder = new GClientGeocoder();
geocoder.getLocations(latitude+','+longitude, addAddressToMap);
}
function mapThisGoogle(latitude,longitude)
{
var mapCenter = new GLatLng(latitude,longitude);
map = new GMap2(document.getElementById("map"));
map.setCenter(mapCenter, 15);
map.addOverlay(new GMarker(mapCenter));
// Start up a new reverse geocoder for addresses?
geocoder = new GClientGeocoder();
geocoder.getLocations(latitude+','+longitude, addAddressToMap);
}
function addAddressToMap(response)
{
if (!response || response.Status.code != 200) {
alert("Sorry, we were unable to geocode that address");
} else {
place = response.Placemark[0];
$('#address').html('Your address: '+place.address);
}
}
window.location.querystring = (function() {
// by Chris O'Brien, prettycode.org
var collection = {};
var querystring = window.location.search;
if (!querystring) {
return { toString: function() { return ""; } };
}
querystring = decodeURI(querystring.substring(1));
var pairs = querystring.split("&");
for (var i = 0; i < pairs.length; i++) {
if (!pairs[i]) {
continue;
}
var seperatorPosition = pairs[i].indexOf("=");
if (seperatorPosition == -1) {
collection[pairs[i]] = "";
}
else {
collection[pairs[i].substring(0, seperatorPosition)]
= pairs[i].substr(seperatorPosition + 1);
}
}
collection.toString = function() {
return "?" + querystring;
};
return collection;
})();
</script>
</head>
<body onLoad="initialize()">
<div id="content">
<div id="map"></div>
<p id="address"></p>
<form id="ContactForm" action="">
<p>
<label>Topic</label>
<input id="event" name="event" maxlength="120" type="text" autocomplete="off"/>
</p>
<p>
<label>Address</label>
<input id="address" name="address" maxlength="120" type="text" autocomplete="off"/>
</p>
<input id="send" type="button" value="Send"/>
<input id="newcontact" name="newcontact" type="hidden" value="1"></input>
</form>
</div>
</body>
</html>
You have to use JavaScript to set the value of address input field, this way
1- Add name attribute to the form and input.
2- document.formName.inputName.value=place.address;
Good Luck