complex jquery/css selector - jquery-selectors

I need a selector for this code:
<div class="panel-heading BWHeadingForSection">
<a style="text-decoration:none" href="#faq-cat-1-sub-2" data-parent="#accordion-cat-2" data-toggle="collapse" tabindex="90">
<i class="fa fa-truck fa-lg"></i>
UPS Deutschland
<span class="pull-right">
<i class="glyphicon glyphicon-plus"></i>
</span>
</a>
</div>
And I tried that:
$('div.BWHeadingForSection a[href~="#faq-cat-1-sub-'+globalcarriernumber+'"]').on("click", function(){
count++;
if(count%2==0){
$("#faq-cat-1-sub-"+globalcarriernumber).slideToggle();
//why doesn't this selector work?
//if ( $(this+">span i").hasClass('plus') ) {
// $(this+">span i").removeClass('plus').addClass('minus');
// }
//this selector work's, at least it enters the if -block
if ( $('div.BWHeadingForSection a[href~="#faq-cat-1-sub-'+globalcarriernumber+'"]>span i').hasClass('plus') ) {
$('div.BWHeadingForSection a[href~="#faq-cat-1-sub-'+globalcarriernumber+'"]>span i').removeClass('glyphicon glyphicon-plus').addClass('glyphicon glyphicon-minus');
}
}else{
$("#faq-cat-1-sub-"+globalcarriernumber).hide();
}
});
The relevant line is "$(this+">span i")" and/or "$('div.BWHeadingForSection a[href~="#faq-cat-1-sub-'+globalcarriernumber+'"]>span i')" , which needs some adjustment. I have to replace that "plus"("") with "minus".
If I use the FireBug debugger I get for "$('div.BWHeadingForSection a[href~="#faq-cat-1-sub-'+globalcarriernumber+'"]>span i')" ,it goes into that if-block, but the symbol is still the same. And if I use "$(this+">span i")" I get(when I hove over it) : "a#faq-cat-1-sub-2",but it's not entering the if-block.
Thanks...

First of all you are mixing types here. The function $(...) accepts either an object (a DOM node or a jQuery object) or a selector string but not a concatenation of both.
So better try $(this).find('span i').
As far as I can see in your code snippet, the element you will find then, has the css classes 'glyphicon' and 'glyphicon-plus', but no class 'plus'. So you probably won't be able to remove that. Maybe you want to remove 'glyphicon-plus' and add 'glyphicon-minus'?

Related

How to avoid overlay using InstantSearch.js rangeSlider?

I'm using InstantSearch.js (via algolia) to make a price rangeslider. It's ok and it works well with one exception: the prices overlap when they are too close.
We can see it on several examples, even on the site of the doc:
Doc algolia
I use it for vehicle prices so we don't see anything when don looks for vehicles with prices not far apart
I would simply like to leave the 2 rheostat-tooltip fixed but I can't find a way to do it. (the prices don't move, but the cursors do)
You can see my problem here :
As #cmgchess suggested in comment I post a link where there is an example : example instantSearch and where you can easily see the overlapping.
thanks for any time and help :)
HTML
<li class="u-bt-thin-translucid">
<button class="my-grid mod-space-between mod-middle my-text mod-ff-lead-bold-2 mod-fs-sm2 mod-uppercase u-pt-sm u-pb-sm u-c-neutral-dark-2 u-bc-neutral-light-max u-w-100 u-b-none"
my-toggle="dd-filtrer-par-prix-mensualite"
my-toggle-options="force_dismiss"
u-pr-xxs="sm,md">
<span class="mod-on icon-chevron-up u-fs-lg"></span>
<span class="mod-off icon-chevron-down u-fs-lg"></span>
</button>
<div class="u-pb-sm" my-toggle-name="dd-filtrer-par-prix-mensualite">
<div class="my-text mod-uppercase">Prix</div>
<div id="price-range" class="u-pl-sm u-pr-md u-mb-md"></div>
<div class="my-text mod-uppercase">Mensualité (€/mois)</div>
<div id="monthly-price-range" class="u-pl-sm u-pr-md"></div>
</div>
</li>
JS
// Filtre prix
if (document.querySelector('#price-range') !== null) {
algoliaBmc.search.addWidgets([
instantsearch.widgets.rangeSlider({
container: '#price-range',
attribute: 'price',
precision: 0,
step: isGoa ? 10 : 1000,
pips: false,
tooltips: true
})
]);
}

Newline inside variable in div

Is it possible to use a variable in <div> with newline inside?
class Hello extends React.Component {
render() {
const texts = {
subHeaderText: 'first line \n second line'
};
return <div>{texts.subHeaderText}</div>;
}
}
I wish to result
first line
second line
What is the simplest way?
https://jsfiddle.net/69z2wepo/263117/
You can use p (paragraph) tags.
check out this site:
https://forum.freecodecamp.org/t/newline-in-react-string-solved/68484/7
div{
white-space: pre-line;
}
Add this to the css file of your html. This will automatically create line breaks whenever /n or <br> are encountered. This is the simplest way.
As a recommendation, since it looks like a hardcode you might as well use two separate <p> or <div> for both like so:
<div>
<p>
first line
</p>
<p>
second line
</p>
</div>
It's just much more elegant that way unless you really want to display line breaks from input. Given that you may also approach it in a js way like so:
texts.subHeaderText.split('\n').map((item, i) => {
return <p key={i}>{item}</p>;
});

Issues getting validation working with dynamically generating form inputs?

I have some basic form/input html that works (including validation) if explicitly written as follows:
<form name="forms.create" novalidate>
<div class="si-container">
<div class="si-input-container">
<input class="si-input" name="someNum" placeholder="Enter a number" ng-model="formdata.number" type="number" min="40"/>
</div>
<div class="si-error">
<div ng-show="forms.create.someNum.$error.min">Error! Value must be > 40.</div>
</div>
</div>
</form>
Now what I want to do is create a directive that allows me to write the html below, but result in the html above:
<form name="forms.create" novalidate>
<div special-input name="someNum" placeholder="Enter a number" type="number" ng-model="formdata.number">
<div error-type="min" error-value="40">Error! Value must be > 40.</div>
</div>
</form>
My attempt at the special-input directive (simplified) is as follows:
.directive('specialInput', [function(){
return {
compile: function(elem, attrs){
var input = angular.element('<input class="si-input"/>');
input.attr('placeholder', attrs.placeholder);
input.attr('type', attrs.type);
input.attr('name', attrs.name);
input.attr('ng-model', attrs.ngModel);
var errorCont = angular.element('<div class="si-error"></div>');
var errors = elem.children();
angular.forEach(errors, function(error){
var err = angular.element(error);
var type = err.attr('error-type');
var value = err.attr('error-value');
input.attr(type, value);
var formName = elem.parent().attr('name');
errorCont.append('<div ng-show="' + formName + '.' + attrs.name + '.$error.' + type + '">' + err.html() + '</div>');
});
var cont = angular.element('<div class="si-container"></div>');
cont.append('<div class="si-floating-label">' + attrs.placeholder + '</div>');
cont.append('<div class="si-input-container">' + input[0].outerHTML + '</div>');
cont.append('<div class="si-underline"></div>');
cont.append(errorCont);
elem.replaceWith(cont[0].outerHTML);
}
};
}]);
Now the resultant html using the directive above looks about right. If I put {{formdata.number}} below the form the value changes as expected. The problem is that now the validation never shows.
For example, if I put the value 5 in the input and inspect the form object, I get weird results. $dirty is set to true for form, but not for form.someNum. If I put 55 in the input, $dirty is still set to false for form.someNum, but $modelValue and $viewValue both show 55.
Any ideas or suggestions? Here is a fiddle to help with any testing.
If you put 50 in the input box you should see the value below, but put 5 and the error does not appear
UPDATE
I have managed to get it working by moving the dom changes into the link function instead of the compile function, and adding this:
elem.replaceWith(cont);
$compile(cont)(scope);
I am still puzzled though, as to why this works, while altering the dom in the exact same way in the compile function doesn't work. Is anyone able to explain this?
It's because the original ng-model is still get compiled even the original DOM has already been replaced by the new one in your compile function.
The ng-model directive will register itself to a parent form in its postLink function. Due to the fact that the postLink function will be executed in reverse (child's before parent's), the new ng-model will do the registration first, thus it will be overridden by the one from the original ng-model eventually.
To avoid this problem, you could change the original ng-model to another name such as my-model, then rename it to ng-model later in your compile function.
Example jsfiddle: http://jsfiddle.net/Wr3cJ/1/
Hope this helps.

How to bind multiple pair of selector:event in jQuery ON method

I m using jQuery 1.7+ latest .on method, but failed to implements, please help me.
working Fiddle.
basically here is my
HTML
<ul id="sortByRight" >
<li id="1">List</li>
<li id="2">Photo</li>
<li id="3">Map</li>
</ul>
<select name="sort" id="sort" >
<option value="1">Recommended</option>
<option value="2">Price: low to high</option>
<option value="3">Price: high to low </option>
<option value="4">Newest</option>
</select>
jQuery code
$(document).on('change click', 'ul#sortByRight,select#sort', function() {
selectedOption = $('select#sort').val();
whatToShow = $(this).attr('id');
alert('selectedOption:'+selectedOption+'whatToShow:'+whatToShow);
}
);
now I havebelow problems/queries.
can we bind one event with one selector i.e. above function should be called
EITHER on change of selectbox OR on click of ul.
how to set data argument in .on method. I have tried like below
$(document).on('change click', 'ul#sortByRight,select#sort',
{ selectedOption : $('select#sort').val(), whatToShow : $(this).attr('id') } ,
function(){console.log('selectedOption:'+selectedOption+'whatToShow:'+whatToShow);}
);
but get an error that selectedOption is not defined.
can we write something like this $(this, li); because I need the id of li not the id of selectbox.
if there is any other optimized solution ( using function like live or bind ), then please tell me.
Thanks A Lot.
I'm not 100% clear on what you actually want to do, but one thing doesn't make much sense. You want to send the ID of the LI when the select box is changed. Which LI? The last LI clicked? You need to store the state of the active LI so that you can send it in the ajax request if the select box is changed.
Perhaps something like this:
$('select#sort').change(function() {
processAjax();
});
$('ul#sortByRight > li > a').click(function() {
$(this).closest('ul').find('li').removeClass('active');
$(this).closest('li').addClass('active');
processAjax();
});
function processAjax() {
selectedOption = $('select#sort').val();
whatToShow = $('ul#sortByRight').find('.active').attr('id');
alert('selectedOption:' + selectedOption + 'whatToShow:' + whatToShow);
}
or check out the jsFiddle

Dojo events: getting it to work with dynamically added DOM elements

I have a method of a class as follows:
add_file: function(name, id, is_new){
// HTML: <div class="icon mime zip">name.zip <a>x</a></div>
var components = name.split('.');
var extension = components[components.length-1];
this.container.innerHTML += "<div id='"+id+"' class='icon mime "+extension+"'>"+name+" <a id='remove-"+id+"' href='#remove'>x</a></div>";
// Add event to a tag
dojo.connect(dojo.byId('remove-'+id), 'onclick', function(ev){
// here i am
});
},
All is working well, until I run this method more than once. The first time the event is registered correctly, and clicking the 'x' will run the "here i am" function. However, once I add more than one node (and yes, the ID is different), the event is registered to the last node, but removed from any previous ones.
In affect I have this:
<div id="field[photos]-filelist">
<div id="file1" class="icon mime jpg">file1.jpg <a id="remove-file1" href="#remove">x</a></div>
<div id="file2" class="icon mime jpg">file2.jpg <a id="remove-file2" href="#remove">x</a></div>
</div>
...and the remove link only works for the last node (remove-file2 in this case).
The problem is you are using the innerHTML +=
That is going to take the existing html, convert it to plain markup, and then completely create new nodes from the markup. In the process, all of the nodes with events get replaced with nodes that look exactly the same but are not connected to anything.
The correct way to do this is to use dojo.place(newNodeOrHTML, refNode, positionString)
var myNewHTML = "<div id='"+id+"' class='icon mime "+extension+"'>"+name+" <a id='remove-"+id+"' href='#remove'>x</a></div>"
//This won't work as is breaks all the connections between nodes and events
this.container.innerHTML += myNewHTML;
//This will work because it uses proper dom manipulation techniques
dojo.place(myNewHTML, this.container, 'last');