Trying to execute a Perl/CGI script and put the output in a div

Hello,

I’m trying to execute a Perl/CGI script and put the output in a div. I’m using jQuery and Ajax.

I’ve confirmed that jQuery is loading (windows.jQuery). I have a simple JavaScript function as below.

function perlExecute(idx,urlx) {
    idx = '\#' + idx;
     $(idx).load(urlx);
 }

I call the Javascript function as below after creating a div. I pass in the div ID and url. I have executed the same url as the SRC in an iframe and DATA in an object. It does not like the load command. When I uncomment it, even alerts don’t work

<DIV ID='head$deRStr'></DIV>
<SCRIPT TYPE='text/JavaScript'>
           perlExecute(\"head$deRStr\",\"$delook\");                   
</SCRIPT>

I am executing without the body tags as I did with the iframe because I have body tags in the CGI program.
But with or without the body tag, nothing happens, Its just a blank screen,

Any help will be appreciated.
craigt

The JavaScript function should be -

function perlExecute(idx,urlx) {
  idx = ‘\#’ + idx;
  \$(idx).load(urlx);
}

I forgot the escape on the $ and thats why it was barking at the load command and alerts would not execute. The pound sign had to be escaped also, but that was in my program. I just forgot it here. But it did not make any difference. The screen is still blank.

@ct8638

[off-topic]
When you post code in the forum, you need to format it. To do so you can either select all the code and click the </> button, or type 3 backticks ``` on a separate line both before and after the code block. I have corrected it for you in your 2 posts, but I’m not sure if I correctly removed your backslashes…
[/off-topic]

Hi @ct8638, you must not escape anything of the actual JS code, only certain characters inside strings and regular expressions. It’s actually a syntax error here, which is most likely the reason why your alerts stopped working; you can check for errors in the console of the browser dev tools.

Thanks for your reply m3g4p0p. Perl simple namespaces begin with a dollar sign and this requires the dollar sign to be escaped in JavaScript.

I’ve gotten the CGI to load into a div. The problem was the parameters being passed to the CGI. The solution was to encode the string passed to ,load with encodeURI. It encodes some characters and leaves other alone and these others are critical in executing the CGI.

But, as good outcomes do sometimes, this has led to another problem. How do I get links in the CGI output to the div to execute and output in the div the link is being exeecuted in. I fear the answer is to execute all of those links the same way. The iframe and object avoid this losing of place of execution.

Any help is appreciated.

ct

1 Like

Ah ok… I’m not familiar with Perl at all TBH. ^^ Thanks for the clarification!

So you want to avoid leaving the page when a link gets clicked, but load the content of the target page into the current page? Then you might fetch the page content using AJAX, provided the target page is on the same origin or allows CORS. Using jQuery it might look like this:

$('.my-link').on('click', function (event) {
  // Don't follow the link...
  event.preventDefault()
  // ... but load the target page into the container div
  $(this).closest('div').load(this.href)
})

(This will render the entire page though, including <head> and everything, so you might want to specify a “fragment” of the page to load – see the docs for load() for details.)

Thanks again m3g4p0p. First let me give you 2 links. Both are executing off my server at my home. The 1st is with iframes (or objects). It works the way I’m hoping to get an approach with divs to work. I’m looking at changing from iframe/object to div because I ran into 2 distinct behaviors processing the combined page history of the page the iframes are in. The behavior in question is how the Back button works after links in iframes are taken and the page is refreshed, in the UI you will see in the link 1, Edge and IE do it ‘right’ and Chrome, FF, O, and Safari do it wrong, from my perspective. The code of link 1 follows the link.

See this in Edge, FF (insert HTML 4 meta tags/deprecated in HTML 5), or IE if possible to avoid the issue above.

link 1

http://steepusa.no-ip.info/scx/gencm1m.cgi?str=0%7ESKY%7EC%253A%252FSteep%252FUSA%2520Data%252FState%252FKY%252F%7EC%3A%2FSteep%2FUSA%20Data%2FState%2FKY%2Fhealthybirths%2Eview%7El

     $pflg = 0; # Instructions/other visualization or color map.

      $exstr = da da da;                
      $delook = "carea3.CGI?str=$exstr$svdp";

      print "   <DIV ID='head$deRStr'></DIV>

      <SCRIPT TYPE='text/JavaScript'>
         var idx = 'div\#' + \"head$deRStr\";
         var urlx = encodeURI(\"$delook\");
         \$(idx).load(urlx); 
         \$('.my-links').on('click', function (event) {
           // Don't follow the link...
           event.preventDefault();
           // ... but load the target page into the container div
           \$(this).closest('div').load(this.href);
         });                          
      </SCRIPT>\n";

      $pflg = 1;
      for ($i=0; $i < $nmeasures; $i++) {

        $xs = $measures[0];
        $xs = preptok($xs);
  
        $exstr = da da da;            
        $delook = "carea3.CGI?str=$exstr";
        
        print "   <DIV ID='f$i$deRStr'></DIV>

        <SCRIPT TYPE='text/JavaScript'>         
           var idx = 'div\#' + \"f$i$deRStr\";
           var urlx = encodeURI(\"$delook\"); 
           \$(idx).load(urlx);
           //\$(idx).attr('href');
           \$('.my-links').on('click', function (event) {
             // Don't follow the link...
             event.preventDefault();
             // ... but load the target page into the container div
             \$(this).closest('div').load(this.href);
           });             
        </SCRIPT>\n";

      } # do ($i=0

But the issue of this post now is not the issue above. I want to open links in iframes/now divs in those divs. And there is a lot of links in each iframe/div. The UI can have up to 6 iframes/now divs. The 1st is instructions/other visualizations and the other 2-5 are color maps (geography is a variable in this application).

Take links in any iframe of link 1 and see that the link opens in the iframe and a user can go several links deep. Each area is a link to a trend/time-series of a measure in that area, depending on the view of the measure in the area, either value or rate. You can change view with the icon to the right of the first word on the 2nd line above each color map. The selection mechanism is for people who only have a area name.

2nd link

http://steepusa.no-ip.info/scx/gencm1mn.cgi?str=0%7ESKY%7EC%253A%252FSteep%252FUSA%2520Data%252FState%252FKY%252F%7EC%3A%2FSteep%2FUSA%20Data%2FState%2FKY%2Fhealthybirths%2Eview%7El

     $pflg = 0;

      $exstr = da da da;                 
      $delook = "carea3.CGI?str=$exstr$svdp";

      print "   <DIV ID='head$deRStr'></DIV>

      <SCRIPT TYPE='text/JavaScript'>
         var idx = 'div\#' + \"head$deRStr\";
         var urlx = encodeURI(\"$delook\");
         \$(idx).load(urlx);

         \$('.my-links').on('click', function (event) {
           // Don't follow the link...
           event.preventDefault();
           // ... but load the target page into the container div
           \$(this).closest('div').load(this.href);
         });                          
      </SCRIPT>\n";

      $pflg = 1;
      for ($i=0; $i < $nmeasures; $i++) {

        $xs = $measures[0];
        $xs = preptok($xs); 
 
        $exstr = da da da;            
        $delook = "carea3.CGI?str=$exstr"; 

        print "   <DIV ID='f$i$deRStr'></DIV>

        <SCRIPT TYPE='text/JavaScript'>         
           var idx = 'div\#' + \"f$i$deRStr\";
           var urlx = encodeURI(\"$delook\"); 
           \$(idx).load(urlx);
           //\$(idx).attr('href');
           \$('.my-links').on('click', function (event) {
             // Don't follow the link...
             event.preventDefault();
             // ... but load the target page into the container div
             \$(this).closest('div').load(this.href);
           });             
        </SCRIPT>\n";

      } # do ($i=0

Notice that the div links open as a new page. This is the problem of this post now as I look for a different way to do what you see in link 1. I’m sure its me in this post. I’m new to jQuery. I’m probable not using your suggestion correctly.

Again thanks for your time.
ct

Well there don’t appear to be any links in the markup you’re generating… instead you’re outputting some empty divs together with the same script several times in a loop. Can you post the actual markup as generated by that Perl script?

Also the .my-link selector was just an example; you have to replace it with the actual class you’re using for those links, or maybe add a container class to those divs to capture all links inside them. And to account for dynamic content, you might use event delegation here:

for ($i=0; $i < $nmeasures; $i++) {
  print "<div id='f$i$deRStr' class='container'></div>"
}

print "<script>/* below script escaped */</script>"
$(document.body).on('click', '.container a', function (event) {
  event.preventDefault()
  $(this).closest('.container').load(event.target.href)
})

Here’s a very basic example you can run from your localhost (again I don’t know any Perl, so this is just the HTML and JS):

Are you saying that nothing came up in the divs with the 2nd link, that they were empty with no instruction div and no color maps??? Please tell me if this is the case. I’m at my server. Those links should work. I’ve tried them on my server and client.

Here is the markup generated by the 1st link.

<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<style>
body {
	background-color: #E6ECFF;
}
#headr1 {
	height: 50%;
	width: 33%;
	position: absolute;
	top: 0%;
	left: 0%;
	border: 0;
}
#f0r1 {
	height: 50%;
	width: 33%;
	position: absolute;
	top: 0%;
	left: 33.01%;
	border: 0;
}
#f1r1 {
	height: 50%;
	width: 33%;
	position: absolute;
	top: 0%;
	left: 66.01%;
	border: 0;
}
#f2r1 {
	height: 49%;
	width: 33%;
	position: absolute;
	top: 50.01%;
	left: 0%;
	border: 0;
}
#f3r1 {
	height: 49%;
	width: 33%;
	position: absolute;
	top: 50.01%;
	left: 33.01%;
	border: 0;
}
#f4r1 {
	height: 49%;
	width: 33%;
	position: absolute;
	top: 50.01%;
	left: 66.01%;
	border: 0;
}
</style>
</head>
<body>
   <iframe name="headr1" id="headr1" src="http://steepusa.no-ip.info/scx/carea3.CGI?str=0_0_SKY_healthy_Special View of Healthy Births - Total In Kentucky Counties_C%3A%2FSteep%2FUSA%20Data%2FState%2FKY%2FMeasures%2Fhealthy%2Fhealthy%2Edtl_healthy_none_level1_1_2006_1_Special View of Healthy Births - Total In Kentucky Counties_(Result)http*//kentucky.gov/Pages/home.aspx(Approach)http*//revenue.ky.gov/(Prospect)http*//www.yahoo.com/_gencm1m.cgi?str=0~SKY~C%3A%2FSteep%2FUSA%20Data%2FState%2FKY%2F~C%3A%2FSteep%2FUSA%20Data%2FState%2FKY%2Fhealthybirths%2Eview~l;quan=;tofield="></iframe>
   
   <iframe name="f0r1" id="f0r1" src="http://steepusa.no-ip.info/scx/carea3.CGI?str=0_1_SKY_healthy_Special View of Healthy Births - Total In Kentucky Counties_C%3A%2FSteep%2FUSA%20Data%2FState%2FKY%2FMeasures%2Fhealthy%2Fhealthy%2Edtl_healthy_none_level1_1_2006_1_Special View of Healthy Births - Total In Kentucky Counties_(Result)http*//kentucky.gov/Pages/home.aspx(Approach)http*//revenue.ky.gov/(Prospect)http*//www.yahoo.com/"></iframe>

   <iframe name="f1r1" id="f1r1" src="http://steepusa.no-ip.info/scx/carea3.CGI?str=0_1_SKY_healthy_Special View of Healthy Births - Total In Kentucky Counties_C%3A%2FSteep%2FUSA%20Data%2FState%2FKY%2FMeasures%2Fhealthy%2Fhealthy%2Edtl_healthy_none_level1_1_2005_1_Special View of Healthy Births - Total In Kentucky Counties_(Result)http*//kentucky.gov/Pages/home.aspx(Approach)http*//revenue.ky.gov/(Prospect)http*//www.yahoo.com/"></iframe>

   <iframe name="f2r1" id="f2r1" src="http://steepusa.no-ip.info/scx/carea3.CGI?str=0_1_SKY_healthy_Special View of Healthy Births - Total In Kentucky Counties_C%3A%2FSteep%2FUSA%20Data%2FState%2FKY%2FMeasures%2Fhealthy%2Fhealthy%2Edtl_healthy_none_level1_1_2004_1_Special View of Healthy Births - Total In Kentucky Counties_(Result)http*//kentucky.gov/Pages/home.aspx(Approach)http*//revenue.ky.gov/(Prospect)http*//www.yahoo.com/"></iframe>

   <iframe name="f3r1" id="f3r1" src="http://steepusa.no-ip.info/scx/carea3.CGI?str=0_1_SKY_healthy_Special View of Healthy Births - Total In Kentucky Counties_C%3A%2FSteep%2FUSA%20Data%2FState%2FKY%2FMeasures%2Fhealthy%2Fhealthy%2Edtl_healthy_none_level1_1_2003_1_Special View of Healthy Births - Total In Kentucky Counties_(Result)http*//kentucky.gov/Pages/home.aspx(Approach)http*//revenue.ky.gov/(Prospect)http*//www.yahoo.com/"></iframe>

   <iframe name="f4r1" id="f4r1" src="http://steepusa.no-ip.info/scx/carea3.CGI?str=0_1_SKY_healthy_Special View of Healthy Births - Total In Kentucky Counties_C%3A%2FSteep%2FUSA%20Data%2FState%2FKY%2FMeasures%2Fhealthy%2Fhealthy%2Edtl_healthy_none_level1_1_2002_1_Special View of Healthy Births - Total In Kentucky Counties_(Result)http*//kentucky.gov/Pages/home.aspx(Approach)http*//revenue.ky.gov/(Prospect)http*//www.yahoo.com/"></iframe>


</body>
</html>

You are exactly right about this div approach at this point. The HTML looks right, but the CSS is very strange.
Inheritance with divs that is not the case with iframes and objects.

Thanks for your explanation on the click device.

Let me look again at this new div approach. There are a number of things that do not work as in the iframe/object approach. I’m thinking a complete redesign may be in order to do with divs what is so easy with iframes and objects. I didn’t expect to run into the back button/refresh problem with iframes and objects. And I don’t know how this same thing will work with divs.

But I hate to lose 2 or eventually 3 browsers. This application runs in Chrome, Edge, FF, IE, and Opera (and Safari pretty much) except for this behavior. Safari is no longer in the picture on WIndows I guess, and IE is apparently on the way out (although I like some things about IE more that the other).

It may take me awhile to get back. There is an approach in JavaScript to prevent links from being added to history as follows.

var anchors = document.getElementsByTagName('a');
for (var i = 0; i < anchors.length; i++) {
    var anchor = anchors[i];
    anchor.addEventListener('click', function(event) {
        history.replaceState(null, null, anchor.href);
    }, false);
}

A variation on this,using a class name, might be doable if it works with Chrome, FF, and O. I have <A> and <AREA> links, and a location.href action in JavaScript on the Select A County function. If it did work, I could keep the iframe approach and still keep all browsers I tested with. However I have already done some testing with no luck. But I need to try more. I don’t have any experiance with replaceState, but I think I understand what the code above is trying to do.

Again thanks for your help m3g4p0p. I’ll be back.
ct

Hahaha sorry man, I completely overlooked those links… but yes they’re working!

As for the browser history, remembering (and restoring) the application state can be quite tricky indeed… but if you have any further questions let me know! :-)

Edit: Sorry @ct8638 I was a bit in a hurry earlier… as for the CSS, that is indeed a common problem. There is currently no solution to this other than using a naming methodology such as BEM to avoid unwanted styling. (Another possibility would be using web components with scoped styles, but this is experimental technology and currently only supported in chrome and opera out of the box.)

But yes you’ll certainly have to adjust the iframe-now-divs’ contents quite a bit. Another thing to watch out for is your JS; if every new content brings its own JS, you might have to clean up the old JS before loading the new content to avoid memory leaks. Also you should not declare any functions or variables in the global scope (actually you should not do this anyway), as all the scripts would otherwise overwrite each other. So at the very least you have to wrap all your JS in IIFEs… of course, better yet would be to have all your JS bundled on the main page only, and handle all the content there. This way you also don’t have to load the same (or largely same) JS over and over again.

But if you prevent the default actions of links inside the containers as in my above snippet, there will nothing be added to the history anyway… or am I missing something here? Anyway I think the history browser API is safe to use in all major browsers now, and jQuery is certainly no problem as x-browser support is one of its main goals.

m3g4p0p, you were right about replaceState. It worked cross browser but did not help me with the problem I’m about to explain.

I’ve run into a navigation problem with a container page with up to 6 iframes in the 6 browsers I test in at this time - Chrome, Edge, FF, IE, O, and Safari. I have a post under Design and UX about the browser Back button discussing this problem. But I think each time I state it, it gets clearer. I hope I’m not out of line in doing this in our conversation. This is about the behavior of the browser processing the history object in relation to use of the Back button before and after a refresh.

The 1 person that responded in the other post helped me understand that the specification on the discard of document objects is ambiguous at this time and, although I had a feel for this from testing, that the combined history of a page containing iframes (or objects) is distinct from the history of any of the iframes taken separately. And the combined history is always sequenced lifo in relation to the Back button. He also suggested that I consider redesigning these UIs which is what I was doing with the div for iframe replacement consideration.

I’m working on a Windows platform running the Apache server. My technical environment has been HTML, JavaScript, CSS, Perl/CGI and a half dozen APIs. I’ve designed 3 UIs that use iframes to visualize - 1) a time series of up to the 5 most recent years of color maps of a measure, 2) the most recent year of color maps of up to 5 different measures, and 3) significant segment visualizations for up to 4 measures.

Lets consider only the 1st UI design - a time series of up to the 5 most recent years of color maps of a measure. My expectations about the behavior of the Back button before and after a refresh and browser processing of the history object when I designed these 3 UIs was that 1) the Back button before a refresh would step back (lifo) through the combines history of the container page of the iframes, 2) that a refresh would return the container page and page elements to their initial state, and 3) that a refresh followed by the Back button would leave the container page.

These 3 expectations held up for Edge and IE (group 1), but the 3rd expectation has not held up in Chrome, FF, O, and Safari (group 2). Edge and IE work just designed and hoped for. I have found 3 HTML 4 meta statements that fix this in FF, but these have been deprecated in HTML 5. Safari for Windows is falling away as is IE I guess, making the loss of Chrome, FF, and Opera more important.

Please do the following simple exercise to see the behavior in question. Below is link 1 from above again.

http://steepusa.no-ip.info/scx/gencm1m.cgi?str=0%7ESKY%7EC%253A%252FSteep%252FUSA%2520Data%252FState%252FKY%252F%7EC%3A%2FSteep%2FUSA%20Data%2FState%2FKY%2Fhealthybirths%2Eview%7El

Open this link in 1 of the browsers from each of the 2 browser groups above. Pick any 3 iframes and take any one link in each of those 3. Hit the Back button once and see the last link taken go back to the previous iframe state in both browser groups. Now take another link (for a total of 3 history entries) anywhere and hit refresh, See that the container page and page elements (iframes) return to their initial state on initial page entry in both browser groups. Now hit the back button.

In Edge and IE, see that you have left the container page. In the other 4 browsers (including FF without the meta tags), after the refresh the Back button has to be entered the number of links you took in the session before the refresh + 1 to leave the container page. On each Back button entry the screen looks like it is refreshing, but that had already been done restoring initial entry state. So its really just blinking without any page change and has to be blinked (Back button entered) a number of times equal to the combined number of links taken in the previous session in all iframes + 1 to leave the container page.

This would be unacceptable to users of this application with group 2 browsers. It can’t be right. They would holler and moan. This has to be a bug or design oversight. Its like the container page still thinks there is history entries in the combined page history object, but there is not. Rather the length of the combined history object did not get reset on the refresh or something??? What do you think???

I know this has been lengthy and I thank you again for your time.

ct

Hm I’m not sure which behaviour I’d expect here… and frankly a browser back after page refresh seems like quite an edge case to me. But if you are concerned about the user being able to navigate the history as intended, you might consider implementing your own page navigation – maybe in the form of breadcrumbs inside each iframe, so that the user doesn’t have to touch the back button at any point.

Of course, if you’re replacing the iframes with regular divs the browser back won’t be functional anyway unless you explicitly add to the browser history using pushState(). For example, you might associate the container IDs with the currently loaded content in the history state object like so:

<div class="container" id="foo">
  <a href="./foo.html">foo</a>
</div>

<div class="container" id="bar">
  <a href="./bar.html">bar</a>
</div>
var $containers = $('.container')

window.addEventListener('popstate', function (event) {
  // Restore dynamically loaded content
  $.each(event.state, function (id, href) {
    $('#' + id).load(href)
  })
})

$containers.on('click', 'a', function (event) {
  var $container = $(event.target).closest($containers)
  var currentState = $.extend({}, window.history.state)
  var id = $container.prop('id')

  // Push the updated state to the history
  currentState[id] = event.target.href
  window.history.pushState(currentState, document.title)
  $container.load(event.target.href)
  event.preventDefault()
})

In this case, you’ll still be able to go back after refreshing the page, but the previous state will be restored so that the browser back makes more sense. You’ll have to account for browser caching though as for example the initial content might not get restored when going back, unless you loaded that content with AJAX as well.

I’d be careful not to mess too much with the browser history though. For dynamic content like this, the user might not even expect to be able to “rewind” the current page’s application state with the browser back button, but rather going to the previous page. So personally I’d rather go with an internal navigation.

Thanks for your reply m3g4p0p. I’ve decided to stay with the iframe approach at this time. Too many functions tested and working broke and would require ‘rigging’ if I went with divs…

I do want to say that the browser Back and Refresh buttons and those same functions in JavaScript have been an important part of the way navigation works in all the UIs I have designed in the WWW environment, including both visualizations and content entry interfaces. In all I’ve done, 1) page history can be walked back before a page refresh, 2) a refresh returns the screen to its initial state, and 3) a Back button immediately after a refresh leaves the page.

I can’t imagine how having to hit the Back button, after a refresh, a number of times equal to all links taken in the combined history of the page before the refresh + 1, could ever be useful or acceptable to a user. They would hollar and moan, as I said above.

Its possible to EASILY take a half dozen links in the iframes containing colormaps. If they took 6 links in 1 iframe, 3 in another, an 1 in a third, in Chrome, FF, O, and Safari, a user would have to hit the Bach button 11 times to leave the page. And nothing would be happening on the screen except that it blinks, because the initial state had already been restored on the refresh.

I think this is a bug or design oversight. I’ve tried, but can’t seem to see this any other way. I’m not sure what to do next. But I still have 3 browsers at this time. This problem came up in some of my last tests in doing the cross browser testing of this application. Isn’t that the way.

Thanks for your time and help and teaching me some jQuery Sir. Its neat.

ct

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.