Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 1.07 breaks templating with HTML #39

Open
njwgh opened this issue Jul 22, 2020 · 5 comments
Open

Version 1.07 breaks templating with HTML #39

njwgh opened this issue Jul 22, 2020 · 5 comments

Comments

@njwgh
Copy link

njwgh commented Jul 22, 2020

This change in Version 1.07
var formatted = this.display(selection, $rendered);
to
var formatted = Utils.entityDecode(this.display(selection, $rendered));

strips any HTML from the rendered selected item.

This stops you from being able to use html for styling of the selected item, via templating as per the documentation for select2:
https://select2.org/selections.

For this reason I have had to dequeue selectWoo in Wordpress and load select2 itself.

Sorry for lack of example - but it is self-evident.

How big a security issue is the un-escaped HTML?

@fabianmarz
Copy link

@njwgh, nice, we catched it as well. Please see my comment below with a "workaround". The workaround might need to be tested and adjusted for your needs. It works for our needs of a single selection.

@claudiosanches, even this release was marked as a patch version these changes break existing integrations and thus should have rather be marked as a major version change instead…

The major changes done here are the decoding, which will return the value of a textarea, which results in [object object] if .value is used if a DOM node is passed in. Additionally the change from $.append() to $.text() which will, as the name states, render the text content and thus will also not render DOM nodes but result in [object object] as well.

In our project we used https://select2.org/selections#templating templateResult, and templateSelection to render a country selector (a flag icon next to the text). Unfortunately this broke with the recent version of this package.

To resolve this we've done the following

function formatCountry (country) {
  if (!country.id) {
    return country.text;
  }
  let $country = $(
    '<span class="flag-icon flag-icon-' + country.id.toLowerCase() + '"></span>' +
    '<span class="flag-text">' + country.text + '</span>'
  );
  return $country;
}

$.fn.selectWoo.amd.define('customSingleSelectionAdapter', [
  'select2/utils',
  'select2/selection/single',
], function (Utils, SingleSelection) {
  const adapter = SingleSelection;
  adapter.prototype.update = function (data) {
    if (data.length === 0) {
      this.clear();
      return;
    }
    var selection = data[0];
    var $rendered = this.$selection.find('.select2-selection__rendered');
    var formatted = this.display(selection, $rendered);
    $rendered.empty().append(formatted);
    $rendered.prop('title', selection.title || selection.text);
  };
  return adapter;
});

$('select.countries').selectWoo({
  minimumResultsForSearch: Infinity,
  width: 'style',
  templateResult: formatCountry,
  templateSelection: formatCountry,
  selectionAdapter: $.fn.selectWoo.amd.require('customSingleSelectionAdapter'),
});

@sun
Copy link

sun commented Feb 3, 2021

The issue is still causing problems today.

@acf-extended
Copy link

acf-extended commented Jul 9, 2021

Hello,

I stumbled upon this bug which prevents any select2 fields to render HTML in the selected choice, specifically for ACF Select fields in my case. I digged in the selectWoo source code and found what was causing the issue.

  • Since wooSelect 1.0.7 for Multiple Selection
  • Since wooSelect 1.0.5 for Single Selection

The problem come from the code that force $.text() on the selection, instead of the previous $.append(). Here is the code that fix the issue on the latest wooSelect 1.0.9 version:

In the file /dist/js/select2.full.js:1629. Find:

$rendered.empty().text(formatted);

Replace with:

$rendered.empty().append(formatted);

In the file /dist/js/select2.full.js:1764. Find:

$selection.text(formatted);

Replace with:

$selection.append(formatted);

Both fix come from selectWoo 1.0.5 and 1.0.2 original code. For Woocommerce integration, the fix is the same, but the file is /woocommerce/assets/js/select2/select2.full.js.

For ACF + Woocommerce users, you can disable selectWoo JS enqueue when ACF is loaded (and use the native select2 library instead). To do so, add the following PHP code in the functions.php file:

// Fix ACF + Woocommerce Select2 HTML render selection
add_action('acf/input/admin_enqueue_scripts', 'acf_force_native_select2_enqueue', 5);
function acf_force_native_select2_enqueue(){

    // Let ACF use native Select2 JS Library
    wp_deregister_script('select2');

}

Regards.

@fabianmarz
Copy link

@acf-extended, you should not modify the core/vendor files of a plugin whenever possible. Depending how you install plugins, the changes might get lost or overridden easily. So I highly discourage using your approach.

Maybe @jonathansadowski (just picked your name as you committed lately) can respond?

@acf-extended
Copy link

acf-extended commented Jul 9, 2021

Hello @fabianmarz,

Thanks for the feedback!

I don't modify the core files since I simply disable the script enqueue to let ACF use the correct select2 JS library instead, as explained in my comment.

I posted the JS code here to explain where the problem come from, so anyone can test the fix with dist files. I already ran multiple version compare on this library and I don't have the time dig further to point you the exact location of those lines in the source.

So I will let core developers decide if this fix is correct or not. I'm sure they know better where those lines are in source files anyway.

Thanks for the thumbs down!

Have a nice day.

Regards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants