Fixing javascript array initialization - javascript

I am trying to initialize an array with another array. The array contains options for loading an RSS feed reader. The user clicks an option button to selection which RSS category to read. Based on the selection I initalize the feed URL and options arrays like this.
feeds = feedsnews.slice(0, feedsnews.length);
options = optionsnews.slice(0, optionsnews.length);
(The entire javascript for this is at the end of the text).
Then I send these arrays to the code for loading the newsreader. This seems to initialize only the first element in the array.
What is the way to initialize the array with all the elements? Are the arrays declared in the right way for the RSS loader to get them?
Here is the code:
<script language="JavaScript">
var feedsnews = [ {title: 'Reuters Top News', url: 'http://feeds.reuters.com/reuters/topNews' }, {title: 'Reuters International',
url: 'http://feeds.reuters.com/reuters/worldNews' }, {title: 'Reuters US News', url: 'http://feeds.reuters.com/Reuters/domesticNews' }];
var optionsnews = {
stacked : true,
horizontal : false,
title : "News"
}
var feedscat = [ {title: 'Catholic News Agency', url: 'http://www.catholicnewsagency.com/rss/news.xml' }, {title: 'Zenit - English', url: 'http://feeds.feedburner.com/zenit/english' }, {title: 'Zenit - Français', url:
'http://feeds.feedburner.com/zenit/french' }];
var optionscat = {
stacked : true,
horizontal : false,
title : "Catholic"
}
</script>
<SCRIPT LANGUAGE="JavaScript">
var feeds=feedsnews.slice();
var options=optionsnews.slice();
function GetSelectedItem() {
feeds=feedsnews.slice(0, feedsnews.length);
options=optionsnews.slice(0, optionsnews.length);
chosen = "";
len = document.f1.r1.length;
for (i = 0; i <len; i++) {
if (document.f1.r1[i].checked) {
chosen = document.f1.r1[i].value
}
}
if (chosen == "") {
alert("No Location Chosen")
}
else if (chosen =="News") {
feeds = feedsnews.slice(0,feedsnews.length);
options = optionsnews.slice(0,optionsnews.length);
}
else if (chosen =="Catholic") {
feeds = feedscat.slice(0,feedscat.length);
options = optionscat.slice(optionscat.length);
}
else if (chosen =="Community") {
}
else if (chosen =="Personal") {
}
else if (chosen =="Professional") {
}
else {
alert(chosen);
}
$("#snews").load("loadnews.php");
}
</script>
HTML (for #snews div)
<div id="snews" style="position:absolute; top:30px; right: 30px; width: 430px; height: 380px; overflow-y: auto; overflow-x: hidden; background: white;">
<?php require("loadnews.php"); ?>
</div> <!-- End snews -->
PHP (loadnews.php)
<!-- ++Begin Dynamic Feed Wizard Generated Code++ -->
<!--
// Created with a Google AJAX Search and Feed Wizard
// http://code.google.com/apis/ajaxsearch/wizards.html
-->
<!--
// The Following div element will end up holding the actual feed control.
// You can place this anywhere on your page.
-->
<div id="feed-control">
<span style="color:#676767;font-size:11px;margin:10px;padding:4px;">Loading...</span>
</div>
<script type="text/javascript">
function LoadDynamicFeedControl() {
new GFdynamicFeedControl(feeds, 'feed-control', options);
}
// Load the feeds API and set the onload callback.
google.load('feeds', '1');
google.setOnLoadCallback(LoadDynamicFeedControl);
</script>
<!-- ++End Dynamic Feed Control Wizard Generated Code++ -->

var optionsnews = {
stacked : true,
horizontal : false,
title : "News"
}
// snip...
options=optionsnews.slice(0, optionsnews.length);
optionsnews is an Object, not an Array. There is no Object.slice method since objects have neither numerical indexing nor inherent ordering.
What is the point of all this .slice()ing? What are you trying to accomplish?

Related

Twitter Embedded Tweets aren't visible if HTML divs are in certain order

I'm building a web application using Vite.js + HTML/CSS/JS and jQuery. I want to embed tweets on a page using lists of twitter post id's returned from an API. I am using Twitter's Javascript Embed Tweets factory function to achieve this and encountering a strange problem. Everything works when the HTML divs are in a certain order, but if I try to move things around, one of the list of tweets doesn't display properly.
To explain further: I have two HTML divs that I'm using as containers for the tweets -- the first container displays tweets from a list of "positive" posts, and the second container displays tweets from a list of "negative" posts (the API returns these lists). When the page loads, the tweets are populated, but remain hidden. The user must click a button "display negative tweets" or "display positive tweets" in order toggle them to hidden/visible.
Now, if I arrange the HTML divs as follows, everything works properly:
Negative Tweets Container
Positive Tweets Container
However, if I reverse the order of the containers, the negative tweets stop displaying on button click:
Positive Tweets Container
Negative Tweets Container
It's quite strange, you'd think that whichever div was placed on the bottom would have the same issue, but it's only the negative tweets container that stops working properly when placed on the bottom. The code I'm using to populate and display the tweets for each section is identical except for the html id tags and variable names, so it doesn't make sense to me that the order of HTML divs would cause an issue. I've logged everything in the console, there are no errors and no indication of what is causing the problem.
I recreated the issue in two codepens for convenience:
Negative Div on Top (everything works)
Negative Div on Bottom (negative tweets won't show)
Please note, the two codepen projects are identical except for the order of HTML divs, so you can just look at one if you want, all you have to do is try putting the negative tweets container below the positive tweets container, or vice versa, and you will see the issue.
Here are code snippets as well. This is the working version, if you switch the order of tweet containers, the negative tweets will stop displaying properly:
//////////////////////////////////////////
// On page load, populate tweets, but they will remain
// hidden until user clicks "display" button
//////////////////////////////////////////
$(function() {
populatePositiveTweets();
populateNegativeTweets();
});
//////////////////////////////////////////
// test data -- positive
//////////////////////////////////////////
const positiveData = {
brand: "serena",
logo: "nike",
match_count: 5,
post_id_list: [{
post_id: "1400014236013764615"
},
{
post_id: "1399610411557683201"
},
{
post_id: "1399594614093271041"
},
{
post_id: "1399566283469819907"
},
{
post_id: "1399538218060500997"
}
],
return_error: null
};
//////////////////////////////////////////
// test data -- negative
//////////////////////////////////////////
const negativeData = {
brand: "serena",
logo: "nike",
match_count: 5,
post_id_list: [{
post_id: "1400014236013764615"
},
{
post_id: "1399610411557683201"
},
{
post_id: "1399594614093271041"
},
{
post_id: "1399566283469819907"
},
{
post_id: "1399538218060500997"
}
],
return_error: null
};
//////////////////////////////////////////
// function to populate positive tweets
//////////////////////////////////////////
const populatePositiveTweets = () => {
// Store the list of post id's in variable
const positiveTweetsList = positiveData.post_id_list;
console.log(positiveTweetsList);
// set up the variables
var subs;
var tempString;
var col1 = "",
col2 = "",
col3 = "";
var column_index = 1;
// loop through the results to build the three column strings
for (subs = 0; subs < positiveTweetsList.length; subs++) {
if (column_index == 1) {
col1 += "<div class='embed-responsive' id='tweetArea" + subs + "'></div>";
} else if (column_index == 2) {
col2 += "<div class='embed-responsive' id='tweetArea" + subs + "'></div>";
} else if (column_index == 3) {
col3 += "<div class='embed-responsive' id='tweetArea" + subs + "'></div>";
}
column_index += 1;
if (column_index == 4) {
column_index = 1;
}
}
// write out the column html code
document.getElementById("tweetCol1__positive").innerHTML = col1;
document.getElementById("tweetCol2__positive").innerHTML = col2;
document.getElementById("tweetCol3__positive").innerHTML = col3;
// loop through the results to display the tweets
for (subs = 0; subs < positiveTweetsList.length; subs++) {
// get the post id
post_id = positiveTweetsList[subs];
// build the twitter area name
twitter_area = "tweetArea" + subs;
// display the tweets
twttr.widgets
.createTweet(
positiveTweetsList[subs].post_id,
document.getElementById(twitter_area), {}
)
.then(function(e1) {
window.setTimeout(hideOverlay, 5000);
})
.catch(function(e2) {});
}
};
//////////////////////////////////////////
// function to populate negative tweets
///////////////////////////////////////////
const populateNegativeTweets = () => {
// Store the list of post id's in variable
const negativeTweetsList = negativeData.post_id_list;
// set up the variables
var subs;
var tempString;
var col1 = "",
col2 = "",
col3 = "";
var column_index = 1;
// loop through the results to build the three column strings
for (subs = 0; subs < negativeTweetsList.length; subs++) {
if (column_index == 1) {
col1 += "<div class='embed-responsive' id='tweetArea" + subs + "'></div>";
} else if (column_index == 2) {
col2 += "<div class='embed-responsive' id='tweetArea" + subs + "'></div>";
} else if (column_index == 3) {
col3 += "<div class='embed-responsive' id='tweetArea" + subs + "'></div>";
}
column_index += 1;
if (column_index == 4) {
column_index = 1;
}
}
// write out the column html code
document.getElementById("tweetCol1__negative").innerHTML = col1;
document.getElementById("tweetCol2__negative").innerHTML = col2;
document.getElementById("tweetCol3__negative").innerHTML = col3;
// loop through the results to display the tweets
for (subs = 0; subs < negativeTweetsList.length; subs++) {
// get the post id
post_id = negativeTweetsList[subs];
// build the twitter area name
twitter_area = "tweetArea" + subs;
// display the tweets
twttr.widgets
.createTweet(
negativeTweetsList[subs].post_id,
document.getElementById(twitter_area), {}
)
.then(function(e1) {
window.setTimeout(hideOverlay, 5000);
})
.catch(function(e2) {});
}
};
//////////////////////////////////////////
// Function to toggle tweets to show/hide
//////////////////////////////////////////
const toggleTweets = (type) => {
let tweetsContainer = $(`#tweets-container__${type}`);
if ($(tweetsContainer).css("display") === "none") {
$(tweetsContainer).show();
console.log("tweets container", $(tweetsContainer).css("display"));
} else {
$(tweetsContainer).hide();
console.log("tweets container", $(tweetsContainer).css("display"));
}
};
//////////////////////////////////////////
// Attach toggle function to buttons as click listeners
//////////////////////////////////////////
$("#tweets-btn__positive").on("click", () => {
console.log("toggle positive tweets");
toggleTweets("positive");
});
$("#tweets-btn__negative").on("click", () => {
console.log("toggle negative tweets")
toggleTweets("negative");
});
#tweets-container__negative,
#tweets-container__positive {
display: none;
width: auto;
}
#no-data__negative-posts,
#no-data__positive-posts {
display: none;
}
#parent-container {
display: block;
}
<!-- CSS Styles -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" crossorigin="anonymous">
<!-- jQuery Scripts -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<!-- Bootstrap JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<!-- JS Add-on Scripts -->
<script src="https://platform.twitter.com/widgets.js"></script>
<div id="parent-container">
<!-- Negative Button -->
<button id="tweets-btn__negative">Toggle Negative Posts</button>
<!-- Negative Tweets Container-->
<div id="tweets-container__negative">
<div class="container-fluid" id="negative-tweets">
<div class="row">
<div class="col-md-12">
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-3" id="tweetCol1__negative"></div>
<div class="col-md-1"></div>
<div class="col-md-3" id="tweetCol2__negative"></div>
<div class="col-md-1"></div>
<div class="col-md-3" id="tweetCol3__negative"></div>
</div>
</div>
</div>
</div>
</div>
<!-- Positive Button -->
<button id="tweets-btn__positive">Toggle Positive Posts</button>
<!-- Positive Tweets Container-->
<div id="tweets-container__positive">
<div class="container-fluid" id="positive-tweets">
<div class="row">
<div class="col-md-12">
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-3" id="tweetCol1__positive"></div>
<div class="col-md-1"></div>
<div class="col-md-3" id="tweetCol2__positive"></div>
<div class="col-md-1"></div>
<div class="col-md-3" id="tweetCol3__positive"></div>
</div>
</div>
</div>
</div>
</div>
</div>
Lastly, Here's one more link to an example of the Twitter embed code that I used as a reference for my code: https://www.labnol.org/code/19933-embed-tweet-with-javascript
I know this is a complex problem, I did my best to create a minimal reproduction of the issue and provide relevant resources. Thanks in advance for any help.
As #bravo pointed out in the comments, I had duplicated id's in my HTML:
As they said,
"the issue is with id='tweetArea" + subs ... and twitter_area =
"tweetArea" + subs; and document.getElementById(twitter_area) will
fail to get the right element half the time"

How to load data from csv file into form field?

I am trying to link my HTML form with my csv file to populate form field automatically. Based on what user selects in first field, second field should be automatically filled with the appropriate value. when the user starts typing in the first field, the input field automatically pulls data from csv file to show available options. Options appear after user completes writing 3 words in the field.
Further, to avoid any CORS issue in code, I have added additional URL in my CSV file URL which makes it accessible by any web application.
I was able to prepare this code with the help of examples available on web. However, my code is not working properly. I tried to solve this problem on my own. But I don't know about coding enough.
Can anyone please help me to solve this problem.
<script>
$(function() { function processData(allText) { var record_num = 2;
// or however many elements there are in each row
var allTextLines = allText.split(/\r\n|\n/); var lines = []; var headings = allTextLines.shift().split(','); while (allTextLines.length > 0) { var tobj = {}, entry; entry = allTextLines.shift().split(','); tobj['label'] = entry[0]; tobj['value'] = entry[1]; lines.push(tobj); } return lines; }
// Storage for lists of CSV Data
var lists = [];
// Get the CSV Content
$.get("https://cors-anywhere.herokuapp.com/www.coasilat.com/wp-content/uploads/2019/06/file.txt ", function(data) { lists = processData(data); }); $("#species").autocomplete({ minLength: 3, source: lists, select: function(event, ui) { $("#species").val(ui.item.label); $("#identifiant").val(ui.item.value); return false; } }); });)
</script>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<form>
<div class="ui-widget"> <label for="species">Species: </label> <input id="species"> <label for="identifiant">Identifiant: </label> <input id="identifiant" style="width: 6em;"> </div></form>
Here's the modified answer, working with jquery-ui autocomplete.
The solution: the $.get() is an asynchronous function (the data is not readily available on page load), so jquery-ui autocomplete didn't work with the updated lists[] array, because it (seems so that it) doesn't work with dynamically generated data. So the source of autocomplete had to be refreshed with the newly arrived data in the $.get()'s callback function.
$("#species").autocomplete('option', 'source', lists) - this is the key line, as it updates autocomplete's source with the new data.
// Only needed for working example
var myCSV = "Species,Identifiant\r\n";
myCSV += "Species A,320439\r\n";
myCSV += "Species B,349450\r\n";
myCSV += "Species C,43435904\r\n";
myCSV += "Species D,320440\r\n";
myCSV += "Species E,349451\r\n";
myCSV += "Species F,43435905\r\n";
console.log(myCSV);
// Begin jQuery Code
$(function() {
function processData(allText) {
// var record_num = 2; // or however many elements there are in each row
var allTextLines = allText.split(/\r\n|\n/);
var lines = [];
var headings = allTextLines.shift().split(',');
while (allTextLines.length > 0) {
var tobj = {},
entry;
entry = allTextLines.shift().split(',');
/*
Normally we'd read the headers into the object.
Since we will be using Autocomplete, it's looking for an array of objects with 'label' and 'value' properties.
tobj[headings[0]] = entry[0];
tobj[headings[1]] = entry[1];
*/
if (typeof entry[1] !== 'undefined') {
let prefix = !entry[0].includes('Species') ? 'Species ' : ''
tobj['label'] = prefix + entry[0];
tobj['value'] = entry[1].trim();
lines.push(tobj);
}
}
return lines;
}
let lists = [];
// For working example
// lists = processData(myCSV);
// console.log('lists1', lists)
// In your script you will get this content from the CSV File
// Get the CSV Content
$.get("https://cors-anywhere.herokuapp.com/www.coasilat.com/wp-content/uploads/2019/06/file.txt", function(data) {
lists = processData(data);
$("#species").autocomplete('option', 'source', lists)
console.log('lists2', lists)
});
$("#species").autocomplete({
minLength: 3,
source: lists,
focus: function(event, ui) {
console.log(ui)
$("#species").val(ui.item.label);
return false;
},
select: function(event, ui) {
$("#species").val(ui.item.label);
$("#identifiant").val(ui.item.value);
return false;
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet" />
<div class="ui-widget">
<label for="species">Species: </label>
<input id="species">
<label for="identifiant">Identifiant: </label>
<input id="identifiant" style="width: 6em;">
</div>
The processData() function didn't work as expected with the source you provided, so that had to be modified too.
My solution is a kinda' autocomplete - it's called typeahead.
I displayed the filtered list, so you see what's happening, but you can place that anywhere - in a dropdown below the input field, for example.
$(function() {
// processing CSV data
function processData(allText) {
// splitting lines
var allTextLines = allText.split(/\r\n|\n/);
const speciesData = []
// reading data into array, if it's not the first row (CSV header) AND
// if it's not 'Species'
let j = 0; // this will be the item's index
for (let i = 0; i < allTextLines.length - 1; i++) {
if (i !== 0 && allTextLines[i] !== 'Species') {
const record = allTextLines[i].split(',')
speciesData.push({
label: record[0],
value: record[1].trim(), // it has a lot of whitespace
index: j // adding this, so we can keep track of items
})
j++; // incrementing index
}
}
// returning processed data
return speciesData;
}
// Storage for lists of processed CSV Data
let lists = [];
// Get the CSV Content
$.get("https://cors-anywhere.herokuapp.com/www.coasilat.com/wp-content/uploads/2019/06/file.txt ", function(data) {
// making processed data availabel app-wide
lists = processData(data);
// filling the 'suggestions list' the first time
suggestionListHtml(lists, $('.suggestions-container'))
});
// actions on input field input event
// only the third param differs in filterSpecies()
$('#species').on('input', function(e) {
const filteredList = filterSpecies($(this).val(), lists, 'label')
suggestionListHtml(filteredList, $('.suggestions-container'))
})
$('#identifiant').on('input', function(e) {
const filteredList = filterSpecies($(this).val(), lists, 'value')
suggestionListHtml(filteredList, $('.suggestions-container'))
})
// clicking on an item in the 'suggestions list' fills out the input fields
$('.suggestions-container').on('click', '.suggestion', function(e) {
const item = lists[$(this).attr('data-listindex')]
$('#species').val(item.label)
$('#identifiant').val(item.value)
})
});
function suggestionListHtml(filteredList, container) {
// creating HTML template for the 'suggestions list'
let html = ''
filteredList.forEach(item => {
html += `<span class="suggestion" data-listindex="${item.index}">label: ${item.label} - value: ${item.value}</span>`
})
// modifying the displayed 'suggestions list'
container
.empty()
.append(html)
}
// filtering the processed list
// #param substr - the text from the input field
// #param list - the list to be filtered
// #param attr - one of the keys in the processed list (label or value)
function filterSpecies(substr, list, attr) {
// doing the actual filtering
const filteredList = list.filter(item => {
return item[attr].toLowerCase().includes(substr.toLowerCase())
})
return filteredList
}
.suggestions-container span {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="ui-widget">
<label for="species">Species: </label>
<input id="species">
<label for="identifiant">Identifiant: </label>
<input id="identifiant" style="width: 6em;">
</div>
<div class="suggestions-container">
</div>
</form>

Strange javascript array push behaviour

I wrote a simple code to manipulate a query result to a bidimensional array (matrix) for a google chart datatable.
I'm getting nut on this strange array.push behaviour: when I push a new row in the matrix this method add the row, but also change the value of all the previus rows!
this is the code:
<script src="https://www.gstatic.com/charts/loader.js" type="text/javascript"></script>
<script type="text/javascript">
query is the matrix from the query
var qry = [[{label:'Montly', type: 'string'}, {label:'Model', type: 'string'}, {label:'total', type: 'number'}], ['12-2017','California T',parseFloat(13+13)], ['12-2017','458 Speciale',parseFloat(3+2)], ['12-2017','GTC4Lusso',parseFloat(2+6)], ['12-2017','458 Spider',parseFloat(0+1)], ['12-2017','GTC4Lusso T',parseFloat(2+0)], ['12-2017','California',parseFloat(0+2)], ['12-2017','488 Spider',parseFloat(16+7)], ['12-2017','FF',parseFloat(1+3)], ['12-2017','488 GTB',parseFloat(17+10)], ['12-2017','F12berlinetta',parseFloat(3+4)], ['12-2017','458 Italia',parseFloat(0+3)], ['12-2017','F12tdf',parseFloat(1+21)], ['12-2017','LaFerrari Aperta',parseFloat(0+1)], ['12-2017','812 Superfast',parseFloat(2+3)], ['12-2017','Portofino',parseFloat(1+1)], ['11-2017','458 Spider',parseFloat(2+4)], ['11-2017','GTC4Lusso',parseFloat(4+34)], ['11-2017','California T',parseFloat(8+15)], ['11-2017','488 GTB',parseFloat(9+12)], ['11-2017','LaFerrari',parseFloat(0+1)], ['11-2017','458 Speciale',parseFloat(2+2)], ['11-2017','GTC4Lusso T',parseFloat(0+1)], ['11-2017','FF',parseFloat(1+4)], ['11-2017','812 Superfast',parseFloat(3+1)], ['11-2017','California',parseFloat(0+3)], ['11-2017','488 Spider',parseFloat(11+8)], ['11-2017','458 Italia',parseFloat(1+5)], ['11-2017','F12tdf',parseFloat(0+1)], ['11-2017','Portofino',parseFloat(0+1)], ['11-2017','F12berlinetta',parseFloat(3+4)], ['10-2017','458 Italia',parseFloat(0+4)], ['10-2017','California T',parseFloat(9+18)], ['10-2017','California',parseFloat(0+8)], ['10-2017','812 Superfast',parseFloat(1+2)], ['10-2017','F12tdf',parseFloat(1+2)], ['10-2017','Portofino',parseFloat(2+0)], ['10-2017','488 GTB',parseFloat(8+14)], ['10-2017','FF',parseFloat(0+3)], ['10-2017','458 Spider',parseFloat(1+3)], ['10-2017','LaFerrari Aperta',parseFloat(0+1)], ['10-2017','F12berlinetta',parseFloat(5+8)], ['10-2017','458 Speciale',parseFloat(3+2)], ['10-2017','488 Spider',parseFloat(9+7)], ['10-2017','GTC4Lusso',parseFloat(2+4)], ['9-2017','California',parseFloat(0+4)], ['9-2017','458 Speciale Aperta',parseFloat(1+0)], ['9-2017','FF',parseFloat(3+6)], ['9-2017','812 Superfast',parseFloat(2+1)], ['9-2017','458 Italia',parseFloat(1+3)], ['9-2017','GTC4Lusso',parseFloat(2+6)], ['9-2017','F12tdf',parseFloat(1+0)], ['9-2017','LaFerrari',parseFloat(0+1)], ['9-2017','488 GTB',parseFloat(18+13)], ['9-2017','458 Spider',parseFloat(3+2)], ['9-2017','F12berlinetta',parseFloat(4+10)], ['9-2017','458 Speciale',parseFloat(5+1)], ['9-2017','California T',parseFloat(23+37)], ['9-2017','488 Spider',parseFloat(11+14)], ['8-2017','FF',parseFloat(0+1)], ['8-2017','458 Spider',parseFloat(0+1)], ['8-2017','F12berlinetta',parseFloat(0+3)], ['8-2017','GTC4Lusso',parseFloat(0+6)], ['8-2017','488 GTB',parseFloat(0+1)], ['8-2017','California T',parseFloat(0+2)], ['8-2017','458 Italia',parseFloat(0+2)], ['8-2017','California',parseFloat(0+2)], ['7-2017','488 GTB',parseFloat(9+14)], ['7-2017','458 Speciale',parseFloat(1+4)], ['7-2017','California T',parseFloat(14+20)], ['7-2017','GTC4Lusso',parseFloat(1+7)], ['7-2017','California',parseFloat(1+6)], ['7-2017','458 Italia',parseFloat(1+4)], ['7-2017','458 Speciale Aperta',parseFloat(1+0)], ['7-2017','F12berlinetta',parseFloat(3+7)], ['7-2017','FF',parseFloat(2+3)], ['7-2017','458 Spider',parseFloat(1+3)], ['7-2017','488 Spider',parseFloat(10+10)], ['7-2017','F12tdf',parseFloat(0+1)], ['6-2017','488 GTB',parseFloat(7+23)], ['6-2017','458 Italia',parseFloat(2+2)], ['6-2017','812 Superfast',parseFloat(1+0)], ['6-2017','FF',parseFloat(0+3)], ['6-2017','GTC4Lusso',parseFloat(2+16)], ['6-2017','458 Spider',parseFloat(3+6)], ['6-2017','F12tdf',parseFloat(0+2)], ['6-2017','LaFerrari',parseFloat(0+1)], ['6-2017','F12berlinetta',parseFloat(4+9)], ['6-2017','458 Speciale',parseFloat(2+3)], ['6-2017','California T',parseFloat(16+18)], ['6-2017','488 Spider',parseFloat(11+14)], ['5-2017','458 Speciale',parseFloat(4+4)], ['5-2017','458 Italia',parseFloat(0+2)], ['5-2017','F12berlinetta',parseFloat(2+5)], ['5-2017','F12tdf',parseFloat(0+3)], ['5-2017','FF',parseFloat(0+1)], ['5-2017','488 GTB',parseFloat(8+13)], ['5-2017','458 Spider',parseFloat(0+2)], ['5-2017','GTC4Lusso',parseFloat(0+6)], ['5-2017','488 Spider',parseFloat(6+12)], ['5-2017','California T',parseFloat(12+19)], ];
I want to extract the unique models from the column and create the series for the line chart
function extractColumn(arr, column) {
function reduction(previousValue, currentValue) {
previousValue.push(currentValue[column]);
return previousValue;
}
return arr.reduce(reduction, []);
}
var prima = extractColumn(qry,1);
var models = [...new Set(prima)];
with extract column I get all the values of the column 1,and with the spread operator I get the models array, without duplicate.
var testa = []; // the header of the matrix
var tabella = []; // the array for the DataTable
for (i=1; i<models.length; i++) {
riga[i]=0;
}
testa.push([{label:'Montly', type: 'string'}]);
for (i=1; i<models.length; i++) {
testa.push([{label:models[i], type:'number'}]);
} // this code create the header objects
tabella.push(testa); //push the header into the tabella array
console.log(tabella[0]); //this push is ok!
var mese=qry[1][0]; // first date value
var riga = []; // array to add as row of the matrix
riga[0]=mese; // start populating the firs row
the following code should create a new row and append it to the chart table.
It checks the date of every row of the query matrix (qry): if it's a new date append the created row to the chart table and start a new row, if not it goes on creating the new row.
for (i=1; i<qry.length; i++){ // iterate qry array
if (mese!=qry[i][0]) { // check if the date is new
console.log(riga); // all the created row are ok!
tabella.push(riga); // append the row to the array
console.table(tabella); // WEIRD PROBLEM: ALL THE ARRAY ROW ARE CHANGED
mese=qry[i][0]; // EVERY CICLE!
for (x=1; x<models.length; x++) {
riga[x]=0;
}
riga[0]=mese; //reset the new row array and set the date
} else {
for (t=0;t<models.length;t++){
pos = models.indexOf(qry[i][1]);
if (pos != -1) {
riga[pos]=qry[i][2]
}
} // this code populates the new row.
}
}
The following code create the chart
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable(tabella);
var options = {
title: 'Montly Trend Focus on Complaint Type',
colors: ['#D9D904','#2A55FF','#000000'],
backgroundColor: {fill:'#FAFAFA',strokeWidth:1},
chartArea: {width:1800,height:380,left:70},
curveType: 'none',
legend: { position: 'bottom' },
hAxis: {direction:-1},
annotations: {
alwaysOutside: true,
textStyle: {
fontSize: 12,
bold: true,
color: '#000000',
}
}
};
var chart = new google.visualization.LineChart(document.getElementById('line_chart'));
chart.draw(data, options);
}
this is an image from my console:
I solved my problem redeclareing the new row in the loop:
for (i=1; i<qry.length; i++){
if (mese!=qry[i][0]) {
tabella.push(riga);
var riga=[]; // NEW DECLARATION
mese=qry[i][0];
for (x=1; x<models.length; x++) {
riga[x]=0;
}
riga[0]=mese;
}
else {
for (t=0;t<models.length;t++){
pos = models.indexOf(qry[i][1]);
if (pos != -1){riga[pos]=qry[i][2]}
}
}
}
Hope this will be usefull for others.

Text to Html conversion in Sharepoint 2010

I have a SharePoint 2010 list of around 198 items. For the first 30 items Text to Html Javascript function successfully converts text code to Html but when I am trying to select next 31 items and go ahead using the pagination the function does not able to convert Html and display only text codes. Does anyone please who have the code handy to make this work? Below is the code used in SharePoint 2010. Thank you.
<script type="text/javascript">
function TextToHTML(NodeSet, HTMLregexp) {
var CellContent = "";
var i=0;
while (i < NodeSet.length){
try {
CellContent = NodeSet[i].innerText || NodeSet[i].textContent;
if (HTMLregexp.test(CellContent)) {NodeSet[i].innerHTML = CellContent;}
}
catch(err){}
i=i+1;
}
}
// Calendar views
var regexpA = new RegExp("\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*");
TextToHTML(document.getElementsByTagName("a"),regexpA);
// List views
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"),regexpTD);
// This function is call continuesly every 100ms until the length of the main field changes
// after which the convert text to HTML is executed.
//
var postElemLength = 0;
function PostConvertToHtml()
{
if (postElemLength == document.getElementsByTagName("TD").length)
{
setTimeout(PostConvertToHtml,100);
}
else
{
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"),regexpTD);
}
}
// Grouped list views
ExpGroupRenderData = (function (old) {
return function (htmlToRender, groupName, isLoaded) {
var result = old(htmlToRender, groupName, isLoaded);
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"),regexpTD);
// start the periodic callback to check when the element has been changed
if(isLoaded == 'false')
{
postElemLength = document.getElementsByTagName("TD").length;
setTimeout(PostConvertToHtml,100);
}
};
})(ExpGroupRenderData);
// Preview pane views
if (typeof(showpreview1)=="function") {
showpreview1 = (function (old) {
return function (o) {
var result = old(o);
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"),regexpTD);
};
})(showpreview1);
}</script>
Below is the generated text code which needs to be converted to Html. Thanks.
="<div style='position:relative;display:inline-block;width:100%;'>
<div style='width:100%;display:inline-block;text-align:center;border:1px solid "&Project_Status_clr&";position:absolute;color:"&Project_Status_clr&";'> "&Project_Status&"
</div>
<div style='display:inline-block;width: 100%;background-color:"&Project_Status_clr&";text-align:center;border:1px solid;z-index:-1;filter:alpha(opacity=20);opacity:0.2;'>"&Project_Status&"
</div>
</div>"
When generating a string of HTML in a calculated column in SharePoint 2010, you can change the calculated column's value type to "Number" to get the HTML to render in the list view.

Zingchart - passing a function to the tooltip

Is it possible to pass a function to the tooltip key in the Zingchart Json?
I tried the following so far:
$scope.applyTooltip = function (timestamp) {
console.log(timestamp);
var tooltip = "<div>";
var data = {
timestamp1: {
param1: "bla",
param2: "foo,
},
...
}
for(var param in data){
console.log(param);
tooltip += param+": "+data[param]+"<br>";
}
tooltop += "</div>;
return tooltip;
}
$scope.graphoptions = {
//...
//just displaying the relevant options
plot: {
"html-mode": true,
tooltip: $scope.applyTooltip("%kt"),
}
}
}
But the function gets the string "%kt" as it is and not the wanted X-Value of the hovered Plot. So how is it possible to pass the X-Value in the Function?
ZingChart does not allow passing in functions through the configuration object.
Instead, there is a property called "jsRule" which allows you to pass the name a function to be evaluated during each tooltip event.
tooltip : {
jsRule : "CustomFn.formatTooltip()"
}
Inside that function, a parameter will be available that will contain information about the node you moused over such as value, scaletext, plotindex, nodeindex, graphid, and more. Simply return an object for the tooltip (including the formatted text) and ZingChart will take care of the rest. Example provided down below.
The one caveat to jsRule is that the function name has to be accessible globally since ZingChart does not accept inline functions. We are aware of this issue and are planning for this to be an option in future versions.
CustomFn = {};
var myConfig = {
type: "line",
tooltip : {
jsRule : "CustomFn.formatTooltip()"
},
series : [
{
values : [1,3,2,3,4,5,4,3,2,1,2,3,4,5,4]
},
{
values : [6,7,8,7,6,7,8,9,8,7,8,7,8,9,8]
}
]
};
CustomFn.formatTooltip = function(p){
var dataset = zingchart.exec('myChart', 'getdata');
var series = dataset.graphset[p.graphindex].series;
var tooltipText = "";
for (var i=0; i < series.length; i++) {
tooltipText += "Series " + i + " : " + series[i].values[p.nodeindex] + "";
if (i !== series.length-1) {
tooltipText += "\n";
}
}
return {
text : tooltipText,
backgroundColor : "#222"
}
}
zingchart.render({
id : 'myChart',
data : myConfig,
height: 400,
width: 600
});
<!DOCTYPE html>
<html>
<head>
<script src= 'https://cdn.zingchart.com/2.3.1/zingchart.min.js'></script>
</head>
<body>
<div id='myChart'></div>
</body>
</html>

Categories

Resources