There is a strange behavior with DOMParser. When I use "text/xml" as the parameter I get my object and each time I use a child (like parentNodes), the child is itself a DOM object. However, when I use "text/html" as the parameter, the children are not DOM objects. Why is that and how can I have DOM objects for all the children?
Here is what I do:
parser = new DOMParser();
doc = parser.parseFromString(stringContainingHTMLSource, "text/html").getElementsByTagName('p');
console.log(doc[0].childNodes[0]);
My childNode returns the element but not as a DOM object...
Edit:
Here are my recursive functions:
var getParents = function(node, parentNodes){
if(node.nodeName == 'span'){
parentNodes.push(node.attributes[0].nodeValue);
} else if(node.nodeName == 'p' && node.attributes.length > 0) {
parentNodes.push(node.nodeName);
parentNodes.push(node.attributes[0].nodeValue);
} else {
parentNodes.push(node.nodeName);
}
if(node.parentNode.nodeName != '#document'){
getParents(node.parentNode, parentNodes);
}
return parentNodes;
};
var parse = function(node, vertical, horizontal, paragraph){
if(node.childNodes.length > 0){
for(var int = 0; int < node.childNodes.length; int++){
parse(node.childNodes[int], vertical, horizontal, paragraph);
}
} else{
var object = {};
var attributes = getParents(node, []);
for(var int = 0; int < attributes.length; int++) {
// right alignment
if(/text-align/i.test(attributes[int])){
object.alignment = attributes[int].split(": ")[1].replace(';','');
} else if (/color/i.test(attributes[int])) {
// color
object.color = attributes[int].split(":")[1];
} else if (attributes[int] == 'em') {
// italic
if (object.italics) {
delete object.bold;
object.bolditalics = true;
} else {
object.italics = true;
}
} else if (attributes[int] == 'strong') {
// bold
if (object.italics) {
delete object.italics;
object.bolditalics = true;
} else {
object.bold = true;
}
} else if (attributes[int] == 'u') {
// underline
object.decoration = 'underline';
} else if (attributes[int] == 's') {
// strike
object.decoration = 'lineThrough';
}
}
object.text = node.textContent;
pdfContent[vertical][horizontal].push(object);
}
};
for(var vertical = 0; vertical < payment.htmlContent.length; vertical++) {
for(var horizontal = 0; horizontal < payment.htmlContent[vertical].length; horizontal++) {
var parser = new DOMParser();
var paragraphs = parser.parseFromString(payment.htmlContent[vertical][horizontal], "text/xml").getElementsByTagName('p');
for (var paragraph = 0; paragraph < paragraphs.length; paragraph++) {
for (var num = 0; num < paragraphs[paragraph].childNodes.length; num++) {
parse(paragraphs[paragraph].childNodes[num], vertical, horizontal, paragraph);
}
}
}
}
I made a few assumptions on what the values are and after I Added a few verifications like if(node.attributes.length>0)into your code, it seems to work.
var payment={htmlContent:[['<p>some<em>text</em></p>', '<p>some<span>text<strong>here</strong></span></p>'],['<p>some<s>text</s></p>', '<p>some<span style="color:#FF00FF">text</span></p>']]};
var getParents = function(node, parentNodes){
if(node.nodeName == 'span'){
if(node.attributes.length>0)
parentNodes.push(node.attributes[0].nodeValue);
} else if(node.nodeName == 'p' && node.attributes.length > 0) {
parentNodes.push(node.nodeName);
if(node.attributes.length>0)
parentNodes.push(node.attributes[0].nodeValue);
} else {
parentNodes.push(node.nodeName);
}
if(node.parentNode.nodeName != '#document'){
getParents(node.parentNode, parentNodes);
}
return parentNodes;
};
var parse = function(node, vertical, horizontal, paragraph){
if(node.childNodes.length > 0){
for(var int = 0; int < node.childNodes.length; int++){
parse(node.childNodes[int], vertical, horizontal, paragraph);
}
} else{
var object = {};
var attributes = getParents(node, []);
console.log(attributes);
for(var int = 0; int < attributes.length; int++) {
// right alignment
if(/text-align/i.test(attributes[int])){
object.alignment = attributes[int].split(": ")[1].replace(';','');
} else if (/color/i.test(attributes[int])) {
// color
object.color = attributes[int].split(":")[1];
} else if (attributes[int] == 'em') {
// italic
if (object.italics) {
delete object.bold;
object.bolditalics = true;
} else {
object.italics = true;
}
} else if (attributes[int] == 'strong') {
// bold
if (object.italics) {
delete object.italics;
object.bolditalics = true;
} else {
object.bold = true;
}
} else if (attributes[int] == 'u') {
// underline
object.decoration = 'underline';
} else if (attributes[int] == 's') {
// strike
object.decoration = 'lineThrough';
}
}
object.text = node.textContent;
if(!pdfContent[vertical])pdfContent[vertical]=[];
if(!pdfContent[vertical][horizontal])
pdfContent[vertical][horizontal]=[];
pdfContent[vertical][horizontal].push(object);
}
};
var pdfContent = [];
for(var vertical = 0; vertical < payment.htmlContent.length; vertical++) {
for(var horizontal = 0; horizontal < payment.htmlContent[vertical].length; horizontal++) {
var parser = new DOMParser();
var paragraphs = parser.parseFromString(payment.htmlContent[vertical][horizontal], "text/xml").getElementsByTagName('p');
for (var paragraph = 0; paragraph < paragraphs.length; paragraph++) {
for (var num = 0; num < paragraphs[paragraph].childNodes.length; num++) {
parse(paragraphs[paragraph].childNodes[num], vertical, horizontal, paragraph);
}
}
}
}
for(var i=0; i<pdfContent.length; i++){
for(var j=0; j<pdfContent[i].length; j++){
document.querySelector('#log').textContent+=pdfContent[i][j].toSource();
}
}
<p id="log"></p>
Related
I'm using a number of boxes that are floating around the screen, I want for them to bounce away from each other when they collide and I am testing this by just changing their colours instead when they collide, for some reason their colour changes at the start(their starting colour is white and if they collide it should change to red but they start and stays red). Is there something I am doing wrong? I would also like for everything to be done within the constructor function. I am sorry for not commenting my code as yet.
function BoxSplash()
{
this.sample = [];
var test = false;
this.col = color(129)
this.changeColour = function()
{
this.col = color(random(0,255),random(0,128),random(0,255))
}
this.intersect = function(other)
{
for(var i = 0; i < numberss; i++)
{ var currentBox = this.sample[i]
var d = dist(currentBox.x,currentBox.y,other.x,other.y)
if(d < currentBox.width + other.width)
{
return true;
}
else
{
return false
}
}
noLoop()
}
this.draw = function()
{
stroke(255)
line(0,windowHeight/2,windowWidth,windowHeight/2)
stroke(0)
for(var i = 0; i < numberss; i++)
{
var box = {
x:random(0,windowWidth - 50),
y:random(windowHeight/2 ,windowHeight - 50),
width:50,
height:50,
speedX:random(1,5),
speedY:random(1,5)
}
this.sample.push(box)
}
//use numberss variable to work with gui
for(var i = 0; i < numberss; i++)
{
fill(this.col)
rect(this.sample[i].x,this.sample[i].y,50,50)
}
this.move()
}
this.move = function()
{
for(var i = 0; i < numberss; i++)
{
var shape = this.sample[i]
shape.x += shape.speedX
shape.y += shape.speedY
if(shape.x + shape.width >= windowWidth || shape.x <= 0 )
{
shape.speedX = -shape.speedX
}
if(shape.y + shape.height >= windowHeight || shape.y <= windowHeight/2)
{
shape.speedY = -shape.speedY;
}
for(var j = 0; j < numberss; j++)
{
var others = this.sample[j]
var d = dist(shape.x,shape.y,others.x,others.y)
if( i != j && d < shape.width + others.width)
{
test = true;
}
else
{
test = false
}
if(test)
{
this.col = color(255,0,0)
}
}
}
}
}
You should visit this link and transform their circles into your boxes.
1st: Calculate dist(object1.x, object.y, object2.x, object2.y) and save into a variable called d
2nd:
if (d < object1.h + object2.h) {
// Enter your code here
}
I'm making a gem-puzzle. I have a save button that after clicking on page reload shows the last saved state of the game. But when I reload the page, the table is rendered but the move click event doesn't work. How can this be fixed? What new arguments need to be passed to the function moveThisTile? Or should I save something else in localstorage? To explain my code: the startNewGame function is called to create the fifteen puzzle. showTable cycles through the two-dimensional array arrayForBoard and generates the necessary HTML for the fifteen puzzle board. moveThisTile takes two arguments that tell the program which tile of the fifteen puzzle needs to be moved
let moves = 0;
let table;
let rows;
let columns;
let textMoves;
let arrayForBoard;
let volumeOn = true;
function start() {
let button = document.getElementById('newGame');
button.addEventListener('click', startNewGame, false );
textMoves = document.getElementById('moves');
table = document.getElementById('table');
rows = 4;
columns = 4;
startNewGame();
}
function startNewGame() {
let arrayOfNumbers = new Array();
let arrayHasNumberBeenUsed;
let randomNumber = 0;
let count = 0;
moves = 0;
rows = document.getElementById('rows').value;
columns = document.getElementById('columns').value;
textMoves.innerHTML = moves;
arrayForBoard = new Array(rows);
for (let i = 0; i < rows; i++){
arrayForBoard[i] = new Array(columns);
}
arrayHasNumberBeenUsed = new Array( rows * columns );
for (let i = 0; i < rows * columns; i++){
arrayHasNumberBeenUsed[i] = 0;
}
for (let i = 0; i < rows * columns; i++){
randomNumber = Math.floor(Math.random()*rows * columns);
if (arrayHasNumberBeenUsed[randomNumber] == 0) {
arrayHasNumberBeenUsed[randomNumber] = 1;
arrayOfNumbers.push(randomNumber);
}else {
i--;
}
}
count = 0;
for (let i = 0; i < rows; i++){
for (let j = 0; j < columns; j++){
arrayForBoard[i][j] = arrayOfNumbers[count];
count++;
}
}
showTable();
}
let tbody = document.createElement('tbody');
document.querySelector('#table').appendChild(tbody);
function showTable() {
for (let tr of document.querySelectorAll("#table tr")) {
tr.remove();
}
for (let i = 0; i < rows; i++) {
let tr = document.createElement('tr');
for (let j = 0; j < columns; j++) {
let cell = document.createElement('td');
if (arrayForBoard[i][j] == 0) {
cell.className = 'blank';
} else {
cell.className = 'tile';
cell.draggable = true;
cell.addEventListener('click', () => {
moveThisTile(i, j);
if(volumeOn) {
sound()
}
})
cell.innerHTML =arrayForBoard[i][j];
}
tr.appendChild(cell);
}
tbody.appendChild(tr);
}
};
function moveThisTile(tableRow, tableColumn) {
if (checkIfMoveable(tableRow, tableColumn, 'up') ||
checkIfMoveable(tableRow, tableColumn, 'down') ||
checkIfMoveable(tableRow, tableColumn, 'left') ||
checkIfMoveable(tableRow, tableColumn, 'right') ) {
incrementMoves();
} else {
alert('ERROR: Cannot move tile!\nTile must be next to a blank space.');
}
if (checkIfWinner()) {
stopTimer();
alert(`Congratulations! You solved the puzzle in ${moves} moves and in ${document.querySelector('#timespan').innerText}.`);
startNewGame();
}
}
function checkIfMoveable(rowCoordinate, columnCoordinate, direction) {
let rowOffset = 0;
let columnOffset = 0;
if (direction == 'up') {
rowOffset = -1;
} else if (direction == 'down') {
rowOffset = 1;
} else if (direction == 'left') {
columnOffset = -1;
} else if (direction == 'right') {
columnOffset = 1;
}
if (rowCoordinate + rowOffset >= 0 && columnCoordinate + columnOffset >= 0 &&
rowCoordinate + rowOffset < rows && columnCoordinate + columnOffset < columns
) {
if ( arrayForBoard[rowCoordinate + rowOffset][columnCoordinate + columnOffset] == 0) {
arrayForBoard[rowCoordinate + rowOffset][columnCoordinate + columnOffset] = arrayForBoard[rowCoordinate][columnCoordinate];
arrayForBoard[rowCoordinate][columnCoordinate] = 0;
showTable();
return true;
}
}
return false;
}
document.querySelector('.save-btn').addEventListener('click', () => {
localStorage.setItem('currentGame', document.querySelector('tbody').innerHTML);
localStorage.setItem('currentMoves', document.querySelector('#moves').innerHTML);
localStorage.setItem('currentTime', document.querySelector('#timespan').innerHTML);
})
window.addEventListener('load', () => {
if(localStorage.getItem('currentGame') !== null) {
tbody.innerHTML = localStorage.getItem('currentGame');
document.querySelector('#moves').innerHTML = localStorage.getItem('currentMoves');
document.querySelector('#timespan').innerHTML = localStorage.getItem('currentTime');
} else {
start();
}
}, false );
While we adding HTML into the HTML output render has in the DIV. If we added something like following
<div class="test" w3-include-html="template_build/header/header-classic.html"></div>
But the output render has incldued that
<div class="test">MY INCLUDED CONTENT</div>
I want to remove that div class="test" on rendering process on w3data.js.
Can someone help me?
Snippet 1 features a simple function that removes any given attribute from any given element. Snippet 2 is the w3data.js with an extra line at 126:
elmnt.removeAttribute("class");
You may use either one to get the same result
SNIPPET 1
removeAttr(".test", "class");
function removeAttr(target, attribute) {
var target = document.querySelector(target);
target.removeAttribute(attribute);
}
.test { color:red }
<div class="test">THIS CONTENT SHOULD BE BLACK TEXT, NOT RED</div>
SNIPPET 2
/* W3Data ver 1.31 by W3Schools.com */
var w3DataObject = {};
function w3DisplayData(id, data) {
var htmlObj, htmlTemplate, html, arr = [],
a, l, rowClone, x, j, i, ii, cc, repeat, repeatObj, repeatX = "";
htmlObj = document.getElementById(id);
htmlTemplate = w3InitTemplate(id, htmlObj);
html = htmlTemplate.cloneNode(true);
arr = w3GetElementsByAttribute(html, "w3-repeat");
l = arr.length;
for (j = (l - 1); j >= 0; j -= 1) {
cc = arr[j].getAttribute("w3-repeat").split(" ");
if (cc.length == 1) {
repeat = cc[0];
} else {
repeatX = cc[0];
repeat = cc[2];
}
arr[j].removeAttribute("w3-repeat");
repeatObj = data[repeat];
if (repeatObj && typeof repeatObj == "object" && repeatObj.length != "undefined") {
i = 0;
for (x in repeatObj) {
i += 1;
rowClone = arr[j];
rowClone = w3NeedleInHaystack(rowClone, "element", repeatX, repeatObj[x]);
a = rowClone.attributes;
for (ii = 0; ii < a.length; ii += 1) {
a[ii].value = w3NeedleInHaystack(a[ii], "attribute", repeatX, repeatObj[x]).value;
}
(i === repeatObj.length) ? arr[j].parentNode.replaceChild(rowClone, arr[j]): arr[j].parentNode.insertBefore(rowClone, arr[j]);
}
} else {
console.log("w3-repeat must be an array. " + repeat + " is not an array.");
continue;
}
}
html = w3NeedleInHaystack(html, "element");
htmlObj.parentNode.replaceChild(html, htmlObj);
function w3InitTemplate(id, obj) {
var template;
template = obj.cloneNode(true);
if (w3DataObject.hasOwnProperty(id)) {
return w3DataObject[id];
}
w3DataObject[id] = template;
return template;
}
function w3GetElementsByAttribute(x, att) {
var arr = [],
arrCount = -1,
i, l, y = x.getElementsByTagName("*"),
z = att.toUpperCase();
l = y.length;
for (i = -1; i < l; i += 1) {
if (i == -1) {
y[i] = x;
}
if (y[i].getAttribute(z) !== null) {
arrCount += 1;
arr[arrCount] = y[i];
}
}
return arr;
}
function w3NeedleInHaystack(elmnt, typ, repeatX, x) {
var value, rowClone, pos1, haystack, pos2, needle = [],
needleToReplace, i, cc, r;
rowClone = elmnt.cloneNode(true);
pos1 = 0;
while (pos1 > -1) {
haystack = (typ == "attribute") ? rowClone.value : rowClone.innerHTML;
pos1 = haystack.indexOf("{{", pos1);
if (pos1 === -1) {
break;
}
pos2 = haystack.indexOf("}}", pos1 + 1);
needleToReplace = haystack.substring(pos1 + 2, pos2);
needle = needleToReplace.split("||");
value = undefined;
for (i = 0; i < needle.length; i += 1) {
needle[i] = needle[i].replace(/^\s+|\s+$/gm, ''); //trim
//value = ((x && x[needle[i]]) || (data && data[needle[i]]));
if (x) {
value = x[needle[i]];
}
if (value == undefined && data) {
value = data[needle[i]];
}
if (value == undefined) {
cc = needle[i].split(".");
if (cc[0] == repeatX) {
value = x[cc[1]];
}
}
if (value == undefined) {
if (needle[i] == repeatX) {
value = x;
}
}
if (value == undefined) {
if (needle[i].substr(0, 1) == '"') {
value = needle[i].replace(/"/g, "");
} else if (needle[i].substr(0, 1) == "'") {
value = needle[i].replace(/'/g, "");
}
}
if (value != undefined) {
break;
}
}
if (value != undefined) {
r = "{{" + needleToReplace + "}}";
if (typ == "attribute") {
rowClone.value = rowClone.value.replace(r, value);
} else {
w3ReplaceHTML(rowClone, r, value);
}
}
pos1 = pos1 + 1;
}
return rowClone;
}
function w3ReplaceHTML(a, r, result) {
var b, l, i, a, x, j;
if (a.hasAttributes()) {
b = a.attributes;
l = b.length;
for (i = 0; i < l; i += 1) {
if (b[i].value.indexOf(r) > -1) {
b[i].value = b[i].value.replace(r, result);
}
}
}
x = a.getElementsByTagName("*");
l = x.length;
a.innerHTML = a.innerHTML.replace(r, result);
}
}
function w3IncludeHTML() {
var z, i, elmnt, file, xhttp;
z = document.getElementsByTagName("*");
for (i = 0; i < z.length; i++) {
elmnt = z[i];
file = elmnt.getAttribute("w3-include-html");
if (file) {
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
elmnt.innerHTML = this.responseText;
elmnt.removeAttribute("w3-include-html");
elmnt.removeAttribute("class"); // Add this expression
w3IncludeHTML();
}
}
xhttp.open("GET", file, true);
xhttp.send();
return;
}
}
}
function w3Http(target, readyfunc, xml, method) {
var httpObj;
if (!method) {
method = "GET";
}
if (window.XMLHttpRequest) {
httpObj = new XMLHttpRequest();
} else if (window.ActiveXObject) {
httpObj = new ActiveXObject("Microsoft.XMLHTTP");
}
if (httpObj) {
if (readyfunc) {
httpObj.onreadystatechange = readyfunc;
}
httpObj.open(method, target, true);
httpObj.send(xml);
}
}
I get my password spec from an API which then I split the object into the needed fields and check that I have the required number of lower, upper, special and length of my password.
function isStrong(passwordChecker) {
if (!passwordChecker) {
return false;
}
debugger;
var securityOption = JSON.parse(localStorage.getItem("Security"));
var MinLength = securityOption.PasswordMinRequiredLength;
var SpecialChars = securityOption.PasswordMinRequiredNonalphanumericCharacters;
var MinLowercase = securityOption.PasswordMinRequiredLowercase;
var MinUppercase = securityOption.PasswordMinRequiredUppercase;
//LenghtCheck
if (passwordChecker.length < MinLength);
return false;
if (!CountSpecialChars(passwordChecker) > SpecialChars) {
return false;
}
if (MinLowercase > 0) {
if (!CountLowerCase(passwordChecker) > MinLowercase) {
return false;
}
}
if (MinUppercase > 0) {
if (!CountUpperCase(passwordChecker) > MinLowercase) {
return false;
}
}
}
function CountSpecialChars(text) {
var Count = 0;
for (var i = 0; i < text.length; i++) {
var c = text[i];
if (text[i] >= 33 && text[i] <= 63){
Count++;
}
}
}
function MinLowercase(text) {
var Count = 0;
for (var i = 0; i < text.length; i++) {
var c = text[i];
if (text[i] >= 97 && text[i] <= 122) {
Count++;
}
}
}
function MinUppercase(text) {
var Count = 0;
for (var i = 0; i < text.length; i++) {
var c = text[i];
if (text[i] >= 65 && text[i] <= 90) {
Count++;
}
}
}
Now what I want to do is, check the different conditions as a whole and if all of the conditions are true then change the class to green..
$(pageId + ' #password').bind('keyup', function () {
var currentpassword = $(pageId + ' #password').val();
if (isStrong(currentpassword)) {
$(pageId + ' #password').addClass('green');
} else {
$(pageId + ' #password').addClass('red');
}
});
I am not sure how to check the conditions as a whole and return an overall true because as I start trying in my password it instantly changes to green as in my password spec you do not need any UpperCase or LowerCase letters so on any input of a char it returns true..
You should refactor your functions so that they accept both the string and the parameter and return true or false. For example:
function CountSpecialChars(text) {
var Count = 0;
for (var i = 0; i < text.length; i++) {
var c = text[i];
if (text[i] >= 33 && text[i] <= 63){
Count++;
}
}
}
if (!CountSpecialChars(passwordChecker) > SpecialChars) {
return false;
}
Should instead be:
function CountSpecialChars(text, min) {
var count = 0;
for (var i = 0; i < text.length; i++) {
var c = text[i];
if (text[i] >= 33 && text[i] <= 63){
count++;
}
}
return count > min;
}
return CountSpecialChars(passwordChecker, SpecialChars);
Also, as a bonus, you could also avoid that for loop for those functions by using replace, like so:
function MinChars(text, min) {
return text.length > min;
}
function MinUppercase(text, min) {
var non_uppers = /[^A-Z]/g;
var uppers = text.replace(non_uppers, text);
return uppers.length > min;
}
function MinLowercase(text, min) {
var non_lowers = /[^a-z]/g;
var lowers = text.replace(non_lowers, text);
return lowers.length > min;
}
function MinSpecialChars(text, min) {
var non_specials = /[^!-\?]/g;
var specials = text.replace(non_specials, text);
return specials.length > min;
}
Now with those functions, you can have:
if !MinChars(pw, MinLength) return false;
if !MinSpecialChars(pw, SpecialChars) return false;
if !MinLowercase(pw, MinLowercase) return false;
if !MinUppercase(pw, MinUppercase) return false;
return true;
How can I save the remaining optionset items after removing an item from the list? Is there any other way of adding the removed option from an optionset in XRM?
function func1() {
var A1 = Xrm.Page.getAttribute("attribute1").getValue();
var B1 = Xrm.Page.getAttribute("attribute2").getValue();
var PickListA1 = Xrm.Page.getControl("attribute1");
var PickListA1Options = PickListA1.getAttribute().getOptions();
var j = 0;
if (B1 == "3") {
if (A1 == "1") {
PickListA1.clearOptions();
for (var i in PickListA1Options) {
if (PickListA1Options[i].value != "null") {
PickListA1.addOption(PickListA1Options[i]);
}
}
}
PickListA1.removeOption(1);
}
else {
PickListA1.getAttribute().setvalue(A1);
for (var i in PickListA1Options) {
if (PickListA1Options[i].value == "1") {
break;
}
else {
j++;
}
}
if (j > 1) {
PickListA1.addOption(PickListA1Options[1]);
}
}
}