I am just learning JS/CSS.
Here is the site I am playing with.
http://keysoft.keydesign-themes.com/demo1/
I want to change "text-align" attribute of a style ".pricing .pricing-row" to "left" using JavaScript.
When I change it in Chrome console (Styles) to "text-align:left" I see that it aligns rows to left but keeps buttons centered. That is what I want.
I tried in console: document.querySelectorAll('.pricing.pricing-row')but I can't understand how to select textAlign attribute from there. It shows a NodeList.
Also I have tried document.getElementsByClassName('pricing-row') but there are elements like div.pricing-row.button-container.
These elements are unnecessary because if I use them in a loop then buttons' alignments will be affected.
So my goal is to align only "pricing-rows" without affecting alignment of buttons or other parts.
Could you tell me please the most efficient way to accomplish this task?
I'm not sure how to do this in pure JS but it's possible with jQuery.
Basically your problem is that some of the 21 divs that have the class 'pricing-row' also have other classes, and you don't want to pick those. Well actually that helps you weed them out.
First off - in order to use jQuery in the webdev console do this:
$===jQuery // should prompt true
Now:
$("div[class='pricing-row'")
will pick only divs with this specific class. Then you can do whatever you want with them. in your case:
$("div[class='pricing-row'").css('text-align', 'left');
another option which is simply very useful to no is the jQuery not() method:
$(".pricing-low).not('.button-container .selector').css('text-align', 'left');
What happens here is that first all of the elements with the "pricing-low" class are selected, and then the not() method drops the ones that have the following extra classes. In the end the css manipulation works.
Related
A created a function that renders buttons depending on how many data gotten from database.
I want to use js to set the style the button container differently,
especially setting property of of the button container to flex direction to column when it starts wrapping,
Since the website can have many buttons.
Is there a way to use javascript to check for the flexwrap property of the button container.
I tried this code but it is returning an empty string
Console.log (btnContainer.style.flexWrap)
try running btnContainer.style in the console directly, rather than console.log(). hope it will help you find a solution
This commend check only inline style like <div style="flex-wrap:wrap;"></div>. Now if you console.log(document.querySelector('div').style.flexWrap) you will get string with value "wrap".
The solution your problem is add style this element in html inline as I wrote above or in js like document.querySelector('div').style.flexWrap = wrap
OK. I'm trying to get elements in javascript by CSS selector. To get one by custom element I know is like 'element[custom-name="Literal name"]'.
OK. This works. But now I need to get the second one. I mean I have some elements with the exact custom-name, and for everyone I need to apply a diferent rule (tehere are only 5).
How can I select the other ones? Is posibble select them by CSS?
PS: They are located in random positions, so maybe the first one is the 5 element one time and if I refresh the page it can be the 10 element inside the container.
PS2: No, It's not possible to change the HTML in my case :( . The only code I'm alowed to change is CSS and javascript.
Thanks for reading me! :D
Assuming you can't select specific ones by another, non-order-dependent factor, you can use the pseudo-selector :nth-child. In your case, the complete CSS selector would be element[custom-name="Literal name"]:nth-child(2) - substitute the 2 for any other number as you see fit. Generally it's not the best idea to select only by position in the document, as position may change more often than attributes - but in any case, there's a pure CSS solution!
Note that this only works if the elements you're working with are the only children of a common parent element - if you're looking for the second element that matches that query in general across the entire document, there is no way to do that with a CSS selector. Instead, you can make sure to add a unique class or other differentiating attribute to each element, or simply use querySelectorAll - in that case, you could get the second element using this little snippet: document.querySelectorAll('element[custom-name="Literal name"]')[1].
I have a dropdown, and a list of elements that default to display:none with css.
Currently, when an element is selected from the dropdown it's changed to display:block
What I'm missing, is how to change the element back to display:none once a new one is selected. I know I could write a loop to constantly check every element and change it to display:none but that seems cumbersome.
My real problem has about 100 elements, and it seems wasteful to re-hide all of them when 99 of them will already be hidden.
Curious what the most elegant way to do this in jQuery (or javascript) is. A fiddle of what I have is here:
https://jsfiddle.net/3w66k51z/4/
Thanks!
I've added $(".sReport").hide(); before your .show() call in order to hide all of the elements.
jQuery.hide() will set the element's display to none
jsfiddle
You could add state so that you know the currently shown item (if any) and hide just that one element. I understand you don't want to hide all items when most of them will already be hidden.
Here is a simple implementation of this idea.
(I imagine your real problem involves many more hidden items than the fiddle. If not — maybe even if so — this may be a premature optimization, and there’s nothing wrong with calling .hide() or whatever on all items.)
Create array of your element then create a function to hide all elements but not the one you want to be display.
There is not nice HTML structure I need to work with and the list of elements I need to select is within an iframe. The problem is that I am interested just in 2 type of divs within many other divs on same level.
I am able to select such a type from the iframe but just one at time:
$("#someIframe").contents().find(".class a img[src*='type1']")
But I am unable to select both:
$("#someIframe").contents().find(".class a img[src*='type1'], .class a img[src*='type2']") -> does not work
The problem is that I need to select the first one, but I don't know which one is the first one :) something like:
$("#someIframe").contents().find(".class a img[src*='type1'], .class a img[src*='type2']").first()
UPDATE 1:
I have found another way around. I have noticed that those elements I don't want to select contains specific text:
<div>not listed</div>
However, again finding the correct selector would be the problem since I need opposite of this below :)
$("#someIframe").contents().find(".someclass div:contains('not listed')").first()
I have figured it out. Here is the code if anyone needs it in the future:
$("#someIframe").contents().find(".someclass").not($("#someIframe").contents().find(".someclass div:contains('not listed')").parent()).first()
It's not nice, but the markup itself is not nice, so I guess it's fine :)
When a draggable attribute is enabled on a parent element(<li>) I cant make contenteditable work on its child element (<a>).
The focus goes on to child element (<a>),but I cant edit it at all.
Please check this sample
http://jsfiddle.net/pavank/4rdpV/11/
EDIT: I can edit content when I disable draggable on <li>
I came across the same problem today, and found a solution [using jQuery]
$('body').delegate('[contenteditable=true]','focus',function(){
$(this).parents('[draggable=true]')
.attr('data-draggableDisabled',1)
.removeAttr('draggable');
$(this).blur(function(){
$(this).parents('[data-draggableDisabled="1"]')
.attr('draggable','true')
.removeAttr('data-draggableDisabled');
});
});
$('body') can be replaced by anything more specific.
If new contenteditable elements are not added in the runtime, one can use bind instead of delegate.
It makes sense that the draggable and contenteditable properties would collide. contenteditable elements, like any text field, will focus on mousedown (not click). draggable elements operate based on mousemove, but so does selecting text in a contenteditable element, so how would the browser determine whether you are trying to drag the element or select text? Since the properties can't coexist on the same element, it appears that you need a javascript solution.
Try adding these two attributes to your anchor tag:
onfocus="this.parentNode.draggable = false;"
onblur="this.parentNode.draggable = true;"
That works for me if I add it to the <a> tags in your jsFiddle. You could also use jQuery if it's more complicated than getting the parentNode.
Note: This is a workaround since I believe the inability for these two functionalities to work together resides in the HTML spec itself (i.e. the not working together thing is intentional since the browser can't determine whether you want to focus or drag on the mousedown event)
I noticed you explicitly set 'no libraries', so I will provide a raw javascript/HTML5 answer
http://jsfiddle.net/4rdpV/26/
This was my crack at it.
First of all, it might be better to include the data in one single localStorage item, rather than scatter it.
storage={
'1.text':'test 1',
'2.text':'test 2'
}
if(localStorage['test']){
storage=JSON.parse(localStorage['test'])
}
this creates that ability, using JSON to convert between object and string. Objects can indeed be nested
I also added (edit) links next to the items, when clicked, these links will transform the items into input elements, so you can edit the text. After hitting enter, it transforms it back and saves the data. At the same time, the list items remain draggable.
After saving, hit F12 in chrome, find the console, and look in the localStorage object, you will see all the data was saved in localStorage['test'] as an Object using JSON.stringify()
I tried my best to design this to be scaleable, and I think I succeeded well enough; you just need to replace the HTML with a container and use a javascript for loop to write out several items, using the iterator of your choice to fill the parameter for edit(). For example:
Say you changed storage to hold "paradigms" of lists, and you have one called "shopping list". And say the storage object looks something like this:
{
"shopping list":{
1:"Milk",
2:"Eggs",
3:"Bread"
}
}
This could render that list out:
for(i in storage['shopping list']){
_item = storage['shopping list'][i];
container.innerHTML+='<li draggable=true><a id="item'+i+'">'+_item+'</a> (edit)</li>'
}
Of course, if you were to edit the structure of the storage object, you would need to edit the functions as well.
The output would look something like this:
Milk (edit)
Eggs (edit)
Bread (edit)
Don't worry about the input elements if that worries you; CSS can easily fix it to look like it didn't just change.
If you don't want the (edit) links to be visible, for example, you can do this in CSS:
a[href="#"]{
display:none;
}
li[draggable="true"]:hover a[href="#"]{
display:inline;
}
Now the edit links will only appear when you hover the mouse over the list item, like this version:
http://jsfiddle.net/4rdpV/27/
I hope this answer helped.
Using html5sortable and newer JQuery events (delegate is deprecated, answer 3 years after initial question), bug still affects Chrome 37. Contenteditable spans and html5sortable seem to play nice in other browsers. I know this is only partially relevant, just keeping documentation on changes I've noticed.
$(document).on('focus', 'li span[contenteditable]', function() {
$(this).parent().parent().sortable('destroy'); // removes sortable from the whole parent UL
});
$(document).on('blur', 'li span[contenteditable]', function() {
$(this).parent().parent().sortable({ connectWith: '.sortable' }); // re-adds sortable to the parent UL
});