Home > Mobile >  How can an html attribute(Javascript Object) be converted in a secure way to an array in Javascript/
How can an html attribute(Javascript Object) be converted in a secure way to an array in Javascript/

Time:12-28

I have the next HTML element that contain a javascript object:

<div ui-jq="easyPieChart"
     ui-options="{
                 percent: 75,
                 lineWidth: 5,
                 trackColor: '#e8eff0',
                 barColor: '#23b7e5',
                 scaleColor: false,
                 color: '#3a3f51',
                 size: 134,
                 lineCap: 'butt',
                 rotate: -90,
                 animate: 1000
                 }"
     >
</div>

How can I convert this string into array like bellow without changing HTML:

[{
  animate: 1000,
  barColor: "#23b7e5",
  color: "#3a3f51",
  lineCap: "butt",
  lineWidth: 5,
  percent: 75,
  rotate: -90,
  scaleColor: false,
  size: 134,
  trackColor: "#e8eff0"
}]

I already tried these versions:

$("[ui-jq]").each(function () {
  var self = $(this);
  // var options = eval('['   self.attr('ui-options')   ']');
  var options = (new Function("return ["   self.attr('ui-options')   "];")());

  console.log(options);
});

But I receive an error regarding CSP:

Content Security Policy of your site blocks the use of 'eval' in JavaScript

The Content Security Policy (CSP) prevents the evaluation of arbitrary strings as JavaScript to make it more difficult for an attacker to inject unauthorized code on your site.

To solve this issue, avoid using eval(), new Function(), setTimeout([string], ...) and setInterval([string], ...) for evaluating strings.

I created a this JSFiddle to help you to show me an example faster: https://jsfiddle.net/oqwc1j58/4/

Thank you

CodePudding user response:

If you make the attribute a data- attribute, and you make the value proper JSON, then jQuery will do that for you:

    $("[ui-jq]").each(function () {
      var self = $(this);
      var options = self.data("uiOptions");
    
      console.log(options);
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div ui-jq="easyPieChart"
     data-ui-options='{
                 "percent": 75,
                 "lineWidth": 5,
                 "trackColor": "#e8eff0",
                 "barColor": "#23b7e5",
                 "scaleColor": false,
                 "color": "#3a3f51",
                 "size": 134,
                 "lineCap": "butt",
                 "rotate": -90,
                 "animate": 1000
                 }'
       >
    </div>

When jQuery sees that a data- attribute value can be parsed as valid JSON, it does that implicitly and returns the resulting value when you load it via .data(). Note that the camel-case version of the name (I think) should be used, but jQuery might work with either version. Note also that you leave off the "data-" prefix.

CodePudding user response:

This is kind of janky but you can parse the HTML yourself and create the array you're looking for:

// From https://stackoverflow.com/a/72773057/378779
const sortObjectByKeys = (object, asc = true) => Object.fromEntries(
  Object.entries(object).sort(([k1], [k2]) => k1 < k2 ^ !asc ? -1 : 1),
)

$("[ui-jq]").each(function () {
  let options = $(this).attr('ui-options').replace('{', '').replace('}', '').split('\n')

  let o = {}
  options.filter(function(option) { return ! option.match(/^\s*$/) }).forEach(function(option){
      option = option.trim().replace(/,$/, '')
      let a = option.split(/: /)
      o[a[0]] = a[1].replace("'", '')
  })
  console.log(sortObjectByKeys(o))
});
</script>
<script src="https://code.jquery.com/jquery-3.6.3.js" integrity="sha256-nQLuAZGRRcILA 6dMBOvcRh5Pe310sBpanc6 QBmyVM=" crossorigin="anonymous"></script>

<div ui-jq="easyPieChart"
     ui-options="{
                 percent: 75,
                 lineWidth: 5,
                 trackColor: '#e8eff0',
                 barColor: '#23b7e5',
                 scaleColor: false,
                 color: '#3a3f51',
                 size: 134,
                 lineCap: 'butt',
                 rotate: -90,
                 animate: 1000
                 }"
     >
</div>

CodePudding user response:

You can use JSON.parse():

const opts=JSON.parse($("[ui-jq]").attr('ui-options').replaceAll("'",'"').replace(/(\w )(?=\s*:)/g,'"$1"'));
console.log(opts);
<script src="https://code.jquery.com/jquery-3.6.3.js" integrity="sha256-nQLuAZGRRcILA 6dMBOvcRh5Pe310sBpanc6 QBmyVM=" crossorigin="anonymous"></script>

<div ui-jq="easyPieChart"
     ui-options="{
                 percent: 75,
                 lineWidth: 5,
                 trackColor: '#e8eff0',
                 barColor: '#23b7e5',
                 scaleColor: false,
                 color: '#3a3f51',
                 size: 134,
                 lineCap: 'butt',
                 rotate: -90,
                 animate: 1000
                 }"
     >
</div>

  • Related