This is the code I have and it is not working. I dunno how to declare this
var input = {
container: '.slide_container',
container_all: '.slide_show',
slides: []
};
var $slides = $('.slide_show .slide');
var l = $slides.length;
for( var i = 0; i < l; i++ ) {
input.slides[i].el = '#' + $slides.eq(i).attr('id');
if( i === 0 ) {
input.slides[i].weight = 1;
} else {
input.slides[i].weight = 0;
}
}
When it gets to
input.slides[i].el = '#' + $slides.eq(i).attr('id');
it says the input.slides[i].el is undefined. Can someone let me know the correct way to declare the empty slides?
You need to create your object first. Something like:
input.slides[i] = { el: '#' + $slides.eq(i).attr('id'), weight: 0 };
You also might want to consider using push to add to your array.
input.slides.push({ el: '#' + $slides.eq(i).attr('id'), weight: 0 }); //Add new object to the array
You should initialize input.slides[i] before assign something to its attribute.
for( var i = 0; i < l; i++ ) {
input.slides[i] = {};
input.slides[i].el = '#' + $slides.eq(i).attr('id');
if( i === 0 ) {
input.slides[i].weight = 1;
} else {
input.slides[i].weight = 0;
}
}
Related
For example, if I have CSS that included within document:
div {
color: red;
}
div.test {
border: 1px solid blue;
}
and html tag within document body:
<div id='demo'>
<div class='test'>123</div>
<div>456</div>
</div>
I want to convert everything within #demo as a string containing tag with all styles it was using, such as:
var parent = $('#demo');
var result = convertExternalInternalStylesToInline(parent);
// the desired result:
result = '<div style="color: red; border: 1px solid blue;">123</div>' +
'<div style="color: red">456</div>'
What I need is the content of convertExternalInternalStylesToInline function, that automatically fetch all descendant elements, apply the calculated/used styles then add css styles to those elements, then return it all as html string.
Can it be done using only client side javascript? If yes, how?
(I need to know how to get all calculated/used styles for a tag)
minimal example:
function convertExternalInternalStylesToInline(parent) {
var parent = $(parent).clone(); // clone it before modify, is this deep clone?
parent.find('*').each(function(idx,el){ // fetch all children
var el = $(el); // convert to jquery object
// get all applied styles on this element
// el.? // --> don't know how
// apply css for each styles
el.css( css_prop, css_style );
});
// return as string, maybe:
return parent.html();
}
EDIT: Thanks to Winchestro, I looked up the window.getMatchedCSSRules function, which is actually only in Webkit, and there is a discussion that it should be deprecated.
What you should be using is actually the window.getComputedStyle() Read the docs at MDN.
Another very useful resource you may look into is the CSSUtilities set of libraries.
What you need are two separate things, a library to parse out your CSS Object Modal (CSSOM), and apply the relevant CSS to your DOM elements.
I know of a good nodejs library which does this called Juice.
There are is a library I found which would probably work on the front-end, called inlineresources, which has a browserified build
On second thoughts, I think you may be able to use Juice along with browserify for this... But you'll have to evaluate that possibility manually...
assuming you have the HTML in an array (lines: string[]):
I'm not sure why I spent so much time on this
let styleLines = this.getLinesInsideStyleTag(lines)
let htmlLinesSeparatedByTag = this.getLinesNotInsideStyleTag(lines)
let mapOfCSSrules = this.getMapOfCSSRuleNamesAndPropertiesFromCSSLines(styleLines)
let linesWithInlineRulesApplied = this.applyInlineStylesToLines(htmlLinesSeparatedByTag, mapOfCSSrules)
let finalString = ""
for(let v = 0; v < linesWithInlineRulesApplied.length; v++ ) {
finalString = finalString + linesWithInlineRulesApplied[v]
}
console.log(finalString)
getLinesInsideStyleTag(lines: any[]) {
let styleLines: any[] = []
let foundStylesStartTag = false
let foundStylesEndTag = false
for(let i = 0; i < lines.length; i++ ) {
if(lines[i].indexOf("<style ") != -1) {
foundStylesStartTag=true
} else if(lines[i].indexOf("</style>") != -1) {
foundStylesEndTag = true
}
if(foundStylesStartTag == true && foundStylesEndTag == false) {
if(lines[i].indexOf("<style") == -1 && lines[i].indexOf("</style") == -1) {
styleLines.push(lines[i])
}
}
}
return styleLines
}
getLinesNotInsideStyleTag(lines: any[]) {
let foundStylesStartTag = false
let foundStylesEndTag = false
let linesToKeep: any[] = []
for(let i = 0; i < lines.length; i++ ) {
if(lines[i].indexOf("<style ") != -1) {
foundStylesStartTag=true
} else if(lines[i].indexOf("</style>") != -1) {
foundStylesEndTag = true
}
if(foundStylesStartTag == false && foundStylesEndTag == false) {
linesToKeep.push(lines[i])
} else if(foundStylesStartTag == true && foundStylesEndTag == true) {
if(lines[i].indexOf("<style") == -1 && lines[i].indexOf("</style") == -1) {
linesToKeep.push(lines[i])
}
}
}
let actualLinesToKeep: any[] = []
for(let i = 0; i < linesToKeep.length; i++ ){
let thisLineSplitOnOpeningTag = linesToKeep[i].split("<")
let pushFullLine = false
let modifiedLine = ""
for(let y = 0; y < thisLineSplitOnOpeningTag.length; y++) {
if(thisLineSplitOnOpeningTag[0] !== "") {
pushFullLine = true
} else {
if(thisLineSplitOnOpeningTag.length > 2) {
//then the line contains nested tags (oof)
if(thisLineSplitOnOpeningTag[y].length > 0) {
if( y != thisLineSplitOnOpeningTag.length - 1) {
modifiedLine = modifiedLine + "<" + thisLineSplitOnOpeningTag[y]+"%*#"
} else {
modifiedLine = modifiedLine + "<" + thisLineSplitOnOpeningTag[y]
}
}
} else {
pushFullLine = true
}
}
}
if(pushFullLine == true) {
// console.log("3pushing full line because it doesn't have nested tags: "+linesToKeep[i])
actualLinesToKeep.push(linesToKeep[i])
} else {
actualLinesToKeep.push(modifiedLine)
}
}
// console.log("actualLinesToKeep: ")
// console.log(actualLinesToKeep)
return actualLinesToKeep
}
//e.g. you pass it
// myRule {
// color: blue;
// text-align: left;
// }
// you get back: a dictionary / map where "myRule" is the key, and "color: blue;" and "text-align: left;" are the values for that key.
getMapOfCSSRuleNamesAndPropertiesFromCSSLines(styleLines: any[]) {
// console.log("styleLines: ")
// console.log(styleLines)
//rule, properties
let CSSrules: Map<string,any[]> = new Map();
let rulesSplitOnClosingBracket = styleLines.toString().split("}")
for(let i = 0; i < rulesSplitOnClosingBracket.length; i++) {
let indexOfOpeningBracket = rulesSplitOnClosingBracket[i].indexOf("{")
let ruleName = rulesSplitOnClosingBracket[i].substring(0,indexOfOpeningBracket).trim()
ruleName = this.replaceAll(ruleName,",","").toLowerCase()
if(ruleName[0] === ".") {
ruleName = ruleName.substring(1)
}
//replace dots with a space
ruleName = ruleName.replace(/\./g,' ')
let propertiesOfThisRule = rulesSplitOnClosingBracket[i].substring(indexOfOpeningBracket+1).split(",")
let propertiesToKeep: any[] = []
for(let j = 0; j < propertiesOfThisRule.length; j++) {
propertiesOfThisRule[j] = propertiesOfThisRule[j].trim()
if(propertiesOfThisRule[j] !== undefined && propertiesOfThisRule[j].length > 0) {
propertiesToKeep.push(propertiesOfThisRule[j])
}
}
if(ruleName !== undefined && ruleName.length > 0 && propertiesToKeep !== undefined && propertiesToKeep.length > 0) {
CSSrules.set(ruleName, propertiesToKeep)
}
}
return CSSrules
}
applyInlineStylesToLines(htmlLinesSeparatedByTag: any[], mapOfCSSrules: Map<string,any[]>) {
let linesWithInlineRulesApplied: any[] = []
let ruleNames = Array.from(mapOfCSSrules.keys())
for(let r = 0; r < htmlLinesSeparatedByTag.length; r++) {
let lineSplitOnContinuationCharacter = htmlLinesSeparatedByTag[r].split("%*#")
let partsOfLineThatContainClosingTags: any[] = []
let partsOfLineThatDoNotContainClosingTags: any[] = []
for(let d = 0; d < lineSplitOnContinuationCharacter.length; d++) {
if(lineSplitOnContinuationCharacter[d].indexOf("</") != -1) {
partsOfLineThatContainClosingTags.push({orderNumber: d, line: lineSplitOnContinuationCharacter[d]})
} else if(lineSplitOnContinuationCharacter[d].indexOf("</") == -1) {
partsOfLineThatDoNotContainClosingTags.push({orderNumber: d, line: lineSplitOnContinuationCharacter[d]})
}
}
let orderNumbers1: any[number] = partsOfLineThatDoNotContainClosingTags.map(val => val.orderNumber)
let orderNumbers2: any[number] = partsOfLineThatContainClosingTags.map(val => val.orderNumber)
let maxOrderNumberFor1 = Math.max.apply(Math,orderNumbers1)
let maxOrderNumberFor2 = Math.max.apply(Math,orderNumbers2)
let maxOrderNumber: number;
if(maxOrderNumberFor1 > maxOrderNumberFor2) {
maxOrderNumber = maxOrderNumberFor1
} else {
maxOrderNumber = maxOrderNumberFor2
}
let thisActualLineWithStylesApplied = ""
for(let u = 0; u < maxOrderNumber+1; u++) {
let partOfLineWithoutClosingTag = partsOfLineThatDoNotContainClosingTags.filter(val => val.orderNumber == u)[0]?.line
let partOfLineWithClosingTag = partsOfLineThatContainClosingTags.filter(val => val.orderNumber == u)[0]?.line
if ( partOfLineWithoutClosingTag !== undefined ) {
let idxOfFirstSpace = partOfLineWithoutClosingTag.indexOf(" ")
for(let s = 0; s < ruleNames.length; s++) {
let applyThisRuleToThisLine = true
let textToCheckFor: any[] = ruleNames[s].split(" ")
for(let t = 0; t < textToCheckFor.length; t++) {
if(partOfLineWithoutClosingTag.indexOf(textToCheckFor[t]) == -1) {
applyThisRuleToThisLine = false
}
}
if(applyThisRuleToThisLine) {
let lineAfterApplyingStyle = partOfLineWithoutClosingTag.substring(0, idxOfFirstSpace) +" style=\""
for(let u = 0; u < mapOfCSSrules.get(ruleNames[s]).length; u++) {
let thisPropertyToApply = mapOfCSSrules.get(ruleNames[s])[u]
lineAfterApplyingStyle=lineAfterApplyingStyle+thisPropertyToApply
}
lineAfterApplyingStyle = lineAfterApplyingStyle +"\""
partOfLineWithoutClosingTag = lineAfterApplyingStyle + partOfLineWithoutClosingTag
let lastIndexOfLessThan = partOfLineWithoutClosingTag.lastIndexOf("<")
let lastIndexOfGreaterThan = partOfLineWithoutClosingTag.lastIndexOf(">")
partOfLineWithoutClosingTag = partOfLineWithoutClosingTag.substring(0,lastIndexOfLessThan) + partOfLineWithoutClosingTag.substring(lastIndexOfGreaterThan)
}
}
thisActualLineWithStylesApplied = thisActualLineWithStylesApplied + partOfLineWithoutClosingTag
}
if(partOfLineWithClosingTag !== undefined) {
thisActualLineWithStylesApplied = thisActualLineWithStylesApplied + partOfLineWithClosingTag
}
}
linesWithInlineRulesApplied.push(thisActualLineWithStylesApplied)
}
return linesWithInlineRulesApplied
}
Edit: Thanks to Kumar I realized my suggested method is nonstandard, and
getComputedStyle( element );
should be used instead, which is a bit more difficult to use and filter but has the advantage of giving you only the final rules that actually apply to the element after the CSS was evaluated (which also includes default, not explicitly declared styles, making it a bit trickier to use in this case).
getMatchedCSSRules( element );
just use this vanilla javascript function. It does exactly what you want. I'd explain it if there were anything to explain that isn't implied by the name of the function.
I have an object output from below code how to set the index start from 0 in js?
Object
3: Object
id: 34
type: 0
var obj = {};
var edited = false;
for (var i = 0; i < $(".list").length; i++) {
var data_id = parseInt($(".list").eq(i).attr('data-id'));
var data_type = parseInt($(".list").eq(i).attr('data-type'));
if ((data_type != 0)) {
edited = true;
} else {
edited = false;
}
if (edited == true) {
obj[i] = {};
obj[i]['id'] = data_id;
obj[i]['type'] = data_type;
}
}
console.log(obj);
Needs more jQuery ?
var arr = $(".list").filter(function() {
return $(this).data('type') != 0;
}).map(function() {
return { id : $(this).data('id'), type : $(this).data('type') };
}).get();
FIDDLE
Actually if you want to start in 0, use another variable and not "i" (which I think is 3 when you use it as index).
var obj = {};
var edited = false;
var obj_idx = 0;
for (var i = 0; i < $(".list").length; i++) {
var data_id = parseInt($(".list").eq(i).attr('data-id'));
var data_type = parseInt($(".list").eq(i).attr('data-type'));
if ((data_type != 0)) {
edited = true;
} else {
edited = false;
}
if (edited == true) {
obj[obj_idx] = {};
obj[obj_idx]['id'] = data_id;
obj[obj_idx]['type'] = data_type;
obj_idx += 1;
}
}
console.log(obj);
I think this time obj will be something like:
Object
0: Object
id: 34
type: 0
you could fake object as array by Array.prototype.push.call, in that way you could also gain the side effect: obj.length. it's kinda ninja and elegant :]
var obj = {};
var edited = false;
for (var i = 0; i < $(".list").length; i++) {
var data_id = parseInt($(".list").eq(i).attr('data-id'));
var data_type = parseInt($(".list").eq(i).attr('data-type'));
if ((data_type != 0)) {
edited = true;
} else {
edited = false;
}
if (edited == true) {
Array.prototype.push.call(obj, {id: data_id, type: data_type});
}
}
I am going to give a very simple and readable example. Say you've got an object with the following structure:
Object
0: Object
key: 'some-key'
value: 'some-value'
1: Object
...
Then you might want to delete an entry from it and reindex the whole thing, this is how I do it:
// obj is Object from above
const reIndexed = Object.entries(obj).map((element, index) => {
if (parseInt(element[0] != index) {
element[0] = index.toString();
}
return element;
});
var sortitems = 1;
function move(fbox, tbox, all)
{
for ( var i = 0; i < fbox.options.length; i++)
{
if (!all && fbox.options[i].selected && fbox.options[i].value != "")
{
var no = new Option();
no.value = fbox.options[i].value;
no.text = fbox.options[i].text;
tbox.options[tbox.options.length] = no;
fbox.options[i].value = "";
fbox.options[i].text = "";
}
else
{
if (all && fbox.options[i].value != "")
{
var no = new Option();
no.value = fbox.options[i].value;
no.text = fbox.options[i].text;
tbox.options[tbox.options.length] = no;
fbox.options[i].value = "";
fbox.options[i].text = "";
}
}
}
BumpUp(fbox);
if (sortitems)
SortD(tbox);
checkSelectAll();
}
This move function is getting called after clicking on the button, then it will call the sort method where sorting is happening by alphabetically. So we dont need to sort we need to populate the data as it is from the left side box to right side box and vice versa, but sorting is happening. Please help out be here.
function SortD(box)
{
var temp_opts = new Array();
var temp = new Object();
for ( var i = 0; i < box.options.length; i++)
{
temp_opts[i] = box.options[i];
}
for ( var x = 0; x < temp_opts.length - 1; x++)
{
for ( var y = (x + 1); y < temp_opts.length; y++)
{
if (temp_opts[x].value > temp_opts[y].value)
{
temp = temp_opts[x].text;
temp_opts[x].text = temp_opts[y].text;
temp_opts[y].text = temp;
temp = temp_opts[x].value;
temp_opts[x].value = temp_opts[y].value;
temp_opts[y].value = temp;
}
}
}
for ( var i = 0; i < box.options.length; i++)
{
box.options[i].value = temp_opts[i].value;
box.options[i].text = temp_opts[i].text;
}
}
Depends on the bumpup box function. The elements are moving from one box to another. It will replace the element with empty space and move to top and do for all the elements. Please help out me here
Thanks in advance
function BumpUp(box)
{
for ( var i = 0; i < box.options.length; i++)
{
if (box.options[i].value == "")
{
for ( var j = i; j < box.options.length - 1; j++)
{
box.options[j].value = box.options[j + 1].value;
box.options[j].text = box.options[j + 1].text;
}
var ln = i;
break;
}
}
if (ln < box.options.length)
{
box.options.length -= 1;
BumpUp(box);
}
}
Maybe it's just me, but it's hard to see what the issue is here.
If it is simply that SortD(tbox) is being called within the move() function, that's because
sortitems is set to 1 right at the top of the code. The value of sortitems is never changed anywhere else, so this conditional is always true and SortD is always called.
if (sortitems)
SortD(tbox);
I meet a trouble with a function. actually I need to make this function to perform a calculation on some text fields. When I worked on a single line no problems. But recently, someone asked to make a table with multiple lines (one line can be added dynamically) so, I do the following function so that it can not only duplicate line but id change all the fields concerned, so I add class to these fields. therefore I proceed as follows:
function clone(line) {
newLine = line.cloneNode(true);
line.parentNode.appendChild(newLine);
var tab = document.getElementsByClassName('libelle_debours')
var i = -1;
while (tab[++i]) {
tab[i].setAttribute("id", "_" + i);
};
var cab = document.getElementsByClassName('ht_no_tva')
var j = -1;
while (cab[++j]) {
cab[j].setAttribute("id", "_" + j);
};
var dab = document.getElementsByClassName('ht_tva')
var k = -1;
while (dab[++k]) {
dab[k].setAttribute("id", "_" + k);
};
var eab = document.getElementsByClassName('taux')
var l = -1;
while (eab[++l]) {
eab[l].setAttribute("id", "_" + l);
};
var fab = document.getElementsByClassName('tva')
var m = -1;
while (fab[++m]) {
fab[m].setAttribute("id", "_" + m);
};
}
function delRow() {
var current = window.event.srcElement;
//here we will delete the line
while ((current = current.parentElement) && current.tagName != "TR");
current.parentElement.removeChild(current);
}
The problem in fact is the second function that is used to make the calculation:
function calcdebours() {
var taux = document.getElementById('debours_taux_tva').value;
var ht_no_tva = document.getElementById('debours_montant_ht_no_tva').value;
var ht_tva = document.getElementById('debours_montant_ht_tva').value;
var tva = Math.round((((ht_tva) * (taux)) / 100) * 100) / 100;;
if (taux == '') {
taux = 0;
}
if (ht_no_tva == '') {
ht_no_tva = 0;
}
if (ht_tva == '') {
ht_tva = 0;
}
document.getElementById('debours_montant_tva').value = tva;
document.getElementById('debours_montant_ttc').value = (tva) + parseFloat(ht_tva) + parseFloat(ht_no_tva)
}
function
montant_debours() {
var ttc = document.getElementById('debours_montant_ttc').value;
var ttc2 = document.getElementById('debours_montant_ttc2').value;
if (ttc == '') {
var ttc = 0;
} else {
var ttc = document.getElementById('debours_montant_ttc').value;
}
if (ttc2 == '') {
var ttc2 = 0;
} else {
var ttc2 = document.getElementById('debours_montant_ttc2').value;
}
tx = parseFloat(ttc) + parseFloat(ttc2);
document.getElementById('ttc_cheque').value = Math.round(tx * 100) / 100;
}
As Id are not the same, do I have to create as many functions
there are lines?
Is it possible to fit a single function to process each line?
If so can you tell me how?
If I'm not mistaken you can use for loop and append increment to the end of element's id. Like this:
trs = document.getElementById('container Id').getElementsByTagName('tr');
For (var i = 1, i <= trs.length; i++)
{
var el = document.getElementById('debours_montant_ttc' + i);
}
Let's say i have this:
<form id='foo'>
<input name='bar[name]' />
<input name='bar[age]' />
</form>
How can i get the values of array inputs within the form foo and put them into an associative array/object like this:
var result = {bar:{name:'blah',age:21}};
P.S. I don't want to use any frameworks for this.
I needed to do this myself and after finding this question I didn't like any of the answers: I don't like regex and the others are limited.
You can get the data variable many ways. I'll be using jQuery's serializeArray method when I implement this.
function parseInputs(data) {
var ret = {};
retloop:
for (var input in data) {
var val = data[input];
var parts = input.split('[');
var last = ret;
for (var i in parts) {
var part = parts[i];
if (part.substr(-1) == ']') {
part = part.substr(0, part.length - 1);
}
if (i == parts.length - 1) {
last[part] = val;
continue retloop;
} else if (!last.hasOwnProperty(part)) {
last[part] = {};
}
last = last[part];
}
}
return ret;
}
var data = {
"nom": "123",
"items[install][item_id_4]": "4",
"items[install][item_id_5]": "16",
"items[options][takeover]": "yes"
};
var out = parseInputs(data);
console.log('\n***Moment of truth:\n');
console.log(out);
You can map the elements to an object like this.
function putIntoAssociativeArray() {
var
form = document.getElementById("foo"),
inputs = form.getElementsByTagName("input"),
input,
result = {};
for (var idx = 0; idx < inputs.length; ++idx) {
input = inputs[idx];
if (input.type == "text") {
result[input.name] = input.value;
}
}
return result;
}
var form = document.getElementById( 'foo' );
var inputs = form.getElementsByTagName( "input" );
var regex = /(.+?)\[(.+?)\]/;
var result = {};
for( var i = 0; i < inputs.length; ++i ) {
var res = regex.exec( inputs[i].name );
if( res !== null ) {
if( typeof result[ res[1] ] == 'undefined' ) result[ res[1] ] = {};
result[ res[1] ][ res[2] ] = inputs[i].value;
}
}
var inputs = document.getElementsByTagName('input');
var field_name, value, matches, result = {};
for (var i = 0; i < inputs.length; i++) {
field_name = inputs[i].name;
value = inputs[i].value;
matches = field_name.match(/(.*?)\[(.*)\]/);
if (!results[matches[0]]) {
results[matches[0]] = {};
}
results[matches[0]][matches[1]] = value;
}
This will get you the elements:
var result = {};
var elements = document.forms.foo.getElementsByTagName("input");
for(var i = 0; i < elements.length; i++)
{
/* do whatever you need to do with each input */
}