Highlighted

Accessing images by ID containing a specific word via external javascript

Engaged ,
Oct 11, 2018

Copy link to clipboard

Copied

Hi everyone, I'm working in Captivate 2017 on a responsive project. What I'm trying to accomplish is take a piece of code which 'zooms' (translates position and scale via GSAP API) images via one function that targets all images by whether or not their id contains the word 'image'. I've created something that 'zooms' images using GSAP already, but the difference is I made each image page a .zip file containing an html, css, and js page. This was nice as I could control the css and html of the images, however, loading a .zip file on each slide with an image can take a minute and sometimes images don't load right away.

I'm wondering if I can do the same effect, however with one external JS file that I'll load into my index.html file after publish. I'm having a hard time calling/accessing images with an id that contains the word 'image' however. I'm not an expert coder by any means and I've had a lot of help from forums to get as far as I am, but essentially the code I'm using looks like this:

var targets = document.querySelectorAll('[id^="image"]');

for (var i = 0; i < targets.length; i++) {

  var tl = new TimelineMax({ paused: true, reversed: true });

  tl.to(targets, 0.6, { x: 100, y: 100 }, 0);

  targets.anim = tl;

  targets.addEventListener("click", function() {

    this.anim.reversed() ? this.anim.play() : this.anim.reverse();

  });

}

This method using document.querySelectorAll returns the variable 'target' in the console log as a node list with the length of 0 (even when on a slide that has an image on it). So I've tried another method:

var targets = $("img[id*=\"image\"]");

for (var i = 0; i < targets.length; i++) {

  var tl = new TimelineMax({ paused: true, reversed: true });

  tl.to(targets, 0.6, { x: 100, y: 100 }, 0);

  targets.anim = tl;

  targets.addEventListener("click", function() {

    this.anim.reversed() ? this.anim.play() : this.anim.reverse();

  });

}

I've tried this using $("img .... and $("div .... as I'm not sure what HTML tag captivate assigns to images? Neither of them seem to pick up my image with the id of "image43"  however. In the console log it returns as "m.fn.init [prevObject: m.fn.init(1), context: document, selector: "img[id*="image"]"]" with a length of 0.

Anyone have an idea as to how I can call my images based off of their id and if it contains the word image? Or if I could do the same thing by calling whatever class name captivate assigns to images (how would I figure out what that is)? Thanks!

Adobe Community Professional
Correct answer by TLCMediaDesign | Adobe Community Professional

Yes, in the window.addEventListener( 'moduleReadyEvent...

You need to add a function call at the end:

initializeEventListeners();

and then wrap the:

if ( interfaceObj.. in the function:

function initializeEventListeners() {

id ( interfaceObj

So what happens is that when Captivate fires the moduleReadyEvent, it then calls the function to set up the slide enter listener.

You code is setting up that listener before it's available.

Views

257

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

Accessing images by ID containing a specific word via external javascript

Engaged ,
Oct 11, 2018

Copy link to clipboard

Copied

Hi everyone, I'm working in Captivate 2017 on a responsive project. What I'm trying to accomplish is take a piece of code which 'zooms' (translates position and scale via GSAP API) images via one function that targets all images by whether or not their id contains the word 'image'. I've created something that 'zooms' images using GSAP already, but the difference is I made each image page a .zip file containing an html, css, and js page. This was nice as I could control the css and html of the images, however, loading a .zip file on each slide with an image can take a minute and sometimes images don't load right away.

I'm wondering if I can do the same effect, however with one external JS file that I'll load into my index.html file after publish. I'm having a hard time calling/accessing images with an id that contains the word 'image' however. I'm not an expert coder by any means and I've had a lot of help from forums to get as far as I am, but essentially the code I'm using looks like this:

var targets = document.querySelectorAll('[id^="image"]');

for (var i = 0; i < targets.length; i++) {

  var tl = new TimelineMax({ paused: true, reversed: true });

  tl.to(targets, 0.6, { x: 100, y: 100 }, 0);

  targets.anim = tl;

  targets.addEventListener("click", function() {

    this.anim.reversed() ? this.anim.play() : this.anim.reverse();

  });

}

This method using document.querySelectorAll returns the variable 'target' in the console log as a node list with the length of 0 (even when on a slide that has an image on it). So I've tried another method:

var targets = $("img[id*=\"image\"]");

for (var i = 0; i < targets.length; i++) {

  var tl = new TimelineMax({ paused: true, reversed: true });

  tl.to(targets, 0.6, { x: 100, y: 100 }, 0);

  targets.anim = tl;

  targets.addEventListener("click", function() {

    this.anim.reversed() ? this.anim.play() : this.anim.reverse();

  });

}

I've tried this using $("img .... and $("div .... as I'm not sure what HTML tag captivate assigns to images? Neither of them seem to pick up my image with the id of "image43"  however. In the console log it returns as "m.fn.init [prevObject: m.fn.init(1), context: document, selector: "img[id*="image"]"]" with a length of 0.

Anyone have an idea as to how I can call my images based off of their id and if it contains the word image? Or if I could do the same thing by calling whatever class name captivate assigns to images (how would I figure out what that is)? Thanks!

Adobe Community Professional
Correct answer by TLCMediaDesign | Adobe Community Professional

Yes, in the window.addEventListener( 'moduleReadyEvent...

You need to add a function call at the end:

initializeEventListeners();

and then wrap the:

if ( interfaceObj.. in the function:

function initializeEventListeners() {

id ( interfaceObj

So what happens is that when Captivate fires the moduleReadyEvent, it then calls the function to set up the slide enter listener.

You code is setting up that listener before it's available.

Views

258

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Oct 11, 2018 0
Most Valuable Participant ,
Oct 11, 2018

Copy link to clipboard

Copied

Since you insist on JS, did not want to answer. But I use one of the

features of CpExtra widget in that case.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 11, 2018 0
Adobe Community Professional ,
Oct 12, 2018

Copy link to clipboard

Copied

Where is this JS being run from?

Is it in an external JS file?

If I get what you are saying, the images are in an iFrame if they are in the zip package.

You need to wrap the script iin a timer, setInterval to see when the iFrame is loaded, then access the iFrame content.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0
Engaged ,
Oct 12, 2018

Copy link to clipboard

Copied

What I'm trying to do currently is run the JS from an external file (then load that js file in via the published index.html file). The images I just added as you would normally add into Captivate, are they still in an iFrame then? 

 

The method I used before was to add the images in via a zip file that contained an html, css, and js file. I'm trying to see if I can do the same effect without adding a .zip file and just controlling the images added in via the Captivate library through an external JS file. 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0
Adobe Community Professional ,
Oct 12, 2018

Copy link to clipboard

Copied

Do you have the script in a CPAPI_SLIDEENTER listener?

I've never had to do a setInterval to get references to images, but you might want to try it anyway since the length is returning 0.

Also, for each image there are going to be three references to it:

image_123

image_123c

re_image_123c

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0
Engaged ,
Oct 12, 2018

Copy link to clipboard

Copied

I do not. I've never written a CPAPI_SLIDEENTER listener before. 

 

When I try to target the image id specifically (in this case it's image43) the code works. For example, when I use - 

window.addEventListener("mousedown", function(e){

if(e.target.id==("image43")){

var tl = new TimelineMax();

var target = document.getElementById("image43c");

tl.to(target, .6, {x:500, y:500});

console.log($(target).position());

}

})

 

The image  will animate. But when I try to 'reference' any image whose id contains the word 'image' by:

$("img[id*=\"image\"]"); 

 

it is not animation nor apparently returning  in the variable assigned to that code. I've never used a jQuery selector as complicated as that before, so I'm not entirely sure what it's doing.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0
Engaged ,
Oct 12, 2018

Copy link to clipboard

Copied

I've never used 'setInterval' before, but I tried : 

setInterval(function(){

var targets = $("img[id*=\"image\"]");

for (var i = 0; i < targets.length; i++) {

  var tl = new TimelineMax({ paused: true, reversed: true });

tl.to(targets, 0.6, { x: 100, y: 100 }, 0);

targets.anim = tl;

  targets.addEventListener("click", function() {

    this.anim.reversed() ? this.anim.play() : this.anim.reverse();

  });

}

 

}, 1000);

 

Now the console log is giving an error saying my variable 'targets' is not defined - I'm guessing since the function isn't firing off right away, the variable is not being identified? 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0
Adobe Community Professional ,
Oct 12, 2018

Copy link to clipboard

Copied

I can't paste the code for the listener, but it's grabbing the elements for me when using the listener.

There is an example if you Google common JavaScript interface.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0
Engaged ,
Oct 12, 2018

Copy link to clipboard

Copied

Would the using the event listener look like this ? 

window.addEventListener("CPAPI_SLIDEENTER", function(){

var targets = $("img[id*=\"image\"]");

for (var i = 0; i < targets.length; i++) {

var tl = new TimelineMax({ paused: true, reversed: true });

tl.to(targets, 0.6, { x: 100, y: 100 }, 0);

targets.anim = tl;

  targets.addEventListener("click", function() {

  this.anim.reversed() ? this.anim.play() : this.anim.reverse();

  });

}

})

 

This code still doesn't seem to be working for me. 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0
Adobe Community Professional ,
Oct 12, 2018

Copy link to clipboard

Copied

There is more.

Look near the bottom of the page where it says:

2 Modifying published content.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 1
Engaged ,
Oct 12, 2018

Copy link to clipboard

Copied

Did you keep it in an external JS file or modify the published index.html file? 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0
Adobe Community Professional ,
Oct 12, 2018

Copy link to clipboard

Copied

It's in an external US file. I have them in the templates directory in the CP source files so every time I publish it's already there. I also edit the index to have the include statement.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0
Engaged ,
Oct 12, 2018

Copy link to clipboard

Copied

I'm sorry to be so helpless, but I've added this into my external JS file (and add the js file in via the index.html), I'm still not having my images animate - are there any errors you see here? 

 

var interfaceObj;

var eventEmitterObj;

window.addEventListener("moduleReadyEvent", function(evt){

interfaceObj = evt.Data;

eventEmitterObj = interfaceObj.getEventEmitter();

});

 

if(interfaceObj){

if(eventEmitterObj){

eventEmitterObj.addEventListener("CPAPI_SLIDEENTER", function(){

var targets = $("div[id*=\"image\"]");

for (var i = 0; i < targets.length; i++) {

var tl = new TimelineMax({ paused: true, reversed: true });

tl.to(targets, 0.6, { x: 100, y: 100 }, 0);

targets.anim = tl;

  targets.addEventListener("click", function() {

  this.anim.reversed() ? this.anim.play() : this.anim.reverse();

   });

}

})

}

}

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0
Adobe Community Professional ,
Oct 12, 2018

Copy link to clipboard

Copied

Yes, in the window.addEventListener( 'moduleReadyEvent...

You need to add a function call at the end:

initializeEventListeners();

and then wrap the:

if ( interfaceObj.. in the function:

function initializeEventListeners() {

id ( interfaceObj

So what happens is that when Captivate fires the moduleReadyEvent, it then calls the function to set up the slide enter listener.

You code is setting up that listener before it's available.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 1
Engaged ,
Oct 12, 2018

Copy link to clipboard

Copied

Thank you! I think I am finally figuring it out. Thanks so much for your help on this! 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0
Engaged ,
Oct 12, 2018

Copy link to clipboard

Copied

Adding to this in case anyone runs into doing the same thing - once I got the SLIDEENTER listener working (big thanks to TLCMediaDesign), I was having some issues with my GSAP timeline not targeting the right images. When I was using "targets" as my object in my GSAP timeline (please reference code I've pasted in above), no images were tweening. I then tried changing it to simply "targets" and that worked, but if there were multiple images on the slide it would tween ALL of them. I think this has something to do with captivate giving each image multiple ids (i.e. the whole "image43" and "image34c" thing), so when calling just one of them with "targets" it wasn't doing anything, because the image has two id's???? I'm not really sure about that part, but I looked at my console.log list for "targets" and after some guessing, figured out that it splits the output up, so if you have two images on the screen it will have both image's 'normal' ID first then both images 'c' appended ID. So I changed my GSAP target to be multiple targets which are "targets, targets[i-2]" and so far, with only TWO images on the page that is working - haven't tested with more than two images. But anyways, hope this helps someone out. It's pretty specific to GSAP, but in case anyone else out there is using it in their CP projects.

UPDATE: realized that since each image has 2 id's and they separated based on id type, it should always(?) be an even number, so I added this to my code:

var num = targets.length/2;

then changed my gsap targets to

[targets[i-num], targets]

and so far so good! Have tested with only up to 3 images on one slide though.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 12, 2018 0