--- loncom/interface/loncommon.pm	2023/11/17 17:02:20	1.1418
+++ loncom/interface/loncommon.pm	2023/11/27 23:24:05	1.1423
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.1418 2023/11/17 17:02:20 raeburn Exp $
+# $Id: loncommon.pm,v 1.1423 2023/11/27 23:24:05 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2441,6 +2441,103 @@ END
 
 =pod
 
+=item * &iframe_wrapper_headjs()
+
+#
+# Where iframe is in use, if window.onload() executes before the custom resize function
+# has been defined (jQuery), two global javascript vars (LCnotready and LCresizedef)
+# are used to ensure document.ready() triggers a call to resize, so the iframe contents
+# do not obscure the Functions menu.
+#
+
+=back
+
+=cut
+
+
+sub iframe_wrapper_headjs {
+    return <<"ENDJS";
+<script type="text/javascript">
+// <![CDATA[
+var LCnotready = 0;
+var LCresizedef = 0;
+// ]]>
+</script>
+
+ENDJS
+
+}
+
+=pod
+
+=item * &iframe_wrapper_resizejs()
+
+#
+# jQuery to use when iframe is in use and a page resize occurs.
+# This script will ensure that the iframe does not obscure any
+# standard LON-CAPA inline menus (primary, secondary, and/or
+# breadcrumbs and Functions menus. Expects javascript from
+# &iframe_wrapper_headjs() to be in head portion of the web page,
+# e.g., by inclusion in second arg passed to &start_page().
+#
+
+=back
+
+=cut
+
+sub iframe_wrapper_resizejs {
+    my $offset = 5;
+    &get_unprocessed_cgi($ENV{'QUERY_STRING'},['inhibitmenu']);
+    if (($env{'form.inhibitmenu'} eq 'yes') || ($env{'form.only_body'})) {
+        $offset = 0;
+    }
+    return &Apache::lonhtmlcommon::scripttag(<<SCRIPT);
+    \$(document).ready( function() {
+        \$(window).unbind('resize').resize(function(){
+            var header = null;
+            var offset = $offset;
+            var height = 0;
+            var hdrtop = 0;
+            if (\$('div.LC_menus_content:first').length) {
+                if (\$('div.LC_menus_content:first').hasClass ("shown")) {
+                    header = \$('div.LC_menus_content:first');
+                    offset = 12;
+                }
+            } else if (\$('div.LC_head_subbox:first').length) {
+                header = \$('div.LC_head_subbox:first');
+                offset = 9;
+            } else {
+                if (\$('#LC_breadcrumbs').length) {
+                    header = \$('#LC_breadcrumbs');
+                }
+            }
+            if (header != null && header.length) {
+                height = header.height();
+                hdrtop = header.position().top;
+            }
+            var pos = height + hdrtop + offset;
+            \$('.LC_iframecontainer').css('top', pos);
+        });
+        LCresizedef = 1;
+        if (LCnotready == 1) {
+            LCnotready = 0;
+            \$(window).trigger('resize');
+        }
+    });
+    window.onload = function(){
+         if (LCresizedef) {
+             LCnotready = 0;
+             \$(window).trigger('resize');
+         } else {
+             LCnotready = 1;
+         }
+    };
+SCRIPT
+
+}
+
+=pod
+
 =head1 Excel and CSV file utility routines
 
 =cut
@@ -6461,6 +6558,19 @@ sub CSTR_pageheader {
     return $output;
 }
 
+##############################################
+=pod
+
+=item * &nocodemirror()
+
+Input: None
+
+Returns: 1 if CodeMirror is deactivated based on
+         user's preference, or domain default,
+         if user indicated use of default.
+
+=cut
+
 sub nocodemirror {
     my $nocodem = $env{'environment.nocodemirror'};
     unless ($nocodem) {
@@ -6475,7 +6585,27 @@ sub nocodemirror {
     return;
 }
 
+##############################################
+=pod
+
+=item * &permitted_editors()
+
+Input: $uri (optional)
+
+Returns: %editors hash in which keys are editors
+         permitted in current Authoring Space.
+         Value for each key is 1. Possible keys
+         are: edit, xml, and daxe. If no specific
+         set of editors has been set for the Author
+         who owns the Authoring Space, then the
+         domain default will be used.  If no domain
+         default has been set, then the keys will be
+         edit and xml.
+
+=cut
+
 sub permitted_editors {
+    my ($uri) = @_;
     my ($is_author,$is_coauthor,$auname,$audom,%editors);
     if ($env{'request.role'} =~ m{^au\./}) {
         $is_author = 1;
@@ -6494,6 +6624,9 @@ sub permitted_editors {
             ($audom,$auname) = ($1,$2);
         } elsif ($env{'request.uri'} =~ m{^/priv/($match_domain)/($match_username)/}) {
             ($audom,$auname) = ($1,$2);
+        } elsif (($uri eq '/daxesave') &&
+                 ($env{'form.path'} =~ m{^/daxeopen/priv/($match_domain)/($match_username)/})) {
+            ($audom,$auname) = ($1,$2);
         }
         if (($audom ne '') && ($auname ne '')) {
             if (($env{'user.domain'} eq $audom) &&
@@ -6754,10 +6887,21 @@ sub bodytag {
         $bodytag .= Apache::lonhtmlcommon::scripttag(
             Apache::lonmenu::utilityfunctions($httphost), 'start');
 
+        if ($args->{'collapsible_header'} ne '') {
+            my $alttext = &mt('menu state: collapsed');
+            my $tooltip = &mt('display standard menus');
+            $bodytag .= <<"END";
+<div id="LC_expandingContainer" style="display:inline;">
+<div id="LC_collapsible" class="LC_collapse_trigger" style="position: absolute;top: -5px;left: 0px; z-index:101; display:inline;">
+<a href="#" style="text-decoration:none;"><img class="LC_collapsible_indicator" alt="$alttext" title="$tooltip" src="/res/adm/pages/collapsed.png" style="border:0;margin:0;padding:0;max-width:100%;height:auto" /></a></div>
+<div class="LC_menus_content hidden">
+END
+        }
         unless ($args->{'no_primary_menu'}) {
             my ($left,$right) = Apache::lonmenu::primary_menu($crstype,$ltimenu,$menucoll,$menuref,
                                                               $args->{'links_disabled'},
-                                                              $args->{'links_target'});
+                                                              $args->{'links_target'},
+                                                              $args->{'collapsible_header'});
 
             if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
                 if ($dc_info) {
@@ -6816,7 +6960,11 @@ sub bodytag {
             $bodytag .= '<hr style="clear:both" />';
             $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end'); 
         }
-
+        if ($args->{'collapsible_header'} ne '') {
+            $bodytag .= $args->{'collapsible_header'}.
+                        '<div id="LC_collapsible_separator"></div>'.
+                        '</div></div>';
+        }
         return $bodytag;
 }
 
@@ -7009,6 +7157,14 @@ form, .inline {
   display: inline;
 }
 
+.LC_menus_content.shown{
+  display: inline;
+}
+
+.LC_menus_content.hidden {
+  display: none;
+}
+
 .LC_right {
   text-align:right;
 }
@@ -7029,6 +7185,12 @@ form, .inline {
   width:400px;
 }
 
+#LC_collapsible_separator {
+    border: 1px solid black;
+    width: 99.9%;
+    height: 0px;
+}
+
 .LC_iframecontainer {
     width: 98%;
     margin: 0;