2017年4月18日火曜日

getElementsByClassNameに対するaddEventListener

下記コードがエラーになった。

document.getElementsByClassName( "jpg" ).addEventListener( "click", function(e) {...});

調べたら、forでloopの中で一つ一つaddEventListenerが必要となる

  var jpgBtn = document.getElementsByClassName( "jpg" );
    for (i = 0; i < jpgBtn.length; i++) {
        jpgBtn[i].addEventListener( "click", function(e) {
        console.log(this);
        console.log(e);
        });
    }

2017年4月14日金曜日

SVGのimage要素での外部画像ファイル参照する場合欠落現象

Fabricjsを使って、いくつかの画像と文字を編集し、以下のように全体をsvgのdata uriとして保存し、imgタグに入れた場合、SVGファイルに「xlink:href」で外部画像を参照する部分が欠落してしまった。

var result = fabCanvas.toSVG();
var dataUri = 'data:image/svg+xml,' + encodeURIComponent(result);
$("#result").html("<img src='" + dataUri + "'/>");

そのため、参照ファイルもdata uriに変換することで対応した。

function drawFrame() {
      fabric.Image.fromURL('../img/frame.png', function(oImg) {
        var dataUri = oImg.toDataURL();
        fabCanvas.setBackgroundImage(dataUri,function(oImg) {
    ......
        });
      });
   
      fabric.Image.fromURL('../img/frame_resize_mask.png', function(oImg) {
        var dataUri = oImg.toDataURL();
        fabCanvas.setOverlayImage(dataUri);
      });
}

参考:http://fingaholic.github.io/posts/2012-09-10-svg.html

2017年4月6日木曜日

jQuery TOOLS使用時ajax POSTうまく機能しない

overlayなど簡単に実現できるjQuery TOOLSライブラリを入れる場合、jqueryそのものが勝手に入れてくれる。なぜか、以前うまく機能していたコードがエラーになって、データをサーバーに転送されなくなった

$.ajax({
          method: "POST",
          url: '/Projects/ajaxCall',
          data: { "base64image" : base64image, "projectName" : projectName },
          success: function (msg) {
              alert("デザインが保存されました。");
              console.log("OK");
          },
          error: function (response, desc, exception) {
              console.log("NG");
          }
      });

そして、ajaxで"POST"を指定することではなく、直接にpost methodを使うことで解決した。原因はわからないが、jQuery TOOLSライブラリのせいだと思う

$.post(
        '/Projects/ajaxCall',
        {
          "base64image" : base64image,
          "projectName" : projectName
        },
        function(data){
          alert("デザインが保存されました。");
          console.log("OK");
        });

2017年4月4日火曜日

Speaking JavaScript -- Statements Expressions Functions

ネットで公開している本(http://speakingjs.com/)を見つかった。ものすごく良いみたい、ここで重要なところをメモする

In other languages, you learn language features. In JavaScript, you often learn patterns instead.

Statements Versus Expressions

Statements “do things.” A program is a sequence of statements.
文,是"做事"
Expressions produce values. They are function arguments, the right side of an assignment, etc.
式,"产生值",在赋值的右边

Finally, wherever JavaScript expects a statement, you can also use an expression; for example:在需要文之处,总可以使用"式;"
foo(7, 1);
The whole line is a statement (a so-called expression statement), but the function call foo(7, 1) is an expression.整个line是文,但foo(7, 1)是式

Using ambiguous expressions as statements

Two kinds of expressions look like statements—they are ambiguous with regard to their syntactic category:
  • Object literals (expressions) look like blocks (statements):
    {
        foo: bar(3, 5)
    }
    The preceding construct is either an object literal (details: Object Literals) or a block followed by the label foo:, followed by the function call bar(3, 5).
  • Named function expressions look like function declarations (statements):
    function foo() { }
    The preceding construct is either a named function expression or a function declaration. The former produces a function, the latter creates a variable and assigns a function to it (details on both kinds of function definition: Defining Functions).
In order to prevent ambiguity during parsing, JavaScript does not let you use object literals and function expressions as statements. That is, expression statements must not start with:
  • A curly brace
  • The keyword function
If an expression starts with either of those tokens, it can only appear in an expression context. You can comply with that requirement by, for example, putting parentheses around the expression. Next, we’ll look at two examples where that is necessary.

Evaluating an object literal via eval()

eval parses its argument in statement context. You have to put parentheses around an object literal if you want eval to return an object:
> eval('{ foo: 123 }')
123
> eval('({ foo: 123 })')
{ foo: 123 }

Immediately invoking a function expression

The following code is an immediately invoked function expression (IIFE), a function whose body is executed right away (you’ll learn what IIFEs are used for in Introducing a New Scope via an IIFE):
> (function () { return 'abc' }())
'abc'
If you omit the parentheses, you get a syntax error, because JavaScript sees a function declaration, which can’t be anonymous:
> function () { return 'abc' }()
SyntaxError: function statement requires a name
If you add a name, you also get a syntax error, because function declarations can’t be immediately invoked:
> function foo() { return 'abc' }()
SyntaxError: Unexpected token )
Whatever follows a function declaration must be a legal statement and ()isn’t.

Functions

One way of defining a function is via a function declaration:定义函数一种方法是函数宣言
function add(param1, param2) {
    return param1 + param2;
}
The preceding code defines a function, add, that has two parameters, param1and param2, and returns the sum of both parameters. This is how you call that function:
> add(6, 1)
7
> add('a', 'b')
'ab'
Another way of defining add() is by assigning a function expression to a variable add:另一种是函数式
var add = function (param1, param2) {
    return param1 + param2;
};
A function expression produces a value and can thus be used to directly pass functions as arguments to other functions:函数式产生值,可以直接传递给另一个函数作为参数
someOtherFunction(function (p1, p2) { ... });

Variables Are Function-Scoped

The scope of a variable is always the complete function (as opposed to the current block). For example:变量的范围总是整个函数
function foo() {
    var x = -512;
    if (x < 0) {  // (1)
        var tmp = -x;
        ...
    }
    console.log(tmp);  // 512
}
We can see that the variable tmp is not restricted to the block starting in line (1); it exists until the end of the function.

Closures

Each function stays connected to the variables of the functions that surround it, even after it leaves the scope in which it was created. For example:每个函数与包围其函数的变量有关联,即使离开了创建该函数的范围(环境)
function createIncrementor(start) {
    return function () {  // (1)
        start++;
        return start;
    }
}
The function starting in line (1) leaves the context in which it was created, but stays connected to a live version of start:
> var inc = createIncrementor(5); //inc成为一个函数,不需要参数。start为5
> inc()
6
> inc()
7
> inc() //start为5一直被inc所记忆
8
closure is a function plus the connection to the variables of its surrounding scopes. Thus, what createIncrementor() returns is a closure.

The IIFE Pattern: Introducing a New Scope

Sometimes you want to introduce a new variable scope—for example, to prevent a variable from becoming global. In JavaScript, you can’t use a block to do so; you must use a function. But there is a pattern for using a function in a block-like manner. It is called IIFE (immediately invoked function expression, pronounced “iffy”):在JS中不能通过block去限制变量范围,但可以使用即时调用函数来模仿block-like
(function () {  // open IIFE
    var tmp = ...;  // not a global variable
}());  // close IIFE
Be sure to type the preceding example exactly as shown (apart from the comments). An IIFE is a function expression that is called immediately after you define it. Inside the function, a new scope exists, preventing tmp from becoming global.

IIFE use case: inadvertent sharing via closures

Closures keep their connections to outer variables, which is sometimes not what you want: result[1]是函数function () { return i },这时i已经变成了5,这个i类似全局变量
var result = [];
for (var i=0; i < 5; i++) {
    result.push(function () { return i });  // (1)
}
console.log(result[1]()); // 5 (not 1)
console.log(result[3]()); // 5 (not 3)
The value returned in line (1) is always the current value of i, not the value it had when the function was created. After the loop is finished, i has the value 5, which is why all functions in the array return that value. If you want the function in line (1) to receive a snapshot of the current value of i, you can use an IIFE: 通过即时调用函数,i2只在(1)范围内有效,被里面的函数关联上,保存在Closure中
for (var i=0; i < 5; i++) {
    (function () { // (1)
        var i2 = i; // copy current i
        result.push(function () { return i2 });
    }());
}