jQuery selector with special characters passed as variable doesn't seems to be work - jquery-selectors

I have a Problem passing a variable with special characters into a jQuery selector.
To simplify the following code is used.
The element looks like:
<div class="S3#123#568745" /> some_text </div>
The following selector works fine:
$(".S3\\#123\\#568745")
This selector doesn't works and i don't know why:
var class_id = ".S3#123#568745";
class_id = class_id.replace(/#/g,'\\\\#');
$(class_id) //doesn't work
console.log(class_id); //shows ".S3\\#123\\#568745"
Any Ideas ?
http://jsfiddle.net/hnr3R/2/

Try this out
Demo: jsFiddle
Javascript:
var class_id = ".S3#123#568745";
class_id = class_id.replace(/#/g,"\\#");
$("#result1").text($(class_id).text())

Related

Binding an html form action to a controller method that takes some parameters

In my Find controller I have a method like:
public Result findLatest(String repoStr) {
............
}
Which is linked through a route:
GET /latest controllers.Find.findLatest(repo: String)
Then, I have a form in a view like:
<form action="#routes.Find.findLatest()" method="get">
....
<select name="repo">....</select>
</form>
But obviously that is failing, because it is expecting some parameters that I do not fulfill in the action. What is the correct way to do this without having to end up leaving the findLatest method taking no parameters in my controller?
You could change the routes to accept an empty string:
GET /latest/:repo controllers.Find.findLatest(repo: String = "")
Then configure your controller function to handle empty string.
That way,
<form action="#routes.Find.findLatest()" method="get">
....
<select name="repo">....</select>
will evaluate repo as an empty string at the controller level.
Edit: Support for this implementation was dropped in Play v 2.1
You may be interested in Play's Optional parameters e.g. play.libs.F.Option[String]
Example: How to handle optional query parameters in Play framework
GET /latest/:repo/:artifact controllers.Find.findLatestArtifact(repo: play.libs.F.Option[String], artifact: play.libs.F.Option[String])
This will allow you flexibility in which arguments need to be provided.
Not sure which language you're using but the link above contains an example for scala and the method declaration in java would look something like:
import play.libs.F.Option;
public static Result findLatestArtifact(Option<String> repo, Option<String> artifact){ ... }
and updated implementation 2.1
Routes with optional parameter - Play 2.1 Scala
EDIT: play 2.1+ Support : Props to #RobertUdah below
Initializing to null:
GET /latest/ controllers.Find.findLatest(repo: String = null)
GET /latest/:repo controllers.Find.findLatest(repo: String)
<form action="#routes.Find.findLatest()" method="get">
Normally all form data go in the body and you can retrieve them in your action method with bindFromRequest() (see docs).
If you really want to pass one form element as a part of the URL then you have to dynamically compose your URL in JavaScript and change your route.
Your route could look like:
GET /latest/:repo controllers.Find.findLatest(repo: String)
And the JavaScript part like (I didn't actually test the code):
<form name="myform" action="javascript:composeUrl();" method="get">
....
<select name="repo">....</select>
</form>
<script>
function submitform() {
var formElement = document.getElementsByName("myform");
var repo = formElement.options[e.selectedIndex].text;
formElement.action = "/lastest/" + repo;
formElement.submit();
}
</script>
Cavice suggested something close to what I consider the best solution for this (since F.Option are not supported anymore with the default binders in Play 2.1 ).
I ended up leaving the route like:
GET /latest controllers.Find.findLatest(repo=null)
and the view like:
<form action="#routes.Find.findLatest(null)" method="get">
<select name="repo"> .... </select>
....
</form>
and in the controller:
public Result findLatest(String repoStr) {
if(repoStr==null) {
repoStr=Form.form().bindFromRequest().get("repo");
.....
This allows me to have a second route like:
GET /latest/:repo controllers.Find.findLatest(repo: String)

Wrong xpath for nav html tag

I m trying to find element using xpath for tag
<nav id="nav">... </nav>
this works:
WebElement navigationPane = firefox.findElement(By.className("nav"));
but this does not:
WebElement navigationPane =
firefox.findElement(By.xpath("//nav[#id='nav')]"));
How do I make it valid expression in xpath?
In the xpath expression, you've meant to use #class instead of #id. And, there is an extra parenthesis inside. Here is the fixed version:
//nav[#class = 'nav']
After finding an HTML block in your question (made it visible with an edit), I've realized that there is an id attribute set on the element, not class. In this case, you should use the following expression:
//nav[#id = 'nav']
Note that by.id would be an easier and faster way to find the element:
WebElement navigationPane = firefox.findElement(By.id("nav"));

Filtering a scope with multiple select in AngularJS

Here is my fiddle: http://jsfiddle.net/mwrLc/12/
<div ng-controller="MyCtrl">
<select ng-model="searchCountries" ng-options="cc.country for cc in countriesList | orderBy:'country'">
<option value="">Country...</option>
</select>
<select ng-model="searchCities" ng-options="ci.city for ci in citiesList | filter:searchCountries | orderBy:'city'">
<option value="">City...</option>
</select>
<ul>
<li ng-repeat="item in list | filter:searchCountries | filter:searchCities">
<p>{{item.country}}</p>
<p>{{item.city}}</p>
<p>{{item.pop}}</p>
<br>
</li>
</ul>
The first select filters the second one but also the result list.
The second select filters only the result list.
It works great until a country and a city are chosen. Then, when you choose another country, second select got reseted but the scope seems to be stuck with the old value.
i cant find a way to have it works properly... Please help!
The best solution is to reset the city model when a change to country model is detected via $scope.$watch():
function MyCtrl($scope) {
// ...
$scope.$watch('searchCountry', function() {
$scope.searchCity = null;
});
}
Note that I changed your model names to singular form ("searchCountry" and "searchCity") which is more appropriate considering the value of those models is set to a single country or city.
Here is the full working example: http://jsfiddle.net/evictor/mwrLc/13/
Ezekiel Victors solution is excellent. However, I ran into a bit of a dependency injection issue while trying to get this to work when referencing the controller from an ng-include. Thanks to the help from Ben Tesser I was able to resolve the issue. Ive attached a jsfiddle that details the fix:
http://jsfiddle.net/uxtx/AXvaM/
the main difference is that you need to wrap the searchCountry/searchCity as an object and set the default value to null. Ditto for the watch.
$scope.test = {
searchCountry: null,
searchCity: null
};
/// And your watch statement ///
$scope.$watch('test.searchCountry', function () {
$scope.test.searchCity = null;
});
In your template you'll change all references from searchCountry/searchCity to test.searchCountry.
I hope this saves someone some time. It's trixy.

How to use ng-class in select with ng-options

I have an array of Person objects
var persons = [
{Name:'John',Eligible:true},
{Name:'Mark',Eligible:true},
{Name:'Sam',Eligible:false},
{Name:'Edward',Eligible:false},
{Name:'Michael',Eligible:true}
];
and i am using select with ng-options like this:
<select ng-model="Blah" ng-options="person.Name for person in persons"></select>
I want to show the record with Eligible:false in red color.
So the problem is how do i use the ng-class in select inorder to achieve this? Since we are not using any option tag it wont work if i simply add ng-class in the select element itself.
You could create a directive that processed the options after the ngOptions directive is processed that updated them with the appropriate classes.
Update: The old code had a few bugs, and I've learned a bit since I answered this question. Here is a Plunk that was redone in 1.2.2 (but should work in 1.0.X as well)
Here is updated (Nov 30 '13 at 3:17) the Code:
app.directive('optionsClass', function ($parse) {
return {
require: 'select',
link: function(scope, elem, attrs, ngSelect) {
// get the source for the items array that populates the select.
var optionsSourceStr = attrs.ngOptions.split(' ').pop(),
// use $parse to get a function from the options-class attribute
// that you can use to evaluate later.
getOptionsClass = $parse(attrs.optionsClass);
scope.$watch(optionsSourceStr, function(items) {
// when the options source changes loop through its items.
angular.forEach(items, function(item, index) {
// evaluate against the item to get a mapping object for
// for your classes.
var classes = getOptionsClass(item),
// also get the option you're going to need. This can be found
// by looking for the option with the appropriate index in the
// value attribute.
option = elem.find('option[value=' + index + ']');
// now loop through the key/value pairs in the mapping object
// and apply the classes that evaluated to be truthy.
angular.forEach(classes, function(add, className) {
if(add) {
angular.element(option).addClass(className);
}
});
});
});
}
};
});
Here's how you'd use it in your markup:
<select ng-model="foo" ng-options="x.name for x in items"
options-class="{ 'is-eligible' : eligible, 'not-eligible': !eligible }">
</select>
It works like ng-class does, with the exception that it's on a per-item-in-the-collection basis.
In this scenario you can only apply ng-class only if you use ng-repeat with option tags:
<select ng-model="Blah">
<option ng-repeat="person in persons" ng-class="{red: person.Eligible}">
{{person.Name}}
</option>
</select>
This will give custom class to your 'Eligible' persons, but CSS won't work consistently across bowsers.
Plunker.
I wanted to comment on the accepted answer, but because I don't have enough reputation points, I must add an answer.
I know that this is an old question, but comments where recently added to the accepted answer.
For angularjs 1.4.x the proposed directive must be adapted to get it working again.
Because of the breaking change in ngOptions, the value of the option isn't anymore the index, so the line
option = elem.find('option[value=' + index + ']');
won't work anymore.
If you change the code in the plunker to
<select ng-model="foo" ng-options="x.id as x.name for x in items"
options-class="{ 'is-eligible' : eligible, 'not-eligible': !eligible }">
</select>
As result the value of the option tag will now be
value="number:x" (x is the id of the item object)
Change the directive to
option = elem.find('option[value=\'number:' + item.id + '\']');
to get it working again.
Of course this isn't a generic solution, because what if you have not an id in your object?
Then you will find value="object:y" in your option tag where y is a number generated by angularjs, but with this y you can't map to your items.
Hopes this helps some people to get their code again working after the update of angularjs to 1.4.x
I tried also to use the track by in ng-options, but didn't get it to work.
Maybe people with more experience in angularjs then me (= my first project in angularjs)?
The directive is one way, but I used a custom filter.
If you know how to select your element, you should be fine here. The challenge was to find the current option element inside the select. I could have used the "contains" selector but the text in the options may not be unique for items. To find the option by value, I injected the scope and the item itself.
<select ng-model="foo" ng-options="item.name|addClass:{eligible:item.eligible,className:'eligible',scope:this,item:item} for item in items"></select>
and in the js:
var app = angular.module('test', []);
app.filter('addClass', function() {
return function(text, opt) {
var i;
$.each(opt.scope.items,function(index,item) {
if (item.id === opt.item.id) {
i = index;
return false;
}
});
var elem = angular.element("select > option[value='" + i + "']");
var classTail = opt.className;
if (opt.eligible) {
elem.addClass('is-' + classTail);
elem.removeClass('not-' + classTail);
} else {
elem.addClass('not-' + classTail);
elem.removeClass('is-' + classTail);
}
return text;
}
})
app.controller('MainCtrl', function($scope) {
$scope.items = [
{ name: 'foo',id: 'x1',eligible: true},
{ name: 'bar',id: 'x2',eligible: false},
{ name: 'test',id: 'x3',eligible: true}
];
});
Here you can see it work.
The accepted answer did not work for me, so I found an alternative without a custom directive using track by :
<select ng-model="foo" ng-options="x.name for x in items track by x.eligible"></select>
Each option now gets the value x.eligible. In CSS you can style options with value = true (I think true has to be a string). CSS:
option[value="true"]{
color: red;
}
In case you not only want to show them in red color but prevent the user from selecting the options, you can use disable when:
<select
ng-model="Blah"
ng-options="person.Name disable when !person.Eligible for person in persons">
</select>
You can then use CSS to set the color of disabled options.
I can't write this as a comment, due to reputation, but I have updated the plunker for the accepted answer to work with Angular 1.4.8. Thanks to Ben Lesh for the original answer, it helped me a lot. The difference seems to be that newer Angular generates options like this:
<option class="is-eligible" label="foo" value="object:1">foo</option>
so the code
option = elem.find('option[value=' + index + ']');
wouldn't be able to find the option. My change parses ngOptions and determines what field of item was used for the label, and finds the option based on that instead of value. See:
http://plnkr.co/edit/MMZfuNZyouaNGulfJn41
I know I am a bit late to the party, but for people who want to solve this with pure CSS, without using a directive you can make a css class like this:
select.blueSelect option[value="false"]{
color:#01aac7;
}
This css rule says : Find all elements with value = false with tag name 'option' inside every 'select' that has a class "blueSelect" and make the text color #01aac7; (a shade of blue)
In your case your HTML will look like this:
<select class="form-control blueSelect" name="persons" id="persons1"
ng-options="person as person.name for person in $ctrl.persons track by person.Eligible"
ng-model="$ctrl.selectedPerson" required>
<option disabled selected value="">Default value</option>
</select>
The track by inside the ng-options is what will hold what to track the options by, or the "value" field of each option. Notice that depending on your project needs , you might have to do some tweaking to make this work as per your requirements.
But that's not going to work right when there's multiple options with the same value for the Eligible field. So to make this work, we create a compound expression to track by, that way we can have unique values to track by in each option. In this case we combine both fields Name and Eligible
So now our html will look like this
<select class="form-control blueSelect" name="persons" id="persons2"
ng-options="person as person.name for person in $ctrl.persons track by (person.name + person.Eligible)"
ng-model="$ctrl.selectedPerson" required>
<option disabled selected value="">Default value</option>
</select>
and our css :
select.blueSelect option[value*="False"]{
color:#01aac7;
}
Notice the * next to value, this is a regular expression which means to find the word "False" somewhere in the value field of the option element.
Quick Edit
You can also choose to disable the options with Eligible = False using the "disable when" in the ng-options expression , for example:
label disable when disable for value in array track by trackexpr
I'll leave how to use that in your case for you to find out ;-)
This works for simple css modifications, for more complex stuff you might need a directive or other methods. Tested in chrome.
I hope this helps someone out there. :-)
I've found another workaround that was easier than adding a directive or filter, which is to add a handler for the onfocus event that applies the style.
angular.element('select.styled').focus( function() {
angular.element(this).find('option').addClass('myStyle');
});

The second child of a second child - Jquery

I wanna know how can I get a value of a child of a child. I have this...
<table id="table4">
<tr>
<td>Id:</td>
<td>Name:</td>
</tr>
<tr>
<td>1515</td>
<td>Thiago</td>
</tr>
</table>
In Jquery, I wanna do something like this...
var id = $("#table4:nth-child(2) tr:nth-child(1)").val();
How can I do this work? The first <td> of the second <tr>. I know that I can use "class" and "id" to make it easier, but in this case I can't do that for others reasons.
PS. Sorry about the bad English, I'm a noob in this language.
Thanks.
Like this:
var id = $("#table4 tr:nth-child(2) td:nth-child(1)").text();
You can test it out here. The :nth-child selector applies to the child, for instance the first is saying "a <tr> that is a second child of its parent", rather than your attempted version, which would mean "the second child of this <tr>".
Also, use .text() to get an elements text, rather than .val() which is for input type elements.
This isn't a fully jQuery solution, but just thought I'd point out that you could do this:
var txt = $("#table4")[0].rows[1].cells[0].innerHTML;
Or if there will be any HTML markup you want to avoid, you could do this:
var cell = $("#table4")[0].rows[1].cells[0];
var txt = cell.innerText || cell.textContent;