ws-replace
The attribute ws-replace creates a Doc or seq hole. The element on which this attribute is set will be replaced with the provided Doc(s). The name of the hole is the value of the ws-replace attribute.
ws-hole
The attribute ws-hole creates a Doc or seq hole. The element on which this attribute is set will have its contents replaced with the provided Doc(s). The name of the hole is the value of the ws-hole attribute.
Can you help me clearly distinguish these two concepts?
https://developers.websharper.com/docs/v4.x/fs/ui#reactive
ws-replace replaces the entire element, while ws-hole just replaces the contents. Look at the examples in the documentation you linked to. Notice how with ws-replace, the <div> element disappears and is completely replaced by the "Welcome" paragraph. Whereas with ws-hole, the <div> element is still there, wrapped around the "Welcome" paragraph.
Using ws-replace
<div ws-replace="Content"></div>
becomes:
<p>Welcome to my site.</p>
Using ws-hole
<div ws-hole="Content"></div>
becomes:
<div>
<p>Welcome to my site.</p>
</div>
Related
I am using the following Google Sheets formula to translate some fields containing HTML tags:
=GOOGLETRANSLATE(A2, "en", "de")
However, the translation results in a messed up HTML and extra spaces between tags opening or closing, especially if there are many nested tags.
For example:
<div> <p>paragraph text</p> </div>
will result in:
<div> <p> Absatztext </ P> </ Div>
Sometimes, the translator changes the tags opening and closing and put extra spaces between some attributes also the closing tags letters are in uppercase.
Issues like:
<p> Absatztext <P />
<a href = " # "> Link </ A>
Sometimes, text are added before the tag closing
<h2 Was> ist Pilates? </h2>
it should be:
<h2> Was ist Pilates? </h2>
Demo here:
https://docs.google.com/spreadsheets/d/11MOZjTknFGdwuAp6g3VUa0o5OQaW44hxN2uEvqnL3jw/edit?usp=sharing
How can I fix those problems?
try simple fix like:
=LOWER(SUBSTITUTE(GOOGLETRANSLATE(A1, "en", "de"), "/ ", "/"))
UPDATE:
=SUBSTITUTE(A1, TRIM(REGEXREPLACE(A1, "</?\S+[^<>]*>", )),
GOOGLETRANSLATE(TRIM(REGEXREPLACE(A1, "</?\S+[^<>]*>", )), "EN", "DE"))
If you don't mind doing it in a single formula and just want to solve the problem, you could try splitting it and only translating what's not an HTML tag.
Put all HTML tags and closing tags in a separate sheet, so you can check for them. I'll put mine in 'tags'!A1:B128.
Considering you have your original text in A1, you can split it up by < and >:
=SPLIT(A1,"<>")
then on a line below (or elsewhere, for me it'll be A2) you can check if the first word in each cell is found among the tags with:
NOT(COUNTIF(tags!$A$1:$B$128,INDEX(SPLIT(A2," "),1,1)))
translate it if it's true with
GOOGLETRANSLATE(A2, "en", "de")
or add the brackets back with
"<"&A2&">" so the whole formula will look like
=IF(NOT(COUNTIF(tags!$A$1:$B$128,INDEX(SPLIT(A2," "),1,1))),GOOGLETRANSLATE(A2, "en", "de"), "<"&A2&">")
then on a line below, just join the whole row back to a single cell with
=JOIN("",A3:L3)
You can hide rows 2 and 3 for convenience, or even put them on a separate sheet along with the tags. You can also add a condition not to add < and > if it's empty, so you can join up the whole row without looking at how long it is.
If you'd like to do this in a single formula, you'd have to write a script for it, as some formulas act strangely with arrayformula and sometimes are barely usable.
I think the most most convenient solution nowerdays is to use a custom JS-Function (Extensions >> AppScripts):
var spanish = LanguageApp.translate('This is a <strong>test</strong>',
'en', 'es', {contentType: 'html'});
// The code will generate "Esta es una <strong>prueba</strong>".
LanguageApp.translate (apidoc) accepts as fourth option a contentType, which can be text or html.
For huge tables be aware that there are daily limits (quotas)!
I think I might just be over complicating things instead of keeping it simple.
My question is: I want to capture the title of a blog post into a prop variable, and the author who wrote it into another prop variable.
My thought would be to create a page load rule focusing only on the path of /blog. From there I would scrape the page looking for the class that defines it, and then pass it into my prop through DTM.
<div class="field field-name-title">
<h2>Online Education</h2>
<div class="field field-name-body">
<p>
<em> by Author Name</em>
</p>
</div>
</div>
I create a page rule pick my prop and set it as: div.field.field-name-title.innerText But when I set it, all I'm seeing being passed is the "div.field.field-name-title.innerText"
Am I tackling this in the wrong way?
The values you enter in a text field are literal, with the exception of %data_element% syntax, which signifies a reference to a Data Element (there are a couple of other built-in variable references, as well).
Point is, if you want to populate your Adobe Analytics variable from scraping page content, you need to create a Data Element that returns the desired value, and then reference the Data Element in the text field for the Adobe Analytics variable.
That aside, your selector is wrong. What you've done is some weird mix of css selector and javascript syntax.
Below is an example of what you can do, based on your posted HTML:
<div class="field field-name-title">
<h2>Online Education</h2>
<div class="field field-name-body">
<p>
<em> by Author Name</em>
</p>
</div>
</div>
Data Element: Article Title
First, create a Data Element to get the article title from the page, based on your html structure.
Go to Rules > Data Elements > Create New Data Element
Fill out the fields with the following:
Name: article_title
Type: CSS Selector
CSS Selector Chain: div.field-name-title h2
get the value of: text
[X] Scrub whitespace and linebreaks using cleanText
Then, click Save Changes
Data Element: Article Author
Next, create another Data Element to get the article author from the page, based on your html structure.
Go to Rules > Data Elements > Create New Data Element
Fill out the fields with the following:
Name: article_author
Type: CSS Selector
CSS Selector Chain: div.field-name-body em
get the value of: text
[X] Scrub whitespace and linebreaks using cleanText
Then, click Save Changes
Page Load Rule: Populate Variables
Finally, within the various form fields of your Page Load Rule, you can now reference your Data Elements with %data_element_name% syntax.
Tip: Once you start typing the Data Element name out (starting with % prefix), DTM will show an auto-complete dialog, listing Data Elements matched.
If you need to reference the Data Element within a javascript custom code box within the Page Load Rule, you can use the following syntax:
_satellite.getVar('data_element_name');
Where 'data_element_name' is the name of your Data Element.
Example:
s.prop1 = _satellite.getVar('article_title');
Note: Unlike the form field syntax, you should not wrap your Data Element's name with %
I cannot get Capybara for find a checkbox element.
I've tried all the usual ways:
find_field
check
find
click_on
It's as if the element isn't there. If I select the parent element, and look at it's innerHTML the checkbox is included:
(byebug) all(:css, '.checkbox.form-group').last['innerHTML']
\n <input type=\"checkbox\" id=\"google_agreed_to_terms_at\" value=\"1\" required=\"true\" ng-model=\"agreed_to_terms\" required-notification=\"Please agree to the terms and conditions\" class=\"ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required\" bs-validation=\"\">\
but selecting the child elements it's not there:
(byebug) all(:css, '.checkbox.form-group').last.all :xpath, './*'
[#<Capybara::Node::Element tag="label"
path="//HTML[1]/BODY[1]/DIV[2]/DIV[1]/DIV[2]/FORM[1]/DIV[1]/LABEL[1]">]
I feel like I'm going mad.
Here's the relevant code (copied from save_and_open_page)
<div class="checkbox form-group">
<input type="checkbox" id="agreed_to_terms_at" value="1" required="true" ng-model="agreed_to_terms" required-notification="Please agree to the terms and conditions" class="ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required" bs-validation="">
<label class="label-light" for="agreed_to_terms_at">
I have read and agree to the terms</label>
</div>
I thought maybe rails was generating slightly non-compliant HTML, so I've gone to writing the checkbox by hand, but it didn't help.
What's going on here?
The checkbox is hidden to allow for uniform styling across all browsers. Since you have a label element correctly associated you can tell check to click the label instead of the actual checkbox
check('agreed_to_terms_at', allow_label_click: true)
which will click the checkbox if visible and if not it will click the label. If you want it to only click the label you can do
find(:label, 'I have read and agree').click
Or
find(:label, for:'agreed_to_terms_at').click
Due to CSS styling, the checkbox element was being hidden and the label used to present it. So the element was getting skipped over by capybara's default behaviour to ignore hidden elements.
I worked around it using
find('#agreed_to_terms_at', :visible => false).trigger('click')
Inside a capybara test, I need to fill in a text field that doesn't have a unique id or class attribute.
The text field (the field called title in this case) can appear anywhere on the page. The only thing we know is that the text field is wrapped in a div and this div sits immediately after an h3 tag which has the content "Title"
<h3>Title</h3>
<div class="input-row clear">
<input id="ember5046" class="ember-view ember-text-field" type="text">
</div>
<h3>Work Location</h3>
<div class="input-row clear">
<input id="ember5048" class="ember-view ember-text-field" type="text">
</div>
How can I do it?
We are not allowed to use xpath (company policy)
We are not allowed to do index based selectors like all("input")[0]
I think it should be possible with the css adjacent siblings combinator selector. Something like:
h3[text=Title] + div
This gives you the next element matching the thing after the +. If you rather want everything that matches you could use the ~ operator instead. These siblings selector can only help you to find things after a certain node. Going backwards is not possible as far as I know.
i am running into problem, concerning append. i ve a dynacmic collabsible, which i fill with a dynamic list. i want to append this list after the header h3 of the collabsible.
when i append it to the collabsible, it does not appear in the
<div class="ui-collapsible-content ui-collapsible-content-collapsed"> </div>
but after. therefor i get a space between the content header and the list, which i want to avoid.
i tried this:
$('some-selector > ui-collapsible-content ui-collapsible-content-collapsed') but it does not work.
any hints?
If you are trying to append inside
<div class="ui-collapsible-content ui-collapsible-content-collapsed"> </div>
Then you should use:
$('div.ui-collapsible-content.ui-collapsible-content-collapsed').append($content);
Where $content is either a jQuery object, a DOM element or a HTML string. Note the . in the selector, which specifies a class (or two).
See append.