text:
/*
 *  New function for traversing elements
 */

html2canvas.Parse = function (element, images, opts) {
    window.scroll(0,0);
    opts = opts || {};

    // select body by default
    if (element === undefined) {
        element = document.body;
    }

    var support = {
        rangeBounds: false

    },
    options = {
        iframeDefault: "default",
        ignoreElements: "IFRAME|OBJECT|PARAM",
        useOverflow: true,
        letterRendering: false
    },
    needReorder = false,
    numDraws = 0,
    fontData = {},
    doc = element.ownerDocument,
    ignoreElementsRegExp = new RegExp("(" + options.ignoreElements + ")"),
    body = doc.body,
    r,
    testElement,
    rangeBounds,
    rangeHeight,
    stack,
    ctx,
    docDim,
    i,
    children,
    childrenLen;

    options = html2canvas.Util.Extend(opts, options);

    images = images || {};

    // Test whether we can use ranges to measure bounding boxes
    // Opera doesn't provide valid bounds.height/bottom even though it supports the method.

    if (doc.createRange) {
        r = doc.createRange();
        //this.support.rangeBounds = new Boolean(r.getBoundingClientRect);
        if (r.getBoundingClientRect){
            testElement = doc.createElement('boundtest');
            testElement.style.height = "123px";
            testElement.style.display = "block";
            body.appendChild(testElement);

            r.selectNode(testElement);
            rangeBounds = r.getBoundingClientRect();
            rangeHeight = rangeBounds.height;

            if (rangeHeight === 123) {
                support.rangeBounds = true;
            }
            body.removeChild(testElement);

        }

    }

    /*
    var rootStack = new this.storageContext($(document).width(),$(document).height());
    rootStack.opacity = this.getCSS(this.element,"opacity");
    var stack = this.newElement(this.element,rootStack);

    this.parseElement(this.element,stack);
     */

    function docSize(){

        return {
            width: Math.max(
                Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth),
                Math.max(doc.body.offsetWidth, doc.documentElement.offsetWidth),
                Math.max(doc.body.clientWidth, doc.documentElement.clientWidth)
                ),
            height: Math.max(
                Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight),
                Math.max(doc.body.offsetHeight, doc.documentElement.offsetHeight),
                Math.max(doc.body.clientHeight, doc.documentElement.clientHeight)
                )
        };

    }

    function getCSS (element, attribute, intOnly) {

        if (intOnly !== undefined && intOnly === true) {
            return parseInt(html2canvas.Util.getCSS(element, attribute), 10);
        }else{
            return html2canvas.Util.getCSS(element, attribute);
        }
    }

    // Drawing a rectangle
    function renderRect (ctx, x, y, w, h, bgcolor) {
        if (bgcolor !=="transparent"){
            ctx.setVariable("fillStyle", bgcolor);
            ctx.fillRect (x, y, w, h);
            numDraws+=1;
        }
    }

    function textTransform (text, transform) {
        switch(transform){
            case "lowercase":
                return text.toLowerCase();

            case "capitalize":
                return text.replace( /(^|\s|:|-|\(|\))([a-z])/g , function (m, p1, p2) {
                    if (m.length > 0) {
                        return p1 + p2.toUpperCase();
                    }
                } );

            case "uppercase":
                return text.toUpperCase();

            default:
                return text;

        }

    }

    function trimText (text) {
        return text.replace(/^\s*/g, "").replace(/\s*$/g, "");
    }

    function fontMetrics (font, fontSize) {

        if (fontData[font + "-" + fontSize] !== undefined) {
            return fontData[font + "-" + fontSize];
        }

        var container = doc.createElement('div'),
        img = doc.createElement('img'),
        span = doc.createElement('span'),
        baseline,
        middle,
        metricsObj;

        container.style.visibility = "hidden";
        container.style.fontFamily = font;
        container.style.fontSize = fontSize;
        container.style.margin = 0;
        container.style.padding = 0;

        body.appendChild(container);

        // http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever (handtinywhite.gif)
        img.src = "data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=";
        img.width = 1;
        img.height = 1;

        img.style.margin = 0;
        img.style.padding = 0;
        img.style.verticalAlign = "baseline";

        span.style.fontFamily = font;
        span.style.fontSize = fontSize;
        span.style.margin = 0;
        span.style.padding = 0;

        span.appendChild(doc.createTextNode('Hidden Text'));
        container.appendChild(span);
        container.appendChild(img);
        baseline = (img.offsetTop - span.offsetTop) + 1;

        container.removeChild(span);
        container.appendChild(doc.createTextNode('Hidden Text'));

        container.style.lineHeight = "normal";
        img.style.verticalAlign = "super";

        middle = (img.offsetTop-container.offsetTop) + 1;
        metricsObj = {
            baseline: baseline,
            lineWidth: 1,
            middle: middle
        };

        fontData[font + "-" + fontSize] = metricsObj;

        body.removeChild(container);

        return metricsObj;

    }

    function drawText(currentText, x, y, ctx){
        if (trimText(currentText).length>0) {
            ctx.fillText(currentText,x,y);
            numDraws+=1;
        }
    }

    function renderText(el, textNode, stack) {
        var ctx = stack.ctx,
        family = getCSS(el, "fontFamily", false),
        size = getCSS(el, "fontSize", false),
        color = getCSS(el, "color", false),
        text_decoration = getCSS(el, "textDecoration", false),
        text_align = getCSS(el, "textAlign", false),
        letter_spacing = getCSS(el, "letterSpacing", false),
        bounds,
        text,
        metrics,
        renderList,
        bold = getCSS(el, "fontWeight", false),
        font_style = getCSS(el, "fontStyle", false),
        font_variant = getCSS(el, "fontVariant", false),
        align = false,
        newTextNode,
        textValue,
        textOffset = 0,
        oldTextNode,
        c,
        range,
        parent,
        wrapElement,
        backupText;

        // apply text-transform:ation to the text

        textNode.nodeValue = textTransform(textNode.nodeValue, getCSS(el, "textTransform", false));
        text = trimText(textNode.nodeValue);

        if (text.length>0){

            if (text_decoration !== "none"){
                metrics = fontMetrics(family, size);
            }

            text_align = text_align.replace(["-webkit-auto"],["auto"]);

            if (options.letterRendering === false && /^(left|right|justify|auto)$/.test(text_align) && /^(normal|none)$/.test(letter_spacing)){
                // this.setContextVariable(ctx,"textAlign",text_align);
                renderList = textNode.nodeValue.split(/(\b| )/);

            }else{
                //  this.setContextVariable(ctx,"textAlign","left");
                renderList = textNode.nodeValue.split("");
            }

            switch(parseInt(bold, 10)){
                case 401:
                    bold = "bold";
                    break;
                case 400:
                    bold = "normal";
                    break;
            }

            ctx.setVariable("fillStyle", color);
            ctx.setVariable("font", font_variant + " " + bold + " " + font_style + " " + size + " " + family);

            if (align){
                ctx.setVariable("textAlign", "right");
            }else{
                ctx.setVariable("textAlign", "left");
            }

            /*
        if (stack.clip){
        ctx.rect (stack.clip.left, stack.clip.top, stack.clip.width, stack.clip.height);
        ctx.clip();
        }
             */

            oldTextNode = textNode;

            for (c=0; c < renderList.length; c+=1) {
                textValue = null;

                if (support.rangeBounds){
                    // getBoundingClientRect is supported for ranges
                    if (text_decoration !== "none" || trimText(renderList[c]).length !== 0) {
                        textValue = renderList[c];
                        if (doc.createRange){
                            range = doc.createRange();

                            range.setStart(textNode, textOffset);
                            range.setEnd(textNode, textOffset + textValue.length);
                        }else{
                            // TODO add IE support
                            range = body.createTextRange();
                        }

                        if (range.getBoundingClientRect()) {
                            bounds = range.getBoundingClientRect();
                        }else{
                            bounds = {};
                        }

                    }
                }else{
                    // it isn't supported, so let's wrap it inside an element instead and get the bounds there

                    // IE 9 bug
                    if (typeof oldTextNode.nodeValue !== "string" ){
                        continue;
                    }

                    newTextNode = oldTextNode.splitText(renderList[c].length);

                    parent = oldTextNode.parentNode;
                    wrapElement = doc.createElement('wrapper');
                    backupText = oldTextNode.cloneNode(true);

                    wrapElement.appendChild(oldTextNode.cloneNode(true));
                    parent.replaceChild(wrapElement, oldTextNode);

                    bounds = html2canvas.Util.Bounds(wrapElement);

                    textValue = oldTextNode.nodeValue;

                    oldTextNode = newTextNode;
                    parent.replaceChild(backupText, wrapElement);

                }

                if (textValue !== null){
                    drawText(textValue, bounds.left, bounds.bottom, ctx);
                }

                switch(text_decoration) {
                    case "underline":
                        // Draws a line at the baseline of the font
                        // TODO As some browsers display the line as more than 1px if the font-size is big, need to take that into account both in position and size
                        renderRect(ctx, bounds.left, Math.round(bounds.top + metrics.baseline + metrics.lineWidth), bounds.width, 1, color);
                        break;
                    case "overline":
                        renderRect(ctx, bounds.left, bounds.top, bounds.width, 1, color);
                        break;
                    case "line-through":
                        // TODO try and find exact position for line-through
                        renderRect(ctx, bounds.left, Math.ceil(bounds.top + metrics.middle + metrics.lineWidth), bounds.width, 1, color);
                        break;

                }

                textOffset += renderList[c].length;

            }

        }

    }

    function listPosition (element, val) {
        var boundElement = doc.createElement( "boundelement" ),
        type,
        bounds;

        boundElement.style.display = "inline";
        //boundElement.style.width = "1px";
        //boundElement.style.height = "1px";

        type = element.style.listStyleType;
        element.style.listStyleType = "none";

        boundElement.appendChild( doc.createTextNode( val ) );

        element.insertBefore(boundElement, element.firstChild);

        bounds = html2canvas.Util.Bounds( boundElement );
        element.removeChild( boundElement );
        element.style.listStyleType = type;
        return bounds;

    }

    function renderListItem(element, stack, elBounds) {

        var position = getCSS(element, "listStylePosition", false),
        x,
        y,
        type = getCSS(element, "listStyleType", false),
        currentIndex,
        text,
        listBounds,
        bold = getCSS(element, "fontWeight");

        if (/^(decimal|decimal-leading-zero|upper-alpha|upper-latin|upper-roman|lower-alpha|lower-greek|lower-latin|lower-roman)$/i.test(type)) {

            // TODO remove jQuery dependency
            currentIndex = $(element).index()+1;

            switch(type){
                case "decimal":
                    text = currentIndex;
                    break;
                case "decimal-leading-zero":
                    if (currentIndex.toString().length === 1){
                        text = currentIndex = "0" + currentIndex.toString();
                    }else{
                        text = currentIndex.toString();
                    }
                    break;
                case "upper-roman":
                    text = html2canvas.Generate.ListRoman( currentIndex );
                    break;
                case "lower-roman":
                    text = html2canvas.Generate.ListRoman( currentIndex ).toLowerCase();
                    break;
                case "lower-alpha":
                    text = html2canvas.Generate.ListAlpha( currentIndex ).toLowerCase();
                    break;
                case "upper-alpha":
                    text = html2canvas.Generate.ListAlpha( currentIndex );
                    break;
            }

            text += ". ";
            listBounds = listPosition(element, text);

            switch(bold){
                case 401:
                    bold = "bold";
                    break;
                case 400:
                    bold = "normal";
                    break;
            }

            ctx.setVariable( "fillStyle", getCSS(element, "color", false) );
            ctx.setVariable( "font", getCSS(element, "fontVariant", false) + " " + bold + " " + getCSS(element, "fontStyle", false) + " " + getCSS(element, "fontFize", false) + " " + getCSS(element, "fontFamily", false) );

            if ( position === "inside" ) {
                ctx.setVariable("textAlign", "left");
                //   this.setFont(stack.ctx, element, false);
                x = elBounds.left;

            }else{
                return;
                /*
                 TODO really need to figure out some more accurate way to try and find the position.
                 as defined in http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-position, it does not even have a specified "correct" position, so each browser
                 may display it whatever way it feels like.
                 "The position of the list-item marker adjacent to floats is undefined in CSS 2.1. CSS 2.1 does not specify the precise location of the marker box or its position in the painting order"
                */
                ctx.setVariable("textAlign", "right");
                //  this.setFont(stack.ctx, element, true);
                x = elBounds.left - 10;
            }

            y = listBounds.bottom;

            drawText(text, x, y, ctx)

        }

    }

    function loadImage (src){
      var img = images[src];
      if (img && img.succeeded === true) {
        return img.img;
      } else {
        return false;
      }
    }

    function clipBounds(src, dst){

        var x = Math.max(src.left, dst.left),
        y = Math.max(src.top, dst.top),
        x2 = Math.min((src.left + src.width), (dst.left + dst.width)),
        y2 = Math.min((src.top + src.height), (dst.top + dst.height));

        return {
            left:x,
            top:y,
            width:x2-x,
            height:y2-y
        };

    }

    function setZ(zIndex, parentZ){
        // TODO fix static elements overlapping relative/absolute elements under same stack, if they are defined after them

        if (!parentZ){
            this.zStack = new html2canvas.zContext(0);
            return this.zStack;
        }

        if (zIndex !== "auto"){
            needReorder = true;
            var newContext = new html2canvas.zContext(zIndex);
            parentZ.children.push(newContext);
            return newContext;

        }

        return parentZ;

    }

    function renderBorders(el, ctx, bounds, clip){

        /*
         *  TODO add support for different border-style's than solid
         */

        var x = bounds.left,
        y = bounds.top,
        w = bounds.width,
        h = bounds.height,
        borderSide,
        borderData,
        bx,
        by,
        bw,
        bh,
        borderBounds,
        borders = (function(el){
            var borders = [],
            sides = ["Top","Right","Bottom","Left"],
            s;

            for (s = 0; s < 4; s+=1){
                borders.push({
                    width: getCSS(el, 'border' + sides[s] + 'Width', true),
                    color: getCSS(el, 'border' + sides[s] + 'Color', false)
                });
            }

            return borders;

        }(el));

        for (borderSide = 0; borderSide < 4; borderSide+=1){
            borderData = borders[borderSide];

            if (borderData.width>0){
                bx = x;
                by = y;
                bw = w;
                bh = h - (borders[2].width);

                switch(borderSide){
                    case 0:
                        // top border
                        bh = borders[0].width;
                        break;
                    case 1:
                        // right border
                        bx = x + w - (borders[1].width);
                        bw = borders[1].width;
                        break;
                    case 2:
                        // bottom border
                        by = (by + h) - (borders[2].width);
                        bh = borders[2].width;
                        break;
                    case 3:
                        // left border
                        bw = borders[3].width;
                        break;
                }

                borderBounds = {
                    left:bx,
                    top:by,
                    width: bw,
                    height:bh
                };

                if (clip){
                    borderBounds = clipBounds(borderBounds, clip);
                }

                if (borderBounds.width>0 && borderBounds.height>0){
                    renderRect(ctx, bx, by, borderBounds.width, borderBounds.height, borderData.color);
                }

            }
        }

        return borders;

    }

    function renderFormValue (el, bounds, stack){

        var valueWrap = doc.createElement('valuewrap'),
        cssArr = ['lineHeight','textAlign','fontFamily','color','fontSize','paddingLeft','paddingTop','width','height','border','borderLeftWidth','borderTopWidth'],
        i,
        textValue,
        textNode,
        arrLen,
        style;

        for (i = 0, arrLen = cssArr.length; i < arrLen; i+=1){
            style = cssArr[i];
            valueWrap.style[style] = getCSS(el, style, false);
        }

        valueWrap.style.borderColor = "black";
        valueWrap.style.borderStyle = "solid";
        valueWrap.style.display = "block";
        valueWrap.style.position = "absolute";
        if (/^(submit|reset|button|text|password)$/.test(el.type) || el.nodeName === "SELECT"){
            valueWrap.style.lineHeight = getCSS(el, "height", false);
        }

        valueWrap.style.top = bounds.top + "px";
        valueWrap.style.left = bounds.left + "px";

        if (el.nodeName === "SELECT"){
            // TODO increase accuracy of text position
            textValue = el.options[el.selectedIndex].text;
        } else{
            textValue = el.value;
        }
        textNode = doc.createTextNode(textValue);

        valueWrap.appendChild(textNode);
        body.appendChild(valueWrap);

        renderText(el, textNode, stack);
        body.removeChild(valueWrap);

    }

    function getBackgroundPosition(el, bounds, image){
        // TODO add support for multi image backgrounds

        var bgpos = getCSS(el, "backgroundPosition").split(",")[0] || "0 0",
        bgposition = bgpos.split(" "),
        topPos,
        left,
        percentage,
        val;

        if (bgposition.length === 1){
            val = bgposition;

            bgposition = [];

            bgposition[0] = val;
            bgposition[1] = val;
        }

        if (bgposition[0].toString().indexOf("%") !== -1){
            percentage = (parseFloat(bgposition[0])/100);
            left =  ((bounds.width * percentage)-(image.width*percentage));

        }else{
            left = parseInt(bgposition[0],10);
        }

        if (bgposition[1].toString().indexOf("%") !== -1){

            percentage = (parseFloat(bgposition[1])/100);
            topPos =  ((bounds.height * percentage)-(image.height*percentage));
        }else{
            topPos = parseInt(bgposition[1],10);
        }

        return {
            top: topPos,
            left: left
        };

    }

    function renderImage (ctx, image, sx, sy, sw, sh, dx, dy, dw, dh) {
        ctx.drawImage(
            image,
            sx, //sx
            sy, //sy
            sw, //sw
            sh, //sh
            dx, //dx
            dy, // dy
            dw, //dw
            dh //dh
            );
        numDraws+=1;

    }

    function renderBackgroundRepeat (ctx, image, x, y, width, height, elx, ely){
        var sourceX = 0,
        sourceY=0;
        if (elx-x>0){
            sourceX = elx-x;
        }

        if (ely-y>0){
            sourceY = ely-y;
        }

        renderImage(
            ctx,
            image,
            sourceX, // source X
            sourceY, // source Y
            width-sourceX, // source Width
            height-sourceY, // source Height
            x+sourceX, // destination X
            y+sourceY, // destination Y
            width-sourceX, // destination width
            height-sourceY // destination height
            );
    }

    function renderBackgroundRepeatY (ctx, image, bgp, x, y, w, h){

        var height,
        width = Math.min(image.width,w),bgy;

        bgp.top = bgp.top-Math.ceil(bgp.top/image.height)*image.height;

        for(bgy=(y+bgp.top);bgy<h+y;){

            if ( Math.floor(bgy+image.height)>h+y){
                height = (h+y)-bgy;
            }else{
                height = image.height;
            }
            renderBackgroundRepeat(ctx,image,x+bgp.left,bgy,width,height,x,y);

            bgy = Math.floor(bgy+image.height);

        }
    }

    function renderBackgroundRepeatX(ctx, image, bgp, x, y, w, h){

        var height = Math.min(image.height,h),
        width,bgx;

        bgp.left = bgp.left-Math.ceil(bgp.left/image.width)*image.width;

        for (bgx=(x+bgp.left);bgx<w+x;) {

            if (Math.floor(bgx+image.width)>w+x){
                width = (w+x)-bgx;
            }else{
                width = image.width;
            }

            renderBackgroundRepeat(ctx,image,bgx,(y+bgp.top),width,height,x,y);

            bgx = Math.floor(bgx+image.width);

        }
    }

    function renderBackground(el,bounds,ctx){

        // TODO add support for multi background-images
        var background_image = getCSS(el, "backgroundImage", false),
        background_repeat = getCSS(el, "backgroundRepeat", false).split(",")[0],
        image,
        bgp,
        bgy,
        bgw,
        bgsx,
        bgsy,
        bgdx,
        bgdy,
        bgh,
        h,
        height,
        add;

        //   if (typeof background_image !== "undefined" && /^(1|none)$/.test(background_image) === false && /^(-webkit|-moz|linear-gradient|-o-)/.test(background_image)===false){

        if ( !/data:image\/.*;base64,/i.test(background_image) && !/^(-webkit|-moz|linear-gradient|-o-)/.test(background_image) ) {
            background_image = background_image.split(",")[0];
        }

        if ( typeof background_image !== "undefined" && /^(1|none)$/.test( background_image ) === false ) {
            background_image = html2canvas.Util.backgroundImage( background_image );
            image = loadImage( background_image );

            bgp = getBackgroundPosition(el, bounds, image);

            if ( image ){
                switch ( background_repeat ) {

                    case "repeat-x":
                        renderBackgroundRepeatX( ctx, image, bgp, bounds.left, bounds.top, bounds.width, bounds.height );
                        break;

                    case "repeat-y":
                        renderBackgroundRepeatY( ctx, image, bgp, bounds.left, bounds.top, bounds.width, bounds.height );
                        break;

                    case "no-repeat":
                        /*
                    this.drawBackgroundRepeat(
                        ctx,
                        image,
                        bgp.left+bounds.left, // sx
                        bgp.top+bounds.top, // sy
                        Math.min(bounds.width,image.width),
                        Math.min(bounds.height,image.height),
                        bounds.left,
                        bounds.top
                        );*/

                        // console.log($(el).css('background-image'));
                        bgw = bounds.width - bgp.left;
                        bgh = bounds.height - bgp.top;
                        bgsx = bgp.left;
                        bgsy = bgp.top;
                        bgdx = bgp.left+bounds.left;
                        bgdy = bgp.top+bounds.top;

                        //
                        //     bgw = Math.min(bgw,image.width);
                        //  bgh = Math.min(bgh,image.height);

                        if (bgsx<0){
                            bgsx = Math.abs(bgsx);
                            bgdx += bgsx;
                            bgw = Math.min(bounds.width,image.width-bgsx);
                        }else{
                            bgw = Math.min(bgw,image.width);
                            bgsx = 0;
                        }

                        if (bgsy<0){
                            bgsy = Math.abs(bgsy);
                            bgdy += bgsy;
                            // bgh = bgh-bgsy;
                            bgh = Math.min(bounds.height,image.height-bgsy);
                        }else{
                            bgh = Math.min(bgh,image.height);
                            bgsy = 0;
                        }

                        //   bgh = Math.abs(bgh);
                        //   bgw = Math.abs(bgw);
                        if (bgh>0 && bgw > 0){
                            renderImage(
                                ctx,
                                image,
                                bgsx, // source X : 0
                                bgsy, // source Y : 1695
                                bgw, // source Width : 18
                                bgh, // source Height : 1677
                                bgdx, // destination X :906
                                bgdy, // destination Y : 1020
                                bgw, // destination width : 18
                                bgh // destination height : 1677
                                );

                        // ctx.drawImage(image,(bounds.left+bgp.left),(bounds.top+bgp.top));

                        }
                        break;
                    default:

                        bgp.top = bgp.top-Math.ceil(bgp.top/image.height)*image.height;

                        for(bgy=(bounds.top+bgp.top);bgy<bounds.height+bounds.top;){

                            h = Math.min(image.height,(bounds.height+bounds.top)-bgy);

                            if ( Math.floor(bgy+image.height)>h+bgy){
                                height = (h+bgy)-bgy;
                            }else{
                                height = image.height;
                            }
                            // console.log(height);

                            if (bgy<bounds.top){
                                add = bounds.top-bgy;
                                bgy = bounds.top;

                            }else{
                                add = 0;
                            }

                            renderBackgroundRepeatX(ctx,image,bgp,bounds.left,bgy,bounds.width,height);
                            if (add>0){
                                bgp.top += add;
                            }
                            bgy = Math.floor(bgy+image.height)-add;
                        }
                        break;

                }
            }else{
                html2canvas.log("html2canvas: Error loading background:" + background_image);
            //console.log(images);
            }

        }
    }

    function renderElement(el, parentStack){

        var bounds = html2canvas.Util.Bounds(el),
        x = bounds.left,
        y = bounds.top,
        w = bounds.width,
        h = bounds.height,
        image,
        bgcolor = getCSS(el, "backgroundColor", false),
        cssPosition = getCSS(el, "position", false),
        zindex,
        opacity = getCSS(el, "opacity", false),
        stack,
        stackLength,
        borders,
        ctx,
        bgbounds,
        imgSrc,
        paddingLeft,
        paddingTop,
        paddingRight,
        paddingBottom;

        if (parentStack === undefined){
            docDim = docSize();
            parentStack = {
                opacity: 1
            };
        }else{
            docDim = {};
        }

        //var zindex = this.formatZ(this.getCSS(el,"zIndex"),cssPosition,parentStack.zIndex,el.parentNode);

        zindex = setZ( getCSS( el, "zIndex", false ), parentStack.zIndex );

        stack = {
            ctx: new html2canvas.canvasContext( docDim.width || w , docDim.height || h ),
            zIndex: zindex,
            opacity: opacity * parentStack.opacity,
            cssPosition: cssPosition
        };

        // TODO correct overflow for absolute content residing under a static position

        if (parentStack.clip){
            stack.clip = html2canvas.Util.Extend( {}, parentStack.clip );
        //stack.clip = parentStack.clip;
        //   stack.clip.height = stack.clip.height - parentStack.borders[2].width;
        }

        if ( options.useOverflow === true && /(hidden|scroll|auto)/.test(getCSS(el, "overflow")) === true && /(BODY)/i.test(el.nodeName) === false ){
            if (stack.clip){
                stack.clip = clipBounds(stack.clip, bounds);
            }else{
                stack.clip = bounds;
            }
        }

        stackLength =  zindex.children.push(stack);

        ctx = zindex.children[stackLength-1].ctx;

        ctx.setVariable("globalAlpha", stack.opacity);

        // draw element borders
        borders = renderBorders(el, ctx, bounds);
        stack.borders = borders;

        // let's modify clip area for child elements, so borders dont get overwritten

        /*
    if (stack.clip){
        stack.clip.width = stack.clip.width-(borders[1].width);
        stack.clip.height = stack.clip.height-(borders[2].width);
    }
     */
        if (ignoreElementsRegExp.test(el.nodeName) && options.iframeDefault !== "transparent"){
            if (options.iframeDefault === "default"){
                bgcolor = "#efefef";
            }else{
                bgcolor = options.iframeDefault;
            }
        }

        // draw base element bgcolor

        bgbounds = {
            left: x + borders[3].width,
            top: y + borders[0].width,
            width: w - (borders[1].width + borders[3].width),
            height: h - (borders[0].width + borders[2].width)
        };

        //if (this.withinBounds(stack.clip,bgbounds)){

        if (stack.clip){
            bgbounds = clipBounds(bgbounds, stack.clip);

        //}

        }

        if (bgbounds.height > 0 && bgbounds.width > 0){
            renderRect(
                ctx,
                bgbounds.left,
                bgbounds.top,
                bgbounds.width,
                bgbounds.height,
                bgcolor
                );

            renderBackground(el, bgbounds, ctx);
        }

        switch(el.nodeName){
            case "IMG":
                imgSrc = el.getAttribute('src');
                image = loadImage(imgSrc);
                if (image){

                    paddingLeft = getCSS(el, 'paddingLeft', true);
                    paddingTop = getCSS(el, 'paddingTop', true);
                    paddingRight = getCSS(el, 'paddingRight', true);
                    paddingBottom = getCSS(el, 'paddingBottom', true);

                    renderImage(
                        ctx,
                        image,
                        0, //sx
                        0, //sy
                        image.width, //sw
                        image.height, //sh
                        x + paddingLeft + borders[3].width, //dx
                        y + paddingTop + borders[0].width, // dy
                        bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight), //dw
                        bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom) //dh
                        );

                }else{
                    html2canvas.log("html2canvas: Error loading <img>:" + imgSrc);
                }
                break;
            case "INPUT":
                // TODO add all relevant type's, i.e. HTML5 new stuff
                // todo add support for placeholder attribute for browsers which support it
                if (/^(text|url|email|submit|button|reset)$/.test(el.type) && el.value.length > 0){

                    renderFormValue(el, bounds, stack);

                /*
                 this just doesn't work well enough

                this.newText(el,{
                    nodeValue:el.value,
                    splitText: function(){
                        return this;
                    },
                    formValue:true
                },stack);
                 */
                }
                break;
            case "TEXTAREA":
                if (el.value.length > 0){
                    renderFormValue(el, bounds, stack);
                }
                break;
            case "SELECT":
                if (el.options.length > 0){
                    renderFormValue(el, bounds, stack);
                }
                break;
            case "LI":
                renderListItem(el, stack, bgbounds);
                break;
            case "CANVAS":
                paddingLeft = getCSS(el, 'paddingLeft', true);
                paddingTop = getCSS(el, 'paddingTop', true);
                paddingRight = getCSS(el, 'paddingRight', true);
                paddingBottom = getCSS(el, 'paddingBottom', true);
                renderImage(
                    ctx,
                    el,
                    0, //sx
                    0, //sy
                    el.width, //sw
                    el.height, //sh
                    x + paddingLeft + borders[3].width, //dx
                    y + paddingTop + borders[0].width, // dy
                    bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight), //dw
                    bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom) //dh
                );
                break;
        }

        return zindex.children[stackLength - 1];
    }

    function parseElement (el, stack) {

        // skip hidden elements and their children
        if (getCSS(el, 'display') !== "none" && getCSS(el, 'visibility') !== "hidden") {

            stack = renderElement(el, stack) || stack;

            ctx = stack.ctx;

            if ( !ignoreElementsRegExp.test( el.nodeName ) ) {
                var elementChildren = html2canvas.Util.Children( el ),
                i,
                node,
                childrenLen;
                for (i = 0, childrenLen = elementChildren.length; i < childrenLen; i+=1) {
                    node = elementChildren[i];

                    if ( node.nodeType === 1 ) {
                        parseElement(node, stack);
                    }else if ( node.nodeType === 3 ) {
                        renderText(el, node, stack);
                    }

                }

            }
        }
    }

    stack = renderElement(element);

    // parse every child element
    for (i = 0, children = element.children, childrenLen = children.length; i < childrenLen; i+=1){
        parseElement(children[i], stack);
    }

    return stack;

};

html2canvas.zContext = function(zindex) {
    return {
        zindex: zindex,
        children: []
    };
};


text:
import os.path
import logging
from PyQt4 import Qt, QtCore
from collections import OrderedDict
from lttngc import model, utils, features
from lttngc.about_dialog import QLttngcAboutDialog
from lttngc.session_btn import QLttngcSessionButton
from lttngc.filter_btns_layout import QLttngcFilterButtonsLayout
from lttngc.domain_sort_filter_proxy_model import QLttngcDomainSortFilterProxyModel
from lttngc.channels_list_model import QLttngcChannelsListModel
from lttngc.events_list_model import QLttngcEventsListModel

class QLttngcMainWindow(Qt.QMainWindow, utils.QtUiLoad):
    _UI_NAME = 'main'
    selected_session_changed = QtCore.pyqtSignal()
    session_button_middle_clicked = QtCore.pyqtSignal(object)

    def __init__(self, features):
        super().__init__()
        self._features = features
        self._load_icons()
        self._setup_model()
        self._setup_ui()
        self._setup_list_models()
        self._setup_dialogs()
        self._setup_actions()
        self._setup_signals()
        self.clear_lists()

    def center_screen(self):
        desktop_widget = Qt.QDesktopWidget()
        primary_screen = desktop_widget.primaryScreen()
        screen_w = desktop_widget.screen(primary_screen).width()
        screen_h = desktop_widget.screen(primary_screen).height()
        self.setGeometry(screen_w / 2 - self.width() / 2,
                         screen_h / 2 - self.height() / 2,
                         self.width(), self.height())

    @staticmethod
    def _create_pseudo_channel(name, domain):
        channel = model.Channel(name, domain, True, None, [])
        channel.is_pseudo = True

        return channel

    def _setup_model(self):
        self._session_buttons = {}
        self._selected_session_name = None
        self._channels_list_model = QLttngcChannelsListModel(self._active_icon,
                                                             self._inactive_icon)
        self._events_list_model = QLttngcEventsListModel(self._active_icon,
                                                         self._inactive_icon)
        self._pseudo_channels = {}
        self._pseudo_channel_jul = self._create_pseudo_channel('java.util.logging pseudo-channel',
                                                               model.Domain.JUL)
        self._pseudo_channel_log4j = self._create_pseudo_channel('log4j 1.2 pseudo-channel',
                                                                 model.Domain.LOG4J)
        self._pseudo_channels[model.Domain.JUL] = self._pseudo_channel_jul
        self._pseudo_channels[model.Domain.LOG4J] = self._pseudo_channel_log4j

        if features.Feature.PYTHON_DOMAIN in self._features:
            self._pseudo_channel_python = self._create_pseudo_channel('Python pseudo-channel',
                                                                      model.Domain.PYTHON)
            self._pseudo_channels[model.Domain.PYTHON] = self._pseudo_channel_python

        self._fully_disabled = False

    def _load_icons(self):
        self._play_icon = utils.get_qicon('play')
        self._stop_icon = utils.get_qicon('stop')
        self._active_icon = utils.get_qicon('active')
        self._inactive_icon = utils.get_qicon('inactive')

    def _setup_icons(self):
        actions_icons = [
            (self._action_load, 'load'),
            (self._action_save, 'save'),
            (self._action_quit, 'quit'),
            (self._action_add_session, 'add'),
            (self._action_remove_session, 'remove'),
            (self._action_remove_all_sessions, 'explosion'),
            (self._action_toggle_tracing, 'play'),
            (self._action_add_channel, 'add'),
            (self._action_attach_context, 'attach'),
            (self._action_enable_channels, 'enable'),
            (self._action_disable_channels, 'disable'),
            (self._action_add_events, 'add'),
            (self._action_enable_events, 'enable'),
            (self._action_disable_events, 'disable'),
            (self._action_show_sessions, 'sessions'),
            (self._action_show_channels, 'channels'),
            (self._action_show_events, 'events'),
            (self._action_show_object_infos, 'infos'),
            (self._action_show_last_operation, 'terminal'),
            (self._action_show_filters, 'filter'),
            (self._action_auto_refresh, 'auto-refresh'),
            (self._action_refresh, 'refresh'),
            (self._action_about, 'about'),
            (self._action_goto_lttng_org, 'lttng'),
        ]

        for pair in actions_icons:
            icon = utils.get_qicon(pair[1])
            pair[0].setIcon(icon)

        buttons_icons = [
            (self._add_session_btn, 'add'),
            (self._add_channel_btn, 'add'),
            (self._attach_context_btn, 'attach'),
            (self._enable_channels_btn, 'enable'),
            (self._disable_channels_btn, 'disable'),
            (self._add_events_btn, 'add'),
            (self._enable_events_btn, 'enable'),
            (self._disable_events_btn, 'disable'),
        ]

        for pair in buttons_icons:
            icon = utils.get_qicon(pair[1])
            pair[0].setIcon(icon)
            pair[0].setIconSize(Qt.QSize(16, 16))

        self.setWindowIcon(utils.get_qicon('lttng'))

    def _setup_dialogs(self):
        self._about_dialog = QLttngcAboutDialog()

    def _setup_filter_btns(self):
        # channels
        domains = [
            model.Domain.KERNEL,
            model.Domain.USER,
            model.Domain.JUL,
            model.Domain.LOG4J,
        ]

        if features.Feature.PYTHON_DOMAIN in self._features:
            domains.append(model.Domain.PYTHON)

        self._channel_filter_btns_layout = QLttngcFilterButtonsLayout(domains, 'channels')
        self._channel_filter_btns_layout.button_clicked.connect(self._channel_filter_btn_clicked)
        self._channels_box.layout().insertLayout(0, self._channel_filter_btns_layout)
        self._channel_filter_btns_layout.set_buttons_visible(False)

        # events
        self._event_filter_btns_layout = QLttngcFilterButtonsLayout(domains, 'events')
        self._event_filter_btns_layout.button_clicked.connect(self._event_filter_btn_clicked)
        self._events_box.layout().insertLayout(0, self._event_filter_btns_layout)
        self._event_filter_btns_layout.set_buttons_visible(False)

    def _setup_ui(self):
        self._load_ui()
        self._setup_icons()
        self._setup_filter_btns()
        self._base_title = 'lttngc'
        self._object_infos_box.hide()
        self._last_operation_dock.hide()

    def _create_proxy_model(self, src_model, list_view):
        proxy_model = QLttngcDomainSortFilterProxyModel()
        proxy_model.setSourceModel(src_model)
        proxy_model.enable_domain(model.Domain.KERNEL, True)
        proxy_model.enable_domain(model.Domain.USER, True)
        proxy_model.enable_domain(model.Domain.JUL, True)
        proxy_model.enable_domain(model.Domain.LOG4J, True)

        if features.Feature.PYTHON_DOMAIN in self._features:
            proxy_model.enable_domain(model.Domain.PYTHON, True)

        list_view.setModel(proxy_model)

        return proxy_model

    def _setup_list_models(self):
        # channels
        proxy_model = self._create_proxy_model(self._channels_list_model,
                                               self._channels_list)
        self._channels_proxy_model = proxy_model

        # events
        proxy_model = self._create_proxy_model(self._events_list_model,
                                               self._events_list)
        self._events_proxy_model = proxy_model

    def _goto_lttng_org(self):
        utils.goto_url('http://lttng.org/')

    def _show_about_dialog(self):
        pos = self.pos()
        pos.setX(pos.x() + 40)
        pos.setY(pos.y() + 40)
        self._about_dialog.show_move(pos)

    def _setup_actions(self):
        self._action_goto_lttng_org.triggered.connect(self._goto_lttng_org)
        self._action_about.triggered.connect(self._show_about_dialog)

    def _channel_filter_btn_clicked(self, btn, checked):
        domain = btn.domain
        self._channels_proxy_model.enable_domain(domain, checked)
        self._update_view_from_model()

    def _event_filter_btn_clicked(self, btn, checked):
        domain = btn.domain
        self._events_proxy_model.enable_domain(domain, checked)
        self._update_view_from_model()

    def _setup_signals(self):
        # selection changed
        channels_selection_model = self._channels_list.selectionModel()
        channels_selection_model.selectionChanged.connect(self._channels_selection_changed)
        events_selection_model = self._events_list.selectionModel()
        events_selection_model.selectionChanged.connect(self._events_selection_changed)

        # click (lists)
        self._channels_list.clicked.connect(self._channels_list_clicked)
        self._events_list.clicked.connect(self._events_list_clicked)

        # show filter buttons
        self._action_show_filters.triggered.connect(self._show_channel_filters_triggered)
        self._action_show_filters.triggered.connect(self._show_event_filters_triggered)

        # support closing a dock from the dock itself
        self._last_operation_dock.visibilityChanged.connect(self._last_op_visibility_changed)

    def _last_op_visibility_changed(self, is_visible):
        self._action_show_last_operation.setChecked(is_visible)

    def _show_channel_filters_triggered(self, checked):
        self._channel_filter_btns_layout.set_buttons_visible(checked)

    def _show_event_filters_triggered(self, checked):
        self._event_filter_btns_layout.set_buttons_visible(checked)

    def get_channel_at_row(self, row):
        # get channel object
        index = self._channels_proxy_model.index(row, 0)
        src_index = self._channels_proxy_model.mapToSource(index)
        item = self._channels_list_model.get_item_at_row(src_index.row())

        return item.obj

    def get_event_at_row(self, row):
        # get event object
        index = self._events_proxy_model.index(row, 0)
        src_index = self._events_proxy_model.mapToSource(index)
        item = self._events_list_model.get_item_at_row(src_index.row())

        return item.obj

    def _event_clicked(self, index):
        # get event object
        event = self.get_event_at_row(index.row())
        self._set_event_infos(event)

    def _set_channel_infos(self, channel):
        # update object infos
        obj_name = 'Channel'

        if channel.is_pseudo:
            obj_name = 'Pseudo-channel'

        domain_name = model.DOMAIN_NAMES[channel.domain]
        text = '{}: {} ({} domain)'.format(obj_name,
                                                         channel.name,
                                                         domain_name)

        if channel.is_pseudo:
            self._object_infos_lbl.setText(text)
            return

        text += '
'
        attr = channel.attributes
        mode = model.CHANNEL_MODE_NAMES[attr.mode]
        output_type = model.CHANNEL_OUTPUT_TYPE_NAMES[attr.output_type]
        buffer_scheme = model.CHANNEL_BUFFER_SCHEME_NAMES[attr.buffer_scheme]
        fmt = 'Mode: {}    Output type: {}    Buffering: {}
'
        text += fmt.format(mode, output_type, buffer_scheme)
        subbuf_size = utils.bytes_to_human(attr.subbuf_size)

        if attr.tracefile_size <= 0:
            tracefile = 'unlimited size'
        else:
            tracefile_size = utils.bytes_to_human(attr.tracefile_size)
            tracefile = '{} x {}'.format(attr.tracefile_count, tracefile_size)

        fmt = 'Sub-buffers: {} x {}    Trace files: {}
'
        text += fmt.format(attr.subbuf_count, subbuf_size, tracefile)
        switch_timer = attr.switch_timer_interval

        if switch_timer == 0:
            switch = 'stopped'
        else:
            switch = '{:.6f} s'.format(switch_timer)

        read_timer = attr.read_timer_interval

        if read_timer == 0:
            read = 'stopped'
        else:
            read = '{:.6f} s'.format(read_timer)

        fmt = 'Switch timer: {}    Read timer: {}'
        text += fmt.format(switch, read)
        self._object_infos_lbl.setText(text)

    def _set_event_infos(self, event):
        def bool_to_yes_no(b):
            return 'yes' if b else 'no'

        # update object infos
        channel_name = event.channel.name
        domain_name = model.DOMAIN_NAMES[event.channel.domain]
        fmt = 'Event: {} ({}, {} domain, channel {})
'
        event_type_name = model.EVENT_TYPE_NAMES[event.source.type]
        text = fmt.format(event.source.name, event_type_name, domain_name,
                          event.channel.name)
        ll = 'none'

        if event.log_level is not None and event.log_level_function != model.LogLevelFunction.ANY:
            if event.log_level_function == model.LogLevelFunction.LT_EQ:
                func = 'lesser than or equal to'
            else:
                func = 'equal to'

            ll = '{} {}'.format(func, event.log_level)

        text += 'Log level: {}'.format(ll)
        has_filter = bool_to_yes_no(event.has_filter)
        text += '    Has filter?: {}'.format(has_filter)

        if event.has_exclusions is not None:
            has_exclusions = bool_to_yes_no(event.has_exclusions)
            text += '    Has exclusions?: {}'.format(has_exclusions)

        self._object_infos_lbl.setText(text)

    def _session_button_clicked(self, checked):
        session_button = self.sender()
        session_summary = session_button.session_summary

        if self._selected_session_name == session_summary.name and not checked:
            # cancel toggling
            session_button.setChecked(True)
            return

        # uncheck current one
        self.set_selected_session_name(session_summary.name)

        # notify
        self.selected_session_changed.emit()

    def _update_toggle_tracing_btn(self):
        selected_session_btn = self._get_selected_session_button()

        if not selected_session_btn:
            self._action_toggle_tracing.setEnabled(False)
            return

        if selected_session_btn.session_summary.is_active:
            self._action_toggle_tracing.setText('&Stop tracing')
            self._action_toggle_tracing.setToolTip('Stop tracing')
            self._action_toggle_tracing.setStatusTip('Stop tracing')
            self._action_toggle_tracing.setIcon(self._stop_icon)
        else:
            self._action_toggle_tracing.setText('&Start tracing')
            self._action_toggle_tracing.setToolTip('Start tracing')
            self._action_toggle_tracing.setStatusTip('Start tracing')
            self._action_toggle_tracing.setIcon(self._play_icon)

        self._action_toggle_tracing.setEnabled(True)

    def _update_selected_session_button(self):
        for session_button in self._session_buttons.values():
            session_summary = session_button.session_summary

            if session_summary.name == self._selected_session_name:
                if not session_button.isChecked():
                    session_button.setChecked(True)
            else:
                if session_button.isChecked():
                    session_button.setChecked(False)

    def _update_remove_session_btn(self):
        selected_session_btn = self._get_selected_session_button()
        is_enabled = bool(selected_session_btn)
        self._action_remove_session.setEnabled(is_enabled)
        self._action_remove_all_sessions.setEnabled(is_enabled)

    def _sort_lists(self):
        self._channels_proxy_model.sort(0)
        self._events_proxy_model.sort(0)

    def _channels_list_clicked(self, index):
        channel = self.get_channel_at_row(index.row())
        self._set_channel_infos(channel)

    def _events_list_clicked(self, index):
        event = self.get_event_at_row(index.row())
        self._set_event_infos(event)

    def _events_selection_changed(self, selected, deselected):
        events = self.get_selected_events()

        if len(events) == 1:
            self._set_event_infos(events[0])

        self._update_view_from_model()

    def _channels_selection_changed(self, selected, deselected):
        channels = self.get_selected_channels()

        if len(channels) == 1:
            self._set_channel_infos(channels[0])

        self._clear_events_list()
        self._update_events_list_from_selected_channels()
        self._update_view_from_model()

    def _update_widgets_enabled(self):
        # one session?
        one_session = bool(self._session_buttons)
        one_session = one_session and not self._fully_disabled

        # one channel selected?
        channels = self.get_selected_channels()
        one_channel = bool(channels)
        one_channel = one_channel and not self._fully_disabled

        # selected channels are all pseudo-channels?
        all_pseudo = True

        for channel in channels:
            all_pseudo = all_pseudo and channel.is_pseudo

        # selected channels have the same domain?
        same_domain = False
        selected_domains = set()

        for channel in channels:
            selected_domains.add(channel.domain)

        if len(selected_domains) == 1:
            same_domain = True

        same_domain = same_domain and not self._fully_disabled

        # one event selected?
        one_event = bool(self.get_selected_events())
        one_event = one_event and not self._fully_disabled

        # enable/disable buttons and actions
        if not one_session:
            self._clear_lists_no_update()

        self._add_session_btn.setEnabled(True)
        self._action_load.setEnabled(not self._fully_disabled)
        self._action_add_session.setEnabled(True)
        self._action_remove_session.setEnabled(one_session)
        self._action_remove_all_sessions.setEnabled(one_session)
        self._add_channel_btn.setEnabled(one_session)
        self._action_add_channel.setEnabled(one_session)
        self._action_save.setEnabled(one_session)
        self._menu_session.setEnabled(not self._fully_disabled)
        self._menu_channel.setEnabled(one_session)
        self._channels_box.setEnabled(one_session)
        en_dis_channels = one_channel and not all_pseudo
        self._enable_channels_btn.setEnabled(en_dis_channels)
        self._disable_channels_btn.setEnabled(en_dis_channels)
        self._attach_context_btn.setEnabled(en_dis_channels)
        self._add_events_btn.setEnabled(same_domain)
        self._action_enable_channels.setEnabled(en_dis_channels)
        self._action_disable_channels.setEnabled(en_dis_channels)
        self._action_attach_context.setEnabled(en_dis_channels)
        self._action_add_events.setEnabled(same_domain)
        self._menu_event.setEnabled(one_channel)
        self._events_box.setEnabled(one_channel)
        self._enable_events_btn.setEnabled(one_event)
        self._disable_events_btn.setEnabled(one_event)
        self._action_enable_events.setEnabled(one_event)
        self._action_disable_events.setEnabled(one_event)

    def _update_title(self):
        sel_session_summary = self.get_selected_session_summary()

        if sel_session_summary is None:
            self.setWindowTitle(self._base_title)
            return

        title = '{} [{}]'.format(self._base_title, sel_session_summary.name)
        self.setWindowTitle(title)

    def _update_view_from_model(self):
        self._update_selected_session_button()
        self._update_toggle_tracing_btn()
        self._update_remove_session_btn()
        self._sort_lists()
        self._update_widgets_enabled()
        self._update_title()

    def _add_session_button(self, session_summary):
        btn = QLttngcSessionButton(session_summary, self._active_icon,
                             self._inactive_icon)
        insert_pos = self._session_layout.count() - 2
        self._session_layout.insertWidget(insert_pos, btn)
        self._session_buttons[session_summary.name] = btn
        btn.clicked.connect(self._session_button_clicked)
        btn.middle_clicked.connect(self.session_button_middle_clicked)

        return btn

    def _get_session_button(self, sname):
        if sname in self._session_buttons:
            return self._session_buttons[sname]

    def _remove_session_button(self, sname):
        self._session_buttons[sname].setParent(None)
        del self._session_buttons[sname]

    def update_session_buttons_from_summaries(self, session_summaries):
        known_snames = []

        # update/add
        for summary in session_summaries.values():
            sname = summary.name

            # does not exist?
            btn = self._get_session_button(sname)

            if btn is None:
                # create it
                btn = self._add_session_button(summary)

            # update session summary
            btn.session_summary = summary

            # mark it as known
            known_snames.append(sname)

        # now remove unknown ones
        to_remove = []

        for sname, session_btn in self._session_buttons.items():
            if sname not in known_snames:
                to_remove.append(sname)

        for sname in to_remove:
            self._remove_session_button(sname)

        # remove current selected session if it was removed
        if self._selected_session_name not in self._session_buttons:
            self._selected_session_name = None

        self._update_view_from_model()

    def _get_selected_session_button(self):
        if self._selected_session_name is None:
            return

        return self._session_buttons[self._selected_session_name]

    def set_selected_session_name(self, sname):
        if sname not in self._session_buttons:
            return

        if self._selected_session_name == sname:
            return

        self._selected_session_name = sname
        self._channels_list_model.set_channels(list(self._pseudo_channels.values()))
        self._update_view_from_model()

    def get_session_names(self):
        return list(self._session_buttons.keys())

    def get_selected_session_summary(self):
        selected_button = self._get_selected_session_button()

        if not selected_button:
            return

        return selected_button.session_summary

    def _update_events_list_from_selected_channels(self):
        channels = self.get_selected_channels()
        events = []

        for channel in channels:
            for event in channel.events:
                events.append(event)

        self._events_list_model.set_events(events)

    def update_lists_from_channels(self, channels):
        # add empty pseudo-channels if they're missing
        domains = set([
            model.Domain.JUL,
            model.Domain.LOG4J,
        ])

        if features.Feature.PYTHON_DOMAIN in self._features:
            domains.add(model.Domain.PYTHON)

        for channel in channels:
            if channel.domain in domains:
                domains.remove(channel.domain)

        for domain in domains:
            pseudo_channel = self._pseudo_channels[domain]
            channels.append(pseudo_channel)

        self._channels_list_model.set_channels(channels)
        self._update_events_list_from_selected_channels()
        self._update_view_from_model()

    def get_current_channels(self):
        return self._channels_list_model.objects

    def get_current_events(self):
        return self._events_list_model.objects

    def _clear_events_list(self):
        self._events_list.selectionModel().reset()
        self._events_list_model.set_events([])

    def _clear_channels_list(self):
        self._channels_list.selectionModel().reset()
        self._channels_list_model.set_channels(list(self._pseudo_channels.values()))

    def _clear_lists_no_update(self):
        self._clear_events_list()
        self._clear_channels_list()

    def clear_lists(self):
        self._clear_lists_no_update()
        self._update_view_from_model()

    @staticmethod
    def _get_selected_objects(object_list, get_at_row):
        model_index_list = object_list.selectedIndexes()
        objects = []

        for index in model_index_list:
            obj = get_at_row(index.row())
            objects.append(obj)

        return objects

    def get_selected_channels(self):
        return self._get_selected_objects(self._channels_list,
                                          self.get_channel_at_row)

    def get_selected_events(self):
        return self._get_selected_objects(self._events_list,
                                          self.get_event_at_row)

    def full_disable(self):
        to_remove = list(self._session_buttons.keys())

        for sname in to_remove:
            self._remove_session_button(sname)

        self._selected_session_name = None
        self._fully_disabled = True
        self._update_view_from_model()

    def full_enable(self):
        self._fully_disabled = False
        self._update_view_from_model()

redpajama_set_name: RedPajamaGithub


text:
<?php include 'includes/header.php' ?>
<div id="page-wrapper">

     <?php if (isset($_GET['source'])) {
                        //put the _GET superglobal to a variable
                        $source = $_GET['source'];
                    }else{
                        $source = '';
                    }

                    switch ($source) {
                        case 'add_post':
                            include "includes/add_comments.php";
                            break;

                        case 'edit_posts':
                            include "includes/edit_comments.php";
                            break;

                        default:
                            include "includes/view_comments.php";
                            break;
                    }
                    ?>
</div>
<?php include 'includes/footer.php' ?>
</body>
</html>


text:
package controllers

import helpers._
import models._
import models.misc._
import models.sys._
import play.api.data.Form
import play.api.data.Forms._
import play.api.i18n._
import play.api.mvc._
import security._
import services._
import views._

import scala.concurrent.Future

/**
 * @author zepeng.li@gmail.com
 */
class PasswordResetCtrl(
  implicit
  val basicPlayApi: BasicPlayApi,
  val mailService: MailService,
  val _groups: Groups,
  val _expirableLinks: ExpirableLinks,
  val _emailTemplates: EmailTemplates,
  val _sysConfig: SysConfigs
) extends Controller
  with PasswordResetCtrlCNamed
  with CanonicalNameBasedMessages
  with BasicPlayComponents
  with DefaultPlayExecutor
  with UsersComponents
  with AuthenticateBySessionComponents
  with MaybeUserActionComponents
  with ExceptionHandlers
  with InternalGroupsComponents
  with AppDomainComponents
  with I18nLoggingComponents
  with SystemAccounts
  with I18nSupport {

  val emailFM = Form[EmailAddress](
    single("email" -> EmailAddress.constrained)
  )

  val resetFM = Form[Password.Confirmation](
    mapping(
      "password.original" -> Password.constrained,
      "password.confirmation" -> text
    )(Password.Confirmation.apply)(Password.Confirmation.unapply)
      .verifying("password.not.confirmed", _.isConfirmed)
  )

  def nnew(email: Option[EmailAddress]) =
    MaybeUserAction().apply { implicit req =>
      Ok {
        val filled = emailFM.fill(email.getOrElse(EmailAddress.empty))
        html.password_reset.nnew(filled)
      }
    }

  /**
   * TODO count access, if someone try to enumerate our users, then ban
   *
   * @return
   */
  def create =
    MaybeUserAction().async { implicit req =>
      emailFM.bindFromRequest().fold(
        failure => Future.successful {
          onError(emailFM, "email.not.found")
        },
        success => (for {
          user <- _users.find(success)
          link <- _expirableLinks.save(user.id)
          tmpl <- getEmailTemplate(s"$basicName.email1")
        } yield (user, link.id, tmpl)).map { case (user, id, tmpl) =>
          mailService.sendTo(user)("noreply", tmpl, Map("link" -> id))
          Ok(html.password_reset.sent())
        }.recover {
          case e: User.NotFound          =>
            onError(emailFM, "email.not.found")
          case e: EmailTemplate.NotFound =>
            Logger.warn(e.reason, e)
            onError(emailFM, "email.not.found")
        }

      )
    }

  /**
   * Show a form that user can enter new password, only if
   * the user got a valid password reset link in his mail inbox.
   */
  def show(id: String) =
    MaybeUserAction().async { implicit req =>
      _expirableLinks.find(id).map { ln =>
        Ok(html.password_reset.show(id)(resetFM))
      }.recover {
        case e: ExpirableLink.NotFound =>
          onError(emailFM, "invalid.reset.link")
      }
    }

  def save(id: String) =
    MaybeUserAction().async { implicit req =>
      val bound = resetFM.bindFromRequest()
      bound.fold(
        failure => Future.successful {
          BadRequest {
            html.password_reset.show(id) {
              if (bound.hasGlobalErrors) bound
              else bound.withGlobalError(msg_key("failed"))
            }
          }
        },
        success => (for {
          link <- _expirableLinks.find(id)
          ____ <- _expirableLinks.remove(id)
          _uid <- Future(link.target_id)
          user <- _users.find(_uid)
          ____ <- user.updatePassword(success.original)
          tmpl <- getEmailTemplate(s"$basicName.email2")
        } yield (user, tmpl)).map { case (user, tmpl) =>
          mailService.sendTo(user)("support", tmpl)
          Redirect(routes.SessionsCtrl.nnew()).flashing(
            AlertLevel.Info -> message("password.changed")
          )
        }.recover {
          case e: ExpirableLink.NotFound => onError(emailFM, "invalid.reset.link")
          case e: Throwable              => onError(emailFM, "invalid.reset.link")
        }
      )
    }

  private def getEmailTemplate(key: String)(
    implicit messages: Messages
  ): Future[EmailTemplate] = _emailTemplates
    .getOrElseUpdate(key, messages.lang)(_systemAccount(PasswordResetCtrl))

  private def onError(bound: Form[EmailAddress], key: String)(
    implicit req: MaybeUserRequest[_]
  ): Result = NotFound {
    html.password_reset.nnew {
      bound.withGlobalError(msg_key(key))
    }
  }
}

object PasswordResetCtrl
  extends PasswordResetCtrlCNamed
    with ViewMessages

trait PasswordResetCtrlCNamed extends CanonicalNamed {

  val basicName = "password_reset"
}


text:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module SD.Utility.MovingAverage.Tests (tests) where

import Data.List (foldl')
import Data.Maybe (fromJust, isNothing)
import qualified SD.Utility.MovingAverage as MA
import Test.QuickCheck (Positive (Positive))
import Test.QuickCheck.Monadic (monadicIO, pick)
import Test.Tasty (TestTree)
import Test.Tasty.QuickCheck (Arbitrary, arbitrary, testProperty)

tests :: [TestTree]
tests =
  [ testMovingAvg @Double 1e-8 1e-8 "movingAvg (Double)",
    testMovingAvg @Float 1e-2 1e-2 "movingAvg (Float)",
    testMovingAvg @Rational 1e-800 1e-800 "movingAvg (Rational)"
  ]

testMovingAvg ::
  forall f.
  (Arbitrary f, Ord f, Show f, Fractional f) =>
  f ->
  f ->
  String ->
  TestTree
testMovingAvg eps0 eps1 desc = testProperty desc $
  monadicIO $ do
    Positive (movingAvgCount :: Int) <- pick arbitrary
    let emptyMovingAvg = fromJust $ MA.empty movingAvgCount
    elements :: [f] <- pick arbitrary
    let movingAvg = foldl' (flip MA.append) emptyMovingAvg elements
    let elemsLen = length elements
    case elemsLen of
      n | n == 0 || n < movingAvgCount -> return . isNothing $ MA.lookup movingAvg
      _ ->
        return $
          areClose
            eps0
            eps1
            (fromJust $ MA.lookup movingAvg)
            (sum (lastElems movingAvgCount elements) / fromIntegral movingAvgCount)

areClose :: (Ord f, Fractional f) => f -> f -> f -> f -> Bool
areClose eps0 eps1 x y =
  let d = abs (x - y)
   in (x == 0 && d < eps0)
        || (y == 0 && d < eps0)
        || (x /= 0 && y /= 0 && d / x < eps1 && d / y < eps1)

lastElems :: Int -> [a] -> [a]
lastElems n l = drop (length l - n) l


text:
'use strict'

const {
  kReplyIsError,
  kReplyHijacked
} = require('./symbols')

function wrapThenable (thenable, reply) {
  thenable.then(function (payload) {
    if (reply[kReplyHijacked] === true) {
      return
    }

    // this is for async functions that
    // are using reply.send directly
    if (payload !== undefined || reply.sent === false) {
      // we use a try-catch internally to avoid adding a catch to another
      // promise, increase promise perf by 10%
      try {
        reply.send(payload)
      } catch (err) {
        reply[kReplyIsError] = true
        reply.send(err)
      }
    }
  }, function (err) {
    if (reply.sent === true) {
      reply.log.error({ err }, 'Promise errored, but reply.sent = true was set')
      return
    }

    reply[kReplyIsError] = true
    reply.send(err)
  })
}

module.exports = wrapThenable


text:
require 'spec_helper'

describe CapBlueGreenDeploy::Tasks::Deploy do

  class TestClass
    include CapBlueGreenDeploy::Tasks::Deploy
  end

  subject do
    TestClass.new
  end

  before do
    @config = double("config")
    allow(@config).to receive(:load) { |&arg| arg.call }
  end

  describe ".task_load" do
    let :subject do
      CapBlueGreenDeploy::Tasks::Deploy
    end

    before do
      allow(subject).to receive(:namespace)
      allow(subject).to receive(:desc)
      allow(subject).to receive(:task)
      allow(subject).to receive(:after)
    end

    context "capistrano blue green pre task" do
      before do
        expect(subject).to receive(:namespace).with(:deploy) { |&arg| arg.call }
        expect(subject).to receive(:namespace).with(:blue_green) { |&arg| arg.call }
      end

      it "should define pre task description" do
        expect(subject).to receive(:desc).with("Deploy your project to pre environment")
        subject.task_load(@config)
      end

      it "should set pre task action" do
        expect(subject).to receive(:task).with(:pre, roles: :app, except: { no_release: true })
        subject.task_load(@config)
      end

      it "should create callback to run capistrano deploy after pre action" do
        expect(subject).to receive(:after).with("deploy:blue_green:pre", "deploy")
        subject.task_load(@config)
      end
    end
  end
end


text:
package com.ThirtyNineEighty.Base.Worlds;

import com.ThirtyNineEighty.Base.Map.IMap;
import com.ThirtyNineEighty.Base.Objects.WorldObject;
import com.ThirtyNineEighty.Base.BindableHost;

import java.util.List;

public abstract class BaseWorld
  extends BindableHost<WorldObject>
  implements IWorld
{
  private static final long serialVersionUID = 1L;

  protected WorldObject<?, ?> player;

  @Override
  public IMap getMap()
  {
    return null;
  }

  @Override
  public void getObjects(List<WorldObject<?, ?>> filled)
  {
    synchronized (objects)
    {
      for (WorldObject<?, ?> object : objects)
        filled.add(object);
    }
  }

  @Override
  public WorldObject<?, ?> getPlayer()
  {
    return player;
  }

  @Override
  public boolean needSave()
  {
    return false;
  }
}


text:
package dts

//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.
//
// Code generated by Alibaba Cloud SDK Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

import (
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
)

// DescribeConsumerChannel invokes the dts.DescribeConsumerChannel API synchronously
func (client *Client) DescribeConsumerChannel(request *DescribeConsumerChannelRequest) (response *DescribeConsumerChannelResponse, err error) {
	response = CreateDescribeConsumerChannelResponse()
	err = client.DoAction(request, response)
	return
}

// DescribeConsumerChannelWithChan invokes the dts.DescribeConsumerChannel API asynchronously
func (client *Client) DescribeConsumerChannelWithChan(request *DescribeConsumerChannelRequest) (<-chan *DescribeConsumerChannelResponse, <-chan error) {
	responseChan := make(chan *DescribeConsumerChannelResponse, 1)
	errChan := make(chan error, 1)
	err := client.AddAsyncTask(func() {
		defer close(responseChan)
		defer close(errChan)
		response, err := client.DescribeConsumerChannel(request)
		if err != nil {
			errChan <- err
		} else {
			responseChan <- response
		}
	})
	if err != nil {
		errChan <- err
		close(responseChan)
		close(errChan)
	}
	return responseChan, errChan
}

// DescribeConsumerChannelWithCallback invokes the dts.DescribeConsumerChannel API asynchronously
func (client *Client) DescribeConsumerChannelWithCallback(request *DescribeConsumerChannelRequest, callback func(response *DescribeConsumerChannelResponse, err error)) <-chan int {
	result := make(chan int, 1)
	err := client.AddAsyncTask(func() {
		var response *DescribeConsumerChannelResponse
		var err error
		defer close(result)
		response, err = client.DescribeConsumerChannel(request)
		callback(response, err)
		result <- 1
	})
	if err != nil {
		defer close(result)
		callback(nil, err)
		result <- 0
	}
	return result
}

// DescribeConsumerChannelRequest is the request struct for api DescribeConsumerChannel
type DescribeConsumerChannelRequest struct {
	*requests.RpcRequest
	PageNumber      requests.Integer `position:"Query" name:"PageNumber"`
	ParentChannelId string           `position:"Query" name:"ParentChannelId"`
	PageSize        requests.Integer `position:"Query" name:"PageSize"`
	DtsJobId        string           `position:"Query" name:"DtsJobId"`
	DtsInstanceId   string           `position:"Query" name:"DtsInstanceId"`
}

// DescribeConsumerChannelResponse is the response struct for api DescribeConsumerChannel
type DescribeConsumerChannelResponse struct {
	*responses.BaseResponse
	HttpStatusCode   string            `json:"HttpStatusCode" xml:"HttpStatusCode"`
	RequestId        string            `json:"RequestId" xml:"RequestId"`
	ErrCode          string            `json:"ErrCode" xml:"ErrCode"`
	PageRecordCount  int               `json:"PageRecordCount" xml:"PageRecordCount"`
	Success          string            `json:"Success" xml:"Success"`
	TotalRecordCount int64             `json:"TotalRecordCount" xml:"TotalRecordCount"`
	ErrMessage       string            `json:"ErrMessage" xml:"ErrMessage"`
	PageNumber       int               `json:"PageNumber" xml:"PageNumber"`
	ConsumerChannels []ConsumerChannel `json:"ConsumerChannels" xml:"ConsumerChannels"`
}

// CreateDescribeConsumerChannelRequest creates a request to invoke DescribeConsumerChannel API
func CreateDescribeConsumerChannelRequest() (request *DescribeConsumerChannelRequest) {
	request = &DescribeConsumerChannelRequest{
		RpcRequest: &requests.RpcRequest{},
	}
	request.InitWithApiInfo("Dts", "2020-01-01", "DescribeConsumerChannel", "dts", "openAPI")
	request.Method = requests.POST
	return
}

// CreateDescribeConsumerChannelResponse creates a response to parse from DescribeConsumerChannel response
func CreateDescribeConsumerChannelResponse() (response *DescribeConsumerChannelResponse) {
	response = &DescribeConsumerChannelResponse{
		BaseResponse: &responses.BaseResponse{},
	}
	return
}


text:
@import url('~app/styles/variables.css');

.field {
  display: flex;
  flex-direction: column;
  margin-bottom: 20px;
  width: 100%;
}

.inputWithError {
  border: 1px solid #c24538 !important;
}

.inputWithWarning {
  border: 1px solid #ff8000 !important;
}

.fieldError {
  background: #c24538;
  color: var(--color-white);
  padding: 5px 10px;
  margin-top: 3px;
  border-radius: 3px;
}

.fieldWarning {
  background: #ff8000;
  color: var(--color-white);
  padding: 5px 10px;
  margin-top: 3px;
  border-radius: 3px;
}

.label {
  font-size: 18px;
}

.required {
  color: #c24538;
  font-weight: 600;
  margin-left: 2px;
}

input[type='text']:disabled {
  background-color: var(--color-mono-gray-4);
  color: var(--color-dark-mono-gray-4);
}

:global {
  /* stylelint-disable-next-line selector-class-pattern */
  .Select.is-disabled > .Select-control {
    background-color: var(--color-mono-gray-4) !important;
    color: var(--color-dark-mono-gray-4);
  }

  /* stylelint-disable-next-line selector-class-pattern */
  .Select--multi.is-disabled .Select-value-label {
    background-color: var(--color-mono-gray-4) !important;
    color: var(--color-dark-mono-gray-4);
  }

  /* stylelint-disable-next-line selector-class-pattern */
  .Select--multi.is-disabled .Select-value {
    border: none !important;
  }
}


text:
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool

from .models import CallToAction
from .settings import STYLES

class CallToActionPlugin(CMSPluginBase):
    model = CallToAction
    module = "Call to Action"
    name = "Call to Action"

    def get_render_template(self, context, instance, placeholder):
        return instance.call_to_action.style

    def render(self, context, instance, placeholder):
        context.update({
            'instance': instance, 'placeholder': placeholder,
            'call_to_action': instance.call_to_action
        })
        return context

plugin_pool.register_plugin(CallToActionPlugin)


text:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick_InputText"
        android:text="输入要写入文本" />

    <TextView
        android:id="@+id/textview_input_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="请将NFC标签靠近手机背面读取或写入文本"
        android:textColor="#F00"
        android:textSize="16sp" />

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/read_nfc_tag" />

</LinearLayout>


text:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, TouchImageViewActivity!</string>
    <string name="app_name">TouchImageView</string>

    <!-- Activities -->
    <string name="single_touchimageview">Single TouchImageView</string>
    <string name="mirror_touchimageview">Mirroring Example</string>
    <string name="viewpager_example">ViewPager Example</string>
    <string name="switch_image_example">Switch Image Example</string>
    <string name="switch_scaletype_example">Switch ScaleType Example</string>

    <string name="get_scroll_position">getScrollPosition():</string>
    <string name="get_zoomed_rect">getZoomedRect():</string>
    <string name="get_current_zoom">getCurrentZoom():</string>
    <string name="mirroring_text">All touch gestures applied to one TouchImageView will be mirrored on the other.</string>
    <string name="swipe_viewpager">Swipe left or right to test ViewPager.</string>
    <string name="switch_image_text">Click TouchImageView to cycle through image resources. Note that the zoom state is maintained.</string>
    <string name="switch_scaletype_text">Click TouchImageView to cycle through supported ScaleTypes.</string>
</resources>


text:
@interface UIView (Mock)

- (void)_shake:(int)times direction:(int)direction currentTimes:(int)current withDelta:(CGFloat)delta speed:(NSTimeInterval)interval shakeDirection:(ShakeDirection)shakeDirection completion:(void(^)())handler;

@end

SpecBegin(UITextFieldShakeTests)

__block UITextField *subject;

describe(@"shake", ^{
    it(@"should eventually call _shake:direction:currentTimes:withDelta:speed:shakeDirection:completion:", ^{
        subject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
        id mock = OCMPartialMock(subject);
        OCMExpect([mock _shake:10 direction:1 currentTimes:0 withDelta:5 speed:0.03 shakeDirection:ShakeDirectionHorizontal completion:nil]);
        [mock shake];
        OCMVerifyAll(mock);
    });
});

describe(@"shake:withDelta:", ^{
    it(@"should eventually call _shake:direction:currentTimes:withDelta:speed:shakeDirection:completion:", ^{
        subject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
        id mock = OCMPartialMock(subject);
        OCMExpect([mock _shake:10 direction:1 currentTimes:0 withDelta:5 speed:0.03 shakeDirection:ShakeDirectionHorizontal completion:nil]);
        [mock shake:10 withDelta:5];
        OCMVerifyAll(mock);
    });
});

describe(@"shake:withDelta:completion:", ^{
    it(@"should eventually call _shake:direction:currentTimes:withDelta:speed:shakeDirection:completion:", ^{
        subject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
        id mock = OCMPartialMock(subject);
        OCMExpect([mock _shake:10 direction:1 currentTimes:0 withDelta:5 speed:0.03 shakeDirection:ShakeDirectionHorizontal completion:nil]);
        [mock shake:10 withDelta:5 completion:nil];
        OCMVerify(mock);
    });

    it(@"should call the completion block", ^{
        subject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
        __block int meaningOfLife = 0;
        [subject shake:10 withDelta:5 completion:^{
            meaningOfLife = 42;
        }];
        expect(meaningOfLife).after(1).to.equal(42);
    });
});

describe(@"shake:withDelta:speed:", ^{
    it(@"should eventually call _shake:direction:currentTimes:withDelta:speed:shakeDirection:completion:", ^{
        subject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
        id mock = OCMPartialMock(subject);
        OCMExpect([mock _shake:10 direction:1 currentTimes:0 withDelta:5 speed:1 shakeDirection:ShakeDirectionHorizontal completion:nil]);
        [mock shake:10 withDelta:5 speed:1];
        OCMVerify(mock);
    });
});

describe(@"shake:withDelta:speed:completion:", ^{
    it(@"should eventually call _shake:direction:currentTimes:withDelta:speed:shakeDirection:completion:", ^{
        subject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
        id mock = OCMPartialMock(subject);
        OCMExpect([mock _shake:10 direction:1 currentTimes:0 withDelta:5 speed:1 shakeDirection:ShakeDirectionHorizontal completion:nil]);
        [mock shake:10 withDelta:5 speed:1 completion:nil];
        OCMVerify(mock);
    });

    it(@"should call the completion block", ^{
        subject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
        __block int meaningOfLife = 0;
        [subject shake:10 withDelta:5 speed:1 completion:^{
            meaningOfLife = 42;
        }];
        expect(meaningOfLife).after(1).to.equal(42);
    });
});

describe(@"shake:withDelta:speed:shakeDirection:", ^{
    it(@"should eventually call _shake:direction:currentTimes:withDelta:speed:shakeDirection:completion:", ^{
        subject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
        id mock = OCMPartialMock(subject);
        OCMExpect([mock _shake:10 direction:1 currentTimes:0 withDelta:5 speed:1 shakeDirection:ShakeDirectionVertical completion:nil]);
        [mock shake:10 withDelta:5 speed:1 shakeDirection:ShakeDirectionVertical];
        OCMVerify(mock);
    });
});

describe(@"shake:withDelta:speed:shakeDirection:completion:", ^{
    it(@"should eventually call _shake:direction:currentTimes:withDelta:speed:shakeDirection:completion:", ^{
        subject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
        id mock = OCMPartialMock(subject);
        OCMExpect([mock _shake:10 direction:1 currentTimes:0 withDelta:5 speed:1 shakeDirection:ShakeDirectionVertical completion:nil]);
        [mock shake:10 withDelta:5 speed:1 shakeDirection:ShakeDirectionVertical completion:nil];
        OCMVerify(mock);
    });

    it(@"should call the completion block", ^{
        subject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
        __block int meaningOfLife = 0;
        [subject shake:10 withDelta:5 speed:1 shakeDirection:ShakeDirectionVertical completion:^{
            meaningOfLife = 42;
        }];
        expect(meaningOfLife).after(1).to.equal(42);
    });
});

SpecEnd


text:
class JitConfigProvider
{
public:
    virtual int getIntConfigValue(
        const wchar_t* name,
        int defaultValue
        ) = 0;

    virtual int getStringConfigValue(
        const wchar_t* name,
        wchar_t* retBuffer,
        int retBufferLength
        ) = 0;
};

// Native implementation of the JIT host.
// The native implementation calls into JitConfigProvider (implemented on the managed side) to get the actual
// configuration values.
// This dance is necessary because RyuJIT calls into the JitHost as part of the process shutdown (to free up
// strings). JitHost therefore can't be implemented in managed code (because managed runtime might have
// already shut down).

class JitHost
{
    JitConfigProvider* pConfigProvider;

public:
    JitHost(JitConfigProvider* pConfigProvider)
        : pConfigProvider(pConfigProvider) { }

    virtual void* allocateMemory(size_t size, bool usePageAllocator = false)
    {
        return malloc(size);
    }

    virtual void freeMemory(void* block, bool usePageAllocator = false)
    {
        free(block);
    }

    virtual int getIntConfigValue(
        const wchar_t* name,
        int defaultValue
        )
    {
        return pConfigProvider->getIntConfigValue(name, defaultValue);
    }

    virtual const wchar_t* getStringConfigValue(
        const wchar_t* name
        )
    {
        // Find out the required length of the buffer
        int numCharacters = pConfigProvider->getStringConfigValue(name, nullptr, 0);
        if (numCharacters == 0)
            return nullptr;

        // Allocate extra char for the null terminator
        wchar_t* retBuffer = (wchar_t*)calloc(numCharacters + 1, sizeof(wchar_t));
        pConfigProvider->getStringConfigValue(name, retBuffer, numCharacters);

        return retBuffer;
    }

    virtual void freeStringConfigValue(
        wchar_t* value
        )
    {
        free(value);
    }
};

DLL_EXPORT void* __stdcall GetJitHost(JitConfigProvider* pConfigProvider)
{
    return new JitHost(pConfigProvider);
}


text:
title: js-model
category: JavaScript libraries
layout: 2017/sheet
---

### Example

```bash
Project = Model "project", ->
  @extend
    findByTitle: (title) -> ...

  @include
    markAsDone: -> ...

  # ActiveRecord::Base.include_root_in_json = false
```

```bash
project = Project.find(1)
project = Project.findByTitle("hello")

project.markAsDone()
```

### Persistence

```bash
Project "hi", ->
  @persistence Model.REST, "/projects"
  @persistence Model.localStorage
```

```bash
Project.load ->
  # loaded
```

### Attrs

```bash
project = new Project(name: "Hello")

project.attr('name', "Hey")
project.attr('name')

project.save()
project.destroy()
```

### Collection

```bash
Food.add(egg)
Food.all()
Food.select (food) -> ...
Food.first()
```

```bash
Food.find(id)
```

### Events

```bash
# Classes
Project.bind "add", (obj) ->
Project.bind "remove", (obj) ->
```

```bash
# Instances
project.bind "update", ->
project.bind "destroy", ->
```

```bash
project.trigger "turn_blue"
```

## References
{: .-one-column}

- <http://benpickles.github.io/js-model/>


text:
<?php

namespace Phalcon\Validation\Validator;

use Phalcon\Validation\Validator;

class ExclusionIn extends Validator
{

	/**
	 * Executes the validation
	 *
	 * @param \Phalcon\Validation $validation
	 * @param string $field
	 *
	 * @return boolean
	 */
	public function validate(\Phalcon\Validation $validation, $field) {}

}


text:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="@dimen/dialog_margin"
        android:scrollbarAlwaysDrawVerticalTrack="true"
        android:scrollbars="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">

            <!-- https://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-address -->
            <!-- {64}@{255} -->
            <EditText
                android:id="@+id/editTextDialogProfileShareEmailPrefix"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:hint="@string/dialog_profile_share_email_prefix"
                android:inputType="text"
                android:maxLength="64" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:text="@string/dialog_profile_share_email_suffix" />

        </LinearLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/dialog_margin"
            android:text="@string/dialog_profile_share_info_1"
            android:textStyle="italic" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/dialog_margin"
            android:text="@string/dialog_profile_share_info_2" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/dialog_margin"
            android:text="@string/dialog_profile_share_info_3" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/dialog_margin"
            android:text="@string/dialog_profile_share_info_4" />

        <CheckBox
            android:id="@+id/checkBoxDialogProfileShare"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/dialog_margin"
            android:text="@string/dialog_profile_share_checkbox" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/dialog_margin"
            android:text="@string/dialog_profile_share_message" />

    </LinearLayout>
</ScrollView>


text:
#include "sys.hpp"
#include <ch.hpp>
#include <hal.h>
#include <chprintf.h>
#include <memstreams.h>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdarg>

namespace os
{

static bool defaultSink(const std::uint8_t*, std::size_t);

static chibios_rt::Mutex g_mutex;
static StandardOutputSink g_sink{&defaultSink};

// Sink invocations are guaranteed to be protected by the mutex, so no extra locking is needed.
static bool defaultSink(const std::uint8_t* const data, const std::size_t sz)
{
    return chnWriteTimeout(&STDOUT_SD, data, sz, TIME_MS2I(10)) == sz;
}

static std::size_t writeExpandingCrLf(const char* str)
{
    std::size_t ret = 0;
    const char* end = str;

    while (*str != '\0')
    {
        if ((*end == '\n') ||
            (*end == '\0'))
        {
            if (end != str)
            {
                const std::size_t range = end - str;
                if (!g_sink(reinterpret_cast<const std::uint8_t*>(str), range))
                {
                    break;
                }

                ret += range;
                str += range;
            }

            if (*end == '\n')
            {
                if (!g_sink(reinterpret_cast<const std::uint8_t*>("\r\n"), 2))
                {
                    break;
                }

                ret += 2U;
                str++;
            }
        }

        end++;
    }

    return ret;
}

static std::size_t genericPrint(const char* format, va_list vl)
{
    MutexLocker locker(g_mutex);

    /*
     * Printing the string into the buffer
     */
    char buffer[256]{};
    MemoryStream ms;
    msObjectInit(&ms, (uint8_t*)buffer, sizeof(buffer), 0);
    ::BaseSequentialStream* chp = (::BaseSequentialStream*)&ms;
    chvprintf(chp, format, vl);
    buffer[sizeof(buffer) - 1] = 0;     // Paranoid termination

    /*
     * Writing the buffer replacing "\n" --> "\r\n"
     */
    return writeExpandingCrLf(buffer);
}

void Logger::println(const char* format, ...)
{
    MutexLocker locker(g_mutex);

    writeExpandingCrLf(name_);
    writeExpandingCrLf(": ");

    va_list vl;
    va_start(vl, format);
    genericPrint(format, vl);
    va_end(vl);

    writeExpandingCrLf("\n");
}

void Logger::puts(const char* line)
{
    MutexLocker locker(g_mutex);
    writeExpandingCrLf(name_);
    writeExpandingCrLf(": ");
    writeExpandingCrLf(line);
    writeExpandingCrLf("\n");
}

void setStandardOutputSink(const StandardOutputSink& sink)
{
    MutexLocker locker(g_mutex);
    if (sink)
    {
        g_sink = sink;
    }
    else
    {
        g_sink = defaultSink;
    }
}

} // namespace os

extern "C"
{

using namespace os;

int printf(const char* format, ...)
{
    va_list vl;
    va_start(vl, format);
    int ret = int(genericPrint(format, vl));
    va_end(vl);
    return ret;
}

int vprintf(const char* format, va_list vl)
{
    return int(genericPrint(format, vl));
}

int puts(const char* str)
{
    MutexLocker locker(g_mutex);
    int ret = int(writeExpandingCrLf(str));
    ret += int(writeExpandingCrLf("\n"));
    return ret;
}

}