How display specified images from selected files

Started by sinus, June 10, 2020, 02:45:07 PM

Previous topic - Next topic

sinus

Hi all,
I thought, it would be better for start a new thread for this, not to make Andy's timeline-thread even longer.  8)

Maybe experienced user can see here, how a beginner does struggle with (I guess) easy problems.

I think, I am able now to display focussed images and seletected images, even with Metadata-fields. Very good.

But I am not able to do this here:
How can I display from selected images some images and display the thumbs of them?

This can be (and I guess, must be) hardcoded.
Means, I want solve, that image number e.g. 3, 15 and 44 from 100 selected images should be displayed (the thumbs).

I have tried and googled and read the help of IMatch and tried to read the "IMatch Web Services documention" and the page with "IMatch Developer center" and "code recipes page".
The live documentation is interesting to click and see some stuff, but to be honest, I have no clue how to use them really in practice.

I have really tried a lot, but I guess, for someone with my level of knowledge, this is simply to complicated ... hence I ask here.  ;) and mostly I get an answer, thanks in advance.

The actual problem:
I took the "Sample App" File Window" from Mario.
I can see a thumb from the focused file, very good.

But now I want to display some files from the selected list and let display them.
I have really tried a lot, without success.
I see the filenname listed, the id listed, but I cannot use them to display these thumbs.

Can someone help me here further? Would be great.

I attach the output so far and what I want to achieve.
And I list here the code from the app (because it is not that long, I post all lines).

Finally: I am sure, this is a basic question and I hesitated to ask here.
But I think, here in the script-forum we could ask also such questions, at least some of us wants to lern more (like me) of html, css and maybe a bit of JavaScript  ;D


<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">

        <!-- Force latest version of IE -->
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />

        <title>Sample App: File Window</title>
       
        <script src="/system/jquery/dist/jquery.min.js"></script>
        <link rel="stylesheet" href="/system/font-awesome/css/font-awesome.min.css" />
        <link rel="stylesheet" href="/system/bootstrap/dist/css/bootstrap.min.css" />
        <link rel="stylesheet" href="/system/bootstrap/dist/css/bootstrap-theme.min.css" />
        <!--<link rel="stylesheet" href="/system/themes/slate/bootstrap.min.css" />-->
        <link rel="stylesheet" href="/system/animate.css/animate.min.css" />
       
        <script src="/system/imws/imwslib.js"></script>
        <script src="/system/imatch/imatchlib.js"></script>

        <style>
            .filename {
                color:rgb(112, 3, 12);
               }

               .add1 {
                color:rgb(190, 3, 19);
                font-size: 20px;
                font-weight:600;
                margin-left:130px;
                margin-top: -140px;
                width: 140px;
                border:2px solid grey;
                padding: 2px;
               }

               .add2 {
                color:rgb(49, 27, 247);
                font-size: 20px;
                font-weight:600;
                margin-left:315px;
                margin-top: -147px;
                width: 140px;
                border:2px solid grey;
                padding: 2px;
               }

        </style>
    </head>
    <body>
        <div class="container">
            <h2><i class="fa fa-info-circle"></i> Sample App: File Window</h2>
           
            <div>
                <p>Files in Scope: <span id="file-count">0</span></p>
                <p>Files Selected: <span id="sel-count">0</span></p>
                <p>Focused File Id: <span id="focused-file"></span></p>
                <!-- We show the thumbnail of the focused file in this tag -->
                <img id="focused-file-img" style="height:140px; width:auto; display:none;" src="#">
               
                <!-- Instead this text should appear file Numer 3 and number 6 -->
                <!-- How can this be done, choosen from the selected images? -->
                <div class="add1">Here should be the THUMBNAIL of the third image</div>
                <div class="add2">Here should be the THUMBNAIL of the sixt image</div>

            </div>

            <div>
                <h4>Select Files</h4>
                <p>Showing the first 7 files in the file window.</p>
                <div id="sel-list"></div>
            </div>
            <br/>
           
            <h4>List of Selected Files:</h4>
            <ul id="file-list"></ul>
        </div>

        <script>
            'use strict';
            var resultWindowInstanceId = 0;

            // This code is executed when the HTML document has finished loaded.
            $(document).ready(function () {
                // We open the web socket (communication channel) to IMatch.
                // This allows us to receive events, e.g., "selection in file window has changed.".
                openWebSocket();

                // This function updates the number of files and file list.
                // We call it once here, and then every time the selection changes.
                updateInfo();
              });


            // This function opens a web socket to IMatch (aka a communication channel).
            function openWebSocket()
            {
                // If the app runs in IMatch, this is all we need.
                if (IMatch.isEmbedded()) {
                    IMatch.openWebSocket();
                }
                else {
                    // If this runs in a browser, we assume that IMatch listens
                    // on the default IP address and port.
                    IMatch.openWebSocket(IMatch.DEFAULT_WS_URL);
                }

                // React on events sent by IMatch.
                IMatch.webSocket().onmessage = function(e) {
                    // Convert the message sent by IMatch to a proper JavaScript object:
                    var msg = JSON.parse(e.data);

                    // Process all events we're interested in.

                    if (msg.msg == 'fileWindow.selectionChanged') {
                        // Selection in the file window has changed.
                        updateInfo();
                    }
                }
            }

            // We call this whenever we need to update the information shown
            // on the HTML page. The function retrieves information about
            // A) All selected files
            // B) The focused file.
            function updateInfo()
            {
                // A) Get information about all files currently in the file window
                IMWS.get('v1/files',{
                    // This idlist represents all files currently selected in the active file window.
                    idlist: IMatch.idlist.fileWindowFiles,
                    // we only need the id and the file name
                    fields: 'id,filename'
                }).then(function(response) {
                    // Update the display which shows how many files are in the file window.
                    $('#file-count').text(response.files.length);

                    // For the first 20 files, we create links that allow the user to select the file.
                    // We use a custom attribute (data-id) to store the file id with every <a> tag.
                    // This makes it easy to access the file id when the link is clicked.
                    var list = $('#sel-list');
                    list.text('');
                    for (var f = 0; f < response.files.length; f++) {
                        var a = '<a href="" class="a-file-sel" data-id="' + response.files[f].id + '">' + response.files[f].id + '</a> ';
                        list.append(a);
                        if (f >= 7) break;
                    }

                    // Handle the click for all <a> tags with the a-file-sel class
                    $('.a-file-sel').click(function(e) {
                        // Get the file id from the data-id.
                        // Note: We need to wrap this in $() to make it a jQuery object
                        var fileid = Number($(this).attr('data-id'));
                        var params = {
                            id: fileid,
                            combine: true
                        }
                        IMatch.selectFiles(params);
                    });
     
                });
               
                // B) Get information about selected files.

                IMWS.get('v1/files',{
                    // This idlist represents all files currently selected in the active file window.
                    idlist: IMatch.idlist.fileWindowSelection,
                    // we only need the id and the file name
                    fields: 'id,filename'
                }).then(function(response) {

                    // Update the display which shows how many files are selected.
                    $('#sel-count').text(response.files.length);

                    // Update the <ul> list of file names. We show the first 20 names.
                   
                    // Ge the list element and clear it.
                    var list = $('#file-list');
                    list.text('');

                    // For all files returned...
                    for (var f = 0; f < response.files.length; f++) {
                        list.append('<li>[id: ' + response.files[f].id + '] <span class="filename">' + response.files[f].fileName + '</span></li>');
                        if (f >= 20) break;
                    }

                    // If we have more than 20 files, we inform the user.
                    if (response.files.length > 20) {
                        list.append('<li>...</li>');
                        list.append('<li>(<i class="fa fa-info-circle"></i> Showing only the first 20 files.)</li>');
                    }
                });


                // C) We also want to know which file is currently focused.

                // This call runs in parallel to the /files call above!.
                // It basically does the same, but it uses the idlist representing the focused file.
                IMWS.get('v1/files',{
                    // Information about the focused file in the active file window.
                    idlist : IMatch.idlist.fileWindowFocusedFile,
                    fields: 'id,filename,protected'
                }).then(function(response) {
                    if (response.files.length > 0) {
                        $('#focused-file').text(response.files[0].id);

                        // If we have a focused file, we show the <img> tag and load the thumbnail.
                        if (response.files[0].id != 0) {
                            loadImage(response.files[0].id,response.files[0].protected);
                        }
                        else  {
                            $('#focused-file-img').hide();
                        }
                    }
                    else {
                        $('#focused-file').text('None.');
                        $('#focused-file-img').hide();
                    }
                });
            }  // updateInfo
           
           
            // This function sets the src attribute of the <img> tag to the url of the focused
            // file. It checks first if the file is protected.
            // If this is the case, it checks if the user has enabled the display of protected files.
            function loadImage(oid,isProtected)
            {
                // This is the url in the format we need for src= attributes.
                // Note that we need include the auto_token so IMatch knows we are allowed to access the file.
                // We load the 'T' size, which means thumbnail.
                // default=true means that the endpoint returns a standard 404 not found image if there is no image for the file.
                var url = IMatch.IMWSUrl() + '/v1/files/image?auth_token=' + IMatch.authToken() + '&id=' + oid + '&imagesize=T&default=true';

                // We can just show the file
                if (!isProtected) {
                    var img = $('#focused-file-img');
                    img.attr('src',url);
                    img.fadeIn();
                }
                else {
                    // We need to check if protected files are enabled
                    IMatch.showProtectedFiles().then(function(response) {
                        // Construct the URL required to fetch the image.
                        // We need to create the format expectecd by the src attribute of the <img> tag.
                        if (response.protectedFilesVisible.value == true) {
                            var img = $('#focused-file-img');
                            img.attr('src',url);
                            img.fadeIn();
                        }
                        else {
                           $('#focused-file-img').hide();
                        }
                   });
                }
            }

        </script>
    </body>
</html>





Best wishes from Switzerland! :-)
Markus

Mario

#1
the v1/files/images endpoint returns an image for a specified file or files.
I'm sure this was asked many times and answered many times.

To get all selected files use v1/files with


                    IMWS.get('v1/files',{
                        idlist: IMatch.idlist.fileWindowSelection,
                        imagesize: 'dbthumbnail',
                        fields: 'id,name,imagewidth,imageheight'


This gives you the id and the size of the thumbnail.
This allows you to dynamically create <img> tags. Set the src attribute of the <img> tag to an URL using the v1/files/images endpoint to get the image, similar to

<img src="https://www.photools.com/dev-center/doc/imatch/IMatch.html and search for ImageURL on that page.
Example:

IMatch.getImageUrl(1,'dbthumbnail')

returns the URL for the image with the id 1 (you would of course use the id of whatever file variable you have).

Assuming you have an image tag <img id="thumb"> in your code, you can make it load the thumbnail for the file with id 1 with:

$('#thumb').attr('src',IMatch.getImageUrl(1,'dbthumbnail'));

The "1" is of course just an example. You would create the img tags in a loop while iterating over the files retrieved by v1/files (see above) and fill it from the id of the current file.

This allows you to display any number of thumbnails in any number of image tags in your page.
Play with it. Make mistakes. Learn. The only way to learn programming.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Jingo

Quote from: Mario on June 10, 2020, 03:03:14 PM

Play with it. Make mistakes. Learn. The only way to learn programming.

^^^ THIS... best advice ever!   8)

ubacher

Not sure I understand what you are trying to do.

Is it maybe IMatch.openResultWindow that you are looking for?
This will show the files you want in a result window.

Mario

No. He wants to display two thumbnails of specific files in his HTML form. See his screen shot.

This can be done easily by setting the src Attributes of the two img tags as I've explained above.
He just has to find the correct file in his set and then use the id to call IMatch.getImageUrl. Just a bit of trial and error, which is how you learn to program.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

sinus

Quote from: Mario on June 10, 2020, 07:54:18 PM
No. He wants to display two thumbnails of specific files in his HTML form. See his screen shot.

This can be done easily by setting the src Attributes of the two img tags as I've explained above.
He just has to find the correct file in his set and then use the id to call IMatch.getImageUrl. Just a bit of trial and error, which is how you learn to program.

Yes, ubacher, thanks, but Mario is correct, I want display two specific files in a HTML-file.  :)

Mario, thanks a lot for your long explanations, I really appreciate it!
I will carefully look at your answer and I will try to see, if I am able to solve my problem. I think and hope so.  :D

Best wishes from Switzerland! :-)
Markus

sinus

Quote from: Jingo on June 10, 2020, 07:41:43 PM
Quote from: Mario on June 10, 2020, 03:03:14 PM

Play with it. Make mistakes. Learn. The only way to learn programming.

^^^ THIS... best advice ever!   8)

Yep, Andy, I agree completely.  ;D 8)

I play a lot with it in the last time and I lern a lot (from my point of view).

At least I am able to do something with a App, with html, css and a bit Javascript.
And css is better and better, I think.

For example to rotate or move a image, there are possibilities without JS, eg. with keyframes of css.
Cool stuff.  ;D
Best wishes from Switzerland! :-)
Markus

sinus

I guess, it looks still "clumpsy", but it works  :D

YEAH!

Means, I can display

- the focused file
- the 3. image from a selection
- the 7. image from a selection

Here is the code
<h2>Sample App: File Window</h2>
           
            <div>
                <img id="thumb" style="height:250px; width:auto; border:5px solid red;" src="#">
                <img id="sel3-thumb" style="height:210px; width:auto; border:3px solid green;" src="#">
                <img id="sel7-thumb" style="height:170px; width:auto; border:6px solid orange" src="#">
            </div>

            <script>
                IMWS.get('v1/files',{
                         idlist : IMatch.idlist.fileWindowFocusedFile,
                         fields: 'id,filename'
                     }).then(function(response) {
                          loadImage(response.files[0].id,response.files[0]);
                       });
           
                 function loadImage(oid) {
                 var url = IMatch.IMWSUrl() + '/v1/files/image?auth_token=' + IMatch.authToken() + '&id=' + oid + '&imagesize=dbthumbnail';
                                 var img = $('#thumb');
                                 img.attr('src',url);
                     }


                     IMWS.get('v1/files',{
                         idlist : IMatch.idlist.fileWindowSelection,
                         fields: 'id,filename'
                     }).then(function(response) {
                          loadImageFromSel3(response.files[3].id,response.files[0]);
                       });
           
                 function loadImageFromSel3(oid) {
                 var url = IMatch.IMWSUrl() + '/v1/files/image?auth_token=' + IMatch.authToken() + '&id=' + oid + '&imagesize=dbthumbnail';
                                 var img = $('#sel3-thumb');
                                 img.attr('src',url);
                     }


                     IMWS.get('v1/files',{
                         idlist : IMatch.idlist.fileWindowSelection,
                         fields: 'id,filename'
                     }).then(function(response) {
                          loadImageFromSel7(response.files[6].id,response.files[0]);
                       });
           
                 function loadImageFromSel7(oid) {
                 var url = IMatch.IMWSUrl() + '/v1/files/image?auth_token=' + IMatch.authToken() + '&id=' + oid + '&imagesize=dbthumbnail';
                                 var img = $('#sel7-thumb');
                                 img.attr('src',url);
                     }
              </script>

</body>
</html>


If you think, I could make the code cleaner/better (not 3 times almost "the same"), it would be great, if you could give me a hint.
But maybe it is good like it is now.
But after all, hey, thanks, Mario, it works!!!  :D
Best wishes from Switzerland! :-)
Markus

Jingo

See.. I KNEW you could do it!

The only thing I would suggest is to streamline things a bit.. and begin creating "libraries" of functions you can re-use.. so, use parameters to pass items to a general function and re-use over and over.. 

Something like this (not tested):



var img;

IMWS.get('v1/files',{
                         idlist : IMatch.idlist.fileWindowSelection,
                         fields: 'id,filename'
                     }).then(function(response) {
                          loadImage(response.files[0].id,'$(#thumb)');
                          loadImage(response.files[3].id,'$(#sel3-thumb)');
                       });
           
                 function loadImage(oid,img) {
                 var url = IMatch.IMWSUrl() + '/v1/files/image?auth_token=' + IMatch.authToken() + '&id=' + oid + '&imagesize=dbthumbnail';
                 img.attr('src',url);
                     }

Mario

I would also recommend a quick check to see if the response really contains more than 3 files.
Else response.files[3] will cause an error  :)

And replace

var url = IMatch.IMWSUrl() + '/v1/files/image?auth_token=' + IMatch.authToken() + '&id=' + oid + '&imagesize=dbthumbnail';

with

var url = IMatch.getImageUrl(oid,'dbthumbnail');

in the loadImage function. Just neater.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

sinus

Wow!   :D
Thanks to both of you a lot, Andy and Mario.


Your suggestions helps me a lot, because it tells me that the code is not completely wrong, but also, what I should make better and think about it.
Very cool.

I will try this and I will lern again something.
Your help is really appreciated!

If I dive a bit into this html, css, JS, Jquery - stuff, it is simply overhelming, what else can be done.
Sometimes I think, it never ends, it goes further and further.

And sometimes, if I see examples on fiddle (Andy, I believe, you gave me the tip), I think, what the heck, how cool is this!

But for me, for almost everything, the base are pictures and hence the base is IMatch.  ;D

Best wishes from Switzerland! :-)
Markus

sinus

#11
Quote from: Mario on June 11, 2020, 06:35:22 PM
I would also recommend a quick check to see if the response really contains more than 3 files.
Else response.files[3] will cause an error  :)

And replace
var url = IMatch.IMWSUrl() + '/v1/files/image?auth_token=' + IMatch.authToken() + '&id=' + oid + '&imagesize=dbthumbnail';
with
var url = IMatch.getImageUrl(oid,'dbthumbnail');
in the loadImage function. Just neater.

Mario, cool, your advise "just neater"  ;D works fine.

btw, you see, that I listen carefully, I have wrote the long line (with ...token) because this remark of you in the code:
// Note that we need include the auto_token so IMatch knows we are allowed to access the file.

But seems not more necessary and of course I like the new, shorter line much more.  :D

Check, if more then 3 files are in the selection is a good advise, thanks, I will try to do this, I have seen some examples, hence I think I am able to do this.
Best wishes from Switzerland! :-)
Markus

sinus

Quote from: Jingo on June 11, 2020, 05:31:30 PM
See.. I KNEW you could do it!

The only thing I would suggest is to streamline things a bit.. and begin creating "libraries" of functions you can re-use.. so, use parameters to pass items to a general function and re-use over and over.. 

Something like this (not tested):



var img;

IMWS.get('v1/files',{
                         idlist : IMatch.idlist.fileWindowSelection,
                         fields: 'id,filename'
                     }).then(function(response) {
                          loadImage(response.files[0].id,'$(#thumb)');
                          loadImage(response.files[3].id,'$(#sel3-thumb)');
                       });
           
                 function loadImage(oid,img) {
                 var url = IMatch.IMWSUrl() + '/v1/files/image?auth_token=' + IMatch.authToken() + '&id=' + oid + '&imagesize=dbthumbnail';
                 img.attr('src',url);
                     }



Andy, thanks for this.
If I understand you correct, you mean, I could replace 3 functions with one and then use this function for all 3 (wished) images.

That would be of course much better, because if I would add say 7 images, it would be better and Mario would say "looks neater".  ;D

I tried your code, but it worked not here, though I tried different things.

I think, I have to try it another day, when I have more time, your idea of course sounds logical.  :D
Best wishes from Switzerland! :-)
Markus

Mario

If you use the methods provided by the IMatch class, the auth_token is automatically managed. The IMatch class takes care for this.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

sinus

Quote from: Mario on June 12, 2020, 03:22:35 PM
If you use the methods provided by the IMatch class, the auth_token is automatically managed. The IMatch class takes care for this.

I see, thanks.
IMatch takes care also for me :D 8) :)

you remember...  and the day comes nearer, that IMatch offers me a button to get coffee, a real coffee.  ;D
I have to trigger the coffee-machine to the computer somehow, and the rest, well, makes IMatch and a bit Javascript.  :D

(hint for all: a personal joke of me, I think, Mario can remember, what is quite old, the joke)
Best wishes from Switzerland! :-)
Markus

Mario

#15
This old joke of yours has become reality already.
I'm sure there are IOT- (Internet of Things) enabled coffee machines. Some of which have built-in web servers and offer endpoints to control the machine. Which means you can control them from an IMatch app.

Else, amazing devices like ESP2866, which costs only about 8€ (!), exist today. It has built-in Wi-Fi to connect to your WLAN, can run a web server, can be programmed in Python, JavaScript or C or whatever. From Visual Studio code, the same environment you use to write your IMatch apps (I hope).
You can install a software which runs a small web server on that ESP.
Add a 5V power source (battery or USB power supply) and you're good.
The software and tools are free.

This gives you a small web server under your control in your local network. The ESP8266 has many I/O pins for controlling devices, taking measurements, all kinds of stuff.

The web server can be programmed to process endpoints like /coffee/on and, for example, to turn on a 250V relay attached to one of the I/O pins of the ESP when it receives that command. Which then turns on your coffee machine. Bang. Instant Magic.

All that is missing now is a small app running in IMatch with a big red button labelled "COFFEE!". You can write that now yourself!
If you press that button, your app calls the endpoint ip-address of your ESP8266:port/coffee/on - exactly like you would call an endpoint in IMatch.
The ESP turns on the relay, which turns on your coffee machine. Yay!

It is slightly more complicated in real life, but only slightly. I've had lots of fun with stuff like that. Learning about all this. So rewarding. Better than wasting life time watching series on TV ;)

Since our world moves quickly into IoT of all sorts, I think it's important to stay ahead and understand all this tech, at least on a basic level.

At least from my standpoint. But I was never a 'consumer' in the normal sense.

I know how a car works or my bike. How PCs, Windows, Android and Linux work. I can repair my dish washer, replace the dead flash tube in my Nikon SB-800 (12$ for parts) or diagnose and repair a blown Mosfet and some bad caps in the power supply of my Hi-Fi receiver - which restored it to perfect working condition again for 10$.

I have learned all that myself - because I find it interesting and rewarding. We can learn so much from YouTube these days! :)
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Jingo

For more info on Bargain PC/Chips - check out Christopher Barnatt on Youtube (explainingcomputers).... really easy to understand and shows what amazing things you can do with a $9 chip computer!

sinus

Quote from: Mario on June 13, 2020, 10:36:27 AM
This old joke of yours has become reality already.
...

Uhh, yep you remember.  :D
Really very interesting and it seems, that my "old joke" could be true.

I will, simply of interest, look a bit into this and the link from Jingo seems also to be interesting.

Like you wrote " We can learn so much from YouTube these days" that is really true.

Say who was "Emanuel Lasker"?
Or how high it the mountain "Matterhorn"?
How long can I eat cheese, what is in the freezer?

If I asked things like that, 50 years ago, puh, not easy to find an answer soon.
Nowadays ... search the Internet ... done.  ;D

Sometimes it is even the contrary, there is not also 1 answer, but 5 different answers and you have to decide, what is correct.
Best wishes from Switzerland! :-)
Markus