What is the correct way to traverse the DOM presented by a Select in CSQuery? - csquery

CSQuery is an awesome C# library that helps with the parsing of HTML in C#.
https://github.com/jamietre/CsQuery
It's all the goodness you'd expect from sizzler/jQuery, and James Treworgy deserves some love and admiration.
Why does the second Select from the result of a first Select result in the wrong number of elements?
CQ fragment = CQ.CreateFragment(#"
<div>
<ul>
<li class=""number english"">one</li>
<li class=""number english"">two</li>
<li class=""number english"">three</li>
<li class=""number english"">four</li>
<li class=""number english"">five</li>
</ul>
<ul>
<li class=""number spanish"">uno</li>
<li class=""number spanish"">dos</li>
<li class=""number spanish"">tres</li>
<li class=""number spanish"">quatro</li>
<li class=""number spanish"">cinco</li>
</ul>
</div>
");
Assert.AreEqual(2, fragment["ul"].Length);
CQ english = fragment["ul:first"];
CQ spanish = fragment["ul:last"];
Assert.AreEqual(1, english.Length);
Assert.AreEqual(1, spanish.Length);
// english seems to not represent only the first ul, but the entire DOM
CQ englishNumbers = english["li.number"];
Assert.AreEqual(5, englishNumbers.Length); // Failed, expected <5> and was <10>
// Both of these methods work. I'm at a loss for as to why the first does not.
CQ spanishNumbers = spanish["li.number", spanish[0]]; // Give it context of where to start searching from
Assert.AreEqual(5, spanishNumbers.Length);
CQ spanishNumbers2 = spanish.Select("li.number", spanish.Elements);
Assert.AreEqual(5, spanishNumbers2.Length);

I've been reading the source and writing more tests and think I have this figured out.
CsQuery/CQ_jQuery/Select.cs
compare public CQ Select(string selector, IDomObject context) to public CQ Select(string selector).
It all boils down to public CQ Select(Selector selector) with this poetic comment.
// When running a true "Select" (which runs against the DOM,
// versus methods that operate against the selection set)
// we should use the CsQueryParent document, which is the DOM
// that sourced this.
The magic I want is when this method public Selector ToFilterSelector() is used. CsQuery/Engine/Selector.cs
// Selecting from a resolved Select is the same as selecting from the root dom
CQ entireDomNumbers = fragment["li.number"];
CQ englishNumbers = english["li.number"];
Assert.AreEqual(entireDomNumbers.Length, englishNumbers.Length);
// When you want to select from a sub-part of the dom, explicitly use it as context
IEnumerable<IDomObject> spanishDomObjects = spanish;
CQ spanishNumbers = spanish["li.number", spanishDomObjects];
Assert.AreEqual(5, spanishNumbers.Length);
// Or from some specific part of the resolved CQ, again explicitly
IDomObject spanishDomObject = spanish[0];
CQ spanishNumbers2 = spanish["li.number", spanishDomObject];
Assert.AreEqual(5, spanishNumbers2.Length);
// Indexer [string, context] is same as Select(string, context) method
CQ spanishNumbers3 = spanish.Select("li.number", spanishDomObject);
Assert.AreEqual(5, spanishNumbers3.Length);
// Or in reverse from an IDomObject just for fun
CQ spanishNumbers3b = spanishDomObject.Cq().Select("li.number", spanish);
Assert.AreEqual(5, spanishNumbers3b.Length);
// Or from the collection...
CQ spanishNumbers4 = spanish.Select("li.number", spanishDomObjects);
Assert.AreEqual(5, spanishNumbers4.Length);
// in the end, Find was the droid I was looking for
CQ findSpanishNumbers = spanish.Find("li.number");
Assert.AreEqual(5, findSpanishNumbers.Length);

Related

Meteor Blaze To Do App checked condition

(Super new to meteor)
I've gone through the meteor todo app tutorial and on the checking off and deleting tasks part It says that
If you try checking off some tasks after adding all of the above code, you will see that checked off tasks have a line through them. This is enabled by the following snippet:
<li class="{{#if checked}}checked{{/if}}">
With this code, if the checked property of a task is true, the checked
class is added to our list item. Using this class, we can make
checked-off tasks look different in our CSS.
Is there any way to have this apply to a different tag, and not the list? so basically have it say
With this code, if the checked property of a task is true, the updatedstyle
class is added to our img tag. Using this class, we can make
checked-off tasks make images look different in our CSS.
You can put the {{#if}} anywhere you want in your template, not just in the list item. If I understand your specific question:
<li>Some item
<img class="{{#if checked}}updatedstyle{{/if}}" src="/myImg.png">
</li>
Per #blueren, the parameter to the {{#if}} is evaluated as a truthy or falsy value. It can be a key in the current data context (i.e. this.checked) or can be returned by a helper.
If you want a class reactively binded to html tag in the template, you can do it like that:
Template code:
<template name="MyTemplate">
<img src="my/img/path.jpg" class={{checked.img}}/>
<ul>
<li class={{checked.li}}>My List Entry</li>
</ul>
</template>
Helper Code:
Template.MyTemplate.helpers({
checked() {
let liClass = '';
let imgClass = '';
//your checked condition
if(document.getElementById('myCheckBox').checked) {
let liClass = 'checked';
let imgClass = 'updatedstyle';
}
return {
li: liClass,
img: imgClass
};
}
});
That way you can bind multiple classes with different names to the checked input value.

Setting an active menu item based on the current URL with jQuery

I want to active menu item on the current URL , now its my HTML :
<ul class="header-tools nav navbar-nav">
<li class="mysetting">
<a class="link-menu-active" href="">first title</a>
</li>
<li class="mysetting">
<a class="link-menu-active" href="">second title</a>
</li>
<li class="mysetting">
<a class="link-menu-active" href="">third title</a>
</li>
</ul>
and it's my jquery code :
$(".header-tools.nav.navbar-nav li").each(function() {
var navItem = $(this);
if( $(navItem).find("a").attr("href") == location.href ) {
navItem.addClass("active");
}
});
or it :
var path = window.location.pathname;
path = path.replace(/\/$/, "");
path = decodeURIComponent(path);
$(".header-tools.nav.navbar-nav li a").each(function () {
var href = $(this).attr('href');
if (path.substring(0, href.length) === href) {
$(this).closest('li').addClass('active');
}
});
but none of them doesn't work , what should I do ?
So Thanks
For this exact use case, you can check if the current path matches or contains the anchor href and act accordingly.
$('.mysetting').each(function() {
var path = window.location.pathname,
href = $(this).find('a').attr('href'),
exactMatch = (path === href), // URL is the same as anchor. Useful when your path can contain the href of multiple links
closeMatch = (path.indexOf(href) !== -1); // URL contains anchor.
// Useful when you don't know if query strings and other crap will be appended/prepended to your links
if (exactMatch /* or closeMatch depending on your preference*/) {
$(this).addClass('active');
}
})
Although, as already noted in the comments above, WP has built-in nav functions that handle exactly this kind of situation and are a lot more robust than any few lines of javascript you can come up with.

MVC4 Current Link?

<li>#Html.ActionLink("Contact Us", "Contact", "Home")</li>
<li>Services
<ul>
<li>#Html.ActionLink("IT", "IT", "Home")
<ul>//Dropdown
<li>#Html.ActionLink("Data Backup", "DataBackup", "Home")</li>
</ul>
</li>
For example this is my menu my css class is "selected" for active link.. I want to use it at the easiest way. Can any one help me for MVC4.. I have looked some solutions but don't have much knowledge to use it..
<ul class="#{booleanForThisIsSelected ? "selected" : "";}">//Dropdown
I use the following technique all the time, using jQuery
<script type="text/javascript">
var currentLocation = window.location;
$(function () {
$('.menu li a').each(function () {
if (this.href == currentLocation) {
$(this).parent().addClass("current");
}
});
});
</script>
This block at first gets the current page url, then it gets all the menu anchors and compares each one with the current page url, once it finds a match, it gives the matching anchor a special class current which should indicate the current page link.
Please note that the selector $('.menu li a') should be changes to match your own structure so it can get the menu items correctly.
Hope this helps, let me know if you need anything else.
I would recommend you to use MvcSiteMapProvider MVC4.
You install the nuget package.
Then you add links according to your site structure to the Mvc.Sitemap-file.
Now you should be able to use the MenuHelperModel.cshtml-file to define the rendering behaviour of all links in your sitemap (including currently selected ones), an example of this could look like this:
#model MvcSiteMapProvider.Web.Html.Models.MenuHelperModel
#using System.Web.Mvc.Html
#using MvcSiteMapProvider.Web.Html.Models
<ul id="menu">
#foreach (var node in Model.Nodes) {
string classes = node.IsCurrentNode | node.IsInCurrentPath | node.Children.Any(n => n.IsCurrentNode)
? "selected" : "";
<li class="#classes">#Html.DisplayFor(m => node)
#if (node.Children.Any()) {
#Html.DisplayFor(m => node.Children)
}
</li>
}
</ul>
All you have to do now is ensure your links show up on your page, best location to put it should be your Layout-/Master-Page.
There you could for example add a call to
#Html.MvcSiteMap("MvcSiteMapProvider").Menu(0, true, false, 1)
Which renders only the first level of your sitemap.
If you want a more verbose example using this you can take a look at my question here.
But keep in mind that uses the now obsolete MvcSiteMapProvider-Package, so there is a slight syntax change inside MenuHelperModel.cshtml.

Angularfirecollection return object instead of array

Before using angularFireCollection() I was using angularFire(). But angularFire listening on value instead of childs so someone suggest me to use angularFireCollection.
But now angularFireCollection return arrays. =.=
So any idea in this situation?
I want my data return in objects and listening on childs.
To access the key names from the array returned by angularFireCollection, you can use the $id property:
<ul>
<li ng-repeat="item in items">{{item.$id}}: {{item.val}}</li>
</ul>
<script>
$scope.items = angularFireCollection(new Firebase(url));
</script>

How can I Give css style to the current menu?

what is the css of current link like when somebody goes to ABOUT US page then about us color changed to red.... then going to CONTACT US page then about us color change to default and CONTACT US color change to red....
please help i am new designer......
use :hover in css
replace li in example with whatever element you use in your actual code
eg.
li:hover{backgroundcolor:Red;}
li tag in case you design menu like
<ul>
<li> Menu1</li>
<li> Menu2</li>
</ul>
Whwn you click on specific menu, that perticular page will be open.
then just do simple thing,
write class for active.
apply this, for home page
for About Us page active class attribute to About Us li
<ul>
<li class="active">Home</li>
<li>Projects</li>
<li>About Us</li>
</ul>
You can't use JUST CSS to determine which page your user currently is - it just won't do it. You have to adjust your markup to add a hook of some kind that your CSS can use. Like so -
<ul id="nav">
<li>About Us</li>
<li>Contact</li>
</ul>
If you're building a static HTML site, you can manually change the HTML on each page to reflect the current page in the menu.
If you're building something more complex, you will probably need to rely on PHP or JavaScript to figure out the current page. This script is a little old (it's from Jeremy Keith's "DOM Scripting"), but it will do the job:
function highlightPage(id){
//make sure DOM methods are understood
if(!document.getElementsByTagName) return false;
if(!document.getElementById) return false;
if(!document.getElementById(id)) return false;
var nav = document.getElementById(id);
var links = nav.getElementsByTagName('a');
for (var i=0; i < links.length; i++){
var linkurl = links[i].getAttribute('href');
var currenturl = window.location.href;
//indexOf will return -1 on non-matches, so we're checking for a positive match
if (currenturl.indexOf(linkurl) != -1) {
links[i].className = "here";
var linktext = links[i].lastChild.nodeValue.toLowerCase();
document.body.setAttribute("id",linktext);
}
}
}
addLoadEvent(function(){
highlightPage('nav');
});
function addLoadEvent(func){
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function(){
oldonload();
func();
}
}
}
This script would go in an externally linked javascript file.
Give the body an id name <body id="about-us">. Your link needs an id, too <a href="#" id='this-link">. Then:
#about-us #this-link {
color:red;
}
#contact-us #this-link {
}

Resources