• 博客园网摘firefox插件源码分析


    首先说明下,博客园火狐版插件安装后,在工具栏没有logo,只有右键菜单,状态栏有。

    参考资料:firefox开发详细指南(中文) http://blog.csdn.net/z6482/article/details/7317766

                  http://blog.csdn.net/sding/article/details/5697652

                  http://blog.csdn.net/jxfengzi/article/details/4775352

                  http://blog.csdn.net/chenyanxu/article/details/3973545

                  http://blog.csdn.net/Xscarlet/article/details/1708102

    1.插件下到本地后,将后缀名.xpi修改为.zip,解压后得到目录文件cnblogswz,目录结构如下:

    .
    │	chrome.manifest //设置资源路径
    │	install.rdf     //安装信息描述文件
    │
    ├─defaults
    │	└─preferences
    │		cwz.js  //保存option.xul配置的数值
    │
    └─content
    cwz.js //js函数,供cwz.xul调用。向博客园服务器发送请求,提交数据 cwz.xul //配置‘添加到博客园’右键弹出窗体,添加成功提示窗体,登陆提示窗体
    logo_small.gif //logo图片
    option.xul //配置设置窗体
    overlay.js //js函数,供overlay.xul调用。单击子菜单‘添加到博客园’的左右键事件
    overlay.xul //配置菜单项


    2.对目录文件遍历分析

    根目录:
      install.rdf  描述了扩展安装所需要的信息,包括了扩展的标识、版本、适用的应用程序、作者等等等等。

    <?xml version="1.0"?>
    <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
        <Description about="urn:mozilla:install-manifest"> //设置插件安装路径资源文件
            <em:id>contact@cnblogs.com</em:id> //设置id,保证与其他插件id不一致即可
            <em:version>1.2</em:version> //插件版本
            <em:targetApplication>
                <Description>
    //表明此扩展是针对firefox的,而不是thunderbird、sunbird,所以,只要是针对firefox的扩 展,此id的值都不变。
                    <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>

                    <em:minVersion>3.0</em:minVersion> //支持火狐浏览器最低版本
                    <em:maxVersion>9.*</em:maxVersion> //支持火狐浏览器最高版本
                </Description>
            </em:targetApplication>
            <em:name>CnblogsWz(博客园网摘)</em:name> //插件名称
    //插件描述
            <em:description>This is a Cnblogs Wz plug-in, you can bookmark article to Cnblogs Wz(这是一个博客园网摘插件,可以收藏文章到博客园网摘)</em:description>

            <em:optionsURL>chrome://cwz/content/option.xul</em:optionsURL> //插件设置项路径
            <em:creator>博客园</em:creator>
        </Description>
    </RDF>

    chrome.manifest 让fierfox找到扩展的content、locale、skin文件在哪里

    content cwz content/ //指明,包名为cwz(类似于java中的包名),content类型文件在content子目录下
    //指明,chrome://cwz/content/overlay.xul加载到chrome://browser/content/browser.xul中
    overlay chrome://browser/content/browser.xul chrome://cwz/content/overlay.xul


    defaults目录:

    cwz.js 保存设置面板中设置的数值,在option.xul中会对其引用

    pref("extensions.cwz.showContextMenu", true);
    pref("extensions.cwz.showStatusBarIcon", true);
    pref("extensions.cwz.quickClose", false);
    pref("extensions.cwz.silentPost", false);

    content目录:

    logo_small.gif logo图片在cwz.xul中有引用

    option.xul

    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
    <prefwindow xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" windowtype="cwzoption" title="设置">
        <prefpane>
            <preferences>
    //类型为boolean,初始值为true,对应cwz.js中pref("extensions.cwz.quickClose", false);


                <preference id="quickClose" name="extensions.cwz.quickClose" instantApply="true" type="bool" />
    //类型为boolean,初始值为true,对应cwz.js中pref("extensions.cwz.silentPost", false);


                <preference id="silentPost" name="extensions.cwz.silentPost" instantApply="true" type="bool" />
            </preferences>
            <groupbox>
                <checkbox preference="quickClose" label="立即关闭窗口(不等待3秒)"/> //UI显示,取值对应preference中的quickClose
                <checkbox preference="silentPost" label="静默方式(不弹窗)"/> //UI显示,取值对应preference中的silentPost
            </groupbox>
        </prefpane>
    </prefwindow>

    overlay.xul 设置菜单UI

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE overlay SYSTEM "chrome://httpresponsereplace/locale/browserOverlay.xul.dtd">
    <overlay id="cwz-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    //加载鼠标事件处理js
        <script src="overlay.js"/>
    //在工具栏中添加子菜单
        <toolbarpalette id="BrowserToolbarPalette">
            <toolbarbutton>...</toolbarbutton>
        </toolbarpalette>
    //在状态栏中添加子菜单
        <statusbar id="status-bar">
            <statusbarpanel id="cwz-status">
    ...
            </statusbarpanel>
        </statusbar>
    //在鼠标右键菜单中添加子菜单
        <popup id="contentAreaContextMenu">
            <menuitem id="cwz-context" label="添加到博客园网摘"  insertafter="context-stop" onclick='cwz.showWindow(event)'/>
        </popup>
    </overlay>

    overlay.js 菜单事件

    //监听器
    var cwz = {
        init: function () {
        },
        showWindow: function (event) {
    //单击左键事件
            if (event.button == 0) {
    //获取包cwz的配置
                var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("extensions.cwz.");
    //取配置项silentPost数值
                var a = prefs.getBoolPref("silentPost");
    //如果配置为不弹出对话框,则直接向博客园提交网摘数据
                if (a) {
                    var currentWebDoc = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService().QueryInterface(Components.interfaces.nsIWindowMediator).
    getMostRecentWindow("navigator:browser").getBrowser().mCurrentBrowser.contentDocument;

                    var xmlHttp = new XMLHttpRequest;
                    xmlHttp.open("get", 'http://home.cnblogs.com/wz/AddWZ?url=' + currentWebDoc.location + '&title=' + escape(currentWebDoc.title), true);
                    xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                    xmlHttp.send();
                    return;
                }
    //否则打开添加网摘的UI
                window.open("chrome://cwz/content/cwz.xul", "cwz", "chrome,resizable=no,centerscreen", this);
                var win = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow("cwz");
                if (win) {
                    win.focus();
                }
    //单击右键事件
            } else if (event.button == 2) {
    //打开设置对话框UI
                window.openDialog("chrome://cwz/content/option.xul", "cwzoption", "chrome,resizable=no,centerscreen", this);
    //获取对话框句柄
                var win = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator).
    getMostRecentWindow("cwzoption");
    //聚焦
                if (win) {
                    win.focus();
                }
            }
        }
    }
    //添加监听器
    window.addEventListener("load", cwz.init, false);

    cwz.xul 添加网摘UI

    <?xml version="1.0" encoding="utf-8"?>
    <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
    //执行js中onload()
    <window onload="onLoad()" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    width="400" height="345" title="博客园网摘" windowtype="cwz">
      //加载事件处理js
    <script src="cwz.js"></script>
    //横向盒子
      <vbox style="padding-left:15px;padding-top:5px;">
    //竖盒子
          <hbox height="48" style="border-bottom:1px solid #CCCCCC;padding-bottom:3px;margin-bottom:5px;">
    //引用logo图片
                <image height="45" src="logo_small.gif"/>
                <spacer flex="1"/>
    //横盒子
                <vbox height="45">
                    <spacer flex="1"/>
    //设置连接
                    <label class="text-link" href="http://home.cnblogs.com/wz/" value="我的网摘"/>
                </vbox>
                <spacer flex="0"/>
                <hr/>
          </hbox>
            <vbox id="panel_add">
                <hbox height="28" style="padding-top:3px;">
                     <label control="tb_url" value="网址:"/>
                     <textbox id="tb_url" width="300" multiline="false" cols="100"/>
                </hbox>
                <hbox height="28" style="padding-top:3px;">
                     <label control="tb_title" value="标题:"/>
                     <textbox id="tb_title" width="300" multiline="false" cols="100"/>
                </hbox>
                <hbox height="28" style="padding-top:3px;">
                  <label control="tb_tags" value="标签:"/>
                  <textbox id="tb_tags" multiline="false" width="200" cols="70"/>
                  <a id="select_block" onclick="showTag()">选择标签</a>
                  <label style="color:Green" value="(逗号隔开)"/>
                </hbox>
                <hbox>
                  <stack id="tagselect" style="display:none;200px">
                    <vbox style="border: 2px solid #97ACD2;margin:10px;">
                      <hbox style="border-bottom:1px solid #CCC;padding:5px;padding-bottom:2px;">
                        <hbox style="color:#999">选择tag</hbox>
                        <hbox onclick="closeTag()" style="margin-left:258px;cursor:pointer;">关闭</hbox>
                      </hbox>
                      <vbox style="height:100px;overflow:auto">
                        <description id="editMenu" align="start" left="0" right="0">
                          <html:div id="tags_box"></html:div>
                        </description >
                      </vbox>
                    </vbox>
                  </stack>
                </hbox>
                <hbox height="105" style="padding-top:3px;">
                     <label control="ta_summary" value="摘要:"/>
                     <vbox>
                     <textbox id="ta_summary" multiline="true" rows="4" cols="44"/>
                     <label style="color:Green" value="(不超过200字)"/>
                     </vbox>
                </hbox>
                <hbox height="20">
                     <spacer style="44px" flex="0"/>
                     <checkbox id="isPrivate" label="私有网摘" checked="false"/>
                </hbox>
                <hbox>
                     <spacer style="44px" flex="0"/>
    //按钮,单击后触发事件
                     <button oncommand="addwz()" id="btnaddwz" style="45px;min-1em;height:20px;" label="收藏"/>
                </hbox>
            </vbox>
          <vbox>
              <label id="as" style="padding:10px;color:Red" value=""/>
    //隐藏的盒子
              <label id="loginl" style="padding-left:10px;display:none;color:Red" class="text-link" href="http://passport.cnblogs.com/login.aspx" value="点此进行登录"/>
              <label id="closet" style="padding-left:10px;display:none;color:Green;" value="3秒后本窗口将自动关闭。"/>
          </vbox>
      </vbox>
    //div
      <div id="tag_box"></div>
    </window>

    cwz.js


    function onLoad()
    {
    //获取当前网页doc
        var currentWebDoc = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService().QueryInterface(Components.interfaces.nsIWindowMediator).getMostRecentWindow("navigator:browser").
    getBrowser().mCurrentBrowser.contentDocument;
        //为盒子中的tb_url赋值
    document.getElementById("tb_url").value = currentWebDoc.location;
        document.getElementById("tb_title").value = currentWebDoc.title;
    }

    //html编码
    function htmlEncode(str) {
    //获取所有的div标签句柄
        var div = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
        div.textContent = str;
    //转换为innerHTML
        return div.innerHTML;
    }

    //添加网摘
    function addwz()
    {
        var isprivate = "on";
        if (document.getElementById("isPrivate").checked) {
            isprivate = "";
        }
        var wz = {};
        wz.url = document.getElementById("tb_url").value;
        wz.title = document.getElementById("tb_title").value;
        wz.tags = document.getElementById("tb_tags").value;
        wz.summary = document.getElementById("ta_summary").value;
        wz.isPrivate = isprivate;
        if (wz.tags.length > 0) {
            wz.tags = wz.tags.replace(/,/g, ',');
        }
        if (wz.summary.length > 200) {
            wz.summary = wz.summary.substring(0, 200);
        }
        document.getElementById("btnaddwz").label = "please wait...";
        document.getElementById("btnaddwz").style.width = "100px";
        document.getElementById("btnaddwz").disabled = true;
        var xmlHttp = new XMLHttpRequest;
    //请求
        xmlHttp.open("get", 'http://home.cnblogs.com/wz/AddWZ?url=' + encodeURIComponent(wz.url) + '&title=' + encodeURIComponent(htmlEncode(wz.title)) + '&tags=' + encodeURIComponent(wz.tags) + '&summary=' + encodeURIComponent(htmlEncode(wz.summary)) + '&isPrivate=' + wz.isPrivate, true);
    //回调函数
        xmlHttp.onreadystatechange=function()
        {
    //获得异步回执
            if(xmlHttp.readyState==4)
            {
    //返回成功
                if(xmlHttp.status==200)
                {
    //显示登录提示
                    if(xmlHttp.responseText.length==4)
                    {
                        document.getElementById("as").value=xmlHttp.responseText;
                        document.getElementById("panel_add").style.display="none";
                        document.getElementById("loginl").style.display="block";
                    }
    //显示添加成功提示
                    else
                    {
                        document.getElementById("as").value=xmlHttp.responseText;
                        document.getElementById("panel_add").style.display="none";
                        document.getElementById("closet").style.display="block";
                        var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("extensions.cwz.");
    //获取cwz.js中配置项quickClose
                        var a = prefs.getBoolPref("quickClose");
                        if (a)
                        {
                            window.opener=null;
                            window.close();
                        }
                        else
                        {
    //3秒后关闭窗口
                            setTimeout("window.opener=null;window.close()",3000);
                        }
                    }
                }
            }
        }
        xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    //发送请求
        xmlHttp.send(true);
    }

    //选中标签并设置css样式
    function $(ID) {
        var element = document.getElementById(ID);
        if (element) {
            element.css = css;
        }
        return element;
    }

    //设置css样式
    function css(prop, value) {
        if (value == null) {
            return this.style[prop];
        }
        if (prop) {
            this.style[prop] = value;
        }
        return true;
    }

    //添加tag事件
    function addTag(tagName) {
        var TagStr = document.getElementById("tb_tags").value;
    //将tagName添加到tb_tags中
        if (TagStr.indexOf(tagName) == -1) {
            if (TagStr == '')
                TagStr = TagStr + tagName;
            else
                TagStr = TagStr + "," + tagName;
            document.getElementById("tb_tags").value = TagStr;
        }
    }

    //显示标签
    function showTag() {
    //如果tags_box已有内容则,显示选择项
        if ($("tags_box").textContent.length > 1) {
            $("tagselect").css("display", "block");
        }
        else {
    //向博客园查询已创建的标签
            var xmlHttp = new XMLHttpRequest;
            xmlHttp.open("get", 'http://home.cnblogs.com/wz/GetUserTags', true);
            xmlHttp.onreadystatechange = function () {
                if (xmlHttp.readyState == 4) {
                    if (xmlHttp.status == 200) {
    //回调函数
                        showTag_CallBack(xmlHttp.responseText);
                    }
                }
            }
            xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            xmlHttp.send(true);
        }
    }

    //显示标签的回调函数
    function showTag_CallBack(data) {
        $("tagselect").css("display", "block");
        $("select_block").css("cursor", "default");
        data = data.slice(5, -6);
        $("tags_box").innerHTML = data;
    }

    //关闭选择
    function closeTag() {
        $("tagselect").css("display", "none");
        $("select_block").css("cursor", "pointer");
    }

    --OVER








  • 相关阅读:
    .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
    使用Visual Studio Code开发.NET Core看这篇就够了
    ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了
    asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程
    【半译】扩展shutdown超时设置以保证IHostedService正常关闭
    从零搭建分布式文件系统MinIO比FastDFS要更合适
    用asp.net core结合fastdfs打造分布式文件存储系统
    在ASP.NET Core中创建基于Quartz.NET托管服务轻松实现作业调度
    Nuget多项目批量打包上传服务器的简明教程
    一个新实验:使用gRPC-Web从浏览器调用.NET gRPC服务
  • 原文地址:https://www.cnblogs.com/zhuri/p/2672276.html
Copyright © 2020-2023  润新知