Posts Tagged ‘Flash

之前写过一篇使用Flash实现本地存储的文章,介绍如何使用flash存储本地数据。这个方案用在早期IE下是非常合适的,我所在的项目一直在用。出于安全的考虑,我们需要在as代码里设置允许与flash交互的域名,也就是前文代码里的这一行:

Security.allowDomain("*");//修改为自己的域名

以前,我是把需要交互权限的域名list编到as文件中,这个list很少需要改,所以一直也没什么问题。最近有意把storage组件放在QWrap提供下载,这个做法就不适用了。GitHub上有个叫SwfStore的同类组件遇到类似的问题,作者写了一段说明,挺有意思的:

=======
Security Warning
=======

The default storage.swf allows any website to read the data in your flash file. You should avoid storing private information in it.

It would be wise to edit and recompile the flash file to limit itself to your domain and http/https settings. If you do not have a copy of Adobe Flash, I can do it for you for $5 - email me for details.

大概是说他的代码默认允许所有网站访问flash存储,用户不要用它存隐私数据;当然更好的做法是把权限改到自己的域名。如果没编译工具,还可以花$5找作者代劳=.=

Read the rest of this entry »

很早之前,写过一篇“跨浏览器“复制到剪贴板”的解决方案”,当时给出的解决方案是,IE使用window.clipboardData,firefox等其它浏览器使用flash来调用System.setClipboard方法。但是,随着Flash10安全策略更新,只允许在flash内部调用setClipboard方法,那篇文章给出的demo已经失效。我重新写了一个demo,见这里

新demo是在flash内部调用的setClipboard方法,原则上安装了flash的浏览器都可以用;另外,IE7及以上版本用js调用clipboardData会弹出选择是否允许的提示,往往初级用户看到这样提示还以为网站有病毒,所以这次一视同仁所有浏览器都用flash写剪切板。原理比较简单,大概说一下:

  • 页面上提供两个js方法getData和copySuccess供flash调用,getData返回需要复制的内容,copySuccess是复制成功的回调函数;
  • 往flash里添加一个任意的DisplayObject,例如TextField,注册Click事件,事件响应函数里先调用页面上的js方法getData得到粘贴内容,再用System.setClipboard写入剪切板,最后通知页面上的copySuccess。

完整的代码见这里。如果要个性化提示文字,打开clipboard.as,修改后编译即可。

本文链接:http://www.imququ.com/post/38.html

--EOF--

刚开始学习flash as3编程,一些学习笔记也丢上来吧,现在还都是些初级的话题~

Flash已经提供了ExternalInterface接口与JavaScript通信,ExternalInterface有两个方法,call和addCallback,call的作用是让Flash调用js里的方法,addCallback是用来注册flash函数让js调用。下面是官方文档对call和addCallback的说明:

利用 ActionScript,可以在 HTML 页上执行以下操作:

  • 调用任何 JavaScript 函数。
  • 传递任意数量、具有任意名称的参数。
  • 传递各种数据类型(Boolean、Number、String 等等)。
  • 接收来自 JavaScript 函数的返回值。

通过在 HTML 页上使用 JavaScript,可以:

  • 调用 ActionScript 函数。
  • 使用标准的函数调用表示法传递参数。
  • 将值返回给 JavaScript 函数。

实际使用的时候,需要注意以下两点:

Read the rest of this entry »

今天无意中看到一个画面还不错的webgame,随手右键单击看是否用flash写的(我对flash的判断标准是看右键菜单有无About Adobe Flash Player…字样),但是点了居然不出任何菜单。记得之前看到要完全干掉flash右键菜单要用到一些很WS的方法,不知道这个webgame怎么实现的。看了一下它的代码,原来是在flash父容器里做文章:firefox下阻止mousedown默认事件及事件传播;IE下给父容器setCapture。摘录核心代码稍加改造就是下面这个样子:

function NoRightClick(pid){//pid:flash's parentNode id
 var el = document.getElementById(pid);
 if(el.addEventListener){
  el.addEventListener("mousedown",function(event){
   if(event.button == 2){
    event.stopPropagation(); //for firefox
    event.preventDefault();  //for chrome
   }
  },true);
 }else{
  el.attachEvent("onmousedown",function(){
   if(event.button == 2){
    el.setCapture();
   }
  });
  el.attachEvent("onmouseup",function(){
   el.releaseCapture();
  });
  el.oncontextmenu = function(){
   return false;
  };
 }
};
<body>
 <div id="testContent" style="width:800px">
 </div>
 <script type="text/javascript">
  var so = new SWFObject("test.swf", "t1", "800", "550", "9", "#000000");
  so.addParam("quality", "high");
  so.addParam("name", "t1");
  so.addParam("id", "t1");
  so.addParam("algin", "middle");
  so.addParam("AllowScriptAccess", "sameDomain");
  so.addParam("menu", "false");
  so.addParam("wmode", "opaque");
  so.addParam("pluginspage", "http://www.adobe.com/go/getflashplayer");
  so.write("testContent");
 
  NoRightClick("testContent");
 </script>
</body>

经过试验,该代码可以在IE、Firefox和Google Chrome里去掉flash的右键菜单,还是挺方便的。至于这样做有什么意义呢?我暂时还没有想到——但网上搜索一下,有这种需求的人还是不少的。

演示地址

本文链接:http://www.imququ.com/post/42.html

--EOF--

之前写过一篇文章跨浏览器“复制到剪贴板”的解决方案,里面讲到在Firefox下如果安装了Flash,就可以利用js调用flash的setClipboard方法来将一段文字写进系统剪切板。但是最近发现,在很多电脑上这种方法已经失灵了。研究了一下,发现是flash10更新了安全策略:新的策略只允许在flash内部调用setClipboard方法,利用js调用无效;当然,如果在flash里添加事件来执行setClipboard是在允许范围内的。

除了setClipboard的更新外,还有一个比较大的更新就是:FileReference.browse和FileReference.download将只能通过Flash 内容响应鼠标或键盘的操作来使用。也就是说类似于SWFUpload一类的通过js来打开文件选择框的应用将会无法工作!SWFUpload官方采用”在SWF中引入一个按钮,用户点击此按钮来触发文件选择对话框的显示”的方案解决的这一问题。

Flash的这次安全升级给我的启示:最好不要用一种语言来做本来不属于他做的事(例如利用window.name跨域传输数据等等),尽管这些Hack在很多情况下很好用,但也最容易因为某次更新升级而失效。

参考:
http://www.jeffothy.com/weblog/clipboard-copy#comment-123736
http://www.v-sky.com/blog/?p=227

本文链接:http://www.imququ.com/post/44.html

--EOF--

我在5月份的一篇文章里列举了一些本地存储解决方案, 包括常见的Cookie、UserData和不是那么常见的globalStorage、Database Storage。文章最后提到了另外两种解决方案:Google Gear和Flash,当时因为觉得用不上就没仔细研究。但实际应用中,那篇文章列出的方案还是不能满足项目的需求。这篇文章就讲一下如何使用Flash来实现本地存储,以及该方案使用的场合。

拿IE6来说,如果要在本地大量存放数据,Cookie因为存放内容太少、浪费用户带宽首先就应该被淘汰掉。UserData在大多数情况下能满足需求,但是它也有一个致命的弱点:只能读取同目录存储,也就是a目录下一个文件不能读取b目录下两一个文件存放的数据。MSDN说明如下:

Security Alert For security reasons, a UserData store is available only in the same directory and with the same protocol used to persist the store. 全文>>

也就是说如果项目中要跨文件夹操作本地存储,UserData也必须被淘汰了。IE不支持Database Storage,IE8才增加了对globalStorage的支持,这个时候Flash就派上用场了。

首先,打开Flash,建立一个工程,编写get、set、remove三个方法并提供给外部程序调用:

package
{
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.TimerEvent;
  import flash.net.SharedObject;
  import flash.system.Security;
  import flash.external.ExternalInterface;
  import flash.utils.Timer;
  
  public class Main extends Sprite {
    
    Security.allowDomain("*");//修改为自己的域名
    private const storageName:String = "data";
 
    public function Main() {
      addExternalInterface();
    }
    
    private function addExternalInterface():void {
      function set(key:String, val:String = ""):void {
        var sobj:SharedObject = SharedObject.getLocal(storageName, "/", false);
        sobj.data[key] = val;
        sobj.flush();
      }
 
      function get(key:String):String{
        var sobj:SharedObject = SharedObject.getLocal(storageName, "/", false);
        return(sobj.data[key]);
      }
 
      function remove(key:String):void{
        var sobj:SharedObject = SharedObject.getLocal(storageName, "/", false);
        delete sobj.data[key];
        sobj.flush();
      }
      
      function isJavaScriptReady():Boolean {
        var isReady:Boolean = ExternalInterface.call("isJSReady");
        return isReady;
      }
      
      function jsReadyHandler():void {
        trace("javascript js ready"); 
        ExternalInterface.addCallback("set", set);
        ExternalInterface.addCallback("get", get);
        ExternalInterface.addCallback("remove", remove);
        ExternalInterface.call("flashReadyHandler");
      }
      
      if (ExternalInterface.available) {
        try {
          if (isJavaScriptReady()) {
            jsReadyHandler();
          }else {
            var timerReady:Timer = new Timer(100, 0);
            timerReady.addEventListener(TimerEvent.TIMER, function(evt:TimerEvent):void {
              trace("checking..."); 
              if (isJavaScriptReady()) {
                Timer(evt.target).stop();
                jsReadyHandler();
              }
            });
            timerReady.start();
          }
        }catch (err:SecurityError) {
          trace(err.message);
        }catch (err:Error) {
          trace(err.message);
        }
      }
    }
  }
}

其中,核心功能是依靠SharedObject来实现的。对于这个对象,Adobe官方说明如下:

Shared objects are quite powerful: they offer real-time data sharing between objects that are persistent on the local location. You can think of local shared objects as “cookies.”

You can use local shared objects to maintain local persistence. This is the simplest way to use a shared object. For example, you can call SharedObject.getLocal to create a shared object, such as a calculator with memory, in the player. Because the shared object is locally persistent, Flash saves its data attributes on the user’s machine when the movie ends. The next time the movie runs, the calculator contains the values it had when the movie ended. Alternatively, if you set the shared object’s properties to null before the movie ends, the calculator opens without any prior values the next time the movie runs. 全文>>

补充一下,SharedObject存储在本地的内容是可以跨浏览器读取的,也就是在IE中存储的内容,可以在firefox中读到,这是一个比较有用的特性。另外,SharedObject一般把内容存在下列位置:

Windows XP:C:\Documents and Settings\[1]\Application Data\Macromedia\Flash Player\#SharedObjects\[2]\[3]\[4].sol

Windows Vista:C:\Users\[1]\AppData\Roaming\Macromedia\Flash Player\#SharedObjects\[2]\[3]\[4].sol
([1]:系统当前用户,[2]:随机字符目录,[3]:网站域名,[4]:SharedObject对象名)

然后用把编译得到的swf文件加到页面中,利用js来调用flash中对应的三个方法就OK了,具体方法都写在演示文件里,就懒得贴出来了。演示地址在这里。(请用IE浏览器打开

update:更新了demo,支持所有的浏览器。

本文链接:http://www.imququ.com/post/74.html

--EOF--

众所周知,firefox的安全性比较高,但是安全带来的弊端就是很多功能不支持。比如说在IE下可以通过脚本来设当前网页为首页,firefox却不行。今天要讨论的是另外一个问题:怎么在firefox等不支持window.clipboardData的浏览器下实现复制呢?

首先,我们来看网易邮箱是怎么解决这个问题的。我们在firefox下进到写邮件页面,点击编辑器上的全部功能,然后点击左边的“复制”按钮,“您的浏览器安全设置不允许编辑器自动执行拷贝操作,请使用键盘快捷键(Ctrl C)来完成”,网易邮箱给了我们这么一个提示。我觉得这个解决方案可以得80分,因为它告诉了我们两个信息:其一,之所以复制操作没有完成是因为我的浏览器很安全,为了安全损失一点用户体验一般用户是可以接受的;其二,它还提示了我们可以通过键盘快捷键ctrl c来完成操作,这对刚上网的新手来说很人性化。但是,有没有更好的解决方案呢?

网上大致有两种解决方案,一种是需要修改firefox配置,其实firefox也是支持复制的,但是需要到about:config里去手动开启,这里不做介绍了;另外一种解决方案是本文要用到的flash。因为flash可以方便的把文字拷贝到系统剪切板中,所以我们利用flash来做跳板,只需要一行代码就能搞定:

System.setClipboard(clipboard);

这句代码的含义后面还会提到。有了这个swf的跳板,剩下的工作就简单了,如果浏览器不支持window.clipboardData,就在复制的时候把内容传给这个flash,就OK了,关键代码如下:

if (window.clipboardData){
    window.clipboardData.setData("Text",str);
}else{
    var flashId = '_clipboard_';
    var flashContent = '<embed src="clipboard.swf" FlashVars="clipboard=' str.replace(/\ /g,"+") '" width="0" height="0" type="application/x-shockwave-flash"></embed>';
    if(!document.getElementById(flashId)){
        var flash = document.createElement("div");
        flash.id = flashId;
        flash.innerHTML = flashContent;
        document.body.appendChild(flash);
    }else{
        document.getElementById(flashId).innerHTML = flashContent;
    }
}

测试地址

adobe的文档中对setClipboard有如下解释:

setClipboard () 方法

public static function setClipboard(string:String):void

语言版本 : ActionScript 3.0
Player 版本 : Flash Player 9

用指定的文本字符串替换剪贴板的内容。

注意:出于安全方面的考虑,您无法读取系统剪贴板的内容。 换句话说,不存在相应的 System.getClipboard() 方法。

参数

  string:String — 要放置在系统剪贴板上的纯文本字符串,用于替换系统剪贴板上的当前内容(如果有)。

由此可见,我们只能利用flash把文字复制到系统剪贴板中,而不能把系统剪切板中的内容拷贝出来。

本文链接:http://www.imququ.com/post/61.html

--EOF--

关于我

JerryQu,当前从事前端开发,@中国北京
这里是我随便记录东西的地方~
需要找我,我的联系方式在这里»
查找QGYWebIM相关信息,请点这里»

  • PPanda sftp如何同步本地文件夹呢?
  • dron 嗯!太有用了,终于完美找回 EditPlus 的感觉了。
  • 袁源 还真的是这样。其实挺佩服微软的呀~就是都太不完善了
  • 三水清 类似功能可以使用fiddler,http://ming.sinaapp.com/?p=218
  • 呆呆 非常感谢~话说我现在想把weinre变成一个服务器,就是我在电脑上修改了,手机上访问可以直接,不知道[...]
  • 困扰了我好几天的问题,不过最后还是让我解决了,要早让我看见这个文章该多好啊,那我也不用烦恼那么久了~[...]
  • hoowolf 非常感谢你的工作!!!
  • welefen 恩,去年我们在新首页导航精准下线的时候也遇到过,当时还做了对用户影响的数据评估和分析。
  • 唠叨下 我们这边测试的时候是在刚做完 preload 后的系统上测试的,就跟刚装完操作系统后一样干净。怎么说[...]
  • gust 我是在ubuntu11.10环境下
  • gust 想用google浏览器的话可以这样 webbrowser.get('/usr/bin/google[...]
  • jin 怎么zenCoding的缩写设置呢,类似editplus下的acp配置
  • Jerry Qu @Feather,确实Shadow是基于Weinre封装的。在我这里也很慢,因为它连的是http:/[...]
  • Feather 谢谢分享,其实Adobe的Shadow产品貌似也是用这个原理来做的,不过shadow封装好,比较方便[...]
  • i am bug 感谢屈屈!