How can I add a downward counting timer to my Elm page? - time

I'm pretty new to Elm and I've been trying to make a quiz while struggling really hard. What I need is a timer that counts downwards from 10 to 1 and once it hits 1 it switches to another page. I've tried using the time example from Elm's site as well as the Elm-timer library but all without success.
The code I'm working with:
module QuizPage exposing (..)
import Browser
import Browser.Navigation as Nav
import Html exposing (..)
import Html.Attributes exposing (..)
import Url
import Html.Events exposing (..)
-- MAIN
main : Program () Model Msg
main =
Browser.application
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
, onUrlChange = UrlChanged
, onUrlRequest = LinkClicked
}
-- MODEL
type alias Model =
{ key : Nav.Key
, url : Url.Url
, uporabnik : String
, igra : Int
}
init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url key =
( Model key url "" 0, Cmd.none )
-- UPDATE
type Msg
= LinkClicked Browser.UrlRequest
| UrlChanged Url.Url
| SpremembaImena String
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
LinkClicked urlRequest ->
case urlRequest of
Browser.Internal url ->
( model, Nav.load (Url.toString url) )
Browser.External href ->
( model, Nav.load href )
UrlChanged url ->
( { model | url = url }
, Cmd.none
)
SpremembaImena ime ->
({model | uporabnik = ime}, Cmd.none)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
-- VIEW
view : Model -> Browser.Document Msg
view model =
{
title = "Kviz"
, body =
[div [style "width" "100%", style "text-align" "center", style "background-color" "powderblue", style "position" "fixed", style "width" "100%", style "height" "100%"]
[ Html.br[][]
, Html.div [style "width" "100%", style "font-size" "20px"][ Html.div[][Html.text "Koda vaše igre: 1234"], Html.div [][Html.text "Čas do konca 7s"] ]
, Html.br [][]
, Html.br [][]
, Html.br [][]
, Html.br [][]
, div [style "font-size" "30px"][Html.text "Vprašanje"]
, Html.br [][]
, Html.br [][]
, Html.br [][]
, Html.br [][]
, Html.div [ style "margin-left" "43%" ][ viewLink "EndPage.elm" "Odgovor1"]
, Html.br [][]
, Html.br [][]
, Html.div [ style "margin-left" "43%"][ viewLink "EndPage.elm" "Odgovor2"]
, Html.br [][]
, Html.br [][]
, Html.div [ style "margin-left" "43%" ][ viewLink "EndPage.elm" "Odgovor3"]
, Html.br [][]
, Html.br [][]
, Html.div [ style "margin-left" "43%" ][ viewLink "EndPage.elm" "Odgovor4"]
]]
}
viewLink : String -> String -> Html msg
viewLink path name =
a [ href path , style "text-decoration" "none", style "color" "black", style "width" "200px", style "magin-left" "200px", style "display" "block", style "font" "bold 11px Arial", style "border-top" "1px solid #CCCCCC", style "text-decoration" "none", style "background-color" "#EEEEEE", style "color" "#333333", style "padding" "2px 6px 2px 6px", style "border-right" "1px solid #CCCCCC", style "border-bottom" "1px solid #CCCCCC", style "border-left" "1px solid #CCCCCC", style "align" "center" ] [ text name ]
Any help is highly appreciated!

The answer to my question is a simple countdown timer.
ELM:
module Main exposing (..)
import Browser
import Html exposing (..)
import Task
import Time
-- MAIN
main =
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{
cas : Int
}
init : () -> (Model, Cmd Msg)
init _ =
( Model 10, Cmd.none
)
-- UPDATE
type Msg
= Tick Time.Posix
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Tick newTime ->
if model.cas == 0 then
( { model | cas = 0 }
, Cmd.none
)
else
( { model | cas = (racun model) }
, Cmd.none
)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Time.every 1000 Tick
racun : Model -> Int
racun model =
model.cas - 1
-- VIEW
view : Model -> Html Msg
view model =
let
first = String.fromInt (model.cas)
in
h1 [] [ text (first) ]
HTML:
<html>
<head>
<style>
/* you can style your program here */
</style>
</head>
<body>
<main></main>
<script>
var app = Elm.Main.init({ node: document.querySelector('main') })
// you can use ports and stuff here
</script>
</body>
</html>

Related

Wear OS Button Background

Button(
onClick = {
raceOn = !raceOn
if (raceOn) {
text.value = "Stop!"
color.value = Color.Red
} else {
text.value = "Go!"
color.value = Color.Green
}
},
modifier = Modifier.background(color = color.value),
content = {
Text(
text = "${text.value}",
)
}
)
Using the code above, I got the attached image. What I want is the inside of the button to be green and not the background behind it. I couldn't the right property to modify.
Has anyone here tried to modify the Button background? Or perhaps suggest another solution. I tried the OutlinedButton and wasn't successful.
Thanks!
Use the MaterialTheme ButtonColors.
val colors: ButtonColors = ButtonDefaults.primaryButtonColors(backgroundColor = Color.Red)
Button(onClick = { /*TODO*/ }, colors = ButtonDefaults.primaryButtonColors()) {
// TODO
}
You can also update via setting the MaterialTheme defaults.
val wearColorPalette: Colors = Colors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200,
secondaryVariant = Teal200,
error = Red400,
onPrimary = Color.Black,
onSecondary = Color.Black,
onError = Color.Black
)
...
MaterialTheme(
colors = wearColorPalette,
typography = Typography,
// For shapes, we generally recommend using the default Material Wear shapes which are
// optimized for round and non-round devices.
content = content
)

Plotly Dash Heatmap not updating with dropdown selection

I am new to plotly dash and i'm trying to make a heatmap that changes with a dropdown selection. The dropdown is to choose a month, but the heatmap doesn't change!
My data frame is called 'New'.
Here's my code:
Month_Default = New['Month'].unique()
Month_def = 2
#create the dash app
app = dash.Dash()
app.layout = html.Div([
html.H1('//Title'),
html.Div([
html.Div([
html.H4('Select Month...'),
dcc.Dropdown(
id='Month_dropdown',
options=[{'label': i, 'value': i} for i in Month_Default],
value = Month_Def
),
],
style={'width': '48%', 'display': 'inline-block'}),
dcc.Graph(id='heatmap',
figure = {
'data': [go.Heatmap(
x=New['Days'].where(New['Month']==2),
y=New['Hour'],
z=New['Usage'],
colorscale='Viridis')],
'layout': go.Layout(
xaxis = dict(title = 'Days'),
yaxis = dict( title = 'Hours'),
)})
]),])
#app.callback(
dash.dependencies.Output(component_id='heatmap',component_property='figure'),
[dash.dependencies.Input(component_id='Month_dropdown',component_property='value')]
)
def update_graph(Month_dropdown):
filtered_df = New[New['Month'] == Month_dropdown]
heat_fig = go.Heatmap(filtered_df,
x='Days', y='Hour', z='Usage',
colorscale='Viridis',
title='PM KWH Usage')
return heat_fig
have created New dataframe in the way you described it in comments
using dash 2.0.0 hence only need to import dash
two key steps missed
did not app.run_server() to start the dash app
no callback to respond to Dropdown
instead of repeating code in dash layout and callback moved figure creation to just the callback
import dash
from jupyter_dash import JupyterDash
import plotly.graph_objects as go
from dash.dependencies import Input, Output, State
import pandas as pd
import numpy as np
New = pd.DataFrame(
{"date": pd.date_range("1-jan-2021", "15-jun-2021", freq="H")}
).assign(
Usage=lambda d: np.random.uniform(0, 1, len(d)),
Month=lambda d: d["date"].dt.month,
Days=lambda d: d["date"].dt.day,
Hour=lambda d: d["date"].dt.hour,
)
Month_Default = New["Month"].unique()
Month_def = 2
# create the dash app
# app = dash.Dash()
app = JupyterDash(__name__)
app.layout = dash.html.Div(
[
dash.html.H1("//Title"),
dash.html.Div(
[
dash.html.Div(
[
dash.html.H4("Select Month..."),
dash.dcc.Dropdown(
id="Month_dropdown",
options=[{"label": i, "value": i} for i in Month_Default],
value=Month_def,
),
],
style={"width": "48%", "display": "inline-block"},
),
dash.dcc.Graph(id="heatmap"),
]
),
]
)
#app.callback(Output("heatmap", "figure"), Input("Month_dropdown", "value"))
def updateGraph(value):
if not value:
value = Month_def
return {
"data": [
go.Heatmap(
x=New["Days"].where(New["Month"] == value),
y=New["Hour"],
z=New["Usage"],
colorscale="Viridis",
)
],
"layout": go.Layout(
xaxis=dict(title="Days"),
yaxis=dict(title="Hours"),
margin={"l": 0, "r": 0, "t": 0, "b": 0},
),
}
app.run_server(mode="inline")

ACE editor adding special characters

The use case is to display server logs in the UI built using Angular9.
I am using ACE editor to display text content received from server upon a http call and the server responds with recent 1000 lines of logs
To verify the content i did console.log() to view the text content in the chrome dev tool.
Console output received from server
While loading the same content to editor I notice special characters
Ace editor content while using in text mode
Attached 2 screenshot to compare
HTML Content
<div ace-editor #codeEditor style="min-height: 550px; width:100%; overflow: auto;"></div>
Typescript
import { Component, ViewChild, ElementRef, Input, SimpleChanges } from '#angular/core';
import * as ace from 'ace-builds';
import 'ace-builds/src-noconflict/mode-json';
import 'ace-builds/src-noconflict/theme-github';
import 'ace-builds/src-noconflict/ext-beautify';
const THEME = 'ace/theme/github';
const LANG = 'ace/mode/text';
#Component({
selector: 'app-text-editor',
templateUrl: './text-editor.component.html',
styleUrls: ['./text-editor.component.css']
})
export class TextEditorComponent {
#ViewChild('codeEditor') codeEditorElmRef: ElementRef;
private codeEditor: ace.Ace.Editor;
#Input() textObject;
#Input() readMode;
data: any;
mode: any;
constructor() { }
ngOnChanges(changes: SimpleChanges) {
for (const properties of Object.keys(changes)) {
if (properties == 'textObject') {
const currentJSONObject = changes[properties];
if (currentJSONObject.currentValue && currentJSONObject.firstChange == false)
this.codeEditor.setValue(currentJSONObject.currentValue, -1);
else
this.data = currentJSONObject.currentValue
}
if (properties == 'readMode') {
const currentReadMode = changes[properties];
if (currentReadMode.firstChange == false)
this.codeEditor.setReadOnly(currentReadMode.currentValue);
else
this.mode = currentReadMode.currentValue
}
}
}
ngAfterViewInit() {
const element = this.codeEditorElmRef.nativeElement;
const editorOptions: Partial<ace.Ace.EditorOptions> = {
highlightActiveLine: true,
displayIndentGuides: true,
highlightSelectedWord: true,
};
this.codeEditor = ace.edit(element, editorOptions);
this.codeEditor.setTheme(THEME);
this.codeEditor.getSession().setMode(LANG);
this.codeEditor.setShowFoldWidgets(true);
this.codeEditor.setHighlightActiveLine(true);
this.codeEditor.setShowPrintMargin(false);
this.codeEditor.setReadOnly(this.readMode);
this.codeEditor.navigateFileEnd();
if (this.data)
this.codeEditor.setValue(this.data, - 1);
if (this.mode)
this.codeEditor.setReadOnly(this.mode);
}
}
This are not characters added by ace, but color control characters sent by the terminal. If you do not want to display colors, and only want the text use the following function
var CSIRegexp;
function getCSIRegexp() {
if (CSIRegexp) return CSIRegexp;
// http://www.inwap.com/pdp10/ansicode.txt
var classes = {
C0 : "\\x00-\\x1F", //
SPACE : "\\x20\\xA0" , // Always and everywhere a blank space
G0 : "\\x21-\\x7E", //
Intermediate : "\\x20-\\x2F", // !"#$%&'()*+,-./
Parameters : "\\x30-\\x3F", // 0123456789:;<=>?
Uppercase : "\\x40-\\x5F", // #ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
Lowercase : "\\x60-\\x7E", // `abcdefghijlkmnopqrstuvwxyz{|}~
Alphabetic : "\\x40-\\x7E", // (all of upper and lower case)
Delete : "\\x7F" , // Always and everywhere ignored
C1 : "\\x80-\\x9F", // 32 additional control characters
G1 : "\\xA1-\\xFE", // 94 additional displayable characters
Special : "\\xA0\\xFF" , // Same as SPACE and DELETE
ESC : "\\x1b" , //
Ignore : "\\x7F\\x00-\\x1F\\x80-\\x9F" // Delete|C0|C1
};
var g = /:ESC:(\[:Parameters:*:Intermediate:?:Alphabetic:?|:Intermediate:+:Parameters:|:Parameters:|:Lowercase:|)|[:Ignore:]/;
var inBrackets = false;
var source = g.source.replace(/(\\.)|([\[\]])|:(\w*):/g, function(_, esc, b, cls) {
if (esc) return esc;
if (b) {
inBrackets = b == "[";
return b;
}
if (!cls) return ":";
var r = classes[cls];
if (!/ESC|Delete|C0|C1/.test(cls)) {
r += classes.Ignore;
}
if (!inBrackets && cls != "ESC")
r = "[" + r + "]";
return r;
});
return CSIRegexp = new RegExp(source, "g");
}
to remove control character before setting data to the editor
this.codeEditor.setValue(this.data.replace(getCSIRegexp(), ""), - 1);
You can test it with the following call:
"\x1b[1mreal text\x1b[10m".replace(getCSIRegexp(), "")

node-graphviz does not generate the expected png file

I am new to node-graphviz, which is a Node.js interface to the GraphViz graphing tool.
I want to draw a directed graph and save it into memory using the code:
var graphviz = require('graphviz');
var debug = true;
function draw (hbGraph) {
/** Create the digraph */
var vGraph = graphviz.digraph('Happens-Before-Graph'),
eventNodes = {};
/** Create nodes for digraph */
for (var i = 0; i < hbGraph.eventNodes.length; i++) {
/** Note, eventNodes is a sparse array */
var event = hbGraph.eventNodes[i];
if (event != undefined) {
var node = vGraph.addNode(event.id, {
'color': common.COLOR.GREY,
'style': common.STYLE,
});
eventNodes[node.id] = node;
}
}
/** Create edges for digraph, just ignore for this question */
if (debug) {
// Create digraph G
var g = graphviz.digraph("G");
// Add node (ID: Hello)
var n1 = g.addNode( "Hello", {"color" : "blue"} );
n1.set( "style", "filled" );
// Add node (ID: World)
g.addNode( "World" );
// Add edge between the two nodes
var e = g.addEdge( n1, "World" );
e.set( "color", "red" );
// Print the dot script
console.log( g.to_dot() );
// Set GraphViz path (if not in your path)
g.setGraphVizPath( "/usr/local/bin" );
// Generate a PNG output
g.output( "png", "test01.png" );
}
console.log( vGraph.to_dot() );
vGraph.setGraphVizPath( "/usr/local/bin" );
vGraph.output('png', 'test02.png');
}
After running the code, file test01.png is generated while file test02.png is not without any exception. Both two results of to_dot() methods are successfully printed on the console.
The printout of to_dot() method for test02.png is:
digraph Happens-Before-Graph {
"1" [ color = "grey" ];
"7" [ color = "grey" ];
"8" [ color = "grey" ];
"9" [ color = "grey" ];
"10" [ color = "grey" ];
"11" [ color = "grey" ];
"12" [ color = "grey" ];
"13" [ color = "grey" ];
"14" [ color = "grey" ];
}
I want to why file test02.png is not generated and how it can be generated. Could anyone help me?
In addition, the documenation about this library cannot be generated, so I am unfamiliar with it.
Additional information: link to node-graphviz is node-graphviz
The answer is just to remove the minus sign - in the digraph.
Since the documentation of node-graphviz cannot be built, I just post the right answer here.

ckeditor balloonpanel not staying attached to an element when scrolling

UPDATE balloon panels are staying attached in below code. We still have an issue where when we close a balloon panel, and then scroll afterward, the balloon panel that was just closed reappears. Here’s the updated code.
HERE WAS THE ORIGINAL QUESTION I am trying to get the ckeditor balloonpanel to stay attached to the element it was initially attached to; currently, when I scroll in the editor, the balloonpanels do not stay in place. The problem is that the balloonpanels shift when the user scrolls in the editor -- they do not remain attached to their initial element they were attached to when I scroll in the editor. Here is the code for the ckeditor plugin. It creates a balloonpanel in a for loop on return of an web service Ajax call and stores the panel in a global array called panels :
( function() {
var arr = new Array();
var panels = [];
var saveCmd = {
readOnly: 1,
modes: { wysiwyg: 1,source: 1 },
exec: function( editor ) {
if ( editor.fire( 'grade_level_score' ) ) {
var $form = editor.element.$.form;
/**
* Destroys the balloon panel by removing it from DOM and purging
* all associated event listeners.
*/
// https://github.com/ckeditor/ckeditor-dev/blob/64749bb245d1e91f6a4ac4e97c9648ec47acda91/plugins/balloonpanel/plugin.js#L743-L745
var panel;
while ( ( panel = panels.pop() ) ) {
panel.destroy();
}
arr = []; // clear the array of user-editable areas
panels = []; // clear the array of panels
// https://stackoverflow.com/a/48022658
var ele = $(editor.editable().$);
var elementOfClass;
var i = 1;
// class "ice-ice-editable" is in a span
$('span',ele).each(function(){
// https://stackoverflow.com/a/35866999
var iceIceEditableClass = "ice-ice-editable";
var hasClassIceIceEditable = $(this).hasClass(iceIceEditableClass);
if( hasClassIceIceEditable ) {
console.log($(this).text());
console.log($(this).attr('class'));
console.log($(this).attr('id'));
var userEditable = "user-editable-" + i;
// If the specified attribute already exists, only the value is set/changed.
this.setAttribute("id","user-editable-" + i);
var record1 = { id : userEditable , userEditableArea : $(this).text() };
arr.push(record1);
i++;
}
});
var gradeLevelObject = new Object();
gradeLevelObject.textAreas = arr;
// var responseGradeLevelScoreWS = gradeLevelScore(gradeLevelObject);
// BEGIN for testing
var result = '{"textAreas":[{"id":"user-editable-1","userEditableArea":"[Insert information specific to what is being addressed (a brief description of request(s) and/or concern(s). Specific training resource document for letter writing assistance will be referenced here.] ","score":22.24,"readingGrade":7,"issues":["asdf","zxcv"]},{"id":"user-editable-2","userEditableArea":"[Insert information specific to what is being addressed (a brief description of request(s) and/or concern(s). Specific training resource document for letter writing assistance will be referenced here.] ","score":22.24,"readingGrade":0,"issues":[]},{"id":"user-editable-3","userEditableArea":"[Insert information specific to what is being addressed (a brief description of request(s) and/or concern(s). Specific training resource document for letter writing assistance will be referenced here.] ","score":22.24,"readingGrade":0,"issues":[]},{"id":"user-editable-4","userEditableArea":"[Insert information specific to what is being addressed (a brief description of request(s) and/or concern(s). Specific training resource document for letter writing assistance will be referenced here.] ","score":22.24,"readingGrade":0,"issues":[]}]}';
var responseGradeLevelScoreWS = JSON.parse(result);
// END for testing
console.log(responseGradeLevelScoreWS);
var i;
for (i = 0; i < responseGradeLevelScoreWS.textAreas.length; i++){
if ( responseGradeLevelScoreWS.textAreas[i].readingGrade > 6 ) {
var j;
var issues = '';
for (j = 0; j < responseGradeLevelScoreWS.textAreas[i].issues.length; j++) {
issues += '<p>' + responseGradeLevelScoreWS.textAreas[i].issues[j] + '</p>';
}
panel = new CKEDITOR.ui.balloonPanel( editor, {
title: 'Grade: ' + responseGradeLevelScoreWS.textAreas[i].readingGrade + '. Score: ' + responseGradeLevelScoreWS.textAreas[i].score,
content: ( (typeof issues === 'undefined' || issues == null) ? 'There are no suggestions in order to descrease the grade level score' : issues ),
width: 500,
height: 120
});
var element = editor.document.getById(responseGradeLevelScoreWS.textAreas[i].id);
panel.attach( element );
panel.registerFocusable(element);
panels.push( panel );
issues = '';
}
}
// We'll use throttling for scroll listener to reduce performance impact.
var scrollListener = CKEDITOR.tools.eventsBuffer( 100, function() {
for (i = 0; i < panels.length; i++) {
panels[i].attach( editor.document.getById( responseGradeLevelScoreWS.textAreas[i].id ), {
focusElement: false,
show: false
} );
}
} );
editor.window.on( 'scroll', scrollListener.input );
if ( $form ) {
try {
//$form.submit();
} catch ( e ) {
// If there's a button named "submit" then the form.submit
// function is masked and can't be called in IE/FF, so we
// call the click() method of that button.
if ( $form.submit.click )
$form.submit.click();
}
}
}
}
};
var pluginName = 'grade_level_score';
// Register a plugin named "save".
CKEDITOR.plugins.add( pluginName, {
// jscs:disable maximumLineLength
lang: 'en,en-au,en-ca,en-gb,es,es-mx', // %REMOVE_LINE_CORE%
// jscs:enable maximumLineLength
icons: 'grade_level_score', // %REMOVE_LINE_CORE%
hidpi: true, // %REMOVE_LINE_CORE%
init: function( editor ) {
// Save plugin is for replace mode only.
if ( editor.elementMode != CKEDITOR.ELEMENT_MODE_REPLACE )
return;
var command = editor.addCommand( pluginName, saveCmd );
command.startDisabled = !( editor.element.$.form );
editor.ui.addButton && editor.ui.addButton( 'Grade_Level_Score', {
//label: editor.lang.save.toolbar,
label: "Grade Level Score",
command: pluginName,
toolbar: 'custom,100'
} );
}
} );
} )();
Only Balloon Toolbar has built-in functionality for automatic reposition on scroll. Balloon Panel itself is a static element. However, it can be easily achieved by attaching scroll listener and repositioning visible panels on scroll:
// We'll use throttling for scroll listener to reduce performance impact.
var scrollListener = CKEDITOR.tools.eventsBuffer( 100, function() {
for (i = 0; i < panels.length; i++) {
panels[i].attach( editor.document.getById(ids[i]), {
focusElement: false,
show: false
} );
}
} );
editor.window.on( 'scroll', scrollListener.input );
See this codepen for the full code (reusing some parts of your original code).

Resources