html小工具——文章注释编辑器
在网上阅读文章时,读者时常会想针对某段文字写一些自己的感想,可惜大部分阅读网站并不提供这样的功能,读者往往只能将文本复制到本地或在线的编辑器中编辑注释,之后如果想在其他地方回顾这些注释也必须先本地安装或联网登录(云笔记)编辑器。如此操作,麻烦倒在其次,错过灵感才是最让人惋惜的,于是决定编写一个简单的小工具尝试解决这一问题,
一、用法:
用Chrome浏览器打开此工具
点击“选择文本文件”选择txt文件,或者直接将纯文本粘贴到文本框中,点击确定则以绿色背景显示出文本内容,鼠标双击绿色正文段落即在下面弹出黄色注释段落,双击注释段落即可编辑注释内容(正文不可编辑),编辑时点击其他地方即可取消编辑,再次双击绿色正文段落则隐藏本段注释。
点击导出html即可将正文和注释内容保存为一个html文档,用Chrome浏览器打开此html文档即可以查看已经录入的正文和注释,另外这个导出的html文档也具有本工具的所有特性,使用者可以继续编辑注释内容,或者完全替换性的加载新的文本,编辑完毕后又可以导出为新的html文档。
二、编写方法:
1、首先拼一个html结构出来:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>实用版,处理事件问题</title>
<style>
/*通用属性*/
body{ margin: 0; padding: 0; border: 0; text-align: center; overflow: hidden;width: 100%;
height: 100%;position: fixed; font-family: verdana,arial,sans-serif; touch-action: none;
-ms-touch-action: none;font-size: 12px;min-width: 600px;}
ul { list-style: none; margin: 0; padding: 0;}
li{ list-style: none; margin: 0; padding: 0;}
ul li { float: left;}
button{ cursor: pointer; height: 23px;}
a:link{ text-decoration: none;} #div_top span,input,button,textarea{margin-left: 20px;float: left;}
.p_h1{font-size: 24px;font-weight: bolder;background-color: darkseagreen}
.p_text{font-size: 20px;font-weight: normal;text-align: left;background-color: darkseagreen} .div_section{position:relative}
.p_a1{font-size: 20px;font-weight: normal;text-align: left;background-color: beige;margin-left: 60px;margin-right: 60px;
;min-height: 80px;display: block;word-break: break-all;overflow-wrap: break-word;white-space: pre-wrap}
.p_a2{font-size: 20px;font-weight: normal;text-align: left;background-color: beige;margin-left:120px}
</style>
</head>
<body>
<div id="div_allbase" style="top:0px;bottom:0px;width:100%;height: 100%;position:relative;overflow-x: hidden;overflow-y: scroll
">
<div id="div_top" style="top:0px;left:0px;width:100%;height: 30px;position:absolute;">
<span style="margin-left: 20px">选择文本文件</span>
<input type="file" id="str_local" onchange="ShowStr()" style="margin-left: 20px">
<span style="margin-left: 20px">粘贴文本</span>
<textarea type="text" id="str_local2" style="word-break: break-all;overflow-wrap: break-word;white-space: pre-wrap;height:40px"></textarea>
<button onclick="ShowStr2()">确定</button>
<button onclick="ExportHtml()">导出Html</button>
</div>
<div id="div_main" style="top:30px;left:0px;width:100%;position:absolute;"> </div>
</div>
</body>
其中div_top是上面的操作区,div_main用来存放正文段落和注释段落。这里文本框使用textarea标签而非input标签,因为input标签会自动将多行文本的换行符替换为空格,white-space: pre-wrap样式则负责告知textarea标签保留换行符,否则换行符也会被替换掉。
2、将纯文本转换为正文段落:
function ShowStr()//从文件读取文本
{
var str_local=document.getElementById("str_local");
var file=str_local.files[0];
var reader=new FileReader();
reader.readAsText(file);
reader.onload=function(e)
{
var str=e.target.result;
loadArticle(str);
}
}
function ShowStr2()//从文本框读取文本
{
var str_local=document.getElementById("str_local2");
var str=str_local.value;
loadArticle(str);
}
var currentSectionid=null;
function loadArticle(str)
{
var div_main=document.getElementById("div_main");
div_main.innerHTML="";
var arr_section=str.split("\r\n");
var len=arr_section.length;
if(len==1)//如果按\r\n分段后只有一段
{
arr_section=str.split("\n");
}
len=arr_section.length;
var count_p=0;//包含主标题在内一共分成几段
var arr_p=[];
for(var i=0;i<len;i++)
{
var section=arr_section[i];
if(section.length>0)
{
let div_section=document.createElement("div");
div_section.className="div_section";//这样可以更方便的在段内插入元素
div_section.id="div_section_"+count_p; let p=document.createElement("p");
if(count_p==0)//标题段
{
p.className="p_h1";
}
else
{
p.className="p_text";
}
p.innerHTML=" "+section;
p.id="p_section_"+count_p; p.ondblclick=function()
{
addAnnotate(div_section.id);
}
count_p++;
div_section.appendChild(p);
div_main.appendChild(div_section);
}
}
}
代码 并不复杂,根据\r\n对文本进行分段(从文本框读取时需要用\n分段),每一段生成对应的html文档插入dom中,每个“section”都有唯一的dom id。目前还没有调试好的是如何在导出导入html时保持每一段前面的四个空格,浏览器会自动将它们去掉。
注意在为批量建立的标签设定事件响应时,需要用let型变量而非var型变量,否则同一循环中定义的所有事件响应都将以循环操作的最后一个标签为目标。
3、双击正文段落时展开注释段落:
function addAnnotate(id)
{
var div_section=document.getElementById(id);
currentSectionid=id;//这个好像没用到
var children=div_section.childNodes;
var len=children.length;
if(len==1)//此时还没有第一级注释
{
let p_a1=document.createElement("p");
p_a1.className="p_a1";
//点击第一级注释,进行编辑
p_a1.ondblclick=function(){openEdit(p_a1)};
p_a1.onblur=function(){closeEdit(p_a1)};//失去焦点时关闭注释段的编辑状态
div_section.appendChild(p_a1)
}
else
{
if(children[1].style.display=="none")//如果当前是隐藏状态
{
for(var i=1;i<len;i++)
{
children[i].style.display="block";//显示注释段
}
}
else
{
for(var i=1;i<len;i++)
{
var child=children[i];
child.style.display="none";//隐藏注释段
if(child.className=="p_a1")
{
closeEdit(child);
}
}
}
}
}
这里根据sectionid找到当前操作的正文段落div,将空白的注释段落插进去。
4、编辑注释及关闭编辑状态:
function openEdit(p)
{
p.style.border="2px solid cornflowerblue";
p.style.borderRadius="5px";
p.contentEditable="true";
}
function closeEdit(p)
{
p.style.border="0px";
p.contentEditable="false";
//Chrome的默认编辑模式会在p内插入一个div,这个div是用来分行的,空白的换行也会导致div!!
// 但在重新导入之后(在取innerHTML导出时尚正常)浏览器会自动把这个div绘制在p的外面!!!!
//多次换行是嵌套的!!!!所以简单的替换还不行!!
p.innerHTML=p.innerHTML.replace(new RegExp(("<[^>]+>"),"gm"),"@");//如果有连续的多个xml标签
p.innerHTML=p.innerHTML.replace(new RegExp(("[@]+"),"gm"),"\r\n");
//p.innerHTML=p.innerHTML.replace(new RegExp(("<[^>]+>"),"gm"),"\r\n");
//p.innerHTML=p.innerHTML.replace(new RegExp(("<[^/][\\S]{1,5}>"),"gm"),"\r\n");
//p.innerHTML=p.innerHTML.replace(new RegExp(("</[\\S]{1,6}>"),"gm"),"");
}
这里使用了浏览器内置的“contentEditable”属性编辑p标签内容,这样做的一个缺点是浏览器会在用户编辑标签时不受用户控制的插入各种控制格式的标签,而同样的html再次导入浏览器时,又会按照不同的规则自动排列成别的顺序。(类似浏览器的CSS调试,只预期在运行时一次性使用?)
为解决这一问题,我在关闭p标签的contentEditable状态时,用正则表达式清除了所有的xml标签,但这也将导致新的问题——使用者希望写在注释中的xml标签(包括替换符号@)也会被清除掉,不知道有没有更好的方法解决这一问题。
5、导出html文档:
function ExportHtml()
{
var str=str_head+window.document.body.outerHTML+"</html>";
var blob=new Blob([str],{//字符串转为二进制流
type: "text/plain"
}) var tmpa = document.createElement("a");
var p_h1=document.getElementsByClassName("p_h1")[0];
tmpa.download = (p_h1?p_h1.innerHTML:"test")+".html";//自动用标题作为文件名
tmpa.href = URL.createObjectURL(blob);//用临时的a标签下载
tmpa.click();//导出后事件需要重新绑定,或者直接使用innHTML定义?
setTimeout(function () {
URL.revokeObjectURL(blob);//释放掉流
}, 100);
}
其中str_head包含了html头部内容,加上目前正在编辑的body内容和html结束标签组成导出的html文档,然后转换为二进制文件流用临时a标签下载。
注意,使用.onxx方式绑定的事件并不会随着html文档一起导出,可以选择在打开html时重新绑定事件,或者在建立标签时使用innerHTML而非appendChild方法,直接将事件响应写在innerHTML里
6、重新打开导出的html文档时重新绑定事件:
window.onload=function(){
//处理导出html的事件有两种思路,一是使用innerHTML定义所有动态生成的标签,二是在每次打开网页时重新绑定事件
var div_main=document.getElementById("div_main");
var arr_section=div_main.getElementsByClassName("div_section");
var len=arr_section.length;
for(var i=0;i<len;i++)
{
let div_section=arr_section[i];
var arr_p=div_section.getElementsByTagName("p");
var len2=arr_p.length;
for(var j=0;j<len2;j++)
{
let p=arr_p[j];
if(j==0)
{
p.ondblclick=function()
{
addAnnotate(div_section.id);
}
}
else
{
p.ondblclick=function(){openEdit(p)};
p.onblur=function(){closeEdit(p)};
}
}
}
}
如此就完成了文章注释编辑器小工具的编写,下面是完整的代码,复制粘贴到一个空白的.html文件中即可使用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>实用版,处理事件问题</title>
<style>
/*通用属性*/
body{ margin: 0; padding: 0; border: 0; text-align: center; overflow: hidden;width: 100%;
height: 100%;position: fixed; font-family: verdana,arial,sans-serif; touch-action: none;
-ms-touch-action: none;font-size: 12px;min-width: 600px;}
ul { list-style: none; margin: 0; padding: 0;}
li{ list-style: none; margin: 0; padding: 0;}
ul li { float: left;}
button{ cursor: pointer; height: 23px;}
a:link{ text-decoration: none;} #div_top span,input,button,textarea{margin-left: 20px;float: left;}
.p_h1{font-size: 24px;font-weight: bolder;background-color: darkseagreen}
.p_text{font-size: 20px;font-weight: normal;text-align: left;background-color: darkseagreen} .div_section{position:relative}
.p_a1{font-size: 20px;font-weight: normal;text-align: left;background-color: beige;margin-left: 60px;margin-right: 60px;
;min-height: 80px;display: block;word-break: break-all;overflow-wrap: break-word;white-space: pre-wrap}
.p_a2{font-size: 20px;font-weight: normal;text-align: left;background-color: beige;margin-left:120px}
</style>
</head>
<body>
<div id="div_allbase" style="top:0px;bottom:0px;width:100%;height: 100%;position:relative;overflow-x: hidden;overflow-y: scroll
">
<div id="div_top" style="top:0px;left:0px;width:100%;height: 30px;position:absolute;">
<span style="margin-left: 20px">选择文本文件</span>
<input type="file" id="str_local" onchange="ShowStr()" style="margin-left: 20px">
<span style="margin-left: 20px">粘贴文本</span>
<textarea type="text" id="str_local2" style="word-break: break-all;overflow-wrap: break-word;white-space: pre-wrap;height:40px"></textarea>
<button onclick="ShowStr2()">确定</button>
<button onclick="ExportHtml()">导出Html</button>
</div>
<div id="div_main" style="top:30px;left:0px;width:100%;position:absolute;"> </div>
</div>
</body>
<script> window.onload=function(){
//处理导出html的事件有两种思路,一是使用innerHTML定义所有动态生成的标签,二是在每次打开网页时重新绑定事件
var div_main=document.getElementById("div_main");
var arr_section=div_main.getElementsByClassName("div_section");
var len=arr_section.length;
for(var i=0;i<len;i++)
{
let div_section=arr_section[i];
var arr_p=div_section.getElementsByTagName("p");
var len2=arr_p.length;
for(var j=0;j<len2;j++)
{
let p=arr_p[j];
if(j==0)
{
p.ondblclick=function()
{
addAnnotate(div_section.id);
}
}
else
{
p.ondblclick=function(){openEdit(p)};
p.onblur=function(){closeEdit(p)};
}
}
}
}
function ShowStr()
{
var str_local=document.getElementById("str_local");
var file=str_local.files[0];
var reader=new FileReader();
reader.readAsText(file);
reader.onload=function(e)
{
var str=e.target.result;
loadArticle(str);
}
}
function ShowStr2()
{
var str_local=document.getElementById("str_local2");
var str=str_local.value;
loadArticle(str);
}
var currentSectionid=null;
function loadArticle(str)
{
var div_main=document.getElementById("div_main");
div_main.innerHTML="";
var arr_section=str.split("\r\n");
var len=arr_section.length;
if(len==1)
{
arr_section=str.split("\n");
}
len=arr_section.length;
var count_p=0;//包含主标题在内一共分成几段
var arr_p=[];
for(var i=0;i<len;i++)
{
var section=arr_section[i];
if(section.length>0)
{
let div_section=document.createElement("div");
div_section.className="div_section";//这样可以更方便的在段内插入元素
div_section.id="div_section_"+count_p; let p=document.createElement("p");
if(count_p==0)//标题段
{
p.className="p_h1";
}
else
{
p.className="p_text";
}
p.innerHTML=" "+section;
p.id="p_section_"+count_p; p.ondblclick=function()
{
addAnnotate(div_section.id);
}
count_p++;
div_section.appendChild(p);
div_main.appendChild(div_section);
}
}
}
function addAnnotate(id)
{
var div_section=document.getElementById(id);
currentSectionid=id;
var children=div_section.childNodes;
var len=children.length;
if(len==1)//此时还没有第一级注释
{
let p_a1=document.createElement("p");
p_a1.className="p_a1";
//点击第一级注释,进行编辑
p_a1.ondblclick=function(){openEdit(p_a1)};
p_a1.onblur=function(){closeEdit(p_a1)};
div_section.appendChild(p_a1)
}
else
{
if(children[1].style.display=="none")//如果当前是隐藏状态
{
for(var i=1;i<len;i++)
{
children[i].style.display="block";
}
}
else
{
for(var i=1;i<len;i++)
{
var child=children[i];
child.style.display="none";
if(child.className=="p_a1")
{
closeEdit(child);
}
}
}
}
}
function openEdit(p)
{
p.style.border="2px solid cornflowerblue";
p.style.borderRadius="5px";
p.contentEditable="true";
}
function closeEdit(p)
{
p.style.border="0px";
p.contentEditable="false";
//Chrome的默认编辑模式会在p内插入一个div,这个div是用来分行的,空白的换行也会导致div!!
// 但在重新导入之后(在取innerHTML导出时尚正常)浏览器会自动把这个div绘制在p的外面!!!!
//多次换行是嵌套的!!!!所以简单的替换还不行!!
p.innerHTML=p.innerHTML.replace(new RegExp(("<[^>]+>"),"gm"),"@");
p.innerHTML=p.innerHTML.replace(new RegExp(("[@]+"),"gm"),"\r\n");
//p.innerHTML=p.innerHTML.replace(new RegExp(("<[^>]+>"),"gm"),"\r\n");
//p.innerHTML=p.innerHTML.replace(new RegExp(("<[^/][\\S]{1,5}>"),"gm"),"\r\n");
//p.innerHTML=p.innerHTML.replace(new RegExp(("</[\\S]{1,6}>"),"gm"),"");
} function ExportHtml()
{
var str=str_head+window.document.body.outerHTML+"</html>";
var blob=new Blob([str],{
type: "text/plain"
}) var tmpa = document.createElement("a");
var p_h1=document.getElementsByClassName("p_h1")[0];
tmpa.download = (p_h1?p_h1.innerHTML:"test")+".html";
tmpa.href = URL.createObjectURL(blob);
tmpa.click();//导出后事件需要重新绑定,或者直接使用innHTML定义?
setTimeout(function () {
URL.revokeObjectURL(blob);
}, 100);
} var str_head="<!DOCTYPE html>\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>实用版</title>\n" +
" <style>\n" +
" /*通用属性*/\n" +
" body{ margin: 0; padding: 0; border: 0; text-align: center; overflow: hidden;width: 100%;\n" +
" height: 100%;position: fixed; font-family: verdana,arial,sans-serif; touch-action: none;\n" +
" -ms-touch-action: none;font-size: 12px;min-width: 600px;}\n" +
" ul { list-style: none; margin: 0; padding: 0;}\n" +
" li{ list-style: none; margin: 0; padding: 0;}\n" +
" ul li { float: left;}\n" +
" button{ cursor: pointer; height: 23px;}\n" +
" a:link{ text-decoration: none;}\n" +
" \n" +
" #div_top span,input,button,textarea{margin-left: 20px;float: left;}\n" +
" .p_h1{font-size: 24px;font-weight: bolder;background-color: darkseagreen}\n" +
" .p_text{font-size: 20px;font-weight: normal;text-align: left;background-color: darkseagreen}\n" +
"\n" +
" .div_section{position:relative}\n" +
" .p_a1{font-size: 20px;font-weight: normal;text-align: left;background-color: beige;margin-left: 60px;margin-right: 60px;\n" +
" ;min-height: 80px;display: block;word-break: break-all;overflow-wrap: break-word;white-space: pre-wrap}\n" +
" .p_a2{font-size: 20px;font-weight: normal;text-align: left;background-color: beige;left:120px}\n" +
" </style>\n" +
"</head>";
</script>
</html>
这个小工具代码不多,功能也不复杂,但我认为比较独特的一点是它像单细胞生物一样在一个文件中实现了信息的“保持”、“显示”、“修改”功能,应该具备一定的可发展性,也欢迎大家在此基础上开源更多功能。
用作例子的文章是康德的《纯粹理性批判》(民国蓝公武译本)(http://book.sbkk8.com/waiguo/chuncuilixingpipan/)
感觉这本书被崇拜者们过誉了,现在更适合作为历史和参考。
2020年2月16日修改:
允许用户添加额外的分隔符,处理额外分隔符的代码如下:
var str_split=document.getElementById("str_split").value;
if(str_split)//如果有额外的分割符号
{
var arr_temp=[];
var arr_split=str_split.split("@");
var len2=arr_split.length;
var str_temp="/";
for(var j=0;j<len2;j++)
{
str_temp+=(arr_split[j]+(j==len2-1?"":"|"));
}
str_temp+="/";
var var_split=eval(str_temp);
for(var i=0;i<len;i++)//对于每一个自然段
{
//
var section=arr_section[i];
if(section.length>0)
{
arr_temp=arr_temp.concat(section.split(var_split));
//arr_temp=arr_temp.splice(arr_temp.length,0,section.split(var_split))
}
}
arr_section=arr_temp;
len=arr_section.length;
}
新的html文件可以在https://github.com/ljzc002/ljzc002.github.io/blob/master/%E5%93%B2%E5%AD%A6%E5%AD%A6%E4%B9%A0/Annotate4split.html下载。
2020年4月26日修改:
调整页面样式,添加文本导出方法和适用于知乎的样式调整脚本:
window.ExportZhihu=function()//在控制台里输出所有文本
{
var div_main=document.getElementById("div_main");
var arr_p=div_main.getElementsByTagName("p");
var len=arr_p.length;
var arr_str=[];
for(var i=0;i<len;i++)
{
var p=arr_p[i];
if(p.className=="p_text")
{
arr_str.push(p.innerHTML);
}
else if(p.className=="p_a1")
{
arr_str.push("@"+p.innerHTML+"@");//在注释内容的前后添加@符号
}
}
var str_res=arr_str.join("\r\n");
console.log(str_res)
}
粘贴到知乎发布之后,在知乎页面的控制台里执行
//RichText ztext Post-RichText
//RichText ztext CopyrightRichText-richText
function addBlockQuoteZhihu(){
var arr_richText=document.getElementsByClassName("RichText ztext");
var len=arr_richText.length;
for(var i=0;i<len;i++)
{
var richText=arr_richText[i];
var arr_c=richText.childNodes;
var len2=arr_c.length;
var temp_HTML="";
//var temp_div=document.createElement("div"); for(var j=0;j<len2;j++)//对于每一个节点元素
{
var flag=0;//还未找到开头#
var node=arr_c[j];
if(node.innerHTML.substr(0,1)=="@"&&node.innerHTML.substr(-1,1)=="@")
{
flag=1;//找到了开头和结尾#
node.innerHTML=node.innerHTML.substring(1);//去掉井号
node.innerHTML=node.innerHTML.substring(node.innerHTML.length-1,0);
temp_HTML+="<blockquote>"+node.outerHTML+"</blockquote>";
//temp_div.appendChild(node.cloneNode());//cloneNode只包含标签,没有innerHTML!!还需要自己填
}
else if(node.innerHTML.substr(0,1)=="@")
{
flag=1;//找到了开头#
node.innerHTML=node.innerHTML.substring(1);
temp_HTML+="<blockquote>"+node.outerHTML;
//temp_div.appendChild(node.cloneNode());
}
else if(node.innerHTML.substr(-1,1)=="@")
{
flag=1;//找到了结尾#
node.innerHTML=node.innerHTML.substring(node.innerHTML.length-1,0);
temp_HTML+=node.outerHTML+"</blockquote>";
//temp_div.appendChild(node.cloneNode());
}
if(flag==0)
{
temp_HTML+=node.outerHTML;
//temp_div.appendChild(node.cloneNode());
}
}
richText.innerHTML=temp_HTML;
//richText.innerHTML=temp_div.innerHTML;
} }//下面时压缩为单行的脚本
//function addBlockQuoteZhihu(){var arr_richText=document.getElementsByClassName("RichText ztext");var len=arr_richText.length;for(var i=0;i<len;i++){var richText=arr_richText[i];var arr_c=richText.childNodes;var len2=arr_c.length;var temp_HTML="";for(var j=0;j<len2;j++){var flag=0;var node=arr_c[j];if(node.innerHTML.substr(0,1)=="@"&&node.innerHTML.substr(-1,1)=="@"){flag=1;node.innerHTML=node.innerHTML.substring(1);node.innerHTML=node.innerHTML.substring(node.innerHTML.length-1,0);temp_HTML+="<blockquote>"+node.outerHTML+"</blockquote>";}else if(node.innerHTML.substr(0,1)=="@"){flag=1;node.innerHTML=node.innerHTML.substring(1);temp_HTML+="<blockquote>"+node.outerHTML;}else if(node.innerHTML.substr(-1,1)=="@"){flag=1;node.innerHTML=node.innerHTML.substring(node.innerHTML.length-1,0);temp_HTML+=node.outerHTML+"</blockquote>";}if(flag==0){temp_HTML+=node.outerHTML;}}richText.innerHTML=temp_HTML;}};addBlockQuoteZhihu()
可以将@之间的文本变为区别于正文的样式,如此在发布长篇文章时可以省去样式调整操作。
html小工具——文章注释编辑器的更多相关文章
- 解决wordpress文章归档和分类目录小工具标题重复问题
最近更新了wordpress,发现更新后小工具中的文章归档和分类目录出现了标题重复,经检查,是部分主题下,主题的代码已经输出了标题,而wordpress的代码又再次输出了一次.于是我们需要删除word ...
- PNote桌面贴小工具 - 项目管理系列文章
项目经理在项目过程中将会使用到各种工具,以期能够相互配合,对项目组的各种管理工作进行工作的开展和完成.以前就写过一些项目工具的使用,见下链接: 1.Mindjet MindManager思维导图工具的 ...
- 2014年Windows平台软件推荐:神器小工具(骨灰级
原文 http://www.wtoutiao.com/a/120621.html 底层工具 “If you know how to use Process Monitor competently, ...
- Windows平台软件推荐:神器小工具(骨灰级)
底层工具 "If you know how to use Process Monitor competently, people of both sexes will immediately ...
- 关于 fir.im 你可能不知道的实用小工具
大家可能都知道 fir.im 是做测试发包的,上传你的 IPA/APK, 测试用户可以通过一个短链接和二维码就可快速安装测试. 除了基本的发包功能即应用上传下载外,fir.im 还为提高发包体验提供了 ...
- Animo.js :一款管理 CSS 动画的强大的小工具
Animo.js 是一个功能强大的小工具,用于管理 CSS 动画.它的特色功能包括像堆栈动画,创建跨浏览器的模糊,设置动画完成的回调等等.Animo 还包括惊人的 animate.css,为您提供了近 ...
- 【游戏开发】Excel表格批量转换成CSV的小工具
一.前言 在工作的过程中,我们有时可能会面临将Excel表格转换成CSV格式文件的需求.这尤其在游戏开发中体现的最为明显,策划的数据文档大多是一些Excel表格,且不说这些表格在游戏中读取的速度,但就 ...
- Windows虚拟地址转物理地址(原理+源码实现,附简单小工具)
...
- python小项目之文本编辑器
高考完后这么久才想起这系列教程,实在抱歉,现在该来继续教程了. 本节利用前面所学知识,来完成一个小工具--文本编辑器! tkinter 在实现文本编辑器之前,先来了解下tkinter这个python库 ...
随机推荐
- 更改微信小程序的组件默认样式
checkbox /*checkbox 整体大小 */ .checkbox { width: 12%; /* height: 240rpx; */ } /*checkbox 选项 ...
- 一个ip, 两个域名, 两个ssl, 对应多个不同的项目 之 坑
之前配置了好几天, 就想通过tomcat直接配置. 找各种资料, 都说先配置Connector, 在配置Host. 我试了很多次, 都不成功. 原因我也没有找到在哪里. 我的配置参考如下网址: 修改这 ...
- webpack优化之玩转代码分割和公共代码提取
前言 开发多页应用的时候,如果不对webpack打包进行优化,当某个模块被多个入口模块引用时,它就会被打包多次(在最终打包出来的某几个文件里,它们都会有一份相同的代码).当项目业务越来越复杂,打包出来 ...
- pat 1108 Finding Average(20 分)
1108 Finding Average(20 分) The basic task is simple: given N real numbers, you are supposed to calcu ...
- 十一、设备初始化(ADK4.0)
1.1 首先初始化连接库 sinkConnectionInit();à ConnectionInitEx2(); theCm.task.handler = connectionBluesta ...
- Clean Code 笔记 之 第四章 如何应用注释
继上一篇笔记之后,今天我们讨论一下 代码中是存在注释是否是一件好的事情. 在我们开发的过程中讲究“名副其实,见名识意”,这也往往是很多公司的要求,但是有了这些要求是不是我们的代码中如果存在注释是不是意 ...
- 带你涨姿势的认识一下 Kafka 消费者
之前我们介绍过了 Kafka 整体架构,Kafka 生产者,Kafka 生产的消息最终流向哪里呢?当然是需要消费了,要不只产生一系列数据没有任何作用啊,如果把 Kafka 比作餐厅的话,那么生产者就是 ...
- flexpaper跨服务器访问swf不显示问题
在项目中使用flexpaper.html在线预览时,发现文件存放在本地localhost能访问,在服务器上的无法访问,通常报错“loadswf() is not defined” 研究发现是跨域问题导 ...
- toString() 方法的参数
除开null 和 undefined之外所有的数据类型都是拥有toString方法的. 通常情况下我们使用toString()方法的时候都是不用传递参数的,但是Number类型的toString方法是 ...
- Fortran文件读写--xdd
1.常规读写 program FileWriteRead implicit none open(unit=,file="F:\desktop\File.txt") !open(un ...