Changing the Text of a Span Class by script (magento) - html

Hello. First of all, sorry for eventual English mistakes, since I'm Brazilian:
I have a ecommerce based on magento 1.9.2.2, and the company that hosts it does not allow the user to access the server files (header, body, footer, etc). You can only edit the website via css and html external scripts.
So there's this div:
<p class="old-price">
<span class="price-label">De:</span>
<span class="price" id="old-price-1046">
R$2.500,00 </span>
</p>
<p class="special-price">
**<span class="price-label">Preço Promocional</span>**
<span class="price" id="product-price-1046">
R$2.299,90 </span>
</p>
Which I just need to replace the text "Preço Promocional" (within the "price-label" class) for "Por:"
So far I've tried:
document.getElementsByClassName('price-label').innerHTML = 'Por:';
javascript:document.getElementsByClassName('price-label').innerHTML = 'Por:';
javascript:void(document.getElementsByClassName('price-label').innerHTML = 'Por:');
Thanks for any help in advance...

getElementsByClassName returns a collection and not a single element. In your example you have two elements with the same class name, you'd access the first one with the index 0 and the second one with the index 1.
<p class="old-price">
<span class="price-label">De:</span>
<span class="price" id="old-price-1046">R$2.500,00</span>
</p>
<p class="special-price">
<span class="price-label">Preço Promocional</span>
<span class="price" id="product-price-1046">R$2.299,90</span>
</p>
<script>
document.getElementsByClassName('price-label')[1].innerHTML = "Por:";
</script>
This code will change the second one that says "Preço Promocional" for "Por:"
//EDIT
Now that I've seen the full page, in javascript you could achieve this with:
<script>
document.querySelectorAll('.special-price .price-label').forEach(function(node) {
node.innerHTML = 'Por: ';
});
</script>
This will target all elements with the class price-label inside elements with the class special-price, loop through each and change their contents. This will change the main, related and recommended products as long as it's put after they are created.
As a preferred alternative, try using the following css:
<style>
.special-price .price-label {
display:none !important;
}
.special-price::before {
content: 'Por: ';
}
</style>
This should hide the content and then prepend the text on the parent and doesn't required to be placed at the end to work.
// EDIT (To address new information added in the comments for this answer)
In order to avoid changing the homepage, you can use the :not() css' pseudo-class (info here) to exclude those instances of special-price that are found within the homepage. I searched for and id or class that was unique to the homepage (found the class cms-home on the body tag for the homepage) so I'm using that to both exclude and target the different price-labels. I also changed the font-size to match the original one:
<style>
// this targets price-label that's NOT in the homepage
body:not(.cms-home) .special-price .price-label {
display:none !important;
}
body:not(.cms-home) .special-price::before {
content: 'Por: ';
font-size:15px;
}
// this targets price-label on the homepage
.cms-home .special-price .price-label {
display:none !important;
}
</style>
If I understood correctly, on the homepage you're simply hiding the text, while on the other pages you're replacing it with "Por: ", this should do it (hopefully) unless there's another special case I'm unaware of.

Try this
<script>
$('.special-price .price-label').text('Por:');
</script>

Related

How to change text style when hovering over text elsewhere with multiple connections in html

I'm new to html, so sorry if the syntax or something is wrong.
I have a some html code. When I hover over 1, I want the sentence "This is the first match" to change e.g. color later in the document
I can achieve that with this CSS code:
#number1:hover ~ #match1{
color: yellow;
}
#number2:hover ~ #match2{
color: yellow;
}
Please hover over this number to see the respective match
<a id="number1">1</a>
<br>
Or hover over this number to see the respective match
<a id="number2">2</a>
<br>
<a id="match1">This is the first match</a>
<br>
<a id="match2">This is the second match</a>
However, I have multiple connections where I want the same pattern and not just these two. Is there any way I can apply this pattern easy globally in the document?
I don't know if <a> is the right to use, but I though that href might be a solution, but I'm not sure.
Thanks in advance!
You can approach this problem using Javascript with the onmouseover (hover) event. However, to give the same attribute to all of our desired tags, we need to give them all a common class name.
<body>
<a class = "colorchange" id="match1">This is the first match</a>
<br>
<a class = "colorchange" id="match2">This is the second match</a>
<br>
<a class = "colorchange" id="match3">This is the third match</a>
<br>
<a class = "colorchange" id="match4">This is the fourth match</a>
<script>
elements = document.getElementsByClassName("colorchange");
for(var i = 0, length = elements.length; i < length; i++) {
colorChange(elements[i])
}
function colorChange(btn){
btn.onmouseover = function(){
btn.style.color = "yellow"
}
}
</script>
</body>

Make an action on class or id affect other

I am working with a Web Form (html) and a CSS file and I wanna know what do I need to write in the CSS to make an action on one class or id- affect an other class or id. For example: I have a
<p class="hh">
Hello!
</p>
(^^ this p tag's class is "hh")
And another one:
<p class="gb">
Goodbye!
</p>
(^^ this p tag's class is "gb")
I wanna write something in the CSS file so that whenever I click on whatever there is in the "hh" class, it will make something change in the "gb" class, so if I click on the text "Hello!" it will make the color of the text "Goodbye!" green. Please help me! I try to find out how to do it for a long long time...
Thank you!
This sounds more like you need a javascript solution. In general you are not really able to change something on a click event in CSS. Consider following solution:
const hh = document.getElementById("hh");
const gb = document.getElementById("gb");
hh.addEventListener("click", function() {
gb.style.color = "green";
});
gb.addEventListener("click", function() {
hh.style.color = "red";
});
<div id="hh">
Hello!
</div>
<div id="gb">
Goodbye!
</div>
A common practice for doing this is by using JavaScript, which is known as the programming language of the web. If you've never used JavaScript before it can be a little bit confusing but if you have experience in other general purpose programming languages such as Python or Java then it shouldn't take much time to pick up.
To do what you are asking, there are a few possible ways to do this. I will share what I believe to be the most simple although not the most robust. You can use JavaScript events to fire off certain functions when certain particular things happen to your elements. For example, you can modify your HTML like so:
<p class="hh" onclick="doSomething()">Hello!</p>
Then, either in a separate JavaScript file linked back to your html file or in the of your html file, you would define the doSomething() function:
function doSomething(){
document.getElementsByClassName("gb")...
}
The document.getElementsByClassName() function is one way to select HTML elements from a page and modify it via JavaScript, I suggest checking out the very good JavaScript tutorials on W3Schools for more and better ways to do this, but this is the general principal. You would then modify the HTML element any way you need to.
Hope this helps!
You need to do that using JavaScript. I have attached a example for that.
$(".one").on('click', function() {
$(".two").css('color', 'red');
})
.one{
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="one"> Change below text to RED </p>
<p class="two"> Black text </p>
There is a way to use a :focus state to change the look of parents, but it wouldn't be possible to differentiate between which click caused the parent to focus.
Here's a simple example using JavaScript and jQuery.
var helloEls = document.querySelectorAll('#jsTest .hh');
var goodbyeEls = document.querySelectorAll('#jsTest .gb');
helloEls.forEach(function(elem) {
elem.addEventListener("click", function() {
goodbyeEls.forEach(function(el) {
if (el.className==='gb active'){
el.className = 'gb';
} else {
el.className = 'gb active';
}
});
});
});
var gbEls = $('#jqueryTest .gb');
$('#jqueryTest .hh').click(function(){
if (gbEls.hasClass('active')){
gbEls.removeClass('active');
} else {
gbEls.addClass('active');
}
});
.gb.active {
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="jsTest">
<p class="hh">
Hello!
</p>
<p class="gb">
Goodbye!
</p>
</div>
<div id="jqueryTest">
<p class="hh">
Hello!
</p>
<p class="gb">
Goodbye!
</p>
</div>

angular ngModel style

Is it possible to style the value in the attribute ngModel of an input tag?
Example:
<input class="input" type="text" [(ngModel)] = "myService.text">
Let's say the value of text is '28 packages', can I put 28 in bold?
So if i understand correctly you want to have it bold whenever the value is 28 ?
yes its possible you can use a ng-class with a ternary expression like this
.bold{
font-weight:600;
}
<input type="text" ng-class="myService.text == '28 ? 'bold' : '''" class="input" ng-model="myService.text" />
This is not angular-related rather a CSS related question.
You cannot style only a part of an input in HTML/CSS so you won't be able to do it in angular.
Instead, you can use an input that is hidden behind a div. The idea is that when the user clicks the div, you actually focus the input. When the user types text, you capture the content of the input and fill the div with it, eventually adding <span class"highlight"> around the number of packages.
I prepared you a stackblitz in pure CSS/JS. You can adapt it in angular if you want.
Relevant pieces of code :
HTML :
<span id="hiddenSpan">This is the hidden div. Click it and start typing</span>
<div>
<label for="in">The real input</label>
<input id="in" type="text">
</div>
JS :
const input = document.getElementById('in')
const hiddenSpan = document.getElementById('hiddenSpan')
function onInputChanged() {
let text = input.value
const regex = new RegExp('(\\d+) packages')
let result = regex.exec(text)
if(result) {
hiddenSpan.innerHTML = '<span class="highlight">'+result[1]+'</span> packages'
} else {
hiddenSpan.innerHTML = text
}
}
// Capture keystrokes.
input.addEventListener('keyup', onInputChanged)
// Focus the input when the user clicks the pink div.
hiddenSpan.addEventListener('click', function() {
input.focus()
})
CSS :
#hiddenSpan {
background-color: pink;
}
.highlight {
font-weight: bold;
background-color: greenyellow;
}
Note : the downside is that the blinking caret is not visible anymore. You can take a look at this resource if you want to simulate one.
It is not possible to style certain parts of a text <input> field in bold. However, you can use a contenteditable div instead of a text <input> field. Inside the contenteditable div you can have other HTML tags like <strong> to style certain parts of the text however you like.
I created an Angular directive called contenteditableModel (check out the StackBlitz demo here) and you can use it to perform 2-way binding on a contenteditable element like this:
<div class="input" contenteditable [(contenteditableModel)]="myService.text"></div>
The directive uses regular expressions to automatically check for numbers in the inputted text, and surrounds them in a <strong> tag to make them bold. For example, if you input "28 packages", the innerHTML of the div will be formatted like this (to make "28" bolded):
<strong>28</strong> packages
This is the code used in the directive to perform the formatting:
var inputElement = this.elementRef.nativeElement;
inputElement.innerHTML = inputElement.textContent.replace(/(\d+)/g, "<strong>$1</strong>");
this.change.emit(inputElement.textContent);
You can change the <strong> tag to something else (e.g. <span style="text-decoration: underline"> if you want the text to be underlined instead of bolded).
When performing the formatting, there is an issue where the user's text cursor position will be unexpectedly reset back to the beginning of the contenteditable div. To fix this, I used 2 functions (getOriginalCaretPosition and restoreCaretPosition) to store the user's original cursor position and then restore the position back after the text formatting is performed. These 2 functions are kind of complex and they're not entirely relevant to the OP's question so I will not go into much detail about them here. You can PM me if you want to learn more about them.

CSS Dot Notation Naming Convention

I am getting started with learning CSS.
While looking through the tutorial on w3schools.
I realized some of the example start with
.awesome-text-box{}
Is there a different between
.awesome-text-box {} and awesome-text-box{}
without the dot?
What does the dot notation means here
p.one {
border-style: solid;
border-width: 5px;
}
p.two {
border-style: solid;
border-width: medium;
}
p referes to ?
A dot in css is for what is called a class.
They can be called almost anything, for example in your CSS you would create a class and add style for it (in this case, I'm making the background black);
.my-first-class {
background-color: #000;
...
}
and to apply this class to an HTML element, you would do the following
<body class="my-first-class">
...
</body>
this would mean the body of the page would become black.
Now, you can create classes for CSS style or you can reference HTML elements directly, for example (CSS again);
body {
background-color: #000;
}
would directly reference the <body> element on the page and do the same again.
The main difference between the two is that CSS classes are reusable. By comparison, referencing the HTML tag directly will affect all tags on the page (that are the same), for example (CSS again);
body {
background-color: #000;
}
.my-first-class {
background-color: #FFF;
}
and now for some HTML;
<body>
<p class="my-first-class">This is the first line</p>
<p class="my-first-class">This is the second line</p>
</body>
This would produce a black page, with 2 white boxes with text inside them (try it out!)
Now for your last part of the question about p.one {...} CSS.
This is a reference to a <p> tag that has class="one" added to it, <p class="one">...</p>
That CSS will only work on a <p> tag with the one class added (as above).
Extra for experts...
There is also one more selector type and it's called an ID (and I personally do not use these when doing CSS styling but some people like too and I don't know why...)
Much like a class, you can have an id on an HTML element; <p id="my-first-id"></p>
and to add CSS style to this, you would put (in the CSS);
#my-first-id {
...
}
and that would style all elements with that id added.
Hopefully that helped answer all the parts, ask again if you need an even better explanation :)
The dot denotes that the selector is a class. So it will select elements in your page as such:
.awesome-text-box {
}
<div class="awesome-text-box"></div>
Whereas without the dot denotes an element name. Such as:
div {
}
<div></div>
In the other example you gave, the dot notation is using chaining this is where you can select an element with numerous conditions. In your example:
p.one {
}
// Will find
<p class="one"></p>
// However it will not find
<div class="one"></div>
Whilst I am here I can give you a list of other common selectors too:
#awesome-text-box => <div id="awesome-text-box"></div> => ID
.btn.btn-style-1 => <span class="btn btn-style-1"></span> => Chaining classes
p > span => <p><span></span></p> => Child
p span => <p><a><span></span></a><span></span> => Descendant (anything below)
p + span => <p></p><span></span> => Sibling
A '.' refers to a class, while a '#' refers to a id.
When neither a '.' or a '#' are used, the CSS will apply the style to an HTML object.
So for p .one and p .two, the CSS will be applied to the '.one' and '.two' classes that exists within the 'p' object.
For a more detailed example;
<p class = "one">This text will have the CSS of "p .one"</p>
<p class = "two">This text will have the CSS of "p .two"</p>
. means a class. You can call that CSS class with HTML
example
<span class="awesome-text-box"> ABCD </span>
and P means <p> tag in HTML you can call
<p class="one"> ABCD </p>
Ref -
http://www.w3schools.com/css/css_selectors.asp
The dot notation is for class and without dot that would not work. The selector name like div, p don't need dot notation. And use hash (#) for the selector with id.
Ex-
<div id="foo">foo bar</div>
<div class="bar">foo bar</div>
#foo{} /* selects foo with id foo */
.bar{} /* selects foo with class bar */
div{} /* selects the div */
Here . is class selector. It means apply style to all elements which has class awesome-text-box ie,
<div class="awesome-text-box"></div>
while without dot it is tag name like you mention in second example p Here p is tag:
<p>Some text</p>
Similarly p.one apply the style to all p tags which has class one. ie,
<p class="one">Some text</p>

Is it bad to put <span /> tags inside <option /> tags, only for string manipulation not styling?

I would like to make groups of the text content of an <option /> tag. Say I have the following: <option>8:00 (1 hour)</option>, the time pattern 8:00 can be modified, then the text in parenthesis (1 hour) can also be modified.
I was thinking of doing something like
<option>
<span>8:00</span>
<span> (1 hour)</span>
</option>
Is it bad to put <span /> tags inside <option /> tags, only for string manipulation not styling?
From the HTML 5spec:
Content model:
If the element has a label attribute and a value attribute: Nothing.
If the element has a label attribute but no value attribute: Text.
If the element has no label attribute and is not a child of a datalist element: Text that is not inter-element whitespace.
If the element has no label attribute and is a child of a datalist element: Text.
So depending on context there are two things that you can put inside an <option> — text or nothing at all — you may not put a <span> or any other element there.
From the HTML 4.01 spec:
<!ELEMENT OPTION - O (#PCDATA) -- selectable choice -->
(Even the HTML 3.2 and HTML 2 specs say: <!ELEMENT OPTION - O (#PCDATA)*>)
An option element cannot have any child elements. So yes, it is bad.
You can use a Javascript plugin to overcome this limitation. For example jQuery plugin "Select2" Select2 plugin homepage. I use it in a couple of my projects and think that it's pretty flexible and convenient.
There are a number of them, but they do quite same thing - convert traditional <select> into <div> blocks with an extra functionality.
The option element
Content model: Text
No, it’s not ok. Consider keeping the values around in your script so you can recompose them when necessary.
You're better off using an HTML replacement for your <select> if you want to do this.
As established by other people, and I have tried with <b> and other tags, <option> does not take tags within it.
What you can do, since you cannot use <span> inside an <option> tag,
You can use the index number to extract the text via
document.getElementById(selectid).options[x].text where x is the relevant index, as a variable.
Then what you do is use the " (" to split the variable into the time, and remove the last character as well which removes the ")"
Sample:
<script type="text/javascript">
function extractSelectText()
{
var text = document.getElementById("main").options[1].text
/*
var tlength = text.length
var splitno = tlength - 1
var text2 = text.slice(0, splitno)
var textArray = text2.split(" )")
var time = textArray[0]
var hours = textArray[1]
}
</script>
Changing it is much simpler:
<script type="text/javascript">
function changeSelectText()
{
/* add your code here to determine the value for the time (use variable time) */
/* add your code here to determine the value for the hour (use variable hours) */
var textvalue = time + " (" + hours + ")"
document.getElementById("main").options[1].text
}
</script>
If you use a for function you can change each value of the select replacing 1 with 2, 3 and so on, and put a set interval function to constantly update it.
One option for editing would be to use some fancy pattern matching to update the content. It will be slower and more resource intensive, and depends on how regular the format is, but doesn't require any HTML modifications. My concern, however, would be on accessibility and the user experience. Having values change is hard for screen reader software to pick up, and it may also confuse other users.
It is not an answer, but may be it will help sombody, it is possible to mimic select with details tag. This example is not complete, I used javascript to close list on click
const items = document.querySelectorAll(".item");
// Add the onclick listeners.
items.forEach(item => {
item.addEventListener("click", e => {
// Close all details on page
closeList(item);
});
});
function closeList(item) {
document.querySelectorAll("details").forEach(deet => {
if (deet != this && deet.open) {
deet.open = !open;
console.log(item);
}
});
}
details {
border: 1px solid #aaa;
border-radius: 4px;
}
summary {
padding: .5em 0 .5em .5em;
font-weight: bold;
}
details[open] {
}
details[open] .item {
cursor: pointer;
padding: .5em 0 .5em .5em;
border-top: 1px solid #aaa;
}
details[open] .item:hover{
background-color: #f1f1f1;
}
details[open] .title{
padding: .5em 0 .5em .5em;
border-top: 1px solid #aaa;
}
<details>
<summary>Select your choice</summary>
<div class='title'>
This is attempt to mimic native <code>select</code> tag with html for <code>option</code> tag
</div>
<div class='item'>item 1</div>
<div class='item'>item 2</div>
<div class='item'>item 3</div>
</details>