问:
Multiple dropzones on same page cause bugs to appear
I have multiple dropzones (dynamic, each product represents a product that is added in a basket in my webshop).

Every image upload an ajax call is made that returns info of the uploaded image and displays it in the previewtemplate (thumbnail block of the uploaded image). Info like the dimensions, DPI and filename.

The problem is that info is always displayed only in the last dropzone, in the last previewtemplate.

For example:

```<code>When I have two dropzones.
I upload an image of 20DPI in the first one, result: no information is shown in the preview.

I upload an image of 20DPI in the second one, result: the preview is shown with 20 DPI as information which is correct.

I upload two images at the same time in the second dropzone, the first image with 20DPI the second one with 72DPI, result: the first preview is empty and the last preview briefly shows 20DPI before it is overwritten with 72DPI.
</code>```

This means the information is received correctly, it's just not placed correctly in the previewtemplates.

This is my dropzone code, it loops through all .dropzone classes:

```<code>$('.dropzone').each(function(index){
    $maxfiles = $(this).attr('maxfiles');
    $inputquantity = $(this).find('input').val();
    $thisdropzone = $(this);
    $(this).dropzone({
        paramName: 'postedFile',
        addRemoveLinks: true,
        dictDefaultMessage: '<i class="fas fa-file-upload uploadicon"></i> <span class="uploadtxt">Upload je bestand(en)</span>',
        dictRemoveFile: 'Verwijder',
        dictCancelUpload: 'Annuleren',
        dictInvalidFileType: 'Dit type bestand is niet toegestaan',
        dictCancelUploadConfirmation: 'Weet je zeker dat je het uploaden wilt annuleren?',
        dictMaxFilesExceeded: 'Maximale aantal bestanden overschreden',
        maxFiles: $maxfiles,
        acceptedFiles: '.jpg, .jpeg, .png, .pdf, .tif, .tiff',
        thumbnailWidth: '205',
        thumbnailHeight: '140',
        thumbnailMethod: 'crop',
        previewTemplate: $(".hiddendiv").html(),
        sending: function (file) {

        },
        // File contains dropzone file object, response contains ajax response from php file
        success: function (file, response) {
            var obj = JSON.parse(response);
            $($thisdropzone).find('.dz-preview:last .bestandnaam').text('Bestandsnaam: ' + obj[0].filename);
            $($thisdropzone).find('.dz-preview:last .resolutie').text('Resolutie: ' + obj[0].dpi + ' DPI');
            $($thisdropzone).find('.dz-preview:last .formaat').text('Formaat: ' + obj[0].heightcm + ' x ' + obj[0].widthcm + 'cm');
        },
    })
});
</code>```

And this is my html with in this example two dropzones (the forms):

```<code><table class="table upload-table">
   <tbody>
      <tr>
         <td class="plantmore-product-thumbnail uploadimg" width="100">
            <a href=""><img src="assets/images/noimg.jpg" alt=""></a>
         </td>
         <td class="plantmore-product-name" width="200">
            <div class="prodinfocheckout">
               <a class="prodname" href="">
               Monomeer
               </a>
               <span id="togglespecscheckout" class="prodspecscheckout noselect">
               <i class="fas fa-chevron-down"></i> Specificaties
               </span>
               <div class="togglespecscheckout">
                  Hoogte : 20cm
                  <br>
                  Breedte : 20cm
                  <br>
                  uploaden : 1
                  <br>
                  Lijmlaag : Wit
                  <br>
                  Laminaat : Anti-slip laminaat
                  <br>
                  Afwerking : Contoursnijden
                  <br>
               </div>
            </div>
         </td>
         <td class="plantmore-product-quantity" width="190">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">
            Benodigd formaat:<br>
            <span class="benodigd">20 x 20cm</span>
            </span>
            </span>
         </td>
         <td class="plantmore-product-quantity" width="185">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">Benodigde aantal<br> bestanden: <span class="benodigd">10</span></span>
            </span>
         </td>
         <td class="plantmore-product-quantity">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">Bestanden <br>toegewezen: <span class="benodigd">0 / 10</span></span>
            </span>
         </td>
         <td class="plantmore-product-quantity" valign="top">
            <button class="uploadbutton btn yellowbtn dz-clickable">Bestand(en) uploaden</button>
         </td>
      </tr>
      <tr class="newrow">
         <td colspan="6">
            <form action="upload/uploaden.php" class="dropzone dropzoneform dz-clickable" maxfiles="10" id="dropzone1">
               <input type="hidden" value="Monomeer" name="productnaam">
               <input type="hidden" value="Twan" name="klantnaam">
               <input type="hidden" value="20" name="hoogte">
               <input type="hidden" value="20" name="breedte">
               <div class="dz-default dz-message"><span><i class="fas fa-file-upload uploadicon"></i> <span class="uploadtxt">Upload je bestand(en)</span></span></div>
            </form>
         </td>
      </tr>
      <tr>
         <td class="plantmore-product-thumbnail uploadimg" width="100">
            <a href=""><img src="assets/images/noimg.jpg" alt=""></a>
         </td>
         <td class="plantmore-product-name" width="200">
            <div class="prodinfocheckout">
               <a class="prodname" href="">
               Monomeer
               </a>
               <span id="togglespecscheckout" class="prodspecscheckout noselect">
               <i class="fas fa-chevron-down"></i> Specificaties
               </span>
               <div class="togglespecscheckout">
                  Hoogte : 90cm
                  <br>
                  Breedte : 90cm
                  <br>
                  uploaden : 1
                  <br>
                  Lijmlaag : Wit
                  <br>
                  Laminaat : Anti-slip laminaat
                  <br>
                  Afwerking : Contoursnijden
                  <br>
               </div>
            </div>
         </td>
         <td class="plantmore-product-quantity" width="190">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">
            Benodigd formaat:<br>
            <span class="benodigd">90 x 90cm</span>
            </span>
            </span>
         </td>
         <td class="plantmore-product-quantity" width="185">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">Benodigde aantal<br> bestanden: <span class="benodigd">1</span></span>
            </span>
         </td>
         <td class="plantmore-product-quantity">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">Bestanden <br>toegewezen: <span class="benodigd">0 / 1</span></span>
            </span>
         </td>
         <td class="plantmore-product-quantity" valign="top">
            <button class="uploadbutton btn yellowbtn dz-clickable">Bestand(en) uploaden</button>
         </td>
      </tr>
      <tr class="newrow">
         <td colspan="6">
            <form action="upload/uploaden.php" class="dropzone dropzoneform dz-clickable" maxfiles="1" id="dropzone4">
               <input type="hidden" value="Monomeer" name="productnaam">
               <input type="hidden" value="Twan" name="klantnaam">
               <input type="hidden" value="90" name="hoogte">
               <input type="hidden" value="90" name="breedte">
               <div class="dz-default dz-message"><span><i class="fas fa-file-upload uploadicon"></i> <span class="uploadtxt">Upload je bestand(en)</span></span></div>
            </form>
         </td>
      </tr>
   </tbody>
</table>
</code>```

What can be causing the bugs? I tried removing the :last parts and only upload one image in the first one and one in the second. But the first preview still doesn't have any information in it.

This is my custom previewelement inside .hiddendiv it's beneath the dropzones in my DOM:

```<code>  <div class="hiddendiv">

    <div class="dz-preview dz-file-preview">
      <div class="dz-image"><img data-dz-thumbnail /></div>
      <div class="dz-details">
          <div class="dz-size"><span data-dz-size></span></div>
          <div class="dz-filename"><span data-dz-name></span></div>
      </div>
      <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
      <div class="dz-error-message"><span data-dz-errormessage></span></div>
            <span class="infoline">
                <span class="infospan bestandnaam">Bestandnaam:</span>
                <!-- <i class="fas fa-times-circle afgekeurd"></i> -->
            </span>
      <span class="infoline">
                <span class="infospan resolutie">Resolutie:</span>
                <!-- <i class="fas fa-check-circle goedgekeurd"></i> -->
            </span>
      <span class="infoline">
                <span class="infospan formaat">Formaat:</span>
                <!-- <i class="fas fa-times-circle afgekeurd"></i> -->
            </span>
            <div class="foutformaat">
                <span>Bestand heeft niet het benodigde formaat.</span>
                <span class="uploadinfobox">
                    <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
                        <i class="fas fa-info-circle"></i>
                    </button>
                </span>
            </div>
      <button class="yellowbtn btn vrijgevenbtn" type="button">Bestand vrijgeven</button>
            <hr class="uploadline">
            <span class="toewijzen">Aantal</span>
      <div class="uploadcontent">
        <input type="text" class="fileinput">
        <button class="plusminupload" id="minupload">−</button>
        <button class="plusminupload" id="plusupload">+</button>
      </div>
    </div>
  </div>
</code>```

Updated code from answer below:

```<code>$('.dropzone').each(function(index, element){
    let $el = $(element);
    let $maxfiles = $el.attr('maxfiles');
    let $inputquantity = $el.find('input').val();
    let $thispreview = $el.find('.hiddendiv');
    let $thisdropzone = $el;
    // $maxfiles = $(this).attr('maxfiles');
    // $inputquantity = $(this).find('input').val();
    // $thisdropzone = $(this);
    // $thispreview = $(this).find('.hiddendiv');

    $(this).dropzone({
        // clickable: ".uploadbutton, .dropzoneform",
        paramName: 'postedFile',
        addRemoveLinks: true,
        dictDefaultMessage: '<i class="fas fa-file-upload uploadicon"></i> <span class="uploadtxt">Upload je bestand(en)</span>',
        dictRemoveFile: 'Verwijder',
        dictCancelUpload: 'Annuleren',
        dictInvalidFileType: 'Dit type bestand is niet toegestaan',
        dictCancelUploadConfirmation: 'Weet je zeker dat je het uploaden wilt annuleren?',
        dictMaxFilesExceeded: 'Maximale aantal bestanden overschreden',
        maxFiles: $maxfiles,
        acceptedFiles: '.jpg, .jpeg, .png, .pdf, .tif, .tiff',
        thumbnailWidth: '205',
        thumbnailHeight: '140',
        thumbnailMethod: 'crop',
        previewTemplate: $thispreview.html(),
        processing: function (file) {

        },
        // File contains dropzone file object, response contains ajax response from php file
        success: function (file, response) {
            // alert('test');
            let file_meta = JSON.parse(response);
            let $preview = $thisdropzone.find('.dz-preview:last');
            if(file_meta[0].status == 'success'){

            }else if(file_meta[0].status == 'error'){
                $preview.find('.vrijgevenbtn').show();
                $preview.find('.foutformaat').show();
            }
            $preview.find('.bestandnaam').text('Bestandsnaam: ' + file_meta[0].filename);
            $preview.find('.resolutie').text('Resolutie: ' + file_meta[0].dpi + ' DPI');
            $preview.find('.formaat').text('Formaat: ' + file_meta[0].heightcm + ' x ' + file_meta[0].widthcm + 'cm');
        },
    })
});
</code>```

This is what happens when I upload multiple images in one selection:
Selecting three images from my computer:

Three previews in the dropzone with only the last one having data:

Every image returns a json string which in this example are:

```<code>[{"status":"error","filename":"instablok.jpg","filesize":22822,"tmp_name":"\/tmp\/phpI6ov6y","height":172,"width":565,"heightcm":"6,07","widthcm":"19,93","tifwidth":null,"dpi":"72"}]

[{"status":"error","filename":"fbblok.jpg","filesize":17349,"tmp_name":"\/tmp\/phpBzh40y","height":172,"width":565,"heightcm":"6,07","widthcm":"19,93","tifwidth":null,"dpi":"72"}]

[{"status":"error","filename":"logo-dark.png","filesize":21137,"tmp_name":"\/tmp\/phpCHGGZg","height":154,"width":881,"heightcm":"5,43","widthcm":"31,08","tifwidth":null,"dpi":"72"}]
</code>```

All of them are returned seperately. The strange thing is, all data is added to the last preview and overwritten by a newer one. So the last preview first contains data from the first returned json, then the second and finally the last correct one, while the first two remain empty.

You can test with these two links:

First add a product to your basket here: https://printzelf.nl/new/folie/monomeer
You Aantal means quantity and this will determine how many images can be uploaded in a dropzone so you need more than 1 to be able to see the bug.

When you are done clicking through the options you can add it Toevoegen. Then go to the dropzone page link which is: https://printzelf.nl/new/bestanden-uploaden

答:
scope your variables. You have this code.

```<code>$('.dropzone').each(function(index){
    $maxfiles = $(this).attr('maxfiles');
    $inputquantity = $(this).find('input').val();
    $thisdropzone = $(this);
</code>```

So in reality the variables you are using are:

```<code>$maxfiles = window.maxfiles
$inputquantity = window.$inputquantity
$thisdropzone = window.$thisdropzone
</code>```

This means that you are "reusing" the same variables on every dropzone field you're iterating through, letting the last element looped through "stick" the variables.  That's why you are seeing your results always on the last dropzone on your page.

A slight visual representation

In code I recreated your behavior simplified. The theory is that all fields should show their hidden gems when the button is clicked. Yet only the last field shows the hidden gem. This is because the window.$selection variable is reassigned by each iteration.

$('.whoa').each(function(i,e) {
   $selection = $(e);
   $('.start').on('click', (e) => {
      $selection.val($selection.data("hidden-gem"));
   });
});```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="whoa" data-hidden-gem="emerald">
<input type="text" class="whoa" data-hidden-gem="diamond">
<input type="text" class="whoa" data-hidden-gem="ruby">
<button class="start">Show gems</button></code>```

What you want are scoped variables using var or better let keyword, making sure each looped element has their own set of variables relevant to their own loop.

In this code sample we see the desired behavior. The only difference the is the added let key word in front of $selection, forcing the creation of a scoped variable, resulting in the desired behaviour.

$('.whoa').each(function(i,e) {
   let $selection = $(e);
   $('.start').on('click', (e) => {
      $selection.val($selection.data("hidden-gem"));
   });
});```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="whoa" data-hidden-gem="emerald">
<input type="text" class="whoa" data-hidden-gem="diamond">
<input type="text" class="whoa" data-hidden-gem="ruby">
<button class="start">Show gems</button></code>```

Also try to refrain from using this in a jQuery context. It is not dependable. The meaning of this changes on every context change and can be altered altogether.

When looping through with $.each the first argument passed is the index, the second the actual element. This is a dependable scoped variable that will not change meaning.

Also, don't instantiate multiple jQuery instances when you need to use the same thing several times. Instance once and re-use.

So with all this in mind rewrite those lines to:

```<code>$('.dropzone').each(function(index, element){
    let $el = $(element);
    let $maxfiles = $el.attr('maxfiles');
    let $inputquantity = $el.find('input').val();
    let $thisdropzone = $el;
</code>```

Then you have these lines

```<code>$($thisdropzone).find('.dz-preview:last .bestandnaam').text('Bestandsnaam: ' + obj[0].filename);
$($thisdropzone).find('.dz-preview:last .resolutie').text('Resolutie: ' + obj[0].dpi + ' DPI');
$($thisdropzone).find('.dz-preview:last .formaat').text('Formaat: ' + obj[0].heightcm + ' x ' + obj[0].widthcm + 'cm');
</code>```

You are re-wrapping something that is already a jQuery instance. Lose the unnecessary double wrapping.

Also consider putting obj[0] in a meaningfully names variable so the code becomes more readable, without having to check what we expect to contain in obj[0] in 3 months when we revisit the code.

Keeping this in mind, we can rewrite this to:

```<code>let file_meta = JSON.parse(response);
let $preview = $thisdropzone.find('.dz-preview:last');
$preview.find('.bestandnaam').text('Bestandsnaam: ' + file_meta.filename);
$preview.find('.resolutie').text('Resolutie: ' + file_meta.dpi + ' DPI');
$preview.find('.formaat').text('Formaat: ' + file_meta.heightcm + ' x ' + file_meta.widthcm + 'cm');
</code>```

Also change let $preview = $thisdropzone.find('.dz-preview:last'); to let $preview = $(file.previewElement); so that when multiple files are uploaded, the correct preview element is used to render the relevant data.

A complete working example, minus upload capability due to no server accepting data.

let counter = 0;
$('.dropzone').each(function(index, element){
    let $el = $(element);
    let $maxfiles = $el.attr('maxfiles');
    let $inputquantity = $el.find('input').val();
    let uploaded_preview = $('.hiddendiv').html();
    let $thisdropzone = $el;
    // $maxfiles = $(this).attr('maxfiles');
    // $inputquantity = $(this).find('input').val();
    // $thisdropzone = $(this);
    // $thispreview = $(this).find('.hiddendiv');

    $el.dropzone({
        // clickable: ".uploadbutton, .dropzoneform",
        paramName: 'postedFile',
        addRemoveLinks: true,
        dictDefaultMessage: ' Upload je bestand(en)',
        dictRemoveFile: 'Verwijder',
        dictCancelUpload: 'Annuleren',
        dictInvalidFileType: 'Dit type bestand is niet toegestaan',
        dictCancelUploadConfirmation: 'Weet je zeker dat je het uploaden wilt annuleren?',
        dictMaxFilesExceeded: 'Maximale aantal bestanden overschreden',
        maxFiles: $maxfiles,
        acceptedFiles: '.jpg, .jpeg, .png, .pdf, .tif, .tiff',
        thumbnailWidth: '205',
        thumbnailHeight: '140',
        thumbnailMethod: 'crop',
        previewTemplate: uploaded_preview,
        processing: function (file) {

        },
        // File contains dropzone file object, response contains ajax response from php file
        error: function (file, response) {

            counter++;
            console.log('Option ' + counter);
            response = '[{"status":"error","filename":"instablok'+counter+'.jpg","filesize":22822,"tmp_name":"\/tmp\/phpI6ov6y","height":172,"width":565,"heightcm":"6'+counter+',07","widthcm":"19'+counter+',93","tifwidth":null,"dpi":"72"}]';

            let file_meta = JSON.parse(response);

            let $preview = $(file.previewElement);
            if(file_meta[0].status == 'success'){

            }else if(file_meta[0].status == 'error'){
                $preview.find('.vrijgevenbtn').show();
                $preview.find('.foutformaat').show();
            }
            $preview.find('.bestandnaam').text('Bestandsnaam: ' + file_meta[0].filename);
            $preview.find('.resolutie').text('Resolutie: ' + file_meta[0].dpi + ' DPI');
            $preview.find('.formaat').text('Formaat: ' + file_meta[0].heightcm + ' x ' + file_meta[0].widthcm + 'cm');
        },
    })
});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.hiddendiv {
   display: none;
}</code>```

<link rel="stylesheet" href="https://rawgit.com/enyo/dropzone/master/dist/dropzone.css">

               Monomeer

                Specificaties

                  Hoogte : 20cm

                  Breedte : 20cm

                  uploaden : 1

                  Lijmlaag : Wit

                  Laminaat : Anti-slip laminaat

                  Afwerking : Contoursnijden

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>

            Benodigd formaat:

            20 x 20cm

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>
            Benodigde aantal
 bestanden: 10

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>
            Bestanden
toegewezen: 0 / 10

            <button class="uploadbutton btn yellowbtn dz-clickable">Bestand(en) uploaden</button>

            <form action="upload/uploaden.php" class="dropzone dropzoneform dz-clickable" maxfiles="10" id="dropzone1">
               <input type="hidden" value="Monomeer" name="productnaam">
               <input type="hidden" value="Twan" name="klantnaam">
               <input type="hidden" value="20" name="hoogte">
               <input type="hidden" value="20" name="breedte">

 Upload je bestand(en)

            </form>

               Monomeer

                Specificaties

                  Hoogte : 90cm

                  Breedte : 90cm

                  uploaden : 1

                  Lijmlaag : Wit

                  Laminaat : Anti-slip laminaat

                  Afwerking : Contoursnijden

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>

            Benodigd formaat:

            90 x 90cm

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>
            Benodigde aantal
 bestanden: 1

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>
            Bestanden
toegewezen: 0 / 1

            <button class="uploadbutton btn yellowbtn dz-clickable">Bestand(en) uploaden</button>

            <form action="upload/uploaden.php" class="dropzone dropzoneform dz-clickable" maxfiles="1" id="dropzone4">
               <input type="hidden" value="Monomeer" name="productnaam">
               <input type="hidden" value="Twan" name="klantnaam">
               <input type="hidden" value="90" name="hoogte">
               <input type="hidden" value="90" name="breedte">

 Upload je bestand(en)

            </form>

                Bestandnaam:

                Resolutie:

                Formaat:

                Bestand heeft niet het benodigde formaat.

                    <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

                    </button>

      <button class="yellowbtn btn vrijgevenbtn" type="button">Bestand vrijgeven</button>

            Aantal

        <input type="text" class="fileinput">
        <button class="plusminupload" id="minupload">−</button>
        <button class="plusminupload" id="plusupload">+</button>

```

Body:
I have multiple dropzones (dynamic, each product represents a product that is added in a basket in my webshop).

Every image upload an ajax call is made that returns info of the uploaded image and displays it in the previewtemplate (thumbnail block of the uploaded image). Info like the dimensions, DPI and filename.

The problem is that info is always displayed only in the last dropzone, in the last previewtemplate.

For example:

When I have two dropzones.
I upload an image of 20DPI in the first one, result: no information is shown in the preview.

I upload an image of 20DPI in the second one, result: the preview is shown with 20 DPI as information which is correct.

I upload two images at the same time in the second dropzone, the first image with 20DPI the second one with 72DPI, result: the first preview is empty and the last preview briefly shows 20DPI before it is overwritten with 72DPI.

This means the information is received correctly, it's just not placed correctly in the previewtemplates.

This is my dropzone code, it loops through all .dropzone classes:

$('.dropzone').each(function(index){
    $maxfiles = $(this).attr('maxfiles');
    $inputquantity = $(this).find('input').val();
    $thisdropzone = $(this);
    $(this).dropzone({
        paramName: 'postedFile',
        addRemoveLinks: true,
        dictDefaultMessage: ' Upload je bestand(en)',
        dictRemoveFile: 'Verwijder',
        dictCancelUpload: 'Annuleren',
        dictInvalidFileType: 'Dit type bestand is niet toegestaan',
        dictCancelUploadConfirmation: 'Weet je zeker dat je het uploaden wilt annuleren?',
        dictMaxFilesExceeded: 'Maximale aantal bestanden overschreden',
        maxFiles: $maxfiles,
        acceptedFiles: '.jpg, .jpeg, .png, .pdf, .tif, .tiff',
        thumbnailWidth: '205',
        thumbnailHeight: '140',
        thumbnailMethod: 'crop',
        previewTemplate: $(".hiddendiv").html(),
        sending: function (file) {

        },
        // File contains dropzone file object, response contains ajax response from php file
        success: function (file, response) {
            var obj = JSON.parse(response);
            $($thisdropzone).find('.dz-preview:last .bestandnaam').text('Bestandsnaam: ' + obj[0].filename);
            $($thisdropzone).find('.dz-preview:last .resolutie').text('Resolutie: ' + obj[0].dpi + ' DPI');
            $($thisdropzone).find('.dz-preview:last .formaat').text('Formaat: ' + obj[0].heightcm + ' x ' + obj[0].widthcm + 'cm');
        },
    })
});

And this is my html with in this example two dropzones (the forms):

               Monomeer

                Specificaties

                  Hoogte : 20cm

                  Breedte : 20cm

                  uploaden : 1

                  Lijmlaag : Wit

                  Laminaat : Anti-slip laminaat

                  Afwerking : Contoursnijden

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>

            Benodigd formaat:

            20 x 20cm

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>
            Benodigde aantal
 bestanden: 10

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>
            Bestanden
toegewezen: 0 / 10

            <button class="uploadbutton btn yellowbtn dz-clickable">Bestand(en) uploaden</button>

            <form action="upload/uploaden.php" class="dropzone dropzoneform dz-clickable" maxfiles="10" id="dropzone1">
               <input type="hidden" value="Monomeer" name="productnaam">
               <input type="hidden" value="Twan" name="klantnaam">
               <input type="hidden" value="20" name="hoogte">
               <input type="hidden" value="20" name="breedte">

 Upload je bestand(en)

            </form>

               Monomeer

                Specificaties

                  Hoogte : 90cm

                  Breedte : 90cm

                  uploaden : 1

                  Lijmlaag : Wit

                  Laminaat : Anti-slip laminaat

                  Afwerking : Contoursnijden

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>

            Benodigd formaat:

            90 x 90cm

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>
            Benodigde aantal
 bestanden: 1

            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

            </button>
            Bestanden
toegewezen: 0 / 1

            <button class="uploadbutton btn yellowbtn dz-clickable">Bestand(en) uploaden</button>

            <form action="upload/uploaden.php" class="dropzone dropzoneform dz-clickable" maxfiles="1" id="dropzone4">
               <input type="hidden" value="Monomeer" name="productnaam">
               <input type="hidden" value="Twan" name="klantnaam">
               <input type="hidden" value="90" name="hoogte">
               <input type="hidden" value="90" name="breedte">

 Upload je bestand(en)

            </form>

What can be causing the bugs? I tried removing the :last parts and only upload one image in the first one and one in the second. But the first preview still doesn't have any information in it.

This is my custom previewelement inside .hiddendiv it's beneath the dropzones in my DOM:

                Bestandnaam:

                Resolutie:

                Formaat:

                Bestand heeft niet het benodigde formaat.

                    <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">

                    </button>

      <button class="yellowbtn btn vrijgevenbtn" type="button">Bestand vrijgeven</button>

            Aantal

        <input type="text" class="fileinput">
        <button class="plusminupload" id="minupload">−</button>
        <button class="plusminupload" id="plusupload">+</button>

Updated code from answer below:

$('.dropzone').each(function(index, element){
    let $el = $(element);
    let $maxfiles = $el.attr('maxfiles');
    let $inputquantity = $el.find('input').val();
    let $thispreview = $el.find('.hiddendiv');
    let $thisdropzone = $el;
    // $maxfiles = $(this).attr('maxfiles');
    // $inputquantity = $(this).find('input').val();
    // $thisdropzone = $(this);
    // $thispreview = $(this).find('.hiddendiv');

    $(this).dropzone({
        // clickable: ".uploadbutton, .dropzoneform",
        paramName: 'postedFile',
        addRemoveLinks: true,
        dictDefaultMessage: ' Upload je bestand(en)',
        dictRemoveFile: 'Verwijder',
        dictCancelUpload: 'Annuleren',
        dictInvalidFileType: 'Dit type bestand is niet toegestaan',
        dictCancelUploadConfirmation: 'Weet je zeker dat je het uploaden wilt annuleren?',
        dictMaxFilesExceeded: 'Maximale aantal bestanden overschreden',
        maxFiles: $maxfiles,
        acceptedFiles: '.jpg, .jpeg, .png, .pdf, .tif, .tiff',
        thumbnailWidth: '205',
        thumbnailHeight: '140',
        thumbnailMethod: 'crop',
        previewTemplate: $thispreview.html(),
        processing: function (file) {

        },
        // File contains dropzone file object, response contains ajax response from php file
        success: function (file, response) {
            // alert('test');
            let file_meta = JSON.parse(response);
            let $preview = $thisdropzone.find('.dz-preview:last');
            if(file_meta[0].status == 'success'){

            }else if(file_meta[0].status == 'error'){
                $preview.find('.vrijgevenbtn').show();
                $preview.find('.foutformaat').show();
            }
            $preview.find('.bestandnaam').text('Bestandsnaam: ' + file_meta[0].filename);
            $preview.find('.resolutie').text('Resolutie: ' + file_meta[0].dpi + ' DPI');
            $preview.find('.formaat').text('Formaat: ' + file_meta[0].heightcm + ' x ' + file_meta[0].widthcm + 'cm');
        },
    })
});

This is what happens when I upload multiple images in one selection:
Selecting three images from my computer:

Three previews in the dropzone with only the last one having data:

Every image returns a json string which in this example are:

[{"status":"error","filename":"instablok.jpg","filesize":22822,"tmp_name":"\/tmp\/phpI6ov6y","height":172,"width":565,"heightcm":"6,07","widthcm":"19,93","tifwidth":null,"dpi":"72"}]

[{"status":"error","filename":"fbblok.jpg","filesize":17349,"tmp_name":"\/tmp\/phpBzh40y","height":172,"width":565,"heightcm":"6,07","widthcm":"19,93","tifwidth":null,"dpi":"72"}]

[{"status":"error","filename":"logo-dark.png","filesize":21137,"tmp_name":"\/tmp\/phpCHGGZg","height":154,"width":881,"heightcm":"5,43","widthcm":"31,08","tifwidth":null,"dpi":"72"}]

All of them are returned seperately. The strange thing is, all data is added to the last preview and overwritten by a newer one. So the last preview first contains data from the first returned json, then the second and finally the last correct one, while the first two remain empty.

You can test with these two links:

First add a product to your basket here: https://printzelf.nl/new/folie/monomeer
You Aantal means quantity and this will determine how many images can be uploaded in a dropzone so you need more than 1 to be able to see the bug.

When you are done clicking through the options you can add it Toevoegen. Then go to the dropzone page link which is: https://printzelf.nl/new/bestanden-uploaden

Body:
scope your variables. You have this code.

$('.dropzone').each(function(index){
    $maxfiles = $(this).attr('maxfiles');
    $inputquantity = $(this).find('input').val();
    $thisdropzone = $(this);

So in reality the variables you are using are:

$maxfiles = window.maxfiles
$inputquantity = window.$inputquantity
$thisdropzone = window.$thisdropzone

This means that you are "reusing" the same variables on every dropzone field you're iterating through, letting the last element looped through "stick" the variables.  That's why you are seeing your results always on the last dropzone on your page.

A slight visual representation

In code I recreated your behavior simplified. The theory is that all fields should show their hidden gems when the button is clicked. Yet only the last field shows the hidden gem. This is because the window.$selection variable is reassigned by each iteration.

$('.whoa').each(function(i,e) {
   $selection = $(e);
   $('.start').on('click', (e) => {
      $selection.val($selection.data("hidden-gem"));
   });
});

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="whoa" data-hidden-gem="emerald">
<input type="text" class="whoa" data-hidden-gem="diamond">
<input type="text" class="whoa" data-hidden-gem="ruby">
<button class="start">Show gems</button>

What you want are scoped variables using var or better let keyword, making sure each looped element has their own set of variables relevant to their own loop.

In this code sample we see the desired behavior. The only difference the is the added let key word in front of $selection, forcing the creation of a scoped variable, resulting in the desired behaviour.

$('.whoa').each(function(i,e) {
   let $selection = $(e);
   $('.start').on('click', (e) => {
      $selection.val($selection.data("hidden-gem"));
   });
});

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="whoa" data-hidden-gem="emerald">
<input type="text" class="whoa" data-hidden-gem="diamond">
<input type="text" class="whoa" data-hidden-gem="ruby">
<button class="start">Show gems</button>

Also try to refrain from using this in a jQuery context. It is not dependable. The meaning of this changes on every context change and can be altered altogether.

When looping through with $.each the first argument passed is the index, the second the actual element. This is a dependable scoped variable that will not change meaning.

Also, don't instantiate multiple jQuery instances when you need to use the same thing several times. Instance once and re-use.

So with all this in mind rewrite those lines to:

$('.dropzone').each(function(index, element){
    let $el = $(element);
    let $maxfiles = $el.attr('maxfiles');
    let $inputquantity = $el.find('input').val();
    let $thisdropzone = $el;

Then you have these lines

$($thisdropzone).find('.dz-preview:last .bestandnaam').text('Bestandsnaam: ' + obj[0].filename);
$($thisdropzone).find('.dz-preview:last .resolutie').text('Resolutie: ' + obj[0].dpi + ' DPI');
$($thisdropzone).find('.dz-preview:last .formaat').text('Formaat: ' + obj[0].heightcm + ' x ' + obj[0].widthcm + 'cm');

You are re-wrapping something that is already a jQuery instance. Lose the unnecessary double wrapping.

Also consider putting obj[0] in a meaningfully names variable so the code becomes more readable, without having to check what we expect to contain in obj[0] in 3 months when we revisit the code.

Keeping this in mind, we can rewrite this to:

let file_meta = JSON.parse(response);
let $preview = $thisdropzone.find('.dz-preview:last');
$preview.find('.bestandnaam').text('Bestandsnaam: ' + file_meta.filename);
$preview.find('.resolutie').text('Resolutie: ' + file_meta.dpi + ' DPI');
$preview.find('.formaat').text('Formaat: ' + file_meta.heightcm + ' x ' + file_meta.widthcm + 'cm');

Also change let $preview = $thisdropzone.find('.dz-preview:last'); to let $preview = $(file.previewElement); so that when multiple files are uploaded, the correct preview element is used to render the relevant data.

A complete working example, minus upload capability due to no server accepting data.

let counter = 0;
$('.dropzone').each(function(index, element){
    let $el = $(element);
    let $maxfiles = $el.attr('maxfiles');
    let $inputquantity = $el.find('input').val();
    let uploaded_preview = $('.hiddendiv').html();
    let $thisdropzone = $el;
    // $maxfiles = $(this).attr('maxfiles');
    // $inputquantity = $(this).find('input').val();
    // $thisdropzone = $(this);
    // $thispreview = $(this).find('.hiddendiv');

    $el.dropzone({
        // clickable: ".uploadbutton, .dropzoneform",
        paramName: 'postedFile',
        addRemoveLinks: true,
        dictDefaultMessage: '<i class="fas fa-file-upload uploadicon"></i> <span class="uploadtxt">Upload je bestand(en)</span>',
        dictRemoveFile: 'Verwijder',
        dictCancelUpload: 'Annuleren',
        dictInvalidFileType: 'Dit type bestand is niet toegestaan',
        dictCancelUploadConfirmation: 'Weet je zeker dat je het uploaden wilt annuleren?',
        dictMaxFilesExceeded: 'Maximale aantal bestanden overschreden',
        maxFiles: $maxfiles,
        acceptedFiles: '.jpg, .jpeg, .png, .pdf, .tif, .tiff',
        thumbnailWidth: '205',
        thumbnailHeight: '140',
        thumbnailMethod: 'crop',
        previewTemplate: uploaded_preview,
        processing: function (file) {

        },
        // File contains dropzone file object, response contains ajax response from php file
        error: function (file, response) {

            counter++;
            console.log('Option ' + counter);
            response = '[{"status":"error","filename":"instablok'+counter+'.jpg","filesize":22822,"tmp_name":"\/tmp\/phpI6ov6y","height":172,"width":565,"heightcm":"6'+counter+',07","widthcm":"19'+counter+',93","tifwidth":null,"dpi":"72"}]';

            let file_meta = JSON.parse(response);

            let $preview = $(file.previewElement);
            if(file_meta[0].status == 'success'){

            }else if(file_meta[0].status == 'error'){
                $preview.find('.vrijgevenbtn').show();
                $preview.find('.foutformaat').show();
            }
            $preview.find('.bestandnaam').text('Bestandsnaam: ' + file_meta[0].filename);
            $preview.find('.resolutie').text('Resolutie: ' + file_meta[0].dpi + ' DPI');
            $preview.find('.formaat').text('Formaat: ' + file_meta[0].heightcm + ' x ' + file_meta[0].widthcm + 'cm');
        },
    })
});

.hiddendiv {
   display: none;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://rawgit.com/enyo/dropzone/master/dist/dropzone.js"></script>
<script type="text/javascript">
// Disable auto discover for all elements:
Dropzone.autoDiscover = false;
</script>
<link rel="stylesheet" href="https://rawgit.com/enyo/dropzone/master/dist/dropzone.css">

<table class="table upload-table">
   <tbody>
      <tr>
         <td class="plantmore-product-thumbnail uploadimg" width="100">
            <a href=""><img src="assets/images/noimg.jpg" alt=""></a>
         </td>
         <td class="plantmore-product-name" width="200">
            <div class="prodinfocheckout">
               <a class="prodname" href="">
               Monomeer
               </a>
               <span id="togglespecscheckout" class="prodspecscheckout noselect">
               <i class="fas fa-chevron-down"></i> Specificaties
               </span>
               <div class="togglespecscheckout">
                  Hoogte : 20cm
                  <br>
                  Breedte : 20cm
                  <br>
                  uploaden : 1
                  <br>
                  Lijmlaag : Wit
                  <br>
                  Laminaat : Anti-slip laminaat
                  <br>
                  Afwerking : Contoursnijden
                  <br>
               </div>
            </div>
         </td>
         <td class="plantmore-product-quantity" width="190">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">
            Benodigd formaat:<br>
            <span class="benodigd">20 x 20cm</span>
            </span>
            </span>
         </td>
         <td class="plantmore-product-quantity" width="185">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">Benodigde aantal<br> bestanden: <span class="benodigd">10</span></span>
            </span>
         </td>
         <td class="plantmore-product-quantity">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">Bestanden <br>toegewezen: <span class="benodigd">0 / 10</span></span>
            </span>
         </td>
         <td class="plantmore-product-quantity" valign="top">
            <button class="uploadbutton btn yellowbtn dz-clickable">Bestand(en) uploaden</button>
         </td>
      </tr>
      <tr class="newrow">
         <td colspan="6">
            <form action="upload/uploaden.php" class="dropzone dropzoneform dz-clickable" maxfiles="10" id="dropzone1">
               <input type="hidden" value="Monomeer" name="productnaam">
               <input type="hidden" value="Twan" name="klantnaam">
               <input type="hidden" value="20" name="hoogte">
               <input type="hidden" value="20" name="breedte">
               <div class="dz-default dz-message"><span><i class="fas fa-file-upload uploadicon"></i> <span class="uploadtxt">Upload je bestand(en)</span></span></div>
            </form>
         </td>
      </tr>
      <tr>
         <td class="plantmore-product-thumbnail uploadimg" width="100">
            <a href=""><img src="assets/images/noimg.jpg" alt=""></a>
         </td>
         <td class="plantmore-product-name" width="200">
            <div class="prodinfocheckout">
               <a class="prodname" href="">
               Monomeer
               </a>
               <span id="togglespecscheckout" class="prodspecscheckout noselect">
               <i class="fas fa-chevron-down"></i> Specificaties
               </span>
               <div class="togglespecscheckout">
                  Hoogte : 90cm
                  <br>
                  Breedte : 90cm
                  <br>
                  uploaden : 1
                  <br>
                  Lijmlaag : Wit
                  <br>
                  Laminaat : Anti-slip laminaat
                  <br>
                  Afwerking : Contoursnijden
                  <br>
               </div>
            </div>
         </td>
         <td class="plantmore-product-quantity" width="190">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">
            Benodigd formaat:<br>
            <span class="benodigd">90 x 90cm</span>
            </span>
            </span>
         </td>
         <td class="plantmore-product-quantity" width="185">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">Benodigde aantal<br> bestanden: <span class="benodigd">1</span></span>
            </span>
         </td>
         <td class="plantmore-product-quantity">
            <span class="centervertical">
            <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
            <i class="fas fa-info-circle"></i>
            </button>
            <span class="amount">Bestanden <br>toegewezen: <span class="benodigd">0 / 1</span></span>
            </span>
         </td>
         <td class="plantmore-product-quantity" valign="top">
            <button class="uploadbutton btn yellowbtn dz-clickable">Bestand(en) uploaden</button>
         </td>
      </tr>
      <tr class="newrow">
         <td colspan="6">
            <form action="upload/uploaden.php" class="dropzone dropzoneform dz-clickable" maxfiles="1" id="dropzone4">
               <input type="hidden" value="Monomeer" name="productnaam">
               <input type="hidden" value="Twan" name="klantnaam">
               <input type="hidden" value="90" name="hoogte">
               <input type="hidden" value="90" name="breedte">
               <div class="dz-default dz-message"><span><i class="fas fa-file-upload uploadicon"></i> <span class="uploadtxt">Upload je bestand(en)</span></span></div>
            </form>
         </td>
      </tr>
   </tbody>
</table>

  <div class="hiddendiv">

    <div class="dz-preview dz-file-preview">
      <div class="dz-image"><img data-dz-thumbnail /></div>
      <div class="dz-details">
          <div class="dz-size"><span data-dz-size></span></div>
          <div class="dz-filename"><span data-dz-name></span></div>
      </div>
      <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
      <div class="dz-error-message"><span data-dz-errormessage></span></div>
            <span class="infoline">
                <span class="infospan bestandnaam">Bestandnaam:</span>
                <!-- <i class="fas fa-times-circle afgekeurd"></i> -->
            </span>
      <span class="infoline">
                <span class="infospan resolutie">Resolutie:</span>
                <!-- <i class="fas fa-check-circle goedgekeurd"></i> -->
            </span>
      <span class="infoline">
                <span class="infospan formaat">Formaat:</span>
                <!-- <i class="fas fa-times-circle afgekeurd"></i> -->
            </span>
            <div class="foutformaat">
                <span>Bestand heeft niet het benodigde formaat.</span>
                <span class="uploadinfobox">
                    <button class="infotooltip tooltipupload" data-tooltip="Lorem ipsum">
                        <i class="fas fa-info-circle"></i>
                    </button>
                </span>
            </div>
      <button class="yellowbtn btn vrijgevenbtn" type="button">Bestand vrijgeven</button>
            <hr class="uploadline">
            <span class="toewijzen">Aantal</span>
      <div class="uploadcontent">
        <input type="text" class="fileinput">
        <button class="plusminupload" id="minupload">−</button>
        <button class="plusminupload" id="plusupload">+</button>
      </div>
    </div>
  </div>


来源: stackexchange

问:
Save PSQL run time parameter as a variable
I am trying to set max_parallel_workers_per_gather to be equal to the run time parameter max_parallel_workers in the current session only.

I want this to be applicable across numerous different machines so instead of hard-coding a value I want it to be directly relational to this other run time parameter.

Is there a way I can do this? I don't seem to be able to create a variable and set it to be the value of max_parallel_workers like such:

```<code>\set test_var max_parallel_workers;
</code>```

答:
You don't need a variable: </p>

```<code>select set_config('max_parallel_workers_per_gather',
                   current_setting('max_parallel_workers'), false);
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I am trying to set max_parallel_workers_per_gather to be equal to the run time parameter max_parallel_workers in the current session only.

I want this to be applicable across numerous different machines so instead of hard-coding a value I want it to be directly relational to this other run time parameter.

Is there a way I can do this? I don't seem to be able to create a variable and set it to be the value of max_parallel_workers like such:

\set test_var max_parallel_workers;

Body:
You don't need a variable:

select set_config('max_parallel_workers_per_gather',
                   current_setting('max_parallel_workers'), false);


问:
All the possible combination and permutations with repetition on python
Essentially, I want to do

```<code>def get_all_possible(N)
    for i0 in range(N) :
        for i1 in range(N) :
            for i2 in range(N) :
             ... for iNm1 in range(N) : #Nm1 is N minus 1
                     yield [i0,i1,i2,i3,...,iNm1]
</code>```

and make a list of all the possible combination of number 0-N at each index and their permutations.
So when N=4 then there should be 4^4 possible combinations to be output.
This nested for loop is not efficient, and the code is not easily expandable to general N case.

答:
A solution that helps readability is itertools.product

```<code>import itertools
all_combs = list(itertools.product(range(4), repeat=4))
</code>```

Body:
Essentially, I want to do

def get_all_possible(N)
    for i0 in range(N) :
        for i1 in range(N) :
            for i2 in range(N) :
             ... for iNm1 in range(N) : #Nm1 is N minus 1
                     yield [i0,i1,i2,i3,...,iNm1]

and make a list of all the possible combination of number 0-N at each index and their permutations.
So when N=4 then there should be 4^4 possible combinations to be output.
This nested for loop is not efficient, and the code is not easily expandable to general N case.

Body:
A solution that helps readability is itertools.product

import itertools
all_combs = list(itertools.product(range(4), repeat=4))


问:
Loop results in wrong position/order
I need to calculate the results of a very simple formula (weighted average) that uses two variables (A and B) and two weight factors (A_prop and B_prop). The calculation is to be performed in a very large data set and the weight factors are stored in another data frame that I called here grid.

My approach was first to create repetitions of the data for each weight factors combination and then performed the calculations. Till that nothing strange. However then I thought about calculating values inside loop. Everything seemed to be in place, but then I checked the results of both approaches and results do not match. The results from the calculation inside loop are incorrect.

I know I should just get along and keep with the one that gives me the correct results, also because the number of lines are quite small. No big problem. However... I can just live with this. I'm about to tear my hair.

Can anyone explain me why the results are not the same? What's wrong with the loop calculation?
Also, in addition, if you have any suggestion on a more elegant it will be welcome.

(note: my first time using a reprex. Hope it is as it should)

```<code>>require(tidyverse)
>require(magicfor)
>require(readxl)
>require(reprex)

> dput(dt)
structure(list(X = 1:5, A = c(83.73, 50.4, 79.59, 62.96, 0),
    B = c(100, 86.8, 80.95, 81.48, 0), weight = c(201.6, 655,
    220.5, 280, 94.5), ind = c(733L, 26266L, 6877L, 8558L, 16361L
    )), class = "data.frame", row.names = c(NA, -5L))

> dput(grid)
structure(list(A_prop = c(0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8,
0.85, 0.9, 0.95, 1), B_prop = c(0.5, 0.45, 0.4, 0.35, 0.3, 0.25,
0.2, 0.15, 0.1, 0.05, 0), id = 1:11, tag = structure(1:11, .Label = c("Aprop_0.5",
"Aprop_0.55", "Aprop_0.6", "Aprop_0.65", "Aprop_0.7", "Aprop_0.75",
"Aprop_0.8", "Aprop_0.85", "Aprop_0.9", "Aprop_0.95", "Aprop_1"
), class = "factor")), class = "data.frame", row.names = c(NA,
-11L))

> foo<-function(data,i){
+   val<-(data$A*grid[i,1])+(data$B*grid[i,2])
+   return(val)
+ }

> magic_for(print, progress=FALSE,silent = TRUE)

> for(i in grid$id){
+
+   score<-(dt$A*grid[i,1])+(dt$B*grid[i,2])
+
+   weight=dt$weight
+   A<-dt$A
+   B<-dt$B
+
+   ind=dt$ind
+
+   print(score)
+   print(weight)
+   print(ind)
+   print(A)
+   print(B)
+ }

> rest<-magic_result_as_dataframe()

> magic_free()

> rest2<-left_join(rest,grid,by=c("i"="id"))%>%
+   arrange(ind,tag)%>%
+   mutate(score2=(A*A_prop)+(B*B_prop))

> head(rest2)
  i   score weight ind     A   B A_prop B_prop        tag  score2
1 1 91.8650  201.6 733 83.73 100   0.50   0.50  Aprop_0.5 91.8650
2 2 84.5435  201.6 733 83.73 100   0.55   0.45 Aprop_0.55 91.0515
3 3 86.1705  201.6 733 83.73 100   0.60   0.40  Aprop_0.6 90.2380
4 4 87.7975  201.6 733 83.73 100   0.65   0.35 Aprop_0.65 89.4245
5 5 89.4245  201.6 733 83.73 100   0.70   0.30  Aprop_0.7 88.6110
6 6 91.0515  201.6 733 83.73 100   0.75   0.25 Aprop_0.75 87.7975
</code>```

答:
The problem is actually your left_join and NOT the for loop. For future posts, I would recommend that you also provide a minimal(istic) example.

I will demonstrate what went wrong in your code.

Say, we have these data frames, which should be similar to your real-world data:

```<code>dt <- data.frame(
  A = c(2,3,4),
  B = c(20,30,40)
)

grid <- data.frame(
  A_prop = c(0.5, 0.6),
  B_prop = c(0.5, 0.4),
  id = c(1,2),
  tag = c("A_prop0.5", "A_prop0.6"))
</code>```

We expect the following outputs:

Expected Output dt[1,] & A_prop 0.5 and B_prop 0.5

2 * 0.5 + 20 * 0.5 #= 11

Expected Output dt[2,] & A_prop 0.5 and B_prop 0.5

3 * 0.5 + 30 * 0.5 #= 16.5

Expected Output dt[3,] & A_prop 0.5 and B_prop 0.5

4 * 0.5 + 40 * 0.5 #= 22

Expected Output dt[1,] & A_prop 0.6 and B_prop 0.4

2 * 0.6 + 20 * 0.4 #= 9.2

Expected Output dt[1,] & A_prop 0.6 and B_prop 0.4
 3 * 0.6 + 30 * 0.4 #= 13.8

Expected Output dt[1,] & A_prop 0.6 and B_prop 0.4

4 * 0.6 + 40 * 0.4 #= 18.4

I have never used the "magicfor" library, but the problem lies in your way of joining i and id.

I would write the for loop as follows:

```<code>l <- list()
for(i in grid$id){
  score<-(dt$A*grid[i,1])+(dt$B*grid[i,2])
  A<-dt$A
  B<-dt$B
  iteration <- rep(i, 3) # to keep track in which iteration the result was created.
  l[[i]] <- list(
    score = score,
    A = A,
    B = B,
    iteration = iteration
  )
}
</code>```

Now I bind the list to a data frame and do the left_join as you did in your example:

```<code>l <- bind_rows(l)

l_merged <- grid %>% left_join(l, by = c("id"="iteration")) %>%
  mutate(score2 = (A*A_prop + B*B_prop))
</code>```

The test that score and score2 are the same:

```<code>transmute(l_merged, identical = score == score2)

  identical
1      TRUE
2      TRUE
3      TRUE
4      TRUE
5      TRUE
6      TRUE
</code>```

Now to the actual problem

I have adapted your code a little bit. I have added the iteration number to the output.

```<code>magic_for(print, progress=FALSE,silent = TRUE)

for(i in grid$id){
  score<-(dt$A*grid[i,1])+(dt$B*grid[i,2])
  A<-dt$A
  B<-dt$B
  iteration <- rep(i, 3)
  print(score)
  print(A)
  print(B)
  print(iteration)
}

rest<-magic_result_as_dataframe()

magic_free()
</code>```

Now, if we look at the output and compare i and iteration, we can see that these are not identical. Therefore your left_join() has produced a confusing result.

```<code>rest %>% arrange(i)

  i score A  B iteration
1 1  11.0 2 20         1
2 1  22.0 4 40         1
3 1  13.8 3 30         2
4 2  16.5 3 30         1
5 2   9.2 2 20         2
6 2  18.4 4 40         2
</code>```

To finalise, we can test it:

```<code>grid %>% left_join(rest, by = c("id"="i")) %>% # using i for the join
  mutate(score2 = (A*A_prop + B*B_prop)) %>%
  transmute(identical = score == score2)

  identical
1      TRUE
2      TRUE
3     FALSE
4     FALSE
5      TRUE
6      TRUE
</code>```

The join with i does not produce the correct results.

But the join with iteration will:

```<code>grid %>% left_join(rest, by = c("id"="iteration")) %>% # using the "manually" produced iteration for the join
  mutate(score2 = (A*A_prop + B*B_prop)) %>%
  transmute(identical = score == score2)

  identical
1      TRUE
2      TRUE
3      TRUE
4      TRUE
5      TRUE
6      TRUE
</code>```

I am not sure why the i from "magicfor" is different from the manually created iteration. I certainly get your confusion...

Title: Loop results in wrong position/order

Body:
I need to calculate the results of a very simple formula (weighted average) that uses two variables (A and B) and two weight factors (A_prop and B_prop). The calculation is to be performed in a very large data set and the weight factors are stored in another data frame that I called here grid.

My approach was first to create repetitions of the data for each weight factors combination and then performed the calculations. Till that nothing strange. However then I thought about calculating values inside loop. Everything seemed to be in place, but then I checked the results of both approaches and results do not match. The results from the calculation inside loop are incorrect.

I know I should just get along and keep with the one that gives me the correct results, also because the number of lines are quite small. No big problem. However... I can just live with this. I'm about to tear my hair.

Can anyone explain me why the results are not the same? What's wrong with the loop calculation?
Also, in addition, if you have any suggestion on a more elegant it will be welcome.

(note: my first time using a reprex. Hope it is as it should)

>require(tidyverse)
>require(magicfor)
>require(readxl)
>require(reprex)

> dput(dt)
structure(list(X = 1:5, A = c(83.73, 50.4, 79.59, 62.96, 0),
    B = c(100, 86.8, 80.95, 81.48, 0), weight = c(201.6, 655,
    220.5, 280, 94.5), ind = c(733L, 26266L, 6877L, 8558L, 16361L
    )), class = "data.frame", row.names = c(NA, -5L))

> dput(grid)
structure(list(A_prop = c(0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8,
0.85, 0.9, 0.95, 1), B_prop = c(0.5, 0.45, 0.4, 0.35, 0.3, 0.25,
0.2, 0.15, 0.1, 0.05, 0), id = 1:11, tag = structure(1:11, .Label = c("Aprop_0.5",
"Aprop_0.55", "Aprop_0.6", "Aprop_0.65", "Aprop_0.7", "Aprop_0.75",
"Aprop_0.8", "Aprop_0.85", "Aprop_0.9", "Aprop_0.95", "Aprop_1"
), class = "factor")), class = "data.frame", row.names = c(NA,
-11L))

> foo<-function(data,i){
+   val<-(data$A*grid[i,1])+(data$B*grid[i,2])
+   return(val)
+ }

> magic_for(print, progress=FALSE,silent = TRUE)

> for(i in grid$id){
+
+   score<-(dt$A*grid[i,1])+(dt$B*grid[i,2])
+
+   weight=dt$weight
+   A<-dt$A
+   B<-dt$B
+
+   ind=dt$ind
+
+   print(score)
+   print(weight)
+   print(ind)
+   print(A)
+   print(B)
+ }

> rest<-magic_result_as_dataframe()

> magic_free()

> rest2<-left_join(rest,grid,by=c("i"="id"))%>%
+   arrange(ind,tag)%>%
+   mutate(score2=(A*A_prop)+(B*B_prop))

> head(rest2)
  i   score weight ind     A   B A_prop B_prop        tag  score2
1 1 91.8650  201.6 733 83.73 100   0.50   0.50  Aprop_0.5 91.8650
2 2 84.5435  201.6 733 83.73 100   0.55   0.45 Aprop_0.55 91.0515
3 3 86.1705  201.6 733 83.73 100   0.60   0.40  Aprop_0.6 90.2380
4 4 87.7975  201.6 733 83.73 100   0.65   0.35 Aprop_0.65 89.4245
5 5 89.4245  201.6 733 83.73 100   0.70   0.30  Aprop_0.7 88.6110
6 6 91.0515  201.6 733 83.73 100   0.75   0.25 Aprop_0.75 87.7975

Body:
The problem is actually your left_join and NOT the for loop. For future posts, I would recommend that you also provide a minimal(istic) example.

I will demonstrate what went wrong in your code.

Say, we have these data frames, which should be similar to your real-world data:

dt <- data.frame(
  A = c(2,3,4),
  B = c(20,30,40)
)

grid <- data.frame(
  A_prop = c(0.5, 0.6),
  B_prop = c(0.5, 0.4),
  id = c(1,2),
  tag = c("A_prop0.5", "A_prop0.6"))

We expect the following outputs:

Expected Output dt[1,] & A_prop 0.5 and B_prop 0.5

2 * 0.5 + 20 * 0.5 #= 11

Expected Output dt[2,] & A_prop 0.5 and B_prop 0.5

3 * 0.5 + 30 * 0.5 #= 16.5

Expected Output dt[3,] & A_prop 0.5 and B_prop 0.5

4 * 0.5 + 40 * 0.5 #= 22

Expected Output dt[1,] & A_prop 0.6 and B_prop 0.4

2 * 0.6 + 20 * 0.4 #= 9.2

Expected Output dt[1,] & A_prop 0.6 and B_prop 0.4
 3 * 0.6 + 30 * 0.4 #= 13.8

Expected Output dt[1,] & A_prop 0.6 and B_prop 0.4

4 * 0.6 + 40 * 0.4 #= 18.4

I have never used the "magicfor" library, but the problem lies in your way of joining i and id.

I would write the for loop as follows:

l <- list()
for(i in grid$id){
  score<-(dt$A*grid[i,1])+(dt$B*grid[i,2])
  A<-dt$A
  B<-dt$B
  iteration <- rep(i, 3) # to keep track in which iteration the result was created.
  l[[i]] <- list(
    score = score,
    A = A,
    B = B,
    iteration = iteration
  )
}

Now I bind the list to a data frame and do the left_join as you did in your example:

l <- bind_rows(l)

l_merged <- grid %>% left_join(l, by = c("id"="iteration")) %>%
  mutate(score2 = (A*A_prop + B*B_prop))

The test that score and score2 are the same:

transmute(l_merged, identical = score == score2)

  identical
1      TRUE
2      TRUE
3      TRUE
4      TRUE
5      TRUE
6      TRUE

Now to the actual problem

I have adapted your code a little bit. I have added the iteration number to the output.

magic_for(print, progress=FALSE,silent = TRUE)

for(i in grid$id){
  score<-(dt$A*grid[i,1])+(dt$B*grid[i,2])
  A<-dt$A
  B<-dt$B
  iteration <- rep(i, 3)
  print(score)
  print(A)
  print(B)
  print(iteration)
}

rest<-magic_result_as_dataframe()

magic_free()

Now, if we look at the output and compare i and iteration, we can see that these are not identical. Therefore your left_join() has produced a confusing result.

rest %>% arrange(i)

  i score A  B iteration
1 1  11.0 2 20         1
2 1  22.0 4 40         1
3 1  13.8 3 30         2
4 2  16.5 3 30         1
5 2   9.2 2 20         2
6 2  18.4 4 40         2

To finalise, we can test it:

grid %>% left_join(rest, by = c("id"="i")) %>% # using i for the join
  mutate(score2 = (A*A_prop + B*B_prop)) %>%
  transmute(identical = score == score2)

  identical
1      TRUE
2      TRUE
3     FALSE
4     FALSE
5      TRUE
6      TRUE

The join with i does not produce the correct results.

But the join with iteration will:

grid %>% left_join(rest, by = c("id"="iteration")) %>% # using the "manually" produced iteration for the join
  mutate(score2 = (A*A_prop + B*B_prop)) %>%
  transmute(identical = score == score2)

  identical
1      TRUE
2      TRUE
3      TRUE
4      TRUE
5      TRUE
6      TRUE

I am not sure why the i from "magicfor" is different from the manually created iteration. I certainly get your confusion...


问:
CK editor 4, google Translate also translate my MATHJAX formulas, even after no translate
Hello all i have a big issue here which is not getting resolved from a long time.

i am using ck editor and Mathjax plugin to add maths formula there like this

```<code><script src="https://cdn.ckeditor.com/4.13.1/standard-all/ckeditor.js"></script>

<textarea name="desc" class="form-control" id="richtext" placeholder="About this category."></textarea>

<script>

var richtext = document.getElementById('richtext');
CKEDITOR.replace('richtext', {
      on : {
            change: function ( evt )  {
            $(richtext).html(evt.editor.getData().replace(/(\r\n|\n|\r)/gm,"") ) ;
            }
        },
      extraPlugins: 'mathjax,colorbutton,font,justify,print,tableresize,uploadimage,uploadfile,pastefromword,liststyle,pagebreak',
      mathJaxLib: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-AMS_HTML',
      height: 320
    });

    if (CKEDITOR.env.ie && CKEDITOR.env.version == 8) {
      document.getElementById('ie8-warning').className = 'tip alert';
    }
                </script>
</code>```

everything works great till here.

now when i publish the data and use google translate to translate the data from english to hindi like this

```<code>require_once ('assets/vendor/autoload.php');
use \Statickidz\GoogleTranslate;
$source = 'en';
$target = 'hi';
$text = "<p>This is a test question. please do not translate this <span class="math-tex">\(x = {-b \pm \sqrt{b^2-4ac} \over 2a}\)</span>equation.</p>";
// i know there is an issue of double quotes in the class math-tex, but this is what i get from ckeditor. even if i replace the double quotes with single it does not does the job.

$tex4444t=str_replace(array("\r\n", "\r", "\n"), " ", $text);
$trans232 = new GoogleTranslate();
$results3 = $trans232->translate($source, $target, $tex4444t);
</code>```

i know there is an issue of double quotes in the class math-tex, but
  this is what i get from ckeditor. even if i replace the double quotes
  with single it does not does the job. i have also tried using notranslate class with math-tex it still does not work.

i have tried amny other alternatives but none works please help me solve this issue.

答:
This has come up in the MathJax issue tracker.  It appears that php google translate doesn't seem to handle the notranslate class.  You might file a bug with them.

In the meantime, the main issue with the math once it has been "translated" is that there are extra spaces after the backslashes. So perhaps doing a regular expression replacement that converts a backslash followed by a space to just a backslash would be all that is needed?

There is also another option suggested in the MathJax issue tracker that is more complicated, but would probably be the safest approach.

Body:
Hello all i have a big issue here which is not getting resolved from a long time.

i am using ck editor and Mathjax plugin to add maths formula there like this

<textarea name="desc" class="form-control" id="richtext" placeholder="About this category."></textarea>

everything works great till here.

now when i publish the data and use google translate to translate the data from english to hindi like this

require_once ('assets/vendor/autoload.php');
use \Statickidz\GoogleTranslate;
$source = 'en';
$target = 'hi';
$text = "
This is a test question. please do not translate this \(x = {-b \pm \sqrt{b^2-4ac} \over 2a}\)equation.
";
// i know there is an issue of double quotes in the class math-tex, but this is what i get from ckeditor. even if i replace the double quotes with single it does not does the job.

$tex4444t=str_replace(array("\r\n", "\r", "\n"), " ", $text);
$trans232 = new GoogleTranslate();
$results3 = $trans232->translate($source, $target, $tex4444t);

i know there is an issue of double quotes in the class math-tex, but
  this is what i get from ckeditor. even if i replace the double quotes
  with single it does not does the job. i have also tried using notranslate class with math-tex it still does not work.

i have tried amny other alternatives but none works please help me solve this issue.


问:
The given value of type String from the data source cannot be converted to type nvarchar of the specified target column
I've tested it with and without explicit conversion in the datatable columns, but it kept throwing me the exception System.InvalidOperationException.

FYI, those columns with typeof(string) are all nvarchar in my database. I'm passing in a List called test which is of a user-defined type.

I wasn't going to use sqlbulkcopy initially, but ever since porting over to azure database, I need a faster insertion query.

Any advice would be appreciated.

var dt = new DataTable();
dt.Columns.Add("LinkID", typeof(string));
dt.Columns.Add("RoadName", typeof(string));
dt.Columns.Add("RoadCategory", typeof(string));
dt.Columns.Add("SpeedBand");
dt.Columns.Add("MinimumSpeed", typeof(string));
dt.Columns.Add("MaximumSpeed", typeof(string));
dt.Columns.Add("StartLatitude");
dt.Columns.Add("StartLongitude");
dt.Columns.Add("EndLatitude");
dt.Columns.Add("EndLongitude");
dt.Columns.Add("Distance", typeof(string));

for (int i = 0; i < test.Count; i++)
{
    dt.Rows.Add(test[i].LinkID, test[i].RoadName, test[i].RoadCategory,
       test[i].SpeedBand, test[i].MinimumSpeed, test[i].MaximumSpeed,
       test[i].StartLatitude, test[i].StartLongitude, test[i].EndLatitude,
       test[i].EndLongitude, test[i].Distance);
}

string sqlConnectionString = "//secret";

using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
    try
    {
        conn.Open();
    }
    catch (Exception e)
    {
        Debug.WriteLine(e);
    }

    using (var sqlBulk = new SqlBulkCopy(conn))
    {
        //sqlBulk.BatchSize = 1000;
        sqlBulk.DestinationTableName = "dbo.TrafficSpeedBands";

        try
        {
            // Write from the source to the destination.
            sqlBulk.WriteToServer(dt);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }
}
```

答:
Your problem lies here:

```<code>var dt = new DataTable();
//...
dt.Columns.Add("SpeedBand");
//...
dt.Columns.Add("StartLatitude");
dt.Columns.Add("StartLongitude");
dt.Columns.Add("EndLatitude");
dt.Columns.Add("EndLongitude");
</code>```

By default, the method Add(string columnName)  will add a column of type string. You therefore have a type mismatch with the underlying db table and the bulk copy fails. Read here for more details.

Your solution with DataAdapter works because the adapter reads the schema of the underyling table and sets up the DataTable with compatible types for you.

Body:
Your problem lies here:

var dt = new DataTable();
//...
dt.Columns.Add("SpeedBand");
//...
dt.Columns.Add("StartLatitude");
dt.Columns.Add("StartLongitude");
dt.Columns.Add("EndLatitude");
dt.Columns.Add("EndLongitude");

By default, the method Add(string columnName)  will add a column of type string. You therefore have a type mismatch with the underlying db table and the bulk copy fails. Read here for more details.

Your solution with DataAdapter works because the adapter reads the schema of the underyling table and sets up the DataTable with compatible types for you.


问:
HTML Content fit in UIWebview without zooming out
I am making use of the UIWebView to render some HTML. However, although the width of my webview is 320 my HTML is still shown full width and can be scrolled horizontally.

I want to achieve the same thing the native mail application achieves which is it fits all content within that width without zooming out - how does the native mail application render HTML like this?

Update

I thought making use of the viewport meta tag will help, but I couldn't get this to work.

This is what is happening:

As you can see the content does not fit the device width. I've tried so many combinations of viewport meta tag. The below is an example of what happens when I try Martins suggestion.

Original HTML is can be found here.

The way this HTML is rendered by the native mail application is like so.

答: i solved the issue by unticking "scales page to fit"

ContentLicense: CC BY-SA 3.0


问:
Unit testing a specific MongoDb FilterDefintion in C# with Moq
Trying to unit test the following MongoDb update function in C#.

```<code>var update = Builders<InvestorMongoDao>.Update
      .Set(x => x.EmailAddress, command.EmailAddress);

await this.myDatabase.Users
.UpdateOneAsync(x => x.UserId == userId), update)
.ConfigureAwait(false);
</code>```

I can easily check whether this function is called with a generic filter:

```<code>this.mockCollection
    .Verify(x => x.UpdateOneAsync(It.IsAny<FilterDefinition<MyDao>>(),
        It.IsAny<UpdateDefinition<MyDao>>(),
        It.IsAny<UpdateOptions>(),
        It.IsAny<CancellationToken>()));
</code>```

However, I want to try and verify that it's being called with the expected parameter. I cannot seem to find a way to extract the parameter I want to check from FilterDefinition. I have tried this:

```<code>var foo = Builders<MyDao>.Filter.Eq("UserId", expectedUserId);
this.mockCollection
    .Verify(x => x.UpdateOneAsync(It.Is<FilterDefinition<MyDao>>(a => a == foo),
        It.IsAny<UpdateDefinition<MyDao>>(),
        It.IsAny<UpdateOptions>(),
        It.IsAny<CancellationToken>()));
</code>```

But the test states the invocation is not performed. What am I doing wrong?

答:
It appears you can approximate what's needed here by using Render.</p>

```<code>var serializerRegistry = BsonSerializer.SerializerRegistry;
var documentSerializer = serializerRegistry.GetSerializer<MyDao>();
var expectedFilter = Builders<MyDao>.Filter.Eq("UserId", existingInvestor2.InvestorId);

this.mockCollection
    .Verify(x => x.UpdateOneAsync(It.Is<FilterDefinition<MyDao>>(a => a.Render(documentSerializer, serializerRegistry) == expectedFilter.Render(documentSerializer, serializerRegistry)),
        It.IsAny<UpdateDefinition<MyDao>>(),
        It.IsAny<UpdateOptions>(),
        It.IsAny<CancellationToken>()));
</code>```

Body:
Trying to unit test the following MongoDb update function in C#.

var update = Builders<InvestorMongoDao>.Update
      .Set(x => x.EmailAddress, command.EmailAddress);

await this.myDatabase.Users
.UpdateOneAsync(x => x.UserId == userId), update)
.ConfigureAwait(false);

I can easily check whether this function is called with a generic filter:

this.mockCollection
    .Verify(x => x.UpdateOneAsync(It.IsAny<FilterDefinition<MyDao>>(),
        It.IsAny<UpdateDefinition<MyDao>>(),
        It.IsAny<UpdateOptions>(),
        It.IsAny<CancellationToken>()));

However, I want to try and verify that it's being called with the expected parameter. I cannot seem to find a way to extract the parameter I want to check from FilterDefinition. I have tried this:

var foo = Builders<MyDao>.Filter.Eq("UserId", expectedUserId);
this.mockCollection
    .Verify(x => x.UpdateOneAsync(It.Is<FilterDefinition<MyDao>>(a => a == foo),
        It.IsAny<UpdateDefinition<MyDao>>(),
        It.IsAny<UpdateOptions>(),
        It.IsAny<CancellationToken>()));

But the test states the invocation is not performed. What am I doing wrong?

Body:
It appears you can approximate what's needed here by using Render.

var serializerRegistry = BsonSerializer.SerializerRegistry;
var documentSerializer = serializerRegistry.GetSerializer<MyDao>();
var expectedFilter = Builders<MyDao>.Filter.Eq("UserId", existingInvestor2.InvestorId);

this.mockCollection
    .Verify(x => x.UpdateOneAsync(It.Is<FilterDefinition<MyDao>>(a => a.Render(documentSerializer, serializerRegistry) == expectedFilter.Render(documentSerializer, serializerRegistry)),
        It.IsAny<UpdateDefinition<MyDao>>(),
        It.IsAny<UpdateOptions>(),
        It.IsAny<CancellationToken>()));


问:
System.MissingMethodException - 3.5 SP1 versioning hell
After deploying an ASP.net webservice to my production server i got this exception:

System.MissingMethodException

Method not found: 'Boolean
  System.Threading.WaitHandle.WaitOne(Int32)'

The MSDN documentation states:

Version Information
  .NET Framework
  Supported in: 3.5 SP1, 3.0 SP2, 2.0 SP2

so the reason of this error is that my server was not updated to the latest service pack.

The question is:

Why does the code start? IMO if the target framework version is different the app should not start at all.

How can I assure that my code can run on the target machine framework version before JIT?

This is crazy. I think Microsoft should take versioning issues more seriously.

答:
The same happended to me with 1.1 and 1.1 SP1 a long time ago...
I guess there's not a good solution since the assemblies have the same version, you can try to validate it by hand reading the .net installed version or just install the last service packs in all your dev and production machines.</p>

OwnerDisplayName: Luca Martinetti

OwnerDisplayName: diegojancic

ContentLicense: CC BY-SA 2.5


问:
Desperately seeking the answer to my pointer problem
I have been working on a college C assignment, and have been trying to make sense of a bug I seem to be having with my code. Basically, it seems like something is wrong with my pointers (and or memory allocation).

This assignment is primarily about linked lists, so the structs contain pointers to the next element in the list. Obviously, to traverse the list until I find that the current element has a NULL pointer to the next element (and then I change that to be the pointer to the 'new' element I want to add.

The problem I have though, is for some reason my code seems to be completely screwing with my memory pointers, because they're getting garbled somehow.  They seem fine for moment but very soon go rubbish.

Here is what my watches in XCode's debugger are showing me:

The first circle shows me the values as the first element in the list, which as far as I can tell are initially set correctly, and should be "C0001\0". The second circle shows the current->nextCategory pointer which should be NULL (0x0) but instead show that weird memory address (look at the size of it!). I assume that these problems are related, but as I am new to C, I don't know how or why.

In either case, when I check current->nextCategory != NULL in my while statement, it throws EXC_BAD_ACCESS:

I've spent the past few hours pulling my hair out becasue I cannot work out what the heck is happening to my program.  Am I doing something wrong with my pointers, or using malloc() improperly?

Here is the relevant part of my program:

```<code>/****************************************************************************
* Initialises the system to a safe empty state.
****************************************************************************/
void systemInit(GJCType* menu)
{
   if (menu == NULL) {
      fprintf(stderr, "can't initialize system with a null menu pointer.\n");
      exit(EXIT_FAILURE);
   }
   menu->headCategory = NULL;
   menu->numCategories = 0;
}

/****************************************************************************
* Loads all data into the system.
****************************************************************************/
int loadData(GJCType* menu, char* menuFile, char* submenuFile)
{
   FILE *fp;
   size_t len;
   char *line;
   char *buffer;
   CategoryTypePtr category_p;
   ItemTypePtr item_p;
   char *catId;

   if (menu == NULL)
      return FALSE;

   fp = fopen(menuFile, "r");
   if(fp == NULL) {
      fprintf(stderr, "can't open %s\n", menuFile);
      return FALSE;
    }

   buffer = malloc(MAX_BUFFER_SIZE);
   len = MAX_BUFFER_SIZE;
   catId = malloc(ID_LEN + 1);

   while((buffer = fgetln(fp, &len))) {
      line = strtok(buffer, "\n\0");
      category_p = malloc(sizeof(CategoryTypePtr));

      if (!tokenizeCategory(line, category_p)) {
         fprintf(stderr, "can't tokenize category:> %s\n", line);
         free(category_p);
         category_p = NULL;
         free(buffer);
         free(catId);
         return FALSE;
      }
      pushCategory(menu, category_p);
      free(category_p);
      category_p = NULL;
   }

   fp = fopen(submenuFile, "r");
   if(fp == NULL) {
      fprintf(stderr, "can't open %s\n", submenuFile);
      return FALSE;
    }

   while((buffer = fgetln(fp, &len))) {
      line = strtok(buffer, "\n\0");
      item_p = malloc(sizeof(ItemTypePtr));

      if (!tokenizeItem(line, item_p, catId)) {
         fprintf(stderr, "can't tokenize item:> %s\n", line);
         free(item_p);
         item_p = NULL;
         free(buffer);
         free(catId);
         return FALSE;
      }
      category_p = findCategory(menu, catId);
      pushItem(category_p, item_p);
      free(item_p);
      item_p = NULL;
   }

   free(buffer);
   free(catId);
   return TRUE;
}

void pushItem(CategoryTypePtr category, ItemTypePtr item)
{
   ItemTypePtr current;
   ItemTypePtr new;

   if ((new = malloc(sizeof(ItemTypePtr))) == NULL) {
      fprintf(stderr, "can't malloc enough memory for new item pointer.\n");
      exit(EXIT_FAILURE);
   }

   *new = *item;

   if (category->headItem == NULL) {
      category->headItem = new;
   } else {
      current = category->headItem;
      while (current->nextItem != NULL) {
         current = current->nextItem;
      }
      current->nextItem = new;

   }
   category->numItems++;
}

void pushCategory(GJCType* menu, CategoryTypePtr category)
{
   CategoryTypePtr current;
   CategoryTypePtr new;

   if ((new = malloc(sizeof(CategoryTypePtr))) == NULL) {
      fprintf(stderr, "can't malloc enough memory for new category pointer.\n");
      exit(EXIT_FAILURE);
   }

   *new = *category;

   if (menu->headCategory == NULL) {
      menu->headCategory = new;
   } else {
      current = menu->headCategory;
      while (current->nextCategory != NULL) {
         current = current->nextCategory;
      }
      current->nextCategory = new;
   }
   menu->numCategories++;
}

CategoryTypePtr findCategory(GJCType* menu, char* id)
{
   CategoryTypePtr current;

   current = menu->headCategory;
   while (current != NULL) {
      if (!strcmp(current->categoryID, id))
         return current;
      current = current->nextCategory;
   }
   return NULL;
}

/* This function takes the character delimited string and converts it into
 * a category structure at the location of the category pointer supplied.
 */
int tokenizeCategory(char *data, CategoryTypePtr category)
{
   char* buffer;

   if (category == NULL || strlen(data) < 1)
      return FALSE;

   buffer = malloc(MAX_BUFFER_SIZE);
   strcpy(buffer, data);
   strcpy(category->categoryID, strtok(buffer, "|\n"));
   category->drinkType = *(strtok(NULL, "|\n"));
   strcpy(category->categoryName, strtok(NULL, "|\n"));
   strcpy(category->categoryDescription, strtok(NULL, "|\n"));
   category->numItems = 0;
   category->nextCategory = NULL;
   category->headItem = NULL;
   free(buffer);
   return TRUE;
}

/* This function takes the character delimited string and converts it into
 * an item structure at the location of the item pointer supplied.
 */
int tokenizeItem(char *data, ItemTypePtr item, char* categoryId)
{
   char* buffer;
   int i;

   if (item == NULL || strlen(data) < 1)
      return FALSE;

   buffer = malloc(MAX_BUFFER_SIZE);
   strcpy(buffer, data);
   strcpy(item->itemID, strtok(buffer, "|\n"));
   strcpy(categoryId, strtok(NULL, "|\n"));
   strcat(categoryId, "\0");
   strcpy(item->itemName, strtok(NULL, "|\n"));
   for (i = 0; i < NUM_PRICES; i++)
      sscanf(strtok(NULL, "|\n"),"%d.%d",&(item->prices[i].dollars),&(item->prices[i].cents));
   strcpy(item->itemDescription, strtok(NULL, "|\n"));
   item->nextItem = NULL;
   free(buffer);
   return TRUE;
}
</code>```

Header definitions:

```<code>/* System-wide constants. */
#define ID_LEN 5
#define MIN_NAME_LEN 1
#define MAX_NAME_LEN 25
#define MIN_DESC_LEN 1
#define MAX_DESC_LEN 250
#define NUM_PRICES 3
#define HOT 'H'
#define COLD 'C'
#define FALSE 0
#define TRUE 1
#define MAX_BUFFER_SIZE 1024

typedef struct category* CategoryTypePtr;
typedef struct item* ItemTypePtr;

/* Structure definitions. */
typedef struct price
{
   unsigned dollars;
   unsigned cents;
} PriceType;

typedef struct item
{
   char itemID[ID_LEN + 1];
   char itemName[MAX_NAME_LEN + 1];
   PriceType prices[NUM_PRICES];
   char itemDescription[MAX_DESC_LEN + 1];
   ItemTypePtr nextItem;
} ItemType;

typedef struct category
{
   char categoryID[ID_LEN + 1];
   char categoryName[MAX_NAME_LEN + 1];
   char drinkType;      /* (H)ot or (C)old. */
   char categoryDescription[MAX_DESC_LEN + 1];
   CategoryTypePtr nextCategory;
   ItemTypePtr headItem;
   unsigned numItems;
} CategoryType;

typedef struct gjc
{
   CategoryTypePtr headCategory;
   unsigned numCategories;
} GJCType;
</code>```

答:
It looks to me like you're not allocating memory properly.

```<code>category_p = malloc(sizeof(CategoryTypePtr));
</code>```

This only allocates enough memory to store a single address, not an entire category structure. Try something like:

```<code>category_p = malloc(sizeof(CategoryType));
</code>```

Body:
I have been working on a college C assignment, and have been trying to make sense of a bug I seem to be having with my code. Basically, it seems like something is wrong with my pointers (and or memory allocation).

This assignment is primarily about linked lists, so the structs contain pointers to the next element in the list. Obviously, to traverse the list until I find that the current element has a NULL pointer to the next element (and then I change that to be the pointer to the 'new' element I want to add.

The problem I have though, is for some reason my code seems to be completely screwing with my memory pointers, because they're getting garbled somehow.  They seem fine for moment but very soon go rubbish.

Here is what my watches in XCode's debugger are showing me:

The first circle shows me the values as the first element in the list, which as far as I can tell are initially set correctly, and should be "C0001\0". The second circle shows the current->nextCategory pointer which should be NULL (0x0) but instead show that weird memory address (look at the size of it!). I assume that these problems are related, but as I am new to C, I don't know how or why.

In either case, when I check current->nextCategory != NULL in my while statement, it throws EXC_BAD_ACCESS:

I've spent the past few hours pulling my hair out becasue I cannot work out what the heck is happening to my program.  Am I doing something wrong with my pointers, or using malloc() improperly?

Here is the relevant part of my program:

/****************************************************************************
* Initialises the system to a safe empty state.
****************************************************************************/
void systemInit(GJCType* menu)
{
   if (menu == NULL) {
      fprintf(stderr, "can't initialize system with a null menu pointer.\n");
      exit(EXIT_FAILURE);
   }
   menu->headCategory = NULL;
   menu->numCategories = 0;
}

/****************************************************************************
* Loads all data into the system.
****************************************************************************/
int loadData(GJCType* menu, char* menuFile, char* submenuFile)
{
   FILE *fp;
   size_t len;
   char *line;
   char *buffer;
   CategoryTypePtr category_p;
   ItemTypePtr item_p;
   char *catId;

   if (menu == NULL)
      return FALSE;

   fp = fopen(menuFile, "r");
   if(fp == NULL) {
      fprintf(stderr, "can't open %s\n", menuFile);
      return FALSE;
    }

   buffer = malloc(MAX_BUFFER_SIZE);
   len = MAX_BUFFER_SIZE;
   catId = malloc(ID_LEN + 1);

   while((buffer = fgetln(fp, &len))) {
      line = strtok(buffer, "\n\0");
      category_p = malloc(sizeof(CategoryTypePtr));

      if (!tokenizeCategory(line, category_p)) {
         fprintf(stderr, "can't tokenize category:> %s\n", line);
         free(category_p);
         category_p = NULL;
         free(buffer);
         free(catId);
         return FALSE;
      }
      pushCategory(menu, category_p);
      free(category_p);
      category_p = NULL;
   }

   fp = fopen(submenuFile, "r");
   if(fp == NULL) {
      fprintf(stderr, "can't open %s\n", submenuFile);
      return FALSE;
    }

   while((buffer = fgetln(fp, &len))) {
      line = strtok(buffer, "\n\0");
      item_p = malloc(sizeof(ItemTypePtr));

      if (!tokenizeItem(line, item_p, catId)) {
         fprintf(stderr, "can't tokenize item:> %s\n", line);
         free(item_p);
         item_p = NULL;
         free(buffer);
         free(catId);
         return FALSE;
      }
      category_p = findCategory(menu, catId);
      pushItem(category_p, item_p);
      free(item_p);
      item_p = NULL;
   }

   free(buffer);
   free(catId);
   return TRUE;
}

void pushItem(CategoryTypePtr category, ItemTypePtr item)
{
   ItemTypePtr current;
   ItemTypePtr new;

   if ((new = malloc(sizeof(ItemTypePtr))) == NULL) {
      fprintf(stderr, "can't malloc enough memory for new item pointer.\n");
      exit(EXIT_FAILURE);
   }

   *new = *item;

   if (category->headItem == NULL) {
      category->headItem = new;
   } else {
      current = category->headItem;
      while (current->nextItem != NULL) {
         current = current->nextItem;
      }
      current->nextItem = new;

   }
   category->numItems++;
}

void pushCategory(GJCType* menu, CategoryTypePtr category)
{
   CategoryTypePtr current;
   CategoryTypePtr new;

   if ((new = malloc(sizeof(CategoryTypePtr))) == NULL) {
      fprintf(stderr, "can't malloc enough memory for new category pointer.\n");
      exit(EXIT_FAILURE);
   }

   *new = *category;

   if (menu->headCategory == NULL) {
      menu->headCategory = new;
   } else {
      current = menu->headCategory;
      while (current->nextCategory != NULL) {
         current = current->nextCategory;
      }
      current->nextCategory = new;
   }
   menu->numCategories++;
}

CategoryTypePtr findCategory(GJCType* menu, char* id)
{
   CategoryTypePtr current;

   current = menu->headCategory;
   while (current != NULL) {
      if (!strcmp(current->categoryID, id))
         return current;
      current = current->nextCategory;
   }
   return NULL;
}

/* This function takes the character delimited string and converts it into
 * a category structure at the location of the category pointer supplied.
 */
int tokenizeCategory(char *data, CategoryTypePtr category)
{
   char* buffer;

   if (category == NULL || strlen(data) < 1)
      return FALSE;

   buffer = malloc(MAX_BUFFER_SIZE);
   strcpy(buffer, data);
   strcpy(category->categoryID, strtok(buffer, "|\n"));
   category->drinkType = *(strtok(NULL, "|\n"));
   strcpy(category->categoryName, strtok(NULL, "|\n"));
   strcpy(category->categoryDescription, strtok(NULL, "|\n"));
   category->numItems = 0;
   category->nextCategory = NULL;
   category->headItem = NULL;
   free(buffer);
   return TRUE;
}

/* This function takes the character delimited string and converts it into
 * an item structure at the location of the item pointer supplied.
 */
int tokenizeItem(char *data, ItemTypePtr item, char* categoryId)
{
   char* buffer;
   int i;

   if (item == NULL || strlen(data) < 1)
      return FALSE;

   buffer = malloc(MAX_BUFFER_SIZE);
   strcpy(buffer, data);
   strcpy(item->itemID, strtok(buffer, "|\n"));
   strcpy(categoryId, strtok(NULL, "|\n"));
   strcat(categoryId, "\0");
   strcpy(item->itemName, strtok(NULL, "|\n"));
   for (i = 0; i < NUM_PRICES; i++)
      sscanf(strtok(NULL, "|\n"),"%d.%d",&(item->prices[i].dollars),&(item->prices[i].cents));
   strcpy(item->itemDescription, strtok(NULL, "|\n"));
   item->nextItem = NULL;
   free(buffer);
   return TRUE;
}

Header definitions:

/* System-wide constants. */
#define ID_LEN 5
#define MIN_NAME_LEN 1
#define MAX_NAME_LEN 25
#define MIN_DESC_LEN 1
#define MAX_DESC_LEN 250
#define NUM_PRICES 3
#define HOT 'H'
#define COLD 'C'
#define FALSE 0
#define TRUE 1
#define MAX_BUFFER_SIZE 1024

typedef struct category* CategoryTypePtr;
typedef struct item* ItemTypePtr;

/* Structure definitions. */
typedef struct price
{
   unsigned dollars;
   unsigned cents;
} PriceType;

typedef struct item
{
   char itemID[ID_LEN + 1];
   char itemName[MAX_NAME_LEN + 1];
   PriceType prices[NUM_PRICES];
   char itemDescription[MAX_DESC_LEN + 1];
   ItemTypePtr nextItem;
} ItemType;

typedef struct category
{
   char categoryID[ID_LEN + 1];
   char categoryName[MAX_NAME_LEN + 1];
   char drinkType;      /* (H)ot or (C)old. */
   char categoryDescription[MAX_DESC_LEN + 1];
   CategoryTypePtr nextCategory;
   ItemTypePtr headItem;
   unsigned numItems;
} CategoryType;

typedef struct gjc
{
   CategoryTypePtr headCategory;
   unsigned numCategories;
} GJCType;

Body:
It looks to me like you're not allocating memory properly.

category_p = malloc(sizeof(CategoryTypePtr));

This only allocates enough memory to store a single address, not an entire category structure. Try something like:

category_p = malloc(sizeof(CategoryType));


问:
Date format in Substring
I need help, in assign I have

out_Date = Split(Question, "Date: ")(1).Split(Environment.NewLine.ToCharArray(), StringSplitOptions.None)(0)
```

, but in WriteLine I have the value of the Date argument as 11 feb 2020 04:54:52- 0500 (EST).

How can I set expression only for date like this 02/11/2020?

答:
Your question is not clear at all.
If I understand correctly, you want to format the date output.

You can use DateTime Format.

Title: Date format in Substring

Body:
I need help, in assign I have

out_Date = Split(Question, "Date: ")(1).Split(Environment.NewLine.ToCharArray(), StringSplitOptions.None)(0)

, but in WriteLine I have the value of the Date argument as 11 feb 2020 04:54:52- 0500 (EST).

How can I set expression only for date like this 02/11/2020?


问:
Column of lists, convert list to string as a new column
I have a dataframe with a column of lists which can be created with:

```<code>import pandas as pd
lists={1:[[1,2,12,6,'ABC']],2:[[1000,4,'z','a']]}
#create test dataframe
df=pd.DataFrame.from_dict(lists,orient='index')
df=df.rename(columns={0:'lists'})
</code>```

The dataframe df looks like:

```<code>                lists
1  [1, 2, 12, 6, ABC]
2     [1000, 4, z, a]
</code>```

I need to create a new column called 'liststring' which takes every element of each list in lists and creates a string with each element separated by commas.  The elements of each list can be int, float, or string.  So the result would be:

```<code>                lists    liststring
1  [1, 2, 12, 6, ABC]  1,2,12,6,ABC
2     [1000, 4, z, a]    1000,4,z,a
</code>```

I have tried various things, including from How do I convert a list in a Pandas DF into a string?:

```<code>df['liststring']=df.lists.apply(lambda x: ', '.join(str(x)))
</code>```

but unfortunately the result takes every character and seperates by comma:

```<code>                lists                                         liststring
1  [1, 2, 12, 6, ABC]  [, 1, ,,  , 2, ,,  , 1, 2, ,,  , 6, ,,  , ', A...
2     [1000, 4, z, a]  [, 1, 0, 0, 0, ,,  , 4, ,,  , ', z, ', ,,  , '...
</code>```

答:
The previous explanations are well and quite straight forward. But let say if you want to convert multiple columns to string separated format. Without going into individual columns you can apply the following function to dataframe and if any column is a list then it will convert to string format.

```<code>def list2Str(lst):
    if type(lst) is list: # apply conversion to list columns
        return";".join(map(str, lst))
    else:
        return lst

df.apply(lambda x: [list2Str(i) for i in x])
</code>```

of course, if you want to apply only to certain columns then you can select
the subset of columns as follows

```<code>df[['col1',...,'col2']].apply(lambda x: [list2Str(i) for i in x])
</code>```

Body:
I have a dataframe with a column of lists which can be created with:

import pandas as pd
lists={1:[[1,2,12,6,'ABC']],2:[[1000,4,'z','a']]}
#create test dataframe
df=pd.DataFrame.from_dict(lists,orient='index')
df=df.rename(columns={0:'lists'})

The dataframe df looks like:

                lists
1  [1, 2, 12, 6, ABC]
2     [1000, 4, z, a]

I need to create a new column called 'liststring' which takes every element of each list in lists and creates a string with each element separated by commas.  The elements of each list can be int, float, or string.  So the result would be:

                lists    liststring
1  [1, 2, 12, 6, ABC]  1,2,12,6,ABC
2     [1000, 4, z, a]    1000,4,z,a

I have tried various things, including from How do I convert a list in a Pandas DF into a string?:

df['liststring']=df.lists.apply(lambda x: ', '.join(str(x)))

but unfortunately the result takes every character and seperates by comma:

                lists                                         liststring
1  [1, 2, 12, 6, ABC]  [, 1, ,,  , 2, ,,  , 1, 2, ,,  , 6, ,,  , ', A...
2     [1000, 4, z, a]  [, 1, 0, 0, 0, ,,  , 4, ,,  , ', z, ', ,,  , '...

Body:
The previous explanations are well and quite straight forward. But let say if you want to convert multiple columns to string separated format. Without going into individual columns you can apply the following function to dataframe and if any column is a list then it will convert to string format.

def list2Str(lst):
    if type(lst) is list: # apply conversion to list columns
        return";".join(map(str, lst))
    else:
        return lst

df.apply(lambda x: [list2Str(i) for i in x])

of course, if you want to apply only to certain columns then you can select
the subset of columns as follows

df[['col1',...,'col2']].apply(lambda x: [list2Str(i) for i in x])