Jump to content

Images are not saved permanently with ajax upload

Recommended Posts

Hi :)

I'm using a lightly modified Version of ProcessSlider on my PW page (3.0.42).

But I'm having a problem with the file upload. It's using Ajax File upload to upload images, which is working fine at first, but the images are only uploaded temporarily (creation date 01.01.1970) when an image is uploaded and saved. When pressing the "save"-Button, this does not change. I'm guessing it's due to changes from PW 2 to 3?

This is the js that is calling the iframe upload, I think :)

I don't know what to do to amke it save correctly. Anybody who can give me a hint?

 * ProcessWire iFrameImagePicker plugin
 * Light verision of InputfieldCKEditor/plugins/pwimage/plugin.js
 * @return callback(src, width, height)

function loadIframeImagePicker(page_id, callback) {

    var page_id = page_id;//$("#Inputfield_id").val();
    var edit_page_id = page_id;
    var file = '';
    var imgWidth = 0;
    var imgHeight = 0;
    var imgDescription = '';
    var imgLink = '';
    var hidpi = false;

    var modalUri = config.urls.admin + 'page/image/';
    var queryString = '?id=' + page_id + '&edit_page_id=' + edit_page_id + '&modal=1';

    if(file.length) queryString += "&file=" + file;
    if(imgWidth) queryString += "&width=" + imgWidth;
    if(imgHeight) queryString += "&height=" + imgHeight;

    queryString += '&hidpi=' + (hidpi ? '1' : '0');

    if(imgDescription && imgDescription.length) {
        queryString += "&description=" + encodeURIComponent(imgDescription);

    if(imgLink && imgLink.length) queryString += "&link=" + encodeURIComponent(imgLink);
    queryString += ("&winwidth=" + ($(window).width() - 30));

    // create iframe dialog box
    var modalSettings = {
        title: "<i class='fa fa-fw fa-folder-open'></i> " + "Select Image",
        open: function() {


    var $iframe = pwModalWindow(modalUri + queryString, modalSettings, 'large');

    $iframe.load(function() {

        // when iframe loads, pull the contents into $i
        var $i = $iframe.contents();

        if($i.find("#selected_image").size() > 0) {
            // if there is a #selected_image element on the page...

            var buttons = [
                    html: "<i class='fa fa-camera'></i> " + "Insert This Image",
                    click:  function() {

                        var $i = $iframe.contents();
                        var $img = $("#selected_image", $i);

                        $iframe.setTitle("<i class='fa fa-fw fa-spin fa-spinner'></i> " + "Saving Image");

                        var width = $img.attr('width');
                        if(!width) width = $img.width();
                        var height = $img.attr('height');
                        if(!height) height = $img.height();
                        var file = $img.attr('src');
                        var page_id = $("#page_id", $i).val();
                        var hidpi = $("#selected_image_hidpi", $i).is(":checked") ? 1 : 0;
                        var rotate = parseInt($("#selected_image_rotate", $i).val());
                        file = file.substring(file.lastIndexOf('/')+1);

                        var resizeURL = modalUri + 'resize?id=' + page_id +
                            '&file=' + file +
                            '&width=' + width +
                            '&height=' + height +
                            '&hidpi=' + hidpi;

                        if(rotate) resizeURL += '&rotate=' + rotate;
                        if($img.hasClass('flip_horizontal')) resizeURL += '&flip=h';
                        else if($img.hasClass('flip_vertical')) resizeURL += '&flip=v';
                        $.get(resizeURL, function(data) {
                            var $div = $("<div></div>").html(data);
                            var src = $div.find('#selected_image').attr('src');

                            callback(src, width, height);


                }, {

                    html: "<i class='fa fa-folder-open'></i> " + "Select Another Image",
                    'class': 'ui-priority-secondary',
                    click: function() {
                        var $i = $iframe.contents();
                        var page_id = $("#page_id", $i).val();
                        $iframe.attr('src', modalUri + '?id=' + page_id + '&modal=1');
                }, {
                    html: "<i class='fa fa-times-circle'></i> " + "Cancel",
                    'class': 'ui-priority-secondary',
                    click: function() { $iframe.dialog("close"); }


            $iframe.setTitle("<i class='fa fa-fw fa-picture-o'></i> " + $i.find('title').html());

        } else {
            var buttons = [];
            $("button.pw-modal-button, button[type=submit]:visible", $i).each(function() {
                var $button = $(this);
                var button = {
                    html: $button.html(),
                    click: function() {
                if(!$button.hasClass('pw-modal-button-visible')) $button.hide();
            var cancelButton = {
                html: "<i class='fa fa-times-circle'></i> " + "Cancel",
                'class': "ui-priority-secondary",
                click: function() { $iframe.dialog("close"); }


  • Like 1
Link to comment
Share on other sites

So, I compared this file with /wire/modules/Inputfield/InputfieldCKEditor/plugins/pwimage/plugin.js and couldn't find any discrepancies.

So maybe the problem lies within a different file? It seems to call just an iframe, so I'm not sure why it would be different for ckeditor and te module...:'(

Link to comment
Share on other sites

I have not been able to solve this properly.

I cheated in order to stop losing images. I added a DB update and changed the file "last-edited"-Date in the module file (InputfieldSlider.module).

Now everytime a slider is saved, it updates all temp image files to permanent files. Not a very clean way to do it, but it saves me from losing data for now :)

This is what I added:

	$sql = 'SELECT `pages_id`,`data` FROM field_images WHERE created LIKE "1970-01-01 01:00:10"';
        $query = $this->database->prepare($sql);

        $rows = $query->fetchAll(PDO::FETCH_CLASS);

        foreach($rows as $row) {
            $path = $_SERVER["DOCUMENT_ROOT"].'/site/assets/files/'.$row->pages_id.'/'.$row->data;
        $sql = 'UPDATE field_images SET created=modified WHERE created LIKE "1970-01-01 01:00:10"';
        $query = $this->database->prepare($sql);


Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Liam88
      I'm really struggling with this as it's something not in my wheelhouse. I'm creating a blog style page (a grid of cards) which has attributes.
      I have a snip of javascript which grabs values from checkboxes which are put into a value like the below:
      document.querySelector("form").onsubmit=ev=>{ ev.preventDefault(); let o={}; ev.target.querySelectorAll("[name]:checked").forEach(el=>{ (o[el.name]=o[el.name]||[]).push(el.value)}) console.log(location.pathname+"?"+ Object.entries(o).map(([v,f])=> v+"="+f.join("_")).join("&") ); document.location.href = location.pathname+"?"+ Object.entries(o).map(([v,f])=> v+"="+f.join("_")).join("&"); } As I'm currently refeshing the page on button click with those values the end result includes the location but can easily remove this.
      I then use this value in "input->get" to get the values which I then append to a find() rule. See code below:
      $selector = "template='adbank_pages',sort=published,include=all,status!=hidden"; // Get the channel and content inputs $channel = $input->get->channel; $content = $input->get->content; if($channel){ // Grab the channel string, explode into an array for checkbox checking and then replace _ with | to create or rules in the selector. $chanArray = explode("_", $channel); $chan = $channel = str_replace('_', '|', $channel); $selector = $selector .= ",ab_channels=$chan"; } if($content){ // Grab the content string, explode into an array for checkbox checking and then replace _ with | to create or rules in the selector. $contArray = explode("_", $content); $cont = $content = str_replace('_', '|', $content); $selector = $selector .= ",ab_content=$cont"; } if($input->get){ // If a valid input result $all = $pages->find($selector); } }else{ // If no input show them all $all = $page->children("template='adbank_pages',sort=-published,include=all,status!=hidden"); } $items = $all->find("limit=12"); // Limit the output and use pagination As mentioned above I currently refresh the page to adjust the $selector filter within the $all with a fallback $all if there are no results.
      I know I need to use AJAX to filter the content without refresh but I am really struggling with the set up. I have read multiple posts including the original by Ryan but still confused.
      If anyone can direct/help on this it would be appreciated.
      Thank you
    • By prestoav
      Hi there, I'm hoping someone can help here.
      I've just moved a new site from my development server account over (where the site was working fine for the client to edit content pre-launch) to the client's final hosting account and the live site is all fine. However, while most edits can be done without an issue, image uploads in admin cannot. I know this has been an issue before but, having trawled the posts about it and suggested esolutions I still can't resolve it on their host.

      PW Version: 3.0.123
      PHP version: 7.3.20
      max_execution_time 160
      max_upload_size 256M
      GD Library is enabled

      Looking at the console data it looks like the AJAX request from the image upload is getting a 403 error which is suggesting a permissions issue? First we get this on console:
      ?id=1169&s=1&c=1:1 Uncaught SyntaxError: Unexpected token < in JSON at position 0 Then, the AJAX request:
      https://*******/admin/page/edit/?&id=1169&InputfieldFileAjax=1 Gets a 403 according to Chrome Dev Tools > Network XHR. Also, the response is empty.

      Can anyone point me in the direction of the directory that deals with this and what the permission should be to allow it or indeed any other fix / area to investigate?

      Thanks so much for your help.

    • By ICF Church
      Hi 👋
      Anyone else having this problem?
      - Repeater (matrix & normal) with mutlilanguage fields (text, textarea…) 
      - Backend language set to something other than default (ie. German) 
      - Add a new repeater Item (ajax, I found no way to possible to disable it with matrix)

      (Notice how the default language tab is active instead of the backend language…)
      - Write something into the (default language) field
      - Try to save, if field is required, this will not work. If not required, then when reloading, the content will be inside the backend language field, instead of the default language field who was (presumably) active
      When  loading  a new repeater element with ajax, the default langue tab is active, but the backend language inputfield is visible (with no visual indication). When writing into the field, it will populate the backend language. When manually clicking on the default language tab (which is already active), the field will switch to the actual default language field (which is [now] empty) (that can now be populated…)
      Also Notice, the labels of the elements to be added are in default language as well instead of the translated label (images instead of Bilder)…
      ProcessWire 3.0.148, Profields 0.0.5…
      Is it my system configuration, or does anyone else have the same issue? This is a screen recording of the problem:
      Issue: https://github.com/processwire/processwire-issues/issues/1179

      Screen Recording 2020-02-25 at 14.18.31.mov
    • By michelangelo
      Hello there,
      I am building my website, which has a dozen projects with 10 images each. Basically, I need a filtering system but built in the most efficient and user-friendly way. You can see below that the images flow sideways so being hidden, JS lazy loading was a good tool, but I just wanted to try AJAX. Is it fit for this purpose or it's more for dynamic content?

    • By louisstephens
      I have been messing around with creating pages from ajax requests, and it has gone swimmingly thus far. However, I am really struggling with creating a page and saving an image via ajax. 
      The form:
      <form action="./" role="form" method="post" enctype="multipart/form-data"> <div> <input type="text" id="preview" name="preview" placeholder="Image Title"> </div> <div> <input type="file" id="preview-name" name="preview-name"> </div> <div> <select id="select-tags" name="select-tags"> <?php $tags = $pages->find("template=tag"); ?> <option value="">Select Your Tags</option> <?php foreach ($tags as $tag) : ?> <option value="<?= $tag->name; ?>"><?= $tag->name; ?></option> <?php endforeach; ?> </select> </div> <div> <button type="button" id="submit-preview" name="submit" class="">Upload Images</button> </div> </form>  
      The ajax in my home template:
      $('#submit-preview').click(function(e) { e.preventDefault(); title = $("#preview").val(); image = $("input[name=preview-name]"); console.log(title); console.log(image); data = { title: title, image: image //not sure if this is actually needed }; $.ajax({ type: 'POST', data: data, url: '/development/upload-preview/', success: function(data) { console.log("Woo"); }, error: function(xhr, ajaxOptions, thrownError) { alert(xhr.responseText); } }); }); And finally in my ajax template:
      $imagePath = $config->paths->assets . "files/pdfs/"; //was from an older iteration $title = $sanitizer->text($_POST['title']); $image = $sanitizer->text($_POST['image']); $p = new Page(); $p->template = "preview"; $p->parent = $pages->get("/previews/"); $p->name = $title; $p->title = $title; $p->save(); $p->setOutputFormatting(false); $u = new WireUpload('preview_image'); $u->setMaxFiles(1); $u->setOverwrite(false); $u->setDestinationPath($p->preview_image->path()); $u->setValidExtensions(array('jpg', 'jpeg', 'gif', 'png', 'pdf')); foreach($u->execute() as $filename) { $p->preview_image->add($filename); } $p->save(); I can complete the file upload but just using a simple post to the same page and it it works well, but I was really trying to work out the ajax on this so I could utilize some modals for success on creation (and to keep my templates a little cleaner). When I do run the code I have, a new/blank folder is created under assets, and a new page is created with the correct title entered. However, no image is being processed. I do get a 200 status in my console. I have searched google for help, but everything seems to be slightly off from my needs. If anyone could help point me in the right direction I would greatly appreciate it. 
  • Create New...