由于本身没有走前端开发的方向,所以对这方面研究不是很深入,如果你有更好的建议或者吐槽,欢迎在评论区留言,每一条我都会认真过目。

发现教务网的问题

最近在提交毕设选题,发现我们学校落后复古的教务网设计使得我们无法通过一个现代的浏览器打开选择导师页面,于是打开代码展开了一点点研究。教务网大概长这样,略去了一些隐私信息,核心界面就是这样。
choosetutor_mainpage
出现的问题在于,我们需要选择导师,而那个框框是不可填写的,按照它的设计,肯定是想让我们点击那个<<。但是任何一个现代的浏览器,点击<<都没有任何反应。

先上简明扼要的结论

如果你对出现这种问题的细节不敢兴趣的话,我就直接上结论了。
最简单的方法有两种:

  • 使用IE浏览器打开(注意不是Microsoft Edge,一定要是Internet Explorer)
  • 使用国产双核浏览器,如360,搜狗等,同时使用兼容模式打开这个界面即可。兼容模式即使用了IE的内核。
  • 对于Mac用户而言,建议借一台使用Windows的同学并使用上面的方法之一,或者遵循我后文里稍微复杂一点的方法(解决方法三)。

为什么会出现这种问题

注意,其实有两个这种按钮,原理相同,这里只讲解第一个。后一个按照同样的方式处理即可。

我使用的是Chrome浏览器。当我点击按钮没反应,第一时间想到使用F12打开控制台,果然发现了报错。
choosetutor_red
我们来康康报了什么错。

1
Uncaught TypeError: window.showModalDialog is not a function at HTMLInputElement.onclick (lw_xssq.aspx?xh=3160105521:166)

说的是window.showModalDialog这个函数不存在。为了更好地确认和定位问题,我们可以使用控制台上方的“选择元素”按钮或者使用快捷键Ctrl + Shift + C 然后选择那个<<按钮。这一步是让浏览器帮我们定位到相应元素(你看得到的网页上的东西)在HTML代码里的相应位置。

在这里呢,它定位到了这样的代码。

1
<input class="button" onclick="javascript:document.getElementById('TextBox6').value=window.showModalDialog('lw_zdjsxz.aspx','教师选择','dialogWidth=600px;dialogHeight=450px;scrollbars=no;resizable=no');Change1();" type="button" value="<<">

简单分析一下这块代码。首先是说明这是一个按钮类型,最后是按钮上显示的类型。中间的onclick()函数就是点击这个按钮后会发生的一系列事情。我们看到,它给TextBox6进行了赋值,赋值的内容是调用了window.showModalDialog()函数,最后再调用了一个Change1()函数。这个函数后面会讲到。

这么一来逻辑就清楚了,点击这个按钮后,打开一个窗口,这个窗口返回一个值,填写到原来的网页上的相应空格位置。(后面会告诉你其实逻辑并不是这样的。教务网代码实际上写错了,实际上赋值这一步是多余且误导性的,不过不影响运行)

而这一流程的问题在于,window.showModalDialog并不能被正常调用。

解决方案一

在查阅相关文档后,可以了解到,window.showModalDialog是一个古老的且不被标准所支持的一个函数,说白了就是IE自家的,然后被淘汰了。

有什么解决方案呢?有很多都是写一个额外的js脚本将showModalDialog重新parse一遍,以适应所有的情况。

可喜的是,经过我的尝试发现,对我们这个特定的情况而言(所谓特定即传递的参数特别巧特别好),不需要这么麻烦。我们只需要在控制台里将window.showModalDialog修改为window.open即可。即将老的函数调用替换成了新的,现代的,被广泛支持的函数调用。

修改的方法就是在控制台那里双击相应元素,编辑,然后点击旁边,这样就算修改好啦~改好的是这样

choosetutor_change

这样子在左边再点击一下<<按钮试试看。

choosetutor_open

Yes!成功了!

解决方案二

在完成第一步后,找到自己的导师,点击右边的"选择"。唉?为什么左边的框显示的是undefined

choosetutor_undefined

怎么肥四!按照之前对onclick()的理解,

1
onclick="javascript:document.getElementById('TextBox6').value=window.showModalDialog('lw_zdjsxz.aspx','教师选择','dialogWidth=600px;dialogHeight=450px;scrollbars=no;resizable=no');Change1();"

可能是window.open的返回值是undefined。在查阅了相关文档后,发现的确如此。合理地方式是单独使用window.open(),然后赋值采用window.returnValue。这种处理方式是这样。

1
2
onclick="window.open('lw_zdjsxz.aspx','教师选择','dialogWidth=600px;dialogHeight=450px;scrollbars=no;resizable=no');
javascript:document.getElementById('TextBox6').value = window.returnValue;Change1();"

嗯,这样看起来不错。可是这样选择完后原来空着的还是空着的。咋回事啊?

这里其实是一个大坑,我纳闷琢磨了好久才研究出来。不卖关子了,实际上是因为原代码写得非常不优雅,那一段赋值内容是无效的(不管在它原版里还是修改版里),实际上真实的赋值在Change1()里。换句话说,就是有一个类似于全局变量的东西,在父页面和子页面所共享。然后调用了一个弹窗的函数,打开了一个子页面。子页面里点击选择修改了这个全局变量。在父页面里,使用Change1()将全局变量复制给文本框。能写出这样的代码真是让人非常崩溃吐血。这不仅仅是写得不优雅的问题,这写的简直就是…好吧,先不吐槽这个了。所以正常的onclick()里应该这样存放。

1
onclick="window.open('lw_zdjsxz.aspx','教师选择','dialogWidth=600px;dialogHeight=450px;scrollbars=no;resizable=no');Change1();"

但是不解决问题啊,还是没回答为什么会空着的。我们先看父页面的Change1()函数。

1
2
3
4
5
6
7
8
9
10
11
12
function Change1(){
var obj=document.getElementById('TextBox6');
var obj1=document.getElementById('TextBox5');
var obj2=document.getElementById('TextBox7');
//alert(obj.value);
if (obj.value!="" && obj.value !='undefined') {
//alert(obj.value.split("|")[1]);
obj2.value=obj.value.split("|")[0];
obj1.value=obj.value.split("|")[1];
__doPostBack('TextBox5','');

}

大意就是对三个空白的地方赋值,应该是“指导教师”,“职称”和“学院”。只要选择了这三个导师那么这三个就会自动生成,没毛病。大概意思这三个数据原来都放在了TextBox6这个框里,按照"|"作为分隔符。将这三个数据分割并填入相应的位置。

同时也要看看在子页面点击"选择"后会调用哪个函数。实测是__doPostBack()这个函数。这个在前面的Change1()里也出现过。那么这个函数里有个啥呢?

1
2
3
4
5
6
7
8
9
10
11
12
function __doPostBack(eventTarget, eventArgument) {
var theform;
if (window.navigator.appName.toLowerCase().indexOf("microsoft") > -1) {
theform = document.jssq_form;
}
else {
theform = document.forms["jssq_form"];
}
theform.__EVENTTARGET.value = eventTarget.split("$").join(":");
theform.__EVENTARGUMENT.value = eventArgument;
theform.submit();
}

这样看起来都没毛病。经过思考和向社畜宋宋请教后我发现,根源还是在于window.showModalDialogwindow.open采用了不同的API所导致的。

因此决定写一个window.showModalDialogpolyfill。但是由于js基础不太好,最后参考了Github也没有写成功。

又想到模仿它父子页面交互的方式来发送请求,可是教务网奇葩地把所有传递的内容都写在了__VIEWSTATE里,实在是难以阅读和实现。

因此解决方案第二步的确以失败而告终,感觉离终点很接近了,很遗憾。

解决方案三

这个就比较简单粗暴了,而且不依赖解决方案一和二。首先,我默认你是认得你的导师的。然后就很简单,只要把原来不可修改的那些框里将readonly标签删掉即可。举例来说,我们第一个“指导教师”的框框是没办法修改的。我们使用F12调出控制台,点击最上方的“选择元素”按钮或者使用Ctrl+Shift+C快捷键,接着点击左侧的不能修改的那个白色的框框。这样,你可以在右边控制台那里找到这个框框所对应的源代码。如图所示
choosetutor_readonly
可以看到,这个框框对应的代码是

1
<input name="TextBox5" type="text" readonly="readonly" onchange="__doPostBack('TextBox5','')" language="javascript" id="TextBox5">

看到哪个碍眼的readonly了吗?对这块内容双击即可编辑,删掉readonly="readonly"。让它变成

1
<input name="TextBox5" type="text" onchange="__doPostBack('TextBox5','')" language="javascript" id="TextBox5">

再点击旁边的空白部分即保存了修改后的代码。现在看看,哈哈,是不是可以自己随便填写啦!

对于所有这样的标签,都这么做即可。

这个方法简单有效,也适用于Mac~

写在最后

我最后在Arch Linux环境下使用Chrome提交了我的论文申请。

由于对前端开发了解地比较浅,所以在解决方法第二步最后没有得出特别优雅的解决方案,非常可惜。如果你有更好地方法和建议的话,欢迎在下面留言吐槽。

祝所有小伙伴毕业论文都能顺利呀~