I was trying to update the graph using chart.js#3.8.0 : https://cdn.jsdelivr.net/npm/chart.js#3.8.0/dist/chart.min.js
1 : when there is a message in the channel call the update function .
2 : get required data to refill the graph .
3 : Search in the array of chart object which data is being updated .
3 : update the graph using previous Instance stored in that array .
var chartInstance ;
function update(host, data) {
let device = (data['did']).substring(0, data['did'].indexOf('-'));
let data_dict = [null, null, null, null, null]
for (let i = 1; i <= 5; i++) {
let url = host + "/graphicalreport/?did=" + device + "-" + i + "&type=json&max=10";
fetch(url).then(async response => await response.json()).then(data => {
// console.log(device,data);
data_dict[i - 1] = getSimplifiedDataForGraph(data['data'], i);
data_dict[i - 1]['label'] = device + "-" + i;
});
}
// console.log(data_dict); try {
chartInstance = chartList[BinarySearch(chartList, device)];
chartInstance.data.datasets = data_dict;
chartInstance.update() ;
}
I am getting this error .
TypeError: Cannot read properties of null (reading '_meta')
at ni.getDatasetMeta (Chart.min.js:7:98656)
at ni.<anonymous> (Chart.min.js:7:94721)
at Object.each (Chart.min.js:7:23303)
at ni.buildOrUpdateControllers (Chart.min.js:7:94678)
at ni.update (Chart.min.js:7:95644)
at update (graph.js:106:18)
at WebSocket.socket.onmessage ((index):123:13)
But the graph is getting updated on :
1 : resizing the browser tab
2 : executing : chartInstance.update() from browser console .
Related
I created a TiteldPane in scalafx
val titled: TitledPane = new TitledPane()
and put some nodes in it for my GUI.
Later I want to read out the heigth of the content of titled.
In javaFX this would be done with:
((Region) titled.getContent()).getHeight()
But if I try to read the height of the content in scala with:
titled.content.height
the height is marked as deprecated and does not compile. I've got a hint to github (scalafx/issue69) that explains why it is deprecated but does not explain how it can be done instead.
Just to clarify: I want to read out the height of the content of the titledpane, not just titled.heigth.
When titled is closed, then titled.height is 0, but I want to know what it would be when it is expanded (to detect when it has finished expanding actually).
So, how can I do this in scalafx?
EDIT:
Here is a example that shows the described error
import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.beans.property.DoubleProperty
import scalafx.beans.value.ObservableValue
import scalafx.collections.ObservableBuffer
import scalafx.event.ActionEvent
import scalafx.scene.Scene
import scalafx.scene.control.cell.TextFieldListCell
import scalafx.scene.control.{Button, ListView, TitledPane}
import scalafx.scene.layout.BorderPane
object TitledPaneEndOfExpansion extends JFXApp {
val expandedHeight = new DoubleProperty()
val data: ObservableBuffer[String] = new ObservableBuffer[String]() ++= List("some", "content", "for", "testing")
stage = new JFXApp.PrimaryStage {
title = "JavaFX: edit after rendering test"
val list: ListView[String] = new ListView[String](data) {
editable = true
cellFactory = TextFieldListCell.forListView()
height.onChange { (source: ObservableValue[Double, Number], oldValue: Number, newValue: Number) =>
expandedHeight.value = titled.content.height
println("old height is: " + oldValue.doubleValue() + " new height is: " + newValue.doubleValue())
if (newValue.doubleValue() == expandedHeight.value) {
edit(1)
}
}
}
val titled: TitledPane = new TitledPane {
text = "titled"
content = list
}
scene = new Scene {
root = new BorderPane {
center = titled
bottom = new Button() {
text = "edit cell 1"
onAction = { _: ActionEvent => list.edit(1) }
}
}
}
expandedHeight.value = titled.content.height //set to 400
list.edit(1)
}
}
And here is the buid.sbt file:
name := "JavaFXrenderingProblem"
version := "0.1"
scalaVersion := "2.13.3"
libraryDependencies += "org.scalafx" %% "scalafx" % "15.0.1-R21"
libraryDependencies += "org.controlsfx" % "controlsfx" % "8.40.18"
// Prevent startup bug in JavaFX
fork := true
// Tell Javac and scalac to build for jvm 1.8
javacOptions ++= Seq("-source", "1.8", "-target", "1.8")
scalacOptions += "-target:jvm-1.8"
scalacOptions += "-feature"
When I just compile with plain sbt i get the compile error-message:
[info] compiling 1 Scala source to ... JavaFXrenderingProblem\target\scala-2.13\classes ...
[error] ... JavaFXrenderingProblem\src\main\scala\TitledPaneEndOfExpansion.scala:38:47: value height is not a member of scalafx.beans.property.ObjectProperty[javafx.scene.Node]
[error] expandedHeight.value = titled.content.height
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 3 s, completed 03.05.2021 11:09:02
I actually get two errors when I execute sbt run on your code, and I do not get a deprecation error:
[info] compiling 1 Scala source to C:\Users\SomeUser\src\SFC\target\scala-2.13\classes ...
[error] C:\Users\SomeUser\src\SFX\src\main\scala\TitledPaneEndOfExpansion.scala:23:41: value height is not a member of scalafx.beans.property.ObjectProperty[javafx.scene.Node]
[error] expandedHeight.value = titled.content.height
[error] ^
[error] C:\Users\MichaelAllen\src\SOSFX\src\main\scala\TitledPaneEndOfExpansion.scala:45:40: value height is not a member of scalafx.beans.property.ObjectProperty[javafx.scene.Node]
[error] expandedHeight.value = titled.content.height //set to 400
[error] ^
[error] two errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 3 s, completed May 3, 2021 9:58:00 AM
From your code, the list value returns the contents of the TitledPane instance, titled, as a ListView[String]. It is this object whose height method you're trying to call. Correct?
The primary problem is that the content method of titled doesn't know enough about the type of the object that titled is storing. All it knows is that it is derived from javafx.scene.Node. Such Node instances do not have a height property, and hence your errors. (It's actually a little more complicated than that, but that's the simplest way to explain the issue.)
However, you already have a reference to the object that is the content of titled: list. So you can replace the second reference to titled.content.height with list.height. The first reference, in list's height's onChanged method, is accessible through the source parameter (it identifies the property that changed value, namely list.height in this case). So you can replace title.content.height with source in this case.
I notice that you're using a DoubleProperty type for expandedHeight in your example, but you need to keep looking at the value of the associated types. That's not very idiomatic. If you don't need this value to be reactive, a simple Double would suffice (but this would require that expandedHeight be declared as a var).
Combined, this produces the following code:
import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.beans.property.DoubleProperty
import scalafx.beans.value.ObservableValue
import scalafx.collections.ObservableBuffer
import scalafx.event.ActionEvent
import scalafx.scene.Scene
import scalafx.scene.control.cell.TextFieldListCell
import scalafx.scene.control.{Button, ListView, TitledPane}
import scalafx.scene.layout.BorderPane
object TitledPaneEndOfExpansion extends JFXApp {
var expandedHeight: Double = _
val data: ObservableBuffer[String] = new ObservableBuffer[String]() ++= List("some", "content", "for", "testing")
stage = new JFXApp.PrimaryStage {
title = "JavaFX: edit after rendering test"
val list: ListView[String] = new ListView[String](data) {
editable = true
cellFactory = TextFieldListCell.forListView()
height.onChange { (source: ObservableValue[Double, Number], oldValue: Number, newValue: Number) =>
expandedHeight = source.value
println("old height is: " + oldValue.doubleValue() + " new height is: " + newValue.doubleValue())
if (newValue.doubleValue() == expandedHeight) {
edit(1)
}
}
}
val titled: TitledPane = new TitledPane {
text = "titled"
content = list
}
scene = new Scene {
root = new BorderPane {
center = titled
bottom = new Button() {
text = "edit cell 1"
onAction = { _: ActionEvent => list.edit(1) }
}
}
}
expandedHeight = list.height.value //set to 400
list.edit(1)
}
}
Your code then compiles and runs.
Updated
ScalaFX is simply a wrapper for JavaFX: each JavaFX type has a corresponding ScalaFX type. ScalaFX provides implicit conversion functions to seamlessly convert, say, a JavaFX TitledPane to a ScalaFX TitledPane, and vice versa. However, there's no inheritance relationship between the two sets of objects. That is, a JavaFX TitledPane has no type relationship to a ScalaFX TitledPane. Casting between the two sets of objects is therefore a complicated process.
If you wanted to be able to cast titled.content correctly in order to access the height property of the contents more directly, you would need to get the property's value and explicitly pattern match on the result with the JavaFX version of the object, as follows:
import javafx.scene.control.{ListView => JFXListView}
import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.beans.property.DoubleProperty
import scalafx.beans.value.ObservableValue
import scalafx.collections.ObservableBuffer
import scalafx.event.ActionEvent
import scalafx.scene.Scene
import scalafx.scene.control.cell.TextFieldListCell
import scalafx.scene.control.{Button, ListView, TitledPane}
import scalafx.scene.layout.BorderPane
object TitledPaneEndOfExpansion extends JFXApp {
var expandedHeight: Double = _
val data: ObservableBuffer[String] = new ObservableBuffer[String]() ++= List("some", "content", "for", "testing")
stage = new JFXApp.PrimaryStage {
title = "JavaFX: edit after rendering test"
val list: ListView[String] = new ListView[String](data) {
editable = true
cellFactory = TextFieldListCell.forListView()
height.onChange { (source: ObservableValue[Double, Number], oldValue: Number, newValue: Number) =>
expandedHeight = titled.content.value match {
case lv: JFXListView[_] => lv.height.value
case _ => {
throw new RuntimeException(s"Unexpected content type: ${titled.content.getClass.getCanonicalName}")
}
}
println("old height is: " + oldValue.doubleValue() + " new height is: " + newValue.doubleValue())
if (newValue.doubleValue() == expandedHeight) {
edit(1)
}
}
}
val titled: TitledPane = new TitledPane {
text = "titled"
content = list
}
scene = new Scene {
root = new BorderPane {
center = titled
bottom = new Button() {
text = "edit cell 1"
onAction = { _: ActionEvent => list.edit(1) }
}
}
}
expandedHeight = titled.content.value match { //set to 400
case lv: JFXListView[_] => lv.height.value
case _ => throw new RuntimeException(s"Unexpected content type: ${titled.content.getClass.getCanonicalName}")
}
list.edit(1)
}
}
If you didn't have any other means of referencing the list object, that would be your only option.
I want send in a Pagination-embed with a music list because whan an embed is lower at 1024 letters it doesn't send.
I want send in many pages (4musics max per pages)
Sorry for my english, i'm french...
console.log(_serverQueue.songs)
let q = ``;
for(var i = 1; i < _serverQueue.songs.length; i++) {
q += `\n${i + 1}. **${_serverQueue.songs[i].title}**`;
}
let resp = [
{name: `Now Playing`, value: _serverQueue.songs[0].title},
{name: `Queue`, value: q},
];
//Putting it all together
const FieldsEmbed = new Pagination.FieldsEmbed()
.setArray({word: `Queue`})
.setAuthorizedUsers([message.author.id])
.setChannel(message.channel)
.setElementsPerPage(4)
.setPageIndicator(true)
.formatField('Playlist :', el => el.word)
FieldsEmbed.embed
.setColor('#008000')
.setTitle('Playlist :')
FieldsEmbed.build()
}
As per the Documentation of https://www.npmjs.com/package/discord-paginationembed
I explained the steps with Comments
const Discord = require('discord.js');
const Pagination = require('discord-paginationembed');
const songText = ["This is a long SongText", "That is Split up Over", "Multiple Sites", "End of Song"];
// The Splitting can happen via Discord.Js Util Class, it has a Splitter
const embeds = [];
for (let i = 1; i <= 4; ++i)
embeds.push(new Discord.MessageEmbed().setFooter('Page ' + i).setDescription(songText[i - 1]));
// Create Embeds here with the Content and push them into the Array
const myImage = message.author.displayAvatarURL();
new Pagination.Embeds()
.setArray(embeds)
.setAuthorizedUsers([message.author.id])
.setChannel(message.channel)
.setPageIndicator(true)
.setPage(1)
// Methods below are for customizing all embeds
.setImage(myImage)
.setThumbnail(myImage)
.setTitle('Test Title')
.setDescription('Test Description')
.setURL(myImage)
.setColor(0xFF00AE)
.build();
I have the following search criteria working very well in Gmail:
user#domain from:/mail delivery/ || /postmaster/ ||/Undeliverable/
I am trying to write Goole Apps code to return the same results. Here is the code:
var thread=GmailApp.search("user#domain from:/mail delivery/ || /postmaster/ ||/Undeliverable/ ");
I am getting different results. I am new to both Regex and Google Apps.
Try Amit Agarwal's tutorial on Gmail Search with Google Apps Script which includes Using Regular Expressions to Find Anything in your Gmail Mailbox:
function Search() {
var sheet = SpreadsheetApp.getActiveSheet();
var row = 2;
// Clear existing search results
sheet.getRange(2, 1, sheet.getMaxRows() - 1, 4).clearContent();
// Which Gmail Label should be searched?
var label = sheet.getRange("F3").getValue();
// Get the Regular Expression Search Pattern
var pattern = sheet.getRange("F4").getValue();
// Retrieve all threads of the specified label
var threads = GmailApp.search("in:" + label);
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var m = 0; m < messages.length; m++) {
var msg = messages[m].getBody();
// Does the message content match the search pattern?
if (msg.search(pattern) !== -1) {
// Format and print the date of the matching message
sheet.getRange(row,1).setValue(
Utilities.formatDate(messages[m].getDate(),"GMT","yyyy-MM-dd"));
// Print the sender's name and email address
sheet.getRange(row,2).setValue(messages[m].getFrom());
// Print the message subject
sheet.getRange(row,3).setValue(messages[m].getSubject());
// Print the unique URL of the Gmail message
var id = "https://mail.google.com/mail/u/0/#all/"
+ messages[m].getId();
sheet.getRange(row,4).setFormula(
'=hyperlink("' + id + '", "View")');
// Move to the next row
row++;
}
}
}
}
I have a Google Spreadsheet with two columns.
First column includes the name of a referrer and second column includes a free format text where some referred email addresses are mentioned. There might be multiple email addresses in one cell, or none.
Ex:
Referrer | Referral
--------------------------------------------------------------------------
Mister X | I would like to refer somebody#gmail.com and somebodyelse#outlook.com
Miss Y | myfriend#mail.com
Mister Z | None!
etc | ...
I would like to format the data such that for each referred address we have the referrer and the email address referred.
EX:
Referrer | Referral
--------------------------------------------------------------------------
Mister X | somebody#gmail.com
Mister X | somebodyelse#outlook.com
Miss Y | myfriend#mail.com
etc | ...
What is the best way of achieving this?
Here's your original data in a table.
Referrer Referral
Mister X I would like to refer somebody#gmail.com and somebodyelse#outlook.com
Miss Y myfriend#mail.com
Mister Z None!
Here's the same columns after they're over written.
Referrer none
Mister X somebody#gmail.com
Mister X somebodyelse#outlook.com
Miss Y myfriend#mail.com
Mister Z none
And here's the code. Currently, you select the two columns as we were shown and I over write them in the format your requested. Although with such a limited dataset one can never be 100% sure. So further testing would be good. I included the menu and some of my display routines which help me debug the program. I suppose you may want to change the range. Go for it. Have fun. I enjoyed writing it.
function onOpen()
{
var ui = SpreadsheetApp.getUi();
ui.createMenu('My Tools')
.addItem('Extract Emails','emailFishing')
.addToUi();
}
function emailFishing()
{
var rng = SpreadsheetApp.getActiveRange();
var rngA = rng.getValues();
var resultsA = [];
//var s = '[';
for(var i = 0;i < rngA.length; i++)
{
if(rngA[i][1])
{
matchA = extractEmails(rngA[i][1]);
if(matchA)
{
for(var j = 0; j < matchA.length;j++)
{
resultsA.push([rngA[i][0], matchA[j]]);
//s += '[' + rngA[i][0] + ', ' + matchA[j] + '], '
}
}
else
{
resultsA.push([rngA[i][0],'none']);
//s += '[' + rngA[i][0] + ', \'none\'],'
}
}
}
//s += ']';
var orng = SpreadsheetApp.getActiveSheet().getRange(rng.getRow(), rng.getColumn(), resultsA.length, resultsA[0].length);
orng.setValues(resultsA);
//dispStatus('Results Array', s, 500, 400);
}
function extractEmails (text)
{
return text.match(/([a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi);
}
function dispStatus(title,html,width,height)
{
// Display a modeless dialog box with custom HtmlService content.
var title = typeof(title) !== 'undefined' ? title : 'No Title Provided';
var width = typeof(width) !== 'undefined' ? width : 250;
var height = typeof(height) !== 'undefined' ? height : 300;
var html = typeof(html) !== 'undefined' ? html : '<p>No html provided.</p>';
var htmlOutput = HtmlService
.createHtmlOutput(html)
.setWidth(width)
.setHeight(height);
SpreadsheetApp.getUi().showModelessDialog(htmlOutput, title);
}
The function extractEmail came from Leniel Macaferi. From this post Extract all email addresses from bulk text using jquery. Although I left out the JQuery part.
I have a view page that currently has two columns of data shown, soon to be expanded to four. Each column contains the result of a QuerySet for that particular model.
Here's what I have in my views.py method:
if request.REQUEST["type"] == "text":
client = Client.objects.get(client_name = request.REQUEST["search"])
peerList = ClientPeers.objects.prefetch_related().filter(client = client.client)
compList = ClientCompetitors.objects.prefetch_related().filter(client = client.client)
else:
peerList = ClientPeers.objects.prefetch_related().filter(client = request.REQUEST["search"])
compList = ClientCompetitors.objects.prefetch_related().filter(client = request.REQUEST["search"])
for peer in peerList:
peerlst.append({"pid" : peer.parentorg.parentorg, "pname" : peer.parentorg.parentorgname})
for comp in compList:
complst.append({"cid" : comp.parentorg.parentorg, "cname" : comp.parentorg.parentorgname})
lst.append(simplejson.dumps(peerlst))
lst.append(simplejson.dumps(complst))
return HttpResponse(simplejson.dumps(lst), mimetype = "text/json")
This allows me to send a 2D array of data to the browser in the format
[ { //JSON }, { //JSON } ]
In my jQuery.ajax success function, I have
function handler(results) {
var data = JSON.parse(results);
for (var i = 0; i < data[0].length; i++)
$("#available_peers").append("<li>" + data[0][i].pname + "</li>");
for (var i = 0; i < data[1].length; i++)
$("#available_competitors").append("<li>" + data[1][i].cname + "</li>");
Firebug shows that the GET request works and I can see the data in the response tab. However, the console prints out
SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data
var data = JSON.parse(results)
This error disappears if I replace var data = JSON.parse(results) with
var peers = JSON.parse(data[0]);
var comps = JSON.parse(data[1]);
Why does one method work but another doesn't?
The jQuery ajax() call will make an intelligent guess as to the returned data type. In your example, function handler(results), the results variable will already be a decoded JSON object, containing two items in an array. The reason that JSON.parse(data[0]) works, is that you have returned JSON encoded data as a string.
Don't encode the individual list elements to JSON before placing in the output array:
lst.append(peerlst) # <-- Don't encode to JSON string here
lst.append(complst)
return HttpResponse(simplejson.dumps(lst), mimetype = "application/json") # <-- Single JSON encoding