I want to see if the text contained in a span which itself is contained in a div contains certain text.
This is the HTML:
<div class="funds">
<span>banking</span>
<span class="m-l-sm">
<b>EUR 1,000</b>
</span><!--anchor-->
</div>
I want to check if <span class="m-l-sm"> contains 'EUR'.
One way I tried to do this (among several others) is:
var checkFunds = element(by.id("m-l-sm"));
if (checkFunds.getText().toContain('EUR'&'GBP')) {
//do something
}
I get an error saying .toContain() is not a function.
I'm at a bit of a loss as to how to proceed.
.toContain() is a Jasmine matcher's method. It is usually used for assertions, e.g.:
expect(checkFunds.getText()).toContain('EUR');
Since it looks like you actually want to do something if you see a substring in a string - you need to get to the actual text of the element, which means you need to resolve the promise returned by .getText(). Then, you can check if substring EUR is inside the text:
var checkFunds = element(by.id("m-l-sm"));
checkFunds.getText().then(function (text) {
if (text.indexOf('EUR') >= 0) {
// do something
}
});
Related
I'm trying to compare two different Strings by HBS.
The function look like this:
hbs.registerHelper('if_equal', function(a, b, opts) {
if (a == b) {
return opts.fn(this)
} else {
return opts.inverse(this)
}
});
Works great!
But the problem is in this lines:
{{#each info.categories}}
<li>{{this.title}}</li>
{{!-- {{#if_equal this.title "מלגזות"}}
{{/if_equal}} --}}
{{/each}}
s you can see I'm trying check if two string are equal inside the loop.
The problem is how I can back to {{info}} one.
To the global object inside the loop.
And than make loop into the object.
I'm not sure I understand your question, but if you want to access info in the loop you can do it by #root.info
https://handlebarsjs.com/reference.html#data-root
I have several attributes set as attributesToRetrieve. In my template though only some of these are displayed. Roughly something like this:
<div id="results">
<div>{{_highlightResult.attr1.value}}</div>
<div>{{_highlightResult.attr2.value}}</div>
<div>{{_highlightResult.attr3.value}}</div>
</div>
This way the attributes will be rendered in any case, and highlighted if they contain a matched word.
Now I'd like to add another section where all other attributes can be displayed but only if they contain a matched word to be highlighted, something like:
<div id="results">
<div>{{_highlightResult.attr_1.value}}</div>
<div>{{_highlightResult.attr_2.value}}</div>
<div>{{_highlightResult.attr_3.value}}</div>
<!--
The following div will be rendered and displayed only
if any of these special attributes contain an highlighted word.
Only an attribute containing a matched word will be displayed
-->
<div class="other-attr">
{{_highlightResult.Long_SpecialAttr_1.value}}
{{_highlightResult.SpecialAttr_2.value}}
{{_highlightResult.SpecialAttr_3.value}}
</div>
</div>
As mentioned in the comment, this section will be rendered and displayed only if any of these special attributes contain an highlighted word, also only an attribute containing a matched word will be displayed.
Plus as you can see there is a Long_SpecialAttr_1, it's a long text attribute, wich I'd like to have it displayed as a snippeted attribute.
To give a better idea (maybe) what I'm trying to achieve for this additional section is something like the one Google display below every search results, a sort of text blob text with ellipsis containing the marked words of these attributes.
Is this possible? I'm using algolia instasearch.js, thank you!
UPDATE
Thanks to #Jerska for his answer, unfortunately a small bit of code wasn't working in my case, specifically:
['highlight', 'snippet'].forEach(function (type) {
data['_' + type + 'Result'].forEach(function (elt) {
elt.display = elt.matchLevel !== 'none';
});
});
giving me an error in the console stating data._snippetResult.forEach() is undefined. So I modified that bit with this:
for(var el in d._snippetResult)
{
// create new property with bool value, true if not "none"
d._snippetResult[el].display = d._snippetResult[el].matchLevel !== 'none';
};
First of all, just to clarify the settings of your index before going forward, Algolia also highlights the attributes in attributesToSnippet.
Also, to have an ellipsis on the attributes you snippet, you can set snippetEllipsisText.
So you might want to use these settings in your index:
attributesToHighlight: ['attr_1', 'attr_2', 'attr_3', 'SpecialAttr_2', 'SpecialAttr_3'],
attributesToSnippet: ['Long_SpecialAttr_1:3'], // Snippet should contain max 3 words
snippetEllipsisText: '…' // This is the utf-8 "Horizontal ellipsis" character
On the front-end side, in instantsearch.js you can use the transformData parameter on almost any widget to be able to access and/or modify the data passed to the template.
In this specific example, we'll want to have a look at transformData.item on the hits widget.
The first step would be to log the data:
search.addWidget(
instantsearch.widgets.hits({
transformData: {
item: function (data) {
console.log(data);
return data;
}
}
})
);
This will allow you to see that kind of response:
_highlightResult: {
attr_1: {
value: 'lorem <em>ipsum</em> dolor <em>sit</em>',
matchLevel: 'full',
matchedWords: ['ipsum', 'sit']
},
attr_2: {
value: 'lorem <em>ipsum</em> dolor',
matchLevel: 'partial',
matchedWords: ['ipsum']
},
attr_3: {
value: 'lorem',
matchLevel: 'none',
matchedWords: []
},
// ...
},
_snippetResult: {
Long_SpecialAttr_1: {
value: 'lorem <em>ipsum</em> dolor …', // Let's assume Long_SpecialAttr_1 was equal to 'lorem ipsum dolor sit'
matchLevel: 'full'
}
}
Unfortunately here, the API is a bit inconsistent since as you can see, snippeted attributes don't have the matchedWords attribute that highlighted attributes have. You can choose to set it both in attributesToSnippet and attributesToHighlight if you really want the info.
However, for your use-case, we just need matchLevel. What we want, is to display elements only if matchLevel !== 'none'. Unfortunately, Hogan.js, the underlying template engine of instantsearch.js doesn't allow for much flexibility, so you can't just put this comparison in your template.
A solution could be to precompute these conditions inside the transformData:
transformData: {
item: function (data) {
['highlight', 'snippet'].forEach(function (type) {
var group = data['_' + type + 'Result'];
for (var attr in group) {
if (!group.hasOwnProperty(attr)) continue;
var elt = group[attr];
elt.display = elt.matchLevel !== 'none';
};
});
data.displaySpecial = false ||
data._snippetResult.Long_SpecialAttr_1.display ||
data._highlightResult.SpecialAttr_2.display ||
data._highlightResult.SpecialAttr_3.display;
return data;
}
}
And then use these new attributes in your template:
<div id="results">
<div>{{{_highlightResult.attr_1.value}}}</div>
<div>{{{_highlightResult.attr_2.value}}}</div>
<div>{{{_highlightResult.attr_3.value}}}</div>
<!--
The following div will be rendered and displayed only
if any of these special attributes contain an highlighted word.
Only an attribute containing a matched word will be displayed
-->
{{#displaySpecial}}
<div class="other-attr">
{{#_snippetResult.Long_SpecialAttr_1.display}}
{{{_highlightResult.Long_SpecialAttr_1.value}}}
{{/_snippetResult.Long_SpecialAttr_1.display}}
{{#_highlightResult.SpecialAttr_2.display}}
{{{_highlightResult.SpecialAttr_2.value}}}
{{/_highlightResult.SpecialAttr_2.display}}
{{#_highlightResult.SpecialAttr_3.display}}
{{{_highlightResult.SpecialAttr_3.value}}}
{{/_highlightResult.SpecialAttr_3.display}}
</div>
{{#displaySpecial}}
</div>
(By the way, to render HTML, you should use {{{ ... }}} instead of {{...}}, I've replaced them here)
I am working on node js with mongodb. I am getting the value of doc in view file.
{{#each doc}}
<div class="abstract" data-reactid=".1ejbmifi4u8.1.1.0.1.2.0:$35.0.0.1.2.0" id="content">
{{this.content}}</div>
{{/each}}
this will print the value of content.
I want to print only 40 characters of this content on view page and then want to implement "read more" to go to full content page.
Guessing by the syntax, you are using Handlebars or some similar derivative. If it's not Handlebars, you'll have to modify the below a little to match your framework, but it should be similar. Leave a comment if it's not and I'll edit.
Handlebars supports what is known as helpers which allow you to manipulate data fed into your views.
You could write a helper named, for example, excerpt, like so:
Handlebars.registerHelper('excerpt', function(data, url) {
if (data.length > 40) {
return new Handlebars.SafeString(
data.substring(0, 40) + '… Read more"
);
}
return data;
});
You can then use it like {{excerpt this.content this.readMoreUrl}}, where this.readMoreUrl is whichever property provides the relevant URL.
I am not familiar with the JavaScript MVC but You can do something like this in JS:
content = this.content
if(content.length > 40)
content_to_print = content.substr(0,40)
content_to_print = content_to_print+' Read More...'
Hope this helps!
I want to get the element through javascript based on attribute value, as per the example I want to get element through attribute "doc-cid" and the value of "doc-cid" is dynamic.
<p align="center" style="font-family:times;" doc-cid="11303">
<font size="2" doc-cid="11304">55</font></p>
<p id="demo">Click the button to change the text of a list item.</p>
<button onclick="myFunction()">Try it</button>
<script>
function myFunction()
{
var list = document.getElementsByTagName("doc-cid=\"11303\"")
alert(list.getAttribute("doc-cid"));
}
</script>
I'll start with a few pointers about your above code, and follow through with a solution.
POINTERS
doc-cid is not a "TagName", it is a custom attribute. hence, your function trying to getElementsByTagName will always fail for "doc-cid".
doc-cid can by dynamic (or not) it doesn't matter. A lookup function will always get the CURRENT DOM value of your element (unless you specifically make it do otherwise).
I suggest you use the new "data-*" attribute in html, it keeps your markup valid (if that is important to you). The use would be as follows:
your content
SOLUTION
function getElementByAttribute (attribute, value, start) {
var start = start || document,
cache, //store found element
i;
function lookup(start) {
// if element has been found and cached, stop
if (cache) {
return;
} else if (start.getAttribute(attribute) === value) { // check if current element is the one we're looking for
cache = start;
return;
} else if (start.childElementCount > 0) { // if the current element has children, loop through those
lookup(start.children[0]);
} else if (start.nextElementSibling) { // if the current element has a sibling, check it
lookup(start.nextElementSibling);
} else {
return;
}
}
lookup(start);
return cache;
}
You simply give the function the attribute name you are looking up, the value you need to match and the starting point of the lookup (if no starting point is specified it'll start at the very beginning of your page (much slower).
Below is an example for your markup:
// you have no easy to get starting point, so we'll traverse the DOM
getElementByAttribute('doc-cid', '11303');
If you want to start at a better node, you can add a wrapper div element and give it id="wrapper" then you could call the function as follows:
var start = document.getElementById('wrapper');
getElementByAttribute('doc-cid', '11303', start);
Hope this helps.
I'm working on designing a site in WP, but I'm at a loss for the right words to google. What I'm looking for is a "text container that can be toggled". I have a syntax highlighting plugin for posting code, but I don't want the code to be visible in large blocks considering it may be a little distracting. I was wondering if anyone could link me to a plugin or give me the technical term for what I'm thinking of, where you can put the text in a group and then be able to toggle whether it is visible or not within the page.
It sounds like what you are looking for is simply applying a CSS class to the element and then using jQuery or some other JS library to toggle its visibility. Example below (code is not optimized in order to explain some of the concepts. This can, read "should", be cleaned up):
// This is HTML/CSS
<body>
...
<p>Here is some normal text.</p>
Show/hide source code for displayText method
<div class="source_code" id="source_code_for_displayText_method">
// Groovy code
...
public void displayText(String message) {
outputStream.write(message)
}
...
</div>
...
Show/hide source code for download method
<div class="source_code" id="source_code_for_download_method">
// Groovy code
...
GParsPool.withPool(threads) {
sessionDownloadedFiles = localUrlQueue.collectParallel { URL url ->
downloadFileFromURL(url)
}
}
...
</div>
...
Show/hide all source code sections
...
</body>
You can default all source code sections to hidden:
// This is CSS
.source_code {
display: hidden;
}
Then you would use JS to provide the toggle ability:
// This is JavaScript
// This toggles a specific section by using an id ("#") selector
$('#source_code_displayText_method_toggle_link').onClick(function() {
$('#source_code_for_displayText_method').toggle();
});
// This toggles all source code sections by using a class (".") selector
$('#source_code_all_toggle_link').onClick(function() {
$('.source_code').toggle();
});
Some thoughts:
If you toggle all sections, you need to determine what the current state is -- if some are currently shown and others hidden, this will invert each. If you want "hide all" and "show all", then use .hide() and .show() respectively.
If you are manually adding the source code sections and want semantic selectors, the above is fine. If you are building some kind of automation/tool to allow you to repeat this, you'll probably want to use generated ids and helper links, in which case it would look like:
.
// This is HTML/CSS
<body>
...
<p>Here is some normal text.</p>
Show/hide source code for displayText method
<div class="source_code" id="source_code_1">
// Groovy code
...
public void displayText(String message) {
outputStream.write(message)
}
...
</div>
...
Show/hide source code for download method
<div class="source_code" id="source_code_2">
// Groovy code
...
GParsPool.withPool(threads) {
sessionDownloadedFiles = localUrlQueue.collectParallel { URL url ->
downloadFileFromURL(url)
}
}
...
</div>
...
Show/hide all source code sections
...
</body>
With the JavaScript to handle id parsing:
// This is JavaScript
// This toggles a specific section by using a dynamic id ("#") selector
$('.source_code_toggle_link').onClick(function(elem) {
var id = $(elem).attr("id");
// Split on the _ and take the last element in the resulting array
var idNumber = id.split("_")[-1];
var codeBlock = $('#source_code_' + idNumber);
codeBlock.toggle();
});