2

I have the following originaldata which I would like to remove the div tags from the each objects inside it, leaving it with the content within the tags as the final result, see modifieddata.

What would be the best approach using javascript? filter and map? or something else.

originaldata = [{
        "name": "john",
        "content": "<div class="ExternalClass06EE5E42165840F48DFA193ACAD4F87A">aa</div>"
    },
    {
        "name": "mary",
        "content": "<div class="ExternalClass3D5F8061F3DE49C4BC55A9CE0ADD6F9A">asd</div>"
    }
]

modifieddata = [{
        "name": "john",
        "content": "aa"
    },
    {
      "name": "mary",
      "content": "asd"
    }
]
FizzyGood
  • 33
  • 8
  • you have an error in the format. The string should be `'
    aa
    '` or "
    aa
    "
    – dhilt Dec 05 '17 at 14:47
  • 1
    @gurvinder372: It's not JSON anyway. But yes, it's still invalid. – T.J. Crowder Dec 05 '17 at 14:47
  • @T.J.Crowder are you saying the accepted answer is incorrect? or not the correct way to solve the issue? – FizzyGood Dec 05 '17 at 15:14
  • @DamienFlood: It's using a regex to parse HTML, which is not a good idea. The rest of it is fine if you want to take a functional approach (creating new objects). – T.J. Crowder Dec 05 '17 at 15:19
  • @T.J.Crowder If there is additional HTML tags within the DIV would this also be removed. Ideally I would like to keep all the content within the DIV even if its other tags. Is this also possible? – FizzyGood Dec 06 '17 at 08:44
  • @DamienFlood: I've updated the accepted answer to show how to do that (minor change). – T.J. Crowder Dec 07 '17 at 07:38
  • @T.J.Crowder Thanks so much! This is great. Learned a lot using this approach. – FizzyGood Dec 07 '17 at 11:44

6 Answers6

1

What would be the best approach using javascript? filter and map? or something else.

If you want to take a functional approach, just map (copying the objects), you're not filtering.

If not, just forEach modifying the existing objects:

Here's the map version:

var originaldata = [{
  "name": "john",
  "content": "<div class='ExternalClass06EE5E42165840F48DFA193ACAD4F87A'>aa</div>"
},
{
  "name": "mary",
  "content": "<div class='ExternalClass3D5F8061F3DE49C4BC55A9CE0ADD6F9A'>asd</div>"
}];
var temp = document.createElement("div");
var modifieddata = originaldata.map(entry => {
  temp.innerHTML = entry.content;
  return {
    name: entry.name,
    content: temp.firstChild.firstChild.nodeValue
  };
});
console.log(modifieddata);

...or using a Stage 3 proposal for object property spread that browser vendors are actively adding (Chrome has it, for instance), we can avoid having to know the names of the other properties:

// Note: I have the "Use BabelJS / ES2015" checkbox ticked
// so this will work even in browsers that don't
// have property spread yet.
const originaldata = [{
  "name": "john",
  "content": "<div class='ExternalClass06EE5E42165840F48DFA193ACAD4F87A'>aa</div>"
},
{
  "name": "mary",
  "content": "<div class='ExternalClass3D5F8061F3DE49C4BC55A9CE0ADD6F9A'>asd</div>"
}];
const temp = document.createElement("div");
const modifieddata = originaldata.map(entry => {
  temp.innerHTML = entry.content;
  return {
    ...entry, // <=== Property spread
    content: temp.firstChild.firstChild.nodeValue
  };
});
console.log(modifieddata);

Here's the forEach version:

var originaldata = [{
  "name": "john",
  "content": "<div class='ExternalClass06EE5E42165840F48DFA193ACAD4F87A'>aa</div>"
},
{
  "name": "mary",
  "content": "<div class='ExternalClass3D5F8061F3DE49C4BC55A9CE0ADD6F9A'>asd</div>"
}];
var temp = document.createElement("div");
originaldata.forEach(entry => {
  temp.innerHTML = entry.content;
  entry.content = temp.firstChild.firstChild.nodeValue;
});
console.log(originaldata);

In a comment you've said:

If there is additional HTML tags within the DIV would this also be removed. Ideally I would like to keep all the content within the DIV even if its other tags. Is this also possible?

In that case, in all of the above, change

entry.content = temp.firstChild.firstChild.nodeValue;

to

entry.content = temp.firstChild.innerHTML;

Here's the forEach with that change:

var originaldata = [{
  "name": "john",
  "content": "<div class='ExternalClass06EE5E42165840F48DFA193ACAD4F87A'>aa<span>stuff in a span</span><br></div>"
},
{
  "name": "mary",
  "content": "<div class='ExternalClass3D5F8061F3DE49C4BC55A9CE0ADD6F9A'>asd</div>"
}];
var temp = document.createElement("div");
originaldata.forEach(entry => {
  temp.innerHTML = entry.content;
  entry.content = temp.firstChild.innerHTML;
});
console.log(originaldata);
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

First of all you must resolve the problem of quotes, you couldn't use the double quotes multiple time in the same string :

"<div class="ExternalClass06EE5E42165840F48DFA193ACAD4F87A">aa</div>"
^___________^_____________________________________________^_________^

Instead use single quotes :

 "<div class='ExternalClass06EE5E42165840F48DFA193ACAD4F87A '>aa</div>"

Then loop through the array and chnage the property you want :

for (var i in originaldata) {
   var temp_div = document.createElement('div'); //Create temporary div
   temp_div.innerHTML = originaldata[i].content; //Append the tag in the content to it

   originaldata[i].content = temp_div.textContent; //Get the text using 'textContent'
}

var originaldata = [{
    "name": "john",
    "content": "<div class='ExternalClass06EE5E42165840F48DFA193ACAD4F87A '>aa</div>"
  },
  {
    "name": "mary",
    "content": "<div class='ExternalClass3D5F8061F3DE49C4BC55A9CE0ADD6F9A '>asd</div>"
  }
];

for (var i in originaldata) {
  var temp_div = document.createElement('div');
  temp_div.innerHTML = originaldata[i].content;

  originaldata[i].content = temp_div.textContent;
}

console.log(originaldata);
halfer
  • 19,824
  • 17
  • 99
  • 186
Zakaria Acharki
  • 66,747
  • 15
  • 75
  • 101
  • 1
    Pretty sure they don't want `"0"` and `"1"` in `content` (they've said they want `"aa"` and `"asd"`). – T.J. Crowder Dec 05 '17 at 14:49
  • _"has no meaning & used just for example too"_ That would be a pretty specific "meaningless example" – Andreas Dec 05 '17 at 14:58
  • He want's to remove the `
    ` tags and extract the text of them (stored in `content`). That step is missing in your answer.
    – Andreas Dec 05 '17 at 15:02
1

Use map and createElement

var output = originaldata.map( function(item){
  var div = document.createElement("div");
  div.innerHTML = item.content;
  return { name : item.name, content : div.textContent }; 
});

var originaldata = [{
"name": "john",
"content": "<div class= 'ExternalClass06EE5E42165840F48DFA193ACAD4F87A'>aa</div>"
},
{
"name": "mary",
"content": "<div class='ExternalClass3D5F8061F3DE49C4BC55A9CE0ADD6F9A'>asd</div>"
}];

var output = originaldata.map( function(item){
  var div = document.createElement("div");
  div.innerHTML = item.content;
  return { name : item.name, content : div.textContent }; 
});

console.log( output );
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
1

I would use Array.prototype.map and regexp:

const originaldata = [{
  "name": "john",
  "content": '<div class="ExternalClass06EE5E42165840F48DFA193ACAD4F87A">aa</div>'
},
{
  "name": "mary",
  "content": '<div class="ExternalClass3D5F8061F3DE49C4BC55A9CE0ADD6F9A">asd</div>'
}];

const regex = /(<([^>]+)>)/ig;

const modifieddata = originaldata.map(item => ({ 
  name: item.name,
  content: item.content.replace(regex, "")
}));

console.log(modifieddata); // [{name: "john", content: "aa"}, {name: "mary", content: "asd"}]

UPD. If the structure of your contents could be more sophisticated than just one tag wrapper, then you should think about using another approach (for example this one and that one).

dhilt
  • 18,707
  • 8
  • 70
  • 85
  • 4
    [Have we learned nothing?](https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags#1732454) ;-) – T.J. Crowder Dec 05 '17 at 15:05
  • I don't see any HTML in the requirements)) PS love that post! – dhilt Dec 05 '17 at 15:10
  • You're using a regex to parse HTML in your answer. Strongly suggest **not** doing that. – T.J. Crowder Dec 05 '17 at 15:12
  • @T.J.Crowder what approact you will follow then ? – AL-zami Dec 05 '17 at 15:20
  • In case of single tag-wrapper, I guess, this is appropriate solution. But I agree, in general the procedure should be another. I updated the answer. – dhilt Dec 05 '17 at 15:23
  • @AL-zami: The one [in my answer](https://stackoverflow.com/a/47656357/157247) (also used -- independently -- by gurvinder372 in [his answer](https://stackoverflow.com/a/47656444/157247)). Let the browser do it, they know how. – T.J. Crowder Dec 05 '17 at 15:23
1

You can create a new element and then insert the content of the originaldata array to the newly created element.

Later on you retrieve the html of the element using innerHTML and overwrite the original originaldata.content with the innerHTML

Working demo

var originaldata = [{
    "name": "john",
    "content": "<div class='ExternalClass06EE5E42165840F48DFA193ACAD4F87A '>aa</div>"
  },
  {
    "name": "mary",
    "content": "<div class='ExternalClass3D5F8061F3DE49C4BC55A9CE0ADD6F9A '>asd</div>"
  }
];

for (var i in originaldata) {
  var html = originaldata[i].content;
  var temp = document.createElement('div');
  
  temp.innerHTML = html;
   
  var htmlContent = temp.firstChild.innerHTML;
  
  originaldata[i].content = htmlContent;
}

console.log(originaldata)
Red
  • 6,599
  • 9
  • 43
  • 85
1

here is a one liner( assuming you will only have letters inside the div tag)

originaldata.forEach( x => { x.content = x.content.match(/>(\w+?)</)[1] })

arrays are reference type, so as object. So you can simply use forEach function to iterate over the array and use regex pattern />(\w+?)</ to match the content inside div tag.That will give you what you want.But be careful.It will change the original data source,in our case originaldata array.

AL-zami
  • 8,902
  • 15
  • 71
  • 130
  • It's incorrect to use `map` when you're A) Not returning anything from the callback, and B) Not using the return value. And of couse, [there's this problem](https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags#1732454). – T.J. Crowder Dec 05 '17 at 15:26
  • Your were right.I shouldn't have used map.Changed it to to forEach.for A) it's not a pure function.I am not following a functional approact here.Then why it should matter whether i am returning something from the function or not ? – AL-zami Dec 05 '17 at 20:19
  • It mattered when using `map`. Doesn't matter now you're not using `map`. The HTML problem remains, and this answer really just duplicates previous answers in any case. – T.J. Crowder Dec 06 '17 at 06:18