Processing content of textarea once button is clicked - fable-f#

While learning Fable and Elmish I thought it is a good exercise to handle the input from a user and do something with it. So I tried to create a textarea and a button and if that button is pressed the input from the textarea should be submitted. However, I'm really puzzled with how to get the value from the textarea. Here is my starter:
type Model = string
type Msg = UserInput of string
let init () : Model = ""
let update (msg: Msg) (_: Model) =
let UserInput x = msg
x
let view (model: Model) dispatch =
div [] [ textarea [] []
button [] [str "submit"]
div [] [str model] ]
Ideally if the user enters some text into the textarea and presses the submit button I would like to echo the users input in the div at the bottom. Any idea how to solve this?

It appears that you are using Elmish. Note that this is an extra layer on top of the React bindings and it is very opinionated! You also can write React components directly or use an alternative system like Feliz, which looks more like modern TypeScript with hooks.
On to your question. You need to do two things:
dispatch a message every time the user changes the textarea value
Set the value of the textarea based on the model
open Fable.Core.JsInterop
open Fable.React
type Model = string
type Msg = UserInput of string
let init () : Model = ""
let update (msg: Msg) (_: Model) =
let (UserInput x) = msg
x
let view (model: Model) dispatch =
div
[]
[
textarea
[
Props.Value model
Props.OnChange
(fun e -> e.target?value |> UserInput |> dispatch)
]
[]
button [] [str "submit"]
div [] [str model]
]

Related

Mention username in a Discord Modal of the person who opened it [duplicate]

I want to create a modal like in the picture when the button is pressed. How can I make this model with Discord.py or nextcord?
You can find examples for modals in Nextcord here:
https://github.com/nextcord/nextcord/blob/master/examples/modals/
class Pet(nextcord.ui.Modal):
def __init__(self):
super().__init__("Your pet") # Modal title
# Create a text input and add it to the modal
self.name = nextcord.ui.TextInput(
label="Your pet's name",
min_length=2,
max_length=50,
)
self.add_item(self.name)
# Create a long text input and add it to the modal
self.description = nextcord.ui.TextInput(
label="Description",
style=nextcord.TextInputStyle.paragraph,
placeholder="Information that can help us recognise your pet",
required=False,
max_length=1800,
)
self.add_item(self.description)
async def callback(self, interaction: nextcord.Interaction) -> None:
"""This is the function that gets called when the submit button is pressed"""
response = f"{interaction.user.mention}'s favourite pet's name is {self.name.value}."
if self.description.value != "":
response += f"\nTheir pet can be recognized by this information:\n{self.description.value}"
await interaction.send(response)
#bot.slash_command(
name="pet",
description="Describe your favourite pet",
guild_ids=[TESTING_GUILD_ID],
)
async def send(interaction: nextcord.Interaction):
# sending the modal on an interaction (can be slash, buttons, or select menus)
modal = Pet()
await interaction.response.send_modal(modal)
class Modal(ui.Modal, title="test title"):
firstfield = ui.TextInput(label="firstfield",placeholder="write here", style=discord.TextStyle.short)
secondfield = ui.TextInput(label="secondfield",placeholder="write here", style=discord.TextStyle.short)
thirdfield = ui.TextInput(label="thirdfield:",placeholder="write here", style=discord.TextStyle.short)
first_big_field = ui.TextInput(label="first_big_field:",placeholder="write here", style=discord.TextStyle.long)
second_big_field = ui.TextInput(label="second_big_field:",placeholder="write here", style=discord.TextStyle.long)
Then u can call Modal() where u want

Pressed state of trumbowyg toolbar buttons not being read out by NVDA but are being read out by VoiceOver

I would like the pressed state of the trumbowyg toolbar buttons (bold/italic etc) to be read out by NVDA screen reader. I have implemented the aria-pressed solution, which works fine for VoiceOver; it reads out select/deselect when the buttons have been selected and deselected, however not for NVDA:
function addValuesToTextEditorButtons() {
const toggleButton = element => {
// Check to see if the button is pressed
var pressed = (element.getAttribute("aria-pressed") === "true");
// Change aria-pressed to the opposite state
element.setAttribute("aria-pressed", !pressed);
}
const handleBtnKeyDown = event => {
// Prevent the default action to stop scrolling when space is pressed
event.preventDefault();
toggleButton(event.target);
}
var buttons = $('.trumbowyg-button-pane .trumbowyg-button-group button[type="button"]');
buttons.each(function (index, element) {
let title = element.title.split(' ')[0]
element.value = title
element.setAttribute('aria-label', title)
element.setAttribute('aria-pressed', false)
element.setAttribute('role', 'button')
element.addEventListener('click', event => {
handleBtnKeyDown(event)
})
element.removeAttribute('tabindex')
});
}
First off, verify that the element you're setting aria-pressed on is a real button (or role='button'). It looks like that's true from your code snippet but would be the first thing to verify. ARIA attributes are only valid on certain elements. (See https://www.w3.org/TR/html53/dom.html#allowed-aria-roles-states-and-properties)
Some screen readers might still announce the value of the attribute even if it's not valid so sometimes that explains why one SR works (such as VO) whereas another does not (NVDA).
I've used aria-pressed successfully with all screen readers without a problem. For NVDA, it will announce the element as a "toggle button" and will say "pressed" or "not pressed" depending on the value.

SwiftUI how to get reference to editing Textfield inside a List?

Is it possible to find a particular view in SwiftUI based on its tag ? Or is there another solution to my problem below ?
Based on string in a Textfield in a Row in List A, am populating search results in List B.
When a row on a List B is tapped, I want the textField on List A to be updated.
But the problem is I dont know how to get hold of the active textField or the index of the row in the List A.
Please refer this image for clarity
Im trying to emulate this behaviour, which is common in desktop. You enter text in a Textfield and either using mouse or up down arrow keys to select an option and the Textfield gets updated with that option.
Here instead of PopOver am using a separate List view.
In the code below, you can see how to accomplish most of the things you require.
You mention you want to know which field you are typing on. You can do that by using the onEdintingChanged closure. This closure receives a boolean value that indicates if the field became active or inactive. You can use it to set a variable like in the example: activeField.
Another of your requests, was being able to refresh the List with every keystroke. The onReceive modifier subscribes to the binding of the TextField and executes your closure for each. There is however, what I think it is a bug: When there is text in both fields, the closure executes for both fields at every keystroke. The if statement comparing self.activeField is there to prevent that.
So, now, from the closure you can trigger an update on your external model. Since your List should be bound to the same model, it will refresh automatically.
Another of your requirements was that tapping on the list should update your text field. That is simple. If your textfield is bound to the same model, you just update the corresponding model variable and the field will update.
I hope I've been clear.
struct ContentView : View {
#State private var field1 = ""
#State private var field2 = ""
#State private var activeField: Int = 0
var body: some View {
VStack {
TextField("", text: $field1, onEditingChanged: { if $0 { self.activeField = 0 } })
.textFieldStyle(.roundedBorder)
.onReceive(field1.publisher().last()) { if self.activeField == 0 { print("FIELD 1 -> \(self.field1): \($0)") } }
TextField("", text: $field2, onEditingChanged: { if $0 { self.activeField = 1 } })
.textFieldStyle(.roundedBorder)
.onReceive(field2.publisher().last()) { if self.activeField == 1 { print("FIELD 2 -> \(self.field2): \($0)") } }
}
}
}

VS2010 Coded UI Test - Test builder unable to map two checkboxes with same text

I'm trying to create a coded UI test (with VS2010 Ultimate) for a simple web form page with two checkboxes and a submit hyperlink. The checkboxes have the same text label; "I Agree".
Using the coded UI test builder to record actions, only one checkbox is captured because both checkboxes have the same text / same UIMap Name.
Using the crosshair tool to select the second checkbox, it replaces the previous checkbox instance because they have the same text / same UIMap Name.
When the test is run, the first checkbox is checked, the second is not, and the hyperlink is clicked to submitted the form (failing validation).
How can I add the second checkbox to the test map and differentiate between the two?
If there are no unique properties on the checkboxes themselves, specify the parent object of each checkbox to differentiate them.
Example:
For
<div id="box1Parent">
<input label="I Agree"/>
</div>
<div id=box2Parent">
<input label="I Agree"/>
</div>
You would define the object like this:
public HtmlCheckBox AgreementBox1()
{
HtmlDiv parent = new HtmlDiv(browser);
parent.SearchProperties["id"] = "box1Parent";
HtmlCheckBox target = new HtmlCheckBox(parent);
target.SearchProperties["label"] = "I Agree";
return target;
}
Then, do the same for the second box, but point the parent to box2Parent. This would be your code in the non-designer section of the .uitest class.
There are multiple ways to do this.
Try to find out unique property of object like id, name.
Try to find out parent control/container of checkbox, then use {TAB} or {UP}/{DOWN} keys.
Use {TAB} key of keyboard. find out previous control -> click on that control -> use {TAB} from that control to get focus on checkbox control and use {UP}/{DOWN} arrow key to navigate.
Find out text of document and click on first or second occurrence of that as per your need.
Code to find out document Text,
public string GetCurrentPageVisibleTexts()
{
var window = this.UIMap.<WindowObject>
UITestControlCollection c = window.GetChildren();
var pgContent = (string)c[0].GetProperty("OuterHtml");
var document = new HtmlAgilityPack.HtmlDocument();
document.LoadHtml(pgContent);
// We don't want these in our result
var exclusionText = new string[] { "<!--", "<![CDATA", "function()", "</form>" };
var visibleTexts = new List<string>();
//var nodes = document.DocumentNode.Descendants().Where(d => !d.Name.ToLower().Equals("span"));
foreach (var elem in document.DocumentNode.Descendants())
{
// Foreach element iterate its path back till root
// and look for "display: none" attribute in each one of its parent node
// to verify whether that element or any of its parent are marked as hidden
var tempElem = elem;
while (tempElem.ParentNode != null)
{
if (tempElem.Attributes["style"] != null)
{
// if hidden attribute found then break.
if (tempElem.Attributes["style"].Value.ToLower().Contains("display: none")) break;
}
tempElem = tempElem.ParentNode;
}
// If iteration reached to head and element is found clean of hidden property then proceed with text extraction.
if (tempElem.ParentNode == null)
{
if (!exclusionText.Any(e => elem.InnerText.Contains(e))
&& (!elem.InnerText.Trim().IsNullOrEmpty())
&& (!elem.HasChildNodes))
{
visibleTexts.Add(elem.InnerText);
}
}
} // Foreach close
var completeText = string.Join(" ", visibleTexts).Replace(" ", " ");
return Regex.Replace(completeText, #"\s+", " ");
}

Clickable Url in Twitter

i have implemented a simple twitter reader in my app. I am able to get the tweets of a
user. But, if there is a url in this tweet, i cant click on it, as its not detected as an URL.
Is there a possibility to implement this function, so that urls in the tweet are displayed
as clickable url, and then launch for example a webbrowser?
Thank you very much
I assume you are using a TextBlock to show the tweet text, correct? If so, change it to a RichTextBox and all you need to do is use Run for text and Hyperlink for the links!
Also, make sure you set the IsReadOnly property of the RichTextBox to true in order for it to work properly!
Next, parse the tweet text with a regular expression to find links, and use the Hiperlink class to create a clickable link on it, and Run on the remaining text!
Here's a sample function that will parse a tweet and build the content for a RichTextBox:
private Block ParseTweet(string tweetText)
{
var paragraph = new Paragraph();
var lastIndex = 0;
foreach (Match m in Regex.Matches(tweetText, #"(http(s)?://)?([\w-]+\.)+[\w-]+(/\S\w[\w- ;,./?%&=]\S*)?"))
{
if (m.Index > 0)
paragraph.Inlines.Add(tweetText.Substring(lastIndex, m.Index));
var hyperlink = new Hyperlink()
{
NavigateUri = new System.Uri(m.Value, System.UriKind.RelativeOrAbsolute),
TargetName = "_blank"
};
hyperlink.Inlines.Add(m.Value);
paragraph.Inlines.Add(hyperlink);
lastIndex = m.Index + m.Length;
}
if (lastIndex < tweetText.Length)
paragraph.Inlines.Add(tweetText.Substring(lastIndex));
return paragraph;
}
You should call this function like so:
var tweetText = #"Testing: http://twitter.com -> link for twitter";
MyRichTextBox.Blocks.Add(ParseTweet(tweetText));
I think it's not possible but but you can parse your text to find URL (with regex) and display a hyperlink below the text.
1) you search for URLs in the text with a regex
2) if a URL is found, you create a HyperlinkButton with this URL

Resources