利用CSS隐藏HTML元素并插入替代内容

创建一个支持切换阅读模式和答题模式的Anki问答题模板中,我创建了一个支持切换阅读模式和答题模式的问答题模板,该文最终利用JavaScript将Anki输出的向下箭头删除,并插入自定义的提示语。经过进一步测试,发现实现上述功能完全不需要使用JavaScript,仅使用CSS即可以实现。

Anki产生向下箭头的那行代码如下:

python 复制代码
format!("{provided}<br><span id=typearrow>&darr;</span><br>{expected}")

从上面的模板字符串可知向下箭头所在span元素的id为typearrow,在这个元素后面跟着一个br元素,后面紧接着输出的内容是用户输入的答案存在的错误,可以通过继续查阅源代码搞清楚这些内容包含在什么HTML元素中,也可以在背面内容模板中插入以下JavaScript让系统提示:

javascript 复制代码
var typearrow = document.getElementById('typearrow');
alert(typearrow.nextSibling.nextSibling.tagName);

运行上述代码可知br元素后面紧跟着的是span元素。不过,在CSS选择器中,可以用"+"定位到紧邻的兄弟结点,也可以用"*"通配符匹配任何HTML节点,因此,如果我们只想在br元素后面紧跟着的元素前面添加提示,实际上无需搞清楚用户输入的答案存在的错误包含在哪个元素中,只需用CSS选择器"#typearrow + br + *"就可以定位到那个元素,再加上伪元素选择器"::before",就可以插入提示信息了。

利用上面的思路改造可切换答题模式与阅读模式的问答题模板后,从下面的源代码可以看出,正面内容模板和背面内容模板都更为简洁,特别是背面内容模板,其中的JavaScript代码完全删除了,理论上运行效率也更高。

正面内容模板:

html 复制代码
<script>
// v0.5.3 - https://github.com/SimonLammer/anki-persistence/blob/7107e73086189c190c4d326ef11ebbcded9a08c6/script.js
if(void 0===window.Persistence){var _persistenceKey="github.com/SimonLammer/anki-persistence/",_defaultKey="_default";if(window.Persistence_sessionStorage=function(){var e=!1;try{"object"==typeof window.sessionStorage&&(e=!0,this.clear=function(){for(var e=0;e<sessionStorage.length;e++){var t=sessionStorage.key(e);0==t.indexOf(_persistenceKey)&&(sessionStorage.removeItem(t),e--)}},this.setItem=function(e,t){void 0==t&&(t=e,e=_defaultKey),sessionStorage.setItem(_persistenceKey+e,JSON.stringify(t))},this.getItem=function(e){return void 0==e&&(e=_defaultKey),JSON.parse(sessionStorage.getItem(_persistenceKey+e))},this.removeItem=function(e){void 0==e&&(e=_defaultKey),sessionStorage.removeItem(_persistenceKey+e)})}catch(e){}this.isAvailable=function(){return e}},window.Persistence_windowKey=function(e){var t=window[e],i=!1;"object"==typeof t&&(i=!0,this.clear=function(){t[_persistenceKey]={}},this.setItem=function(e,i){void 0==i&&(i=e,e=_defaultKey),t[_persistenceKey][e]=i},this.getItem=function(e){return void 0==e&&(e=_defaultKey),void 0==t[_persistenceKey][e]?null:t[_persistenceKey][e]},this.removeItem=function(e){void 0==e&&(e=_defaultKey),delete t[_persistenceKey][e]},void 0==t[_persistenceKey]&&this.clear()),this.isAvailable=function(){return i}},window.Persistence=new Persistence_sessionStorage,Persistence.isAvailable()||(window.Persistence=new Persistence_windowKey("py")),!Persistence.isAvailable()){var titleStartIndex=window.location.toString().indexOf("title"),titleContentIndex=window.location.toString().indexOf("main",titleStartIndex);titleStartIndex>0&&titleContentIndex>0&&titleContentIndex-titleStartIndex<10&&(window.Persistence=new Persistence_windowKey("qt"))}}</script>
<script>
	var model = Persistence.getItem();
   if (model == null) {
      model = { model:'answer',};
		Persistence.setItem(model);
   	}else{
		var back = document.getElementById('back');
		var btnToggle = document.getElementById('btnToggle');
		var answer = document.getElementById('answer');
		if (model.model == 'answer'){
			btnToggle.value = '答题模式';
			back.style = 'display:none';
			answer.style = 'display:bolck';
		}else{
			btnToggle.value = '阅读模式';
			back.style = 'display:bolck';
			answer.style = 'display:none';
		}
	}
	
	function toggleModel(){
		var btnToggle = event.currentTarget;
		var back = document.getElementById('back');
		var answer = document.getElementById('answer');
		if (model.model == 'answer'){
			model.model = 'read';
			btnToggle.value = '阅读模式';
			back.style='display:bolck';
			answer.style = 'display:none';
		}
		else{
			model.model = 'answer';
			btnToggle.value = '答题模式';
			back.style='display:none';
			answer.style = 'display:block';
		}
		Persistence.setItem(model);
	}
</script>
<div><a>说明:</a><q>当前模式如下方按钮所示。点击下方按钮可在阅读模式和答题模式之间切换。</q></div>
<div align="center">
<input id='btnToggle' type='button' onclick='toggleModel()' value='答题模式'></input></div>

<hr class="separator" />
<div class="h1 xcolor xleft">
	<span>⛳问题</span>	
		<span id="time">
	</span>
</div>
<div class="h2 xleft" align=left>{{edit:问题}}</div>
<hr class="separator" />

<div class="slide">
	<div class="h1 ycolor yleft">
	<span>👉	口诀</span>
	</div>
	<div class="h3  yleft";align=left>{{edit:口诀}}</div>
</div>
<hr class="separator" />

<div id='answer' class="h1 ycolor xleft" style='display:block'>
	<span class="yimg">✍️	回答</span><br><br>
	{{type:答案}} 	
	<hr class="separator" />
</div>

<div id='back' style='display:none'>
	<div class="h1 ycolor yleft">
		<span>👍正确答案</span>	
	</div>
	<div class='normal'>{{edit:答案}}<div>

	<hr class="separator" />
	<div class="h1 ycolor xleft md-content">
		<span>⚓备注</span>
	</div>
	<div class='normal'>{{edit:备注}}<div>
</div>

背面内容模板:

html 复制代码
<div class="h1 xcolor xleft">
	<span>⛳	问题</span>
		<span id="time">
	</span>
</div>
<div class="h2 xleft" align="left">{{edit:问题}}</div>
<hr class="separator" />

<div class="slide">
	<div class="h1 ycolor yleft">
	<span>👉	口诀</span>
	</div>
	<div class="h3  yleft" align="left">{{edit:口诀}}</div>
</div>
<hr class="separator" />
<div class="slide" id="slide1">
	<div class="h1 ycolor yleft">
	<span>👉答案对比</span>
	<div class= "note"><a>说明:</a>没有另外显示正确答案时表示你的答案完全正确。</div>
	</div>
	<div class="h1  yleft" align="left" >{{FrontSide:type:答案}}</div>
</div>
<hr class="separator" />
<div class="h1 ycolor xleft md-content">
	<span>⚓备注</span>
</div>
<div class='normal'>{{edit:备注}}<div>

样式文件只贴出在Anki自带的问答题模板基础上后来添加的内容,其中值得注意的地方均有注释注明:

css 复制代码
.color1,q{
	font-weight:bold;
	color:red;
}
.color2,a,a:link,a:visited,a:hover,a:active{
	font-weight:bold;
	color:blue;
	text-decoration:none;
}
.color3,i{
	font-weight:bold;
	color:rgb(230,12,237);
}
.separator{
	border:none;
	border-top-width:0.3em;
	border-top-style:solid;
	border-top-color:#aaa;
	margin:1.2em 0 1.2em 0;
}
.normal{
	text-indent:2em;
	font: 22px/22px 'Aa奶糖油画体','干就完事了简';
	line-height:1.5em;
}
.h3{
	font-family:"Aa奇思胖丫儿";
	color:green;
	background:yellow;
}
b{
	font-size:1.2em;
	-webkit-text-stroke:0.01em #0f0;
}

q::before,q::after{
	content:"";
}
#btnToggle {
    background-color: #4CAF50; /* Green */
    border: none;
    color: yellow;
    padding: 0.3em;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 1.2em;
	 border-radius:0.5em;
	 box-shadow: 0.1em 0.15em teal;
}
/*拼写正确时的文字样式*/
.typeGood{
 	background-color:#0f0; /*transparent:透明*/
}
/*拼写错误时的文字样式*/
/*没有拼写出来的文字样式*/
.typeBad, .typeMissed{
 	background-color:#ff0;
	color:red;
	font-weight:bold;
}

code#typeans {
	font-family: "Aa虎头虎脑";
	font-weight:bold;
}
.note{
	text-indent:2em;
	margin:1em 0em;
}
/*在用户输入的答案前添加提示*/
code#typeans::before {
	content:"你的答案:";
	color:#33c;
}
/*隐藏anki生成的箭头,该箭头包含在一个id为typearrow的span中*/
#typearrow{
	display:none;
}
/*跳过向下箭头元素及其后面的br元素,添加提示。当然我们可以利用
JavaScript查出那个元素的标签名是span*/
#typearrow + br + *::before{
	content:"正确答案:";
	color:#33c;
	-webkit-text-stroke:0em;
}

这篇文章本质上是上一篇文章的延续,但上一篇文章已经补充过多次,为方便阅读,在此另写一文。下面放一张背面截图:

相关推荐
奔跑吧邓邓子31 分钟前
npm包管理深度探索:从基础到进阶全面教程!
前端·npm·node.js
软件开发技术深度爱好者40 分钟前
用HTML5+CSS+JavaScript庆祝国庆
javascript·css·html5
前端李易安1 小时前
ajax的原理,使用场景以及如何实现
前端·ajax·okhttp
汪子熙1 小时前
Angular 服务器端应用 ng-state tag 的作用介绍
前端·javascript·angular.js
Envyᥫᩣ2 小时前
《ASP.NET Web Forms 实现视频点赞功能的完整示例》
前端·asp.net·音视频·视频点赞
Мартин.5 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。7 小时前
案例-表白墙简单实现
前端·javascript·css
数云界7 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd7 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常7 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine