WPF split HTML string for every TextBlock - html

Does anyone know how to split the HTML string for every TextBlock? I split them, but something is wrong. The lines count are not the same in every page. How do I solve this issue?
Here's the code:
XAML:
<Window x:Class="Ebook.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:WPFMitsuControls;assembly=WPFMitsuControls"
Title="eBook" Height="600" Width="800"
Loaded="MainWindow_OnLoaded" Background="Silver">
<DockPanel>
<Viewbox Margin="10">
<Grid>
<controls:Book x:Name="myBook" Width="600" Height="400" Margin="20">
<controls:Book.ItemTemplate>
<DataTemplate>
<Border BorderThickness="4" BorderBrush="Gray" Background="White">
<ContentControl Content="{Binding .}" />
</Border>
</DataTemplate>
</controls:Book.ItemTemplate>
</controls:Book>
<Button Content="<" HorizontalAlignment="Left" VerticalAlignment="Center" VerticalContentAlignment="Center" Background="Transparent" Height="50" Click="AutoPreviousClick" />
<Button Content=">" HorizontalAlignment="Right" VerticalAlignment="Center" VerticalContentAlignment="Center" Background="Transparent" Height="50" Click="AutoNextClick" />
</Grid>
</Viewbox>
</DockPanel>
</Window>
CODE:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Globalization;
using System.IO;
namespace Ebook
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
string html_str = "<p>The standard <b>Lorem Ipsum</b> passage, used since the 1500s</p>"
+ "<p>'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'</p>"
+ "<p>Section 1.10.32 of 'de Finibus Bonorum et Malorum', written by Cicero in 45 BC</p>"
+ "<p>'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?'</p>"
+ "<p><u>1914 translation by H. Rackham</u></p>"
+ "<p>'But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?'</p>"
+ "<p>Section 1.10.33 of 'de Finibus Bonorum et Malorum', written by Cicero in 45 BC</p>"
+ "<p>'At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.'</p>"
+ "<p><i>1914 translation by H. Rackham</i></p>"
+ "<p>'On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains.'</p>";
private void AutoNextClick(object sender, RoutedEventArgs e)
{
myBook.AnimateToNextPage(false, 700);
myBook.Focus();
}
private void AutoPreviousClick(object sender, RoutedEventArgs e)
{
myBook.AnimateToPreviousPage(false, 700);
myBook.Focus();
}
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
List<string> lines = WrapText(html_str, 200, "Arial", 12);
int rows = 20;
int pages = lines.Count / rows;
string _Page = "";
int j = 0, k = 0;
TextBlock tb1;
for (int i = 0; i < pages; i++)
{
tb1 = new TextBlock();
tb1.TextWrapping = TextWrapping.Wrap;
tb1.Margin = new Thickness(5);
tb1.TextAlignment = TextAlignment.Justify;
_Page = "";
for (j = 0; j < rows; j++)
{
_Page += lines[rows * i + j] + "\n";
k++;
}
//myBook.Items.Add(new TextBlock { Text = _Page, TextWrapping = TextWrapping.Wrap, Margin = new Thickness(5), TextAlignment = TextAlignment.Justify });
tb1.Inlines.AddRange(MarkupProcessor.HTMLToWPF(_Page));
myBook.Items.Add(tb1);
}
}
static List<string> WrapText(string text, double pixels, string fontFamily, float emSize)
{
string[] originalLines = text.Split(new string[] { " " },
StringSplitOptions.None);
List<string> wrappedLines = new List<string>();
StringBuilder actualLine = new StringBuilder();
double actualWidth = 0;
foreach (var item in originalLines)
{
FormattedText formatted = new FormattedText(item,
CultureInfo.CurrentCulture,
System.Windows.FlowDirection.LeftToRight,
new Typeface(fontFamily), emSize, Brushes.Black);
actualLine.Append(item + " ");
actualWidth += formatted.Width;
if (actualWidth > pixels)
{
wrappedLines.Add(actualLine.ToString());
actualLine = new StringBuilder();
actualWidth = 0;
}
}
if (actualLine.Length > 0)
wrappedLines.Add(actualLine.ToString());
return wrappedLines;
}
}
}
http://i.stack.imgur.com/AEpsm.png
Here's the download link to the project: http://www.megafileupload.com/en/file/532650/WPF-Ebook-zip.html

You can`t control number of lines because of this:
tb1.TextWrapping = TextWrapping.Wrap;
Line count will depend on length of string. Long strings will be wrapped.

Related

Set different styles in a list

I'm creating a FAQ, I have an array with the questions and answers, I managed to render this array on my page, but I want to edit different styles for the questions and answers, how can I do this? here is my code:
My FAQ list:
const FAQ = ({ props }) => {
const history = useHistory();
const classes = useStyles();
const dispatch = useDispatch();
const { user, userlist, isLoading } = useSelector((state) => state.Authentication);
const [expanded, setExpanded] = React.useState(false);
const handleChange = (panel) => (event, isExpanded) => {
setExpanded(isExpanded ? panel : false);
};
const WellbeingData = [
{
index: 1,
question: "Lorem ipsum dolor sit amet?",
answer:
"Tenetur ullam rerum ad iusto possimus sequi mollitia dolore sunt quam praesentium. Tenetur ullam rerum ad iusto possimus sequi mollitia dolore sunt quam praesentium.Tenetur ullam rerum ad iusto possimus sequi mollitia dolore sunt quam praesentium.",
},
{
index: 2,
question: "Dignissimos sequi architecto?",
answer:
"Aperiam ab atque incidunt dolores ullam est, earum ipsa recusandae velit cumque. Aperiam ab atque incidunt dolores ullam est, earum ipsa recusandae velit cumque.",
},
{
index: 3,
question: "Voluptas praesentium facere?",
answer:
"Blanditiis aliquid adipisci quisquam reiciendis voluptates itaque.",
},
];
and here is my last failed try to render it correctly
const questionList = WellbeingData.map((data) => <div style={{fontSize: 18, fontWeight: 'bold'}}><li key={data.index}>{data.question}</li></div>)
const answerList = WellbeingData.map((data) => <div style={{fontSize: 16}}><li key={data.index}>{data.answer}</li></div>)
{questionList}
<br/>
{answerList}
What could I do to solve this...
If the styles are limited, lets say "Answered", "New", "Deleted", you can have one css class for each style (e.g .deletedAnswer .deletedQuestion) and add a new element to your object like type: something, then dynamically choose a class based on the value of type. the easiest way is to set the value to the class name:
{
index: 3,
question: "Voluptas praesentium facere?",
answer:
"Blanditiis aliquid adipisci quisquam reiciendis voluptates itaque.",
class: "deletedAnswer"
}
And then just putting the value of array[index].class to your element's class.

How to get the text of a section on an HTML page

I have a webpage with this section:
<section class="post__content">
At vero eos et accusamus et iusto odio dignissimos ducimus qui
blanditiis praesentium voluptatum deleniti atque corrupti quos
dolores et quas molestias excepturi sint occaecati cupiditate
non provident.
</section>
I need to get the text from that section.
I tried:
https://www.example.com/quote-of-the-day?d=01/09/2021/#post__content
IF the text is on the same PAGE as the script
console.log(document.querySelector("section.post__content").textContent
.replace(/(\r\n|\n|\r)/gm,"") // get rid of trailing newlines, remove if you need them
)
<section class="post__content">
At vero eos et accusamus et iusto odio dignissimos ducimus qui
blanditiis praesentium voluptatum deleniti atque corrupti quos
dolores et quas molestias excepturi sint occaecati cupiditate
non provident.
</section>
IF the text is on ANOTHER page which is on the same server as where you want to grab it, you can use jQuery or fetch. Here jQuery can parse the page and just grab the section
$.get("/quote-of-the-day?d=01/09/2021/ section.post__content",function(data) { console.log(data) })
Please note that class is .post__content and ID is #post__content
If NOT, then you need some server process
Try this:
const sectionText = document.querySelector("section.post__content").textContent
console.log(sectionText)
You can even create a function that gets an element's text:
const getElementText = selector => {
return document.querySelector(selector).textContent
}
const sectionText = getElementText("section.post__content")
console.log(sectionText)
NOTE: If you have more section tags with post__content class, then you should use document.querySelectorAll() which return an array of all nodes.

axios or fetch get local json - strange response format and Unexpected token in JSON then i tried to parse it

My axios response (or fetch, tried both) it's plain text (string). But I expect javaScript map. If I tried JSON.parse() (or from fetch .json()) I got error:
Uncaught (in promise) SyntaxError: Unexpected token in JSON at
position 0
at JSON.parse ()
at eval (List.vue?8915:66)
UTF-8 without BOM
I checked my json via few json validators online - json is valid
I tried create my json via some online json creator - the same error
so I have few questions:
I thought that json is a special format. If you got it via axios/fetch your response always will be js map? It's not true?
What is the best way to creating and validating json to be sure it's ok?
I use vue cli, there haven't json loader (i think so, not sure, it not use webpack, but I can't see some loaders). It could be problem? Or some environment settings? I tried to check it, but maybe can't find.
Or maybe ma header is still wrong, ad accept give me nothing?
votingService.ts
import axios, { AxiosResponse } from "axios";
export const getVotingsService = (): Promise<AxiosResponse> => {
return axios
.get("http://localhost:8080/fakeData/votings.json", {
headers: {
"accept": "application/json",
'Content-Type': 'application/json'
},
})
};
List.vue
...
private getVotings() {
getVotingsService().then(response => {
console.log("resp", response.data); //string, data is ok
console.log(JSON.parse(response.data)); //error
});
}
...
votings.json (in public folder)
{
"votings": [
{
"createDate": "20-07-20",
"deadline": "20-08-20",
"status": "active",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"createDate": "20-07-20",
"deadline": "20-08-20",
"status": "active",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"createDate": "20-07-20",
"deadline": "20-08-20",
"status": "active",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
}
chrome consola:
chrome network response:
chrome network headers:
Problem solved. I'm not sure why, but VSCode didn't want to save me file without BOM, so I still had UTF-8 with BOM
On August 20, 2020, Axios released v0.20.0 which addresses the issue of removing the byte order marker (UTF-8 BOM) when transforming the response.

How can I Extract information from HTML page using Python?

Based on the HTML page below, I am looking to extract this information about this property:
1- Number of bathrooms
2- Living Area
3- Energy Rating
4- Description
<div class="bloco-imovel-resumo-dados">
<div id="Cpl_modulodadosresumidos_module_holder" class="modulo-dados-resumidos">
<h2 class="lbl_descricao_dados">Property Information</h2>
<ul class="bloco-dados">
<li>
<b>Condition:</b> <span>Renewed</span></li>
<li>
<b>Living Area:</b><span> 80 m<sup>2</sup></span></li>
<li>
<b>Total Area:</b><span> 0 m<sup>2</sup></span></li>
<li>
<b>Bathrooms:</b><span> 1 </span></li>
<li>
<b>Bedrooms:</b><span> 2 </span></li>
<li>
<b>Energy Rating:</b><span> C</span></li>
</ul>
<div class="bloco-imovel-texto">
<h3 class="lbl_description">
Description </h3>
<p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident.Nam libero tempore, omnis dolor repellendus.</p>
</div>
I tried to extract the number of bathrooms by writing the code below, but I have received this error "AttributeError: 'HtmlElement' object has no attribute 'find_element_by_css_selector"
from lxml import html,etree
with open(r'listing.html', "r") as f:
page = f.read()
tree = html.fromstring(page)
Bathrooms = tree.find_element_by_css_selector('Bathrooms')
print('Bathrooms: {}'.format(tree.cssselect(Bathrooms)[0].text))
I am a beginner at HTML and CSS so I need your help.
import lxml.html
with open(r'listing.html', "r") as f:
page = f.read()
root=lxml.html.parse(page)
object_list = root.xpath(".//div[#class='bloco-dado']")
bathrooms = object_list[0]
text=bathrooms.text_content()
print(text)
Try this once, May this works

How to Achieve Just the Ctrl + A Functionality of Contenteditable Attribute?

I'm trying to display a div with some example code for users. I want them to be able to select inside the div and use Ctrl + A to select all of the example code, but I don't want them to be able to edit the actual text (lest the remove a bit on accident and then it won't work).
I'm achieving this right now through contenteditable set on the div, but how do I get the same functionality of this attribute sans the actual text editing?
EDIT: Looking at the solution linked in #Mr. Llama's comment, I can use this method to achieve the primary functionality I'm looking for. However, if possible I would like to simply allow for the Ctrl + A command my users are familiar with, and still allow for the manual highlighting of snippets of the div's text. Again, all while disallowing the addition or removal of any text.
Seems to work for me when I prevent the onkeydown, oncut and onpaste events.
for (const elm of document.getElementsByClassName('editable-not-editable')) {
elm.setAttribute('contenteditable', true);
elm.spellcheck = false;
elm.oncut = () => false;
elm.onpaste = () => false;
elm.onkeydown = (event) => {
if (event.metaKey || event.ctrlKey) {
return;
}
event.preventDefault();
}
}
<div class="editable-not-editable">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
</div>