<commit_before>/*! Image Zoom - v1
 *  Copyright (c) 2016 Mattias Hinderson
 *  License: MIT
 */

(function (window, factory) {
    'use strict';

    if (typeof define == 'function' && define.amd) {
        // AMD
        define([
            './utils',
            './pubsub',
            './vendor/stackblur',
            './vendor/picturefill'
        ], function(utils, pubsub, stackblur, picturefill) {
            return factory(window, utils, pubsub, stackblur, picturefill);
        });
    } else if (typeof exports == 'object') {
        // CommonJS
        module.exports = factory(
            window,
            require('./utils'),
            require('./pubsub'),
            require('./vendor/stackblur'),
            require('./vendor/picturefill')
        );
    }

}(window, function factory (window, utils, pubsub, stackblur, picturefill) {
    'use strict';

    // Constants
    var BLUR_AMOUNT = 40;

    // Unloaded items
    var unloadedItems = [];

    // Support helpers
    var supportsObjectFit = 'objectFit' in document.documentElement.style;
    var supportsIntersectionObserver = 'IntersectionObserver' in window;

    // Add a background-image fallback for object-fit
    // Must be called after Picturefill
    function polyfillObjectFit (img, container) {
        if (supportsObjectFit) { return; }

        utils.requestAnimFrame.call(window, function ( ) {
            // Get current image src: Edge only supports 'currentSrc' for getting the current image src ('src' returns value DOM value)
            var imageSrc = img.currentSrc || img.src;
            img.style.display = 'none';
            container.style.backgroundSize = img.getAttribute('data-object-fit');
            container.style.backgroundImage = 'url(' + imageSrc + ')';
        });
    }

    function checkImageVisibility ( ) {
        if (!Object.keys(unloadedItems).length) {
            // We've loaded all images in the document
            return destroy();
        }

        utils.forEach(unloadedItems, function (index, item) {
    		if (!item) { return; }

    		if (utils.isInViewport(item)) {
                loadMedia(item);
    		}
	   });
    }

    function loadMedia (item) {
        var showMedia = function ( ) {
            var mediaElem = this;

            item.classList.remove('loading-media');
            item.classList.add('media-loaded');

            pubsub.publish('mediaLoaded', [item, mediaElem]);
        };

        var makeImageElem = function (attributes) {
            var mediaElem = new Image();
            mediaElem.classList.add('media');

            var constructAttributes = function (prop) {
                mediaElem.setAttribute(prop, attributes[prop]);
            };

            item.appendChild(mediaElem);

            // Does the browser support srcset?
            // We either have srcset and native support for it, or just a regular src attribute
            if ('srcset' in mediaElem || !attributes.hasOwnProperty('srcset')) {
                mediaElem.onload = showMedia.bind(mediaElem);
                Object.keys(attributes).forEach(constructAttributes);
            } else {
                // We have only srcset, and we need to polyfill
                Object.keys(attributes).forEach(constructAttributes);
                showMedia.call(mediaElem);
                picturefill({ elements: [ mediaElem ] }); // Polyfill srcset images
                if (attributes.hasOwnProperty('data-object-fit')) {
                    polyfillObjectFit(mediaElem, item); // Polyfill object-fit images
                }
            }

            return mediaElem;
        };

        var makeVideoElem = function (attributes) {
            var video = document.createElement('video');
            video.className = 'media';
            video.autoplay = true;

            // Construct attributes
            Object.keys(attributes).forEach(function (prop) {
                video.setAttribute(prop, attributes[prop]);
            });

            return video;
        };

        var fallbackVideoElem = function ( ) {
            // Device doesn't support autoplay
            // Delete video attributes
            delete attributes.loop;
            delete attributes.muted;
            delete attributes.autoplay;
            delete attributes['webkit-playsinline'];

            // Append video fallback image
            attributes.src = item.getAttribute('data-video-fallback');
            var mediaElem = makeImageElem(attributes);
            item.classList.add('using-video-fallback');
            mediaElem.classList.add('video-fallback');
        };

        var attributes = JSON.parse(item.getAttribute('data-attributes'));
        var type = (attributes.src || attributes.srcset.split(',')[0].split(' ')[0]).match(/\.(jpg|jpeg|png|gif)$/) ? 'image' : 'video';

        // Add loading class
        item.classList.add('loading-media');

        // Try to load media element
        if (type === 'video') {
            var video = makeVideoElem(attributes);
            var videoPromise = video.play();

            if (videoPromise instanceof Promise) {
                videoPromise.then(function () {
                    item.appendChild(video);
                    showMedia.call(video);
                }).catch(fallbackVideoElem);
            } else {
                fallbackVideoElem();
            }
        } else {
            makeImageElem(attributes);
        }

        // Remove item from unloaded items array
        delete unloadedItems[unloadedItems.indexOf(item)];
    }

    function createBlurryPlaceholder (item) {
        var placeholder = item.getElementsByTagName('img')[0];
        var canvas = item.getElementsByTagName('canvas')[0];

        // Force reload
        var placeholderImg = new Image();
        placeholderImg.crossOrigin = 'Anonymous';
        placeholderImg.src = placeholder.src;

        // Wait for thumb to load completely
        var applyBlur = function ( ) {
            canvas.getContext('2d').drawImage(placeholderImg, 0, 0, canvas.width, canvas.height);
            stackblur.canvasRGB(canvas, 0, 0, canvas.width, canvas.height, BLUR_AMOUNT);
            item.classList.add('placeholder-loaded');
            pubsub.publish('placeholderCreated', item);
        };

        if (placeholderImg.complete) {
            applyBlur();
        } else {
            placeholderImg.onload = applyBlur;
        }

        return item;
    }

    function destroy ( ) {
        window.removeEventListener('resize', resizeEvent);
        window.removeEventListener('scroll', scrollEvent);
    }

    var lazyBlur = function (query, options) {
        if (!query) return;

        if (options) {
            BLUR_AMOUNT = options.blur;
        }

        // Export event emitter
        this.on = pubsub.subscribe;

        // Export functions
        this.check = checkImageVisibility;

        // Instantiate all provided queries
        var elems = (typeof query === 'string' ? document.querySelectorAll(query) : query);
        utils.forEach(elems, function (index, elem) {
            var unloadedItem = createBlurryPlaceholder(elem);
            unloadedItems.push(unloadedItem);
        });

        // Check for viewport visibility
        if (supportsIntersectionObserver) {
            var config = {
                root: null,
                rootMargin: '0px',
                threshold: options['threshold'] || 0.1
            };

            var observer = new IntersectionObserver(function (changes, observer) {
                changes.forEach(function (change) {
                    if (change.intersectionRatio > 0) {
                        // Stop watching and load the image
                        loadMedia(change.target);
                        observer.unobserve(change.target);
                    }
                });
            }, config);

            utils.forEach(unloadedItems, function (index, item) {
                observer.observe(item);
            });
        } else {
            // Do an initial check of image visibility
            checkImageVisibility();

            // Fallback to event listeners when Intersection Observers isn't supported
            window.addEventListener('resize', checkImageVisibility);
            window.addEventListener('scroll', checkImageVisibility);
        }
    };

	// Expose to interface
	if (typeof module === 'object' && typeof module.exports === 'object') {
		// CommonJS, just export
		module.exports = lazyBlur;
	} else if (typeof define === 'function' && define.amd) {
		// AMD support
		define('lazyBlur', function ( ) { return lazyBlur; } );
	}
}));
<commit_msg>Fix Promise return<commit_after>/*! Image Zoom - v1
 *  Copyright (c) 2016 Mattias Hinderson
 *  License: MIT
 */

(function (window, factory) {
    'use strict';

    if (typeof define == 'function' && define.amd) {
        // AMD
        define([
            './utils',
            './pubsub',
            './vendor/stackblur',
            './vendor/picturefill'
        ], function(utils, pubsub, stackblur, picturefill) {
            return factory(window, utils, pubsub, stackblur, picturefill);
        });
    } else if (typeof exports == 'object') {
        // CommonJS
        module.exports = factory(
            window,
            require('./utils'),
            require('./pubsub'),
            require('./vendor/stackblur'),
            require('./vendor/picturefill')
        );
    }

}(window, function factory (window, utils, pubsub, stackblur, picturefill) {
    'use strict';

    // Constants
    var BLUR_AMOUNT = 40;

    // Unloaded items
    var unloadedItems = [];

    // Support helpers
    var supportsObjectFit = 'objectFit' in document.documentElement.style;
    var supportsIntersectionObserver = 'IntersectionObserver' in window;

    // Add a background-image fallback for object-fit
    // Must be called after Picturefill
    function polyfillObjectFit (img, container) {
        if (supportsObjectFit) { return; }

        utils.requestAnimFrame.call(window, function ( ) {
            // Get current image src: Edge only supports 'currentSrc' for getting the current image src ('src' returns value DOM value)
            var imageSrc = img.currentSrc || img.src;
            img.style.display = 'none';
            container.style.backgroundSize = img.getAttribute('data-object-fit');
            container.style.backgroundImage = 'url(' + imageSrc + ')';
        });
    }

    function checkImageVisibility ( ) {
        if (!Object.keys(unloadedItems).length) {
            // We've loaded all images in the document
            return destroy();
        }

        utils.forEach(unloadedItems, function (index, item) {
    		if (!item) { return; }

    		if (utils.isInViewport(item)) {
                loadMedia(item);
    		}
	   });
    }

    function loadMedia (item) {
        var showMedia = function ( ) {
            var mediaElem = this;

            item.classList.remove('loading-media');
            item.classList.add('media-loaded');

            pubsub.publish('mediaLoaded', [item, mediaElem]);
        };

        var makeImageElem = function (attributes) {
            var mediaElem = new Image();
            mediaElem.classList.add('media');

            var constructAttributes = function (prop) {
                mediaElem.setAttribute(prop, attributes[prop]);
            };

            item.appendChild(mediaElem);

            // Does the browser support srcset?
            // We either have srcset and native support for it, or just a regular src attribute
            if ('srcset' in mediaElem || !attributes.hasOwnProperty('srcset')) {
                mediaElem.onload = showMedia.bind(mediaElem);
                Object.keys(attributes).forEach(constructAttributes);
            } else {
                // We have only srcset, and we need to polyfill
                Object.keys(attributes).forEach(constructAttributes);
                showMedia.call(mediaElem);
                picturefill({ elements: [ mediaElem ] }); // Polyfill srcset images
                if (attributes.hasOwnProperty('data-object-fit')) {
                    polyfillObjectFit(mediaElem, item); // Polyfill object-fit images
                }
            }

            return mediaElem;
        };

        var makeVideoElem = function (attributes) {
            var video = document.createElement('video');
            video.className = 'media';
            video.autoplay = true;

            // Construct attributes
            Object.keys(attributes).forEach(function (prop) {
                video.setAttribute(prop, attributes[prop]);
            });

            return video;
        };

        var fallbackVideoElem = function ( ) {
            // Device doesn't support autoplay
            // Delete video attributes
            delete attributes.loop;
            delete attributes.muted;
            delete attributes.autoplay;
            delete attributes['webkit-playsinline'];

            // Append video fallback image
            attributes.src = item.getAttribute('data-video-fallback');
            var mediaElem = makeImageElem(attributes);
            item.classList.add('using-video-fallback');
            mediaElem.classList.add('video-fallback');
        };

        var attributes = JSON.parse(item.getAttribute('data-attributes'));
        var type = (attributes.src || attributes.srcset.split(',')[0].split(' ')[0]).match(/\.(jpg|jpeg|png|gif)$/) ? 'image' : 'video';

        // Add loading class
        item.classList.add('loading-media');

        // Try to load media element
        if (type === 'video') {
            var video = makeVideoElem(attributes);
            var videoPromise = video.play();

            if (videoPromise !== undefined) {
                videoPromise.then(function () {
                    item.appendChild(video);
                    showMedia.call(video);
                }).catch(fallbackVideoElem);
            } else {
                fallbackVideoElem();
            }
        } else {
            makeImageElem(attributes);
        }

        // Remove item from unloaded items array
        delete unloadedItems[unloadedItems.indexOf(item)];
    }

    function createBlurryPlaceholder (item) {
        var placeholder = item.getElementsByTagName('img')[0];
        var canvas = item.getElementsByTagName('canvas')[0];

        // Force reload
        var placeholderImg = new Image();
        placeholderImg.crossOrigin = 'Anonymous';
        placeholderImg.src = placeholder.src;

        // Wait for thumb to load completely
        var applyBlur = function ( ) {
            canvas.getContext('2d').drawImage(placeholderImg, 0, 0, canvas.width, canvas.height);
            stackblur.canvasRGB(canvas, 0, 0, canvas.width, canvas.height, BLUR_AMOUNT);
            item.classList.add('placeholder-loaded');
            pubsub.publish('placeholderCreated', item);
        };

        if (placeholderImg.complete) {
            applyBlur();
        } else {
            placeholderImg.onload = applyBlur;
        }

        return item;
    }

    function destroy ( ) {
        window.removeEventListener('resize', resizeEvent);
        window.removeEventListener('scroll', scrollEvent);
    }

    var lazyBlur = function (query, options) {
        if (!query) return;

        if (options) {
            BLUR_AMOUNT = options.blur;
        }

        // Export event emitter
        this.on = pubsub.subscribe;

        // Export functions
        this.check = checkImageVisibility;

        // Instantiate all provided queries
        var elems = (typeof query === 'string' ? document.querySelectorAll(query) : query);
        utils.forEach(elems, function (index, elem) {
            var unloadedItem = createBlurryPlaceholder(elem);
            unloadedItems.push(unloadedItem);
        });

        // Check for viewport visibility
        if (supportsIntersectionObserver) {
            var config = {
                root: null,
                rootMargin: '0px',
                threshold: options['threshold'] || 0.1
            };

            var observer = new IntersectionObserver(function (changes, observer) {
                changes.forEach(function (change) {
                    if (change.intersectionRatio > 0) {
                        // Stop watching and load the image
                        loadMedia(change.target);
                        observer.unobserve(change.target);
                    }
                });
            }, config);

            utils.forEach(unloadedItems, function (index, item) {
                observer.observe(item);
            });
        } else {
            // Do an initial check of image visibility
            checkImageVisibility();

            // Fallback to event listeners when Intersection Observers isn't supported
            window.addEventListener('resize', checkImageVisibility);
            window.addEventListener('scroll', checkImageVisibility);
        }
    };

	// Expose to interface
	if (typeof module === 'object' && typeof module.exports === 'object') {
		// CommonJS, just export
		module.exports = lazyBlur;
	} else if (typeof define === 'function' && define.amd) {
		// AMD support
		define('lazyBlur', function ( ) { return lazyBlur; } );
	}
}));
<|endoftext|>


<commit_before>/* Highlight */
$(document).ready(function () {
  hljs.initHighlightingOnLoad();
  $('table').addClass('table table-striped table-hover');

  $.getJSON("https://api.github.com/repos/Baqend/js-sdk/tags").done(function (json) {
    var release = json[0].name.substring(1);
    var releasTag = $('.release .html .hljs-value');
    var newRelease = releasTag.text().replace('latest', release);
    releasTag.text(newRelease);
  });

  if($('body').has($('#speedKitDoc')).length > 0) {
      getSpeedKitAPIDoc();
  }
});

$('body').scrollspy({
  target: '.bs-sidebar',
});

/* Toggle the `clicky` class on the body when clicking links to let us
 retrigger CSS animations. See ../css/base.css for more details. */
$('a').click(function (e) {
  $('body').toggleClass('clicky');
});

$('#main h1[id], #main h2[id], #main h3[id], #main h4[id], #main h5[id], #main h6[id]').each(function (e) {
  $(this).append($(`<a href="#${$(this).attr('id')}" class="anchor fa fa-link"></a>`))
})

/* Prevent disabled links from causing a page reload */
$("li.disabled a").click(function () {
  event.preventDefault();
});

function shootingStar(that, dir) {
  setInterval(function(){
    var topPos = Math.floor(Math.random() * 80) + 1;
    var leftPos = Math.floor(Math.random() * 40) + 1;
    var trans = Math.floor(Math.random() * 300) + 1;
    that.css({
      'top': topPos + '%',
      'dir': leftPos + '%',
      'transform': 'rotate(' + trans + ')' + 'deg'
    });
  }, 2000);
}

$('.shooting-star').each(function(){
  shootingStar($(this), 'left');
});

$('.shooting-star-right').each(function(){
  shootingStar($(this), 'right');
});

/*Printing*/
function onBeforePrint(){
  if (window.Tawk_API && window.Tawk_API.hideWidget)
    window.Tawk_API.hideWidget();
}

function onAfterPrint(){
  if (window.Tawk_API && window.Tawk_API.showWidget)
    window.Tawk_API.showWidget();

}

function getSpeedKitAPIDoc() {
    $.get( "https://www.baqend.com/speed-kit/latest/", function( data ) {
      const content = $(data).find('.content');
      content.children().remove('.page-title');
      $('#speedKitDoc').append(content.children());
    });
}

window.addEventListener('beforeprint', onBeforePrint);
window.addEventListener('afterprint', onAfterPrint);
window.matchMedia('print').addListener((mql) => mql.matches? this.onBeforePrint(): this.onAfterPrint() );
<commit_msg>fix download link of embedded speed kit doc<commit_after>/* Highlight */
$(document).ready(function () {
  hljs.initHighlightingOnLoad();
  $('table').addClass('table table-striped table-hover');

  $.getJSON("https://api.github.com/repos/Baqend/js-sdk/tags").done(function (json) {
    var release = json[0].name.substring(1);
    var releasTag = $('.release .html .hljs-value');
    var newRelease = releasTag.text().replace('latest', release);
    releasTag.text(newRelease);
  });

  if($('body').has($('#speedKitDoc')).length > 0) {
      getSpeedKitAPIDoc();
  }
});

$('body').scrollspy({
  target: '.bs-sidebar',
});

/* Toggle the `clicky` class on the body when clicking links to let us
 retrigger CSS animations. See ../css/base.css for more details. */
$('a').click(function (e) {
  $('body').toggleClass('clicky');
});

$('#main h1[id], #main h2[id], #main h3[id], #main h4[id], #main h5[id], #main h6[id]').each(function (e) {
  $(this).append($(`<a href="#${$(this).attr('id')}" class="anchor fa fa-link"></a>`))
})

/* Prevent disabled links from causing a page reload */
$("li.disabled a").click(function () {
  event.preventDefault();
});

function shootingStar(that, dir) {
  setInterval(function(){
    var topPos = Math.floor(Math.random() * 80) + 1;
    var leftPos = Math.floor(Math.random() * 40) + 1;
    var trans = Math.floor(Math.random() * 300) + 1;
    that.css({
      'top': topPos + '%',
      'dir': leftPos + '%',
      'transform': 'rotate(' + trans + ')' + 'deg'
    });
  }, 2000);
}

$('.shooting-star').each(function(){
  shootingStar($(this), 'left');
});

$('.shooting-star-right').each(function(){
  shootingStar($(this), 'right');
});

/*Printing*/
function onBeforePrint(){
  if (window.Tawk_API && window.Tawk_API.hideWidget)
    window.Tawk_API.hideWidget();
}

function onAfterPrint(){
  if (window.Tawk_API && window.Tawk_API.showWidget)
    window.Tawk_API.showWidget();

}

function getSpeedKitAPIDoc() {
    $.get( "https://www.baqend.com/speed-kit/latest/", function( data ) {
      const content = $(data).find('.content');
      content.children().remove('.page-title');
      content.children().find('a[download]').each(function() {
        const href = $(this).attr('href');
        $(this).attr('href', '/speed-kit/latest/' + href);
      });

      $('#speedKitDoc').append(content.children());
    });
}

window.addEventListener('beforeprint', onBeforePrint);
window.addEventListener('afterprint', onAfterPrint);
window.matchMedia('print').addListener((mql) => mql.matches? this.onBeforePrint(): this.onAfterPrint() );
<|endoftext|>


<commit_before>import { action, computed, observable } from "mobx";
import UiState from "./UiState";

class PlaybackState {
  @observable isPlaying = false;
  @observable currentPlayingIndex = 0;
  @observable currentRunningTest = null;
  @observable currentRunningSuite = null;
  @observable commandsCount = 0;
  @observable commandState = new Map();
  @observable testState = new Map();
  @observable suiteState = new Map();
  @observable runs = 0;
  @observable failures = 0;
  @observable hasFailed = false;
  @observable aborted = false;
  @observable paused = false;
  @observable delay = 0;

  constructor() {
    this.maxDelay = 3000;
    this._testsToRun = [];
    this.runningQueue = [];
  }

  @computed get finishedCommandsCount() {
    let counter = 0;

    this.commandState.forEach(({ state }) => {
      if (state !== PlaybackStates.Pending) {
        counter++;
      }
    });

    return counter;
  }

  @computed get hasFinishedSuccessfully() {
    return this.runningQueue.filter(({id}) => (
      this.commandState.get(id) ? this.commandState.get(id).state === PlaybackStates.Passed : false
    )).length === this.runningQueue.length;
  }

  @action.bound startPlayingSuite() {
    const { suite } = UiState.selectedTest;
    if (this.currentRunningSuite !== (suite ? suite.id : undefined)) {
      this.resetState();
      this.currentRunningSuite = suite.id;
    }
    this.clearCommandStates();
    this.hasFailed = false;
    this.runs++;
    this._testsToRun = [...suite.tests];
    this.commandsCount = this._testsToRun.reduce((counter, test) => (counter + test.commands.length), 0);
    this.playNext();
  }

  @action.bound startPlaying(command) {
    const { test } = UiState.selectedTest;
    if (this.currentRunningSuite || !this.currentRunningTest || this.currentRunningTest.id !== test.id) {
      this.resetState();
      this.currentRunningSuite = undefined;
      this.currentRunningTest = test;
    }
    this.clearCommandStates();
    if (command) this.currentPlayingIndex = test.commands.indexOf(command);
    this.runs++;
    this.hasFailed = false;
    this.runningQueue = test.commands.peek();
    this.commandsCount = test.commands.length;
    this.isPlaying = true;
  }

  @action.bound playCommand(command) {
    this.resetState();
    this.currentRunningTest = UiState.selectedTest.test;
    this.runningQueue = [command];
    this.commandsCount = 1;
    this.isPlaying = true;
  }

  @action.bound playNext() {
    this.currentRunningTest = this._testsToRun.shift();
    UiState.selectTest(this.currentRunningTest, UiState.selectedTest.suite);
    this.runningQueue = this.currentRunningTest.commands.peek();
    this.currentPlayingIndex = 0;
    this.isPlaying = true;
  }

  @action.bound stopPlaying() {
    this.isPlaying = false;
  }

  @action.bound abortPlaying() {
    this.aborted = true;
    this.hasFailed = true;
    this._testsToRun = [];
    this.commandState.set(this.runningQueue[this.currentPlayingIndex].id, { state: PlaybackStates.Failed, message: "Playback aborted" });
    this.isPlaying = false;
  }

  @action.bound pause() {
    this.paused = true;
  }

  @action.bound resume() {
    this.paused = false;
  }

  @action.bound finishPlaying() {
    this.isPlaying = false;
    this.testState.set(this.currentRunningTest.id, this.hasFinishedSuccessfully ? PlaybackStates.Passed : PlaybackStates.Failed);
    if (this._testsToRun.length) {
      this.playNext();
    } else if (this.currentRunningSuite) {
      this.suiteState.set(this.currentRunningSuite, !this.hasFailed ? PlaybackStates.Passed : PlaybackStates.Failed);
    }
  }

  @action.bound setPlayingIndex(index) {
    this.currentPlayingIndex = index;
  }

  @action.bound setCommandState(commandId, state, message) {
    if (this.isPlaying) {
      if (state === PlaybackStates.Failed) {
        this.hasFailed = true;
        this.failures++;
      }
      this.commandState.set(commandId, { state, message });
    }
  }

  @action.bound clearCommandStates() {
    this.commandState.clear();
  }

  @action.bound setDelay(delay) {
    this.delay = delay;
  }

  @action.bound resetState() {
    this.clearCommandStates();
    this.currentPlayingIndex = 0;
    this.runs = 0;
    this.failures = 0;
    this.hasFailed = false;
    this.aborted = false;
    this.paused = false;
  }
}

export const PlaybackStates = {
  Passed: "passed",
  Failed: "failed",
  Pending: "pending"
};

if (!window._playbackState) window._playbackState = new PlaybackState();

export default window._playbackState;
<commit_msg>fixed an issue where the progress bar would not calculate the maximum correctly<commit_after>import { action, computed, observable } from "mobx";
import UiState from "./UiState";

class PlaybackState {
  @observable isPlaying = false;
  @observable currentPlayingIndex = 0;
  @observable currentRunningTest = null;
  @observable currentRunningSuite = null;
  @observable commandsCount = 0;
  @observable commandState = new Map();
  @observable testState = new Map();
  @observable suiteState = new Map();
  @observable runs = 0;
  @observable failures = 0;
  @observable hasFailed = false;
  @observable aborted = false;
  @observable paused = false;
  @observable delay = 0;

  constructor() {
    this.maxDelay = 3000;
    this._testsToRun = [];
    this.runningQueue = [];
  }

  @computed get finishedCommandsCount() {
    let counter = 0;

    this.commandState.forEach(({ state }) => {
      if (state !== PlaybackStates.Pending) {
        counter++;
      }
    });

    return counter;
  }

  @computed get hasFinishedSuccessfully() {
    return this.runningQueue.filter(({id}) => (
      this.commandState.get(id) ? this.commandState.get(id).state === PlaybackStates.Passed : false
    )).length === this.runningQueue.length;
  }

  @action.bound startPlayingSuite() {
    const { suite } = UiState.selectedTest;
    if (this.currentRunningSuite !== (suite ? suite.id : undefined)) {
      this.resetState();
      this.currentRunningSuite = suite.id;
    }
    this.clearCommandStates();
    this.hasFailed = false;
    this.runs++;
    this._testsToRun = [...suite.tests];
    this.commandsCount = this._testsToRun.reduce((counter, test) => (counter + test.commands.length), 0);
    this.playNext();
  }

  @action.bound startPlaying(command) {
    const { test } = UiState.selectedTest;
    if (this.currentRunningSuite || !this.currentRunningTest || this.currentRunningTest.id !== test.id) {
      this.resetState();
      this.currentRunningSuite = undefined;
      this.currentRunningTest = test;
    }
    this.clearCommandStates();
    if (command) this.currentPlayingIndex = test.commands.indexOf(command);
    this.runs++;
    this.hasFailed = false;
    this.runningQueue = test.commands.peek();
    this.commandsCount = test.commands.length - this.currentPlayingIndex;
    this.isPlaying = true;
  }

  @action.bound playCommand(command) {
    this.resetState();
    this.currentRunningTest = UiState.selectedTest.test;
    this.runningQueue = [command];
    this.commandsCount = 1;
    this.isPlaying = true;
  }

  @action.bound playNext() {
    this.currentRunningTest = this._testsToRun.shift();
    UiState.selectTest(this.currentRunningTest, UiState.selectedTest.suite);
    this.runningQueue = this.currentRunningTest.commands.peek();
    this.currentPlayingIndex = 0;
    this.isPlaying = true;
  }

  @action.bound stopPlaying() {
    this.isPlaying = false;
  }

  @action.bound abortPlaying() {
    this.aborted = true;
    this.hasFailed = true;
    this._testsToRun = [];
    this.commandState.set(this.runningQueue[this.currentPlayingIndex].id, { state: PlaybackStates.Failed, message: "Playback aborted" });
    this.isPlaying = false;
  }

  @action.bound pause() {
    this.paused = true;
  }

  @action.bound resume() {
    this.paused = false;
  }

  @action.bound finishPlaying() {
    this.isPlaying = false;
    this.testState.set(this.currentRunningTest.id, this.hasFinishedSuccessfully ? PlaybackStates.Passed : PlaybackStates.Failed);
    if (this._testsToRun.length) {
      this.playNext();
    } else if (this.currentRunningSuite) {
      this.suiteState.set(this.currentRunningSuite, !this.hasFailed ? PlaybackStates.Passed : PlaybackStates.Failed);
    }
  }

  @action.bound setPlayingIndex(index) {
    this.currentPlayingIndex = index;
  }

  @action.bound setCommandState(commandId, state, message) {
    if (this.isPlaying) {
      if (state === PlaybackStates.Failed) {
        this.hasFailed = true;
        this.failures++;
      }
      this.commandState.set(commandId, { state, message });
    }
  }

  @action.bound clearCommandStates() {
    this.commandState.clear();
  }

  @action.bound setDelay(delay) {
    this.delay = delay;
  }

  @action.bound resetState() {
    this.clearCommandStates();
    this.currentPlayingIndex = 0;
    this.runs = 0;
    this.failures = 0;
    this.hasFailed = false;
    this.aborted = false;
    this.paused = false;
  }
}

export const PlaybackStates = {
  Passed: "passed",
  Failed: "failed",
  Pending: "pending"
};

if (!window._playbackState) window._playbackState = new PlaybackState();

export default window._playbackState;
<|endoftext|>


<commit_before>(function (factory) {
    "use strict";
    if (typeof define === "function" && define.amd) { // AMD
        define(factory);
    } else if (typeof module === "object" && typeof module.exports === "object") { // nodeJS commonJS
        module.exports = factory();
    } else { // browser
        factory();
    }
})((function (global) {
    "use strict";
    return function () {
        /**
         * 添加多个事件监听
         * @param {Array} eventList [需要添加的监听列表]
         * eventList example:
         * [{
         *     elem: "HTMLElement",
         *     type: "eventType",
         *     cb: callback
         * },]
         */
        function addListener(eventList) {
            eventList.forEach(function (event) {
                var elem = event.elem,
                    type = event.type,
                    cb = event.cb;

                elem.addEventListener(type, cb, false);
            });
        }

        /**
         * 懒加载构造函数
         * @constructor
         */
        function LazyLoad() {
            this.imgList = [].slice.call(document.querySelectorAll(".lazyload-img"));
            this.init();
        }

        /**
         * 初始化，添加 "scroll" 和 "resize" 事件监听
         */
        LazyLoad.prototype.init = function () {
            var self = this,
                timer = null;

            function callback() {
                timer && clearTimeout(timer);
                setTimeout(function () {
                    var imgInVp = [];

                    self.imgList.forEach(function (img) {
                        if(self.isInViewport(img)) {
                            imgInVp.push(img);
                        }
                    });

                    self.loadImg(imgInVp);
                }, 100);
            }

            callback();

            addListener([
                {
                    elem: document,
                    type: "scroll",
                    cb: callback
                },
                {
                    elem: document,
                    type: "resize",
                    cb: callback
                }
            ]);
        };

        /**
         * 判断图片是否在可视区
         * @param  {HTMLElement} img [需要进行判断的图片元素]
         * @return {Boolean}     [返回是否在可视区]
         */
        LazyLoad.prototype.isInViewport = function (img) {
            var clientH = document.documentElement.clientHeight,
                clientW = document.documentElement.clientWidth,
                imgPosOb, imgH, imgL, imgT, imgW;

            if(typeof img.getBoundingClientRect === "function") {
                imgPosOb = img.getBoundingClientRect();
                imgT = imgPosOb.top;
                imgL = imgPosOb.left;
                imgH = imgPosOb.height;
                imgW = imgPosOb.width;

                if((imgT > -imgH && imgT < clientH) && (imgL > -imgW && imgL < clientW)) {
                    return true;
                } else {
                    return false;
                }
            } else {
                throw new Error("您的浏览器版本过低！");
                return;
            }
        };

        /**
         * 图片加载实现
         * @param  {Array} imgList [需要加载的图片列表]
         */
        LazyLoad.prototype.loadImg = function (imgList) {
            var self = this;

            imgList.forEach(function (img) {
                var src = img.getAttribute("data-src");
                img.src = src;
                img.removeAttribute("data-src");
                self.removeItem(img);
            });
        };

        /**
         * 从imgList中移除加载过的图片
         * @param  {HTMLElement} img [需要移除的图片]
         */
        LazyLoad.prototype.removeItem = function (img) {
            var idx = this.imgList.indexOf(img);
            if(idx > -1) {
                this.imgList.splice(idx, 1);
            }
        };

        global && (global.LazyLoad = LazyLoad);

        return LazyLoad;
    };
})(this))
<commit_msg>update<commit_after>(function (factory) {
    "use strict";
    if (typeof define === "function" && define.amd) { // AMD
        define(factory);
    } else if (typeof module === "object" && typeof module.exports === "object") { // nodeJS commonJS
        module.exports = factory();
    } else { // browser
        factory();
    }
})((function (global) {
    "use strict";
    return function () {
        /**
         * 添加多个事件监听
         * @param {Array} eventList [需要添加的监听列表]
         * eventList example:
         * [{
         *     elem: "HTMLElement",
         *     type: "eventType",
         *     cb: callback
         * },]
         */
        function addListener(eventList) {
            eventList.forEach(function (event) {
                var elem = event.elem,
                    type = event.type,
                    cb = event.cb;

                elem.addEventListener(type, cb, false);
            });
        }

        /**
         * 懒加载构造函数
         * @constructor
         */
        function LazyLoad() {
            this.imgList = [].slice.call(document.querySelectorAll(".lazyload-img"));
            this.init();
        }

        /**
         * 初始化，添加 "scroll" 和 "resize" 事件监听
         */
        LazyLoad.prototype.init = function () {
            var self = this,
                timer = null;

            function callback() {
                timer && clearTimeout(timer);
                timer = setTimeout(function () {
                    var imgInVp = [];

                    self.imgList.forEach(function (img) {
                        if(self.isInViewport(img)) {
                            imgInVp.push(img);
                        }
                    });

                    self.loadImg(imgInVp);
                }, 100);
            }

            callback();

            addListener([
                {
                    elem: document,
                    type: "scroll",
                    cb: callback
                },
                {
                    elem: document,
                    type: "resize",
                    cb: callback
                }
            ]);
        };

        /**
         * 判断图片是否在可视区
         * @param  {HTMLElement} img [需要进行判断的图片元素]
         * @return {Boolean}     [返回是否在可视区]
         */
        LazyLoad.prototype.isInViewport = function (img) {
            var clientH = document.documentElement.clientHeight,
                clientW = document.documentElement.clientWidth,
                imgPosOb, imgH, imgL, imgT, imgW;

            if(typeof img.getBoundingClientRect === "function") {
                imgPosOb = img.getBoundingClientRect();
                imgT = imgPosOb.top;
                imgL = imgPosOb.left;
                imgH = imgPosOb.height;
                imgW = imgPosOb.width;

                if((imgT > -imgH && imgT < clientH) && (imgL > -imgW && imgL < clientW)) {
                    return true;
                } else {
                    return false;
                }
            } else {
                throw new Error("您的浏览器版本过低！");
                return;
            }
        };

        /**
         * 图片加载实现
         * @param  {Array} imgList [需要加载的图片列表]
         */
        LazyLoad.prototype.loadImg = function (imgList) {
            var self = this;

            imgList.forEach(function (img) {
                var src = img.getAttribute("data-src");
                img.src = src;
                img.removeAttribute("data-src");
                self.removeItem(img);
            });
        };

        /**
         * 从imgList中移除加载过的图片
         * @param  {HTMLElement} img [需要移除的图片]
         */
        LazyLoad.prototype.removeItem = function (img) {
            var idx = this.imgList.indexOf(img);
            if(idx > -1) {
                this.imgList.splice(idx, 1);
            }
        };

        global && (global.LazyLoad = LazyLoad);

        return LazyLoad;
    };
})(this))
<|endoftext|>


<commit_before>var Path = require('path');
var Url = require('url');
var traverseAsync = require('traverse-async').traverse;
var traverse = require('traverse');
var Class = require('es-class');
var each = require('async-each');
var extend = require('xtend');
var debug = require('debug')('fs-storage');

var config = require('config');

var stripSlashes = function (name) {
  return name.replace(/^\/|\/$/g, '');
};

var serialize = function serialize (obj) {
  return JSON.stringify(obj, null, 2);
};

var deserialize = function deserialize (str) {
  return JSON.parse(str);
};

module.exports = Class({

  constructor: function (options) {

    this.collection = options.collection || "";
    this.collections = options.collections || {};

    this.collNamesByType = {};
    Object.keys(this.collections).forEach(function (collName) {
      var collection = this.collections[collName];
      this.collNamesByType[collection.id] = collName;
    }.bind(this));

    this.fs = options.fs || require('fs');
    this.fsRoot = options.fsRoot || config.get('data.root');

    this.extname = options.extname || ".json";
    this.serialize = options.serialize || serialize;
    this.deserialize = options.deserialize || deserialize;
  },

  fullId: function (collection, id) {
    debug("fullId(", collection, id, ")")

    var fullId = Path.join(
      collection,
      id
    );

    debug("fullId() ->", fullId);
    return fullId;
  },

  path: function (fullId) {
    debug("path(", fullId, ")")

    var path = Path.join(
      this.fsRoot,
      fullId ? (fullId + this.extname) : ""
    );

    debug("path() ->", path);
    return path;
  },

  read: function (path, cb) {
    debug("read(", path, ")");
    this.fs.readFile(path, function (err, buf) {
      if (err) { return cb(err); }

      var str = buf.toString();
      debug("read raw", str);

      var obj = this.deserialize(str);

      debug("read() ->", obj);

      return cb(null, obj);
    }.bind(this));
  },

  write: {
  },

  find: function (params, cb) {
    var path = this.path(this.collection)
    return this.fs.readdir(path, function (err, dirList) {
      var ids = dirList.filter(function (name) {
        return Path.extname(name) === this.extname;
      }, this).map(function (name) {
        return Path.basename(name, this.extname);
      }, this);

      each(ids, function (id, next) {
        return this.get(id, params, next);
      }.bind(this), cb);
    }.bind(this));
  },

  get: function (id, params, cb) {
    debug("get", id, params);

    var seen = {};

    var self = this;
    var fullId = self.fullId(self.collection, id);
    var path = self.path(fullId);

    return self.read(path, function (err, initObj) {
      if (err) { return cb(err); }

      seen[path] = true;

      debug("traversing object", initObj);
      var queue = traverseAsync(initObj, function (node, next) {
        debug("travsersing node", node);

        if (
          typeof this.parent !== 'undefined' &&
          typeof node['@type'] === 'string' &&
          typeof node['@id'] === 'string'
        ) {
          var collection = self.collNamesByType[node['@type']];
          var fullId = self.fullId(collection, node['@id']);
          var path = self.path(fullId);

          if (seen[path]) {
            return next();
          }

          return self.read(path, function (err, obj) {
            if (err) {
              queue.break();
              return cb(err);
            }

            seen[path] = true;

            this.parent[this.key] = extend(this.node, obj, {
              '@id': fullId,
            });

            queue.push(this);

            return next();
          }.bind(this));
        }
        else {
          return next();
        }
      }, function (newObj) {
        newObj['@id'] = fullId;

        // fix ids of leaves
        newObj = traverse(newObj).map(function () {

          if (
            typeof this.node === 'object' &&
            Object.keys(this.node).length == 2 &&
            typeof this.node['@id'] === 'string' &&
            typeof this.node['@type'] === 'string'
          ) {
            var collection = self.collNamesByType[this.node['@type']];
            var fullId = self.fullId(collection, this.node['@id']);

            this.update(extend(this.node, {
              '@id': fullId,
            }));
          };
        });

        return cb(null, newObj)
      });
    });
  },
  create: function () {
  },
  update: function () {
  },
  patch: function () {
  },
  remove: function () {
  },

});
<commit_msg>fix nested entities<commit_after>var Path = require('path');
var Url = require('url');
var traverseAsync = require('traverse-async').traverse;
var traverse = require('traverse');
var Class = require('es-class');
var each = require('async-each');
var extend = require('xtend');
var debug = require('debug')('fs-storage');

var config = require('config');

var stripSlashes = function (name) {
  return name.replace(/^\/|\/$/g, '');
};

var serialize = function serialize (obj) {
  return JSON.stringify(obj, null, 2);
};

var deserialize = function deserialize (str) {
  return JSON.parse(str);
};

module.exports = Class({

  constructor: function (options) {

    this.collection = options.collection || "";
    this.collections = options.collections || {};

    this.collNamesByType = {};
    Object.keys(this.collections).forEach(function (collName) {
      var collection = this.collections[collName];
      this.collNamesByType[collection.id] = collName;
    }.bind(this));

    this.fs = options.fs || require('fs');
    this.fsRoot = options.fsRoot || config.get('data.root');

    this.extname = options.extname || ".json";
    this.serialize = options.serialize || serialize;
    this.deserialize = options.deserialize || deserialize;
  },

  fullId: function (collection, id) {
    debug("fullId(", collection, id, ")")

    var fullId = Path.join(
      collection,
      id
    );

    debug("fullId() ->", fullId);
    return fullId;
  },

  path: function (fullId) {
    debug("path(", fullId, ")")

    var path = Path.join(
      this.fsRoot,
      fullId ? (fullId + this.extname) : ""
    );

    debug("path() ->", path);
    return path;
  },

  read: function (path, cb) {
    debug("read(", path, ")");
    this.fs.readFile(path, function (err, buf) {
      if (err) { return cb(err); }

      var str = buf.toString();
      debug("read raw", str);

      var obj = this.deserialize(str);

      debug("read() ->", obj);

      return cb(null, obj);
    }.bind(this));
  },

  write: {
  },

  find: function (params, cb) {
    var path = this.path(this.collection)
    return this.fs.readdir(path, function (err, dirList) {
      var ids = dirList.filter(function (name) {
        return Path.extname(name) === this.extname;
      }, this).map(function (name) {
        return Path.basename(name, this.extname);
      }, this);

      each(ids, function (id, next) {
        return this.get(id, params, next);
      }.bind(this), cb);
    }.bind(this));
  },

  get: function (id, params, cb) {
    debug("get", id, params);

    var seen = {};

    var self = this;
    var fullId = self.fullId(self.collection, id);
    var path = self.path(fullId);

    return self.read(path, function (err, initObj) {
      if (err) { return cb(err); }

      seen[path] = true;

      debug("traversing object", initObj);
      var queue = traverseAsync(initObj, function (node, next) {
        debug("travsersing node", node);

        if (
          typeof this.parent !== 'undefined' &&
          typeof node['@type'] === 'string' &&
          typeof node['@id'] === 'string'
        ) {
          var collection = self.collNamesByType[node['@type']];
          var fullId = self.fullId(collection, node['@id']);
          var path = self.path(fullId);

          if (seen[path]) {
            return next();
          }

          return self.read(path, function (err, obj) {
            if (err) {
              queue.break();
              return cb(err);
            }

            seen[path] = true;

            this.parent[this.key] = this.node = obj;

            queue.push(this);

            return next();
          }.bind(this));
        }
        else {
          return next();
        }
      }, function (newObj) {
        newObj['@id'] = fullId;

        // fix ids of leaves
        newObj = traverse(newObj).map(function () {

          if (
            typeof this.node === 'object' &&
            Object.keys(this.node).length == 2 &&
            typeof this.node['@id'] === 'string' &&
            typeof this.node['@type'] === 'string'
          ) {
            var collection = self.collNamesByType[this.node['@type']];
            var fullId = self.fullId(collection, this.node['@id']);

            this.update(extend(this.node, {
              '@id': fullId,
            }));
          };
        });

        return cb(null, newObj)
      });
    });
  },
  create: function () {
  },
  update: function () {
  },
  patch: function () {
  },
  remove: function () {
  },

});
<|endoftext|>


<commit_before>/**
 * @module ol/renderer/canvas/ImageLayer
 */
import {ENABLE_RASTER_REPROJECTION} from '../../reproj/common.js';
import {inherits} from '../../index.js';
import ImageCanvas from '../../ImageCanvas.js';
import LayerType from '../../LayerType.js';
import ViewHint from '../../ViewHint.js';
import {equals} from '../../array.js';
import {getHeight, getIntersection, getWidth, isEmpty} from '../../extent.js';
import VectorRenderType from '../../layer/VectorRenderType.js';
import {assign} from '../../obj.js';
import IntermediateCanvasRenderer from '../canvas/IntermediateCanvas.js';
import {create as createTransform, compose as composeTransform} from '../../transform.js';

/**
 * @constructor
 * @extends {module:ol/renderer/canvas/IntermediateCanvas}
 * @param {module:ol/layer/Image} imageLayer Single image layer.
 * @api
 */
const CanvasImageLayerRenderer = function(imageLayer) {

  IntermediateCanvasRenderer.call(this, imageLayer);

  /**
   * @private
   * @type {?module:ol/ImageBase}
   */
  this.image_ = null;

  /**
   * @private
   * @type {module:ol/transform~Transform}
   */
  this.imageTransform_ = createTransform();

  /**
   * @type {!Array.<string>}
   */
  this.skippedFeatures_ = [];

  /**
   * @private
   * @type {module:ol/renderer/canvas/VectorLayer}
   */
  this.vectorRenderer_ = null;

};

inherits(CanvasImageLayerRenderer, IntermediateCanvasRenderer);

/**
 * Determine if this renderer handles the provided layer.
 * @param {module:ol/layer/Layer} layer The candidate layer.
 * @return {boolean} The renderer can render the layer.
 */
CanvasImageLayerRenderer['handles'] = function(layer) {
  return layer.getType() === LayerType.IMAGE ||
    layer.getType() === LayerType.VECTOR &&
    /** @type {module:ol/layer/Vector} */ (layer).getRenderMode() === VectorRenderType.IMAGE;
};

/**
 * Create a layer renderer.
 * @param {module:ol/renderer/Map} mapRenderer The map renderer.
 * @param {module:ol/layer/Layer} layer The layer to be rendererd.
 * @return {module:ol/renderer/canvas/ImageLayer} The layer renderer.
 */
CanvasImageLayerRenderer['create'] = function(mapRenderer, layer) {
  const renderer = new CanvasImageLayerRenderer(/** @type {module:ol/layer/Image} */ (layer));
  if (layer.getType() === LayerType.VECTOR) {
    const candidates = mapRenderer.getLayerRendererConstructors();
    for (let i = 0, ii = candidates.length; i < ii; ++i) {
      const candidate = /** @type {Object.<string, Function>} */ (candidates[i]);
      if (candidate !== CanvasImageLayerRenderer && candidate['handles'](layer)) {
        renderer.setVectorRenderer(candidate['create'](mapRenderer, layer));
        break;
      }
    }
  }
  return renderer;
};

/**
 * @inheritDoc
 */
CanvasImageLayerRenderer.prototype.disposeInternal = function() {
  if (this.vectorRenderer_) {
    this.vectorRenderer_.dispose();
  }
  IntermediateCanvasRenderer.prototype.disposeInternal.call(this);
};

/**
 * @inheritDoc
 */
CanvasImageLayerRenderer.prototype.getImage = function() {
  return !this.image_ ? null : this.image_.getImage();
};

/**
 * @inheritDoc
 */
CanvasImageLayerRenderer.prototype.getImageTransform = function() {
  return this.imageTransform_;
};

/**
 * @inheritDoc
 */
CanvasImageLayerRenderer.prototype.prepareFrame = function(frameState, layerState) {

  const pixelRatio = frameState.pixelRatio;
  const size = frameState.size;
  const viewState = frameState.viewState;
  const viewCenter = viewState.center;
  const viewResolution = viewState.resolution;

  let image;
  const imageLayer = /** @type {module:ol/layer/Image} */ (this.getLayer());
  const imageSource = imageLayer.getSource();

  const hints = frameState.viewHints;

  let renderedExtent = frameState.extent;
  if (layerState.extent !== undefined) {
    renderedExtent = getIntersection(renderedExtent, layerState.extent);
  }

  if (!hints[ViewHint.ANIMATING] && !hints[ViewHint.INTERACTING] &&
      !isEmpty(renderedExtent)) {
    let projection = viewState.projection;
    if (!ENABLE_RASTER_REPROJECTION) {
      const sourceProjection = imageSource.getProjection();
      if (sourceProjection) {
        projection = sourceProjection;
      }
    }
    const vectorRenderer = this.vectorRenderer_;
    if (vectorRenderer) {
      const context = vectorRenderer.context;
      const imageFrameState = /** @type {module:ol/PluggableMap~FrameState} */ (assign({}, frameState, {
        size: [
          getWidth(renderedExtent) / viewResolution,
          getHeight(renderedExtent) / viewResolution
        ],
        viewState: /** @type {module:ol/View~State} */ (assign({}, frameState.viewState, {
          rotation: 0
        }))
      }));
      const skippedFeatures = Object.keys(imageFrameState.skippedFeatureUids).sort();
      if (vectorRenderer.prepareFrame(imageFrameState, layerState) &&
          (vectorRenderer.replayGroupChanged ||
          !equals(skippedFeatures, this.skippedFeatures_))) {
        context.canvas.width = imageFrameState.size[0] * pixelRatio;
        context.canvas.height = imageFrameState.size[1] * pixelRatio;
        vectorRenderer.compose(imageFrameState, layerState, context);
        this.image_ = new ImageCanvas(renderedExtent, viewResolution, pixelRatio, context.canvas);
        this.skippedFeatures_ = skippedFeatures;
      }
    } else {
      image = imageSource.getImage(
        renderedExtent, viewResolution, pixelRatio, projection);
      if (image) {
        const loaded = this.loadImage(image);
        if (loaded) {
          this.image_ = image;
        }
      }
    }
  }

  if (this.image_) {
    image = this.image_;
    const imageExtent = image.getExtent();
    const imageResolution = image.getResolution();
    const imagePixelRatio = image.getPixelRatio();
    const scale = pixelRatio * imageResolution /
        (viewResolution * imagePixelRatio);
    const transform = composeTransform(this.imageTransform_,
      pixelRatio * size[0] / 2, pixelRatio * size[1] / 2,
      scale, scale,
      0,
      imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution,
      imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution);
    composeTransform(this.coordinateToCanvasPixelTransform,
      pixelRatio * size[0] / 2 - transform[4], pixelRatio * size[1] / 2 - transform[5],
      pixelRatio / viewResolution, -pixelRatio / viewResolution,
      0,
      -viewCenter[0], -viewCenter[1]);

    this.renderedResolution = imageResolution * pixelRatio / imagePixelRatio;
  }

  return !!this.image_;
};

/**
 * @inheritDoc
 */
CanvasImageLayerRenderer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
  if (this.vectorRenderer_) {
    return this.vectorRenderer_.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, thisArg);
  } else {
    return IntermediateCanvasRenderer.prototype.forEachFeatureAtCoordinate.call(this, coordinate, frameState, hitTolerance, callback, thisArg);
  }
};

/**
 * @param {module:ol/renderer/canvas/VectorLayer} renderer Vector renderer.
 */
CanvasImageLayerRenderer.prototype.setVectorRenderer = function(renderer) {
  if (this.vectorRenderer_) {
    this.vectorRenderer_.dispose();
  }
  this.vectorRenderer_ = renderer;
};
export default CanvasImageLayerRenderer;
<commit_msg>Fix prepare/compose sequence to support icon loading<commit_after>/**
 * @module ol/renderer/canvas/ImageLayer
 */
import {ENABLE_RASTER_REPROJECTION} from '../../reproj/common.js';
import {inherits} from '../../index.js';
import ImageCanvas from '../../ImageCanvas.js';
import LayerType from '../../LayerType.js';
import ViewHint from '../../ViewHint.js';
import {equals} from '../../array.js';
import {getHeight, getIntersection, getWidth, isEmpty} from '../../extent.js';
import VectorRenderType from '../../layer/VectorRenderType.js';
import {assign} from '../../obj.js';
import IntermediateCanvasRenderer from '../canvas/IntermediateCanvas.js';
import {create as createTransform, compose as composeTransform} from '../../transform.js';

/**
 * @constructor
 * @extends {module:ol/renderer/canvas/IntermediateCanvas}
 * @param {module:ol/layer/Image} imageLayer Single image layer.
 * @api
 */
const CanvasImageLayerRenderer = function(imageLayer) {

  IntermediateCanvasRenderer.call(this, imageLayer);

  /**
   * @private
   * @type {?module:ol/ImageBase}
   */
  this.image_ = null;

  /**
   * @private
   * @type {module:ol/transform~Transform}
   */
  this.imageTransform_ = createTransform();

  /**
   * @type {!Array.<string>}
   */
  this.skippedFeatures_ = [];

  /**
   * @private
   * @type {module:ol/renderer/canvas/VectorLayer}
   */
  this.vectorRenderer_ = null;

};

inherits(CanvasImageLayerRenderer, IntermediateCanvasRenderer);

/**
 * Determine if this renderer handles the provided layer.
 * @param {module:ol/layer/Layer} layer The candidate layer.
 * @return {boolean} The renderer can render the layer.
 */
CanvasImageLayerRenderer['handles'] = function(layer) {
  return layer.getType() === LayerType.IMAGE ||
    layer.getType() === LayerType.VECTOR &&
    /** @type {module:ol/layer/Vector} */ (layer).getRenderMode() === VectorRenderType.IMAGE;
};

/**
 * Create a layer renderer.
 * @param {module:ol/renderer/Map} mapRenderer The map renderer.
 * @param {module:ol/layer/Layer} layer The layer to be rendererd.
 * @return {module:ol/renderer/canvas/ImageLayer} The layer renderer.
 */
CanvasImageLayerRenderer['create'] = function(mapRenderer, layer) {
  const renderer = new CanvasImageLayerRenderer(/** @type {module:ol/layer/Image} */ (layer));
  if (layer.getType() === LayerType.VECTOR) {
    const candidates = mapRenderer.getLayerRendererConstructors();
    for (let i = 0, ii = candidates.length; i < ii; ++i) {
      const candidate = /** @type {Object.<string, Function>} */ (candidates[i]);
      if (candidate !== CanvasImageLayerRenderer && candidate['handles'](layer)) {
        renderer.setVectorRenderer(candidate['create'](mapRenderer, layer));
        break;
      }
    }
  }
  return renderer;
};

/**
 * @inheritDoc
 */
CanvasImageLayerRenderer.prototype.disposeInternal = function() {
  if (this.vectorRenderer_) {
    this.vectorRenderer_.dispose();
  }
  IntermediateCanvasRenderer.prototype.disposeInternal.call(this);
};

/**
 * @inheritDoc
 */
CanvasImageLayerRenderer.prototype.getImage = function() {
  return !this.image_ ? null : this.image_.getImage();
};

/**
 * @inheritDoc
 */
CanvasImageLayerRenderer.prototype.getImageTransform = function() {
  return this.imageTransform_;
};

/**
 * @inheritDoc
 */
CanvasImageLayerRenderer.prototype.prepareFrame = function(frameState, layerState) {

  const pixelRatio = frameState.pixelRatio;
  const size = frameState.size;
  const viewState = frameState.viewState;
  const viewCenter = viewState.center;
  const viewResolution = viewState.resolution;

  let image;
  const imageLayer = /** @type {module:ol/layer/Image} */ (this.getLayer());
  const imageSource = imageLayer.getSource();

  const hints = frameState.viewHints;

  let renderedExtent = frameState.extent;
  if (layerState.extent !== undefined) {
    renderedExtent = getIntersection(renderedExtent, layerState.extent);
  }

  if (!hints[ViewHint.ANIMATING] && !hints[ViewHint.INTERACTING] &&
      !isEmpty(renderedExtent)) {
    let projection = viewState.projection;
    if (!ENABLE_RASTER_REPROJECTION) {
      const sourceProjection = imageSource.getProjection();
      if (sourceProjection) {
        projection = sourceProjection;
      }
    }
    let skippedFeatures = this.skippedFeatures_;
    const vectorRenderer = this.vectorRenderer_;
    if (vectorRenderer) {
      const context = vectorRenderer.context;
      const imageFrameState = /** @type {module:ol/PluggableMap~FrameState} */ (assign({}, frameState, {
        size: [
          getWidth(renderedExtent) / viewResolution,
          getHeight(renderedExtent) / viewResolution
        ],
        viewState: /** @type {module:ol/View~State} */ (assign({}, frameState.viewState, {
          rotation: 0
        }))
      }));
      const newSkippedFeatures = Object.keys(imageFrameState.skippedFeatureUids).sort();
      image = new ImageCanvas(renderedExtent, viewResolution, pixelRatio, context.canvas, function(callback) {
        if (vectorRenderer.prepareFrame(imageFrameState, layerState) &&
            (vectorRenderer.replayGroupChanged ||
            !equals(skippedFeatures, newSkippedFeatures))) {
          context.canvas.width = imageFrameState.size[0] * pixelRatio;
          context.canvas.height = imageFrameState.size[1] * pixelRatio;
          vectorRenderer.compose(context, imageFrameState, layerState);
          skippedFeatures = newSkippedFeatures;
          callback();
        }
      });
    } else {
      image = imageSource.getImage(
        renderedExtent, viewResolution, pixelRatio, projection);
    }
    if (image && this.loadImage(image)) {
      this.image_ = image;
      this.skippedFeatures_ = skippedFeatures;
    }
  }

  if (this.image_) {
    image = this.image_;
    const imageExtent = image.getExtent();
    const imageResolution = image.getResolution();
    const imagePixelRatio = image.getPixelRatio();
    const scale = pixelRatio * imageResolution /
        (viewResolution * imagePixelRatio);
    const transform = composeTransform(this.imageTransform_,
      pixelRatio * size[0] / 2, pixelRatio * size[1] / 2,
      scale, scale,
      0,
      imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution,
      imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution);
    composeTransform(this.coordinateToCanvasPixelTransform,
      pixelRatio * size[0] / 2 - transform[4], pixelRatio * size[1] / 2 - transform[5],
      pixelRatio / viewResolution, -pixelRatio / viewResolution,
      0,
      -viewCenter[0], -viewCenter[1]);

    this.renderedResolution = imageResolution * pixelRatio / imagePixelRatio;
  }

  return !!this.image_;
};

/**
 * @inheritDoc
 */
CanvasImageLayerRenderer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
  if (this.vectorRenderer_) {
    return this.vectorRenderer_.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, thisArg);
  } else {
    return IntermediateCanvasRenderer.prototype.forEachFeatureAtCoordinate.call(this, coordinate, frameState, hitTolerance, callback, thisArg);
  }
};

/**
 * @param {module:ol/renderer/canvas/VectorLayer} renderer Vector renderer.
 */
CanvasImageLayerRenderer.prototype.setVectorRenderer = function(renderer) {
  if (this.vectorRenderer_) {
    this.vectorRenderer_.dispose();
  }
  this.vectorRenderer_ = renderer;
};
export default CanvasImageLayerRenderer;
<|endoftext|>


<commit_before>(function( $ ){
	$.fn.qrcode = function(options) {
		// if options is string,
		if( typeof options === 'string' ){
			options	= { text: options };
		}

		// set default values
		// typeNumber < 1 for automatic calculation
		options	= $.extend( {}, {
			render		: "canvas",
			width		: 256,
			height		: 256,
			typeNumber	: -1,
			correctLevel	: QRErrorCorrectLevel.H,
                        background      : "#ffffff",
                        foreground      : "#000000"
		}, options);

		var createCanvas	= function(){
			// create the qrcode itself
			var qrcode	= new QRCode(options.typeNumber, options.correctLevel);
			qrcode.addData(options.text);
			qrcode.make();

			// create canvas element
			var canvas	= document.createElement('canvas');
			canvas.width	= options.width;
			canvas.height	= options.height;
			var ctx		= canvas.getContext('2d');

			// compute tileW/tileH based on options.width/options.height
			var tileW	= options.width  / qrcode.getModuleCount();
			var tileH	= options.height / qrcode.getModuleCount();

			// draw in the canvas
			for( var row = 0; row < qrcode.getModuleCount(); row++ ){
				for( var col = 0; col < qrcode.getModuleCount(); col++ ){
					ctx.fillStyle = qrcode.isDark(row, col) ? options.foreground : options.background;
					var w = (Math.ceil((col+1)*tileW) - Math.floor(col*tileW));
					var h = (Math.ceil((row+1)*tileW) - Math.floor(row*tileW));
					ctx.fillRect(Math.round(col*tileW),Math.round(row*tileH), w, h);
				}
			}
			// return just built canvas
			return canvas;
		}

		// from Jon-Carlos Rivera (https://github.com/imbcmdth)
		var createTable	= function(){
			// create the qrcode itself
			var qrcode	= new QRCode(options.typeNumber, options.correctLevel);
			qrcode.addData(options.text);
			qrcode.make();

			// create table element
			var $table	= $('

')
				.css("width", options.width+"px")
				.css("height", options.height+"px")
				.css("border", "0px")
				.css("border-collapse", "collapse")
				.css('background-color', options.background);

			// compute tileS percentage
			var tileW	= options.width / qrcode.getModuleCount();
			var tileH	= options.height / qrcode.getModuleCount();

			// draw in the table
			for(var row = 0; row < qrcode.getModuleCount(); row++ ){
				var $row = $('

').css('height', tileH+"px").appendTo($table);

				for(var col = 0; col < qrcode.getModuleCount(); col++ ){
					$('	')
						.css('width', tileW+"px")
						.css('background-color', qrcode.isDark(row, col) ? options.foreground : options.background)
						.appendTo($row);
				}
			}
			// return just built canvas
			return $table;
		}

		return this.each(function(){
			var element	= options.render == "canvas" ? createCanvas() : createTable();
			$(element).appendTo(this);
		});
	};
})( jQuery );
<commit_msg>pull https://github.com/jeromeetienne/jquery-qrcode/pull/43/files for jquery.qrcode.js<commit_after>(function( $ ){
	$.fn.qrcode = function(options) {
		// if options is string,
		if( typeof options === 'string' ){
			options	= { text: options };
		}

		// set default values
		// typeNumber < 1 for automatic calculation
		options	= $.extend( {}, {
			render		: "canvas",
			width		: 256,
			height		: 256,
			margin		: 4,
			typeNumber	: -1,
			correctLevel	: QRErrorCorrectLevel.H,
                        background      : "#ffffff",
                        foreground      : "#000000"
		}, options);

		var createCanvas	= function(){
			// create the qrcode itself
			var qrcode	= new QRCode(options.typeNumber, options.correctLevel);
			qrcode.addData(options.text);
			qrcode.make();

			// create canvas element
			var canvas	= document.createElement('canvas');
			canvas.width	= options.width;
			canvas.height	= options.height;
			var ctx		= canvas.getContext('2d');

			// compute tileW/tileH based on options.width/options.height
			var margin	= options.margin;
			var tileW	= options.width  / (qrcode.getModuleCount() + 2*options.margin);
			var tileH	= options.height / (qrcode.getModuleCount() + 2*options.margin);

			var isDark = function(x, y) {
				x -= margin; y -= margin;
				if(x < 0 || x >= qrcode.getModuleCount() || y < 0 || y >= qrcode.getModuleCount())
				    return false;
				else
				    return qrcode.isDark(x, y);
			}

			// draw in the canvas
			for( var row = 0; row < qrcode.getModuleCount()+2*margin; row++ ){
				for( var col = 0; col < qrcode.getModuleCount()+2*margin; col++ ){
					ctx.fillStyle = isDark(row, col) ? options.foreground : options.background;
					var w = (Math.ceil((col+1)*tileW) - Math.floor(col*tileW));
					var h = (Math.ceil((row+1)*tileH) - Math.floor(row*tileH));
					ctx.fillRect(Math.round(col*tileW),Math.round(row*tileH), w, h);
				}
			}
			// return just built canvas
			return canvas;
		}

		// from Jon-Carlos Rivera (https://github.com/imbcmdth)
		var createTable	= function(){
			// create the qrcode itself
			var qrcode	= new QRCode(options.typeNumber, options.correctLevel);
			qrcode.addData(options.text);
			qrcode.make();

			// create table element
			var $table	= $('

')
				.css("width", options.width+"px")
				.css("height", options.height+"px")
				.css("border", "0px")
				.css("border-collapse", "collapse")
				.css('background-color', options.background);

			// compute tileS percentage
			var margin	= options.margin;
			var tileW	= options.width / (qrcode.getModuleCount() + 2*margin);
			var tileH	= options.height / (qrcode.getModuleCount() + 2*margin);

			var isDark = function(x, y) {
				x -= margin; y -= margin;
				if(x < 0 || x >= qrcode.getModuleCount() || y < 0 || y >= qrcode.getModuleCount())
				    return false;
				else
				    return qrcode.isDark(x, y);
			}

			// draw in the table
			for(var row = 0; row < (qrcode.getModuleCount() + 2*margin); row++ ){
				var $row = $('

').css('height', tileH+"px").appendTo($table);
				for(var col = 0; col < (qrcode.getModuleCount() + 2*margin); col++ ){
					$('	')
						.css('width', tileW+"px")
						.css('background-color', isDark(row, col) ? options.foreground : options.background)
						.appendTo($row);
				}
			}
			// return just built canvas
			return $table;
		}

		return this.each(function(){
			var element	= options.render == "canvas" ? createCanvas() : createTable();
			$(element).appendTo(this);
		});
	};
})( jQuery );
<|endoftext|>


<commit_before>// This is the entry point for our client-side logic
// The server-side has a similar configuration in `src/server/middleware/render.js`
import 'isomorphic-fetch'
import '../../core/polyfills'
import '../../core/logger'
import '../assets/css/index.scss'
import onEnter from '../../core/helpers/onEnter'
import Inferno from 'inferno'
import { Router, match } from 'inferno-router'
import createBrowserHistory from 'history/createBrowserHistory';
import autorun from './autorun'
import stores from './stores'
import routes from './routes'
import App from '../components/App'

// We render our react app into this element
const container = document.getElementById('container')
const history = createBrowserHistory()
const routing = routes(stores)

// React to changes
autorun(stores)

/**
 * Render our component according to our routes
 */
Inferno.render(<App stores={stores}>
    <Router history={history}>
        {routing}
    </Router>
</App>, container)

// Fetch data on route change
history.listen(location => {
    onEnter(match(routing, location), stores)
})

if (module.hot) {
    module.hot.accept()
}
<commit_msg>Execute fetchData methods before first render pass<commit_after>// This is the entry point for our client-side logic
// The server-side has a similar configuration in `src/server/middleware/render.js`
import 'isomorphic-fetch'
import '../../core/polyfills'
import '../../core/logger'
import '../assets/css/index.scss'
import onEnter from '../../core/helpers/onEnter'
import Inferno from 'inferno'
import { Router, match } from 'inferno-router'
import createBrowserHistory from 'history/createBrowserHistory';
import autorun from './autorun'
import stores from './stores'
import routes from './routes'
import App from '../components/App'

// We render our react app into this element
const container = document.getElementById('container')
const history = createBrowserHistory()
const routing = routes(stores)

// React to changes
autorun(stores)

// Fetch data on route change
history.listen(location => {
    onEnter(match(routing, location), stores)
})

/**
 * Render our component according to our routes
 */
Inferno.render(<App stores={stores}>
    <Router history={history}>
        {routing}
    </Router>
</App>, container)

if (module.hot) {
    module.hot.accept()
}
<|endoftext|>


<commit_before>const { download } = require('@prisma/fetch-engine')
const fs = require('fs')
const path = require('path')
const pkgUp = require('pkg-up')
const Debug = require('debug')
const debug = Debug('prisma:download')

const binaryDir = eval(`require('path').join(__dirname, '../')`)
const pkg = eval(`require(require('path').join(binaryDir, 'package.json'))`)

const version = (pkg && pkg.prisma && pkg.prisma.version) || 'latest'

const lockFile = path.join(binaryDir, 'download-lock')

let createdLockFile = false
async function main() {
  if (
    fs.existsSync(lockFile) &&
    JSON.parse(fs.readFileSync(lockFile) > Date.now() - 20000)
  ) {
    debug(
      `Lock file already exists, so we're skipping the download of the prisma binaries`,
    )
  } else {
    createLockFile()
    await download({
      binaries: {
        'query-engine': binaryDir,
        'migration-engine': binaryDir,
        'introspection-engine': binaryDir,
        'prisma-fmt': binaryDir,
      },
      showProgress: true,
      version,
      failSilent: true,
    }).catch((e) => debug(e))

    cleanupLockFile()
  }
}

function createLockFile() {
  createdLockFile = true
  fs.writeFileSync(lockFile, Date.now())
}

function cleanupLockFile() {
  if (createdLockFile) {
    try {
      if (fs.existsSync(lockFile)) {
        fs.unlinkSync(lockFile)
      }
    } catch (e) {
      debug(e)
    }
  }
}

main().catch((e) => debug(e))

// if we are in a Now context, ensure that `prisma generate` is in the postinstall hook
if (process.env.INIT_CWD && process.env.NOW_BUILDER) {
  ensurePostInstall().catch((e) => {
    debug(e)
  })
}

async function ensurePostInstall() {
  const initPkgPath = eval(
    `require('path').resolve(process.env.INIT_CWD, 'package.json')`,
  )
  if (fs.existsSync(initPkgPath)) {
    if (addPostInstallHook(initPkgPath)) {
      return
    }
  } else {
    // walk up all the way
    let cwd = path.join(process.cwd(), '..')
    let pkgPath
    do {
      pkgPath = await pkgUp({
        cwd,
      })
      cwd = path.join(pkgPath, '../..')
    } while (pkgPath && !addPostInstallHook(pkgPath))
  }
}

function addPostInstallHook(pkgPath) {
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
  // only update package.json if @prisma/cli is a dependency or devDependency
  if (!pkg.dependencies['@prisma/cli'] && !pkg.devDependencies['@prisma/cli']) {
    return false
  }

  pkg.scripts = pkg.scripts || {}

  if (!pkg.scripts.postinstall) {
    pkg.scripts.postinstall = `prisma generate || true`
  } else {
    if (!pkg.scripts.postinstall.includes('prisma generate')) {
      pkg.scripts.postinstall = `prisma generate || true && ${pkg.scripts.postinstall}`
    }
  }

  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2))
  return true
}

process.on('beforeExit', () => {
  cleanupLockFile()
})

process.once('SIGINT', () => {
  cleanupLockFile()
  process.exit()
})
<commit_msg>fix(cli): writeFileSync API changed for Node 14<commit_after>const { download } = require('@prisma/fetch-engine')
const fs = require('fs')
const path = require('path')
const pkgUp = require('pkg-up')
const Debug = require('debug')
const debug = Debug('prisma:download')

const binaryDir = eval(`require('path').join(__dirname, '../')`)
const pkg = eval(`require(require('path').join(binaryDir, 'package.json'))`)

const version = (pkg && pkg.prisma && pkg.prisma.version) || 'latest'

const lockFile = path.join(binaryDir, 'download-lock')

let createdLockFile = false
async function main() {
  if (
    fs.existsSync(lockFile) &&
    JSON.parse(fs.readFileSync(lockFile) > Date.now() - 20000)
  ) {
    debug(
      `Lock file already exists, so we're skipping the download of the prisma binaries`,
    )
  } else {
    createLockFile()
    await download({
      binaries: {
        'query-engine': binaryDir,
        'migration-engine': binaryDir,
        'introspection-engine': binaryDir,
        'prisma-fmt': binaryDir,
      },
      showProgress: true,
      version,
      failSilent: true,
    }).catch((e) => debug(e))

    cleanupLockFile()
  }
}

function createLockFile() {
  createdLockFile = true
  fs.writeFileSync(lockFile, Date.now().toString())
}

function cleanupLockFile() {
  if (createdLockFile) {
    try {
      if (fs.existsSync(lockFile)) {
        fs.unlinkSync(lockFile)
      }
    } catch (e) {
      debug(e)
    }
  }
}

main().catch((e) => debug(e))

// if we are in a Now context, ensure that `prisma generate` is in the postinstall hook
if (process.env.INIT_CWD && process.env.NOW_BUILDER) {
  ensurePostInstall().catch((e) => {
    debug(e)
  })
}

async function ensurePostInstall() {
  const initPkgPath = eval(
    `require('path').resolve(process.env.INIT_CWD, 'package.json')`,
  )
  if (fs.existsSync(initPkgPath)) {
    if (addPostInstallHook(initPkgPath)) {
      return
    }
  } else {
    // walk up all the way
    let cwd = path.join(process.cwd(), '..')
    let pkgPath
    do {
      pkgPath = await pkgUp({
        cwd,
      })
      cwd = path.join(pkgPath, '../..')
    } while (pkgPath && !addPostInstallHook(pkgPath))
  }
}

function addPostInstallHook(pkgPath) {
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
  // only update package.json if @prisma/cli is a dependency or devDependency
  if (!pkg.dependencies['@prisma/cli'] && !pkg.devDependencies['@prisma/cli']) {
    return false
  }

  pkg.scripts = pkg.scripts || {}

  if (!pkg.scripts.postinstall) {
    pkg.scripts.postinstall = `prisma generate || true`
  } else {
    if (!pkg.scripts.postinstall.includes('prisma generate')) {
      pkg.scripts.postinstall = `prisma generate || true && ${pkg.scripts.postinstall}`
    }
  }

  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2))
  return true
}

process.on('beforeExit', () => {
  cleanupLockFile()
})

process.once('SIGINT', () => {
  cleanupLockFile()
  process.exit()
})
<|endoftext|>


<commit_before>/*!
 * OS.js - JavaScript Cloud/Web Desktop Platform
 *
 * Copyright (c) 2011-2017, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */
import Translations from './locales';
import PanelItem from './panelitem';

const _ = OSjs.require('core/locales').createLocalizer(Translations);
const DOM = OSjs.require('utils/dom');
const Events = OSjs.require('utils/events');
const Menu = OSjs.require('gui/menu');
const WindowManager = OSjs.require('core/window-manager');

/*eslint valid-jsdoc: "off"*/

const PANEL_SHOW_TIMEOUT = 150;
const PANEL_HIDE_TIMEOUT = 600;

export default class Panel {

  constructor(name, options, wm) {
    options = options || {};

    this._name = name;
    this._$element = null;
    this._$container = null;
    this._items = [];
    this._outtimeout = null;
    this._intimeout = null;
    this._options = options.mergeDefaults({
      position: 'top'
    });

    console.debug('Panel::construct()', this._name, this._options.get());
  }

  init(root) {
    var wm = WindowManager.instance;

    function createMenu(ev) {
      var menu = [
        {title: _('Open Panel Settings'), onClick: function(ev) {
          wm.showSettings('panel');
        }}
      ];

      if ( wm.getSetting('useTouchMenu') === true ) {
        menu.push({
          title: _('Turn off TouchMenu'),
          onClick: function(ev) {
            wm.applySettings({useTouchMenu: false}, false, true);
          }
        });
      } else {
        menu.push({
          title: _('Turn on TouchMenu'),
          onClick: function(ev) {
            wm.applySettings({useTouchMenu: true}, false, true);
          }
        });
      }

      Menu.create(menu, ev);
    }

    this._$container = document.createElement('corewm-panel-container');
    this._$element = document.createElement('corewm-panel');
    this._$element.setAttribute('data-orientation', 'horizontal');
    this._$element.setAttribute('role', 'toolbar');

    /*Utils.$bind(this._$element, 'mousedown', function(ev) {
      ev.preventDefault();
    }); // This makes DnD not work in panel items*/
    Events.$bind(this._$element, 'mouseover', (ev) => {
      this.onMouseOver(ev);
    });
    Events.$bind(this._$element, 'mouseout', (ev) => {
      this.onMouseOut(ev);
    });
    Events.$bind(this._$element, 'contextmenu', function(ev) {
      createMenu(ev);
    });

    Events.$bind(document, 'mouseout:panelmouseleave', (ev) => {
      this.onMouseLeave(ev);
    }, false);

    this._$element.appendChild(this._$container);
    root.appendChild(this._$element);

    setTimeout(() => this.update(), 0);
  }

  destroy() {
    this._clearTimeouts();

    Events.$unbind(document, 'mouseout:panelmouseleave');
    Events.$unbind(this._$element);

    this._items.forEach(function(item) {
      item.destroy();
    });
    this._items = [];
    this._$element = DOM.$remove(this._$element);
    this._$container = null;
  }

  update(options) {
    options = options || this._options.get();

    // CSS IS SET IN THE WINDOW MANAGER!
    var attrs = {
      ontop: !!options.ontop,
      position: options.position || 'bottom'
    };

    if ( options.autohide ) {
      this.onMouseOut();
    }
    if ( this._$element ) {
      Object.keys(attrs).forEach((k) => {
        this._$element.setAttribute('data-' + k, typeof attrs[k] === 'boolean' ? (attrs[k] ? 'true' : 'false') : attrs[k]);
      });
    }
    this._options.set(null, options);
  }

  autohide(hide) {
    if ( !this._options.get('autohide') || !this._$element ) {
      return;
    }

    if ( hide ) {
      this._$element.setAttribute('data-autohide', 'true');
    } else {
      this._$element.setAttribute('data-autohide', 'false');
    }
  }

  _clearTimeouts() {
    if ( this._outtimeout ) {
      clearTimeout(this._outtimeout);
      this._outtimeout = null;
    }
    if ( this._intimeout ) {
      clearTimeout(this._intimeout);
      this._intimeout = null;
    }
  }

  onMouseLeave(ev) {
    var from = ev.relatedTarget || ev.toElement;
    if ( !from || from.nodeName === 'HTML' ) {
      this.onMouseOut(ev);
    }
  }

  onMouseOver() {
    this._clearTimeouts();
    this._intimeout = setTimeout(() => {
      this.autohide(false);
    }, PANEL_SHOW_TIMEOUT);
  }

  onMouseOut() {
    this._clearTimeouts();
    this._outtimeout = setTimeout(() => {
      this.autohide(true);
    }, PANEL_HIDE_TIMEOUT);
  }

  addItem(item) {
    if ( !(item instanceof PanelItem) ) {
      throw 'Expected a PanelItem in Panel::addItem()';
    }

    this._items.push(item);
    this._$container.appendChild(item.init());
  }

  isAutoHidden() {
    if ( this._$element ) {
      return this._$element.getAttribute('data-autohide') === 'true';
    }

    return false;
  }

  getItemByType(type) {
    return this.getItem(type);
  }

  getItemsByType(type) {
    return this.getItem(type, true);
  }

  getItem(type, multiple) {
    var result = multiple ? [] : null;

    this._items.forEach(function(item, idx) {
      if ( item instanceof type ) {
        if ( multiple ) {
          result.push(item);
        } else {
          result = item;
          return false;
        }
      }
      return true;
    });

    return result;
  }

  getOntop() {
    return this._options.get('ontop');
  }

  getPosition(pos) {
    return pos ? (this._options.get('position') === pos) : this._options.get('position');
  }

  getAutohide() {
    return this._options.get('autohide');
  }

  getRoot() {
    return this._$element;
  }

  getHeight() {
    return this._$element ? this._$element.offsetHeight : 0;
  }
}
<commit_msg>CoreWM: Fixed panel item contextmenu overlapping (#639)<commit_after>/*!
 * OS.js - JavaScript Cloud/Web Desktop Platform
 *
 * Copyright (c) 2011-2017, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */
import Translations from './locales';
import PanelItem from './panelitem';

const _ = OSjs.require('core/locales').createLocalizer(Translations);
const DOM = OSjs.require('utils/dom');
const Events = OSjs.require('utils/events');
const Menu = OSjs.require('gui/menu');
const WindowManager = OSjs.require('core/window-manager');

/*eslint valid-jsdoc: "off"*/

const PANEL_SHOW_TIMEOUT = 150;
const PANEL_HIDE_TIMEOUT = 600;

export default class Panel {

  constructor(name, options, wm) {
    options = options || {};

    this._name = name;
    this._$element = null;
    this._$container = null;
    this._items = [];
    this._outtimeout = null;
    this._intimeout = null;
    this._options = options.mergeDefaults({
      position: 'top'
    });

    console.debug('Panel::construct()', this._name, this._options.get());
  }

  init(root) {
    var wm = WindowManager.instance;

    function createMenu(ev) {
      var menu = [
        {title: _('Open Panel Settings'), onClick: function(ev) {
          wm.showSettings('panel');
        }}
      ];

      if ( wm.getSetting('useTouchMenu') === true ) {
        menu.push({
          title: _('Turn off TouchMenu'),
          onClick: function(ev) {
            wm.applySettings({useTouchMenu: false}, false, true);
          }
        });
      } else {
        menu.push({
          title: _('Turn on TouchMenu'),
          onClick: function(ev) {
            wm.applySettings({useTouchMenu: true}, false, true);
          }
        });
      }

      Menu.create(menu, ev);
    }

    this._$container = document.createElement('corewm-panel-container');
    this._$element = document.createElement('corewm-panel');
    this._$element.setAttribute('data-orientation', 'horizontal');
    this._$element.setAttribute('role', 'toolbar');

    /*Utils.$bind(this._$element, 'mousedown', function(ev) {
      ev.preventDefault();
    }); // This makes DnD not work in panel items*/
    Events.$bind(this._$element, 'mouseover', (ev) => {
      this.onMouseOver(ev);
    });
    Events.$bind(this._$element, 'mouseout', (ev) => {
      this.onMouseOut(ev);
    });
    Events.$bind(this._$element, 'contextmenu', function(ev) {
      if ( !ev.target || ev.target.getAttribute('role') !== 'button' ) {
        createMenu(ev);
      }
    });

    Events.$bind(document, 'mouseout:panelmouseleave', (ev) => {
      this.onMouseLeave(ev);
    }, false);

    this._$element.appendChild(this._$container);
    root.appendChild(this._$element);

    setTimeout(() => this.update(), 0);
  }

  destroy() {
    this._clearTimeouts();

    Events.$unbind(document, 'mouseout:panelmouseleave');
    Events.$unbind(this._$element);

    this._items.forEach(function(item) {
      item.destroy();
    });
    this._items = [];
    this._$element = DOM.$remove(this._$element);
    this._$container = null;
  }

  update(options) {
    options = options || this._options.get();

    // CSS IS SET IN THE WINDOW MANAGER!
    var attrs = {
      ontop: !!options.ontop,
      position: options.position || 'bottom'
    };

    if ( options.autohide ) {
      this.onMouseOut();
    }
    if ( this._$element ) {
      Object.keys(attrs).forEach((k) => {
        this._$element.setAttribute('data-' + k, typeof attrs[k] === 'boolean' ? (attrs[k] ? 'true' : 'false') : attrs[k]);
      });
    }
    this._options.set(null, options);
  }

  autohide(hide) {
    if ( !this._options.get('autohide') || !this._$element ) {
      return;
    }

    if ( hide ) {
      this._$element.setAttribute('data-autohide', 'true');
    } else {
      this._$element.setAttribute('data-autohide', 'false');
    }
  }

  _clearTimeouts() {
    if ( this._outtimeout ) {
      clearTimeout(this._outtimeout);
      this._outtimeout = null;
    }
    if ( this._intimeout ) {
      clearTimeout(this._intimeout);
      this._intimeout = null;
    }
  }

  onMouseLeave(ev) {
    var from = ev.relatedTarget || ev.toElement;
    if ( !from || from.nodeName === 'HTML' ) {
      this.onMouseOut(ev);
    }
  }

  onMouseOver() {
    this._clearTimeouts();
    this._intimeout = setTimeout(() => {
      this.autohide(false);
    }, PANEL_SHOW_TIMEOUT);
  }

  onMouseOut() {
    this._clearTimeouts();
    this._outtimeout = setTimeout(() => {
      this.autohide(true);
    }, PANEL_HIDE_TIMEOUT);
  }

  addItem(item) {
    if ( !(item instanceof PanelItem) ) {
      throw 'Expected a PanelItem in Panel::addItem()';
    }

    this._items.push(item);
    this._$container.appendChild(item.init());
  }

  isAutoHidden() {
    if ( this._$element ) {
      return this._$element.getAttribute('data-autohide') === 'true';
    }

    return false;
  }

  getItemByType(type) {
    return this.getItem(type);
  }

  getItemsByType(type) {
    return this.getItem(type, true);
  }

  getItem(type, multiple) {
    var result = multiple ? [] : null;

    this._items.forEach(function(item, idx) {
      if ( item instanceof type ) {
        if ( multiple ) {
          result.push(item);
        } else {
          result = item;
          return false;
        }
      }
      return true;
    });

    return result;
  }

  getOntop() {
    return this._options.get('ontop');
  }

  getPosition(pos) {
    return pos ? (this._options.get('position') === pos) : this._options.get('position');
  }

  getAutohide() {
    return this._options.get('autohide');
  }

  getRoot() {
    return this._$element;
  }

  getHeight() {
    return this._$element ? this._$element.offsetHeight : 0;
  }
}
<|endoftext|>