Category Archives: Frontend

Advanced HTML5 JavaScript down ‘n dirty

[html5]网页的全屏模式: Fullscreen API

Demon页面

它是怎么工作的呢? 比如<div>这个元素想要全屏, 首先需要

div.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
div.mozRequestFullScreen();

退出全屏模式, 只需要在docment元素做操作即可:

document.webkitCancelFullScreen();
document.mozCancelFullScreen();

当全屏模式被创建后, 你需要针对这个div设置一下css.例如:

div:-webkit-full-screen{
  width: 100% !important;
}
div:-moz-full-screen{
 width: 100% !important;
}
:-webkit-full-screen .tohide{
 display:none;
}
:-moz-full-screen .tohide{
 display:none;
}

Fullscreen API在chrome 15下已经默认开启了, 在Firefox night builds版本下, 你需要在about:config中设置fullscreen-api.enabled为true. 了解更多详情可以参阅Fullscreen设计草案.

使用js读取文件


文章原地址: Reading locale files in Javascript

简介

HTML5通过File API提供了一套读取文件的标准方法.

 

选择文件

首先我们通过以下代码检测你的浏览器是否支持File API:

if (window.File && window.FileReader && window.FileList && window.Blob){
//你的浏览完全支持这些API
}else{
//你的浏览器不完全支持这些API
}

通过input方式上传文件

<input id="files" type="file" name="files&#91;&#93;" />
<output id="list"></output>
<script type="text/javascript">
function handlerFileSelect(e){
  var files = e.target.files;//从event中获取FileList
  var output = [];
  for (var c = 0, f; f = files[c]; ++c){
    output.push("<li><b>", f.name, "</b> (", f.type || "n/a", ")-", f.size, " bytes, last modified: ", f.lastModifiedDate.toLocaleDateString(), "</li>");
  }
  document.getElementByID("list").innerHTML = "<ul>" + output.join("") + "</ul>";
}
document.getElementByID("files").addEventListener("change", handlerFileSelect, false);
</script>

示例: 现在我们就来尝试一下.


通过拖放功能上传文件

这个是html5新增的一个功能, 可以让你直接从桌面拖文件到指定区域.

<div id="drop_zone">将文件拖放到此处</div>
<output id="list"></output>

<script>
function handleFileSelect(e){
  e.stopPropagation();
  e.preventDefault();

  var files = e.dataTransfer.files;
  var output = [];
  for (var c =0, f; f = files[c]; ++c){
    output.push("<li><b>", f.name, "</b> (", f.type || "n/a", ")-", f.size, " bytes, last modified: ", f.lastModifiedDate.toLocaleDateString(), "</li>");
  }
  document.getElementByID("list").innerHTML = "<ul>" + output.join("") + "</ul>";
}

function hanleDragOver(e){
  e.stopPragation();
  e.preventDefault();
  e.dataTransfer.dropEffect = "copy";
}

var dropZone = document.getElementByID("drop_zone");
dropZone.addEventListener("dropover", handleDragOver, false);
dropZone.addEventListener("drop", handleFileSelect, false);
</script>

备注: 有些浏览器

<input type="file">

直接支持原生的拖放.

读取文件

最最重要部分来了.
在你获取文件后, 就要开始使用FileReader读取文件了.
FileReader共有4种方式:

  1. FileReader.readAsBinaryString(Blob|File) –
  2. FileReader.readAsText(Blob|File, opt_encoding) –
  3. FileReader.readAsDataURL(Blob|File) –
  4. FileReader.readAsArrayBuffer(Blob|File) –
<style>
  .thumb {
    height: 75px;
    border: 1px solid #000;
    margin: 10px 5px 0 0;
  }
</style>

<input type="file" id="files" name="files&#91;&#93;" multiple />
<output id="list"></output>

<script>
  function handleFileSelect(evt) {
    var files = evt.target.files; // FileList object

    // Loop through the FileList and render image files as thumbnails.
    for (var i = 0, f; f = files[i]; i++) {

      // Only process image files.
      if (!f.type.match('image.*')) {
        continue;
      }

      var reader = new FileReader();

      // Closure to capture the file information.
      reader.onload = (function(theFile) {
        return function(e) {
          // Render thumbnail.
          var span = document.createElement('span');
          span.innerHTML = ['<img class="thumb" src="', e.target.result,
                            '" title="', theFile.name, '"/>'].join('');
          document.getElementById('list').insertBefore(span, null);
        };
      })(f);

      // Read in the image file as a data URL.
      reader.readAsDataURL(f);
    }
  }

  document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>

解析文件

二进制读取

if (file.webkitSlice) {
  var blob = file.webkitSlice(startingByte, endindByte);
} else if (file.mozSlice) {
  var blob = file.mozSlice(startingByte, endindByte);
}
reader.readAsBinaryString(blob);
<style>
  #byte_content {
    margin: 5px 0;
    max-height: 100px;
    overflow-y: auto;
    overflow-x: hidden;
  }
  #byte_range { margin-top: 5px; }
</style>

<input type="file" id="files" name="file" /> Read bytes: 
<span class="readBytesButtons">
  <button data-startbyte="0" data-endbyte="4">1-5</button>
  <button data-startbyte="5" data-endbyte="14">6-15</button>
  <button data-startbyte="6" data-endbyte="7">7-8</button>
  <button>entire file</button>
</span>
<div id="byte_range"></div>
<div id="byte_content"></div>

<script>
  function readBlob(opt_startByte, opt_stopByte) {

    var files = document.getElementById('files').files;
    if (!files.length) {
      alert('Please select a file!');
      return;
    }

    var file = files[0];
    var start = parseInt(opt_startByte) || 0;
    var stop = parseInt(opt_stopByte) || file.size - 1;

    var reader = new FileReader();

    // If we use onloadend, we need to check the readyState.
    reader.onloadend = function(evt) {
      if (evt.target.readyState == FileReader.DONE) { // DONE == 2
        document.getElementById('byte_content').textContent = evt.target.result;
        document.getElementById('byte_range').textContent = 
            ['Read bytes: ', start + 1, ' - ', stop + 1,
             ' of ', file.size, ' byte file'].join('');
      }
    };

    if (file.webkitSlice) {
      var blob = file.webkitSlice(start, stop + 1);
    } else if (file.mozSlice) {
      var blob = file.mozSlice(start, stop + 1);
    }
    reader.readAsBinaryString(blob);
  }
  
  document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
    if (evt.target.tagName.toLowerCase() == 'button') {
      var startByte = evt.target.getAttribute('data-startbyte');
      var endByte = evt.target.getAttribute('data-endbyte');
      readBlob(startByte, endByte);
    }
  }, false);
</script>

边上传边读取

<style>
  #progress_bar {
    margin: 10px 0;
    padding: 3px;
    border: 1px solid #000;
    font-size: 14px;
    clear: both;
    opacity: 0;
    -moz-transition: opacity 1s linear;
    -o-transition: opacity 1s linear;
    -webkit-transition: opacity 1s linear;
  }
  #progress_bar.loading {
    opacity: 1.0;
  }
  #progress_bar .percent {
    background-color: #99ccff;
    height: auto;
    width: 0;
  }
</style>

<input type="file" id="files" name="file" />
<button onclick="abortRead();">Cancel read</button>
<div id="progress_bar"><div class="percent">0%</div></div>

<script>
  var reader;
  var progress = document.querySelector('.percent');

  function abortRead() {
    reader.abort();
  }

  function errorHandler(evt) {
    switch(evt.target.error.code) {
      case evt.target.error.NOT_FOUND_ERR:
        alert('File Not Found!');
        break;
      case evt.target.error.NOT_READABLE_ERR:
        alert('File is not readable');
        break;
      case evt.target.error.ABORT_ERR:
        break; // noop
      default:
        alert('An error occurred reading this file.');
    };
  }

  function updateProgress(evt) {
    // evt is an ProgressEvent.
    if (evt.lengthComputable) {
      var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
      // Increase the progress bar length.
      if (percentLoaded < 100) {
        progress.style.width = percentLoaded + '%';
        progress.textContent = percentLoaded + '%';
      }
    }
  }

  function handleFileSelect(evt) {
    // Reset progress indicator on new file selection.
    progress.style.width = '0%';
    progress.textContent = '0%';

    reader = new FileReader();
    reader.onerror = errorHandler;
    reader.onprogress = updateProgress;
    reader.onabort = function(e) {
      alert('File read cancelled');
    };
    reader.onloadstart = function(e) {
      document.getElementById('progress_bar').className = 'loading';
    };
    reader.onload = function(e) {
      // Ensure that the progress bar displays 100% at the end.
      progress.style.width = '100%';
      progress.textContent = '100%';
      setTimeout("document.getElementById('progress_bar').className='';", 2000);
    }

    // Read in the image file as a binary string.
    reader.readAsBinaryString(evt.target.files&#91;0&#93;);
  }

  document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>

一道JS的面试题

题目:

with({}){
//在不污染全局情况下定义 with 里内部变量
//代码必须写在以下大括号里
alert(f) // 1 ,让 f 值为 1
}
alert(window.f) //undefined

答案:

with({}){
//在不污染全局情况下定义 with 里内部变量
//代码必须写在以下大括号里
constructor = function(){return this;};
constructor = constructor();
constructor.f = 1;
alert(f) // 1 ,让 f 值为 1
}
alert(window.f) //undefined

利用object的构造器功能, 使with的作用域做出改变

[ExtJS]4.0.7版本中panel卷起后无法看到按钮效果

这个目前在官方还没到有任何反应. 当一个带有collapse属性的panel作为hbox样式panel时, 就会发生此问题

mainPanel = Ext.create("Ext.panel.Panel", {
	height: 800,
        width: 700,
	autoHeight: true,
	autoScroll: true,
	border: false,
	layout: {
		type: "hbox",
		columns: 2,
		align: 'stretch'
	},
})
leftPanel = Ext.create("Ext.panel.Panel", {
	frame: true,
	lookMask: true,
	collapsible: true,
	collapseDirection: Ext.Component.DIRECTION_LEFT,
	width: 230,
        height: 400,
	border: 0,
	useArrow: true,
	title: "产品分类",
	split: true,
	tbar: [
	      {
		xtype: "button",
		text: "全部卷起"
              }]
});
mainPanel.add(leftPanel)
mainPanel.doLayout()

这个时候点击卷起的话. 那个卷起按钮会不显示. 在4.0.7版本之前没这个问题.

经排查 问题在于reExpander没用设置height,top, left这三个style属性. 更确切的说, 这个panel原本会向上查找height. 但是4.0.7严格的检查.高度无法正确获取到. 因此这个时候的高度为0. 所以看到缩起来后的按钮以及文字.
这个时候我们在leftPanel上增加一个监听事件. 手动向reExpander设置style属性.

leftPanel.addListener({
	collapse: function(p){
		if (p && p.collapsed && p.reExpander){
			var reExpander = p.reExpander;
			setTimeout(function(){
				reExpander.el.applyStyles({top: 0, left: 0});
				reExpander.setHeight(me.getHeight())
			}, 50);
		}
	}
})

这个时候 卷起来已经可以正常看到按钮以及文字了.

Get the real type in javascript

In javascript, we can use “type” function to get the type of an element (e.g “aa”, [], {}, 1, true, null, undefined, function, global), but get an array’s type. it returns a “object”. So, how to get the real type of the element?

USE “Object.prototype.toString.apply” function.

WHY?

Because any elements inherit it. Now, let’s see the results

Object.prototype.toString.apply("aa") //return [object String]
Object.prototype.toString.apply(1) //return [object Number]
Object.prototype.toString.apply({}) //return [object Object]
Object.prototype.toString.apply([]) //return [object Array]
Object.prototype.toString.apply(true) //return [object Boolean]
Object.prototype.toString.apply(null) //return [object Null]
Object.prototype.toString.apply(undefined) //return [object Undefined]
Object.prototype.toString.apply(window) //return [object global]
Object.prototype.toString.apply(Math.abs)//return [object Function]

//... and all

[RT] Defining Getters and Setters in NodeJS

Recently I discovered something interesting while messing around with NodeJS… you can define getters and setters using the ECMAScript5 syntax. For a useless example I could do something like this:

var sys = require('sys')

function Person(age){
this.__defineGetter__('age', function(){
return age
})

this.__defineSetter__('age', function(arg){
age = arg
})
}

var dude = new Person(18)

sys.puts(dude.age)
dude.age = 32

sys.puts(dude.age)

This is kind of boring though because it’s just a more complicated way of doing

function Person(age){
this.age = age
}

however you can notice in the first example you can add any kind of custom behavior to the getter and setter and access it via person.age. Where this does become useful however is if you want to create a read only property, which you can do by just defining the getter alone:

var sys = require('sys')

function Person(age){
this.__defineGetter__('age', function(){
return age
})
}

var dude = new Person(18)

sys.puts(dude.age)
dude.age = 32

This will print the initial age as expected, however the last line where the attempt is made to set the property will throw the exception “TypeError: Cannot set property age of # which has only a getter.”

A small discovery, yet very useful.

This origin post url: http://blog.james-carr.org/2010/07/19/defining-getters-and-setters-in-nodejs/

Ext4中DataStore以及Model需要注意的几点

最近使用ExtJS在做项目, 其中grid会大量的使用Model以及Data.Store.平常使用是没有问题的, 如果做高级搜索的时候, 按照一般情况下, 当然时重建model以及data.store, 就是按以上的思路来做的, 起初的几次, 也没什么问题. 但是使用多次高级搜索之后, 就会报一个this model is undefined错误.
遍历整个代码, model每次都会赋值, 为什么还会是undefined? Google搜索之, 也没找到任何原因.
今天, 重新看Ext文档的时候, 发现了Data.Store的setProxy方法, proxy是用于将搜索条件以及调用函数储存起来, 然后extjs内部会去读取这个object.生成你想要的数据.
目前我已经高级搜索的方法都改成store.setProxy(object); store.loadPage(1); 目前用户测试反馈下来, 无报错..

Geolocation and get the address by Google Map API

在移动设备以及现代浏览器中可以直接同navigator.geolocation所提供的api, 获取你当前经纬度. 并且通过GoogleMapAPI, 查看你当前所在位置的地图.

一. 在客户端上获取经纬度.

获取经纬度有两个api: getCurrentPosition以及watchPosition. 从本质上来说都是获取你当前所在的位置.

getCurrentPosition(callback)

watchPosition(successCallback, failureCallback, options)

在stackoverflow上找到了一篇讨论两者不同的论题. http://stackoverflow.com/questions/1948952/watchposition-vs-getcurrentposition-w-settimeout

After some serious testing, I have verified watchPosition() will give you an accurate location much more quickly than getCurrentPostion() over and over again. When using watchPostion(), the map behaves poorly if you redraw it over and over again every time the device updates your location. To get around this, I have added a listener to the tilesloaded event, which allows me to only redraw the map if there is not already a thread trying to draw on the map. Once the user is happy with the determined location, I will clear the watch. This will get me the best of both worlds, as far as battery consumption and accuracy are concerned.

这个就看你个人喜欢用哪个api了, 我推荐后者watchPosition. 首先写一个页面用来获取经纬度
Read more »