《Head First 设计模式》代码之PHP版
《Head First 设计模式》是本不错的讲解设计模式的书,不像F4写的那么枯燥,应该算是比较容易理解的好书。书中的例子都比较浅显易懂,不过由于是外国佬写的,所以例子的习惯不是很附合中国特色,可能偶尔看起来有些别扭,还有语言习惯也不是中国风。当然看过这本书之后,你才能深刻理解设计模式到底能为你解决哪些题,不能为你解决哪些问题(比如不能代替你的编码)。
策略模式
- <?php
- /**
- * 策略模式
- * 定义了算法族,分别封装起来,让它们之间可以互相替换,
- * 此模式让算法的变化独立于使用算法的客户。
- */
- //飞行行为接口
- interface FlyBehavior {
- public function fly();
- }
- //呱呱叫行为接口
- interface QuackBehavior {
- public function quack();
- }
- //翅膀飞行
- class FlyWithWings implements FlyBehavior {
- public function fly() {
- echo "I'm flying!!/n";
- }
- }
- //不会飞
- class FlyNoWay implements FlyBehavior {
- public function fly() {
- echo "I can't fly!/n";
- }
- }
- class FlyRocketPowered implements FlyBehavior {
- public function fly() {
- echo "I'm flying with a rocket!/n";
- }
- }
- class Qquack implements QuackBehavior {
- public function quack() {
- echo "Quack/n";
- }
- }
- class Squeak implements QuackBehavior {
- public function quack() {
- echo "Squeak/n";
- }
- }
- class MuteQuack implements QuackBehavior {
- public function quack() {
- echo "<< Silence >>/n";
- }
- }
- abstract class Duck {
- protected $quack_obj;
- protected $fly_obj;
- public abstract function display();
- public function performQuack() {
- $this->quack_obj->quack();
- }
- public function performFly() {
- $this->fly_obj->fly();
- }
- public function swim() {
- echo "All ducks float, even decoys!/n";
- }
- public function setFlyBehavior(FlyBehavior $fb) {
- $this->fly_obj = $fb;
- }
- public function setQuackBehavior(QuackBehavior $qb) {
- $this->quack_obj = $qb;
- }
- }
- class ModelDuck extends Duck {
- public function __construct() {
- $this->fly_obj = new FlyNoWay();
- $this->quack_obj = new MuteQuack();
- }
- public function display() {
- echo "I'm a model duck!/n";
- }
- }
- $model = new ModelDuck();
- $model->performFly();
- $model->performQuack();
- //提供新的能力
- $model->setFlyBehavior(new FlyRocketPowered());
- $model->setQuackBehavior(new Squeak());
- $model->performFly();
- $model->performQuack();
- ?>
单件模式
- <?php
- /**
- * 单件模式
- * 确保一个类只有一个实例,并提供一个全局访问点。
- */
- class MyClass {
- private static $uniqueInstance;
- private function __construct() {
- }
- public static function getInstance() {
- if (self::$uniqueInstance == null) {
- self::$uniqueInstance = new MyClass();
- }
- return self::$uniqueInstance;
- }
- }
- $myClass = MyClass::getInstance();
- var_dump($myClass);
- $myClass = MyClass::getInstance();
- var_dump($myClass);
- ?>
工厂方法模式
- <?php
- abstract class PizzaStore {
- public function orderPizza($type) {
- $pizza = $this->createPizza($type);
- $pizza->prepare();
- $pizza->bake();
- $pizza->cut();
- $pizza->box();
- return $pizza;
- }
- public abstract function createPizza($type);
- }
- class NYPizzaStore extends PizzaStore {
- public function createPizza($type) {
- if ($type == "cheese") {
- return new NYStyleCheesePizza();
- } elseif ($type == "veggie") {
- return new NYStyleVeggiePizza();
- } elseif ($type == "clam") {
- return new NYStyleClamPizza();
- } elseif ($type == "papperoni") {
- return new NYStylePapperoniPizza();
- } else {
- return null;
- }
- }
- }
- class ChicagoPizzaStore extends PizzaStore {
- public function createPizza($type) {
- if ($type == "cheese") {
- return new ChicagoStyleCheesePizza();
- } elseif ($type == "veggie") {
- return new ChicagoStyleVeggiePizza();
- } elseif ($type == "clam") {
- return new ChicagoStyleClamPizza();
- } elseif ($type == "papperoni") {
- return new ChicagoStylePapperoniPizza();
- } else {
- return null;
- }
- }
- }
- abstract class Pizza {
- public $name;
- public $dough;
- public $sauce;
- public $toppings = array();
- public function prepare() {
- echo "Preparing " . $this->name . "/n";
- echo "Yossing dough.../n";
- echo "Adding sauce.../n";
- echo "Adding toppings: /n";
- for ($i = 0; $i < count($this->toppings); $i++) {
- echo " " . $this->toppings[$i] . "/n";
- }
- }
- public function bake() {
- echo "Bake for 25 minutes at 350/n";
- }
- public function cut() {
- echo "Cutting the pizza into diagonal slices/n";
- }
- public function box() {
- echo "Place pizza in official PizzaStore box/n";
- }
- public function getName() {
- return $this->name;
- }
- }
- class NYStyleCheesePizza extends Pizza {
- public function __construct() {
- $this->name = "NY Style Sauce and cheese Pizza";
- $this->dough = "Thin Crust Dough";
- $this->sauce = "Marinara Sauce";
- $this->toppings[] = "Grated Reggiano Cheese";
- }
- }
- class NYStyleVeggiePizza extends Pizza {
- public function __construct() {
- $this->name = "NY Style Sauce and veggie Pizza";
- $this->dough = "Thin Crust Dough";
- $this->sauce = "Marinara Sauce";
- $this->toppings[] = "Grated Reggiano veggie";
- }
- }
- class NYStyleClamPizza extends Pizza {
- public function __construct() {
- $this->name = "NY Style Sauce and clam Pizza";
- $this->dough = "Thin Crust Dough";
- $this->sauce = "Marinara Sauce";
- $this->toppings[] = "Grated Reggiano clam";
- }
- }
- class NYStylePapperoniPizza extends Pizza {
- public function __construct() {
- $this->name = "NY Style Sauce and papperoni Pizza";
- $this->dough = "Thin Crust Dough";
- $this->sauce = "Marinara Sauce";
- $this->toppings[] = "Grated Reggiano papperoni";
- }
- }
- class ChicagoStyleCheesePizza extends Pizza {
- public function __construct() {
- $this->name = "Chicago Style Deep Dish Cheese Pizza";
- $this->dough = "Extra Thick Crust Dough";
- $this->sauce = "Plum Tomato Sauce";
- $this->toppings[] = "Shredded Mozzarella Cheese";
- }
- public function cut() {
- echo "Cutting the pizza into square slices/n";
- }
- }
- $myStore = new NYPizzaStore();
- $chicagoStore = new ChicagoPizzaStore();
- $pizza = $myStore->orderPizza("cheese");
- echo "Ethan ordered a " . $pizza->getName() . "/n";
- $pizza = $chicagoStore->orderPizza("cheese");
- echo "Ethan ordered a " . $pizza->getName() . "/n";
- ?>
工厂模式
- <?php
- abstract class PizzaStore {
- public function orderPizza($type) {
- $pizza = $this->createPizza($type);
- $pizza->prepare();
- $pizza->bake();
- $pizza->cut();
- $pizza->box();
- return $pizza;
- }
- public abstract function createPizza($type);
- }
- class NYPizzaStore extends PizzaStore {
- public function createPizza($type) {
- $pizza = null;
- $ingredientFactory = new NYPizzaIngredientFactory();
- if ($type == "cheese") {
- $pizza = new CheesePizza($ingredientFactory);
- $pizza->setName('New York Style Cheese Pizza');
- } elseif ($type == "veggie") {
- $pizza = new VeggiePizza($ingredientFactory);
- $pizza->setName('New York Style Veggie Pizza');
- } elseif ($type == "clam") {
- $pizza = new ClamPizza($ingredientFactory);
- $pizza->setName('New York Style Clam Pizza');
- } elseif ($type == "papperoni") {
- $pizza = new PapperoniPizza($ingredientFactory);
- $pizza->setName('New York Style Papperoni Pizza');
- }
- return $pizza;
- }
- }
- class ChicagoPizzaStore extends PizzaStore {
- public function createPizza($type) {
- if ($type == "cheese") {
- return new ChicagoStyleCheesePizza();
- } elseif ($type == "veggie") {
- return new ChicagoStyleVeggiePizza();
- } elseif ($type == "clam") {
- return new ChicagoStyleClamPizza();
- } elseif ($type == "papperoni") {
- return new ChicagoStylePapperoniPizza();
- } else {
- return null;
- }
- }
- }
- interface PizzaIngredientFactory {
- public function createDough();
- public function createSauce();
- public function createCheese();
- public function createVeggies();
- public function createPepperoni();
- public function createClam();
- }
- class NYPizzaIngredientFactory implements PizzaIngredientFactory {
- public function createDough() {
- return new ThinCrustDough();
- }
- public function createSauce() {
- return new MarinaraSauce();
- }
- public function createCheese() {
- return new ReggianoCheese();
- }
- public function createVeggies() {
- $veggies = array(
- new Garlic(),
- new Onion(),
- new Mushroom(),
- new RedPepper(),
- );
- return $veggies;
- }
- public function createPepperoni() {
- return new SlicedPepperoni();
- }
- public function createClam() {
- return new FreshClams();
- }
- }
- class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {
- public function createDough() {
- return new ThickCrustDough();
- }
- public function createSauce() {
- return new PlumTomatoSauce();
- }
- public function createCheese() {
- return new Mozzarella();
- }
- public function createVeggies() {
- $veggies = array(
- new BlackOlives(),
- new Spinach(),
- new EggPlant(),
- );
- return $veggies;
- }
- public function createPepperoni() {
- return new SlicedPepperoni();
- }
- public function createClam() {
- return new FrozenClams();
- }
- }
- abstract class Pizza {
- public $name;
- public $dough;
- public $sauce;
- public $veggies = array();
- public $cheese;
- public $pepperoni;
- public $clam;
- public abstract function prepare();
- public function bake() {
- echo "Bake for 25 minutes at 350/n";
- }
- public function cut() {
- echo "Cutting the pizza into diagonal slices/n";
- }
- public function box() {
- echo "Place pizza in official PizzaStore box/n";
- }
- public function getName() {
- return $this->name;
- }
- public function setName($name) {
- $this->name = $name;
- }
- public function __toString() {
- }
- }
- class CheesePizza extends Pizza {
- public $ingredientFactory;
- public function __construct(PizzaIngredientFactory $ingredientFactory) {
- $this->ingredientFactory = $ingredientFactory;
- }
- public function prepare() {
- echo "Preparing " . $this->name . "/n";
- $this->dough = $this->ingredientFactory->createDough();
- $this->sauce = $this->ingredientFactory->createSauce();
- $this->cheese = $this->ingredientFactory->createCheese();
- }
- }
- class ClamPizza extends Pizza {
- public $ingredientFactory;
- public function __construct(PizzaIngredientFactory $ingredientFactory) {
- $this->ingredientFactory = $ingredientFactory;
- }
- public function prepare() {
- echo "Preparing " . $this->name . "/n";
- $this->dough = $this->ingredientFactory->createDough();
- $this->sauce = $this->ingredientFactory->createSauce();
- $this->cheese = $this->ingredientFactory->createCheese();
- $clam = $this->ingredientFactory->createClam();
- }
- }
- $nyPizzaStore = new NYPizzaStore();
- $nyPizzaStore->orderPizza('cheese');
- ?>
观察者模式
- <?php
- /**
- * 观察者模式
- * 定义了对象之间的一对多依赖,当一个对象改变状态时,
- * 它的所有依赖者都会收到通知并自动更新。
- */
- interface Subject {
- public function registerObserver(Observer $o);
- public function removeObserver(Observer $o);
- public function notifyObservers();
- }
- interface Observer {
- public function update($temperature, $humidity, $pressure);
- }
- interface DisplayElement {
- public function display();
- }
- class WeatherData implements Subject {
- private $observers = array();
- private $temperature;
- private $humidity;
- private $pressure;
- public function __construct() {
- $this->observers = array();
- }
- public function registerObserver(Observer $o) {
- $this->observers[] = $o;
- }
- public function removeObserver(Observer $o) {
- if (($key = array_search($o, $this->observers)) !== false) {
- unset($this->observers[$key]);
- }
- }
- public function notifyObservers() {
- foreach ($this->observers as $observer) {
- $observer->update($this->temperature, $this->humidity, $this->pressure);
- }
- }
- public function measurementsChanged() {
- $this->notifyObservers();
- }
- public function setMeasurements($temperature, $humidity, $pressure) {
- $this->temperature = $temperature;
- $this->humidity = $humidity;
- $this->pressure = $pressure;
- $this->measurementsChanged();
- }
- }
- class CurrentConditionsDisplay implements Observer, DisplayElement {
- private $temperature;
- private $humidity;
- private $weatherData;
- public function __construct(Subject $weatherData) {
- $this->weatherData = $weatherData;
- $weatherData->registerObserver($this);
- }
- public function update($temperature, $humidity, $pressure) {
- $this->temperature = $temperature;
- $this->humidity = $humidity;
- $this->display();
- }
- public function display() {
- echo "温度:" . $this->temperature . "; 湿度:" . $this->humidity . "%/n";
- }
- }
- class StatistionsDisplay implements Observer, DisplayElement {
- private $temperature;
- private $humidity;
- private $pressure;
- private $weatherData;
- public function __construct(Subject $weatherData) {
- $this->weatherData = $weatherData;
- $weatherData->registerObserver($this);
- }
- public function update($temperature, $humidity, $pressure) {
- $this->temperature = $temperature;
- $this->humidity = $humidity;
- $this->pressure = $pressure;
- $this->display();
- }
- public function display() {
- echo "温度:" . $this->temperature . "; 湿度:" . $this->humidity . "%; 气压:" . $this->pressure . "/n";
- }
- }
- $weatherData = new WeatherData();
- $currentDisplay = new CurrentConditionsDisplay($weatherData);
- $statistionDisplay = new StatistionsDisplay($weatherData);
- $weatherData->setMeasurements(10, 20, 30);
- $weatherData->removeObserver($currentDisplay);
- $weatherData->setMeasurements(30, 40, 50);
- ?>
命令模式
- <?php
- class Light {
- public function __construct() {
- }
- public function on() {
- echo "Light On/n";
- }
- public function off() {
- echo "Light Off/n";
- }
- }
- interface Command {
- public function execute();
- }
- class LightOnCommand implements Command {
- public $light;
- public function __construct(Light $light) {
- $this->light = $light;
- }
- public function execute() {
- $this->light->on();
- }
- }
- class SimpleRemoteControl {
- public $slot;
- public function __construct() {
- }
- public function setCommand(Command $command) {
- $this->slot = $command;
- }
- public function buttonWasPressed() {
- $this->slot->execute();
- }
- }
- class RemoteControlTest {
- public static function main() {
- $remote = new SimpleRemoteControl();
- $light = new Light();
- $lightOn = new LightOnCommand($light);
- $remote->setCommand($lightOn);
- $remote->buttonWasPressed();
- }
- }
- RemoteControlTest::main();
- ?>
装饰者模式
- <?php
- /**
- * 装饰着模式
- * 动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
- */
- abstract class Beverage {
- public $description = "Unknown Beverage";
- public function getDescription() {
- return $this->description;
- }
- public abstract function cost();
- }
- abstract class CondimentDecorator extends Beverage {
- //JAVA代码里这里是个抽象类,PHP不允许这么做
- public function getDescription() {
- return $this->description;
- }
- }
- class Espresso extends Beverage {
- public function __construct() {
- $this->description = "Espresso";
- }
- public function cost() {
- return 1.99;
- }
- }
- class HouseBlend extends Beverage {
- public function __construct() {
- $this->description = "HouseBlend";
- }
- public function cost() {
- return .89;
- }
- }
- class DarkRoast extends Beverage {
- public function __construct() {
- $this->description = "DarkRoast";
- }
- public function cost() {
- return .99;
- }
- }
- class Mocha extends CondimentDecorator {
- public $beverage;
- public function __construct(Beverage $beverage) {
- $this->beverage = $beverage;
- }
- public function getDescription() {
- return $this->beverage->getDescription() . ", Mocha";
- }
- public function cost() {
- return .20 + $this->beverage->cost();
- }
- }
- class Whip extends CondimentDecorator {
- public $beverage;
- public function __construct(Beverage $beverage) {
- $this->beverage = $beverage;
- }
- public function getDescription() {
- return $this->beverage->getDescription() . ", Whip";
- }
- public function cost() {
- return .10 + $this->beverage->cost();
- }
- }
- class Soy extends CondimentDecorator {
- public $beverage;
- public function __construct(Beverage $beverage) {
- $this->beverage = $beverage;
- }
- public function getDescription() {
- return $this->beverage->getDescription() . ", Soy";
- }
- public function cost() {
- return .15 + $this->beverage->cost();
- }
- }
- $beverage = new Espresso();
- echo $beverage->getDescription() . "/n";
- $beverage2 = new DarkRoast();
- $beverage2 = new Mocha($beverage2);
- $beverage2 = new Mocha($beverage2);
- $beverage2 = new Whip($beverage2);
- echo $beverage2->getDescription() . " $" . $beverage2->cost() . "/n";
- $beverage3 = new HouseBlend();
- $beverage3 = new Soy($beverage3);
- $beverage3 = new Mocha($beverage3);
- $beverage3 = new Whip($beverage3);
- echo $beverage3->getDescription() . " $" . $beverage3->cost() . "/n";
- ?>
状态模式
- <?php
- class GumballMachine {
- const SOLD_OUT = 0;
- const NO_QUARTER = 1;
- const HAS_QUARTER = 2;
- const SOLD = 3;
- public $state = self::SOLD_OUT;
- public $count = 0;
- public function __construct($count) {
- $this->count = $count;
- if ($count > 0) {
- $this->state = self::NO_QUARTER;
- }
- }
- public function insertQuarter() {
- if ($this->state == self::HAS_QUARTER) {
- echo "You can't insert another quarter!/n";
- } else if ($this->state == self::NO_QUARTER) {
- $this->state = self::HAS_QUARTER;
- echo "You inserted a quarter!/n";
- } else if ($this->state == self::SOLD_OUT) {
- echo "You can't insert a quarter, the machine is sold out!/n";
- } else if ($this->state == self::SOLD) {
- echo "Please wait, we're already giving you a gumball!/n";
- }
- }
- }
- $obj = new GumballMachine(0);
- print_r($obj)
- ?>
jQuery 中使用 JSON
JSON 格式
json 是 Ajax 中使用频率最高的数据格式,在浏览器和服务器中之间的通讯可离不开它。
JSON 的格式说明可以在可以这里看到,非常详细,还是中文的。
需要特别注意的是,在 JSON 中的属性名是需要使用引号引起来的。
jQuery 中使用 JSON
jQuery 是现在使用广泛的脚本库,那么,在 jQuery 中如何使用 JSON 呢?
解析 JSON
在 jQuery 中已经提供了对于解析 JSON 的内在支持,
jQuery.parseJSON 函数提供了解析的支持,详细的说明见这里。
var obj = jQuery.parseJSON('{"name":"John"}');
alert( obj.name === "John" );
使用对象生成 JSON 格式串
在 jQuery 中并没有提供直接将普通的 JavaScript 对象转换为 JSON 串的方法,可以使用下面的扩展库来完成。
jquery-json 扩展库
这个库用来扩展 jQuery ,对于 JSON 的使用,扩展了两个方法。
toJSON 方法用来将一个普通的 JavaScript 对象序列化为 JSON 串。
var thing = {plugin: 'jquery-json', version: 2.3}; var encoded = $.toJSON( thing ); // '{"plugin":"jquery-json","version":2.3}'
evalJSON 方法将一个 JSON 串解析为一个普通的 JavaScript 对象。
var thing = {plugin: 'jquery-json', version: 2.3}; var encoded = $.toJSON( thing ); // '{"plugin":"jquery-json","version":2.3}' var name = $.evalJSON( encoded ).plugin; // "jquery-json" var version = $.evalJSON(encoded).version; // 2.3
这个扩展的下载地址:http://code.google.com/p/jquery-json/
使用 jQuery 配合 WCF
客户端
jQuery 中的 $.post 可以直接向服务器发出请求,将服务器返回的数据按照 JSON 方式进行解析,不过,需要注意下面几点:
请求的内容类型必须为 json 格式,这可以通过上面的 jQuery-json 扩展库来完成,需要特别注意的在请求的 contentType 也必须使用 text/json 进行说明,默认的 post 使用普通的名值对方式请求,因此 contentType 是: application/x-www-form-urlencoded,可以通过 $.ajaxSetup 来进行设置:
// Ajax 设置 $.ajaxSetup({ contentType: 'text/json' });
这样,请求的内容类型就设置为需要的类型。
其次,实际的请求内容必须使用 JSON 方式,这可以通过扩展库的 $.toJSON 来实现,例如:
$.toJSON({ x: 2, y: 3 })
这样,如果服务器端提供了一个服务方法 Sum,定义如下:
public int Sum(int x, int y) { return x + y; }
就可以如下调用了。注意,WCF 返回的数据在属性 d 中。
// Ajax 设置 $.ajaxSetup({ contentType: 'text/json' }); $("#wcfBtn").click(function () { $.post("Service1.svc/Sum", $.toJSON({ x: 2, y: 3 }), function (data) { alert(data.d); }); });
服务器端的配置
首先,为服务增加标签:[System.ServiceModel.Activation.AspNetCompatibilityRequirements(RequirementsMode = System.ServiceModel.Activation.AspNetCompatibilityRequirementsMode.Allowed)]
然后,在网站的配置文件中,如下配置。
<system.serviceModel> <!-- 为了支持在浏览器端调用 WCF 服务的特定配置 --> <serviceHostingEnvironment aspNetCompatibilityEnabled="true"> <serviceActivations> <!-- relativeAddress 服务的地址 service 实现服务的类型,全名,包含命名空间,甚至程序集 factory 是 WCF 系统提供,直接使用 --> <add relativeAddress="Service1.svc" service="MServer.Service1" factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" /> </serviceActivations> </serviceHostingEnvironment> <behaviors> <serviceBehaviors> <behavior name=""> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
Zend Studio9 配置优化
今天使用ZendStudio9的时候再次被卡得想死,ctrl+s保存文件的时候zend会先build什么东西,然后才进行save操作,每次如此。突然好怀念当初使用的zendStudio5.5,完全只是php的开发环境。而在6.0之后的版本都成为了ZendStudio for eclipse,也就是均是基于eclipse的。功能很强大,但能用到的却不多,还很占用资源。真想把他换了。但找来找去,还真找不到一个能比拟ZendStudio的开发环境,也不是很想退回去使用5.5的版本。
那么我就自己研究Zend Studio的菜单栏和工具栏,看看有没有可以优化的配置,以下说明不一定正确:
1、关闭自动Build:
将 Project -> Build Automatically 前面的勾选取消掉
在使用中,我发现Build的作用应该是为整个项目建立一个索引和预读取,加快查找和载入文件的速度,但不必要让zend 自动Build项目,他还没有聪明到知道自己该什么时候build才会让主人不觉得卡,所以,取消Build Automatically会让你觉得你的Zend Studio跑的快了点。你可以在添加完项目或者在修改过项目之后,右键点击项目,然后选择Build Project
2、开启智能插入模式
勾选 Edit->Smart Insert Mode
3、快捷键加注释
使用ctrl + / 增加和取消一行的注释
使用ctrl + shift + / 注释一个代码块
使用ctrl + shift + 取消注释一个代码块
4、设置代码格式
Window->Preferences->PHP->Code Style->Formatter
选择Show之后,可以设置类、方法、for语句块、switch语句中的代码是否需要缩进,设置类、方法、语句块中的前半个大括号是直接跟在本行结尾还是换到下一行,还有许多,可以自己查看
选择文件:使用快捷键ctrl + shift + f可以快速将你的php文件格式化为你设置的格式,也可以使用菜单栏的Source -> Format
5、修改配置文件ZendStudio.ini
加大zendstudio的使用内存,也就是讲XXMaxPermSize加大到512m,如果你的内存足够大到4G,那么你这里使用1024都可以,修改完后的配置文件内容如下:
6、加快鼠标经过时代码提示速度
选择Window -> Preferences -> PHP -> Editor -> Content Assist ->Auto Activation
将Auto activation delay(in msecs)设置为50,默认值可能是200或者500
7、使用空格代替tab
选择Window -> Preferences -> PHP -> Code Style -> Formatter
一、选择Zend Framework Coventions[build-in],然后在Window -> Preferences -> General -> Editors -> Text Editors中如下设置:
二、如果是自定义的话,点击Edit,在Indentation选项卡中,设置Tab policy为Spaces,然后在Indentation size填写使用的空格数,
8、快速搜索方法和类:
之前我更习惯于在项目文件夹上直接点击右键,然后选择Search进行查找,这样的话ZendStudio会去扫描所有文件,比较耗时。
如果只是需要查找方法的话,可以使用快捷键ctrl + shift + M
根据类名称查找的话使用快捷键ctrl + shift + T
速度真的很快
9、添加新的文件类型:
drupal中的模块后缀名是*.module,我们使用zend打开的时候是纯文本内容,不会有代码高亮的效果,设置方法:
选择:Window -> Preferences -> General -> Content Types
点开右侧的Text,选择php content type,点击Add按钮,在弹出框中输入*.module,最后保存即可
将*.tpl添加到HTML中也是类似操作
git查看某个文件的修改历史
有时候在比对代码时,看到某些改动,但不清楚这个改动的作者和原因,也不知道对应的CR号,也就是说无从查到这些改动的具体原因了~
【注】:某个文件的改动是有限次的,而且每次代码修改的提交都会有commit描述,我们可以从这里进行入手;
一、切换到目录
首先切换到要查看的文件所在的目录:
cd packages/apps/Mms/src/com/android/mms/ui/
二、git log --pretty
然后使用下面的命令可列出文件的所有改动历史,注意,这里着眼于具体的一个文件,而不是git库,如果是库,那改动可多了去了~
git log --pretty=oneline 文件名
如:
root@ubuntu:android_src/packages/apps/Mms/src/com/android/mms/ui# git log --pretty=oneline MessageItem.java 27209385caf678abe878375a470f4edd67a2d806 fix cr 17973 to process force close when empty address contained in card 0e04b16f1dad7dc0a36e2235f7337bc656c365c7 display for 1970-1-1 e4abf3a213197491e0855e101117b59b5dc0160d HREF#13954 receive, store, and display wap push 356f6def9d3fb7f3b9032ff5aa4b9110d4cca87e HREF#16265_uim_show_time_error 350f9d34c35ab50bdb4b2d43fb3ff9780e6c73fa fix href#13617 and href#15149 715e32f97bd9d8ce4b5ba650b97ba4b137150456 Fix ANR from calling Contact.get() fd8357ff5febab0141e1beb8dd3b26f70416b108 Fix missing From field d130e2e6dc448fd80ecb70f0d31e3affb9888b9a fix bug 2112925: don't display zip file garbage content in MMS. 0e19f738c114f86d0d88825ee48966015fb48b6d Don't always show sent timestamp 52f854cbb75e8f9975c7e33216b828eb2f981095 Don't show Anonymous as the MMS sender 331864544ec51ba6807fc5471cc6d537b7fef198 add search capability 33a87f96f8c625aa10131a77a3968c97c4ec5a62 Remove all references to ContactInfoCache except those in Contact. 70c73e05a792832aa28da751cdaf3fa83a7b8113 Begin moving all conversation data behind a data model with a cache. 48da875f1beea835c6771977e5bd8a9aa3d4bc10 Begin adding UI unit tests to the Mms app. 66dde9460badebf8e740275cabde9cca256006eb Stop requiring a Context to be passed in to ContactInfoCache. 591d17e9a51bb9f829d6860dc7aa0bad25062cd5 auto import from //branches/cupcake_rel/...@138607 72735c62aba8fd2a9420a0f9f83d22543e3c164f auto import from //depot/cupcake/@135843 892f2c5bf965b1431ae107b602444a93f4aad4a3 auto import from //depot/cupcake/@135843 153ae99e0a7d626a24d61475eeb133249deb448c auto import from //depot/cupcake/@132589 abd7b2d90f7491075f1daba4b4cccdfc82f8ddd1 auto import from //depot/cupcake/@137055 59d72c57ce9c319b6cd43ce2ab36b7076c9e821f auto import from //branches/cupcake/...@132276 44cea74dc55e2459262d0d765ef4a69267dd09b0 auto import from //branches/cupcake/...@131421 0f236f55349f070ac94e12cca963847173393da8 Code drop from //branches/cupcake/...@124589 8eed706474910ccb978acda03e85d3261037da6e Initial Contribution
三、git show
如上所示,打印出来的就是针对文件MessageItem.java的所有的改动历史,每一行最前面的那一长串数字就是每次提交形成的哈希值,接下来使用git show即可显示具体的某次的改动的修改~
git show 356f6def9d3fb7f3b9032ff5aa4b9110d4cca87e
结果如下:
root@ubuntu:/android_src/packages/apps/Mms/src/com/android/mms/ui# git show 356f6def9d3fb7f3b9032ff5aa4b9110d4cca87e commit 356f6def9d3fb7f3b9032ff5aa4b9110d4cca87e Author: 某某某 <某某某的邮箱> Date: Thu Jan 6 01:50:31 2011 +0800 修改的描述(是该代码commit时所填) Signed-off-by: 某某某 <某某某的邮箱> diff --git a/src/com/android/mms/ui/MessageItem.java b/src/com/android/mms/ui/MessageItem.java index 0a0c4b7..55c3b27 100644 --- a/src/com/android/mms/ui/MessageItem.java +++ b/src/com/android/mms/ui/MessageItem.java + + 列出具体的改动 - -
这样就可以知道是谁做了修改,以及具体的修改代码~
那接下来不管是直接去找他交流还是研究代码,都有依据了~
Git .gitignore 設定與注意事項 – 以Zim操作為範例
Git 設定 .gitignore, 設定完成就都直接生效, 在測試時都很正常, 但是實際使用 卻沒有生效, 有點軌異.
環境
- Git 所管理的專案名稱、位置: /home/user/doc
下述範例是以 Zim 為主, Zim 是一套桌面的 Wiki 編輯器, 裡面寫的內容都會存成 txt 檔, .zim 的目錄下會存 “*.cache” 和 “zim 本身自己的設定值”.
Zim 在剛開始建立完成後, 就使用下述步驟:
- cd /home/user/doc
- git init
- git commit -a
- git push #一開始沒有設定 .gitignore, 所以會將 .zim/* 都 commit 進去
於每次開啟 Zim 後, 都會出現
modified: .zim/history.cache
modified: .zim/index.cache
造成 git commit -a 的麻煩 (因為多台電腦要同步時, index.cache / history.cache 都會出現需要 merge 的狀況), 所以想設定 .gitignore 來把它拿掉. (方便 git commit -a)
設定 .gitignore 位置、方法
設定 Git ignore 的方式都一樣, 有下面幾個地方可以設定, 依自己喜好 / 需求來設定即可.(設定位置)
- vim ~/.gitignore # 對所有 Git 的專案生效 (自己的 home 目錄下)
- vim doc/.gitignore # doc 是專案名稱, 用這個的好處是, 將 .gitignore commit 進去, 此 .gitignore 可以隨著專案到處走. (Git 管理的 Project 目錄下)
- vim doc/.git/info/exclude # 只有單獨於此處 .git 生效 (Project 的 .git/info/exclude 檔案)
- 這幾個地方都可以設定, 可以使用 * 等符號. 詳可見: gitignore(5) Manual Page
於 .zim 的狀況, 可以設定下述: (設定方法)
- 所有 . 開頭的目錄 / 檔案都不 commit
.*
- .zim 目錄內 的 所有 *.cache 都不 commit
.zim/*.cache
- 只有 .zim/history.cache, .zim/index.cache 不 commit
.zim/history.cache
.zim/index.cache
.gitignore 無法生效 的 問題修復
在測試狀況都是正常, 但是在 Zim 實際使用就有問題, 每次都出現 modified 的解法.
解法
- 因為第一次 commit 已經將 .zim/*.cache commit 進去了, 所以每次它都會去檢查, 造成都出現 modified 的狀況.
- git rm -f .zim/history.cache
- git rm -f .zim/index.cache
- git commit # 即可
- 再將 .gitignore 設定好, 就可以避免掉這些狀況囉~
範例 -我的 Zim 設定方式
- cd /home/user/doc
- vim .gitignore
.zim/*.cache
- git add .gitignore
- git commit
- git push
Zend Studio 9.0.4正式版注册破解
以下方法仅供技术交流学习,请勿非法使用,如长期使用请支持购买正版。
正版购买地址:http://shop.zend.com/en/zend-studio-for-eclipse.html
你还没有最新安装程序?
ZendStudio下载地址:http://www.geekso.com/component/zendstudio-downloads/
注册破解步骤
第一步:如果已经安装过Zend Studio 9.0.4的,请打开Zend Studio 9.0.4,在菜单中“help>Unregister”,如果显示是灰的跳过此步退出Zend Studio。如果显示可以点击的请点击,这时Zend Studio会重启,重启到要求你填注册码时点“QUIT”按钮
第二步:请根据你使用的Zend Studio版本下载对应的破解文件:
ZendStudio9.0破解文件com.zend.php.core_9.0.0.201111081531.jar (已下载 12120 次)
ZendStudio9.0.1破解文件com.zend.php.core_9.0.1.201112141951.jar (已下载 17358 次)
ZendStudio9.0.2破解文件com.zend.php.core_9.0.2.201202240955.jar (已下载 25255 次)
ZendStudio9.0.3破解文件com.zend.php.core_9.0.3.201206251721.jar (已下载 10651 次)
ZendStudio9.0.4破解文件com.zend.php.core_9.0.4.201210081806.jar (已下载 24400 次)
Zend Studio 10 Beta测试版官方下载地址——更新2012-10-25
Windows : 官方下载 | 复制地址
Linux—32: 官方下载 | 复制地址
Linux—64: 官方下载 | 复制地址
Mac OS X: 官方下载 | 复制地址
Zend Studio 9.0.4 正式版官方下载地址——更新2012-10-12
Windows : 官方下载 | 复制地址
Linux—32: 官方下载 | 复制地址
Linux—64: 官方下载 | 复制地址
Mac OS X: 官方下载 | 复制地址
Zend Studio 9.0.3 正式版官方下载地址——更新2012-05-10
Windows : 官方下载 | 复制地址
Linux—32: 官方下载 | 复制地址
Linux—64: 官方下载 | 复制地址
Mac OS X: 官方下载 | 复制地址
Zend Studio 9.0.2 正式版官方下载地址——更新2012-03-05
Windows : 官方下载 | 复制地址
Linux—32: 官方下载 | 复制地址
Linux—64: 官方下载 | 复制地址
Mac OS X: 官方下载 | 复制地址
Zend Studio 9.0.1 正式版官方下载地址——更新2011-12-16
Windows : 官方下载 | 复制地址
Linux—32: 官方下载 | 复制地址
Linux—64: 官方下载 | 复制地址
Mac OS X: 官方下载 | 复制地址
Zend Studio 9.0.0 正式版官方下载地址
Windows : 官方下载 | 复制地址
Linux—32: 官方下载 | 复制地址
Linux—64: 官方下载 | 复制地址
Mac OS X: 官方下载 | 复制地址
提示:com.zend.php.core_9.0.4.201210081806.jar对应的版本号为9.0.4.v20121009466
下载成功后(提示:破解文件千万不要解压,也不要修改破解文件的文件名)复制到你安装Zend Studio 9.0.4的plugins目录下,覆盖同名文件。
第三步:启动Zend Studio,复制如下注册码License key,粘贴(粘贴快捷键是ctrl+v)到注册框中
复制注册码
提示:先覆盖第二步当中的破解文件,然后在启动Zend Studio输入注册码。
第四步:查看是否注册成功,在菜单中“help>About Zend Studio ”, 显示如下图。
过期时间9999年12月31日说明注册破解成功完成。
【已解决问题】
2011-12-06:解决同一局域网内相同的key只能使用一台的问题。如你遇到提示“user license number 1 is already in use by 1 users”,请重新下载破解文件。
zend studio9.0.4汉化及常见问题解答:http://www.geekso.com/zendstudioquestion/
win7 64位32位,window server2008 64位,mac版都没问题,如果遇到无法注册的请留言。
我试了在CentOS(32位)操作系统下用此方法注册Zend Studio 9.0.4成功,所以Linux操作系统是没有问题的。以下是我在Linux操作系统注册成功的截图:
查看截图:http://www.geekso.com/attachment/201112/1323070502_8926bffc.png
你没破解成功,不防看一下是不是这个原因造成的?
最近发现好多朋友告诉我说注册破解没有成功,我看了下主要是因为把下载的那个破解包给解压了,造成破解不成功。所以下载完这个破解包后千万不要解压,直接覆盖到你安装Zend Studio 9.0.4的plugins目录下的同名文件。还有查看注册码复制的对不对。
为什么我复制破解文件到plugins目录时没有提示已存在同名文件?
原因1:是你下载的是9.0的测试版。建议下载最新版本的Zend Studio9.0.4,下载地址:http://www.geekso.com/component/zendstudio-downloads/
原因2:下载的破解文件版本跟你的安装的ZendStudio版本不一样。
原因3:下载的破解文件文件名跟我发布的破解文件名不一样,有可能在下载的时侯被修改了,请核对确认文件名是否被修改,必须跟我发布的文件名是一模一样的。
Linux操作系统破解zendstudio都按上面操作了,但在复制注册码时还是显示不正确?
注册码复制进去后,按下 ctrl+z (回滚),一直按回滚,一直滚到无法回滚的时候这个注册码就变成绿色的勾了!
如果以上方法你还是没有破解成功,请添加QQ群解答ZendStudio破解问题
1号QQ群:204192303(已满)。
2号QQ群:204192304(已满)。
3号QQ群:187586326(已满)。
同时也附上两个最新的zendStudio 10测试版的试用注册码(有效期2012年12月9号):
zendStudio 10第二个注册码(有效期2013年01月15号):
jQuery性能优化指南
现在jquery应用的越来越多, 有些同学在享受爽快淋漓coding时就将性能问题忽略了, 比如我. jquery虽在诸多的js类库中性能表现还算优秀, 但毕竟不是在用原生的javascript开发, 性能问题还是需要引起重视的. 在twitter上发现了<jQuery Performance Rules>这篇文章, 简单的摘译了一下:
- 总是从ID选择器开始继承
- 在class前使用tag
- 将jquery对象缓存起来
- 掌握强大的链式操作
- 使用子查询
- 对直接的DOM操作进行限制
- 冒泡
- 消除无效查询
- 推迟到 $(window).load
- 压缩js
- 全面掌握jquery库
1. 总是从ID选择器开始继承
在jquery中最快的选择器是ID选择器. 因为它直接来自于Javascript的getElementById()方法.
<form method=“post” action=“/”>
<h2>Traffic Light</h2>
<ul id=“traffic_light”>
<li><input type=“radio” class=“on” name=“light” value=“red” /> Red</li>
<li><input type=“radio” class=“off” name=“light” value=“yellow” /> Yellow</li>
<li><input type=“radio” class=“off” name=“light” value=“green” /> Green</li>
</ul>
<input class=“button” id=“traffic_button” type=“submit” value=“Go” />
</form>
</div>
像这样选择按钮是低效的:
用ID直接选择按钮效率更高:
选择多个元素
提到多元素选择其实是在说DOM遍历和循环, 这些都是比较慢的东西.为了提高性能, 最好从就近的ID开始继承.
2. 在class前使用tag
第二快的选择器是tag选择器($(’head’)). 同理,因为它来自原生的getElementsByTagName() 方法.
<form method=“post” action=“/”>
<h2>Traffic Light</h2>
<ul id=“traffic_light”>
<li><input type=“radio” class=“on” name=“light” value=“red” /> Red</li>
<li><input type=“radio” class=“off” name=“light” value=“yellow” /> Yellow</li>
<li><input type=“radio” class=“off” name=“light” value=“green” /> Green</li>
</ul>
<input class=“button” id=“traffic_button” type=“submit” value=“Go” />
</form>
</div>$$
总是用一个tag name来限制(修饰)class (并且不要忘记就近的ID):
注意: 在jquery中Class是最慢的选择器. IE浏览器下它会遍历所有DOM节点不管它用在那里.
不要用用tag name来修饰ID. 下面的例子将会遍历所有的div元素来查找id为’content’的哪一个节点:
用ID修饰ID也是画蛇添足:
3.将jquery对象缓存起来
要养成将jquery对象缓存进变量的习惯.
永远不要这样做:
$(’#traffic_light input.on).css(‘border’, ‘3px dashed yellow’);
$(‘#traffic_light input.on).css(’background-color‘, ‘orange‘);
$(’#traffic_light input.on).fadeIn(’slow’);
最好先将对象缓存进一个变量然后再操作:
$active_light.bind(‘click’, function(){…});
$active_light.css(‘border’, ‘3px dashed yellow’);
$active_light.css(‘background-color’, ‘orange’);
$active_light.fadeIn(’slow’);
为了记住我们本地变量是jquery的封装, 通常用一个$作为变量前缀. 记住,永远不要让相同的选择器在你的代码里出现多次.
缓存jquery结果,备用
如果你打算将jquery结果对象用在程序的其它部分,或者你的function会多次执行, 那么就将他们缓存到一个全局变量中.
定义一个全局容器来存放jquery结果, 我们就可以在其它函数引用它们:
window.$my ={
// 初始化所有可能会不止一次要使用的查询
head : $(‘head’),
traffic_light : $(‘#traffic_light’),
traffic_button : $(‘#traffic_button’)
};
function do_something(){
// 现在你可以引用存储的结果并操作它们
var script = document.createElement(’script’);
$my.head.append(script);
// 当你在函数内部操作是, 可以继续将查询存入全局对象中去.
$my.cool_results = $(‘#some_ul li’);
$my.other_results = $(‘#some_table td’);
// 将全局函数作为一个普通的jquery对象去使用.
$my.other_results.css(‘border-color’, ‘red’);
$my.traffic_light.css(‘border-color’, ‘green’);
}
4. 掌握强大的链式操作
上面的例子也可以写成这样:
.css(‘border’, ‘3px dashed yellow’)
.css(‘background-color’, ‘orange’)
.fadeIn(’slow’);
这样可以写更少的代码, 让我们的js更轻量.
5.使用子查询
jQuery 允许我们对一个已包装的对象使用附加的选择器操作. 因为我们已经在保存了一个父级对象在变量里, 这样大大提高对其子元素的操作:
<form method=“post” action=“/”>
<h2>Traffic Light</h2>
<ul id=“traffic_light”>
<li><input type=“radio” class=“on” name=“light” value=“red” /> Red</li>
<li><input type=“radio” class=“off” name=“light” value=“yellow” /> Yellow</li>
<li><input type=“radio” class=“off” name=“light” value=“green” /> Green</li>
</ul>
<input class=“button” id=“traffic_button” type=“submit” value=“Go” />
</form>
</div>
例如, 我们可以用子查询的方法来抓取到亮或不亮的灯, 并缓存起来以备后续操作.
$active_light = $traffic_light.find(‘input.on’),
$inactive_lights = $traffic_light.find(‘input.off’);
提示: 你可以用逗号分隔的方法一次声明多个局部变量–节省字节数
6.对直接的DOM操作进行限制
这里的基本思想是在内存中建立你确实想要的东西,然后更新DOM 。这并不是一个jQuery最佳实践,但必须进行有效的JavaScript操作 。直接的DOM操作速度很慢。
例如,你想动态的创建一组列表元素, 千万不要这么做:
$mylist = $(‘#mylist’); // jQuery 选择到 <ul> 元素
for (var i=0, l=top_100_list.length; i<l; i++){
$mylist.append(‘<li>’ + top_100_list[i] + ‘</li>’);
}
我们应该将整套元素字符串在插入进dom中之前全部创建好:
$mylist = $(‘#mylist’),
top_100_li = “”; // 这个变量将用来存储我们的列表元素
for (var i=0, l=top_100_list.length; i<l; i++){
top_100_li += ‘<li>’ + top_100_list[i] + ‘</li>’;
}
$mylist.html(top_100_li);
我们在插入之前将多个元素包裹进一个单独的父级节点会更快:
$mylist = $(‘#mylist’),
top_100_ul = ‘<ul id=”#mylist”>’;
for (var i=0, l=top_100_list.length; i<l; i++){
top_100_ul += ‘<li>’ + top_100_list[i] + ‘</li>’;
}
top_100_ul += ‘</ul>’; //关闭无序列表
$mylist.replaceWith(top_100_ul);
如果你做了以上几条还是担心有性能问题,那么:
- 试试jquery的 clone() 方法, 它会创建一个节点树的副本, 它允许以”离线”的方式进行dom操作, 当你操作完成后再将其放回到节点树里.
- 使用DOM DocumentFragments. 正如jQuery作者所言, 它的性能要明显优于直接的dom操作.
7. 冒泡
除非在特殊情况下, 否则每一个js事件(例如:click, mouseover, 等.)都会冒泡到父级节点. 当我们需要给多个元素调用同个函数时这点会很有用.
代替这种效率很差的多元素事件监听的方法就是, 你只需向它们的父节点绑定一次, 并且可以计算出哪个节点触发了事件.
例如, 我们要为一个拥有很多输入框的表单绑定这样的行为: 当输入框被选中时为它添加一个class
像这样绑定事件是低效的:
$(this).addClass(’selected‘);
}).bind(’blur‘, function(){
$(this).removeClass(’selected‘);
});
我们需要在父级监听获取焦点和失去焦点的事件:
var cell = $(e.target); // e.target grabs the node that triggered the event.
cell.addClass(’selected’);
}).bind(‘blur’, function(e){
var cell = $(e.target);
cell.removeClass(’selected’);
});
父级元素扮演了一个调度员的角色, 它可以基于目标元素绑定事件. 如果你发现你给很多元素绑定了同一个事件监听, 那么你肯定哪里做错了.
8.消除无效查询
尽管jquery可以很优雅的处理没有匹配元素的情况, 但它还是需要花费时间去寻找. 如果你整站只有一个全局js, 那么极有可能把所有的jquery函数塞进$(document)ready(function(){//所有你引以为傲的代码})里.
只运行在页面里用到的函数. 大多数有效的方法就是使用行内初始化函数, 这样你的模板就能准确的控制何时何处该执行js.
例如, 你的”文章”页面模板, 你可能会引用如下的代码在body结束处:
mylib.article.init();
</script>
</body>
如果你的页面模板包含一些多变的模块可能不会出现在页面中, 或者为了视觉呈现的原因你需要它们能够快速加载, 你可以将初始化函数紧跟在模块之后.
<li><input type=“radio” class=“on” name=“light” value=“red” /> Red</li>
<li><input type=“radio” class=“off” name=“light” value=“yellow” /> Yellow</li>
<li><input type=“radio” class=“off” name=“light” value=“green” /> Green</li>
</ul>
<script type=“text/javascript>
mylib.traffic_light.init();
</script>
你的全局js库可能会是这样子的:
article_page :{
init : function(){
// Article 特有的jQuery函数.
}
},
traffic_light :{
init : function(){
// Traffic light 特有的jQuery函数.
}
}
}
9. 推迟到 $(window).load
jquery对于开发者来说有一个很诱人的东西, 可以把任何东西挂到$(document).ready下冒充事件. 在大多数例子中你都会发现这样的情况.
尽管$(document).ready确实很有用, 它可以在页面渲染时,其它元素还没下载完成就执行. 如果你发现你的页面一直是载入中的状态, 很有可能就是$(document).ready函数引起的.
你可以通过将jquery函数绑定到$(window).load 事件的方法来减少页面载入时的cpu使用率. 它会在所有的html(包括<iframe>)被下载完成后执行.
// 页面完全载入后才初始化的jQuery函数.
});
多余的功能例如拖放, 视觉特效和动画, 预载入隐藏图像,等等. 都是适合这种技术的场合.
10. 压缩js
推荐一个js在线压缩地址: http://dean.edwards.name/packer/
11. 全面掌握jquery库
知己知彼, 百战百胜. 只有更深入的了解jQuery才能更灵活的使用它. 这里提供一个jQuery的速查手册, 可以打印出来随身携带. 要是有能力将jQuery源码通读一遍那就更好了.
10款好用的快速在线web开发工具
这篇文章提供的10个快速在线网页开发工具可以为你在时间十分紧迫之际解决燃眉之急。这类工具的优点在于界面非常直观,操作简单快速,利用它们你可以做的事情包括:网页条纹,背景图案,网站Logo制作,字体样式,文本编辑,图像转换,取色器,等等,就算你不熟悉专业的应用程序如Dreamweaver之类,你也可以相当快速地完成操作。
1. Stripe Generator
这是我比较喜欢使用的网页条纹生成工具,可以制作完全个性化的渐隐渐显条形图案。
2. BgPatterns
类似于上面的条纹生成器,利用预设图片或者背景条纹可制作漂亮的重复图形背景。
3. Creatr
我不怎么喜欢此类工具,但是有时没有其它选择,我又需要创建‘Web 2.0′ logo,这个工具似乎是不二选择。
4. Image Tool
又一个免费的Web 2.0 Logo制作工具。
5. Typetester
需要快速设置你的字体? Typetester是一个很棒的工具,它能够让你按照自己的需要调整字体样式,提供在线预览,满意后可以下载一个样式表。
6. Editpad
一个轻量级的在线文本编辑器,可将编辑好的文本下载到本地保存。
7. Converticon
一款图片格式转换工具,能够将普通图片转换成ico 或 png的格式,一切操作全部在线完成,推荐使用,建议收藏。
8. Color Scheme Designer
一款颜色生成工具。
9. Gomockingbird
网页框架生成工具,能够快速生成你想要的网页布局。
10. ColourLovers
又一款好用的取色工具,颜色种类非常丰富,可以搜索颜色。
你对网页设计感兴趣吗?如果你喜欢这些在线工具,有新的想法,欢迎发表评论,并将本文分享给你的朋友。
免费 jQuery 交互式图形图表库
1. The Coolest Calendar
界面非常漂亮的一款日期选择插件,有详细的使用文档,最新版本 1.5。
2. DatePicker
这款日期插件支持单选、多选和时间区间选择,功能齐全,有 Dialog 和 Flat 两种模式。
3. Tigra Calendar
Tigra Calendar 是一个跨浏览器的 JavaScript 日历控件,以下拉弹出方式选择日期。
4. jQuery UI Datepicker
这款日期选择插件属于 jQuery UI 的组件,外观可以利用 jQuery UI 的主题功能定制。
5. Unobtrusive Date-Picker Widget
支持键盘快捷键,包含 16 种语言的语言包,定制性强。
6. Simple jQuery DatePicker
一款非常简单的 jQuery 日期选择插件,适合作为学习的示例。
7. YUI Library: Calendar Control
这款插件是 YUI 库的日期选择插件,功能实用。
8. Date Range Picker
这款插件是对 jQuery UI 日期插件的扩充,支持多种模式的时间区间选择。
9. jQuery Date Input
另一款基于 jQuery 的日期选择插件,轻量、快速、易用。
10. Multiday Calendar Datepicker
基于 jQuery 编写的时间区间选择插件,功能简单使用。
11. Calendar for Mootools
Calendar 是一个 Mootools 库的日期选择插件,定制性很强,代码托管在 Github 上面。
12. jQuery Date Input
基于 jQuery UI 的日期选择插件,支持日期和时间(时分秒)选择。