Currently I have the following element
<h6 class="header">
Chance of Precipitation: <span data-bind="text: PrecipitationLabel"></span>
</h6>
This works fine, but I don't really need a span tag in my case --the observable only loads for display, so I don't need to update an element. I know I could bind with a computed/dependent variable that combines the "Chance..." text with PrecipitationLabel, but that takes some of the static markup out of the view, which is not ideal.
Is there something similar to Razor's tags to output just a literal?
The functionality you are looking for was added to github 11 days ago. The syntax would be:
<h6 class="header">
Chance of Precipitation: <!-- ko text: PrecipitationLabel --><!-- /ko -->
</h6>
It is not yet included in any published download.
Or you may use this,
<h6 class="header" data-bind="text: 'Chance of Precipitation: ' + PrecipitationLabel()" />
Related
I want to display two items of carousel side by side in the frontend in TYPO3, but I can display just one item now.
I have no idea how I can write some codes with Fluid in a HTML-file to display two items.
I use a plug-In bootstrap_package and bild a carousel like a carousel of bootstrap_packgae now. But the carousel of bootstrap_package has just a item on a slide.
However, I want to display two items on a page and if a user click a button (preview or next), another item will be displayed. My image is like this:
Now my codes in a HTM-file CarouselStartseiteAngebote.html (in Template) seem like so:
<f:if condition="{records}">
<div id="carousel-{data.uid}" class="carousel carousel-small carousel-startseite-angebote carousel-{data.pi_flexform.transition} slide" {f:if(condition: data.pi_flexform.interval, then: 'data-interval="{data.pi_flexform.interval}" ')}data-wrap="{f:if(condition:data.pi_flexform.wrap,then:'true',else:'false')}" data-ride="carousel" {f:if(condition: data.pi_flexform.interval, then: 'data-bs-interval="{data.pi_flexform.interval}"')} data-bs-wrap="{f:if(condition:data.pi_flexform.wrap,then:'true',else:'false')}" data-bs-ride="carousel">
<div class="carousel-inner carousel-startseite-angebote-inner">
<f:for each="{records}" as="item" iteration="iteration">
<f:variable name="itemClass">item</f:variable>
<f:if condition="{iteration.isFirst}">
<f:variable name="itemClass">{itemClass} active</f:variable>
</f:if>
<f:variable name="itemClass">{itemClass} carousel-item</f:variable>
<f:variable name="itemClass">{itemClass} carousel-item-layout-{f:if(condition: item.data.layout,then:item.data.layout,else: 'custom')}</f:variable>
<f:variable name="itemClass">{itemClass} carousel-item-type-{item.data.item_type}</f:variable>
<div class="{itemClass}" data-itemno="{iteration.index}">
<f:render partial="Carousel/General/BackgroundImage" arguments="{_all}" />
<div class="carousel-content carousel-startseite-angebote-content">
<f:render partial="Carousel/Item/{item.data.item_type -> bk2k:format.upperCamelCase()}" arguments="{_all}" />
</div>
</div>
</f:for>
</div>
<f:render partial="Carousel/Control/ControlStartseiteAngebote" arguments="{_all}" />
</div>
</f:if>
In a CarouselStartseiteAngebote.html (in Partial):
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:if condition="{records -> f:count()} > 1">
<button data-slide="prev" data-target="#carousel-{data.uid}" data-bs-slide="prev" data-bs-target="#carousel-{data.uid}" type="button" class="carousel-control carousel-control-prev carousel-startseite-angebote-control-prev">
<span class="startseite-angebote-icons-prev carousel-startseite-angebote-icons slidenow"></span>
<span class="visually-hidden">{f:translate(key: 'previous', extensionName: 'rasanidesign_startseite-angebote')}</span>
</button>
<button data-slide="next" data-target="#carousel-{data.uid}" data-bs-slide="next" data-bs-target="#carousel-{data.uid}" type="button" class="carousel-control carousel-control-next carousel-startseite-angebote-control-next">
<span class="startseite-angebote-icons-next carousel-startseite-angebote-icons"></span>
<span class="visually-hidden">{f:translate(key: 'next', extensionName: 'rasanidesign_startseite-angebote')}</span>
</button>
</f:if>
</html>
In a TextAndImageForCarouselStartseiteAngebote.html (in Partial):
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:link.typolink parameter="{item.data.link}" additionalAttributes="{draggable:'false'}">
<div class="carousel-sa-content">
<!-- Slider1 -->
<div class="carousel-startseite-angebote-content-inner-container row saslider">
<!-- Imagefeld -->
<div class="carousel-startseite-angebote-left col">
<f:if condition="{item.images.0}">
<f:variable name="image-startseite-angeboteConfig">{settings.responsiveimages.contentelements.{data.CType}}</f:variable>
<f:variable name="image-startseite-angeboteConfig">{image-startseite-angeboteConfig.{item.data.item_type}}</f:variable>
<bk2k:data.imageVariants as="variants" variants="{variants}" multiplier="{image-startseite-angeboteConfig.multiplier}" gutters="{image-startseite-angeboteConfig.gutters}" corrections="{image-startseite-angeboteConfig.corrections}" />
<f:render partial="Media/Rendering/ImageStartseiteAngebote" arguments="{file: item.images.0, data: item.data, settings: settings, variants: variants}" />
</f:if>
</div>
<!-- Textfeld -->
<div class="carousel-startseite-angebote-right col">
<div class="carousel-startseite-angebote-right-container">
<h{item.data.header_layout} class="carousel-startseite-angebote-header-h4 carousel-header{f:if(condition: item.data.header_class, then: ' {item.data.header_class}')}{f:if(condition: item.data.header_position, then: ' text-{item.data.header_position}')}"><f:format.htmlspecialchars doubleEncode="false">{item.data.header}</f:format.htmlspecialchars></h{item.data.header_layout}>
<f:if condition="{item.data.subheader}">
<h{item.data.subheader_layout} class="carousel-startseite-angebote-header-h2 carousel-startseite-angebote-image carousel-subheader{f:if(condition: item.data.subheader_class, then: ' {item.data.subheader_class}')}{f:if(condition: item.data.header_position, then: ' text-{item.data.header_position}')}"><f:format.htmlspecialchars doubleEncode="false">{item.data.subheader}</f:format.htmlspecialchars></h{item.data.subheader_layout}>
</f:if>
<span class="carousel-startseite-angebote-bodytext"><f:format.html>{item.data.bodytext}</f:format.html></span>
</div>
</div>
</div>
</div>
</f:link.typolink>
</html>
What schould I wirte codes to display two items side by side? The items have to switch step by step and they have to be repeated.
I tryed to give a condition on the line 6 in the CarouselStartseiteAngebote.html:
<f:if condition="{iteration.isFirst} && {iteration.index}">
If I check it using developer-tool, then I could find two items. But I can't display anything in the frontend, even first item, because the word "active" is disappeared.:
How can I add the word "active" for the two items? ALso, if another item comes up, how can I remove the word "active" from the previous item?
I hope someone can give me an advice or correct codes. Thank you.
That't actually more a styling thing. Take a slider plugin that fit your needs e.g. https://swiperjs.com/demos#slides-per-view
and build the template (html, css, js) according to your needs.
In general:
Special interactive elements in a web page are build normally by javascript that takes some standard HTML like lists and transforms it to a carousel, an accordion, a slider or similar.
This javascript needs a container which is identified by a class or an id so that the controls only effect the contained elements of this element.
In this way you can have two carousels (or similar) in a page which are independent of each other.
In TYPO3 you have full control over the rendering and can generate everything you like by adding your own fluid templates. for the unique identifier you can use the uid field of the content element or any relevant record.
You can display anything as far as you have the javascript library to modify the original HTML and to change the HTML for your wished behaviour.
Look in the web to get a javascript library which handles your behaviour, include it in the page, build the required HTML markup and don't forget to add the initialization call for each element (that could either behind the HTML) or with an asset viewhelper in the usual position at the end of the page.
I am storing the HTML in a string and using it in the HTML file, I have used the HTML sanitize pipe.
below is my string
privacyNotice = "<div style=\"color: #ff0000;font-style: italic;\">Before continuing to the Application, you are required to read and acknowledge this Privacy Notice</div>......<div><input type=\"checkbox\" (change)=\"changeAcknowledgeBtnState()\"/><span class=\"pl-5\">I acknowledge terms of the privacy notice</span> </div> <div> <button class=\"ackBtn\" [disabled]=\"disableButton\" (click)=\"changePrivacyNoticeStatus()\">Acknowledge </button> </div>";
below is the html file code
<div class="container" [innerHTML]='privacyNotice | safeHtml'>
I have used the safeHtml pipe by referring this example
the disabled attribute to the button is not working and also changePrivacyNoticeStatus() is also not getting called
The safeHtml pipe only parses HTML, it is impossible to parse Angular code such as [disabled]="angularCode()" or (click)="changePrivacyNoticeStatus()". The [] and () syntax is part of Angular's data binding syntax that is compiled into Javascript when you are building your Angular project. Your string is provided at runtime and is expected to be pure and ready to go HTML: It can't be resolved from Angular code to Javascript at runtime anymore.
The fact that you are using dynamic content in the form of a string is considered a code smell in Angular, see if you can't solve this problem by writing a component for it and by providing Inputs to the component, rather than generating HTML code strings.
Another option could be content projection:
<app-privacy-notice>
<button class="ackBtn" [disabled]="disableButton" (click)="changePrivacyNoticeStatus()">
Acknowledge
</button>
<input type="checkbox" (change)="changeAcknowledgeBtnState()"/>
</app-privacy-notice>
privacy-notice.component.html:
<div style="color: #ff0000;font-style: italic;">
Before continuing to the Application, you are required to read and
acknowledge this Privacy Notice
</div>
<div>
<ng-content select="input"></ng-content>
<span class="pl-5">I acknowledge terms of the privacy notice</span>
</div>
<div>
<ng-content select="button"></ng-content>
</div>
I am trying to add live region support in a web page to make NVDA usable with the page. However, I have seen quite a different behavior with aria-live attributes than expected.
I have tried adding a single live region which is hidden and I dump all the messages (each message enclosed in <p> tag) into that region to be read by screen reader. It works fine, but the only problem is that the first message inserted into live region div is never read by the NVDA screen reader. Subsequent messages are read perfectly. This live regions div is created dynamically when the first message is to be announced.
aria-live="assertive" doesn't really interrupt the current flow to announce the message.
I am using knockout in web page. When HTML div, which is marked as live-region, is displayed based on knockout condition, then it is not detected by screen reader.
For example:
<!-- ko if: $data -->
<div aria-live="polite" data-bind="text: $data">
</div>
<!-- ko -->
When page is loaded initially, $data is null. So live-region div is absent. But when data is fetched that div gets inserted. However, NVDA doesn't read the content in added div. Is this expected behavior? Is there any workaround to fix this behavior?
Quick answer, pressed for time.
You must have your live region on the page at page render. This primes the browser to monitor it for updates. Adding the element after the fact only primes the browser, but does not trigger it.
I forked your pen and got it working in the first button (through the browser pronounces "XYZ" as "zeyes"). This is in debug mode so there is no CodePen code in there at all (nor frames) to jack it up:
http://s.codepen.io/aardrian/debug/wgWqVm
Non-debug mode so you cans see the code:
http://codepen.io/aardrian/pen/wgWqVm
Your code puts the aria-live on an element wrapped within a Knockout ko if: statement, so it is not rendered to the page at load:
<p>Last name:
<!-- ko if: lastName -->
<strong aria-live="polite" data-bind="text: lastName"></strong>
<!-- /ko -->
</p>
I tweaked it to put the live region around the ko if: check, and now it is announced when the button is pressed:
<p>Last name:
<div aria-live="polite">
<!-- ko if: lastName -->
<strong data-bind="text: lastName"></strong>
<!-- /ko -->
</div>
</p>
Yes, I put a <div> in a <p>, but that is only for demonstration purposes.
Tested in NVDA 2016.4 / Firefox 50.1.1 and it works as I believe you intend. I did not touch the second one at all.
I'm trying to make responsible grid with thumbnails using bootstrap and knockout. Currently i have the next html:
<div class="row">
<!-- ko if: toys().length == 0 -->
<div>No toys in category</div>
<!-- /ko -->
<!-- ko foreach: toys-->
<div class="col-lg-2 col-md-3 col-sm-4 col-xs-6 previewGridItem">
<a class="thumbnail" data-bind="attr: { href: '#!/toy/' + id }">
<img data-bind="attr: {src: images[0] ? images[0] : '/Content/img/NoImage.jpg' }" />
<span data-bind="text: name"></span>
</a>
</div>
<!-- /ko -->
</div>
Sometimes i'm getting correct grid. But in most cases (ofcourse depending on size of images and length of item's names) i've got something like this:
.
How to properly align items? The most simple answer is to set height of images to constant, but then the proportions of images are ruined. More over, i want images resizing including height. Text are limited by 2 lines per image.
Live demo: JSFiddle
I suggest you to take a look at Gridalicious plugin - it's created exactly for this type of situations. It's also pretty fast, and can be easly adjusted for your needs with built in configurable parameters as well as simply editing uncompressed version of plugin accordingly to your needs.
http://suprb.com/apps/gridalicious/
For now, i solved problem using jQuery plugin mentioned in comment by Artanis. I've also have to use plugin imagesLoaded because i have ajax call which loading images. In result i've written next code:
window.imagesLoaded(".previewGridItem", function(instance) {
$(".previewGridItem").matchHeight();
});
I do not think that it's the best solution, because now i have 40kb (12Kb minimized) libraries only to align images. But for now i can't find a solution only with css.
Existing HTML looks like such:
<span>
<i class='icon-class'></i> OBJECT NAME HERE
</span>
I realize I can add a span and bind the text value to the object name, but it breaks the existing CSS layout. I could tweak the CSS, but before I go doing that (it's quite a complex template) I wanted to make sure there is not a way to do a virtual element that simply displays a string value.
<!-- ko string: objects.name --><!-- /ko -->
or something would be awesome, but from what I can see in the docs you can only use foreach or if in a virtual element.
Am I missing something or am I going to have to use a span?
You can use text binding:
<!-- ko text: objects.name --><!-- /ko -->
Here is working fiddle: http://jsfiddle.net/3RLfR/