一个popUp和parentDOM的交互问题

本文探讨了在Internet Explorer浏览器中实现自定义组合框样式时遇到的问题,并提供了两种解决方案。一种是通过显示隐藏的DIV来避免DOM结构分离,另一种是在弹出窗口中手动绑定鼠标悬停事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

页面代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
    
<head>
        
<title></title>
        
<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
        
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
        
<meta content="VisualStudio.HTML" name="ProgId">
        
<meta content="Microsoft Visual Studio .NET 7.1" name="Originator">
        
<base target="_top">
        
<script language="javascript">
<!--

function showDropdown()
{
        
var oPopup=window.createPopup();
        oPopup.document.body.innerHTML
=divPercent.innerHTML;
        
    
        
//oPopup.document.write("test!");
        //oPopup.document.write("<script language"javascript">" + "function f(){alert('dynamic!!');}" + "</script>");
        
        
        oPopup.show(
0,25,150,100,l1);
        
//divPercent.style.height=50;
        //divPercent.style.display="";
}

function handleComboItemMouseOver(id)
{
    
var item=window.document.getElementById(id);
    item.style.backgroundColor
="LightCyan";
    
}

function handleComboItemMouseOut(id)
{
    
var item=window.document.getElementById(id);
    item.style.backgroundColor
="whitesmoke";
    
}

//-->
        </script>
    
</head>
    
<body>
        
<P><label id="l1" onmouseover="this.style.cursor='hand'" style="BORDER-RIGHT: #ff6600 1px ridge; BORDER-TOP: #ff6600 1px ridge; BORDER-LEFT: #ff6600 1px ridge; BORDER-BOTTOM: #ff6600 1px ridge; BACKGROUND-COLOR: honeydew"
                onclick
="showDropdown()"> &nbsp;ComboBox &nbsp;</label></P>
        
</FONT>
        
<div id="divPercent" style=" DISPLAY: none" >
            
<div style=" 
                    BORDER-RIGHT: black 1px solid; 
                    BORDER-TOP: black 1px solid; 
                    SCROLLBAR-FACE-COLOR: #889b9f; 
                    OVERFLOW-X: hidden; 
                    SCROLLBAR-HIGHLIGHT-COLOR: #c3d6da; 
                    OVERFLOW: auto; 
                    BORDER-LEFT: black 1px solid; 
                    WIDTH: 120px; 
                    SCROLLBAR-SHADOW-COLOR: #3d5054; 
                    COLOR: blue; 
                    SCROLLBAR-3DLIGHT-COLOR: #3d5054; 
                    SCROLLBAR-ARROW-COLOR: #ffd6da; 
                    SCROLLBAR-TRACK-COLOR: #95a6aa; 
                    BORDER-BOTTOM: black 1px solid; 
                    SCROLLBAR-DARKSHADOW-COLOR: #85989c; 
                    HEIGHT: 100px; 
                    BACKGROUND-COLOR: whitesmoke"
>
                
<div id="p10" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke"
                    onmouseover
="this.style.backgroundColor='LightCyan'" onmouseout="this.style.backgroundColor='whitesmoke'"
                    onclick
="this.document.parentWindow.getElementById('l1').text='test';"><span>10%</span>
                
</div>
                
<div id="p20" onmouseover="this.style.backgroundColor='LightCyan'" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke"
                    onmouseout
="this.style.backgroundColor='whitesmoke'" onclick="window.alert('20%');"><span>20%</span>
                
</div>
                
<div id="p30" onmouseover="f();" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke"
                    onmouseout
="this.style.backgroundColor='whitesmoke'"><span>30%</span>
                
</div>
                
<div id="p40" onmouseover="this.style.backgroundColor='LightCyan'" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke"
                    onmouseout
="this.style.backgroundColor='whitesmoke'"><span>40%</span>
                
</div>
                
<div id="p50" onmouseover="this.style.backgroundColor='LightCyan'" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke"
                    onmouseout
="this.style.backgroundColor='whitesmoke'"><span>50%</span>
                
</div>
                
<div id="p60" onmouseover="this.style.backgroundColor='LightCyan'" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke"
                    onmouseout
="this.style.backgroundColor='whitesmoke'"><span>60%</span>
                
</div>
                
<div id="p70" onmouseover="this.style.backgroundColor='LightCyan'" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke"
                    onmouseout
="this.style.backgroundColor='whitesmoke'"><span>70%</span>
                
</div>
                
<div id="p80" onmouseover="this.style.backgroundColor='LightCyan'" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke"
                    onmouseout
="this.style.backgroundColor='whitesmoke'"><span>80%</span>
                
</div>
                
<div id="p90" onmouseover="this.style.backgroundColor='LightCyan'" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke"
                    onmouseout
="this.style.backgroundColor='whitesmoke'"><span>90%</span>
                
</div>
                
<div id="p100" onmouseover="this.style.backgroundColor='LightCyan'" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-BOTTOM: black 1px solid; BACKGROUND-COLOR: whitesmoke"
                    onmouseout
="this.style.backgroundColor='whitesmoke'"><span>100%</span>
                
</div>
            
</div>
        
</div>
    
</body>
</html>

 

运行效果如下:

 

  • 问题:

                        当我把:

                       onmouseover="this.style.backgroundColor='LightCyan'" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke"
                      onmouseout="this.style.backgroundColor='whitesmoke'"  独立出来写成javascript 函数,分别是:handleComboItemMouseOver,handleComboItemMouseOut 的时候,请求页面的时候,去提示: Microsoft JScript runtime error: Object expected ,不能正常现实combo item 的背景色

  • 原因分析:

                       Popup对象的docment 和 打开它的document ,不属于同一个DOM 结构,因此在Popup对象中,

         不能够访问handleComboItemMouseOver,handleComboItemMouseOut 。如果原因是这样子的话,我

     如何在另外一个DOM结构中通过javascript拿到parentWindow中的DOM元素或则javascript函数呢?

 

  • 解决(from liu yuan):

下面列了两种解决方法,希望能对解决问题有点提示

第一:重新修改你的CreatePopupwindow方法,修改为如下
主要功能是将隐藏的DIV打开而已,这样保证javascript和Dom树是一体工作的,自然不会有问题。

function showDropdown()
{
        //var oPopup=window.createPopup();
        //oPopup.document.body.innerHTML=divPercent.innerHTML;
        var oPopup=window.document.getElementById("divPercent");
        oPopup.style.POSITION="absolute";
        oPopup.style.top=35;
        oPopup.style.left=15;
        oPopup.style.display="";
        //oPopup.show(0,25,150,100,l1);
}

第二:
在Create的Window上添加事件,例如下面的代码,这样在打开的window 上的Item是有事件的

function showDropdown()
{
        var oPopup=window.createPopup();
        oPopup.document.body.innerHTML=divPercent.innerHTML;
        var p10=oPopup.document.getElementById("p10");
        p10.onmouseover=function()
        {
        handleComboItemMouseOver(this,"p10");
        }
        p10.onmouseout=function()
        {
        handleComboItemMouseOut(this,"p10");
        }
        oPopup.show(0,25,150,100,l1);
}

function handleComboItemMouseOver(con,id)
{
    var item=con.document.getElementById(id);
    item.style.backgroundColor="LightCyan";
}

function handleComboItemMouseOut(con,id)
{
    var item=con.document.getElementById(id);
    item.style.backgroundColor="whitesmoke";
   
}

  • 修改后的Code

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
    
<head>
        
<title></title>
        
<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
        
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
        
<meta content="VisualStudio.HTML" name="ProgId">
        
<meta content="Microsoft Visual Studio .NET 7.1" name="Originator">
        
<base target="_top">
        
<script language="javascript">
<!--

function showDropdown()
{
        
var oPopup=window.createPopup();
        oPopup.document.body.innerHTML
=divPercent.innerHTML;
        
var p10=oPopup.document.getElementById("p10");
        
        
//first combo item
        p10.onmouseover=function()
        
{
        handleComboItemMouseOver(
this,"p10");
        }

        p10.onmouseout
=function()
        
{
        handleComboItemMouseOut(
this,"p10");
        }

        p10.onclick
=function()
        
{
        handleComboItemClick(oPopup,
"p10");
        
        }

        
           
//second  combo item
        var p20=oPopup.document.getElementById("p20");
        
          p20.onmouseover
=function()
        
{
        handleComboItemMouseOver(
this,"p20");
        }

        p20.onmouseout
=function()
        
{
        handleComboItemMouseOut(
this,"p20");
        }

        p20.onclick
=function()
        
{
        handleComboItemClick(oPopup,
"p20");
        
        }

        
        
        
//third combo item
        
        
        
var p30=oPopup.document.getElementById("p30");
        
        p30.onmouseover
=function()
        
{
        handleComboItemMouseOver(
this,"p30");
        }

        p30.onmouseout
=function()
        
{
        handleComboItemMouseOut(
this,"p30");
        }

        p30.onclick
=function()
        
{
        handleComboItemClick(oPopup,
"p30");
        
        }

        
        
        
        
//more combo items..........
        //..........................................
        oPopup.show(0,25,150,100,l1);

}


function handleComboItemMouseOver(con,id)
{
    
//alert(id);
    var item=con.document.getElementById(id);
    item.style.backgroundColor
="LightCyan";
}


function handleComboItemMouseOut(con,id)
{
    
//alert("mouse out");
    var item=con.document.getElementById(id);
    item.style.backgroundColor
="whitesmoke";
}


function handleComboItemClick(oPopup,percent)
{
    
//alert("mouse click");
    var item=window.document.getElementById("l1");
    item.innerText
=percent;
    oPopup.hide();
    

}


//-->
        
</script>
    
</head>
    
<body>
        
<P><label id="l1" onmouseover="this.style.cursor='hand'" style="BORDER-RIGHT: #ff6600 1px ridge; BORDER-TOP: #ff6600 1px ridge; BORDER-LEFT: #ff6600 1px ridge; BORDER-BOTTOM: #ff6600 1px ridge; BACKGROUND-COLOR: honeydew"
                onclick
="showDropdown()"> &nbsp;ComboBox &nbsp;</label></P>
        
</FONT>
        
<div id="divPercent" style=" DISPLAY: none">
            
<div style=" 
                    BORDER-RIGHT: black 1px solid; 
                    BORDER-TOP: black 1px solid; 
                    SCROLLBAR-FACE-COLOR: #889b9f; 
                    OVERFLOW-X: hidden; 
                    SCROLLBAR-HIGHLIGHT-COLOR: #c3d6da; 
                    OVERFLOW: auto; 
                    BORDER-LEFT: black 1px solid; 
                    WIDTH: 115px; 
                    SCROLLBAR-SHADOW-COLOR: #3d5054; 
                    COLOR: blue; 
                    SCROLLBAR-3DLIGHT-COLOR: #3d5054; 
                    SCROLLBAR-ARROW-COLOR: #ffd6da; 
                    SCROLLBAR-TRACK-COLOR: #95a6aa; 
                    BORDER-BOTTOM: black 1px solid; 
                    SCROLLBAR-DARKSHADOW-COLOR: #85989c; 
                    HEIGHT: 100px; 
                    BACKGROUND-COLOR: whitesmoke"
>
                
<div id="p10" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke">
                    
<span style="FONT-FAMILY: Arial">10%</span>
                
</div>
                
<div id="p20" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BACKGROUND-COLOR: whitesmoke">
                    
<span style="FONT-FAMILY: Arial">20%</span>
                
</div>
                
<div id="p30" style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-BOTTOM: 1px solid; BACKGROUND-COLOR: whitesmoke; border-buttom: black 1px solid">
                    
<span style="FONT-FAMILY: Arial">30%</span>
                
</div>
            
</div>
        
</div>
    
</body>
</html>

 

 效果:

<think>好的,用户想了解如何在Streamlit的文本输入框右键点击弹出窗口。首先,我需要确认用户的需求。他们可能希望在输入框右键时触发自定义的菜单或操作,比如复制、粘贴以外的功能,或者显示额外信息。 接下来,我需要回忆Streamlit的现有组件API。Streamlit本身没有直接支持右键事件的原生组件,所以可能需要借助自定义组件或JavaScript注入。不过,用户可能希望用纯PythonStreamlit的方法实现,或者接受使用第三方库。 然后,考虑可能的解决方案。一种方法是使用JavaScript来监听右键事件,然后触发Streamlit的回调。这需要用到st.components.v1.html来注入JavaScript代码,并结合Session State来管理状态。例如,当用户右键点击输入框时,JavaScript检测到事件,通过WebSocket通知Streamlit,更新Session State,从而显示或隐藏一个弹出窗口(比如用st.expander或st.popup)。 不过,需要注意的是,Streamlit的架构是服务器端的,每次交互都会重新运行整个脚本。因此,弹出窗口的状态需要保存在Session State中,否则每次触发事件后,状态会丢失。此外,直接操作DOM可能会有兼容性问题,特别是在不同浏览器或Streamlit更新后。 另一个考虑点是,用户可能希望弹出的是一个原生的上下文菜单,而不是Streamlit组件模拟的。这时候可能需要更复杂的JavaScript代码来创建浮动元素,并处理点击外部区域关闭等行为。但这样会增加实现的复杂度,并且需要处理样式事件冲突的问题。 还需要检查是否有现成的Streamlit组件或社区解决方案。例如,搜索Streamlit的论坛或第三方库,看是否有类似的需求已经被实现。如果没有,可能需要自己开发一个自定义组件,封装JavaScriptPython的通信逻辑。 在实施步骤上,首先需要创建一个文本输入框,然后注入JavaScript代码来监听右键事件。当事件发生时,通过Streamlit的setQueryParams或自定义消息传递机制,将事件触发信号发送回Python端,然后根据Session State的变化,渲染弹出窗口组件,比如使用st.modal或st.expander来展示内容。 需要测试不同的方法,比如使用st.experimental_memo来防止重复渲染,或者调整CSS样式确保弹出窗口出现在正确的位置。同时,要考虑用户体验,比如弹出窗口的位置、关闭方式,以及如何处理多个输入框的情况。 最后,可能需要提供示例代码,并说明可能的限制,比如浏览器的兼容性、Streamlit版本的要求,以及自定义样式的调整方法。还要提醒用户,这种方法可能不如原生应用那样流畅,但在Streamlit的框架内可以实现基本的功能。</think>在Streamlit中实现文本输入框右键弹出窗口的功能,可以通过自定义JavaScript监听事件并结合组件状态管理实现。以下是分步骤的实现方法: 1. 基础组件搭建 ```python import streamlit as st from streamlit.components.v1 import html def create_input(): st.text_input("右键点击输入框", key="my_input") html(""" <script> // 监听输入框的右键点击事件 const inputElement = parent.document.querySelector('input[data-testid="stTextInput"]'); inputElement.addEventListener('contextmenu', (e) => { e.preventDefault(); // 与Streamlit通信 Streamlit.setComponentValue('show_menu'); }); </script> """, height=0) ``` 2. 弹出窗口控制 ```python def show_context_menu(): # 使用columns布局模拟弹出菜单 if st.session_state.get('show_menu'): cols = st.columns([0.8, 0.2]) with cols[1]: with st.container(): st.markdown(""" <style> .custom-menu { border: 1px solid #ccc; box-shadow: 3px 3px 5px rgba(0,0,0,0.2); padding: 10px; background: white; } </style> """, unsafe_allow_html=True) st.markdown('<div class="custom-menu">', unsafe_allow_html=True) if st.button("复制"): st.session_state.menu_action = "copy" if st.button("粘贴"): st.session_state.menu_action = "paste" st.markdown('</div>', unsafe_allow_html=True) # 点击外部区域关闭 if st.session_state.get('menu_action'): st.session_state.show_menu = False st.experimental_rerun() ``` 3. 整合使用 ```python if __name__ == "__main__": st.title("右键菜单演示") if 'show_menu' not in st.session_state: st.session_state.show_menu = False create_input() show_context_menu() ``` 实现原理说明: 1. 使用`st.components.v1.html`注入JavaScript代码监听右键事件 2. 通过`Streamlit.setComponentValue`与Python端通信 3. 利用Session State管理菜单状态 4. 使用CSS模拟原生菜单样式 5. 通过布局控制实现菜单定位 注意事项: 1. 需要允许页面运行JavaScript 2. 菜单定位可能需要根据实际布局调整 3. 不同浏览器可能存在兼容性问题 4. 建议配合`st.experimental_rerun()`使用确保状态更新 5. 复杂功能推荐使用`streamlit-modal`等第三方组件库 更高级的实现方案可参考: ```python # 使用streamlit-modal组件 from streamlit_modal import Modal modal = Modal("右键菜单", key="context_menu") if modal.is_open(): with modal.container(): st.button("选项1") st.button("选项2") # 添加自定义业务逻辑 ``` 这种方法通过组合使用Streamlit的组件系统JavaScript交互,可以在保持应用响应式特性的同时实现自定义右键菜单功能。实际开发中可根据需求扩展菜单项交互逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值