Data-sly-list is adding white space, causing bugginess - css

I'm having an issue where an unordered list created by data-sly-list is adding whitespace that isn't represented in the DOM or by any class. If I manually code the list rather than letting data-sly-list handle it, the whitespace isn't added.
 <div class="bullets">
    <ul class="columns unordered-list" id="stateList">
      <div data-sly-unwrap data-sly-list.slidesNode="${resource.listChildren}">
        <div data-sly-unwrap data-sly-list.states="${slidesNode.listChildren}">
          <li data-sly-test="${states.valueMap.flag}">
<sly data-sly-use.htmlpaths="${'htmlpaths.js' # thePath=states.valueMap.path}" data-sly-unwrap>
${states.valueMap.name}
</sly>                    
</li>
        </div>
    </div>
    </ul>
</div>
If I hardcode the list like the following, there's no whitespace
  <div class="bullets">
    <ul class="columns unordered-list" id="stateList">
<li>Accessibility   
</li>
<li>Accessibility    
</li>
<li>Accessibility     
</li>
<li>Accessibility     
</li>
    </ul>
</div>
There's also a htmlpaths.js involved:
"use strict";
use(function() {
var path = this.thePath;
var httpRegex = /http/;
    var hashRegex = /#/;
    if (path !== undefined && (httpRegex.test(path) === false && hashRegex.test(path) === false)){
       path = path + '.html';
    }
return {
href: path
}
});
The only difference I see is that its run through Sightly iterating. Is there any fix to this? In addition to listing I'm trying to break them into columns with the following CSS
li {
width:25%;
float:left;
display:inline;
}
This works perfectly fine on the hardcoded list, but on the Sightly iterated one it creates all kind of weird spacing issues that change based on screen width
This whitespace isn't accounted for at all in the DOM. I'm not sure what to do.
More weirdness:
If the margin top is set to -9 or higher, it looks like the above screenshot. But if its set to -10 or lower, it looks like this
It's like its a breakpoint, it goes from one extreme to the other on that one pixel change. No change otherwise. It's bizarre.

It's a little weird behavior in sightly, when you have some extra spaces in your HTML code, it will display with extra spaces in the HTML.
Try to remove all the spaces in the HTML as shown below and try it.
 <div class="bullets"><ul class="columns unordered-list" id="stateList"><sly data-sly-list.slidesNode="${resource.listChildren}"><sly data-sly-list.states="${slidesNode.listChildren}"><li>${states.valueMap.name}</li></sly></sly></ul></div>
You can use HTML formatter in your IDE or online tools like below to format the HTML for a readable format
https://www.freeformatter.com/html-formatter.html.
<div class="bullets">
<ul class="columns unordered-list" id="stateList">
<sly data-sly-list.slidesNode="${resource.listChildren}">
<sly data-sly-list.states="${slidesNode.listChildren}">
<li>${states.valueMap.name}</li>
</sly>
</sly>
</ul>
</div>
This should get rid of the extra spaces in your HTML.
Also, it is best to use sightly tags wherever we need some conditions to check or embed them directly in the actual div tag or html tags instead of using data-sly-unwrap.
You can also use sling models to get the required data and check all the conditions(including appending html) in the backend and send the data just to display and avoid all the conditions in sightly.

Using data-sly-unwrap or a sly tag still adds an empty line in the generated HTML. Even though most browsers ignore those spaces, they might cause issues in some cases. If you want the HTL output to look similar to your hardcoded HTML, try placing the use statement and anchor tag in a single line as shown below.
<div class="bullets">
    <ul class="columns unordered-list" id="stateList" data-sly-list.slidesNode="${resource.listChildren}">
       <li data-sly-repeat.states="${slidesNode.listChildren}" data-sly-test="${states.valueMap.flag}"><sly data-sly-use.htmlpaths="${'htmlpaths.js' # thePath=states.valueMap.path}">${states.valueMap.name} </sly></li>
    </ul>
</div>
Also, a few tips
The sly tag doesn't need a data-sly-unwrap. It is automatically
removed in the generated HTML.
data-sly-list can be added to the parent ul tag itself instead of introducing an extra div tag and then unwrapping it.
Use data-sly-repeat instead of data-sly-list wherever possible. I was able to bring down the generated HTML of one of our complex pages from 20k lines to 12k lines, as data-sly-repeat doesn't introduce additional white spaces.

Solution
The issue is on line 7 of your HTL template:
${states.valueMap.name}
You have a space at the end of the inner HTML of your tag ;)
Unrelated
Regarding your htmlpaths.js script, are you aware of Transformers in AEM? You can use them to implement a global Link Rewriter which will fix links when a page is rendered, much like your script does. You can see an example here: https://helpx.adobe.com/experience-manager/using/aem63_link_rewriter.html
If you decide to keep htmlpaths.js, you may want to review it because I'm afraid there might be some problems with it. Of course, I don't know your requirement so it's just a suggestion :)

Related

xpath/css href not printing

I am trying to print the href of a html doc, however I am not able to do so.
newurl = 'http://www.heroesfire.com/hots/guide/the-many-ways-of-abathur-1194'
buildpage = Nokogiri::HTML(open(newurl))
#puts buildpage
thistext = buildpage.css("div#wrap div#site-content.self-clear div#guide.view-guide div.col-l div.tab-contents.box div.guide-tab div.chapter-text div.text table.bbcode_columns tbody tr td.bbcode_column a").each do |href|
puts href['href']
end
I am expecting to see '/hots/wiki/talents/pressurized-glands'
I was able to get something similar to work earlier in my script, but I am having zero luck with this.
Invariably, the longer the Node selector, the less likely it will work correctly, especially if you're dealing with HTML you don't control.
Reduce it to find way-points, places that help you drill down instead of trying to define each step.
You're also relying on tbody in the selector. When we see that, the odds are good that it's not in the original HTML source but instead was injected by your browser. Selectors like that smell of using a browser and an inspector to locate a particular item in the page, but the resulting path won't work if the HTML doesn't actually contain tbody. Browsers do a lot of fix-up in an attempt to present something useful, including adding tags. So be careful when you see tbody and confirm it actually exists. In your case, it does, but the concern still exists when navigating through a document.
A simple example of simplifying the path is:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<div id="foo">
<div id="bar">
<p>text1</p>
</div>
<div id="baz">
<p>text2</p>
</div>
</div>
</body>
</html>
EOT
doc.at('body div#foo div#bar p').text # => "text1"
Can be written more easily, while still accomplishing the same thing, using:
doc.at('#bar p').text # => "text1"
or perhaps one of these:
doc.at('#foo div p').text # => "text1"
doc.search('#foo div p').first.text # => "text1"
All scraping requires at least some advance knowledge of the target page's structure, so, while you're nosing around, take note of the important layout tags. id parameters are especially useful, followed by class and/or unique patterns of tags not replicated elsewhere in the document. Those make it easy to reduce the selector. Sometimes we have to step into the document incrementally like I did using first or one of the "sibling" methods after locating a particular node, but using a long selector rarely is needed.

AngularJS view rendering issue

I am using ng-view to render dynamic data on my page. When the page loads, if I use static html I get this (top):
When Angular loads the page the data is there but it's like the element is still empty (bottom).
If I make even the slightest adjustment in Chrome dev tools, the items snap into place but I cannot get them to prefill without using CSS to make them static sizes, which doesn't work because text is different sizes. The elements in question have CSS of inline-block.
As you can see in this screenshot, I have tried two ways of populating the data, both with the same result:
<div class="cd-rating" ng-class="caseData.scoreClass">
<span class="score" ng-bind="caseData.adjustedScore | number:0" ng-cloak>N/A</span>
<span class="verdict">{{caseData.recommendation}}</span>
</div>
Here is the what the HTML looks like in the browser:
<div class="cd-rating medium" ng-class="caseData.scoreClass">
<span class="score ng-binding" ng-bind="caseData.adjustedScore | number:0">349</span>
<span class="verdict ng-binding">review</span>
</div>
If I hard-code that HTML identically, then it renders perfectly. It's only when Angularjs renders it that the elements are collapsed, appearing if there is not content.
I would also like to add that I am using RequireJS and manually bootstrapping the app instead of using the ng-app directive, in case that matters.
Any ideas on how to make the view fill the elements?
EDIT: Here is a video that demonstrates the behavior: http://youtu.be/zTwv-o6mWRM
I am not able to figure out what exactly you mean by the "..data is still there but the element is empty.." - the only issue that I find with the rendering by AngularJS is that the "Review" (button?) is overwritten with the number.
Looking at your code (which, as #Wingman4l7 suggests needs to be posted in the question rather than as a image), I see that you are using bindings to define a class dynamically. Instead, can you use the ng-class directive and see if it resolves the issue?
That is, replace:
<div class="cd-rating {{caseData.scoreClass}}">
with
<div class="cd-rating" ng-class="caseData.scoreClass">
instead and check if the issue gets resolved?

What should be the following tag to a span nested within an anchor?

I am trying to learn fundamentals of html and markings.
I want to create an anchor which containes two lines of information.
first line: the name of the link
second line: short explanation
e.g.
<a href='#'>
<span>Studies</span>
<span class="alt">-Information about studies</span>
</a>
Is this correct?
How should the following (2nd span) be modified if necessary?
Thank you
PS. Both lines need to be surrounded with span for css-styling.
First off, don't rule out using a br tag. This is a semantically-appropriate place for a br tag (forcing a hard break inside a line or paragraph of text). Plus, if you use a br tag, it may no longer be necessary to put either of the two lines of text in separate tags, unless you want to style them differently.
<a href='#'>
Studies<br/>
-Information about studies
</a>
Second, try viewing the HTML with stylesheets disabled (I do this in Firefox by pressing ctrl-shift-S, with a little help from the Web Developer extension). Is the browser able to render the content in an easy-to-read way based solely on the HTML provided? To some extent, the more readable the "unstyled" content appears, the more semantically-correct the HTML is.
Given that the second line of text seems to be secondary to the first line (a subtitle, not as important, possibly redundant or not entirely essential), putting the first line in a strong tag or putting the second line in a small tag are a couple ways to establish the relative importance of the two lines, if you wish to do so.
<a href='#'>
<strong>Studies</strong><br/>
-Information about studies
</a>
<a href='#'>
Studies<br/>
<small>-Information about studies</small>
</a>
There's some room for personal preference here. These are just two approaches.
It may be a little bit of a stretch using a small tag in a case like this, but it's not entirely inappropriate. A small tag is typically used for "fine print", attribution, disclaimers, or side comments. It doesn't semantically mean the text is small, but it does tend to be used for content that's secondary to something else (that clarifies something else). It should though only be used for text that's short in length.
And a strong tag doesn't have to be styled bold. In fact, that's the whole point of semantic markup: It doesn't specify or imply how the content will be styled; all it does is offer a hint to the meaning or context of the content. A strong tag can reasonably be given a style of font-weight:normal.
In order to achieve that those are in separate lines, try using the <div> tag instead. You can still specify a class for styling, the only difference is that <div>s are block-elements; each of them is rendered on a separate line. Here's the modified version of your code:
<a href='#'>
Studies
<div class="alt">-Information about studies</div>
</a>
Another, slightly more preferable way of doing that is by styling the elements to be block-elements. That can be used by setting the CSS display property to block. Something like:
<a href='#'>
Studies
<span class = "alt block">-Information about studies</span>
</a>
(Note that class = "alt block" means the element has both classes alt and block, and note also that the first <span> is removed because there's no need to style that node with anything).
CSS:
.block {
display: block;
}
Hope that helped you!

How can i find extra closing div in html string

I have some html stored in database.
I dont know that html stored in databse has extra closing div like </div> or not.
I want to find extra closing div in html string.
I have tried to find using HTML Agility pack but not find the way to achieve this.
Example:
<div class="readers">
A total of 218 users are reading this article.
</div>
</div>
</div>
How can i find these two extra closing div and extract fully valid html.
Use this pure javascript parser before rendering the html: http://ejohn.org/blog/pure-javascript-html-parser/
You can check out by pasting your code here,
http://ejohn.org/apps/htmlparser/
it removes the extra </div>s.
You just need to pass your html to the HTMLtoXML function as:
HTMLtoXML(your_html);
and it would remove the extra closing tags. Infact what it does is that it converts it into xml format, but since you are dealing with html strigs & all tags are expected to be valid in html, you can be safe to use this.
EDIT: You can easily call javascript functions from a C# file. See this question for more details.
Click here to find both unclosed (hanging) as well as extra div tags: tormus

Creating Valid XHTML Clickable Block Region

I'm trying to make a "clickable" region.
<a
style="display: block"
href="http://stackoverflow.com">
StackOverflow
</a>
A is an inline element but the CSS made it a block.
If the above is valid, then the following should be valid too:
<a
style="display: block"
href="http://stackoverflow.com">
<div>Some DIV that links to StackOverflow</div>
</a>
But validator.w3.org shouldn't be flagging it as invalid (which it is right now).
If it is invalid, what would be the most proper way to make a block element "clickable" and redirects to an arbitrary page. I'm aware I can use JS onclick to achieve this behaviour, but how will Google see this?
The validator is correct - you can't put <div> inside <a>, no matter what you do afterwards with CSS.
The proper thing to do is what you did in your first code block - <a style="display: block;">
If you want something inside that you can do <a style="display: block;"><span style="display: block;">
Don't confuse valid HTML with valid CSS. It is valid to use the display css property to make inline elements block. It is not valid to put block HTML elements within inline ones.
It doesn't follow that the one being valid implies the other has to be. There are nesting rules for HTML, and div-within-anchor doesn't fit them, which is why validator.w3.org is giving you a hard time.
If you truly must have a div, rather than text, images or <span style="display: block">s, that's clickable, then yes, you will have to use an onclick event. Google will not understand or acknowledge the existence of the link. (You may be able to cope with this by having an anchor on something that anchors can apply to, in addition to the onclick div.)
Something I've done in the past with this sort of problem is invoke the click on the parent element (My example uses jQuery):
<div class="link">
Visit Google
</div>
$(".link").click(function(){
document.location = $(this).find("a:first").attr("href");
});
With styles you could make the entire area appear to be the link by setting the cursor, a roll-over state, etc.
First you need to know whether you want to use strict or transitional XHTML (frameset is not useful here). Then you look into the DTD (link) and you'll see that A cannot have a DIV inside.
Why don't you use an area tag for this? It is supposed to define the clickable area in an imagemap.
Google bots now follow simple javascript links, so using JS on the onClick event of your div is an option. Other search engine bots don't do that, but sooner or later they will.
More info in this article.

Resources