'ITWeb/개발일반'에 해당되는 글 489건

  1. 2012.02.10 Eclipse Project Import & Export
  2. 2012.02.10 [펌] Spring MVC Tutorial
  3. 2011.12.26 [펌] Javascript Garden...
  4. 2011.12.21 [펌] CSS Fonts Module Level3
  5. 2011.12.16 JavaScript OOP - 다중객체 생성 맛보기
  6. 2011.12.14 HTML5 Notification 맛보기
  7. 2011.12.09 허접 배너 Viewer 맛보기.
  8. 2011.12.07 정규표현식과 trim 맛보기.
  9. 2011.12.06 text rolling 맛보기 - using javascript.
  10. 2011.12.05 JSCoverage 사용 팁.

Eclipse Project Import & Export

ITWeb/개발일반 2012. 2. 10. 19:31
누구나 다 아는 Import & Export
뭐.. 난  머리가 나빠서.. 아무리 쉬운거라도 작성을 해놔야 하니까.. ^^;;

[Eclipse 에서 Project Export 하기]

1. Eclipse Package Expolorer 에서 Project 선택.
2. 선택한 Project 에서 마우스  우클릭.
3. 매뉴들에서 중간 쯤에 Export 클릭.
4. 팝업 매뉴창에서 General 클릭.
5. Archive File 선택 후 Next 버튼 클릭.
6. Import 목적이니까.. Select All 하고 "To archive file: " 선택 (어느 경로에 어떤 파일 명으로  Export 할거냐 하는 거임.)
7. 나머지는 그냥 "Save in zip format 이랑 Create directory structure for files 그리고 Compress the contents of the file" 선택 한체로 Finish 버튼 클릭

 

[Eclipse 에서 Export 한 Project 파일 Import 하기]

1. Eclipse 에서 매뉴에 File 선택.
2. Import 클릭.
3. General 클릭.
4. Existing Projects into Workspace 선택 후 Next 버튼 클릭.
5. Export 한 파일 찾아서 선택후 (Select archive file:)   Finish 버튼 클릭.



이게 왜 필요 할까요??
CI 서버나 Repository 가 없는 경우 누군가에게 진행중이던 Project 를 넘겨 주고 개발 하라고 시킬때 필요 하지 않을까 싶내요.. ㅎㅎ

사실 급하게 다른 PC 에 옮겨서 개발을 해야 해서.. 걍.. 이렇게 했다는.. ;; 
:

[펌] Spring MVC Tutorial

ITWeb/개발일반 2012. 2. 10. 19:18
:

[펌] Javascript Garden...

ITWeb/개발일반 2011. 12. 26. 17:42
원문 :  http://bonsaiden.github.com/JavaScript-Garden/

아주 좋은 글이 있어 퍼옵니다.
해당 사이트에서 ko 선택 하시면 한글 번역문 나옵니다.

Intro

JavaScript Garden is a growing collection of documentation about the most quirky parts of the JavaScript programming language. It gives advice to avoid common mistakes and subtle bugs, as well as performance issues and bad practices, that non-expert JavaScript programmers may encounter on their endeavours into the depths of the language.


JavaScript Garden does not aim to teach you JavaScript. Former knowledge of the language is strongly recommended in order to understand the topics covered in this guide. In order to learn the basics of the language, please head over to the excellent guide on the Mozilla Developer Network.


The Authors


This guide is the work of two lovely Stack Overflow users, Ivo Wetzel (Writing) and Zhang Yi Jiang (Design).


Contributors


Caio Romão (Spelling corrections)

Andreas Blixt (Language corrections)

Hosting


JavaScript Garden is hosted on GitHub, but Cramer Development supports us with a mirror at JavaScriptGarden.info.


License


JavaScript Garden is published under the MIT license and hosted on GitHub. If you find errors or typos please file an issue or a pull request on the repository. You can also find us in the JavaScript room on Stack Overflow chat.


Objects

Object Usage and Properties


Everything in JavaScript acts like an object, with the only two exceptions being null and undefined.


false.toString() // 'false'

[1, 2, 3].toString(); // '1,2,3'


function Foo(){}

Foo.bar = 1;

Foo.bar; // 1

A common misconception is that number literals cannot be used as objects. That is because a flaw in JavaScript's parser tries to parse the dot notation on a number as a floating point literal.


2.toString(); // raises SyntaxError

There are a couple of workarounds which can be used in order make number literals act as objects too.


2..toString(); // the second point is correctly recognized

2 .toString(); // note the space left to the dot

(2).toString(); // 2 is evaluated first

Objects as a Data Type


Objects in JavaScript can also be used as a Hashmap; they mainly consist of named properties mapping to values.


Using a object literal - {} notation - it is possible to create a plain object. This new object inherits from Object.prototype and has no own properties defined on it.


var foo = {}; // a new empty object


// a new object with a property called 'test' with value 12

var bar = {test: 12}; 

Accessing Properties


The properties of an object can be accessed in two ways, via either the dot notation or the square bracket notation.


var foo = {name: 'Kitten'}

foo.name; // kitten

foo['name']; // kitten


var get = 'name';

foo[get]; // kitten


foo.1234; // SyntaxError

foo['1234']; // works

Both notations are identical in their workings, with the only difference being that the square bracket notation allows for dynamic setting of properties, as well as the use of property names that would otherwise lead to a syntax error.


Deleting Properties


The only way to actually remove a property from an object is to use the delete operator; setting the property to undefined or null only removes the value associated with the property, but not the key.


var obj = {

    bar: 1,

    foo: 2,

    baz: 3

};

obj.bar = undefined;

obj.foo = null;

delete obj.baz;


for(var i in obj) {

    if (obj.hasOwnProperty(i)) {

        console.log(i, '' + obj[i]);

    }

}

The above outputs both bar undefined and foo null - only baz was removed and is therefore missing from the output.


Notation of Keys


var test = {

    'case': 'I am a keyword, so I must be notated as a string',

    delete: 'I am a keyword, so me too' // raises SyntaxError

};

Object properties can be both notated as plain characters and as strings. Due to another mis-design in JavaScript's parser, the above will throw a SyntaxError prior to ECMAScript 5.


This error arises from the fact that delete is a keyword; therefore, it must be notated as a string literal to ensure that it will be correctly interpreted by older JavaScript engines.


The Prototype


JavaScript does not feature a classical inheritance model; instead, it uses a prototypal one.


While this is often considered to be one of JavaScript's weaknesses, the prototypal inheritance model is in fact more powerful than the classic model. It is, for example, fairly trivial to build a classic model on top of it, while the other way around is a far more difficult task.


Due to the fact that JavaScript is basically the only widely used language that features prototypal inheritance, it takes some time to adjust to the differences between the two models.


The first major difference is that inheritance in JavaScript is done by using so called prototype chains.


Note: Simply using Bar.prototype = Foo.prototype will result in both objects sharing the same prototype. Therefore, changes to either object's prototype will affect the prototype of the other as well, which in most cases is not the desired effect.

function Foo() {

    this.value = 42;

}

Foo.prototype = {

    method: function() {}

};


function Bar() {}


// Set Bar's prototype to a new instance of Foo

Bar.prototype = new Foo();

Bar.prototype.foo = 'Hello World';


// Make sure to list Bar as the actual constructor

Bar.prototype.constructor = Bar;


var test = new Bar() // create a new bar instance


// The resulting prototype chain

test [instance of Bar]

    Bar.prototype [instance of Foo] 

        { foo: 'Hello World' }

        Foo.prototype

            { method: ... }

            Object.prototype

                { toString: ... /* etc. */ }

In the above, the object test will inherit from both Bar.prototype and Foo.prototype; hence, it will have access to the function method that was defined on Foo. It will also have access to the property value of the one Foo instance that is its prototype. It is important to note that new Bar() does not create a new Foo instance, but reuses the one assigned to its prototype; thus, all Bar instances will share the same value property.


Note: Do not use Bar.prototype = Foo, since it will not point to the prototype of Foo but rather to the function object Foo. So the prototype chain will go over Function.prototype and not Foo.prototype; therefore, method will not be on the prototype chain.

Property Lookup


When accessing the properties of an object, JavaScript will traverse the prototype chain upwards until it finds a property with the requested name.


When it reaches the top of the chain - namely Object.prototype - and still hasn't found the specified property, it will return the value undefined instead.


The Prototype Property


While the prototype property is used by the language to build the prototype chains, it is still possible to assign any given value to it. However, primitives will simply get ignored when assigned as a prototype.


function Foo() {}

Foo.prototype = 1; // no effect

Assigning objects, as shown in the example above, will work, and allows for dynamic creation of prototype chains.


Performance


The lookup time for properties that are high up on the prototype chain can have a negative impact on performance critical sections of code. Additionally, trying to access non-existent properties will always traverse the full prototype chain.


Also, when iterating over the properties of an object every property that is on the prototype chain will get enumerated.


Extension of Native Prototypes


One mis-feature that is often used is to extend Object.prototype or one of the other built in prototypes.


This technique is called monkey patching and breaks encapsulation. While used by widely spread frameworks such as Prototype, there is still no good reason for cluttering built-in types with additional non-standard functionality.


The only good reason for extending a built-in prototype is to backport the features of newer JavaScript engines; for example, Array.forEach.


In Conclusion


It is a must to understand the prototypal inheritance model completely before writing complex code which makes use of it. Also, watch the length of the prototype chains and break them up if necessary to avoid possible performance issues. Further, the native prototypes should never be extended unless it is for the sake of compatibility with newer JavaScript features.


hasOwnProperty


In order to check whether a object has a property defined on itself and not somewhere on its prototype chain, it is necessary to use the hasOwnProperty method which all objects inherit from Object.prototype.


Note: It is not enough to check whether a property is undefined. The property might very well exist, but its value just happens to be set to undefined.

hasOwnProperty is the only thing in JavaScript which deals with properties and does not traverse the prototype chain.


// Poisoning Object.prototype

Object.prototype.bar = 1; 

var foo = {goo: undefined};


foo.bar; // 1

'bar' in foo; // true


foo.hasOwnProperty('bar'); // false

foo.hasOwnProperty('goo'); // true

Only hasOwnProperty will give the correct and expected result; this is essential when iterating over the properties of any object. There is no other way to exclude properties that are not defined on the object itself, but somewhere on its prototype chain.


hasOwnProperty as a Property


JavaScript does not protect the property name hasOwnProperty; thus, if the possibility exists that an object might have a property with this name, it is necessary to use an external hasOwnProperty in order to get correct results.


var foo = {

    hasOwnProperty: function() {

        return false;

    },

    bar: 'Here be dragons'

};


foo.hasOwnProperty('bar'); // always returns false


// Use another Object's hasOwnProperty and call it with 'this' set to foo

({}).hasOwnProperty.call(foo, 'bar'); // true

In Conclusion


When checking for the existence of a property on a object, hasOwnProperty is the only method of doing so. It is also recommended to make hasOwnProperty part of every for in loop; this will avoid errors from extended native prototypes.


The for in Loop


Just like the in operator, the for in loop also traverses the prototype chain when iterating over the properties of an object.


Note: The for in loop will not iterate over any properties that have their enumerable attribute set to false; for example, the length property of an array.

// Poisoning Object.prototype

Object.prototype.bar = 1;


var foo = {moo: 2};

for(var i in foo) {

    console.log(i); // prints both bar and moo

}

Since it is not possible to change the behavior of the for in loop itself, it is necessary to filter out the unwanted properties inside the loop body; this is done by using the hasOwnProperty method of Object.prototype.


Note: Since the for in always traverses the complete prototype chain, it will get slower with each additional layer of inheritance added to an object.

Using hasOwnProperty for Filtering


// still the foo from above

for(var i in foo) {

    if (foo.hasOwnProperty(i)) {

        console.log(i);

    }

}

This version is the only correct one to use. Due to the use of hasOwnProperty, it will only print out moo. When hasOwnProperty is left out, the code is prone to errors in cases where the native prototypes - e.g. Object.prototype - have been extended.


One widely used framework which does this is Prototype. When this framework is included, for in loops that do not use hasOwnProperty are guaranteed to break.


In Conclusion


It is recommended to always use hasOwnProperty. Never should any assumptions be made about the environment the code is running in, or whether the native prototypes have been extended or not.


Functions

Function Declarations and Expressions


Functions in JavaScript are first class objects. That means they can be passed around like any other value. One common use of this feature is to pass an anonymous function as a callback to another, possibly asynchronous function.


The function Declaration


function foo() {}

The above function gets hoisted before the execution of the program starts; thus, it is available everywhere in the scope it was defined in, even if called before the actual definition in the source.


foo(); // Works because foo was created before this code runs

function foo() {}

The function Expression


var foo = function() {};

This example assigns the unnamed and anonymous function to the variable foo.


foo; // 'undefined'

foo(); // this raises a TypeError

var foo = function() {};

Due to the fact that var is a declaration that hoists the variable name foo before the actual execution of the code starts, foo is already defined when the script gets executed.


But since assignments only happen at runtime, the value of foo will default to undefined before the corresponding code is executed.


Named Function Expression


Another special case is the assignment of named functions.


var foo = function bar() {

    bar(); // Works

}

bar(); // ReferenceError

Here, bar is not available in the outer scope, since the function only gets assigned to foo; however, inside of bar, it is available. This is due to how name resolution in JavaScript works, the name of the function is always made available in the local scope of the function itself.


How this Works


JavaScript has a different concept of what the special name this refers to than most other programming languages do. There are exactly five different ways in which the value of this can be bound in the language.


The Global Scope


this;

When using this in global scope, it will simply refer to the global object.


Calling a Function


foo();

Here, this will again refer to the global object.


ES5 Note: In strict mode, the global case no longer exists. this will instead have the value of undefined in that case.

Calling a Method


test.foo(); 

In this example, this will refer to test.


Calling a Constructor


new foo(); 

A function call that is preceded by the new keyword acts as a constructor. Inside the function, this will refer to a newly created Object.


Explicit Setting of this


function foo(a, b, c) {}


var bar = {};

foo.apply(bar, [1, 2, 3]); // array will expand to the below

foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3

When using the call or apply methods of Function.prototype, the value of this inside the called function gets explicitly set to the first argument of the corresponding function call.


As a result, the above example the method case does not apply, and this inside of foo will be set to bar.


Note: this cannot be used to refer to the object inside of an Object literal. So var obj = {me: this} will not result in me referring to obj, since this only gets bound by one of the five listed cases.

Common Pitfalls


While most of these cases make sense, the first one is to be considered another mis-design of the language because it never has any practical use.


Foo.method = function() {

    function test() {

        // this is set to the global object

    }

    test();

}

A common misconception is that this inside of test refers to Foo; while in fact, it does not.


In order to gain access to Foo from within test, it is necessary to create a local variable inside of method which refers to Foo.


Foo.method = function() {

    var that = this;

    function test() {

        // Use that instead of this here

    }

    test();

}

that is just a normal variable name, but it is commonly used for the reference to an outer this. In combination with closures, it can also be used to pass this values around.


Assigning Methods


Another thing that does not work in JavaScript is function aliasing, which is assigning a method to a variable.


var test = someObject.methodTest;

test();

Due to the first case, test now acts like a plain function call; therefore, this inside it will no longer refer to someObject.


While the late binding of this might seem like a bad idea at first, in fact, it is what makes prototypal inheritance work.


function Foo() {}

Foo.prototype.method = function() {};


function Bar() {}

Bar.prototype = Foo.prototype;


new Bar().method();

When method gets called on a instance of Bar, this will now refer to that very instance.


Closures and References


One of JavaScript's most powerful features is the availability of closures. With closures, scopes always keep access to the outer scope, in which they were defined. Since the only scoping that JavaScript has is function scope, all functions, by default, act as closures.


Emulating private variables


function Counter(start) {

    var count = start;

    return {

        increment: function() {

            count++;

        },


        get: function() {

            return count;

        }

    }

}


var foo = Counter(4);

foo.increment();

foo.get(); // 5

Here, Counter returns two closures: the function increment as well as the function get. Both of these functions keep a reference to the scope of Counter and, therefore, always keep access to the count variable that was defined in that very scope.


Why Private Variables Work


Since it is not possible to reference or assign scopes in JavaScript, there is no way of accessing the variable count from the outside. The only way to interact with it is via the two closures.


var foo = new Counter(4);

foo.hack = function() {

    count = 1337;

};

The above code will not change the variable count in the scope of Counter, since foo.hack was not defined in that scope. It will instead create - or override - the global variable count.


Closures Inside Loops


One often made mistake is to use closures inside of loops, as if they were copying the value of the loops index variable.


for(var i = 0; i < 10; i++) {

    setTimeout(function() {

        console.log(i);  

    }, 1000);

}

The above will not output the numbers 0 through 9, but will simply print the number 10 ten times.


The anonymous function keeps a reference to i. At the time console.log gets called, the for loop has already finished, and the value of i as been set to 10.


In order to get the desired behavior, it is necessary to create a copy of the value of i.


Avoiding the Reference Problem


In order to copy the value of the loop's index variable, it is best to use an anonymous wrapper.


for(var i = 0; i < 10; i++) {

    (function(e) {

        setTimeout(function() {

            console.log(e);  

        }, 1000);

    })(i);

}

The anonymous outer function gets called immediately with i as its first argument and will receive a copy of the value of i as its parameter e.


The anonymous function that gets passed to setTimeout now has a reference to e, whose value does not get changed by the loop.


There is another possible way of achieving this, which is to return a function from the anonymous wrapper that will then have the same behavior as the code above.


for(var i = 0; i < 10; i++) {

    setTimeout((function(e) {

        return function() {

            console.log(e);

        }

    })(i), 1000)

}

The arguments Object


Every function scope in JavaScript can access the special variable arguments. This variable holds a list of all the arguments that were passed to the function.


Note: In case arguments has already been defined inside the function's scope either via a var statement or being the name of a formal parameter, the arguments object will not be created.

The arguments object is not an Array. While it has some of the semantics of an array - namely the length property - it does not inherit from Array.prototype and is in fact an Object.


Due to this, it is not possible to use standard array methods like push, pop or slice on arguments. While iteration with a plain for loop works just fine, it is necessary to convert it to a real Array in order to use the standard Array methods on it.


Converting to an Array


The code below will return a new Array containing all the elements of the arguments object.


Array.prototype.slice.call(arguments);

Because this conversion is slow, it is not recommended to use it in performance-critical sections of code.


Passing Arguments


The following is the recommended way of passing arguments from one function to another.


function foo() {

    bar.apply(null, arguments);

}

function bar(a, b, c) {

    // do stuff here

}

Another trick is to use both call and apply together to create fast, unbound wrappers.


function Foo() {}


Foo.prototype.method = function(a, b, c) {

    console.log(this, a, b, c);

};


// Create an unbound version of "method" 

// It takes the parameters: this, arg1, arg2...argN

Foo.method = function() {


    // Result: Foo.prototype.method.call(this, arg1, arg2... argN)

    Function.call.apply(Foo.prototype.method, arguments);

};

Formal Parameters and Arguments Indices


The arguments object creates getter and setter functions for both its properties, as well as the function's formal parameters.


As a result, changing the value of a formal parameter will also change the value of the corresponding property on the arguments object, and the other way around.


function foo(a, b, c) {

    arguments[0] = 2;

    a; // 2


    b = 4;

    arguments[1]; // 4


    var d = c;

    d = 9;

    c; // 3

}

foo(1, 2, 3);

Performance Myths and Truths


The arguments object is always created with the only two exceptions being the cases where it is declared as a name inside of a function or one of its formal parameters. It does not matter whether it is used or not.


Both getters and setters are always created; thus, using it has nearly no performance impact at all, especially not in real world code where there is more than a simple access to the arguments object's properties.


ES5 Note: These getters and setters are not created in strict mode.

However, there is one case which will drastically reduce the performance in modern JavaScript engines. That case is the use of arguments.callee.


function foo() {

    arguments.callee; // do something with this function object

    arguments.callee.caller; // and the calling function object

}


function bigLoop() {

    for(var i = 0; i < 100000; i++) {

        foo(); // Would normally be inlined...

    }

}

In the above code, foo can no longer be a subject to inlining since it needs to know about both itself and its caller. This not only defeats possible performance gains that would arise from inlining, but it also breaks encapsulation because the function may now be dependent on a specific calling context.


It is highly recommended to never make use of arguments.callee or any of its properties.


ES5 Note: In strict mode, arguments.callee will throw a TypeError since its use has been deprecated.

Constructors


Constructors in JavaScript are yet again different from many other languages. Any function call that is preceded by the new keyword acts as a constructor.


Inside the constructor - the called function - the value of this refers to a newly created Object. The prototype of this new object is set to the prototype of the function object that was invoked as the constructor.


If the function that was called has no explicit return statement, then it implicitly returns the value of this - the new object.


function Foo() {

    this.bla = 1;

}


Foo.prototype.test = function() {

    console.log(this.bla);

};


var test = new Foo();

The above calls Foo as constructor and sets the prototype of the newly created object to Foo.prototype.


In case of an explicit return statement, the function returns the value specified that statement, but only if the return value is an Object.


function Bar() {

    return 2;

}

new Bar(); // a new object


function Test() {

    this.value = 2;


    return {

        foo: 1

    };

}

new Test(); // the returned object

When the new keyword is omitted, the function will not return a new object.


function Foo() {

    this.bla = 1; // gets set on the global object

}

Foo(); // undefined

While the above example might still appear to work in some cases, due to the workings of this in JavaScript, it will use the global object as the value of this.


Factories


In order to be able to omit the new keyword, the constructor function has to explicitly return a value.


function Bar() {

    var value = 1;

    return {

        method: function() {

            return value;

        }

    }

}

Bar.prototype = {

    foo: function() {}

};


new Bar();

Bar();

Both calls to Bar return the exact same thing, a newly create object which has a property called method on it, which is a Closure.


It is also to note that the call new Bar() does not affect the prototype of the returned object. While the prototype will be set on the newly created object, Bar never returns that new object.


In the above example, there is no functional difference between using and not using the new keyword.


Creating New Objects via Factories


An often made recommendation is to not use new because forgetting its use may lead to bugs.


In order to create new object, one should rather use a factory and construct a new object inside of that factory.


function Foo() {

    var obj = {};

    obj.value = 'blub';


    var private = 2;

    obj.someMethod = function(value) {

        this.value = value;

    }


    obj.getPrivate = function() {

        return private;

    }

    return obj;

}

While the above is robust against a missing new keyword and certainly makes the use of private variables easier, it comes with some downsides.


It uses more memory since the created objects do not share the methods on a prototype.

In order to inherit the factory needs to copy all the methods from another object or put that object on the prototype of the new object.

Dropping the prototype chain just because of a left out new keyword somehow goes against the spirit of the language.

In Conclusion


While omitting the new keyword might lead to bugs, it is certainly not a reason to drop the use of prototypes altogether. In the end it comes down to which solution is better suited for the needs of the application, it is especially important to choose a specific style of object creation and stick with it.


Scopes and Namespaces


Although JavaScript deals fine with the syntax of two matching curly braces for blocks, it does not support block scope; hence, all that is left is in the language is function scope.


function test() { // a scope

    for(var i = 0; i < 10; i++) { // not a scope

        // count

    }

    console.log(i); // 10

}

Note: When not used in an assignment, return statement or as a function argument, the {...} notation will get interpreted as a block statement and not as an object literal. This, in conjunction with automatic insertion of semicolons, can lead to subtle errors.

There are also no distinct namespaces in JavaScript, which means that everything gets defined in one globally shared namespace.


Each time a variable is referenced, JavaScript will traverse upwards through all the scopes until it finds it. In the case that it reaches the global scope and still has not found the requested name, it will raise a ReferenceError.


The Bane of Global Variables


// script A

foo = '42';


// script B

var foo = '42'

The above two scripts do not have the same effect. Script A defines a variable called foo in the global scope, and script B defines a foo in the current scope.


Again, that is not at all the same effect: not using var can have major implications.


// global scope

var foo = 42;

function test() {

    // local scope

    foo = 21;

}

test();

foo; // 21

Leaving out the var statement inside the function test will override the value of foo. While this might not seem like a big deal at first, having thousands of lines of JavaScript and not using var will introduce horrible, hard-to-track-down bugs.


// global scope

var items = [/* some list */];

for(var i = 0; i < 10; i++) {

    subLoop();

}


function subLoop() {

    // scope of subLoop

    for(i = 0; i < 10; i++) { // missing var statement

        // do amazing stuff!

    }

}

The outer loop will terminate after the first call to subLoop, since subLoop overwrites the global value of i. Using a var for the second for loop would have easily avoided this error. The var statement should never be left out unless the desired effect is to affect the outer scope.


Local Variables


The only source for local variables in JavaScript are function parameters and variables that were declared via the var statement.


// global scope

var foo = 1;

var bar = 2;

var i = 2;


function test(i) {

    // local scope of the function test

    i = 5;


    var foo = 3;

    bar = 4;

}

test(10);

While foo and i are local variables inside the scope of the function test, the assignment of bar will override the global variable with the same name.


Hoisting


JavaScript hoists declarations. This means that both var statements and function declarations will be moved to the top of their enclosing scope.


bar();

var bar = function() {};

var someValue = 42;


test();

function test(data) {

    if (false) {

        goo = 1;


    } else {

        var goo = 2;

    }

    for(var i = 0; i < 100; i++) {

        var e = data[i];

    }

}

The above code gets transformed before any execution is started. JavaScript moves the var statements, as well as the function declarations to the top of the nearest surrounding scope.


// var statements got moved here

var bar, someValue; // default to 'undefined'


// the function declaration got moved up too

function test(data) {

    var goo, i, e; // missing block scope moves these here

    if (false) {

        goo = 1;


    } else {

        goo = 2;

    }

    for(i = 0; i < 100; i++) {

        e = data[i];

    }

}


bar(); // fails with a TypeError since bar is still 'undefined'

someValue = 42; // assignments are not affected by hoisting

bar = function() {};


test();

Missing block scoping will not only move var statements out of loops and their bodies, it will also make the results of certain if constructs non-intuitive.


In the original code, although the if statement seemed to modify the global variable goo, it actually modifies the local variable - after hoisting has been applied.


Without the knowledge about hoisting, the below code might seem to raise a ReferenceError.


// check whether SomeImportantThing has been initiliazed

if (!SomeImportantThing) {

    var SomeImportantThing = {};

}

But of course, the above works due to the fact that the var statement is being moved to the top of the global scope.


var SomeImportantThing;


// other code might initiliaze SomeImportantThing here, or not


// make sure it's there

if (!SomeImportantThing) {

    SomeImportantThing = {};

}

Name Resolution Order


All scopes in JavaScript, including the global scope, have the special name this, defined in them, which refers to the current object.


Function scopes also have the name arguments, defined in them, which contains the arguments that were passed to a function.


For example, when trying to access a variable named foo inside the scope of a function, JavaScript will lookup the name in the following order:


In case there is a var foo statement in the current scope, use that.

If one of the function parameters is named foo, use that.

If the function itself is called foo, use that.

Go to the next outer scope, and start with #1 again.

Note: Having a parameter called arguments will prevent the creation of the default arguments object.

Namespaces


A common problem of having only one global namespace is the likeliness of running into problems where variable names clash. In JavaScript, this problem can easily be avoided with the help of anonymous wrappers.


(function() {

    // a self contained "namespace"


    window.foo = function() {

        // an exposed closure

    };


})(); // execute the function immediately

Unnamed functions are considered expressions; so in order to being callable, they must first be evaluated.


( // evaluate the function inside the paranthesis

function() {}

) // and return the function object

() // call the result of the evaluation

There are other ways for evaluating and calling the function expression; which, while different in syntax, do behave the exact same way.


// Two other ways

+function(){}();

(function(){}());

In Conclusion


It is recommended to always use an anonymous wrapper for encapsulating code in its own namespace. This does not only protect code against name clashes, but it also allows for better modularization of programs.


Additionally, the use of global variables is considered bad practice. Any use of them indicates badly written code that is prone to errors and hard to maintain.


Arrays

Array Iteration and Properties


Although arrays in JavaScript are objects, there are no good reasons to use the for in loop in for iteration on them. In fact, there are a number of good reasons against the use of for in on arrays.


Note: JavaScript arrays are not associative arrays. JavaScript only has objects for mapping keys to values. And while associative arrays preserve order, objects do not.

Because the for in loop enumerates all the properties that are on the prototype chain and because the only way to exclude those properties is to use hasOwnProperty, it is already up to twenty times slower than a normal for loop.


Iteration


In order to achieve the best performance when iterating over arrays, it is best to use the classic for loop.


var list = [1, 2, 3, 4, 5, ...... 100000000];

for(var i = 0, l = list.length; i < l; i++) {

    console.log(list[i]);

}

There is one extra catch in the above example, which is the caching of the length of the array via l = list.length.


Although the length property is defined on the array itself, there is still an overhead for doing the lookup on each iteration of the loop. And while recent JavaScript engines may apply optimization in this case, there is no way of telling whether the code will run on one of these newer engines or not.


In fact, leaving out the caching may result in the loop being only half as fast as with the cached length.


The length Property


While the getter of the length property simply returns the number of elements that are contained in the array, the setter can be used to truncate the array.


var foo = [1, 2, 3, 4, 5, 6];

foo.length = 3;

foo; // [1, 2, 3]


foo.length = 6;

foo; // [1, 2, 3]

Assigning a smaller length does truncate the array, but increasing the length does not have any effect on the array.


In Conclusion


For the best performance, it is recommended to always use the plain for loop and cache the length property. The use of for in on an array is a sign of badly written code that is prone to bugs and bad performance.


The Array Constructor


Since the Array constructor is ambiguous in how it deals with its parameters, it is highly recommended to always use the array literals - [] notation - when creating new arrays.


[1, 2, 3]; // Result: [1, 2, 3]

new Array(1, 2, 3); // Result: [1, 2, 3]


[3]; // Result: [3]

new Array(3); // Result: []

new Array('3') // Result: ['3']

In cases when there is only one argument passed to the Array constructor and when that argument is a Number, the constructor will return a new sparse array with the length property set to the value of the argument. It should be noted that only the length property of the new array will be set this way; the actual indexes of the array will not be initialized.


var arr = new Array(3);

arr[1]; // undefined

1 in arr; // false, the index was not set

The behavior of being able to set the length of the array upfront only comes in handy in a few cases, like repeating a string, in which it avoids the use of a for loop code.


new Array(count + 1).join(stringToRepeat);

In Conclusion


The use of the Array constructor should be avoided as much as possible. Literals are definitely preferred. They are shorter and have a clearer syntax; therefore, they also increase the readability of the code.


Types

Equality and Comparisons


JavaScript has two different ways of comparing the values of objects for equality.


The Equality Operator


The equality operator consists of two equal signs: ==


JavaScript features weak typing. This means that the equality operator coerces types in order to compare them.


""           ==   "0"           // false

0            ==   ""            // true

0            ==   "0"           // true

false        ==   "false"       // false

false        ==   "0"           // true

false        ==   undefined     // false

false        ==   null          // false

null         ==   undefined     // true

" \t\r\n"    ==   0             // true

The above table shows the results of the type coercion, and it is the main reason why the use of == is widely regarded as bad practice. It introduces hard-to-track-down bugs due to its complicated conversion rules.


Additionally, there is also a performance impact when type coercion is in play; for example, a string has to be converted to a number before it can be compared to another number.


The Strict Equality Operator


The strict equality operator consists of three equal signs: ===.


It works exactly like the normal equality operator, except that strict equality operator does not perform type coercion between its operands.


""           ===   "0"           // false

0            ===   ""            // false

0            ===   "0"           // false

false        ===   "false"       // false

false        ===   "0"           // false

false        ===   undefined     // false

false        ===   null          // false

null         ===   undefined     // false

" \t\r\n"    ===   0             // false

The above results are a lot clearer and allow for early breakage of code. This hardens code to a certain degree and also gives performance improvements in case the operands are of different types.


Comparing Objects


While both == and === are stated as equality operators, they behave differently when at least one of their operands happens to be an Object.


{} === {};                   // false

new String('foo') === 'foo'; // false

new Number(10) === 10;       // false

var foo = {};

foo === foo;                 // true

Here, both operators compare for identity and not equality; that is, they will compare for the same instance of the object, much like is in Python and pointer comparison in C.


In Conclusion


It is highly recommended to only use the strict equality operator. In cases where types need to be coerced, it should be done explicitly and not left to the language's complicated coercion rules.


The typeof Operator


The typeof operator (together with instanceof) is probably the biggest design flaw of JavaScript, as it is near of being completely broken.


Although instanceof still has its limited uses, typeof really has only one practical use case, which does not happen to be checking the type of an object.


Note: While typeof can also be called with a function like syntax i.e. typeof(obj), this is not a function call. The two parenthesis will behave like normal and the return value will be used as the operand of the typeof operator. There is no typeof function.

The JavaScript Type Table


Value               Class      Type

-------------------------------------

"foo"               String     string

new String("foo")   String     object

1.2                 Number     number

new Number(1.2)     Number     object

true                Boolean    boolean

new Boolean(true)   Boolean    object

new Date()          Date       object

new Error()         Error      object

[1,2,3]             Array      object

new Array(1, 2, 3)  Array      object

new Function("")    Function   function

/abc/g              RegExp     object (function in Nitro/V8)

new RegExp("meow")  RegExp     object (function in Nitro/V8)

{}                  Object     object

new Object()        Object     object

In the above table, Type refers to the value that the typeof operator returns. As can be clearly seen, this value is anything but consistent.


The Class refers to the value of the internal [[Class]] property of an object.


From the Specification: The value of [[Class]] can be one of the following strings. Arguments, Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, String.

In order to retrieve the value of [[Class]], one has to make use of the toString method of Object.prototype.


The Class of an Object


The specification gives exactly one way of accessing the [[Class]] value, with the use of Object.prototype.toString.


function is(type, obj) {

    var clas = Object.prototype.toString.call(obj).slice(8, -1);

    return obj !== undefined && obj !== null && clas === type;

}


is('String', 'test'); // true

is('String', new String('test')); // true

In the above example, Object.prototype.toString gets called with the value of this being set to the object whose [[Class]] value should be retrieved.


ES5 Note: For convenience the return value of Object.prototype.toString for both null and undefined was changed from Object to Null and Undefined in ECMAScript 5.

Testing for Undefined Variables


typeof foo !== 'undefined'

The above will check whether foo was actually declared or not; just referencing it would result in a ReferenceError. This is the only thing typeof is actually useful for.


In Conclusion


In order to check the type of an object, it is highly recommended to use Object.prototype.toString because this is the only reliable way of doing so. As shown in the above type table, some return values of typeof are not defined in the specification; thus, they can differ across various implementations.


Unless checking whether a variable is defined, typeof should be avoided at all costs.


The instanceof Operator


The instanceof operator compares the constructors of its two operands. It is only useful when comparing custom made objects. Used on built-in types, it is nearly as useless as the typeof operator.


Comparing Custom Objects


function Foo() {}

function Bar() {}

Bar.prototype = new Foo();


new Bar() instanceof Bar; // true

new Bar() instanceof Foo; // true


// This just sets Bar.prototype to the function object Foo

// But not to an actual instance of Foo

Bar.prototype = Foo;

new Bar() instanceof Foo; // false

Using instanceof with Native Types


new String('foo') instanceof String; // true

new String('foo') instanceof Object; // true


'foo' instanceof String; // false

'foo' instanceof Object; // false

One important thing to note here is that instanceof does not work on objects that originate from different JavaScript contexts (e.g. different documents in a web browser), since their constructors will not be the exact same object.


In Conclusion


The instanceof operator should only be used when dealing with custom made objects that originate from the same JavaScript context. Just like the typeof operator, every other use of it should be avoided.


Type Casting


JavaScript is a weakly typed language, so it will apply type coercion wherever possible.


// These are true

new Number(10) == 10; // Number.toString() is converted

                      // back to a number


10 == '10';           // Strings gets converted to Number

10 == '+10 ';         // More string madness

10 == '010';          // And more 

isNaN(null) == false; // null converts to 0

                      // which of course is not NaN


// These are false

10 == 010;

10 == '-10';

ES5 Note: Number literals that start with a 0 are interpreted as octal (Base 8). Octal support for these has been removed in ECMAScript 5 strict mode.

In order to avoid the above, use of the strict equal operator is highly recommended. Although this avoids a lot of common pitfalls, there are still many further issues that arise from JavaScript's weak typing system.


Constructors of Built-In Types


The constructors of the built in types like Number and String behave differently when being used with the new keyword and without it.


new Number(10) === 10;     // False, Object and Number

Number(10) === 10;         // True, Number and Number

new Number(10) + 0 === 10; // True, due to implicit conversion

Using a built-in type like Number as a constructor will create a new Number object, but leaving out the new keyword will make the Number function behave like a converter.


In addition, having literals or non-object values in there will result in even more type coercion.


The best option is to cast to one of the three possible types explicitly.


Casting to a String


'' + 10 === '10'; // true

By prepending an empty string, a value can easily be casted to a string.


Casting to a Number


+'10' === 10; // true

Using the unary plus operator, it is possible to cast to a number.


Casting to a Boolean


By using the not operator twice, a value can be converted a boolean.


!!'foo';   // true

!!'';      // false

!!'0';     // true

!!'1';     // true

!!'-1'     // true

!!{};      // true

!!true;    // true

Core

Why Not to Use eval


The eval function will execute a string of JavaScript code in the local scope.


var foo = 1;

function test() {

    var foo = 2;

    eval('foo = 3');

    return foo;

}

test(); // 3

foo; // 1

However, eval only executes in the local scope when it is being called directly and when the name of the called function is actually eval.


var foo = 1;

function test() {

    var foo = 2;

    var bar = eval;

    bar('foo = 3');

    return foo;

}

test(); // 2

foo; // 3

The use of eval should be avoided at all costs. 99.9% of its "uses" can be achieved without it.


eval in Disguise


The timeout functions setTimeout and setInterval can both take a string as their first argument. This string will always get executed in the global scope since eval is not being called directly in that case.


Security Issues


eval also is a security problem. Because it executes any code given to it, it should never be used with strings of unknown or untrusted origins.


In Conclusion


eval should never be used. Any code that makes use of it is to be questioned in its workings, performance and security. In case something requires eval in order to work, it should not be used in the first place. A better design should be used, that does not require the use of eval.


undefined and null


JavaScript has two distinct values for nothing, the more useful of these two being undefined.


The Value undefined


undefined is a type with exactly one value: undefined.


The language also defines a global variable that has the value of undefined; this variable is also called undefined. However, this variable is neither a constant nor a keyword of the language. This means that its value can be easily overwritten.


ES5 Note: undefined in ECMAScript 5 is no longer writable in strict mode, but its name can still be shadowed by for example a function with the name undefined.

Some examples for when the value undefined is returned:


Accessing the (unmodified) global variable undefined.

Implicit returns of functions due to missing return statements.

return statements which do not explicitly return anything.

Lookups of non-existent properties.

Function parameters which do not had any explicit value passed.

Anything that has been set to the value of undefined.

Handling Changes to the Value of undefined


Since the global variable undefined only holds a copy of the actual value of undefined, assigning a new value to it does not change the value of the type undefined.


Still, in order to compare something against the value of undefined, it is necessary to retrieve the value of undefined first.


In order to protect code against a possible overwritten undefined variable, a common technique used is to add an additional parameter to an anonymous wrapper that gets no argument passed to it.


var undefined = 123;

(function(something, foo, undefined) {

    // undefined in the local scope does 

    // now again refer to the value


})('Hello World', 42);

Another way to achieve the same effect would be to use a declaration inside the wrapper.


var undefined = 123;

(function(something, foo) {

    var undefined;

    ...


})('Hello World', 42);

The only difference here is that this version results in 4 more bytes being used in case it is minified, and there is no other var statement inside the anonymous wrapper.


Uses of null


While undefined in the context of the JavaScript language is mostly used in the sense of a traditional null, the actual null (both a literal and a type) is more or less just another data type.


It is used in some JavaScript internals (like declaring the end of the prototype chain by setting Foo.prototype = null), but in almost all cases, it can be replaced by undefined.


Automatic Semicolon Insertion


Although JavaScript has C style syntax, it does not enforce the use of semicolons in the source code, so it is possible to omit them.


JavaScript is not a semicolon-less language. In fact, it needs the semicolons in order to understand the source code. Therefore, the JavaScript parser automatically inserts them whenever it encounters a parse error due to a missing semicolon.


var foo = function() {

} // parse error, semicolon expected

test()

Insertion happens, and the parser tries again.


var foo = function() {

}; // no error, parser continues

test()

The automatic insertion of semicolon is considered to be one of biggest design flaws in the language because it can change the behavior of code.


How it Works


The code below has no semicolons in it, so it is up to the parser to decide where to insert them.


(function(window, undefined) {

    function test(options) {

        log('testing!')


        (options.list || []).forEach(function(i) {


        })


        options.value.test(

            'long string to pass here',

            'and another long string to pass'

        )


        return

        {

            foo: function() {}

        }

    }

    window.test = test


})(window)


(function(window) {

    window.someLibrary = {}


})(window)

Below is the result of the parser's "guessing" game.


(function(window, undefined) {

    function test(options) {


        // Not inserted, lines got merged

        log('testing!')(options.list || []).forEach(function(i) {


        }); // <- inserted


        options.value.test(

            'long string to pass here',

            'and another long string to pass'

        ); // <- inserted


        return; // <- inserted, breaks the return statement

        { // treated as a block


            // a label and a single expression statement

            foo: function() {} 

        }; // <- inserted

    }

    window.test = test; // <- inserted


// The lines got merged again

})(window)(function(window) {

    window.someLibrary = {}; // <- inserted


})(window); //<- inserted

Note: The JavaScript parser does not "correctly" handle return statements which are followed by a new line, while this is not neccessarily the fault of the automatic semicolon insertion, it can still be an unwanted side-effect.

The parser drastically changed the behavior of the code above. In certain cases, it does the wrong thing.


Leading Parenthesis


In case of a leading parenthesis, the parser will not insert a semicolon.


log('testing!')

(options.list || []).forEach(function(i) {})

This code gets transformed into one line.


log('testing!')(options.list || []).forEach(function(i) {})

Chances are very high that log does not return a function; therefore, the above will yield a TypeError stating that undefined is not a function.


In Conclusion


It is highly recommended to never omit semicolons; it is also advocated to keep braces on the same line with their corresponding statements and to never omit them for one single-line if / else statements. Both of these measures will not only improve the consistency of the code, but they will also prevent the JavaScript parser from changing its behavior.


The delete Operator


In short, it's impossible to delete global variables, functions and some other stuff in JavaScript which have a DontDelete attribute set.


Global code and Function code


When a variable or a function is defined in a global or a function scope it is a property of either Activation object or Global object. Such properties have a set of attributes, one of these is DontDelete. Variable and function declarations in global and function code always create properties with DontDelete, therefore cannot be deleted.


// global variable:

var a = 1; // DontDelete is set

delete a; // false

a; // 1


// normal function:

function f() {} // DontDelete is set

delete f; // false

typeof f; // "function"


// reassigning doesn't help:

f = 1;

delete f; // false

f; // 1

Explicit properties


There are things which can be deleted normally: these are explicitly set properties.


// explicitly set property:

var obj = {x: 1};

obj.y = 2;

delete obj.x; // true

delete obj.y; // true

obj.x; // undefined

obj.y; // undefined

In the example above obj.x and obj.y can be deleted because they have no DontDelete atribute. That's why an example below works too.


// this works fine, except for IE:

var GLOBAL_OBJECT = this;

GLOBAL_OBJECT.a = 1;

a === GLOBAL_OBJECT.a; // true - just a global var

delete GLOBAL_OBJECT.a; // true

GLOBAL_OBJECT.a; // undefined

Here we use a trick to delete a. this here refers to the Global object and we explicitly declare variable a as it's property which allows us to delete it.


IE (at least 6-8) has some bugs, so code above doesn't work.


Function arguments and built-ins


Functions' normal arguments, arguments object and built-in properties also have DontDelete set.


// function arguments and properties:

(function (x) {


  delete arguments; // false

  typeof arguments; // "object"


  delete x; // false

  x; // 1


  function f(){}

  delete f.length; // false

  typeof f.length; // "number"


})(1);

Host objects


Behaviour of delete operator can be unpredictable for hosted objects. Due to specification, host objects are allowed to implement any kind of behavior.


In conclusion


delete operator often has an unexpected behaviour and can be safely used only for dealing with explicitly set properties on normal objects.


Other

setTimeout and setInterval


Since JavaScript is asynchronous, it is possible to schedule the execution of a function by using the setTimeout and setInterval functions.


Note: Timeouts are not part of the ECMAScript Standard. They are implemented as part of the DOM.

function foo() {}

var id = setTimeout(foo, 1000); // returns a Number > 0

When setTimeout gets called, it will return the ID of the timeout and schedule foo to run in approximately one thousand milliseconds in the future. foo will then get executed exactly once.


Depending on the timer resolution of the JavaScript engine that is running the code, as well as the fact that JavaScript is single threaded and other code that gets executed might block the thread, it is by no means a safe bet that one will get the exact delay that was specified in the setTimeout call.


The function that was passed as the first parameter will get called by the global object, which means that this inside the called function refers to that very object.


function Foo() {

    this.value = 42;

    this.method = function() {

        // this refers to the global object

        console.log(this.value); // will log undefined

    };

    setTimeout(this.method, 500);

}

new Foo();

Note: As setTimeout takes a function object as its first parameter, an often made mistake is to use setTimeout(foo(), 1000), which will use the return value of the call foo and not foo. This is, most of the time, a silent error, since when the function returns undefined setTimeout will not raise any error.

Stacking Calls with setInterval


While setTimeout only runs the function once, setInterval - as the name suggests - will execute the function every X milliseconds, but its use is discouraged.


When code that is being executed blocks the timeout call, setInterval will still issue more calls to the specified function. This can, especially with small intervals, result in function calls stacking up.


function foo(){

    // something that blocks for 1 second

}

setInterval(foo, 100);

In the above code, foo will get called once and will then block for one second.


While foo blocks the code, setInterval will still schedule further calls to it. Now, when foo has finished, there will already be ten further calls to it waiting for execution.


Dealing with Possible Blocking Code


The easiest solution, as well as most controllable solution, is to use setTimeout within the function itself.


function foo(){

    // something that blocks for 1 second

    setTimeout(foo, 100);

}

foo();

Not only does this encapsulate the setTimeout call, but it also prevents the stacking of calls and it gives additional control. foo itself can now decide whether it wants to run again or not.


Manually Clearing Timeouts


Clearing timeouts and intervals works by passing the respective ID to clearTimeout or clearInterval, depending which set function was used in the first place.


var id = setTimeout(foo, 1000);

clearTimeout(id);

Clearing all timeouts


Because there is no built-in method for clearing all timeouts and/or intervals, it is necessary to use brute force in order to achieve this functionality.


// clear "all" timeouts

for(var i = 1; i < 1000; i++) {

    clearTimeout(i);

}

There might still be timeouts that are unaffected by this arbitrary number; therefore, is is instead recommended to keep track of all the timeout IDs, so they can be cleared specifically.


Hidden use of eval


setTimeout and setInterval can also take a string as their first parameter. This feature should never be used because it internally makes use of eval.


Note: Since the timeout functions are not specified by the ECMAScript standard, the exact workings when a string is passed to them might differ in various JavaScript implementations. For example, Microsoft's JScript makes use of the Function constructor in place of eval.

function foo() {

    // will get called

}


function bar() {

    function foo() {

        // never gets called

    }

    setTimeout('foo()', 1000);

}

bar();

Since eval is not getting called directly in this case, the string passed to setTimeout will get executed in the global scope; thus, it will not use the local variable foo from the scope of bar.


It is further recommended to not use a string for passing arguments to the function that will get called by either of the timeout functions.


function foo(a, b, c) {}


// NEVER use this

setTimeout('foo(1,2, 3)', 1000)


// Instead use an anonymous function

setTimeout(function() {

    foo(a, b, c);

}, 1000)

Note: While it is also possible to use the syntax setTimeout(foo, 1000, a, b, c), it is not recommended, as its use may lead to subtle errors when used with methods.

In Conclusion


Never should a string be used as the parameter of setTimeout or setInterval. It is a clear sign of really bad code, when arguments need to be supplied to the function that gets called. An anonymous function should be passed that then takes care of the actual call.


Furthermore, the use of setInterval should be avoided because its scheduler is not blocked by executing JavaScript.


:

[펌] CSS Fonts Module Level3

ITWeb/개발일반 2011. 12. 21. 17:07

-webkit-text-size-adjust: none;

-moz-text-size-adjust: none;

-ms-text-size-adjust: none;


원본링크 : 
http://www.w3.org/TR/css3-fonts/ 

Property index

PropertyValuesInitialApplies toInh.PercentagesMedia
font[ [ <‘font-style’> || <font-variant-css21> || <‘font-weight’> ]? <‘font-size’> [ / <‘line-height’> ]? <‘font-family’> ] | caption | icon | menu | message-box | small-caption | status-bar | inherit see individual properties all elements yes see individual properties visual
font-family[[ <family-name> | <generic-family> ] [, <family-name> | <generic-family>]* ] | inherit depends on user agent all elements yes N/A visual
font-feature-settingsnormal | <feature-tag-value> [, <feature-tag-value>]* normal all elements yes N/A visual
font-kerningauto | normal | none auto all elements yes N/A visual
font-language-overridenormal | inherit | <string> normal all elements yes N/A visual
font-size<absolute-size> | <relative-size> | <length> | <percentage> | inherit medium all elements yes refer to parent element's font size visual
font-size-adjust<number> | none | inherit none all elements yes N/A visual
font-stretchnormal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded | inherit normal all elements yes N/A visual
font-stylenormal | italic | oblique | inherit normal all elements yes N/A visual
font-synthesisnone | [ weight || style ] weight style all elements yes N/A visual
font-variantnormal | inherit | [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> || stylistic(<feature-value-name>) || historical-forms || styleset(<feature-value-name> [, <feature-value-name>]*) || character-variant(<feature-value-name> [,<feature-value-name>]*) || swash(<feature-value-name>) || ornaments(<feature-value-name>) || annotation(<feature-value-name>) || ruby || <caps-value> || <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || slashed-zero || <east-asian-variant-values> || <east-asian-width-values> ] normal all elements yes N/A visual
font-variant-alternatesnormal | inherit | [ <contextual-alt-values> || stylistic(<feature-value-name>) || historical-forms || styleset(<feature-value-name> [, <feature-value-name>]*) || character-variant(<feature-value-name> [,<feature-value-name>;]*) || swash(<feature-value-name>) || ornaments(<feature-value-name>) || annotation(<feature-value-name>) || ruby ] normal all elements yes N/A visual
font-variant-capsnormal | inherit | <caps-value> normal all elements yes N/A visual
font-variant-east-asiannormal | inherit | [ <east-asian-variant-values> || <east-asian-width-values> ] normal all elements yes N/A visual
font-variant-ligaturesnormal | inherit | [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> ] normal all elements yes N/A visual
font-variant-numericnormal | inherit | [ <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || slashed-zero ] normal all elements yes N/A visual
font-variant-positionnormal | sub | super | ordinal normal all elements yes N/A visual
font-weightnormal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit normal all elements yes N/A visua




:

JavaScript OOP - 다중객체 생성 맛보기

ITWeb/개발일반 2011. 12. 16. 16:22
Javascript 로 Class 를 구현해서 사용하다 보면 상속이랑 다중생성을 자주 사용하게 됩니다.
그래서 다중객체 생성하는 방법에 대한 두 가지 접근 방법에 대해서 예제 코드를 작성해 보았습니다.

[Object 생성을 위한 Brace({}) 사용]

// Class 다중 생성 및 Linking 구조

var ClassSuper = {};

var ClassSuperWrap = function () {};

var classObj1, classObj2;


ClassSuper.key = 'KEY';


ClassSuperWrap.prototype = ClassSuper;


classObj1 = new ClassSuperWrap();

classObj2 = new ClassSuperWrap();


classObj1.prototype = ClassSuper;

classObj2.prototype = ClassSuper;


console.log(classObj1.key);

console.log(classObj2.key);


classObj1.key = 'KEY1 Changed';


console.log(classObj1.key);

console.log(classObj2.key);


classObj2.key = 'KEY2 Changed';


console.log(classObj1.key);

console.log(classObj2.key);


delete classObj1.key;


console.log(classObj1.key);

console.log(classObj2.key);



[Function 을 이용한 방법]

// Class 다중 생성 및 Linking 구조

var ClassSuper = function () {};

var classObj1, classObj2;


ClassSuper.prototype.key = 'KEY';


classObj1 = new ClassSuper();

classObj2 = new ClassSuper();


console.log(classObj1.key);

console.log(classObj2.key);


classObj1.key = 'KEY1 Changed';


console.log(classObj1.key);

console.log(classObj2.key);


classObj2.key = 'KEY2 Changed';


console.log(classObj1.key);

console.log(classObj2.key);


delete classObj1.key;


console.log(classObj1.key);

console.log(classObj2.key);



※ 눈치 빠르신 분들은 아시겠지만 fake 입니다.. ^^; (그냥 다른 방법 이라고 보시는게 맞겠죠..)
누가 번거롭게 첫번째 방식으로 하겠냐고 하실 수도 있으나 할 수 있습니다.. 
뭐.. 코딩 하는 사람 맘 아니겠습니까!! 

그럼 크롬에서 찍힌 로그를 확인해 볼까요.
아래 결과 첨부 합니다.

// 첫번째 로그 결과

KEY
instanceof.html:29KEY1 Changed
instanceof.html:34KEY1 Changed
instanceof.html:35KEY2 Changed
instanceof.html:40KEY2 Changed

// 두번째 로그 결과
KEY
instanceof.html:56KEY1 Changed
instanceof.html:61KEY1 Changed
instanceof.html:62KEY2 Changed
instanceof.html:67KEY2 Changed



[참고링크]
-  http://www.danielbaulig.de/now-thats-class-its-an-object-prototypal-inheritance-in-javascript/

[원문 Scrap]

Now that’s class, it’s an object! – Prototypal Inheritance in JavaScript

JavaScript is an object oriented programming language like most programming languages nowadays. However, unlike most programming languages it does not use the concept of classes. Instead from classes objects inherit directly from other objects, their so called prototypes. If you’re familiar with a traditional object oriented programming language like Java or C++ and / or if you already have fundamental knowledge of JavaScript, then this article is directed at you.

In the beginning there was Object.prototype

To fully understand how object oriented JavaScript works, you will have to abandon any concept of object orientation you know. Yes, forget it. You won’t need it, and I will teach you anew. JavaScript object orientation works quite differently than in most other languages, you will only get confused about what is going on in JavaScript if you try to apply your old concepts and ideas of object orientation to JavaScript. So forget about it. Done? Good. So now that you forgot, let me introduce you to the object:

{};

This is what we call an object literal in JavaScript. It is the most basic form of an object and works similar to array literals in other languages. You may have noticed that there is no reference to a class. – Didn’t I tell you to forget everything you know about other object oriented languages?! That certainly includes classes! – Whatever, there are no classes in JavaScript. Objects in JavaScript do not inherit from classes, but from other objects, their so called prototypes. If an object does not have an explicit prototype, like in the case of an object literal, it will inherit from a special built-in object, which is accessible throughObject.prototype.

Objects in JavaScript are dynamic hashmaps. A hashmap is a set of key/value pairs. For each value in an object, like an attribute or a method, there is a key, that identifies that value and allows access to it. You can access an object member with the dot operator followed by the literal key (dot notation) or by enclosing the key in string form in index brackets (bracket notation):

o.member; // dot notation
o['member']; // bracket notation

If you think the bracket notation looks a lot like accessing arrays then this is because arrays in JavaScript basically are nothing but objects with integer attribute keys.

Because objects are dynamic, you can add and remove any member at runtime, even after the object was created. You add a member by simply assigning to it and your remove it by using the delete operator on the member:

var o = {}; // create an empty object
o.member = 'value'; // create the attribute "member" by assigning 
                    // value "value" to it
o.method = function() { // create the method "method" by assigning 
                        // an anonymous function to it
  return this.member;
};
o.method(); // returns "value"
delete o.member; // delete the member "member"
o.method(); // returns undefined

Also, when you create an object using an object literal, you can add an arbitrary amount of attributes and methods to it, by listing key/value pairs, separated by comma and split by a colon:

var printer = {
  message: 'Hello, World!',
  count: 0,
  printMessage: function () {
    console.log(this.message);
    return ++this.count;
  }
};

Defining objects this way is very cool and singlehandedly eliminates the need for the singleton pattern, but it can be very tyring if you require multiple objects with the same attributes over and over again. What you want is a method that makes creating similar objects easy. Luckily JavaScript provides such a method.

Crock’ the Constructor

For easier object instantiation JavaScript provides the new keyword. Calling any function with a prepended new keyword will turn this function into a constructor function. Constructor functions basically work like normal functions with the difference that their this keyword will be bound to a newly created object and they will automatically return this newly created object if there is no explicit return statement. Although you could turn any arbitrary function into a constructor function using the new keyword, this does not make much sense in most cases. Usually you build special functions that will be used exclusively as constructor functions. By convention those functions start with a capital letter.

function Printer() {
  this.message = 'Hello, World!';
  this.count = 0;
  this.printMessage = function () {
    console.log(this.message);
    return ++this.count;
  };
}
var printer = new Printer();
printer.printMessage(); // prints "Hello, World!" to console
printer.count; // returns 1

What this constructor function does is implicitly create a new object and bind it to the functions this identifier. Then the function body is executed, which will create a messageattribute, a count attribute and a printMessage method on the new object. Since there is no explicit return statement, the new object, augmented with it’s new members, will be returned implicitly.
Note though, that this construct is not a class. There are no classes is JavaScript. This is simply a function which adds members to a new object. The style of calling it might look a bit like a class constructor in other languages, but I told you: forget about what other languages do.

But there is a problem with this example. Not with constructor functions in general, but because we used a very naive variant. Each time we call this constructor function it will create a new object with a message and a count attribute. Up until here this is fine, but it will also create a new anonymous function and add it as a method to the object each timeyou call the constructor function. This means, that each object will get it’s own, separate function, which will require it’s own memory, it’s own compilation time, etc. While this >might> be what you want, it’s most likely not. What you actually want are several objects that all use the exact same function. Prototypes are what enables this in a very easy way.

Honor, guide me!

Prototypes are JavaScript’s way of inheritance. Each object in JavaScript has exactly one prototype. There are several ways to declare a newly created object’s prototype (and some implementations even allow the prototype to be changed after object instantiation), but let us look at how exactly prototypes work first.

When you read a member from an object, JavaScript will look for this member on the object itself first. If JavaScript cannot find the member on the object, it will go to the objects prototype and see if it can find the member there. If it fails again it will proceed to move along the prototype chain until it either finds the member on one of the prototype objects, in which case it will return it’s value or has reached the end of the chain without finding the member on any of the objects on the prototype chain. In that case undefined is returned.

If you write an object’s member by assigning to it, JavaScript will always set the objects own member. When assigning a member, JavaScript will never alter any object on the prototype chain. This is possible however, you will only need to do it explicitly. The following code will demonstrate what I just explained. Note that p is set as o‘s prototype.

var p = {
    key: 'value',
    method: function () {
      return this.key;
    }
  }, o = Object.create(p); // create an object with p as it's prototype
 
p.key; // returns 'value'
p.method(); // returns 'value'
 
o.key; // returns 'value'
o.method(); // calling a method is a read, returns 'value'
 
o.key = 'other'; // assign as o's own member!
o.key; // returns 'other'
p.key; // returns 'value'
 
o.method() // returns 'other', because the method
           // is evaluated with o bound to this, even
           // though the method actually is on p
 
delete o.key;
o.key; // returns 'value', after deletion the member
       // is no longer found on o, but still on p, when
       // traversing the prototype chain.
 
p.key = 'changed';
o.key; // returns 'changed', the prototype chain is
       // evaluated each time a property is read from.

I just introduced you to the first method of setting an objects prototype:Object.create(prototype);Object.create returns an empty object with it’s prototype set to whatever object you pass in. Object.create can do more, but this is out of scope for this article.

When using an object literal you cannot specify a prototype for your object. The syntax simply doesn’t give you the tools to do so (although this might come in a future ECMAScript version). However, when using the constructor function pattern, you can specifiy the prototype of the created object. This is done by setting the prototype attribute of the constructor function. Whenever the function is called using the new keyword, the returned object will have it’s prototype set to whatever the value of the constructor functions prototype attribute was at the time:

var p = {
  key: 'value',
  method: function() {
    return this.key;
  }
};
function Thing() {
  // do nothing, implicitly return this
}
 
Thing.prototype = p; // make p the prototype of all objects created using Thing
Thing.prototype.constructor = Thing; // this is not required, but makes your 
                                     // objects pass the object.constructor 
                                     // === Thing test like you would expect.
 
var o = new Thing();
 
o.key; // returns 'value'
o.method(); // returns 'value'
 
p.key = 'changed'; // assign to the prototype
o.key; // returns 'changed'
 
o.key = 'other'; // assign o's own attribute
o.key; // retutns 'other'
 
// etc

With this pattern, you can now create an arbitrary amount of Things, which all inherit from p. All those Things share the exact same methods and attributes. Whenever you call a Thingsmethod method, it will call the exact same function p.method (that is as long as you do not explicitly set the Things members to something else). So in comparison to our first try with using the constructor function, we will save memory, compilation time, etc, becausemethod exists only once, on the prototype p.

Busfactor

You now basically know everything you need to know about object oriented JavaScript. The rest is forging this knowledge into practically usable patterns. The following code is a small example how an object oriented system could be created using JavaScript prototypal inheritance. Be aware, that there are multiple patterns to do object orientation in JavaScript. Some embrace the prototypal nature of JavaScript, while others try to mimic what JavaScript people call classical object orientation.

Personally I don’t like classical patterns as much (especially those that try to mimic information hiding and private methods and attributes), since most will make your code slow and clunky. The following pattern is a good balance I think. It is aware of JavaScripts prototypal model, but people coming from a classical model will be able to grasp what it does.

function Vehicle() {
    this.passengers = 0;
}
 
Vehicle.prototype.seats = 0;
 
Vehicle.prototype.board = function() {
  if (this.seats > this.passengers) {
    this.passengers++;
  }
}
 
Vehicle.prototype.deboard = function() {
  if (this.passengers > 0) {
    this.passengers--;
  }
}
 
function Car() {
  Vehicle.apply(this, arguments);
}
 
Car.prototype = new Vehicle();
Car.prototype.constructor = Car;
Car.prototype.seats = 5;
 
function Bus(driver) {
  Vehicle.apply(this, arguments);
  this.driver = driver;
}
 
Bus.prototype = new Vehicle();
Bus.prototype.constructor = Bus;
Bus.prototype.seats = 20;
 
Bus.prototype.board = function (ticket) {
  if (ticket) {
    Vehicle.prototype.board.apply(this, arguments);
  }
}

JavaScript is all about functions and objects. That’s all what’s to it, even in it’s inheritance model. I hope you enjoyed this article. If you have any further questions or would like to comment, please do so below. If you want to learn more about JavaScript come back soon, to learn more about the secrets of closures, scope and functions. You can also subscribe tothe feed, to stay tuned. Or, if you are in a hurry and want some good lecture, you should definitly check out Douglas Crockfords “JavaScript: The Good Parts” (Amazon Affiliate Link).



 
:

HTML5 Notification 맛보기

ITWeb/개발일반 2011. 12. 14. 16:53
[원문]
http://www.html5rocks.com/en/tutorials/notifications/quick/

[번역문]
http://html5korea.co.kr/1993

[Notification Test용 Content Twitter API]
- http://twitter.com/statuses/user_timeline/계정명.json?count=목록수&callback=콜백함수(실행시킬함수명)
- 트위터 API 관련 : https://dev.twitter.com/

[참고사이트]
http://www.chromium.org/developers/design-documents/desktop-notifications/api-specification
http://dev.w3.org/2006/webapi/WebNotifications/publish/Notifications.html


[Notification Interface]

the Notification interface

interface Notification : EventTarget {

  void               show();
  void               cancel();
           attribute Function   onclick;
           attribute Function   onshow;
           attribute Function   onerror;
           attribute Function   onclose;
  void               setReplaceId(in DOMString replaceId);
           attribute DOMString  dir;
};


[Constructor]

Constructing a notification

  Notification Notification(in DOMString iconUrl, in DOMString title, in DOMString body);


[Code Example]

<!DOCTYPE html>

<html>

<head>

<title>HTML5 Notification</title>

<script type="text/javascript">

/*

[Notification Interface]

the Notification interface


interface Notification : EventTarget {


  void               show();

  void               cancel();

           attribute Function   onclick;

           attribute Function   onshow;

           attribute Function   onerror;

           attribute Function   onclose;

  void               setReplaceId(in DOMString replaceId);

           attribute DOMString  dir;

};


[Constructor]

Constructing a notification


  Notification Notification(in DOMString iconUrl, in DOMString title, in DOMString body);



*/


var noti;


/*

json

opt

resource

이미지 나 Content 가능

title

text 등록 가능 하며, HTML 코드 사용 안됨

content

text 등록 가능 하며, HTML 코드 사용 안됨

ondisplay

ondisplay function 등록

onclose

ondisplay function 등록
        .. 추가적인 이벤트 등록을 하고 싶다면 등록해서 사용하면 됩니다.

ex) {opt:'default', resource:'http://.....', title:'제목', content:'내용'}

*/

function createInstanceOfNotification(json) {

if ( window.webkitNotifications.checkPermission() == 0 ) {

switch ( json.opt ) {

case 'default' :

noti = window.webkitNotifications.createNotification(json.resource, json.title, json.content);

break;

case 'html' :

noti = window.webkitNotifications.createHTMLNotification(json.resource);

break;

}

noti.ondisplay = json.ondisplay;

noti.onclose = json.onclose;

noti.show();

} else {

window.webkitNotifications.requestPermission();

}

}


function eventNotificationOnDisplay () {

console.log('ondisplay catch');

for ( var i in arguments ) {

console.log ( i + ' : ' + arguments[i]);

}

}


function eventNotificationOnClose () {

console.log('onclose catch');

}

</script>

</head>

<body style='margin:0px; padding:0px;' topmargin='0px'  leftmargin='0px' marginheight='0px' marginwidth='0px'>

<button onclick='createInstanceOfNotification({opt:"default",resource:"banner1.png",title:"제목을 보여주세요.",content:"내용을 보여주세요.",ondisplay:eventNotificationOnDisplay,onclose:eventNotificationOnClose});'>window.webkitNotifications.createNotification - JSON</button><br>

<button onclick='createInstanceOfNotification({opt:"html",resource:"http://m.naver.com",ondisplay:eventNotificationOnDisplay,onclose:eventNotificationOnClose});'>window.webkitNotifications.createHTMLNotification - JSON</button><br>

</body>

</html>


※ 위 예제 코드에서 사용되는 console 는 크롬 브라우저에서 제공하는 Global Object 입니다. F12 를 눌러서 디버깅시 효과적으로 활용 하시면 매우 좋습니다.
- 관련 동영상 링크 입니다.
http://www.youtube.com/results?search_query=chrome+debug

이제 JSONP 를 이용한 예제 코드를 하나 더 작성해 볼 예정입니다.
JSONP 는 검색해 보시면 많은 내용들이 나옵니다.
그래도 쉽게 이해 할수 있는 article 링크 하나 걸어 봅니다.
http://www.ibm.com/developerworks/kr/library/wa-aj-jsonp1/

JSONP 의 기초개념은 
JSON String + CallBack 함수의 결합만 이해 하면 될 것 같습니다.
Request API 하나에 callback 함수를 지정해서 이걸 <script> 태그에 삽입하여 body 에서 callback 함수를 실행 하도록 하면 끝....



[JSONP 예제]

function jsonReceiver(json) {

    var size = json.length;


    for ( var i=0; i<size; i++ ) {

        console.log(json[i].source + ', ' + json[i].text + ', ' + json[i].user.screen_name);

        createInstanceOfNotification({opt:"default",resource:"",title:"",content:json[i].text});

    }

}


function createScript() {

    var scripts = document.createElement('script');


    scripts.src = 'http://twitter.com/statuses/user_timeline/sophistlv.json?count=4&callback=jsonReceiver';


    document.body.appendChild(scripts);

}
============================================================================================== 

<button onclick='createScript();'>Create Scripts JSONP</button>

※ 추가된 코드 입니다.

역시 모든 구현 예제 코드의 기본은 상단의 원문과 참고사이트의 코드를 기반으로 한 것입니다.
이를 가지고 응용하는 방법은 Biz 요구사항에 맞춰서 구현을 하시면 좋겠죠.. 
- Chrome 에서 테스트 된 것이구요.
- 관련 코드는 html 파일로 해서 서버에 올려 놓고 테스트 한 내용입니다.
- local file 형태로 실행 시키기면 동작 하지 않습니다.
- 동작하지 않는다는건 notification 의 show() 함수 실행 시 dialog 가 뜨지 않는다는 의미 입니다.
:

허접 배너 Viewer 맛보기.

ITWeb/개발일반 2011. 12. 9. 16:07
지난 번 허접 텍스트 sliding 포스팅 후 이미지 돌리는 것도 보여 달라고 해서..ㅡ.ㅡ;
구글링 하면 아주 멋진거 많은데..

뭐.. 후배가 보여 달라면 보여줘야죠.. ㅋ
기교 이런거 하나도 없이 생짜 코드 들어 갑니다.

기본 컨셉은 linked list 를 바탕으로 작성을 했으나 코드를 보시면 전혀 그런 내용은 없습니다.
단순히 배열을 가지고 loop 돌리는게 전부 입니다. ㅡ.ㅡ;;

[구글검색 linkedlist]
http://www.google.co.kr/search?q=javascript+linkedlist

[구현코드]

<!DOCTYPE html>

<html>

<head>

<title>BannerSlider</title>

<script type="text/javascript">

var bannerList = ['banner1.png', 'banner2.png', 'banner3.png', 'banner4.png', 'banner5.png']

var bannerSize = 4;  // 이 숫자 바꾸면 그 크기만큼 돌아 갑니다.

var bannerIndexLast = bannerSize - 1;

var bannerIndexCurrent = 0;

var bannerIndexLeft;

var bannerIndexRight;

var bannerWidth = 320;

var bannerHeight = 48;

var imageList = new Array(bannerSize);

var swapIndex = 'front';


// 이건 잘 아시는 이미지 preload 입니다.
function bannerPreload () {

for ( var i=0; i<bannerSize; i++ ) {

imageList[i] = new Image();

imageList[i].src = bannerList[i];

}

bannerIndexLeft = bannerIndexLast;

bannerIndexRight = 1;

}


// 이름이 view 와 slide 로 되어 있는건 사실 slide 효과를 주기 위해 시작을 한거구요.
// 일단은 효과 빼고 배너 돌리는거 부터 보여 줄라고 이래 되었습니다.

function moveLeft () {

var adView;

var adSlide;

switch ( swapIndex ) {

case 'front' :

adView = document.getElementById('adFront');

adSlide = document.getElementById('adBack');

swapIndex = 'back';

break;

case 'back' :

adView = document.getElementById('adBack');

adSlide = document.getElementById('adFront');

swapIndex = 'front';

break;

}

// 이 부분은 예전에 작성한 DOM Linknig Element 를 이용해서 하면 더 좋겠지만
// 빠르게 보여 주다 보니.. 
// 이전 글 참고 : 
http://jjeong.tistory.com/522 

adSlide.innerHTML = "<img src='"+bannerList[bannerIndexRight]+"' border='0' width='320px' height='48px'>";

leftSlide(adView, adSlide);

}


// 왼쪽 화살표 클릭 했을 때 sliding 될 배너의 위치를 지정하고 돌리기 위한 함수 임돠.

function leftSlide (adViewer, adSlider) {

var temp;

adViewer.style.left = '0px';

adSlider.style.left = '320px';

temp = adViewer.style.zIndex;

adViewer.style.zIndex = adSlider.style.zIndex;

adSlider.style.zIndex = temp;

adSlider.style.left = '0px';

bannerIndexLeftCalc();

}


// linkedilst 를 가장한 배열의 순서를 계산하는 함수 임돠.

function bannerIndexLeftCalc () {

bannerIndexLeft = bannerIndexCurrent;

bannerIndexCurrent = bannerIndexRight;

if ( bannerIndexRight == bannerIndexLast ) {

bannerIndexRight = 0;

} else {

bannerIndexRight++;

}

}


// 여기서 부터는 왼쪽과 반대 입니다.

function moveRight () {

var adView;

var adSlide;

switch ( swapIndex ) {

case 'front' :

adView = document.getElementById('adFront');

adSlide = document.getElementById('adBack');

swapIndex = 'back';

break;

case 'back' :

adView = document.getElementById('adBack');

adSlide = document.getElementById('adFront');

swapIndex = 'front';

break;

}

adSlide.innerHTML = "<img src='"+bannerList[bannerIndexLeft]+"' border='0' width='320px' height='48px'>";

rightSlide(adView, adSlide);

}


function rightSlide (adViewer, adSlider) {

var temp;

adViewer.style.left = '0px';

adSlider.style.left = '-320px';

temp = adViewer.style.zIndex;

adViewer.style.zIndex = adSlider.style.zIndex;

adSlider.style.zIndex = temp;

adSlider.style.left = '0px';

bannerIndexRightCalc();

}


function bannerIndexRightCalc () {

bannerIndexRight = bannerIndexCurrent;

bannerIndexCurrent = bannerIndexLeft;

if ( bannerIndexLeft == 0 ) {

bannerIndexLeft = bannerIndexLast;

} else {

bannerIndexLeft--;

}

}


bannerPreload();


</script>

</head>

<body style='margin:0px; padding:0px;' topmargin='0px'  leftmargin='0px' marginheight='0px' marginwidth='0px'>

<div id='adWrap' style='width:320px; height:48px; line-height:48px; background-color:#000000; valign:center; color:#FFFFFF; text-align:center; z-index:0'>

<div id='arrowLeft' style='position:absolute; width:25px; height:48px; top:0px; left:0px; z-index:99'><a href="javascript:moveLeft();"><img src='arrow_left.jpg' border="0" width="25px" height="48px"></a></div>

<div id='arrowright' style='position:absolute; width:25px; height:48px; top:0px; left:295px; z-index:99'><a href="javascript:moveRight();"><img src='arrow_right.jpg' border="0" width="25px" height="48px"></a></div>

<div id='adFront' style='position:absolute; top:0px; left:0px; width:320px; height:48px; z-index:2'><img src='banner1.png' border="0" width="320px" height="48px"></div>

<div id='adBack' style='position:absolute; top:0px; left:0px; width:320px; height:48px; z-index:1'></div>

</div>

</body>

</html>



※ Code Refactoring 할 내용은 보시는 바와 같이 많이 있습니다. 그건 각자 알아서.. ㅎㅎ
※ 위 코드는 sliding 효과를 전제 하다 보니 <div> 를 두개 사용하게 된거구요.. 아래는 그냥 이미지 대체용 입니다. 코드는 완전 간단해 집니다.

// 그냥 좌우 확인해서.. image list 에 대한 array index 로만 replace 하는 내용 입니다.
// 뭐.. div.innerHTML 이 싫으신 분은 그냥 image.src 로 하셔도 크게 상관 없습니다.
// 이럴려면 <img> 에 id 를 부여하거나 tag name 으로 처리 하시거나요.

function bannerChange(dir) {

switch ( dir ) {

case 'left' :

if ( bannerIndexCurrent >= 4 ) {

bannerIndexCurrent = 0;

} else {

bannerIndexCurrent++;

}

break;

case 'right' :

if ( bannerIndexCurrent <= 0 ) {

bannerIndexCurrent = bannerIndexLast;

} else {

bannerIndexCurrent--;

}

break;

}

adView = document.getElementById('adFront');

adView.innerHTML = "<img src='"+bannerList[bannerIndexCurrent]+"' border='0' width='320px' height='48px'>";

}

<div id='arrowLeft' style='position:absolute; width:25px; height:48px; top:0px; left:0px; z-index:99'><a href="javascript:bannerChange('left');"><img src='arrow_left.jpg' border="0" width="25px" height="48px"></a></div>

<div id='arrowright' style='position:absolute; width:25px; height:48px; top:0px; left:295px; z-index:99'><a href="javascript:bannerChange('right');"><img src='arrow_right.jpg' border="0" width="25px" height="48px"></a></div>


 


 
 
:

정규표현식과 trim 맛보기.

ITWeb/개발일반 2011. 12. 7. 17:50
얼마전에 작성했던 Cookie 맛보기에서 사용된 정규표현식에 대한 질문을 하신 후배분이 있어 맛보기 들어 갑니다. ㅎㅎ

[이전글]
http://jjeong.tistory.com/532

[사용된 정규표현식 코드]

key = key.replace(/^\s+|\s+$/g, "");


[간단설명]
- 그냥 이해하기 쉽게 풀어 쓴것이니 설명에 대해서는 정규표현식을 검색하셔서 공부 하심 됩니다.

/ : 시작과 끝을 의미 합니다.
^ : 문자열의 처음 시작 부분을 의미 합니다. (일치하는 패턴이 문자열의 처음에 있어야 함)
\s : 공백을 의미 합니다. (Whitespace)
+ : 1번 이상 반복을 의미 합니다.
    \s+ : 이렇게 하면 공백이 여러번 나타나는걸 의미 하겠죠.
| : 또는 (or) 을 의미 합니다.
    a|b : a 이거나 b 이거나 라고 보시면 됩니다.
$ : 문자열의 제일 마지막 부분을 의미 합니다. (일치하는 패턴이 문자열의 끝에 있어야 함)
g : 문자열의 전체에서 매칭을 하라는 의미 입니다.

결국 정리 하면,
문자열의 제일 앞부분과 제일 뒷부분에 반복되는 공백을 제거 하라는 의미 입니다. 



[참고내용]
- 한빛미디어에서 퍼 왔습니다.
http://www.hanb.co.kr/network/view.html?bi_id=1653

[메타문자 요약]

다음은 정규 표현식에서 사용 가능한 메타문자를 보여준다.

/ - 정규 표현식을 시작하고 끝낸다.

. - 줄 바꿈 문자를 제외한 임의의 한 문자와 일치한다.

element* - 요소와 0번 이상 일치한다.

element+ - 요소와 1번 이상 일치한다.

element? - 요소와 일치하지 않거나 한 번 일치한다.

[characters] - 대괄호 안에 포함된 한 문자와 일치한다.

[^characters] - 대괄호 안에 포함되어 있지 않은 한 문자와 일치한다.

(regex) - regex를 그룹으로 간주하여 갯수를 세거나, 다음에 오는 *, +, ?에 적용한다.

left|right - left나 right와 일치한다.

l-r - l과 r사이의 문자 범위와 일치한다(대괄호 안에 있을 때만)

^ - 일치하는 패턴이 문자열의 처음에 있어야 함

$ - 일치하는 패턴이 문자열의 끝에 있어야 함

b - 단어의 경계와 일치한다.

B - 단어의 경계가 아닌 문자와 일치한다.

d - 숫자 문자 하나와 일치한다.

D - 숫자 문자가 아닌 문자와 일치한다.

n - 줄 바꿈 문자와 일치한다.

s - 공백 문자와 일치한다.

S - 공백 문자가 아닌 문자와 일치한다.

t - 탭 문자와 일치한다.

w - 단어 문자(a-z, A-Z, 0-9, _)와 일치한다

W - 비단어 문자(a-z, A-Z, 0-9, _이 아닌 문자)와 일치한다

x - x(x가 메타문자이더라도 x를 쓰고자 할 때 유용함)

{n} - 정확히 n번 일치한다.

{n,} - n번이나 그 이상 일치한다.

{min,max} - 최소 min, 최대 max 번 일치한다.



[일반적인 변경자]

정규 표현식에서는 몇 가지 변경자(modifier)를 사용할 수 있다.

/g - "전역" 일치를 활성화. 바꾸기(replace) 기능을 쓸 경우 이 변경자를 쓰면 첫 번째 일치 결과만 바꾸는 것이 아니라 모든 일치 결과를 바꾼다.

/i - 정규 표현식이 대소문자를 구별하지 않음. 따라서 /[a-zA-Z]/ 대신 /[a-z]/i나 [A-Z]/i를 지정하면 된다.

/m - 캐럿(^)과 달러 기호($)가 대상 문자열 안의 줄 바꿈 전과 후와 일치하는 경우, 여러 줄 모드(multi-line mode)를 활성화. 보통 여러 줄 문자열에서 ^는 문자열의 시작과 일치하고, $는 문자열의 끝과 일치한다.


:

text rolling 맛보기 - using javascript.

ITWeb/개발일반 2011. 12. 6. 16:09
text rolling 만들어 달라고 해서 아주 쉽게 만든 코드로 맛보기를 해보겠습니다.

[기능]
- Text Replace : 2개로 replace (swap 아님)
- Text Rolling : 2개만 사용 (응용은 알아서.. ㅎㅎ)
- CSS 는 무식하게 inline style 사용

[사용된 함수]
- window.setInterval
- parseInt
- document.getElementById

[설명]
- textReplace() 는 말 그대로 Text Array1, 2 를 번갈아 가면서 보여 주는 역할
- textRolling() 은 말 그대로 Text Array1, 2가 height 의 1/2 간격으로 윗쪽으로 rolling 되는 역할 (빨간색 참고)

[예제코드]

<!DOCTYPE html>

<html>

<head>

<title>Text Rolling</title>

<script type="text/javascript">
var textArr = ['Text Array1', 'Text Array2']; 

var textIdx = 0;

var timer = null;

var height = 48;


function textReplace() {

var obj = document.getElementById('adWrap');

obj.innerText = textAd[textIdx];

if ( textIdx == 0 ) {

textIdx = 1;

} else {

textIdx = 0;

}

}


function runTextReplace() {

window.setInterval('textReplace();', 2000);

}


function textRolling() {

var obj1 = document.getElementById('textWrap1');

var obj2 = document.getElementById('textWrap2');

if ( parseInt(obj1.style.top) == -(height) ) {

obj1.style.top = (height*2) + 'px';

} else {

obj1.style.top = (parseInt(obj1.style.top) - 1) + 'px';

}

if ( parseInt(obj2.style.top) == -(height*2) ) {

obj2.style.top = height + 'px';

} else {

obj2.style.top = (parseInt(obj2.style.top) - 1) + 'px';

}

}


function runTextRolling () {

timer = window.setInterval('textRolling();', 50);

}


</script>

</head>

<body style='margin:0px; padding:0px;' topmargin='0px'  leftmargin='0px' marginheight='0px' marginwidth='0px'>

<div id='textWrap' style='width:320px; height:48px; line-height:48px; background-color:#000000; valign:center; color:#FFFFFF; text-align:center'>

</div>

<button onclick='runTextReplace();'>Text Replace Run</button>

<br>

<div id='boxWrap' style='width:320px; height:48px; line-height:48px; background-color:red; valign:center; color:#FFFFFF; text-align:center'>

<div id='textWrap1' style='position:relative; top:0px; left:0px; width:320px; height:48px; line-height:48px; background-color:#000000; valign:center; color:#FFFFFF; text-align:center'>

Text Array1

</div>

<div id='textWrap2' style='position:relative; top:24px; left:0px; width:320px; height:48px; line-height:48px; background-color:#000000; valign:center; color:#FFFFFF; text-align:center'>

Text Array2

</div>

</div>

<br><br><br><br>

<button onclick='runTextRolling();'>Text Rolling Run</button>

</body>

</html>



[지정 시간 동안 정지후 롤링]
- textRolling 함수에 아래 코드가 추가 되면 됩니다.

function textRolling() {

var obj1 = document.getElementById('textWrap1');

var obj2 = document.getElementById('textWrap2');

if ( parseInt(obj1.style.top) == -(height) ) {

obj1.style.top = (height*2) + 'px';

} else {

obj1.style.top = (parseInt(obj1.style.top) - 1) + 'px';

}

if ( parseInt(obj2.style.top) == -(height*2) ) {

obj2.style.top = height + 'px';

} else {

obj2.style.top = (parseInt(obj2.style.top) - 1) + 'px';

}

if ( parseInt(obj1.style.top) == 0 || parseInt(obj2.style.top) == -(height) ) {

window.clearInterval(timer);

window.setTimeout('runTextRolling();', 2000);

}

}


[간격 없이 Rolling 시키기]
- 위 코드의 예제는 특정 간격 만큼의 차이를 두고 rolling 시키는 예제 이고 아래는 간격 없이 바로 붙어서 동작함. 

function textRolling() {

var obj1 = document.getElementById('adWrap1');

var obj2 = document.getElementById('adWrap2');

obj1.style.top = (parseInt(obj1.style.top) - 1) + 'px';

obj2.style.top = (parseInt(obj2.style.top) - 1) + 'px';

if ( parseInt(obj1.style.top) == 0 || parseInt(obj2.style.top) == -(height) ) {

window.clearInterval(timer);

window.setTimeout('runTextRolling();', 2000);

if ( parseInt(obj1.style.top) == -(height) ) {

obj1.style.top = height + 'px';

}

if ( parseInt(obj2.style.top) == -(height*2) ) {

obj2.style.top = '0px';

}

}

}


<div id='textWrap2' style='position:relative; top:0px; left:0px; width:320px; height:48px; line-height:48px; background-color:#000000; valign:center; color:#FFFFFF; text-align:center'>

Text Array2

</div> 


※ 잘 아시겠지만 이미지도 <div> 안에 넣으시면 동일한 rolling 효과를 주실 수 있습니다. 
:

JSCoverage 사용 팁.

ITWeb/개발일반 2011. 12. 5. 16:09
오늘 작성한 js code 에 대해서 test code 와 coverage 확인을 위해 jscoverage 를 적용하던 중.. 
아래와 같은 오류가 발생 하였습니다.

[오류내용]

jscoverage-server:/TestCase/indexTest.js:1: SyntaxError: illegal character

jscoverage-server: parse error in file /TestCase/indexTest.js

- 작성한 indexTest.js 파일을 깨끗하게 비운 후 테스트를 해도 동일한 오류가 발생을 하더군요.

[해결방법]

- 처음 시도 방법
- 파일 타입과 인코딩 확인 (UNIX 형식에 UTF-8)
- 계속 SyntaxError 발생 함.
- 개발하는 환경이 Windows  니까.. UNIX 형식에 ANSI 로 변경
- 오류 발생 하지 않음. 

- 실제 서버에 올라갈때는 LINUX 서버라서 UNIX 파일 형식을 사용하는게 맞습니다.
- 다만, 인코딩 방식 때문에 문제가 될거라고는 미쳐 생각을 못했었구요.
- 왜냐면, UTF-8 을 사용했으니까.. 하지만 이런 좁은 사고가 오류 해결하는데 시간을 많이 허비하게 했내요.

※ 총평
- 늘 하는 이야기지만 오류 메시지를 보면 그 안에 답이 있습니다.
-  "SyntaxError: illegal character" 딱 보이시나요?? 대부분 이런 오류는 문법적 오류가 아니라면 encoding 문제입니다.

[이전글 참고]
- JSCoverage 알아보기




 
: