<commit_before>/*
 * XDSMjs
 * Copyright 2016 Rémi Lafage
 */

const WIDTH = 1000;
const HEIGHT = 500;
const X_ORIG = 50;
const Y_ORIG = 20;
const PADDING = 20;
const CELL_W = 200;
const CELL_H = 75;
const UID = "_U_";
const PLAINTEXT_SEP = "_";
const MULTI_TYPE = "_multi";
const MULTI_OFFSET = 3;

function Node(id, name, type) {
    if (typeof(name)==='undefined') type = id;
    if (typeof(type)==='undefined') type = 'analysis';
    this.id   = id;
    this.name = name;
    this.isMulti = (type.search(/_multi$/)>=0);
    this.type = this.isMulti?type.substr(0,type.length-MULTI_TYPE.length):type;
}

function Edge(from, to, name, row, col, isMulti) {
    this.id = from+"-"+to;
    this.name = name;
    this.row = row;
    this.col = col;
    this.iotype = row<col?"in":"out";
    this.io = {from_u: (from==UID), to_u: (to==UID)};
    this.isMulti = isMulti;
}
Edge.prototype.isIO = function() {return this.io.from_u || this.io.to_u;};

function Cell(x, y, width, height) {
    this.x = x;
    this.y = y;
    this.width  = width;
    this.height = height;
}

function Graph(mdo) {
    this.nodes = [new Node(UID, UID, "user")];
    this.edges = [];
    this.chains = [];

    mdo.nodes.forEach(function(item) {
        this.nodes.push(new Node(item.id, item.name, item.type));
    }, this);

    mdo.edges.forEach(function(item){
        var ids = this.nodes.map(function(elt) {return elt.id;});
        var idA = ids.indexOf(item.from);
        var idB = ids.indexOf(item.to);
        //console.log("Edge "+item.from+"-"+item.to, item.name, idA, idB);
        //console.log(item.from, item.to, this.nodes[idB]);
        var isMulti = this.nodes[idA].isMulti || this.nodes[idB].isMulti;
        this.edges.push(new Edge(item.from, item.to, item.name, idA, idB, isMulti));
    }, this);

    mdo.chains.forEach(function(chain, i) {
        if (chain.length < 2) {
            console.log("Bad process chain ("+chain.length+"elt)");
        } else {
            this.chains.push([]);
            chain.forEach(function(item, j) {
                if (j!==0) {
                    var ids = this.nodes.map(function(elt) {return elt.id;});
                    var idA = ids.indexOf(chain[j-1]);
                    var idB = ids.indexOf(chain[j]);
                    this.chains[i].push([idA, idB]);
                }
            }, this);
        }
    }, this);
}

d3.json("xdsm.json", function(error, mdo) {
    if (error) throw error;
    var graph = new Graph(mdo);
    //console.log(graph);
    //var nolatex = false;
    var nolatex = true;
    xdsm(graph, nolatex);
});

function xdsm(graph, nolatex) {
    var svg = d3.select(".xdsm").append("svg")
                .attr("width", WIDTH)
                .attr("height", HEIGHT)
                .attr("id", "main");
    var grid  = [];

    // kind: node || edge
    function createTextGroup(kind) {
        return svg.selectAll("."+kind)
                        .data(graph[kind+"s"])
                      .enter().append("g")
                        .attr("class", function (d, i) {
                            var klass = kind==="node"?d.type:"dataInter";
                            if (klass==="dataInter" && d.isIO()) { klass = "dataIO";}
                            return kind+" "+klass; })
                        .each(function(d, i) {
                            var that = d3.select(this);
                            if (nolatex) {
                                that.append("text")
                                   .text(function(d) { return d.name; })
                                   .attr("class", "plaintext");
                            } else if (d.name[0] === PLAINTEXT_SEP && d.name[d.name.length-1] === PLAINTEXT_SEP) {
                                that.append("text")
                                   .text(function(d) { return d.name.substr(1, d.name.length-2); })
                                   .attr("class", "plaintext");
                            } else {
                                that.append("foreignObject")
                                   .text(function(d) { return "$"+d.name+"$"; });
                            }
                        });
    }

    var edges = createTextGroup("edge");
    var nodes = createTextGroup("node");

    MathJax.Hub.Register.StartupHook("End Typeset", function () {

        // Workflow
        svg.selectAll(".workflow")
            .data(graph.chains)
          .enter().insert("g", ":first-child")
            .attr("class", "workflow")
            .selectAll("polyline")
            .data(function (d) { return d; })
          .enter().insert("polyline", ":first-child")
            .attr("points", function (d, i) {
                var i1 = d[0]<d[1]?d[1]:d[0];
                var i2 = d[0]<d[1]?d[0]:d[1];
                var w = CELL_W*(i1-i2);
                var h = CELL_H*(i1-i2);
                var points = [];
                if (d[0]<d[1]) {
                    if (d[0]!=0) { points.push((-w)+",0"); }
                    points.push("0,0");
                    if (d[1]!=0) { points.push("0,"+h); }
                } else {
                    if (d[0]!=0) { points.push(w+",0"); }
                    points.push("0,0");
                    if (d[1]!=0) { points.push("0,"+(-h)); }
                }
                return points.join(" ");
        })
        .attr("transform", function(d) {
                     var i1 = d[0]<d[1]?d[1]:d[0];
                     var i2 = d[0]<d[1]?d[0]:d[1];
                     if (d[0]<d[1]) {
                        var w = CELL_W*i1+X_ORIG;
                        var h = CELL_H*i2+Y_ORIG;
                     } else {
                        var w = CELL_W*i2+X_ORIG;
                        var h = CELL_H*i1+Y_ORIG;
                     }
                     return "translate("+ (X_ORIG+w) +"," + (Y_ORIG+h) + ")";
         });

        function layoutText(items) {
            items.each(function(d, i) {
                var item = d3.select(this);
                if (grid[i]===undefined) {
                    grid[i] = new Array(items.length);
                }
                item.select("foreignObject svg")
                    .each(function(d, j) {
                        var that = d3.select(this);
                        var data = item.data()[0];
                        var m = (data.row===undefined)?i:data.row;
                        var n = (data.col===undefined)?i:data.col;
                        grid[m][n] = new Cell(-that[0][j].width.baseVal.value/2, -that[0][j].height.baseVal.value/2,
                                               that[0][j].width.baseVal.value, that[0][j].height.baseVal.value);

                        var foreign = item.select("foreignObject");
                        foreign.attr("x", function () { return grid[m][n].x; })
                               .attr("y", function () { return grid[m][n].y; })
                               .attr("width", function () { return grid[m][n].width; })
                               .attr("height", function () { return grid[m][n].height+5; });  // +5 adjustment for Firefox
                    });

                item.select(".plaintext")
                    .each(function(d, j)  {
                        var that = d3.select(this);
                        var data = item.data()[0];
                        var m = (data.row===undefined)?i:data.row;
                        var n = (data.col===undefined)?i:data.col;
                        //console.log(that);
                        grid[m][n] = new Cell(-that[0][j].getBBox().width/2, that[0][j].getBBox().height/3,
                                               that[0][j].getBBox().width, that[0][j].getBBox().height);
                        that.attr("x", function () { return grid[m][n].x; })
                            .attr("y", function () { return grid[m][n].y; })
                            .attr("width", function () { return grid[m][n].width; })
                            .attr("height", function () { return grid[m][n].height; });
                    });
           });

            items.attr("transform", function(d, i) {
                                var m = (d.col===undefined)?i:d.col;
                                var n = (d.row===undefined)?i:d.row;
                                var w = CELL_W*m+X_ORIG;
                                var h = CELL_H*n+Y_ORIG;
                                return "translate("+ (X_ORIG+w) +"," + (Y_ORIG+h) + ")";
                           });
        }

        // layout text
        layoutText(nodes);
        layoutText(edges);

        // rectangles for nodes
        function customRect(node, d, i, offset){
            node.insert("rect", ":first-child").attr("x", function () {return grid[i][i].x+offset - PADDING;})
            .attr("y", function () {return -Math.abs(grid[i][i].y) - PADDING - offset;})
            .attr("width", function () {return grid[i][i].width + (PADDING*2);})
            .attr("height", function () {return grid[i][i].height + (PADDING*2);})
            .attr("rx", function () {
                var rounded = d.type==='optimization' || d.type==='mda' || d.type==='doe';
                return rounded?(grid[i][i].height + (PADDING*2))/2:0;})
            .attr("ry", function () {
                var rounded = d.type==='optimization' || d.type==='mda' || d.type==='doe';
                return rounded?(grid[i][i].height + (PADDING*2))/2:0;});
        }
        nodes.each(function (d, i) {
            that = d3.select(this);
            that.call(customRect, d, i, 0);
            if (d.isMulti) {
                that.call(customRect, d, i, 1*MULTI_OFFSET);
                that.call(customRect, d, i, 2*MULTI_OFFSET);
            }
        });

        // trapezium for edges
        function customTrapz(edge, d, i, offset) {
            edge.insert("polygon", ":first-child")
            .attr("points", function (d, i) {
               var pad = 10;
               var w = grid[d.row][d.col].width;
               var h = grid[d.row][d.col].height;
               var topleft = (-2*pad+5-w/2+offset)+", "+(-h-offset);
               var topright = (5+w/2+pad+offset)+", "+(-h-offset);
               var botright = (w/2+pad+offset)+", "+(pad+h/2-offset);
               var botleft = (-2*pad-w/2+offset)+", "+(pad+h/2-offset);
               var tpz = [topleft, topright, botright, botleft].join(" ");
               return tpz; });
        }
        edges.each(function (d, i) {
            that = d3.select(this);
            that.call(customTrapz, d, i, 0);
            if (d.isMulti) {
                that.call(customTrapz, d, i, 1*MULTI_OFFSET);
                that.call(customTrapz, d, i, 2*MULTI_OFFSET);
            }
        });

        // Dataflow
        var dataflow = svg.insert("g", ":first-child")
            .attr("class", "dataflow");

        edges.each(function (d, i) {
            dataflow.insert("polyline", ":first-child")
                .attr("points", function () {
                    //console.log(d);
                    var i1 = (d.iotype === "in")?d.col:d.row;
                    var i2 = (d.iotype === "in")?d.row:d.col;
                    var w = CELL_W*(i1-i2);
                    var h = CELL_H*(i1-i2);
                    points = [];
                    if (d.iotype === "in") {
                        if (!d.io.from_u) { points.push((-w)+",0"); }
                        points.push("0,0");
                        if (!d.io.to_u) { points.push("0,"+h); }
                    } else {
                        if (!d.io.from_u) { points.push(w+",0"); }
                        points.push("0,0");
                        if (!d.io.to_u) { points.push("0,"+(-h)); }
                    }
                    return points.join(" ");
                })
                .attr("transform", function() {
                                var m = (d.col===undefined)?i:d.col;
                                var n = (d.row===undefined)?i:d.row;
                                var w = CELL_W*m+X_ORIG;
                                var h = CELL_H*n+Y_ORIG;
                                return "translate("+ (X_ORIG+w) +"," + (Y_ORIG+h) + ")";
                           });
           });

        // set svg size
        var w = CELL_W*(graph.nodes.length)+PADDING;
        var h = CELL_H*(graph.nodes.length)+PADDING;
        svg.attr("width", w).attr("height", h);

        d3.select("button").on("click", function () {
            computedStyleToInlineStyle(svg[0][0], true);

            var html = d3.select("svg")
                            .attr("title", "xdsm")
                            .attr("version", 1.1)
                            .attr("xmlns", "http://www.w3.org/2000/svg")
                            .node().parentNode.innerHTML;

            var imgsrc = "data:image/svg+xml;base64,"+ btoa(unescape(encodeURIComponent(html)));
            //var img = '';
            //d3.select("#svgdataurl").html(img);

            var canvas = d3.select("canvas")
                            .attr("width", w)
                            .attr("height", h);
            var context = canvas[0][0].getContext("2d");

            var image = new Image;
            image.src = imgsrc;
            image.onload = function() {
                context.drawImage(image, 0, 0);
                var canvasdata = canvas[0][0].toDataURL("image/png");
                var pngimg = '';
                d3.select("#pngdataurl").html(pngimg);
                var a = document.createElement("a");
                a.download = "xdsm.png";
                a.href = canvasdata;
                document.body.appendChild(a);
                a.click();
            };
        });

    });  // Startup Hook
}

function computedStyleToInlineStyle(element, recursive) {
    if (!element) {
      throw new Error("No element specified.");
    }

    if (!(element instanceof Element)) {
      throw new Error("Specified element is not an instance of Element.");
    }

    if (recursive) {
      Array.prototype.forEach.call(element.children, function(child) {
        computedStyleToInlineStyle(child, recursive);
      });
    }

    var computedStyle = getComputedStyle(element, null);
    for (var i = 0; i < computedStyle.length; i++) {
      var property = computedStyle.item(i);
      if (property==="fill"
          || property==="stroke"
          || property==="stroke-width"
          || property==="visibility") {
        var value = computedStyle.getPropertyValue(property);
        element.style[property] = value;
      }
    }
};

<commit_msg>restore latex use as the default<commit_after>/*
 * XDSMjs
 * Copyright 2016 Rémi Lafage
 */

const WIDTH = 1000;
const HEIGHT = 500;
const X_ORIG = 50;
const Y_ORIG = 20;
const PADDING = 20;
const CELL_W = 200;
const CELL_H = 75;
const UID = "_U_";
const PLAINTEXT_SEP = "_";
const MULTI_TYPE = "_multi";
const MULTI_OFFSET = 3;

function Node(id, name, type) {
    if (typeof(name)==='undefined') type = id;
    if (typeof(type)==='undefined') type = 'analysis';
    this.id   = id;
    this.name = name;
    this.isMulti = (type.search(/_multi$/)>=0);
    this.type = this.isMulti?type.substr(0,type.length-MULTI_TYPE.length):type;
}

function Edge(from, to, name, row, col, isMulti) {
    this.id = from+"-"+to;
    this.name = name;
    this.row = row;
    this.col = col;
    this.iotype = row<col?"in":"out";
    this.io = {from_u: (from==UID), to_u: (to==UID)};
    this.isMulti = isMulti;
}
Edge.prototype.isIO = function() {return this.io.from_u || this.io.to_u;};

function Cell(x, y, width, height) {
    this.x = x;
    this.y = y;
    this.width  = width;
    this.height = height;
}

function Graph(mdo) {
    this.nodes = [new Node(UID, UID, "user")];
    this.edges = [];
    this.chains = [];

    mdo.nodes.forEach(function(item) {
        this.nodes.push(new Node(item.id, item.name, item.type));
    }, this);

    mdo.edges.forEach(function(item){
        var ids = this.nodes.map(function(elt) {return elt.id;});
        var idA = ids.indexOf(item.from);
        var idB = ids.indexOf(item.to);
        //console.log("Edge "+item.from+"-"+item.to, item.name, idA, idB);
        //console.log(item.from, item.to, this.nodes[idB]);
        var isMulti = this.nodes[idA].isMulti || this.nodes[idB].isMulti;
        this.edges.push(new Edge(item.from, item.to, item.name, idA, idB, isMulti));
    }, this);

    mdo.chains.forEach(function(chain, i) {
        if (chain.length < 2) {
            console.log("Bad process chain ("+chain.length+"elt)");
        } else {
            this.chains.push([]);
            chain.forEach(function(item, j) {
                if (j!==0) {
                    var ids = this.nodes.map(function(elt) {return elt.id;});
                    var idA = ids.indexOf(chain[j-1]);
                    var idB = ids.indexOf(chain[j]);
                    this.chains[i].push([idA, idB]);
                }
            }, this);
        }
    }, this);
}

d3.json("xdsm.json", function(error, mdo) {
    if (error) throw error;
    var graph = new Graph(mdo);
    //console.log(graph);
    var nolatex = false;
    //var nolatex = true;
    xdsm(graph, nolatex);
});

function xdsm(graph, nolatex) {
    var svg = d3.select(".xdsm").append("svg")
                .attr("width", WIDTH)
                .attr("height", HEIGHT)
                .attr("id", "main");
    var grid  = [];

    // kind: node || edge
    function createTextGroup(kind) {
        return svg.selectAll("."+kind)
                        .data(graph[kind+"s"])
                      .enter().append("g")
                        .attr("class", function (d, i) {
                            var klass = kind==="node"?d.type:"dataInter";
                            if (klass==="dataInter" && d.isIO()) { klass = "dataIO";}
                            return kind+" "+klass; })
                        .each(function(d, i) {
                            var that = d3.select(this);
                            if (nolatex) {
                                that.append("text")
                                   .text(function(d) { return d.name; })
                                   .attr("class", "plaintext");
                            } else if (d.name[0] === PLAINTEXT_SEP && d.name[d.name.length-1] === PLAINTEXT_SEP) {
                                that.append("text")
                                   .text(function(d) { return d.name.substr(1, d.name.length-2); })
                                   .attr("class", "plaintext");
                            } else {
                                that.append("foreignObject")
                                   .text(function(d) { return "$"+d.name+"$"; });
                            }
                        });
    }

    var edges = createTextGroup("edge");
    var nodes = createTextGroup("node");

    MathJax.Hub.Register.StartupHook("End Typeset", function () {

        // Workflow
        svg.selectAll(".workflow")
            .data(graph.chains)
          .enter().insert("g", ":first-child")
            .attr("class", "workflow")
            .selectAll("polyline")
            .data(function (d) { return d; })
          .enter().insert("polyline", ":first-child")
            .attr("points", function (d, i) {
                var i1 = d[0]<d[1]?d[1]:d[0];
                var i2 = d[0]<d[1]?d[0]:d[1];
                var w = CELL_W*(i1-i2);
                var h = CELL_H*(i1-i2);
                var points = [];
                if (d[0]<d[1]) {
                    if (d[0]!=0) { points.push((-w)+",0"); }
                    points.push("0,0");
                    if (d[1]!=0) { points.push("0,"+h); }
                } else {
                    if (d[0]!=0) { points.push(w+",0"); }
                    points.push("0,0");
                    if (d[1]!=0) { points.push("0,"+(-h)); }
                }
                return points.join(" ");
        })
        .attr("transform", function(d) {
                     var i1 = d[0]<d[1]?d[1]:d[0];
                     var i2 = d[0]<d[1]?d[0]:d[1];
                     if (d[0]<d[1]) {
                        var w = CELL_W*i1+X_ORIG;
                        var h = CELL_H*i2+Y_ORIG;
                     } else {
                        var w = CELL_W*i2+X_ORIG;
                        var h = CELL_H*i1+Y_ORIG;
                     }
                     return "translate("+ (X_ORIG+w) +"," + (Y_ORIG+h) + ")";
         });

        function layoutText(items) {
            items.each(function(d, i) {
                var item = d3.select(this);
                if (grid[i]===undefined) {
                    grid[i] = new Array(items.length);
                }
                item.select("foreignObject svg")
                    .each(function(d, j) {
                        var that = d3.select(this);
                        var data = item.data()[0];
                        var m = (data.row===undefined)?i:data.row;
                        var n = (data.col===undefined)?i:data.col;
                        grid[m][n] = new Cell(-that[0][j].width.baseVal.value/2, -that[0][j].height.baseVal.value/2,
                                               that[0][j].width.baseVal.value, that[0][j].height.baseVal.value);

                        var foreign = item.select("foreignObject");
                        foreign.attr("x", function () { return grid[m][n].x; })
                               .attr("y", function () { return grid[m][n].y; })
                               .attr("width", function () { return grid[m][n].width; })
                               .attr("height", function () { return grid[m][n].height+5; });  // +5 adjustment for Firefox
                    });

                item.select(".plaintext")
                    .each(function(d, j)  {
                        var that = d3.select(this);
                        var data = item.data()[0];
                        var m = (data.row===undefined)?i:data.row;
                        var n = (data.col===undefined)?i:data.col;
                        //console.log(that);
                        grid[m][n] = new Cell(-that[0][j].getBBox().width/2, that[0][j].getBBox().height/3,
                                               that[0][j].getBBox().width, that[0][j].getBBox().height);
                        that.attr("x", function () { return grid[m][n].x; })
                            .attr("y", function () { return grid[m][n].y; })
                            .attr("width", function () { return grid[m][n].width; })
                            .attr("height", function () { return grid[m][n].height; });
                    });
           });

            items.attr("transform", function(d, i) {
                                var m = (d.col===undefined)?i:d.col;
                                var n = (d.row===undefined)?i:d.row;
                                var w = CELL_W*m+X_ORIG;
                                var h = CELL_H*n+Y_ORIG;
                                return "translate("+ (X_ORIG+w) +"," + (Y_ORIG+h) + ")";
                           });
        }

        // layout text
        layoutText(nodes);
        layoutText(edges);

        // rectangles for nodes
        function customRect(node, d, i, offset){
            node.insert("rect", ":first-child").attr("x", function () {return grid[i][i].x+offset - PADDING;})
            .attr("y", function () {return -Math.abs(grid[i][i].y) - PADDING - offset;})
            .attr("width", function () {return grid[i][i].width + (PADDING*2);})
            .attr("height", function () {return grid[i][i].height + (PADDING*2);})
            .attr("rx", function () {
                var rounded = d.type==='optimization' || d.type==='mda' || d.type==='doe';
                return rounded?(grid[i][i].height + (PADDING*2))/2:0;})
            .attr("ry", function () {
                var rounded = d.type==='optimization' || d.type==='mda' || d.type==='doe';
                return rounded?(grid[i][i].height + (PADDING*2))/2:0;});
        }
        nodes.each(function (d, i) {
            that = d3.select(this);
            that.call(customRect, d, i, 0);
            if (d.isMulti) {
                that.call(customRect, d, i, 1*MULTI_OFFSET);
                that.call(customRect, d, i, 2*MULTI_OFFSET);
            }
        });

        // trapezium for edges
        function customTrapz(edge, d, i, offset) {
            edge.insert("polygon", ":first-child")
            .attr("points", function (d, i) {
               var pad = 10;
               var w = grid[d.row][d.col].width;
               var h = grid[d.row][d.col].height;
               var topleft = (-2*pad+5-w/2+offset)+", "+(-h-offset);
               var topright = (5+w/2+pad+offset)+", "+(-h-offset);
               var botright = (w/2+pad+offset)+", "+(pad+h/2-offset);
               var botleft = (-2*pad-w/2+offset)+", "+(pad+h/2-offset);
               var tpz = [topleft, topright, botright, botleft].join(" ");
               return tpz; });
        }
        edges.each(function (d, i) {
            that = d3.select(this);
            that.call(customTrapz, d, i, 0);
            if (d.isMulti) {
                that.call(customTrapz, d, i, 1*MULTI_OFFSET);
                that.call(customTrapz, d, i, 2*MULTI_OFFSET);
            }
        });

        // Dataflow
        var dataflow = svg.insert("g", ":first-child")
            .attr("class", "dataflow");

        edges.each(function (d, i) {
            dataflow.insert("polyline", ":first-child")
                .attr("points", function () {
                    //console.log(d);
                    var i1 = (d.iotype === "in")?d.col:d.row;
                    var i2 = (d.iotype === "in")?d.row:d.col;
                    var w = CELL_W*(i1-i2);
                    var h = CELL_H*(i1-i2);
                    points = [];
                    if (d.iotype === "in") {
                        if (!d.io.from_u) { points.push((-w)+",0"); }
                        points.push("0,0");
                        if (!d.io.to_u) { points.push("0,"+h); }
                    } else {
                        if (!d.io.from_u) { points.push(w+",0"); }
                        points.push("0,0");
                        if (!d.io.to_u) { points.push("0,"+(-h)); }
                    }
                    return points.join(" ");
                })
                .attr("transform", function() {
                                var m = (d.col===undefined)?i:d.col;
                                var n = (d.row===undefined)?i:d.row;
                                var w = CELL_W*m+X_ORIG;
                                var h = CELL_H*n+Y_ORIG;
                                return "translate("+ (X_ORIG+w) +"," + (Y_ORIG+h) + ")";
                           });
           });

        // set svg size
        var w = CELL_W*(graph.nodes.length)+PADDING;
        var h = CELL_H*(graph.nodes.length)+PADDING;
        svg.attr("width", w).attr("height", h);

        d3.select("button").on("click", function () {
            computedStyleToInlineStyle(svg[0][0], true);

            var html = d3.select("svg")
                            .attr("title", "xdsm")
                            .attr("version", 1.1)
                            .attr("xmlns", "http://www.w3.org/2000/svg")
                            .node().parentNode.innerHTML;

            var imgsrc = "data:image/svg+xml;base64,"+ btoa(unescape(encodeURIComponent(html)));
            //var img = '';
            //d3.select("#svgdataurl").html(img);

            var canvas = d3.select("canvas")
                            .attr("width", w)
                            .attr("height", h);
            var context = canvas[0][0].getContext("2d");

            var image = new Image;
            image.src = imgsrc;
            image.onload = function() {
                context.drawImage(image, 0, 0);
                var canvasdata = canvas[0][0].toDataURL("image/png");
                var pngimg = '';
                d3.select("#pngdataurl").html(pngimg);
                var a = document.createElement("a");
                a.download = "xdsm.png";
                a.href = canvasdata;
                document.body.appendChild(a);
                a.click();
            };
        });

    });  // Startup Hook
}

function computedStyleToInlineStyle(element, recursive) {
    if (!element) {
      throw new Error("No element specified.");
    }

    if (!(element instanceof Element)) {
      throw new Error("Specified element is not an instance of Element.");
    }

    if (recursive) {
      Array.prototype.forEach.call(element.children, function(child) {
        computedStyleToInlineStyle(child, recursive);
      });
    }

    var computedStyle = getComputedStyle(element, null);
    for (var i = 0; i < computedStyle.length; i++) {
      var property = computedStyle.item(i);
      if (property==="fill"
          || property==="stroke"
          || property==="stroke-width"
          || property==="visibility") {
        var value = computedStyle.getPropertyValue(property);
        element.style[property] = value;
      }
    }
};

<|endoftext|>


<commit_before>$(function() {
  window.AudioContext = window.AudioContext || window.webkitAudioContext;
  var ctx = new AudioContext();

  var handleStart = function(event) {
    var zhtext;
    var pinyin;
    var num;
    var anshtml;
    var mp3elmid;
    zhtext = $(event.target).data('zh');
    pinyin = $(event.target).data('pinyin');
    num = $(event.target).data('num');
    if(zhtext) {
      $(event.target).css('border', '2px solid #000');
      anshtml = '';
      if(pinyin) {
        anshtml = anshtml + '<ruby>' + zhtext + '<rt>' + pinyin + '</rt></ruby>';
      } else {
        anshtml = anshtml + zhtext;
      }
      mp3elmid = 'mp3elm_' + num;
      anshtml = anshtml + '
-';
      $(event.target).html(anshtml);
      $(event.target).off('touchstart', handleStart);

      // ----------------------------------------
      // 音声MP3データのダウンロード
      // ----------------------------------------
      var elm = document.getElementById(mp3elmid);
      var mp3 = "/mp3/" + zhtext + ".mp3";
      var xhr = new XMLHttpRequest();

      xhr.open('GET', mp3, true);
      xhr.responseType = "arraybuffer";
      xhr.onload = function () {
        if(xhr.status == 200) {
          $(elm).html('');
          $(elm).click(function() {
            var src = ctx.createBufferSource();
            // オーディオをデコード
            ctx.decodeAudioData(xhr.response, function (buf) {
              src.buffer = buf;
              src.loop = false;
              src.connect(ctx.destination);
              src.start(0);
            });
          });
        }
      };
      xhr.send(null);

      // ----------------------------------------
      // 15秒後に表示を元に戻す
      // ----------------------------------------
      setTimeout(function() {
        $(event.target).html($(event.target).data('jp'));
        $(event.target).css('border', '2px solid #fff');
        $(event.target).on('touchstart', handleStart);
      }, 15000);
    }
  };

  var q = $.url().param().q;
  var wordsjson = "y7words.json";
  if(q)
    wordsjson = q;

  var time1;
  time1 = new Date();
  $.getJSON("json/" + wordsjson + "?" + time1.getTime(), function(words) {
    var i, cnt, template;
    cnt = 0;
    for(i = 0; i < words.length; i++) {
      if(words[i] && words[i][0] && words[i][0]!=='END') {
        cnt = cnt + 1;
        if(words[i][1]) {
          template = '';
          template = template + '
';
          template = template + '
' + words[i][0];
          template = template + '
';
          template = template + '
';
        } else {
          template = '
' + words[i][0] + '
';
        }
        $("main").append(template);
      }
      $("#navbar1").text(cnt);
    }
    $(".word").on('touchstart', handleStart);
    $(".word").on('click', handleStart);
  });
});
<commit_msg>2019-01-09<commit_after>$(function() {
  var handleStart = function(event) {
    var zhtext;
    var pinyin;
    var num;
    var anshtml;
    var mp3elmid;
    zhtext = $(event.target).data('zh');
    pinyin = $(event.target).data('pinyin');
    num = $(event.target).data('num');
    if(zhtext) {
      $(event.target).css('border', '2px solid #000');
      anshtml = '';
      if(pinyin) {
        anshtml = anshtml + '<ruby>' + zhtext + '<rt>' + pinyin + '</rt></ruby>';
      } else {
        anshtml = anshtml + zhtext;
      }
      mp3elmid = 'mp3elm_' + num;
      anshtml = anshtml + '
-';
      $(event.target).html(anshtml);
      $(event.target).off('touchstart', handleStart);

      // ----------------------------------------
      // 音声MP3データのダウンロード
      // ----------------------------------------
      window.AudioContext = window.AudioContext || window.webkitAudioContext;
      var ctx = new AudioContext();
      var elm = document.getElementById(mp3elmid);
      var mp3 = "/mp3/" + zhtext + ".mp3";
      var xhr = new XMLHttpRequest();

      xhr.open('GET', mp3, true);
      xhr.responseType = "arraybuffer";
      xhr.onload = function () {
        if(xhr.status == 200) {
          $(elm).html('');
          $(elm).click(function() {
            var src = ctx.createBufferSource();
            // オーディオをデコード
            ctx.decodeAudioData(xhr.response, function (buf) {
              src.buffer = buf;
              src.loop = false;
              src.connect(ctx.destination);
              src.start(0);
            });
          });
        }
      };
      xhr.send(null);

      // ----------------------------------------
      // 15秒後に表示を元に戻す
      // ----------------------------------------
      setTimeout(function() {
        $(event.target).html($(event.target).data('jp'));
        $(event.target).css('border', '2px solid #fff');
        $(event.target).on('touchstart', handleStart);
      }, 15000);
    }
  };

  var q = $.url().param().q;
  var wordsjson = "y7words.json";
  if(q)
    wordsjson = q;

  var time1;
  time1 = new Date();
  $.getJSON("json/" + wordsjson + "?" + time1.getTime(), function(words) {
    var i, cnt, template;
    cnt = 0;
    for(i = 0; i < words.length; i++) {
      if(words[i] && words[i][0] && words[i][0]!=='END') {
        cnt = cnt + 1;
        if(words[i][1]) {
          template = '';
          template = template + '
';
          template = template + '
' + words[i][0];
          template = template + '
';
          template = template + '
';
        } else {
          template = '
' + words[i][0] + '
';
        }
        $("main").append(template);
      }
      $("#navbar1").text(cnt);
    }
    $(".word").on('touchstart', handleStart);
    $(".word").on('click', handleStart);
  });
});
<|endoftext|>


<commit_before>'use strict'

const facebook = require('./facebook.js'),
      brain = require('./brain/brain.js'),
      senderActions = require('./sender_actions.js')

exports.handle = function(event) {
  let payload = event.postback.payload
  if (brain.messages[payload]) {
    let payloadClone = JSON.parse(JSON.stringify(brain.messages[payload]))
    handlePayload(event, payloadClone)
  }
}

function handlePayload(event, messages) {
  let message = messages.shift()

  if (message !== undefined) {
    sendMessage(event, message, () => {
      handlePayload(event, messages)
    })
  }
}

function sendMessage(event, message, callback) {
  sendTypingOn(event, message, () => {
    if (message.text) {
      sendTextMessage(event, message, callback)
    } else if (message.attachment) {
      sendAttachmentMessage(event, message, callback)
    }
  })
}

function sendTypingOn(event, message, callback) {
  let text = message.text ? message.text : message.attachment.text
  senderActions.typingOn(event.sender.id, () => {
    // According to http://10fastfingers.com/typing-test/english I type 39 words/min :P
    let millisPerWord = (60 * 1000) / 39
    let delay = text.split(' ').length * millisPerWord
    setTimeout(callback, delay)
  })
}

function sendTextMessage(event, message, callback) {
  getMessageText(event, message, (text) => {
    let body = {
      recipient: {
        id: event.sender.id
      },
      message: {
        text: text
      }
    }
    facebook.sendMessage(body, callback)
  })
}

function getMessageText(event, message, callback) {
  if (message.required_user_fields) {
    facebook.getUserInfo(event.sender.id, message.required_user_fields, (user) => {
      for (let user_field of message.required_user_fields) {
        let placeholder = '##' + user_field + '##'
        let replace = new RegExp(placeholder, 'g');
        message.text = message.text.replace(replace, user[user_field])
        callback(message.text)
      }
    })
  } else {
    callback(message.text)
  }
}

function sendAttachmentMessage(event, message, callback) {
  let body = {
    recipient: {
      id: event.sender.id
    },
    message: {
      attachment: message.attachment
    }
  }
  facebook.sendMessage(body, callback)
}
<commit_msg>smaller delay<commit_after>'use strict'

const facebook = require('./facebook.js'),
      brain = require('./brain/brain.js'),
      senderActions = require('./sender_actions.js')

exports.handle = function(event) {
  let payload = event.postback.payload
  if (brain.messages[payload]) {
    let payloadClone = JSON.parse(JSON.stringify(brain.messages[payload]))
    handlePayload(event, payloadClone)
  }
}

function handlePayload(event, messages) {
  let message = messages.shift()

  if (message !== undefined) {
    sendMessage(event, message, () => {
      handlePayload(event, messages)
    })
  }
}

function sendMessage(event, message, callback) {
  sendTypingOn(event, message, () => {
    if (message.text) {
      sendTextMessage(event, message, callback)
    } else if (message.attachment) {
      sendAttachmentMessage(event, message, callback)
    }
  })
}

function sendTypingOn(event, message, callback) {
  let text = message.text ? message.text : message.attachment.text
  senderActions.typingOn(event.sender.id, () => {
    let millisPerWord = (60 * 1000) / 600
    let delay = text.split(' ').length * millisPerWord
    setTimeout(callback, delay)
  })
}

function sendTextMessage(event, message, callback) {
  getMessageText(event, message, (text) => {
    let body = {
      recipient: {
        id: event.sender.id
      },
      message: {
        text: text
      }
    }
    facebook.sendMessage(body, callback)
  })
}

function getMessageText(event, message, callback) {
  if (message.required_user_fields) {
    facebook.getUserInfo(event.sender.id, message.required_user_fields, (user) => {
      for (let user_field of message.required_user_fields) {
        let placeholder = '##' + user_field + '##'
        let replace = new RegExp(placeholder, 'g');
        message.text = message.text.replace(replace, user[user_field])
        callback(message.text)
      }
    })
  } else {
    callback(message.text)
  }
}

function sendAttachmentMessage(event, message, callback) {
  let body = {
    recipient: {
      id: event.sender.id
    },
    message: {
      attachment: message.attachment
    }
  }
  facebook.sendMessage(body, callback)
}
<|endoftext|>


<commit_before>videojs.addLanguage("ja",{
 "Play": "再生",
 "Pause": "一時停止",
 "Current Time": "現在の時間",
 "Duration Time": "長さ",
 "Remaining Time": "残りの時間",
 "Stream Type": "ストリームの種類",
 "LIVE": "ライブ",
 "Loaded": "ロード済み",
 "Progress": "進行状況",
 "Fullscreen": "フルスクリーン",
 "Non-Fullscreen": "フルスクリーン以外",
 "Mute": "ミュート",
 "Unmuted": "ミュート解除",
 "Playback Rate": "再生レート",
 "Subtitles": "サブタイトル",
 "subtitles off": "サブタイトル オフ",
 "Captions": "キャプション",
 "captions off": "キャプション オフ",
 "Chapters": "チャプター",
 "You aborted the video playback": "動画再生を中止しました",
 "A network error caused the video download to fail part-way.": "ネットワーク エラーにより動画のダウンロードが途中で失敗しました",
 "The video could not be loaded, either because the server or network failed or because the format is not supported.": "サーバーまたはネットワークのエラー、またはフォーマットがサポートされていないため、動画をロードできませんでした",
 "The video playback was aborted due to a corruption problem or because the video used features your browser did not support.": "破損の問題、またはお使いのブラウザがサポートしていない機能が動画に使用されていたため、動画の再生が中止されました",
 "No compatible source was found for this video.": "この動画に対して互換性のあるソースが見つかりませんでした"
});<commit_msg>Delete ja.js<commit_after><|endoftext|>


<commit_before>/**
 * Telegram API Services
 *
 * @description :: Server-side logic for managing Telegram's BOT Updates
 * @author      :: Alejandro González - algope@github
 * @licence     :: The MIT License (MIT)
 *
 */

var querystring = require('querystring');
var https = require('https');
var request = require('request');

module.exports.sendMessage = function (chat_id, text, parse_mode, disable_web_page_preview, reply_to_message_id, reply_markup) {
    var options = {
        host: sails.config.telegram.url,
        path: "/bot" + sails.config.telegram.token + '/sendMessage',
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        }
    };
    var post_data = JSON.stringify({
        chat_id: chat_id,
        text: text,
        parse_mode: parse_mode,
        disable_web_page_preview: disable_web_page_preview,
        reply_to_message_id: reply_to_message_id,
        reply_markup: reply_markup
    });

    return new Promise(function (resolve, reject) {
        var postReq = https.request(options, function (res) {
            res.setEncoding('utf8');
            var json = "";
            res.on('data', function (chunk) {
                json += chunk;
            });
            res.on('end', function () {
                resolve(JSON.parse(json))
            });
        });
        postReq.write(post_data);
        postReq.end();
    });
};

module.exports.setWebHook = function (url) {
    return new Promise(function (resolve, reject) {
        var formData = {
            url: url
        };
        request.post({
            url: 'https://' + sails.config.telegram.url + '/bot' + sails.config.telegram.token + '/setWebHook',
            formData: formData
        }, function (err, httpResponse, body) {
            if (err) {
                reject(err);
            }
            resolve(JSON.parse(body))
        });

    })
};

module.exports.getFile = function (file_id) {
    var options = {
        host: sails.config.telegram.url,
        path: '/bot' + sails.config.telegram.token + '/getFile?file_id='+file_id
    };

    return new Promise(function (resolve, reject) {
        https.get(options, function (res) {
            var json = "";
            res.on('data', function (chunk) {
                json += chunk;
            });
            res.on('end', function () {
                resolve(JSON.parse(json));
            });
            res.on('error', function (){
            })
        });
    })
};

module.exports.pushToS3 = function(path){
    var url = 'api.telegram.org/file/bot' + sails.config.telegram.token + path;
    var file = path.split('/');
    var file_name = file[1];

    sails.log.debug("FILE NAME FOR S3 ::::: "+file_name);
    sails.log.debug("URL FOR STREAM:::: "+url);

    return new Promise(function (resolve, reject){
        var StreamingS3 = require('streaming-s3'),
            request = require('request');
        var rStream = request.get(url);

        var uploader = new StreamingS3(rStream, {accessKeyId: sails.config.s3.accessKeyId, secretAccessKey: sails.config.s3.secretAccessKey},
            {
                Bucket: sails.config.s3.bucket,
                Key: file_name,
                ContentType: 'image/jpeg'

            },function (err, resp, stats) {
                if (err) return console.log('Upload error: ', err);
                console.log('Upload stats: ', stats);
                console.log('Upload successful: ', resp);
            }

        );

    })
};

module.exports.downloadFile = function (file_path) {
    var options = {
        host: "api.telegram.org",
        path: "/file/bot" + sails.config.telegram.token + file_path
    };
    return new Promise(function (resolve, reject) {
        https.get(options, function (res) {
            var json = "";
            res.on('data', function (chunk) {
                json += chunk;
            });
            res.on('end', function () {
                resolve(JSON.parse(json));
            });
        });
    })
};
<commit_msg>Testing push to S3<commit_after>/**
 * Telegram API Services
 *
 * @description :: Server-side logic for managing Telegram's BOT Updates
 * @author      :: Alejandro González - algope@github
 * @licence     :: The MIT License (MIT)
 *
 */

var querystring = require('querystring');
var https = require('https');
var request = require('request');

module.exports.sendMessage = function (chat_id, text, parse_mode, disable_web_page_preview, reply_to_message_id, reply_markup) {
    var options = {
        host: sails.config.telegram.url,
        path: "/bot" + sails.config.telegram.token + '/sendMessage',
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        }
    };
    var post_data = JSON.stringify({
        chat_id: chat_id,
        text: text,
        parse_mode: parse_mode,
        disable_web_page_preview: disable_web_page_preview,
        reply_to_message_id: reply_to_message_id,
        reply_markup: reply_markup
    });

    return new Promise(function (resolve, reject) {
        var postReq = https.request(options, function (res) {
            res.setEncoding('utf8');
            var json = "";
            res.on('data', function (chunk) {
                json += chunk;
            });
            res.on('end', function () {
                resolve(JSON.parse(json))
            });
        });
        postReq.write(post_data);
        postReq.end();
    });
};

module.exports.setWebHook = function (url) {
    return new Promise(function (resolve, reject) {
        var formData = {
            url: url
        };
        request.post({
            url: 'https://' + sails.config.telegram.url + '/bot' + sails.config.telegram.token + '/setWebHook',
            formData: formData
        }, function (err, httpResponse, body) {
            if (err) {
                reject(err);
            }
            resolve(JSON.parse(body))
        });

    })
};

module.exports.getFile = function (file_id) {
    var options = {
        host: sails.config.telegram.url,
        path: '/bot' + sails.config.telegram.token + '/getFile?file_id='+file_id
    };

    return new Promise(function (resolve, reject) {
        https.get(options, function (res) {
            var json = "";
            res.on('data', function (chunk) {
                json += chunk;
            });
            res.on('end', function () {
                resolve(JSON.parse(json));
            });
            res.on('error', function (){
            })
        });
    })
};

module.exports.pushToS3 = function(path){
    var url = 'https://api.telegram.org/file/bot' + sails.config.telegram.token + path;
    var file = path.split('/');
    var file_name = file[1];

    sails.log.debug("FILE NAME FOR S3 ::::: "+file_name);
    sails.log.debug("URL FOR STREAM:::: "+url);

    return new Promise(function (resolve, reject){
        var StreamingS3 = require('streaming-s3'),
            request = require('request');
        var rStream = request.get(url);

        var uploader = new StreamingS3(rStream, {accessKeyId: sails.config.s3.accessKeyId, secretAccessKey: sails.config.s3.secretAccessKey},
            {
                Bucket: sails.config.s3.bucket,
                Key: file_name,
                ContentType: 'image/jpeg'

            },function (err, resp, stats) {
                if (err) return console.log('Upload error: ', err);
                console.log('Upload stats: ', stats);
                console.log('Upload successful: ', resp);
            }

        );

    })
};

module.exports.downloadFile = function (file_path) {
    var options = {
        host: "api.telegram.org",
        path: "/file/bot" + sails.config.telegram.token + file_path
    };
    return new Promise(function (resolve, reject) {
        https.get(options, function (res) {
            var json = "";
            res.on('data', function (chunk) {
                json += chunk;
            });
            res.on('end', function () {
                resolve(JSON.parse(json));
            });
        });
    })
};
<|endoftext|>


<commit_before>var rootDirectorys = [
    "E:\\77"
];
module.exports = rootDirectorys;<commit_msg>使用系统路径<commit_after>var rootDirectorys = require("../../../server/checkAccess").roots;
module.exports = rootDirectorys;<|endoftext|>


<commit_before>define(function(require) {
var Backbone = require('backbone'),
    ContentView = require('streamhub-backbone/views/ContentView'),
    FeedTickerView = require('streamhub-ticker/views/FeedTickerView');

var TickerView = Backbone.View.extend(
{
    initialize: function (opts) {
        this.$el.addClass(this.className);
        this.$el.hide();
		this.feedCollection = opts.feedCollection;
        this.childViews = {};

        this.collection.on('add', this._insertItem, this);
        this.collection.on('initialDataLoaded', this.render, this);

		if (this.feedCollection) {
	        this.feedCollection.on('add', this._addFeedItem, this);
    	}
    },
    className: "hub-TickerView",
    render: function () {
    	// todo : create sub divs
        this.$el.fadeIn();
    }
});

TickerView.prototype._insertItem = function (item, col) {
    var itemEl = $(document.createElement('div'));
    var feedEl = $(document.createElement('div'));
    itemEl.append(feedEl);
    var contentEl = $(document.createElement('div'));
    itemEl.append(contentEl);

    var json = item.toJSON();

    if (!json.author) { return; }

    itemEl
      .addClass('hub-item')
      .attr('data-hub-contentId', json.id)
      .attr('data-hub-source-id', item.get('sourceId'));

    feedEl.addClass('item-feed-view');
    contentEl.addClass('item-content-view');

    var contentView = new ContentView({
        model: item,
        el: contentEl
    });

    var subCol = new Backbone.Collection();
    subCol.comparator = function(i) { return i.get('createdAt');};

    var feedView = new FeedTickerView({
    	collection: subCol,
    	el: feedEl
    });
    feedView.render();

    this.childViews[item.get('createdAt')] = {feedView:feedView, item: item};

	this._animateAdd(itemEl, col, col.indexOf(item));

	this._rebalanceFeedItems(item, col);

    return itemEl;
};

TickerView.prototype._animateAdd = function(itemEl, col, index) {
	var prev = col.at(index-1);
	var next = col.at(index+1);

	var origScrollWidth = this.$el[0].scrollWidth;
    if (index == 0) {
    	this.$el.append(itemEl);
    } else {
    	prevEl = this.$el.find('.hub-item[data-hub-contentid=' + prev.get('id') + "]");
    	itemEl.insertAfter(prevEl);
    }
    var newScrollWidth = this.$el[0].scrollWidth;
    var diff = newScrollWidth - origScrollWidth;

    if (!this.paused && col._initialized) {
    	this.$el.animate({
    		scrollLeft: this.$el.scrollLeft() + diff
		}, 500);
	} else if (!col._initialized) {
		this.$el.scrollLeft(this.$el.scrollLeft() + diff);
	}
};

TickerView.prototype._rebalanceFeedItems = function(item, col) {
	var index = col.indexOf(item);
	var createdAt = item.get('createdAt');
	var feedCol = this.childViews[createdAt].feedView.collection;

	// this is going to trace backwards, then forewards along the the feed items,
	// in each collection, moving feed item that need to be in this newly added item's collection
	var prev;
	var prevFeedItem;
	var prevCursor = 0;
	while (!prevFeedItem || prevFeedItem.get('createdAt') > createdAt) {
		while (!prevFeedItem) {
			prev = null;
			prevCursor++;
			var prevItem = col.at(index-prevCursor);
			if (prevItem) {
				prev = this.childViews[prevItem.get('id')];
			}
			if (!prev) { break; }
			prevFeedItem = prev.item.collection.last()
		}
		if (!prev) { break; }
		if (prevFeedItem.get('createdAt') > createdAt) {
			console.log("Shuffled from prev: ", prevFeedItem.get('createdAt'), ' > ', createdAt);
			prev.item.collection.remove(prevFeedItem);
			feedCol.add(prevFeedItem);
		}
		prevFeedItem = prev.item.collection.last()
	}

	var next;
	var nextFeedItem;
	var nextCursor = 0;

	while (!nextFeedItem || nextFeedItem.get('createdAt') < createdAt) {
		while (!nextFeedItem) {
			next = null;
			nextCursor++;
			var nextItem = col.at(index+nextCursor);
			if (nextItem) {
				next = this.childViews[nextItem.get('id')];
			}
			if (!next) { break; }
			nextFeedItem = next.item.collection.first()
		}
		if (!next) { break; }
		if (nextFeedItem.get('createdAt') < createdAt) {
			console.log("Shuffled from next: ", nextFeedItem.get('createdAt'), ' < ', createdAt);
			next.item.collection.remove(nextFeedItem);
			feedCol.add(nextFeedItem);
		}
		nextFeedItem = next.item.collection.first()
	}
};

TickerView.prototype._addFeedItem = function(item, col) {
	// parse the tree
    var itemCreatedAt = item.get('createdAt');
    var keys = Object.keys(this.childViews).sort();

    if (keys.length == 0) {
    	return;
    }
    for (var i = 0; i < keys.length; i++) {
    	if (itemCreatedAt > keys[i] && (i == keys.length - 1 || itemCreatedAt < keys[i+1])) {
	    	var feedView = this.childViews[keys[i]].feedView;
			feedView.collection.add(item);
			break;
		}
    }

};

return TickerView;
});
<commit_msg>added child class to parent class<commit_after>define(function(require) {
var Backbone = require('backbone'),
    ContentView = require('streamhub-backbone/views/ContentView'),
    FeedTickerView = require('streamhub-ticker/views/FeedTickerView');

var TickerView = Backbone.View.extend(
{
    initialize: function (opts) {
        this.$el.addClass(this.className);
        this.$el.hide();
		this.feedCollection = opts.feedCollection;
        this.childViews = {};

        this.collection.on('add', this._insertItem, this);
        this.collection.on('initialDataLoaded', this.render, this);

		if (this.feedCollection) {
	        this.feedCollection.on('add', this._addFeedItem, this);
    	}
    },
    className: "hub-TickerView",
    render: function () {
    	// todo : create sub divs
        this.$el.fadeIn();
    }
});

TickerView.prototype._insertItem = function (item, col) {
    var itemEl = $(document.createElement('div'));
    var feedEl = $(document.createElement('div'));
    itemEl.append(feedEl);
    var contentEl = $(document.createElement('div'));
    itemEl.append(contentEl);

    var json = item.toJSON();

    if (!json.author) { return; }

    itemEl
      .addClass('hub-item')
      .attr('data-hub-contentId', json.id)
      .attr('data-hub-source-id', item.get('sourceId'));

    feedEl.addClass('item-feed-view');
    contentEl.addClass('item-content-view');
    contentEl.addClass($(item.get('bodyHtml')).attr('class'));

    var contentView = new ContentView({
        model: item,
        el: contentEl
    });

    var subCol = new Backbone.Collection();
    subCol.comparator = function(i) { return i.get('createdAt');};

    var feedView = new FeedTickerView({
    	collection: subCol,
    	el: feedEl
    });
    feedView.render();

    this.childViews[item.get('createdAt')] = {feedView:feedView, item: item};

	this._animateAdd(itemEl, col, col.indexOf(item));

	this._rebalanceFeedItems(item, col);

    return itemEl;
};

TickerView.prototype._animateAdd = function(itemEl, col, index) {
	var prev = col.at(index-1);
	var next = col.at(index+1);

	var origScrollWidth = this.$el[0].scrollWidth;
    if (index == 0) {
    	this.$el.append(itemEl);
    } else {
    	prevEl = this.$el.find('.hub-item[data-hub-contentid=' + prev.get('id') + "]");
    	itemEl.insertAfter(prevEl);
    }
    var newScrollWidth = this.$el[0].scrollWidth;
    var diff = newScrollWidth - origScrollWidth;

    if (!this.paused && col._initialized) {
    	this.$el.animate({
    		scrollLeft: this.$el.scrollLeft() + diff
		}, 500);
	} else if (!col._initialized) {
		this.$el.scrollLeft(this.$el.scrollLeft() + diff);
	}
};

TickerView.prototype._rebalanceFeedItems = function(item, col) {
	var index = col.indexOf(item);
	var createdAt = item.get('createdAt');
	var feedCol = this.childViews[createdAt].feedView.collection;

	// this is going to trace backwards, then forewards along the the feed items,
	// in each collection, moving feed item that need to be in this newly added item's collection
	var prev;
	var prevFeedItem;
	var prevCursor = 0;
	while (!prevFeedItem || prevFeedItem.get('createdAt') > createdAt) {
		while (!prevFeedItem) {
			prev = null;
			prevCursor++;
			var prevItem = col.at(index-prevCursor);
			if (prevItem) {
				prev = this.childViews[prevItem.get('id')];
			}
			if (!prev) { break; }
			prevFeedItem = prev.item.collection.last()
		}
		if (!prev) { break; }
		if (prevFeedItem.get('createdAt') > createdAt) {
			console.log("Shuffled from prev: ", prevFeedItem.get('createdAt'), ' > ', createdAt);
			prev.item.collection.remove(prevFeedItem);
			feedCol.add(prevFeedItem);
		}
		prevFeedItem = prev.item.collection.last()
	}

	var next;
	var nextFeedItem;
	var nextCursor = 0;

	while (!nextFeedItem || nextFeedItem.get('createdAt') < createdAt) {
		while (!nextFeedItem) {
			next = null;
			nextCursor++;
			var nextItem = col.at(index+nextCursor);
			if (nextItem) {
				next = this.childViews[nextItem.get('id')];
			}
			if (!next) { break; }
			nextFeedItem = next.item.collection.first()
		}
		if (!next) { break; }
		if (nextFeedItem.get('createdAt') < createdAt) {
			console.log("Shuffled from next: ", nextFeedItem.get('createdAt'), ' < ', createdAt);
			next.item.collection.remove(nextFeedItem);
			feedCol.add(nextFeedItem);
		}
		nextFeedItem = next.item.collection.first()
	}
};

TickerView.prototype._addFeedItem = function(item, col) {
	// parse the tree
    var itemCreatedAt = item.get('createdAt');
    var keys = Object.keys(this.childViews).sort();

    if (keys.length == 0) {
    	return;
    }
    for (var i = 0; i < keys.length; i++) {
    	if (itemCreatedAt > keys[i] && (i == keys.length - 1 || itemCreatedAt < keys[i+1])) {
	    	var feedView = this.childViews[keys[i]].feedView;
			feedView.collection.add(item);
			break;
		}
    }

};

return TickerView;
});
<|endoftext|>


<commit_before>window.addEventListener( 'load', function () {
  var manifest = chrome.runtime.getManifest();
  var version = document.getElementById("version");
  version.innerText = manifest.version;

  chrome.runtime.getBackgroundPage(function (backgroundWindow) {
    var target = backgroundWindow.instance();
    var formats = target.formats;

    var defaultFormatButton = document.getElementById('set-default-format');
    var currentDefault = target.getDefaultFormat();
    document.getElementById('current-default-format').textContent = String(currentDefault);
    defaultFormatButton.textContent = 'Set default to ' + currentDefault;
    defaultFormatButton.addEventListener('click', function () {
      var v = defaultFormatButton.getAttribute('data-selected-value');
      target.setDefaultFormat(v);
      document.getElementById('current-default-format').textContent = v;
    });

    try{
      var ctable = new CocoaTable(formats, [
        'label', 'format', 'filter'
      ] );

      ctable.onSelectedRowChanged(function (rowEvent) {
        try {
          var currentSelectedRow = rowEvent.detail.current;
          var selectedName = currentSelectedRow.querySelector('span').textContent;
          defaultFormatButton.textContent = 'Set default to ' + selectedName;
          defaultFormatButton.setAttribute('data-selected-value', selectedName);
        } catch (e) {
          console.log(e);
        }
      });

      ctable._listener.onUpdated = function () {
        var json = ctable.serialize();
        target.setFormatPreferences(json);

        // Update context menus
        chrome.extension.sendMessage({
          command: 'updateContextMenus'
        });
      };
      window.ctable = ctable;
    }catch(e){
      console.log(e);
    }
  });

}, false);
<commit_msg>Get instance anew inside event handlers to be more robust.<commit_after>window.addEventListener( 'load', function () {
  var manifest = chrome.runtime.getManifest();
  var version = document.getElementById("version");
  version.innerText = manifest.version;

  chrome.runtime.getBackgroundPage(function (backgroundWindow) {
    var target = backgroundWindow.instance();
    var formats = target.formats;

    var defaultFormatButton = document.getElementById('set-default-format');
    var currentDefault = target.getDefaultFormat();
    document.getElementById('current-default-format').textContent = String(currentDefault);
    defaultFormatButton.textContent = 'Set default to ' + currentDefault;
    defaultFormatButton.addEventListener('click', function () {
      var v = defaultFormatButton.getAttribute('data-selected-value');
      backgroundWindow.instance().setDefaultFormat(v);
      document.getElementById('current-default-format').textContent = v;
    });

    try{
      var ctable = new CocoaTable(formats, [
        'label', 'format', 'filter'
      ] );

      ctable.onSelectedRowChanged(function (rowEvent) {
        try {
          var currentSelectedRow = rowEvent.detail.current;
          var selectedName = currentSelectedRow.querySelector('span').textContent;
          defaultFormatButton.textContent = 'Set default to ' + selectedName;
          defaultFormatButton.setAttribute('data-selected-value', selectedName);
        } catch (e) {
          console.log(e);
        }
      });

      ctable._listener.onUpdated = function () {
        var json = ctable.serialize();
        backgroundWindow.instance().setFormatPreferences(json);

        // Update context menus
        chrome.extension.sendMessage({
          command: 'updateContextMenus'
        });
      };
      window.ctable = ctable;
    }catch(e){
      console.log(e);
    }
  });

}, false);
<|endoftext|>


<commit_before>/**
 * @fileoverview Extens for KineticJS
 */

/**
 * @type {Object}
 * @const
 */
var Kinetic = {};

/**
 * @typedef {{
 *   data: (string|undefined),
 *   fill: (string|undefined),
 *   scale: (number|undefined),
 *   x: (number|undefined),
 *   y: (number|undefined)
 * }}
 */
Kinetic.Config;

/**
 * @param {Kinetic.Config=} params
 * @constructor
 */
Kinetic.Shape = function(params) {};

/**
 * get/set fill color
 * @param {string=} opt_color
 * @return {string}
 */
Kinetic.Shape.prototype.fill = function(opt_color) {};

/**
 * get/set fill green component
 * @param {number} opt_color
 * @return {number}
 */
Kinetic.Shape.prototype.fillGreen = function(opt_color) {};

/**
 * get/set fill red component
 * @param {number} opt_color
 * @return {number}
 */
Kinetic.Shape.prototype.fillRed = function(opt_color) {};

/**
 * get/set fill blue component
 * @param {number} opt_color
 * @return {number}
 */
Kinetic.Shape.prototype.fillBlue = function(opt_color) {};

/**
 * @param {Kinetic.Config=} params
 * @constructor
 * @extends {Kinetic.Shape}
 */
Kinetic.Container = function(params) {};

/**
 * @param {Kinetic.Config=} params
 * @constructor
 * @extends {Kinetic.Shape}
 */
Kinetic.Path = function(params) {};

/**
 * @param {Kinetic.Config=} params
 * @constructor
 * @extends {Kinetic.Shape}
 */
Kinetic.Circle = function(params) {};

/**
 * @param {Kinetic.Config=} params
 * @constructor
 * @extends {Kinetic.Shape}
 */
Kinetic.Rect = function(params) {};

/**
 * @param {Kinetic.Config=} params
 * @constructor
 * @extends {Kinetic.Shape}
 */
Kinetic.Text = function(params) {};

/**
 * @param {{scaleX: number, scaleY: number}=} params
 * @constructor
 * @extends {Kinetic.Container}
 */
Kinetic.Group = function(params) {};

/**
 * @param {Kinetic.Shape} path
 */
Kinetic.Group.prototype.add = function(path) {};

/**
 * @return {Array.<Kinetic.Shape>}
 */
Kinetic.Group.prototype.getChildren = function() {};

/**
 * @constructor
 */
Kinetic.Layer = function() {};

/**
 * @param {Kinetic.Container} g
 */
Kinetic.Layer.prototype.add = function(g) {};

/**
 * @return {Array.<Kinetic.Group>}
 */
Kinetic.Layer.prototype.getChildren = function() {};

/**
 * @param {{
 * container: (string|Element),
  * width: number,
  * height: number}=} params
 * @constructor
 */
Kinetic.Stage = function(params) {};

/**
 * @param {Kinetic.Layer} layer
 */
Kinetic.Stage.prototype.add = function(layer) {};

/**
 * @constructor
 */
Kinetic.AnimationFrame = function() {};

/**
 * @type {number}
 */
Kinetic.AnimationFrame.prototype.timeDiff;

/**
 * @type {number}
 */
Kinetic.AnimationFrame.prototype.lastTime;

/**
 * @type {number}
 */
Kinetic.AnimationFrame.prototype.time;

/**
 * @type {number}
 */
Kinetic.AnimationFrame.prototype.frameRate;

/**
 * @param {function(Kinetic.AnimationFrame)} frame
 * @param {Kinetic.Layer} layer
 * @constructor
 */
Kinetic.Animation = function(frame, layer) {};

/**
 */
Kinetic.Animation.prototype.start = function() {};

/**
 */
Kinetic.Animation.prototype.stop = function() {};

<commit_msg>activity panel<commit_after>/**
 * @fileoverview Extens for KineticJS
 */

/**
 * @type {Object}
 * @const
 */
var Kinetic = {};

/**
 * @typedef {{
 *   data: (string|undefined),
 *   fill: (string|undefined),
 *   fontSize: (number|undefined),
 *   fontFamily: (string|undefined),
 *   scale: (number|undefined),
 *   stroke: (string|undefined),
 *   strokeWidth: (number|undefined),
 *   text: (string|undefined),
 *   x: (number|undefined),
 *   y: (number|undefined)
 * }}
 */
Kinetic.Config;

/**
 * @param {Kinetic.Config=} params
 * @constructor
 */
Kinetic.Node = function(params) {};

/**
 * @param {Kinetic.Config=} params
 * @constructor
 * @extends {Kinetic.Node}
 */
Kinetic.Shape = function(params) {};

/**
 * get/set fill color
 * @param {string=} opt_color
 * @return {string}
 */
Kinetic.Shape.prototype.fill = function(opt_color) {};

/**
 * get/set fill green component
 * @param {number} opt_color
 * @return {number}
 */
Kinetic.Shape.prototype.fillGreen = function(opt_color) {};

/**
 * get/set fill red component
 * @param {number} opt_color
 * @return {number}
 */
Kinetic.Shape.prototype.fillRed = function(opt_color) {};

/**
 * get/set fill blue component
 * @param {number} opt_color
 * @return {number}
 */
Kinetic.Shape.prototype.fillBlue = function(opt_color) {};

/**
 * @param {Kinetic.Config=} params
 * @constructor
 * @extends {Kinetic.Shape}
 */
Kinetic.Container = function(params) {};

/**
 * @param {Kinetic.Config=} params
 * @constructor
 * @extends {Kinetic.Shape}
 */
Kinetic.Path = function(params) {};

/**
 * @param {Kinetic.Config=} params
 * @constructor
 * @extends {Kinetic.Shape}
 */
Kinetic.Circle = function(params) {};

/**
 * @param {Kinetic.Config=} params
 * @constructor
 * @extends {Kinetic.Shape}
 */
Kinetic.Rect = function(params) {};

/**
 * @param {Kinetic.Config=} params
 * @constructor
 * @extends {Kinetic.Shape}
 */
Kinetic.Text = function(params) {};

/**
 * Set/Get text.
 * @param {string=} text
 * @return {string}
 */
Kinetic.Text.prototype.text = function(text) {};

/**
 * @param {{scaleX: number, scaleY: number}=} params
 * @constructor
 * @extends {Kinetic.Container}
 */
Kinetic.Group = function(params) {};

/**
 * @param {Kinetic.Shape} path
 */
Kinetic.Group.prototype.add = function(path) {};

/**
 * @return {Array.<Kinetic.Shape>}
 */
Kinetic.Group.prototype.getChildren = function() {};

/**
 * @constructor
 * @extends {Kinetic.Container}
 */
Kinetic.Layer = function() {};

/**
 * @param {Kinetic.Node} g
 */
Kinetic.Layer.prototype.add = function(g) {};

/**
 * clear scene and hit canvas contexts tied to the layer
 */
Kinetic.Layer.prototype.clear = function() {};

/**
 * @return {Array.<Kinetic.Group>}
 */
Kinetic.Layer.prototype.getChildren = function() {};

/**
 * @param {{
 * container: (string|Element),
  * width: number,
  * height: number}=} params
 * @constructor
 */
Kinetic.Stage = function(params) {};

/**
 * @param {Kinetic.Layer} layer
 */
Kinetic.Stage.prototype.add = function(layer) {};

/**
 * @constructor
 */
Kinetic.AnimationFrame = function() {};

/**
 * @type {number}
 */
Kinetic.AnimationFrame.prototype.timeDiff;

/**
 * @type {number}
 */
Kinetic.AnimationFrame.prototype.lastTime;

/**
 * @type {number}
 */
Kinetic.AnimationFrame.prototype.time;

/**
 * @type {number}
 */
Kinetic.AnimationFrame.prototype.frameRate;

/**
 * @param {function(Kinetic.AnimationFrame)} frame
 * @param {Kinetic.Layer} layer
 * @constructor
 */
Kinetic.Animation = function(frame, layer) {};

/**
 */
Kinetic.Animation.prototype.start = function() {};

/**
 */
Kinetic.Animation.prototype.stop = function() {};

<|endoftext|>


<commit_before>jsio('from shared.javascript import Class, bind')
jsio('import fan.ui.Component')

exports = Class(fan.ui.Component, function(supr){

	this._className = 'List'

	this.init = function(makeCellFn) {
		supr(this, 'init')
		this._cells = {}
		this._items = []
		this._itemsById = {}
		this._makeCellFn = makeCellFn
	}

	this._createContent = function() {
		this._delegateOn('click', bind(this, '_onClick'))
		this._render()
	}

	this._onClick = function(cellId, element) {
		this.unselect()
		this._selectedElement = element
		this.addClassName(this._selectedElement, 'selected')
		this._publish('Click', cellId, element)
	}

	this.unselect = function() {
		if (this._selectedElement) {
			this.removeClassName(this._selectedElement, 'selected')
		}
	}

	this.addItems = function(itemIds) {
		var byId = this._itemsById
		for (var i=0, itemId; itemId = itemIds[i]; i++) {
			if (byId[itemId]) { continue }
			byId[itemId] = this._addItem(itemId)
		}
		this._render()
	}

	this.removeItems = function(removeItemIds) {
		// this n*m loop could be made more efficient...
		for (var i=0, removeItemId; removeItemId = removeItemIds[i]; i++) {
			if (!this._itemsById[removeItemId]) { continue }
			for (var j=0, item; item = this._items[j]; j++) {
				var itemId = this._getItemId(item)
				if (itemId != removeItemId) { continue }
				this._items.splice(j, 1)
				delete this._itemsById[itemId]
				if (!this._cells[itemId]) { break }
				this.remove(this._cells[itemId])
				delete this._cells[itemId]
				break
			}
		}

		this._render()
	}

	this.append = function(items) {
		Array.prototype.push.apply(this._items, items)
		this._render()
	}
	this.prepend = function(items) {
		Array.prototype.unshift.apply(this._items, items)
		this._render()
	}

	this.createDelayedMethod('_render', function() {
		var items = this._items,
			cells = this._cells

		if (!this._element || !items) { return }

		for (var i=0, item; item = items[i]; i++) {
			var itemId = this._getItemId(item)

			if (!cells[itemId]) {
				cells[itemId] = this._makeCellFn(item)
				this._makeFocusable(cells[itemId])
			}
			parentEl = (this._groupsById && this._groupsById[itemId]) || this._element
			parentEl.appendChild(cells[itemId])
		}
	})

	this._getItemId = function(item) {
		return item.getId ? item.getId()
				: item.timestamp ? item.timestamp
				: item
	}

	this.handleKeyboardSelect = function(cell) {
		this._onClick(cell['delegateId'], cell)
	}
})<commit_msg>Move private property setter in initialize to the top<commit_after>jsio('from shared.javascript import Class, bind')
jsio('import fan.ui.Component')

exports = Class(fan.ui.Component, function(supr){

	this._className = 'List'

	this.init = function(makeCellFn) {
		supr(this, 'init')

		this._makeCellFn = makeCellFn
		this._cells = {}
		this._items = []
		this._itemsById = {}
	}

	this._createContent = function() {
		this._delegateOn('click', bind(this, '_onClick'))
		this._render()
	}

	this._onClick = function(cellId, element) {
		this.unselect()
		this._selectedElement = element
		this.addClassName(this._selectedElement, 'selected')
		this._publish('Click', cellId, element)
	}

	this.unselect = function() {
		if (this._selectedElement) {
			this.removeClassName(this._selectedElement, 'selected')
		}
	}

	this.addItems = function(itemIds) {
		var byId = this._itemsById
		for (var i=0, itemId; itemId = itemIds[i]; i++) {
			if (byId[itemId]) { continue }
			byId[itemId] = this._addItem(itemId)
		}
		this._render()
	}

	this.removeItems = function(removeItemIds) {
		// this n*m loop could be made more efficient...
		for (var i=0, removeItemId; removeItemId = removeItemIds[i]; i++) {
			if (!this._itemsById[removeItemId]) { continue }
			for (var j=0, item; item = this._items[j]; j++) {
				var itemId = this._getItemId(item)
				if (itemId != removeItemId) { continue }
				this._items.splice(j, 1)
				delete this._itemsById[itemId]
				if (!this._cells[itemId]) { break }
				this.remove(this._cells[itemId])
				delete this._cells[itemId]
				break
			}
		}

		this._render()
	}

	this.append = function(items) {
		Array.prototype.push.apply(this._items, items)
		this._render()
	}
	this.prepend = function(items) {
		Array.prototype.unshift.apply(this._items, items)
		this._render()
	}

	this.createDelayedMethod('_render', function() {
		var items = this._items,
			cells = this._cells

		if (!this._element || !items) { return }

		for (var i=0, item; item = items[i]; i++) {
			var itemId = this._getItemId(item)

			if (!cells[itemId]) {
				cells[itemId] = this._makeCellFn(item)
				this._makeFocusable(cells[itemId])
			}
			parentEl = (this._groupsById && this._groupsById[itemId]) || this._element
			parentEl.appendChild(cells[itemId])
		}
	})

	this._getItemId = function(item) {
		return item.getId ? item.getId()
				: item.timestamp ? item.timestamp
				: item
	}

	this.handleKeyboardSelect = function(cell) {
		this._onClick(cell['delegateId'], cell)
	}
})<|endoftext|>


<commit_before>/*

            _/    _/_/    _/_/_/_/_/                              _/
               _/    _/      _/      _/_/    _/    _/    _/_/_/  _/_/_/
          _/  _/  _/_/      _/    _/    _/  _/    _/  _/        _/    _/
         _/  _/    _/      _/    _/    _/  _/    _/  _/        _/    _/
        _/    _/_/  _/    _/      _/_/      _/_/_/    _/_/_/  _/    _/
       _/
    _/

    Created by David Kaneda <http://www.davidkaneda.com>
    Maintained by Thomas Yip <http://beedesk.com/>
    Sponsored by Sencha Labs <http://www.sencha.com/>
    Special thanks to Jonathan Stark <http://www.jonathanstark.com/>

    Documentation and issue tracking on GitHub <http://github.com/senchalabs/jQTouch/>

    (c) 2009-2012 Sencha Labs
    jQTouch may be freely distributed under the MIT license.
*/

(function($) {
    var src = $("head script").last().attr("src") || '';
    var scriptpath = src.split('?')[0].split('/').slice(0, -1).join('/')+'/';
    var csspath = scriptpath + 'jqt.menusheet.css';
    var link = $('<link href="' + csspath + '" rel="stylesheet">');
    $('head').append($(link));

    function hide(callback) {
        var $target = $(this);
        var data = $(this).data('menusheet');
        if (data.shown) {
            $(this).data('menusheet', {});
            var $source = data.source;
            $source.trigger('pageAnimationStart', {
                direction: 'in', animation: undefined, back: true
            });
            $target.trigger('pageAnimationStart', {
                direction: 'out', animation: undefined, back: true
            });
            $source.unbind('touchstart mousedown', data.closehandler);
            $source.one('webkitTransitionEnd', function() {
                $source.removeClass('inmotion transition in');
                $target.removeClass('inmotion out');
                $source.trigger('pageAnimationEnd', {
                    direction: 'in', animation: undefined, back: true
                });
                $target.trigger('pageAnimationEnd', {
                    direction: 'out', animation: undefined, back: true
                });
                !callback || callback.apply(this, arguments);
            });

            $source.addClass('inmotion transition in');
            $target.addClass('inmotion out').removeClass('current');
            $('#jqt').removeClass('menuopened');
        }
        return $target;
    }

    function show(callback) {
        var $target = $(this);
        var data = $(this).data('menusheet') || {};
        if (!data.shown) {
            var $source = $('#jqt .current:not(.menusheet)');
            $target.trigger('pageAnimationStart', {
                direction: 'in', animation: undefined, back: true
            });
            $source.trigger('pageAnimationStart', {
                direction: 'out', animation: undefined, back: true
            });
            var closehandler = function() {
                $target.menusheet('hide');
                return false;
            };

            $source.one('webkitTransitionEnd', function() {
                $source.one('touchstart mousedown', closehandler);
                $source.removeClass('inmotion transition out');
                $target.removeClass('inmotion in');
                $target.trigger('pageAnimationEnd', {
                    direction: 'in', animation: undefined, back: true
                });
                $source.trigger('pageAnimationEnd', {
                    direction: 'out', animation: undefined, back: true
                });
                !callback || callback.apply(this, arguments);
            });

            data.shown = true;
            data.closehandler = closehandler;
            data.source = $source;
            $(this).data('menusheet', data);

            $source.addClass('inmotion transition out');
            $target.addClass('current in');
            $('#jqt').addClass('menuopened');
        }
        return $target;
    }

    var methods = {
        init: function(options) {
            $(this).addClass('menusheet');
            $(this).data('menusheet', {shown: false});
        },
        show: show,
        hide: hide
    };

    $.fn.menusheet = function(method) {
      if (methods[method]) {
          if ($(this).is('.menusheet')) {
              return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
          } else {
              var msg = 'Target is not a `menusheet`. Action `' + method + '` is ignored.';
              console.warn(msg);
          }
      } else if ( typeof method === 'object' || ! method ) {
          return methods.init.apply(this, arguments);
      } else {
          $.error('Method "' + method + '" does not exist on jqt.menusheet' );
      }
    };

    if ($.jQTouch) {
        $.jQTouch.addTapHandler({
            name: 'open-menusheet',
            isSupported: function(e, params) {
                return params.$el.is('.menu');
            },
            fn: function(e, params) {
                params.$el.removeClass('active');

                var $target = $(params.hash);
                $target.menusheet('show');

                return false;
            }
        });
        $.jQTouch.addTapHandler({
            name: 'follow-menulink',
            isSupported: function(e, params) {
                if ($('#jqt').hasClass('menuopened')) {
                    return params.$el.is('.menusheet a');
                }
                return false;
            },
            fn: function(e, params) {
                params.$el.removeClass('active');

                var $target = params.$el.closest('.menusheet');
                $target.menusheet('hide', function() {
                    if (!params.$el.is('.dismiss')) {
                      params.$el.trigger('tap');
                    }
                });
                return false;
            }
        });
    } else {
        console.error('Extension `jqt.menusheet` failed to load. jQT not found');
    }
})($);
<commit_msg>data.ack was incorrectly always true<commit_after>/*

            _/    _/_/    _/_/_/_/_/                              _/
               _/    _/      _/      _/_/    _/    _/    _/_/_/  _/_/_/
          _/  _/  _/_/      _/    _/    _/  _/    _/  _/        _/    _/
         _/  _/    _/      _/    _/    _/  _/    _/  _/        _/    _/
        _/    _/_/  _/    _/      _/_/      _/_/_/    _/_/_/  _/    _/
       _/
    _/

    Created by David Kaneda <http://www.davidkaneda.com>
    Maintained by Thomas Yip <http://beedesk.com/>
    Sponsored by Sencha Labs <http://www.sencha.com/>
    Special thanks to Jonathan Stark <http://www.jonathanstark.com/>

    Documentation and issue tracking on GitHub <http://github.com/senchalabs/jQTouch/>

    (c) 2009-2012 Sencha Labs
    jQTouch may be freely distributed under the MIT license.
*/

(function($) {
    var src = $("head script").last().attr("src") || '';
    var scriptpath = src.split('?')[0].split('/').slice(0, -1).join('/')+'/';
    var csspath = scriptpath + 'jqt.menusheet.css';
    var link = $('<link href="' + csspath + '" rel="stylesheet">');
    $('head').append($(link));

    function hide(callback) {
        var $target = $(this);
        var data = $(this).data('menusheet');
        if (data.shown) {
            $(this).data('menusheet', {});
            var $source = data.source;
            $source.trigger('pageAnimationStart', {
                direction: 'in', animation: undefined, back: true
            });
            $target.trigger('pageAnimationStart', {
                direction: 'out', animation: undefined, back: true
            });
            $source.unbind('touchstart mousedown', data.closehandler);
            $source.one('webkitTransitionEnd', function() {
                $source.removeClass('inmotion transition in');
                $target.removeClass('inmotion out');
                $source.trigger('pageAnimationEnd', {
                    direction: 'in', animation: undefined, back: true
                });
                $target.trigger('pageAnimationEnd', {
                    direction: 'out', animation: undefined, back: true
                });
                !callback || callback.apply(this, arguments);
            });

            $source.addClass('inmotion transition in');
            $target.addClass('inmotion out').removeClass('current');
            $('#jqt').removeClass('menuopened');
        }
        return $target;
    }

    function show(callback) {
        var $target = $(this);
        var data = $(this).data('menusheet') || {};
        if (!data.shown) {
            var $source = $('#jqt .current:not(.menusheet)');
            $target.trigger('pageAnimationStart', {
                direction: 'in', animation: undefined, back: false
            });
            $source.trigger('pageAnimationStart', {
                direction: 'out', animation: undefined, back: false
            });
            var closehandler = function() {
                $target.menusheet('hide');
                return false;
            };

            $source.one('webkitTransitionEnd', function() {
                $source.one('touchstart mousedown', closehandler);
                $source.removeClass('inmotion transition out');
                $target.removeClass('inmotion in');
                $target.trigger('pageAnimationEnd', {
                    direction: 'in', animation: undefined, back: false
                });
                $source.trigger('pageAnimationEnd', {
                    direction: 'out', animation: undefined, back: false
                });
                !callback || callback.apply(this, arguments);
            });

            data.shown = true;
            data.closehandler = closehandler;
            data.source = $source;
            $(this).data('menusheet', data);

            $source.addClass('inmotion transition out');
            $target.addClass('current in');
            $('#jqt').addClass('menuopened');
        }
        return $target;
    }

    var methods = {
        init: function(options) {
            $(this).addClass('menusheet');
            $(this).data('menusheet', {shown: false});
        },
        show: show,
        hide: hide
    };

    $.fn.menusheet = function(method) {
      if (methods[method]) {
          if ($(this).is('.menusheet')) {
              return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
          } else {
              var msg = 'Target is not a `menusheet`. Action `' + method + '` is ignored.';
              console.warn(msg);
          }
      } else if ( typeof method === 'object' || ! method ) {
          return methods.init.apply(this, arguments);
      } else {
          $.error('Method "' + method + '" does not exist on jqt.menusheet' );
      }
    };

    if ($.jQTouch) {
        $.jQTouch.addTapHandler({
            name: 'open-menusheet',
            isSupported: function(e, params) {
                return params.$el.is('.menu');
            },
            fn: function(e, params) {
                params.$el.removeClass('active');

                var $target = $(params.hash);
                $target.menusheet('show');

                return false;
            }
        });
        $.jQTouch.addTapHandler({
            name: 'follow-menulink',
            isSupported: function(e, params) {
                if ($('#jqt').hasClass('menuopened')) {
                    return params.$el.is('.menusheet a');
                }
                return false;
            },
            fn: function(e, params) {
                params.$el.removeClass('active');

                var $target = params.$el.closest('.menusheet');
                $target.menusheet('hide', function() {
                    if (!params.$el.is('.dismiss')) {
                      params.$el.trigger('tap');
                    }
                });
                return false;
            }
        });
    } else {
        console.error('Extension `jqt.menusheet` failed to load. jQT not found');
    }
})($);
<|endoftext|>


<commit_before>/*
 * Copyright 2016 The Closure Compiler Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Definitions for W3C's DOM4 specification. This file depends on
 * w3c_dom3.js. The whole file has been fully type annotated. Created from
 * https://www.w3.org/TR/domcore/.
 *
 * @externs
 * @author zhoumotongxue008@gmail.com (Michael Zhou)
 */

/**
 * @typedef {?(DocumentType|Element|CharacterData)}
 * @see https://www.w3.org/TR/domcore/#interface-childnode
 */
var ChildNode;

/**
 * @return {undefined}
 * @see https://www.w3.org/TR/domcore/#dom-childnode-remove
 */
DocumentType.prototype.remove = function() {};

/**
 * @return {undefined}
 * @see https://www.w3.org/TR/domcore/#dom-childnode-remove
 */
Element.prototype.remove = function() {};

/**
 * @return {undefined}
 * @see https://www.w3.org/TR/domcore/#dom-childnode-remove
 */
CharacterData.prototype.remove = function() {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-replacewith
 */
DocumentType.prototype.replaceWith = function(nodes) {};

/**
 * @const {string}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#sec-domerror
 */
DOMException.prototype.name;

/**
 * @const {string}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#sec-domerror
 */
DOMException.prototype.message;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.SECURITY_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.NETWORK_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.ABORT_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.URL_MISMATCH_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.QUOTA_EXCEEDED_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.TIMEOUT_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.INVALID_NODE_TYPE_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.DATA_CLONE_ERR;

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-replacewith
 */
Element.prototype.replaceWith = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-replacewith
 */
CharacterData.prototype.replaceWith = function(nodes) {};

/**
 * @return {!Array<string>}
 * @see https://dom.spec.whatwg.org/#dom-element-getattributenames
 */
Element.prototype.getAttributeNames = function() {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-append
 */
Element.prototype.append = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-append
 */
Document.prototype.append = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-append
 */
DocumentFragment.prototype.append = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-prepend
 */
Element.prototype.prepend = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-prepend
 */
Document.prototype.prepend = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-prepend
 */
DocumentFragment.prototype.prepend = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-before
 */
Element.prototype.before = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-before
 */
DocumentType.prototype.before = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-before
 */
CharacterData.prototype.before = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-after
 */
Element.prototype.after = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-after
 */
DocumentType.prototype.after = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-after
 */
CharacterData.prototype.after = function(nodes) {};

/**
 * @param {string} name
 * @param {boolean=} force
 * @return {boolean}
 * @throws {DOMException}
 * @see https://dom.spec.whatwg.org/#dom-element-toggleattribute
 */
Element.prototype.toggleAttribute = function(name, force) {};

/**
 * @type {Element}
 * @see http://msdn.microsoft.com/en-us/library/ms534327(VS.85).aspx
 */
Node.prototype.parentElement;

/**
 * @param {string} name
 * @return {!HTMLCollection<!Element>}
 * @nosideeffects
 * @see https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname-classnames-classnames
 */
Document.prototype.getElementsByClassName = function(name) {};

/**
 * @param {string} classNames
 * @return {!HTMLCollection<!Element>}
 * @nosideeffects
 * @see https://dom.spec.whatwg.org/#dom-element-getelementsbyclassname-classnames-classnames
 */
Element.prototype.getElementsByClassName = function(classNames) {};
<commit_msg>Added to externs Element.insertAdjacentElement, Element.insertAdjacentHTML, and Element.insertAdjacentText<commit_after>/*
 * Copyright 2016 The Closure Compiler Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Definitions for W3C's DOM4 specification. This file depends on
 * w3c_dom3.js. The whole file has been fully type annotated. Created from
 * https://www.w3.org/TR/domcore/.
 *
 * @externs
 * @author zhoumotongxue008@gmail.com (Michael Zhou)
 */

/**
 * @typedef {?(DocumentType|Element|CharacterData)}
 * @see https://www.w3.org/TR/domcore/#interface-childnode
 */
var ChildNode;

/**
 * @return {undefined}
 * @see https://www.w3.org/TR/domcore/#dom-childnode-remove
 */
DocumentType.prototype.remove = function() {};

/**
 * @return {undefined}
 * @see https://www.w3.org/TR/domcore/#dom-childnode-remove
 */
Element.prototype.remove = function() {};

/**
 * @return {undefined}
 * @see https://www.w3.org/TR/domcore/#dom-childnode-remove
 */
CharacterData.prototype.remove = function() {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-replacewith
 */
DocumentType.prototype.replaceWith = function(nodes) {};

/**
 * @const {string}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#sec-domerror
 */
DOMException.prototype.name;

/**
 * @const {string}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#sec-domerror
 */
DOMException.prototype.message;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.SECURITY_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.NETWORK_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.ABORT_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.URL_MISMATCH_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.QUOTA_EXCEEDED_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.TIMEOUT_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.INVALID_NODE_TYPE_ERR;

/**
 * @const {number}
 * @see https://www.w3.org/TR/2015/REC-dom-20151119/#dfn-error-names-table
 */
DOMException.DATA_CLONE_ERR;

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-replacewith
 */
Element.prototype.replaceWith = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-replacewith
 */
CharacterData.prototype.replaceWith = function(nodes) {};

/**
 * @return {!Array<string>}
 * @see https://dom.spec.whatwg.org/#dom-element-getattributenames
 */
Element.prototype.getAttributeNames = function() {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-append
 */
Element.prototype.append = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-append
 */
Document.prototype.append = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-append
 */
DocumentFragment.prototype.append = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-prepend
 */
Element.prototype.prepend = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-prepend
 */
Document.prototype.prepend = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-parentnode-prepend
 */
DocumentFragment.prototype.prepend = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-before
 */
Element.prototype.before = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-before
 */
DocumentType.prototype.before = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-before
 */
CharacterData.prototype.before = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-after
 */
Element.prototype.after = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-after
 */
DocumentType.prototype.after = function(nodes) {};

/**
 * @param {...(!Node|string)} nodes
 * @return {undefined}
 * @see https://dom.spec.whatwg.org/#dom-childnode-after
 */
CharacterData.prototype.after = function(nodes) {};

/**
 * @param {string} name
 * @param {boolean=} force
 * @return {boolean}
 * @throws {DOMException}
 * @see https://dom.spec.whatwg.org/#dom-element-toggleattribute
 */
Element.prototype.toggleAttribute = function(name, force) {};

/**
 * @type {Element}
 * @see http://msdn.microsoft.com/en-us/library/ms534327(VS.85).aspx
 */
Node.prototype.parentElement;

/**
 * @param {string} name
 * @return {!HTMLCollection<!Element>}
 * @nosideeffects
 * @see https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname-classnames-classnames
 */
Document.prototype.getElementsByClassName = function(name) {};

/**
 * @param {string} classNames
 * @return {!HTMLCollection<!Element>}
 * @nosideeffects
 * @see https://dom.spec.whatwg.org/#dom-element-getelementsbyclassname-classnames-classnames
 */
Element.prototype.getElementsByClassName = function(classNames) {};

/**
 * @param {string} where
 * @param {Element} element
 * @return {!Element}
 * @throws {DOMException}
 * @see https://dom.spec.whatwg.org/#dom-element-insertadjacentelement
 */
Element.prototype.insertAdjacentElement = function(where, element) {};

/**
 * @param {string} position
 * @param {string} text
 * @return {undefined}
 * @throws {DOMException}
 * @see https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml
 */
Element.prototype.insertAdjacentHTML = function(position, text) {};

/**
 * @param {string} where
 * @param {string} data
 * @return {undefined}
 * @throws {DOMException}
 * @see https://dom.spec.whatwg.org/#dom-element-insertadjacenttext
 */
Element.prototype.insertAdjacentText = function(where, data) {};
<|endoftext|>