Change text in div class with text from another - javascript

I'm trying to change the text in the div class "instock" with the words 'Made by' plus the "companyName" text
<div class="productDetails">
<div class="description">
<span class="companyName>The Company Name</span>
</div>
<div class="instock">Handmade to order</div>
<div>
I want instock to look like this:
<div class="instock">Made by The Company Name</div>
I've tried this
var companyName = document.getElementsByClassName('companyName');
var companyNameText = companyName.nodeValue;
var instock = document.getElementsByClassName('instock');
var instockAlt = instock.nodeValue;
instockAlt.textContent = 'Made by' + companyNameText;
Also as this might not always need to be done (when there is no company name for changing) I think I need to check if the span class is there first.

With JQuery, you can do the following
var companyName = $('.companyName').text();
if(companyName){
$('.instock').html('Made by ' + companyName);
}

With jQuery you could do:
$('.instock').html(function() {
if ( $(this).prev('.description').find('span').length ) return 'Made by ' + $(this).prev('.description').find('span').html()
})
jsFiddle example

You have a " missing in the <span>. The line:
var companyName = document.getElementsByClassName('companyName');
Returns a HTMLCollection. Either change it to:
var companyName = document.getElementsByClassName('companyName')[0];
var companyName = document.querySelector('.companyName');
If you are using jQuery, please use:
var companyName = $('.companyName');
var companyNameText = companyName.text();
var instock = $('.instock');
var instockAlt = instock.text();
instockAlt.text('Made by' + companyNameText);
The reason is, textContent is not available everywhere, while some browsers use innerText. jQuery takes care of browser incompatibilities like this.
Also, the final code is </div> not <div>.
If the whole code is a section block, then you need to use a contextual way:
$(function () {
$('.instock').each(function() {
if ( $(this).prev('.description').find('span').length )
$(this).text('Made by ' + $(this).prev('.description').find('span').text());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="productDetails">
<div class="description">
<span class="companyName">The Company Name</span>
</div>
<div class="instock">Handmade to order</div>
</div>

Related

How to hide text/div and replace it with asterisks?

I need some help.. the idea behind this is like a simple toggle button that can hide the object and replacing the empty area with ****.
I was thinking it was more like in a Password form input where you can hide password by clicking the Eye icon. However, I needed something that are not required input form, something that is just simple DIV
function toggler(divId) {
$("#" + divId).toggle();
.css('content', 'sadas');
}
.hidden {
display:none;
}
this is a test
<div id="myContent" class='hidden'>
<div>this is a test #1 </div>
</div>
I can hide the DIV but leaving the empty area, how can I replace this empty area with ***** ??
example:
My balance is $200 [hide]
My balance is **** [show]
https://jsfiddle.net/qobgfLh6/
I have written a fiddle.
There are some points that can be better managed.
But I think you are looking for something like that.
The idea is to add another div with the **** placeholder and use toggleClass() function of jQuery.
$("#" + divId).toggleClass('hidden');
$("#myPlaceholder").toggleClass('hidden');
https://jsfiddle.net/qze8fydv/
Try to use something like this.
$(document).ready(function () {
function handle(input, toggler) {
var inputValue = ""
var shouldShowAsterisks = false
input.change(function () {
inputValue = $(this).val()
})
toggler.click(function () {
shouldShowAsterisks = !shouldShowAsterisks
shouldShowAsterisks
? input.val("*".repeat(inputValue.length))
: input.val(inputValue)
input.prop("disabled", shouldShowAsterisks)
})
}
handle($(".enter"), $(".toggler"))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="enter" />
<button class="toggler">Hide</button>
function toggleElementMask(element){
//Regex to find *
let reg = /^\*+$/g;
//If all * we are masked
let isMasked = element.innerText.match(reg);
if(!isMasked) {
//Store the original text
element.dataset.original = element.innerText;
//Replace the contente with the same amount of *
element.innerText = "*".repeat(element.innerText.length);
}else{
//Restore the text
element.innerText = element.dataset.original;
}
}
//Mask on page load
$(".masked").each(function(){
toggleElementMask(this);
});
//Click event handler
$(".toggleMask").on("click", function(e){
e.preventDefault();
toggleElementMask($($(this).attr("href"))[0]);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
this is a test
<div id="myContent" class='masked'>
<div>this is a test #1 </div>
</div>
this is a test
<div id="myContent2" class='masked'>
<div>Another one</div>
</div>
this is a test
<div id="myContent3" class='masked'>
<div>one with <span>a</span> span</div>
</div>

Looping through all divs inside a container div using jQuery

I'm trying to do a sort of invoicing system, and the html looks like this:
<invoice>
<headers>
<div date contenteditable>15-Jan-2020</div>
<div buyer contenteditable>McDonalds</div>
<div order contenteditable>145632</div>
</headers>
<item>
<div name contenteditable>Big Mac</div>
<div quantity contenteditable>5</div>
<div rate contenteditable>20.00</div>
</item>
<item>
<div name contenteditable>Small Mac</div>
<div quantity contenteditable>10</div>
<div rate contenteditable>10.00</div>
</item>
</invoice>
<button>Loop</button>
I need to loop through each <invoice> and get details from <headers> and <item>, so the end results look like this.
date : 15-Jan-2020 buyer : McDonalds order:145632
item : Big Mac quantity : 5 rate : 20.00
item : Small Mac quantity : 10 rate : 10.00
I plan on sending this data as json to a PHP script for processing.
The problem is, <headers>,<items> wont be the only containers in each invoice. There could be <address>,<transporter> etc. but they'll all be inside each <invoice>.
With that being the case, how can I loop through each container and get it's data?
Here's the jQuery I was attempting:
var button = $("button")
button.on("click", function() {
$('invoice').each(function() {
alert('It works');
});
});
Fiddle here
You can loop through div and use data-attribute for name label as below
$('invoice>headers>div, invoice>item>div').each(function(index,item) {
console.log($(this).attr('data-name'), $(this).text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<invoice>
<headers>
<div date contenteditable data-name="date">15-Jan-2020</div>
<div buyer contenteditable data-name="buyer">McDonalds</div>
<div order contenteditable data-name="order">145632</div>
</headers>
<item>
<div name contenteditable data-name="name">Big Mac</div>
<div quantity contenteditable data-name="quantity">5</div>
<div rate contenteditable data-name="rate">20.00</div>
</item>
<item>
<div name contenteditable data-name="name">Small Mac</div>
<div quantity contenteditable data-name="quantity">10</div>
<div rate contenteditable data-name="rate">10.00</div>
</item>
</invoice>
$('headers > div, item > div').each(function(item) {
console.log('item');
});
It seems your HTML isn't valid HTML. The spec doesn't define elements like <invoice>, <headers> and <item>. Besides that, attributes on elements almost always resemble key-value pairs, meaning you should declare your name, buyer, order, quantity and rate attributes as values of existing attributes. The contenteditable attribute is a boolean attribute which is OK to be left as it currently is.
Here is a fixed and working example:
var button = $('#read-invoice');
// readLine :: [String] -> (HTMLElement -> String)
function readLine(fields) {
return function (el) {
return fields.reduce(function (txt, field) {
var data = $('.' + field, el).text();
return txt === ''
? field + ': ' + data
: txt + '; ' + field + ': ' + data
}, '');
}
}
// readBlock :: { (HTMLElement -> String) } -> (HTMLElement -> String)
function readBlock(readers) {
return function (el) {
var rtype = el.className;
if (typeof readers[rtype] === 'function') {
return readers[rtype](el);
}
return '';
}
}
// autoRead :: HTMLElement -> String
var autoRead = readBlock({
headers: readLine(['date', 'buyer', 'order']),
item: readLine(['name', 'quantity', 'rate'])
// ... address, etc.
});
button.on('click', function () {
var result = $('.invoice').
children().
toArray().
reduce(function (txt, el) {
var line = autoRead(el);
return line === ''
? txt
: txt + line + '\n';
}, '');
console.log(result);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="invoice">
<div class="headers">
<div class="date" contenteditable>15-Jan-2020</div>
<div class="buyer" contenteditable>McDonalds</div>
<div class="order" contenteditable>145632</div>
</div>
<div class="item">
<div class="name" contenteditable>Big Mac</div>
<div class="quantity" contenteditable>5</div>
<div class="rate" contenteditable>20.00</div>
</div>
<div class="item">
<div class="name" contenteditable>Small Mac</div>
<div class="quantity" contenteditable>10</div>
<div class="rate" contenteditable>10.00</div>
</div>
</div>
<button id="read-invoice">Loop</button>
JS explanation
The function readLine takes an Array of Strings, where each String resembles the class name of one of the inner <div> elements. It returns a function that's waiting for a "block" element (like <div class="headers">) and reads the contents of it's contained <div>'s into a single String. Let's call the returned function a reader.
The readBlock function takes an Object of reader functions and returns a function taking a "block" element. The returned function determines which type of "block" it received and calls the matching reader function with the element as argument. If no reader matches the block type, it returns the empty String.
In the end, autoRead becomes a single function taking in a whole "block" element and returning all of it's contents as a line of text.
The button click handler looks up the <div class="invoice"> element, traverses it's DOM tree down to it's child elements (our "block" elements) and passes each "block" to autoRead, building up a result String. The final result is logged to the console.
Extending
To add new types of "block"s, simply define a new reader for it and add it to the Object passed to readBlock. For example, to add an <div class="address"> reader that reads "name", "street", "zip" and "city" infos:
var autoRead = readBlock({
headers: readLine(['date', 'buyer', 'order']),
item: readLine(['name', 'quantity', 'rate']),
address: readLine(['name', 'street', 'zip', 'city']) // <<< new
});
Extending the fields a certain reader reads is also simple, just add the name of the field to read:
var autoRead = readBlock({
headers: readLine(['date', 'buyer', 'order']),
item: readLine(['name', 'quantity', 'rate', 'currency']) // <<< added "currency"
});

How to select element has class start and end with specific string using jquery?

I got several divs using classes like
.wrap-1-addon-1
.wrap-2-addon-1
.wrap-3-addon-1
I want to select all of them and use if ( $(this).hasClass() ) to check if its one of them. Currently I only do check for a single class. How can I check all of these, for example .hasClass('wrap-*-addon-1')?
Best regards.
You can combine two jquery Attribute Starts With Selector [name^=”value”] and Attribute Ends With Selector [name$=”value”] to do this work.
$('div[class^="wrap-"][class$="-addon-1"]')
$('div[class^="wrap-"][class$="-addon-1"]').css("color", "red");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap-1-addon-1">wrap-1-addon-1</div>
<div class="wrap-2-addon-1">wrap-2-addon-1</div>
<div class="wrap-3-addon-1">wrap-3-addon-1</div>
<div class="wrap-3-addon-2">wrap-3-addon-2</div>
You can use starts with selector:
$('div[class^="wrap"]')
JsFiddle demo
You could use .is() which support multiple classes, unfortunately .hasClass() works only for one class at a time.
Example:
element.is('.wrap-1-addon-1, .wrap-2-addon-1, .wrap-2-addon-1')
It is better to add another class and select with this class. You can then test it with regex.
$el = $(".wrap");
$el.each(function() {
var test = /wrap-[1-3]-addon-1/.test($(this).attr("class"));
$(".result").html(test);
console.log(test);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap-1-addon-1 wrap"></div>
<div class="wrap-2-addon-1 wrap"></div>
<div class="wrap-3-addon-1 wrap"></div>
<div class="result"></div>
Inspiring regex matching from this answer:
var $ele = $("div:first");
alert(matchRule($ele.attr('class'),'wrap-*-addon-1'))
function matchRule(str, rule) {
return new RegExp("^" + rule.split("*").join(".*") + "$").test(str);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="wrap-1-addon-1">
</div>
<div class="wrap-2-addon-1">
</div>
<div class="wrap-3-addon-1">
</div>
This might help you, i used regex to resolve if current element's class(es) suits the desired pattern.
I assume you have more than 3 classes to check.
This pattern is for wrap-1-addon-1 to wrap-n-addon-1, n is some digit
function hasMyClass(elm) {
var regex = /(wrap-)+(\d)+(-addon-1)/i;// this is the regex pattenr for wrap-*-addon-1
var $this = $(elm);
var myClassesStr = $this.attr('class');
if(myClassesStr) { // if this has any class
var myClasses = myClassesStr.split(' '); // split the classes
for(i=0;i<myClasses.length;i++) { // foreach class
var myClass = myClasses[i]; // take one of classes
var found = myClass.match(regex); // check if regex matches the class
if(found) {
return true;
}
}
}
return false;
}
function test() {
$('#container div').each(function(){
var $this = $(this);
$('#pTest').append('<br/>test result for ' + $this.attr('id') + ':' + hasMyClass(this));
// hasMyClass(this) is the sample usage
})
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div id="div1" class="wrap-1-addon-1 anotherClass">div1 (wrap-1-addon-1)</div>
<div id="div2" class="wrap-2-addon-1 anotherClass anotherClass2">div2 (wrap-2-addon-1)</div>
<div id="div3" class="wrap-3-addon-1 anotherClass">div3 (wrap-3-addon-1)</div>
<div id="div4" class="anotherClass">div4 (none)</div>
</div>
<button id="testBtn" onclick="test();" type="button">TEST</button>
<p id="pTest" >...</p>

JavaScript reselect class personally in ListView

I am creating ListView using my template:
HTML:
<div id="ItemTemplate" data-win-control="WinJS.Binding.Template">
<div class="ItemTemplate">
<div class="back"></div>
<div data-win-bind="innerText:Info.shortName" class="shortName"></div>
<div data-win-bind="innerText:value Converters.BeginValue" class="value"></div>
<div data-win-bind="innerText:value Converters.EndValue" class="valueEnd"></div>
<div data-win-bind="innerText:Info.longName"></div>
<img data-win-bind="src:Info.flag" class="flag" />
<div data-win-bind="innerText:change Converters.BeginChange" class="change"></div>
<div data-win-bind="innerText:change Converters.EndValue" class="changeEnd"></div>
<div data-win-bind="innerText:changePercent Converters.BeginChangePercent" class="changePercent"></div>
<div data-win-bind="innerText:changePercent Converters.EndValue" class="changePercentEnd"></div>
</div>
</div>
The issue is when I meet the very long name I need to adjust font-size.
So I do (for each element in list):
JavaScript:
template = document.getElementById('ItemTemplate');
// Adjust font - size
var name = item.data.Info.longName;
// Split by words
var parts = name.split(' ');
// Count words
var count = parts.filter(function(value) {
return value !== undefined;
}).length;
var longNameDiv = $(template).children("div").children("div").eq(4);
if (count > 2) {
// Display very long names correctly
$(longNameDiv).removeClass();
$(longNameDiv).addClass("veryLongName");
}
var rootDiv = document.createElement('div');
template.winControl.render(item.data, rootDiv);
return rootDiv;
CSS:
.veryLongName {
font-size: 10pt;
}
But it doesn't effect selectivly. Moreover seems like it is check conditions for the first time and then just apply the same setting for remaining items. But it needs to change font-size to smaller only in case if the name is too long. So what am I doing wrong? Thanks.
Try by using following code instead, but u must include jquery for it.
jsfiddle : http://jsfiddle.net/vH6G8/
You can do this using jquery's filter
$(".ItemTemplate > div").filter(function(){
return ($(this).text().length > 5);
}).addClass('more_than5');
$(".ItemTemplate > div").filter(function(){
return ($(this).text().length > 10);
}).removeClass('more_than5').addClass('more_than10');
DEMO

How to remove elements except any specific id

let say there is a parent id which contains many elements and i want to remove all elements except one.
ex. :
<div id = "parent_id">
<div id = "id_1">
<div id = "id_11"> </div>
<div id = "id_11"> </div>
</div>
<div id = "id_2"> </div>
<div id = "id_n"> </div> // No need to remove this id_n only
</div>
As i can remove innerHTML like this document.getElementId('parent_id').innerHTML = ''; but i need not to remove id_n. is there any way to do that using javascript or jQuery.
$("#parent_id").children(":not(#id_n)").remove();
$("#parent_id > :not(#id_n)").remove();
No jQuery required:
const parent = document.querySelector('#parent_id');
const keepElem = document.querySelector('#id_n');
[...parent.children]
.forEach(child => child !== keepElem ? parent.removeChild(child) : null);
I think the Attribute Not Equals selector makes sense here.
$("#parent_id div[id!='id_n']").remove();
Demo.
For fun, POJS is a tad more code, but no jQuery :-)
var p = document.getElementById('parent_id');
var d = document.getElementById('id_n');
p.innerHTML = '';
p.appendChild(d);
A lot faster too. ;-)
Deleting all children other than id_n with jQuery:
$('#parent_id div').not('#id_n').remove();
If you'are going to delete the parent_id as well:
$('#id_n').insertAfter('#parent_id');
$('#parent_id').remove();

Categories