Jump to content
nikola

Extending image field

Recommended Posts

I want to extend image field to have second text input besides description so I can easily add link alongside the description. What needs to be done to accomplish that feature?

It's a neat feature for image sliders, carousels etc.

Share this post


Link to post
Share on other sites

The field wasn't really designed for that particular use, so there currently aren't instructions on how to do that, but it's certainly possible (and probably not too difficult). But there isn't any easy answer to this question short of modifying the existing Fieldtype/Inputfield or creating a new one that extends it. I imagine that we'll have this built in eventually.

  • Like 1

Share this post


Link to post
Share on other sites

Thanks, I'll try to inspect the code, maybe I'll come up with something.

Share this post


Link to post
Share on other sites

Looking a little closer, I think the simplest solution will be for you to extend InputfieldImage.module, creating a new module. The module won't need much code in it. It'll just have to override two methods (outlined below). I've included some sample code in this message and it's written in the browser and untested. So you may have to adjust it and play around a bit to make it work.

Unless you want to also create a new Fieldtype, you'll need to work within the data available to FieldtypeImage, and that means just a single 'description' field. You'll use that 'description' field to hold an encoded version of multiple fields. I would suggest using JSON (with PHP's json_encode() and json_decode()) or XML, whatever you prefer. But here's an [untested] example of the two methods you would override in your new module that extends InputfieldImage.module:

<?php

protected $descriptionTemplate = array(
        'your_field1' => '',
        'your_field2' => '',
        'your_field3' => '',
        // or whatever you want
        );

protected function renderItemDescriptionField(Pagefile $pagefile, $id, $n) {

    $description = json_decode($pagefile->description, true); 
    if(!$description) $description = $this->descriptionTemplate; 

    foreach($description as $key => $value) {
        $description[$key] = htmlentities($value, ENT_QUOTES, "UTF-8"); 
    }

    $out = <<< _OUT 

        <label for='your_field1_$id'>Your Field #1</label>
        <textarea id='your_field1_$id' name='your_field1_$id'>$description[your_field1]</textarea>

        <label for='your_field2_$id'>Your Field #2</label>
        <input type='text' name='your_field2_$id' id='your_field2_$id' value='$description[your_field2]' />

        <label for='your_field3_$id'>Your Field #3</label>
        <input type='text' name='your_field3_$id' id='your_field3_$id' value='$description[your_field3]' />

_OUT; 

    return $out; 

}

Then you'll also need to override ___processInputFile with something like this (example):

<?php
protected function ___processInputFile(WireInputData $input, Pagefile $pagefile, $n) {

    $changed = parent::___processInputFile($input, $pagefile, $n); 
    $id = $this->name . '_' . $pagefile->hash;

    $description = $this->descriptionTemplate; 

    $description['your_field1'] = $input['your_field1_' . $id]; 
    $description['your_field2'] = $input['your_field2_' . $id]; 
    $description['your_field3'] = $input['your_field3_' . $id]; 
      
    $description = json_encode($description); 

    if($description != $pagefile->description) {
        $pagefile->description = $description; 
        $changed = true;   
    }

    return $changed; 
}

Once you've created and installed your new module, you'll select it as the "Input field" in field's settings, for your image(s) field. You'll also want to make sure that you set it to "no" for entity encoding the description field, in the field's settings.

The main drawback of this approach is that you'll need to decode the fields from the image's description field every time you want to access them. So if you are iterating through some images in your template, you'd do it like this:

<?php

foreach($page->images as $image) {

     // decode the description field to an array
     $description = json_decode($image->description, true); 

     // if there's nothing there, then skip it
     if(!$description) continue; 

     foreach($description as $key => $value) {
         // you decide if this is necessary for your intended use (usually I would say Yes)
         $description[$key] = htmlentities($value, ENT_QUOTES, "UTF-8"); 
     }
     echo "<p>Field 1: $description[your_field1]</p>";
     echo "<p>Field 2: $description[your_field2]</p>";
     echo "<p>Field 3: $description[your_field3]</p>";

}

We can get around this drawback by implementing a hook to do this for you once a page has finished loading. However, if it's that important, I would suggest looking at creating a new Fieldtype instead, as that would be ultimately more efficient, and probably easy to do. If you want to take that approach, let me know because you won't need to do any of this encoding/decoding, instead we'll just have the Fieldtype's DB schema keep the fields instead. So with that approach, the corresponding Inputfield would be a little different.

  • Like 2

Share this post


Link to post
Share on other sites

Thanks Ryan,

I'll try it tomorrow and let you know how it works...

Share this post


Link to post
Share on other sites

Hi Ryan,

is it possible for you that you create a new inputfield as you suggested in end of your post (so we can skip encode/decode)?

I think it might be useful to others also.

Thanks!

Share this post


Link to post
Share on other sites

Attached is an entire Fieldtype and Inputfield that show an example of 3 inputs for each image (title, tags and description). I've also set it up so that you can just change the schema in the getDatabaseSchema() function and it should automatically work with whatever varchar or text fields that you add. Though note that you'll want to make those changes before you create any fields with it. This works because the only place these custom fields are defined is in that schema, and everything else in the Fieldtype and Inputfield just picks it up from that schema.

In the future, I will probably use this as a foundation for a more advanced image/file fieldtype where you can specify the schema from the field's configuration in the admin, rather than modifying the code. But figured this would be a good example for what you asked for.

Ryan

FieldtypeImageExtra.zip

  • Like 6

Share this post


Link to post
Share on other sites

Well done!  ;D This is exactly the field type that I need for an upcoming project.

Share this post


Link to post
Share on other sites

Thanks Ryan! This was very helpful for my latest project. I really want to learn to create custom modules now! The possibilities are endless!

Share this post


Link to post
Share on other sites

How do you install, or use these extra fields/inputs? I am keen on adding a title field to the images field. At the moment there is just the description field.

thanks

Alex

Share this post


Link to post
Share on other sites

How do you install, or use these extra fields/inputs? I am keen on adding a title field to the images field. At the moment there is just the description field.

To literally extend the images field to have more inputs, you would have to make your own Fieldtype/Inputfield to support. See the file attached above (in one of my previous posts) for an example of that--it does take some PHP. Most likely we'll add built-in support for extending the image/file fields in the future (i.e. something you could configure with the field settings).

Another approach that some use is to create an 'image' template with one image field, and all the other fields you want to be grouped with an image. Then each page serves as an image with whatever metadata you want. At small scale use, this may be less convenient to manage than having an image field with it all built in. But it is more powerful and scalable to use this approach.

Share this post


Link to post
Share on other sites

I would like to know if it is possible and easy to extend FieldtypeImageExtra to have a Page field (instead of a common text field). This way, each image would have one or more pages associated with it. It would be like tags but the client can select a Page with the ACM Select component.

I guess it's easier to do this with an 'image' template but I loose the sorting manually by looking at the imagee (well, my client does). What do you think?

Share this post


Link to post
Share on other sites

I came back to this thread because of this other one http://processwire.c...portfolio-site/. As I remember, the need of adding extra information to the images and files fields was already mentioned some times. Ryan, are you still planning to extend the core fields with this? It would be actually a great feature to do this in the field config options!!

  • Like 2

Share this post


Link to post
Share on other sites

I am also wondering about this. If/when you do add in functionality for extending the core image fields, will those enhancements also be carried over to the Thumbnail module since it extends the image field? Am I understanding that relationship correctly? Because it would be killer to have extra info for my pictures and the ability to choose my thumbnail crop. That would help solve some issues related to my other thread that diogo referenced.

Share this post


Link to post
Share on other sites

I just downloaded and install ryans custom image field. i'm trying to get it work within a repeater but, as a normal image field inside a repeater description, it does not save any input field but the image. title, tags and description are not getting saved. Any idea?

Share this post


Link to post
Share on other sites
I just downloaded and install ryans custom image field. i'm trying to get it work within a repeater but, as a normal image field inside a repeater description, it does not save any input field but the image. title, tags and description are not getting saved. Any idea?

You mentioned "as a normal image field" -- does that mean you are getting the same behavior with a normal (non custom) image field? What happens if you change the sort order of the images or the repeater, is that saved? Does it work outside of a repeater? What version of ProcessWire? Sorry for all the questions, just trying to figure out what the issue might be. 

Share this post


Link to post
Share on other sites

Hey all – I’ve been using this FieldtypeImageExtra inputfield to create multi-language captions for a repeater that contains multiple image instances. It is working well so far. Only thing is, I get flooded with notifications after saving a page, it looks like this:

Is there any way to disable this? Will definitely make my client happier :)

more-green.png

Share this post


Link to post
Share on other sites

It was this line of code:

$this->message("$name = $value"); 

  • Like 1

Share this post


Link to post
Share on other sites

I have a (somewhat) related question, so I thought better to ask here than creating a new thread...

Is it possible to make the image / file description field multiline? i.e. textarea?

I'd like to create a simple way for logged-in users to look at images and Flash files and add comments (in the frontend, via API). A second text-field wouldn't be necessary - as long as I can add linebreaks for feedback / remarks in the existing default desc. field.

Share this post


Link to post
Share on other sites

Dragan, have a look in your image/file field settings (Setup > Fields > your-file-field) on the "input" tab. There is a option there asking how many row you want available for the description. 

  • Like 1

Share this post


Link to post
Share on other sites

Thanks Ryan. I completely overlooked that tab in the image / file fields. 

PW is like a box of chocolates. You never know what you're gonna discover today.

Share this post


Link to post
Share on other sites

I've added an extra field, which is just a text field for linking to other pages.
 

The user has to copy and paste this link manually, it would be much better to use a pageList select.


Any pointers on how I can achive this?

Share this post


Link to post
Share on other sites

Is there an easier way to make this language aware than putting tons of fields in an individual add-on module? 

With all the new toys from the PW dev version?

What, if an additional language comes? I am not sure editors want to edit modules code for that extra content fields?

Share this post


Link to post
Share on other sites

Since this module does not have a multi-language version, the best bet is to make your own with a repeater. 

Share this post


Link to post
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.

×
×
  • Create New...