<commit_before>'use strict';

var generators = require('yeoman-generator'),
    _ = require('lodash'),
    chalk = require('chalk'),
    yosay = require('yosay'),
    chip = require('chip')();

module.exports = generators.Base.extend({
    constructor: function() {
        generators.Base.apply(this, arguments);

        this.argument('appname', { type: String, required: true });

        chip('Application Name (arg): ' + this.appname);
        this.appname = _.kebabCase(this.appname);

        this.option('include-utils', {
            desc: 'Optionally includes Angular-UI Utils library.',
            type: Boolean,
            default: false
        });
    },

    initializing: function() {
        this.pkg = {
            name: '<%= pkg.name %>',
            title: '<%= pkg.title %>',
            url: '<%= pkg.url %>',
            author: '<%= pkg.author %>',
            version: '<%= pkg.version %>',
            copyright: '<%= pkg.copyright %>',
            license: '<%= pkg.license %>'
        };
        this.project = {
            src: '<%= project.src %>',
            dist: '<%= project.dist %>',
            dist_src: '<%= project.dist_src %>',
            app: '<%= project.app %>',
            index: '<%= project.index %>',
            assets: '<%= project.assets %>',
            css: '<%= project.css %>',
            js: '<%= project.js %>'
        };
        this.tag = {
            banner: '<%= tag.banner %>'
        };
        this.connect = {
            options: {
                port: '<%= connect.options.port %>'
            }
        };
    },
    prompting: function() {
        this.log(yosay('Welcome to ' + chalk.yellow.bold('NSWD Angular') + ' Generator!\n'));

        var done = this.async();
        this.prompt([{
            type: 'input',
            name: 'ngappname',
            message: 'Angular Application Name (ng-app)',
            default: this.config.get('ngappname') || 'app'
        },
        {
            type: 'checkbox',
            name: 'dependencies',
            message: 'Which JS Libraries would you like to include?',
            choices: [{
                name: 'lodash: ^4.6.1',
                value: 'lodash',
                checked: true
            },{
                name: 'moment: ^2.12.0',
                value: 'momentjs',
                checked: true
            },{
                name: 'angular-ui-utils: ^3.0.0',
                value: 'angularuiutils',
                checked: true
            }]
        }], function(answers) {
            this.config.set('ngappname', _.camelCase(answers.ngappname));
            this.config.save();

            this.includeLodash = _.includes(answers.dependencies, 'lodash');
            this.includeMoment = _.includes(answers.dependencies, 'momentjs');
            this.includeAngularUIUtils = _.includes(answers.dependencies, 'angularuiutils');

            this.log('\n');
            chip('The required libraries will be installed:')
            chip.info('angular: ^1.5.0');
            chip.info('angular-route: ^1.5.0');
            chip.info('angular-animate: ^1.5.0');
            chip.info('angular-bootstrap: ^1.2.4');
            chip.info('angular-loading-bar: ^0.8.0');
            chip.info('bootstrap-css-only: ^3.3.6\n');
            chip('Additional libraries will be installed:');
            this.includeLodash ? chip.info('lodash: ^4.6.1') : chip.error('lodash: ^4.6.1');
            this.includeMoment ? chip.info('moment: ^2.12.0') : chip.error('moment: ^2.12.0');
            this.includeAngularUIUtils ? chip.info('angular-ui-utils: ^3.0.0\n') : chip.error('angular-ui-utils: ^3.0.0\n');

            done();
        }.bind(this));
    },
    configuring: function() {
    },
    writing: {
        gulpfile: function() {
            this.copy('_Gruntfile.js', 'Gruntfile.js'),
            {
                pkg: this.pkg,
                project: this.project,
                tag: this.tag,
                connect: this.connect
            }
            this.copy('jshintrc', '.jshintrc');
        },
        packageJSON: function() {
            this.copy('_package.json', 'package.json');
        },
        git: function() {
            this.composeWith('common', {
                options: {
                    'skip-messages': true,
                    gitignore: true,
                    gitattributes: true,
                    jshintrc: false,
                    editorconfig: false,
                    'test-jshintrc': false
                }
            },
            {
                local: require.resolve('generator-common')
            });
        },
        bower: function() {
            var bowerJson = {
                name: this.appname,
                license: 'MIT',
                dependencies: {}
            };

            bowerJson.dependencies['angular'] = '^1.5.0';
            bowerJson.dependencies['angular-animate'] = '^1.5.0';
            bowerJson.dependencies['angular-bootstrap'] = '^1.2.4';
            bowerJson.dependencies['angular-loading-bar'] = '^0.8.0';
            bowerJson.dependencies['angular-route'] = '^1.5.0';
            bowerJson.dependencies['bootstrap-css-only'] = '^3.3.6';
            if(this.includeLodash) {
                bowerJson.dependencies['lodash'] = '^4.6.1';
            }
            if(this.includeMoment) {
                bowerJson.dependencies['moment'] = '^2.12.0';
            }
            if(this.includeAngularUIUtils) {
                bowerJson.dependencies['angular-ui-utils'] = '^3.0.0';
            }
            this.fs.writeJSON('bower.json', bowerJson);
            this.copy('bowerrc', '.bowerrc');
        },
        appStaticFiles: function() {
            this.copy('_favicon.ico', 'app/favicon.ico');
            this.directory('app/scss', 'src/scss');
            this.directory('app/css', 'app/assets/css');
            this.directory('app/fonts', 'app/assets/fonts');
            this.directory('app/images', 'app/assets/images');
            this.directory('app/app/directives', 'app/assets/app/directives');
            this.directory('app/app/filters', 'app/assets/app/filters');
            this.directory('app/app/services', 'app/assets/app/services');
        },
        scripts: function() {
            this.fs.copyTpl(
                this.templatePath('app/js/_app.js'),
                this.destinationPath('app/assets/js/app.js'),
                {
                    ngapp: this.config.get('ngappname')
                }
            );
            this.fs.copyTpl(
                this.templatePath('app/app/controllers/_shell.controller.js'),
                this.destinationPath('app/assets/app/controllers/shell.controller.js'),
                {
                    ngapp: this.config.get('ngappname')
                }
            );
            this.fs.copyTpl(
                this.templatePath('app/app/controllers/_about.controller.js'),
                this.destinationPath('app/assets/app/controllers/about.controller.js'),
                {
                    ngapp: this.config.get('ngappname')
                }
            );
            this.fs.copyTpl(
                this.templatePath('app/app/controllers/_home.controller.js'),
                this.destinationPath('app/assets/app/controllers/home.controller.js'),
                {
                    ngapp: this.config.get('ngappname')
                }
            );
        },
        html: function() {
            this.fs.copyTpl(
                this.templatePath('_index.html'),
                this.destinationPath('app/index.html'),
                {
                    appname: _.startCase(this.appname),
                    ngapp: this.config.get('ngappname'),
                    currentYear: new Date().getFullYear()>2016 ? ' - ' + new Date().getFullYear() : ''
                }
            );
            this.fs.copyTpl(
                this.templatePath('app/app/views/_shell.html'),
                this.destinationPath('app/assets/app/views/shell.html'),
                {
                    appname: _.startCase(this.appname)
                }
            );
            this.fs.copyTpl(
                this.templatePath('app/app/views/_about.html'),
                this.destinationPath('app/assets/app/views/about.html')
            );
            this.fs.copyTpl(
                this.templatePath('app/app/views/_home.html'),
                this.destinationPath('app/assets/app/views/home.html')
            );
        },
    },
    conflicts: function() {
    },
    install: function() {
        //this.bowerInstall();
        //this.npmInstall();
        this.installDependencies({
            skipInstall: this.options['skip-install']
        });
    },
    end: function() {
        chip(chalk.yellow.bold('Installation successful!\n'));

        var howToInstall =
            'After running ' + chalk.yellow.bold('npm install & bower install') +
            ', enjoy in your work using ' +
            chalk.yellow.bold('NSWD Angular') +
            ' Generator.';

        if (this.options['skip-install']) {
            chip(howToInstall);
            return;
        }
    }
});<commit_msg>Added files via upload<commit_after>'use strict';

var generators = require('yeoman-generator'),
    _ = require('lodash'),
    chalk = require('chalk'),
    yosay = require('yosay'),
    chip = require('chip')();

module.exports = generators.Base.extend({
    constructor: function() {
        generators.Base.apply(this, arguments);

        this.argument('appname', { type: String, required: true });

        chip('Application Name (arg): ' + this.appname);
        this.appname = _.kebabCase(this.appname);

        this.option('include-utils', {
            desc: 'Optionally includes Angular-UI Utils library.',
            type: Boolean,
            default: false
        });
    },

    initializing: function() {
        this.pkg = {
            name: '<%= pkg.name %>',
            title: '<%= pkg.title %>',
            url: '<%= pkg.url %>',
            author: '<%= pkg.author %>',
            version: '<%= pkg.version %>',
            copyright: '<%= pkg.copyright %>',
            license: '<%= pkg.license %>'
        };
        this.project = {
            src: '<%= project.src %>',
            dist: '<%= project.dist %>',
            dist_src: '<%= project.dist_src %>',
            app: '<%= project.app %>',
            index: '<%= project.index %>',
            assets: '<%= project.assets %>',
            css: '<%= project.css %>',
            js: '<%= project.js %>'
        };
        this.tag = {
            banner: '<%= tag.banner %>'
        };
        this.connect = {
            options: {
                port: '<%= connect.options.port %>'
            }
        };
    },
    prompting: function() {
        this.log(yosay('Welcome to ' + chalk.yellow.bold('NSWD Angular') + ' Generator!\n'));

        var done = this.async();
        this.prompt([{
            type: 'input',
            name: 'ngappname',
            message: 'Angular Application Name (ng-app)',
            default: this.config.get('ngappname') || 'app'
        },
        {
            type: 'checkbox',
            name: 'dependencies',
            message: 'Which JS Libraries would you like to include?',
            choices: [{
                name: 'lodash: ^4.6.1',
                value: 'lodash',
                checked: true
            },{
                name: 'moment: ^2.12.0',
                value: 'momentjs',
                checked: true
            },{
                name: 'angular-ui-utils: ^3.0.0',
                value: 'angularuiutils',
                checked: true
            }]
        }], function(answers) {
            this.config.set('ngappname', _.camelCase(answers.ngappname));
            this.config.save();

            this.includeLodash = _.includes(answers.dependencies, 'lodash');
            this.includeMoment = _.includes(answers.dependencies, 'momentjs');
            this.includeAngularUIUtils = _.includes(answers.dependencies, 'angularuiutils');

            this.log('\n');
            chip('The required libraries will be installed:')
            chip.info('angular: ^1.5.0');
            chip.info('angular-route: ^1.5.0');
            chip.info('angular-animate: ^1.5.0');
            chip.info('angular-bootstrap: ^1.2.4');
            chip.info('angular-loading-bar: ^0.8.0');
            chip.info('bootstrap-css-only: ^3.3.6\n');
            chip('Additional libraries will be installed:');
            this.includeLodash ? chip.info('lodash: ^4.6.1') : chip.error('lodash: ^4.6.1');
            this.includeMoment ? chip.info('moment: ^2.12.0') : chip.error('moment: ^2.12.0');
            this.includeAngularUIUtils ? chip.info('angular-ui-utils: ^3.0.0\n') : chip.error('angular-ui-utils: ^3.0.0\n');

            done();
        }.bind(this));
    },
    configuring: function() {
    },
    writing: {
        gruntfile: function() {
            this.copy('_Gruntfile.js', 'Gruntfile.js'),
            {
                pkg: this.pkg,
                project: this.project,
                tag: this.tag,
                connect: this.connect
            }
            this.copy('jshintrc', '.jshintrc');
        },
        packageJSON: function() {
            this.copy('_package.json', 'package.json');
        },
        configJSON: function() {
            this.copy('_config.json', 'config.json');
        },
        git: function() {
            this.composeWith('common', {
                options: {
                    'skip-messages': true,
                    gitignore: true,
                    gitattributes: true,
                    jshintrc: false,
                    editorconfig: false,
                    'test-jshintrc': false
                }
            },
            {
                local: require.resolve('generator-common')
            });
        },
        bower: function() {
            var bowerJson = {
                name: this.appname,
                license: 'MIT',
                dependencies: {}
            };

            bowerJson.dependencies['angular'] = '^1.5.0';
            bowerJson.dependencies['angular-animate'] = '^1.5.0';
            bowerJson.dependencies['angular-bootstrap'] = '^1.2.4';
            bowerJson.dependencies['angular-loading-bar'] = '^0.8.0';
            bowerJson.dependencies['angular-route'] = '^1.5.0';
            bowerJson.dependencies['bootstrap-css-only'] = '^3.3.6';
            if(this.includeLodash) {
                bowerJson.dependencies['lodash'] = '^4.6.1';
            }
            if(this.includeMoment) {
                bowerJson.dependencies['moment'] = '^2.12.0';
            }
            if(this.includeAngularUIUtils) {
                bowerJson.dependencies['angular-ui-utils'] = '^3.0.0';
            }
            this.fs.writeJSON('bower.json', bowerJson);
            this.copy('bowerrc', '.bowerrc');
        },
        appStaticFiles: function() {
            this.copy('_favicon.ico', 'app/favicon.ico');
            this.directory('app/scss', 'src/scss');
            this.directory('app/css', 'app/assets/css');
            this.directory('app/fonts', 'app/assets/fonts');
            this.directory('app/images', 'app/assets/images');
            this.directory('app/app/directives', 'app/assets/app/directives');
            this.directory('app/app/filters', 'app/assets/app/filters');
            this.directory('app/app/services', 'app/assets/app/services');
        },
        scripts: function() {
            this.fs.copyTpl(
                this.templatePath('app/js/_app.js'),
                this.destinationPath('app/assets/js/app.js'),
                {
                    ngapp: this.config.get('ngappname')
                }
            );
            this.fs.copyTpl(
                this.templatePath('app/app/controllers/_shell.controller.js'),
                this.destinationPath('app/assets/app/controllers/shell.controller.js'),
                {
                    ngapp: this.config.get('ngappname')
                }
            );
            this.fs.copyTpl(
                this.templatePath('app/app/controllers/_about.controller.js'),
                this.destinationPath('app/assets/app/controllers/about.controller.js'),
                {
                    ngapp: this.config.get('ngappname')
                }
            );
            this.fs.copyTpl(
                this.templatePath('app/app/controllers/_home.controller.js'),
                this.destinationPath('app/assets/app/controllers/home.controller.js'),
                {
                    ngapp: this.config.get('ngappname')
                }
            );
        },
        html: function() {
            this.fs.copyTpl(
                this.templatePath('_index.html'),
                this.destinationPath('app/index.html'),
                {
                    appname: _.startCase(this.appname),
                    ngapp: this.config.get('ngappname'),
                    currentYear: new Date().getFullYear()>2016 ? ' - ' + new Date().getFullYear() : ''
                }
            );
            this.fs.copyTpl(
                this.templatePath('app/app/views/_shell.html'),
                this.destinationPath('app/assets/app/views/shell.html'),
                {
                    appname: _.startCase(this.appname)
                }
            );
            this.fs.copyTpl(
                this.templatePath('app/app/views/_about.html'),
                this.destinationPath('app/assets/app/views/about.html')
            );
            this.fs.copyTpl(
                this.templatePath('app/app/views/_home.html'),
                this.destinationPath('app/assets/app/views/home.html')
            );
        },
    },
    conflicts: function() {
    },
    install: function() {
        //this.bowerInstall();
        //this.npmInstall();
        this.installDependencies({
            skipInstall: this.options['skip-install']
        });
    },
    end: function() {
        chip(chalk.yellow.bold('Installation successful!\n'));

        var howToInstall =
            'After running ' + chalk.yellow.bold('npm install & bower install') +
            ', enjoy in your work using ' +
            chalk.yellow.bold('NSWD Angular') +
            ' Generator.';

        if (this.options['skip-install']) {
            chip(howToInstall);
            return;
        }
    }
});<|endoftext|>


<commit_before>(function () {

    'use strict';

    var util = require('util'),
        path = require('path'),
        fs = require('fs'),
        yeoman = require('yeoman-generator'),
        chalk = require('chalk');

    var ScaffoldGenerator = module.exports = function ScaffoldGenerator(args, options, config) {
        yeoman.generators.Base.apply(this, arguments);

        this.on('end', function () {
            this.installDependencies({
                skipInstall: options['skip-install']
            });
        });

        this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
    };

    util.inherits(ScaffoldGenerator, yeoman.generators.Base);

    ScaffoldGenerator.prototype.askFor = function askFor() {
        var cb = this.async();

        this.log(chalk.cyan('\t \t [ Welcome to Scaffold Generator ] \n \n'));
        this.log(chalk.green('I will guide you to generate your best workflow. Come with me... \n \n'));

        var prompts = [{
                name: 'projectName',
                message: 'What is the name of your project?'
            }, {
                name: 'projectDescription',
                message: 'What is the description?'
            }, {
                name: 'projectMember',
                message: 'Which members involved in the project?'
            }];

        this.prompt(prompts, function (props) {
            for(var item in props) {
                this[item] = props[item];
            }

            cb();
        }.bind(this));
    };

    ScaffoldGenerator.prototype.projectfiles = function projectfiles() {
        this.copy('_editorconfig', '.editorconfig');
        this.copy('_jshintrc', '.jshintrc');
        this.copy('_bowerrc', '.bowerrc');
    };

    ScaffoldGenerator.prototype.copyScaffold = function copyScaffold() {
        var cb = this.async();

        this.log.writeln('Downloading version ' + this.version + ' of Ghost');
        this.tarball('https://github.com/marcosmoura/scaffold/archive/master.zip', '.', cb);
    };

})();
<commit_msg>Creates the package.json based on the answers<commit_after>(function () {

    'use strict';

    var util = require('util'),
        path = require('path'),
        slug = require('slug'),
        fs = require('fs'),
        yeoman = require('yeoman-generator'),
        chalk = require('chalk');

    var ScaffoldGenerator = module.exports = function ScaffoldGenerator(args, options, config) {
        yeoman.generators.Base.apply(this, arguments);

        this.on('end', function () {
            this.installDependencies({
                skipInstall: options['skip-install']
            });
        });

        this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
    };

    util.inherits(ScaffoldGenerator, yeoman.generators.Base);

    ScaffoldGenerator.prototype.askFor = function askFor() {
        var cb = this.async();

        this.log(chalk.cyan('\t \t [ Welcome to Scaffold Generator ] \n \n'));
        this.log(chalk.green('I will guide you to generate your best workflow. Come with me... \n \n'));

        var prompts = [{
                name: 'projectName',
                message: 'What is the name of your project?'
            }, {
                name: 'projectDescription',
                message: 'What is the description?'
            }, {
                name: 'projectMember',
                message: 'Which members involved in the project?'
            }];

        this.prompt(prompts, function (props) {
            for(var item in props) {
                this[item] = props[item];
            }

            cb();
        }.bind(this));
    };

    ScaffoldGenerator.prototype.downloadScaffold = function downloadScaffold() {
        var cb = this.async();

        this.log(chalk.green('\n \n Downloading scaffold'));
        this.tarball('https://github.com/marcosmoura/scaffold/archive/master.zip', '.', cb);
    };

    ScaffoldGenerator.prototype.overwritePackage = function overwritePackage() {
        var pkgPath = path.join(this.env.cwd, 'package.json'),
            pkg = JSON.parse(this.readFileAsString(pkgPath));

        pkg.projectName = this.projectName;
        pkg.name = slug(this.projectName).toLowerCase();
        pkg.description = this.projectDescription;
        pkg.developers = this.projectMember;

        var dev = this.projectMember.split(','),
            devList = [];

        for(var member in dev) {
            devList.push({
                'name': dev[member].trim()
            });
        }

        pkg.author = devList;

        this.write(pkgPath, JSON.stringify(pkg, null, 2));
    };

})();
<|endoftext|>


<commit_before>const {remote, ipcRenderer} = require('electron')
const csv = require('fast-csv')
const swappy = require('swappy-client')
const url = require('url')
const path = require('path')
const fs = require('fs')
const Line = require('../Line')
const settings = require('electron-settings')

settings.get('account.token').then(val => {
    console.log('Fetched token', val)
    if (val) {
        app.setToken(val)
    }
})

let partitionInc = 1;

const app = new Vue({
    el: '#app',
    data: {
        headers: Line.getHeaders(),
        lastClickedLine: null,
        access_token: null,
        login: null,
        filePath: null,
        lines: [],
        uploading: false,
        uploadMessages: [],
        uploadDone: false,
        uploadCanceled: false,
        showLine: {
            index: null,
            line: null
        }
    },
    computed: {
        selectedLines() {
            return this.lines.filter((line) => {
                return line.selected
            })
        }
    },
    methods: {
        cancelUpload() {
            console.error('Cancel upload')
            this.uploadCanceled = true
            this.uploadDone = true
        },
        addUploadMessage(message, error = false) {
            this.uploadMessages.unshift({
                message: message,
                error: error
            })
        },
        addUploadError(error) {
            this.addUploadMessage(error, true)
        },
        pushLine(data) {
            let line = new Line(data)
            this.lines.push(line)
        },
        openDialog() {

            let file = remote.dialog.showOpenDialog({
                properties: ['openFile'],
                filters: [
                    {name: 'Comma-Separated Values (CSV)', extensions: ['csv', 'txt']},
                    {name: 'All Files', extensions: ['*']}
                ]
            })
            if (file) {
                this.openFile(file[0])
            }
        },
        openFile(filePath) {
            //Save base dir
            this.filePath = filePath

            //Import CSV file
            this.lines = []
            csv
                .fromPath(filePath, {
                    headers: true,
                    delimiter: ',',
                    quote: '"',
                    escape: '"',
                    trim: true,
                })
                .on("data", (data) => {
                    this.pushLine(data)
                })
                .on("end", () => {
                    console.log('file', filePath, 'loaded')
                    ipcRenderer.send('fileModified', false)
                })
        },
        saveFile() {
            let csvStream = csv.createWriteStream({
                    headers: true,
                    delimiter: ',',
                    quote: '"',
                    escape: '"',
                }),
                writableStream = fs.createWriteStream(this.filePath)

            writableStream.on("finish", function () {
                ipcRenderer.send('fileModified', false)
            })

            csvStream.pipe(writableStream)
            for (let line of this.lines) {
                csvStream.write(line)
            }
            csvStream.end()

        },
        sendLines() {
            if (!this.lines.length) {
                return alert('Please select a CSV file first!')
            }
            if (!this.access_token) {
                return this.authenticate((error) => {
                    if (error) {
                        this.addUploadMessage('Auth error: ' + error, true)
                        console.error('Authenticate error', error)
                        this.uploading = false
                        return
                    }
                    this.sendLines()
                })
            }
            let lines = this.selectedLines
            if (!lines.length) {
                lines = this.lines
            }

            //Reset errors
            for (let line of lines) {
                line.errors = []
            }

            this.uploadMessages = []
            this.uploading = lines.length
            this.addUploadMessage('Uploading ' + lines.length + ' lines...')
            this.uploadImages(lines, () => {
                this.addUploadMessage('All images ready, sending lines...')
                this.sendReadyLines(lines, () => {
                    this.addUploadMessage('Done!')
                    this.uploadDone = true
                })
            })
        },
        uploadImages(lines, callback, index = 0) {
            if (this.uploadCanceled) return
            if (index >= lines.length) {
                return callback()
            }
            let nextCallback = () => {
                    this.uploadImages(lines, callback, index + 1)
                },
                line = lines[index]
            if (line.areImagesReady()) {
                return nextCallback()
            }
            this.selectLine({}, index, line)

            let imagesPath = []

            for (let image of line.getJson().images) {
                let imagePath = path.join(path.dirname(this.filePath), image.url)
                try {
                    let stats = fs.lstatSync(imagePath)
                    if (stats.isDirectory()) {
                        let fileNames = fs.readdirSync(imagePath)
                        for (let fileName of fileNames) {
                            if (fileName.substr(0, 1) !== '.') {
                                imagesPath.push(path.join(imagePath, fileName))
                            }
                        }
                    } else if (stats.isFile()) {
                        imagesPath.push(imagePath)
                    }
                } catch (e) {
                    let err = 'File/Directory not found ' + imagePath
                    line.errors.push({
                        field: 'images',
                        code: 'invalid',
                        message: err
                    })
                    this.addUploadError('File/Directory not found ' + err)
                    return nextCallback()
                }
            }
            this.addUploadMessage('Uploading ' + imagesPath.length + ' images for ' + line.title)
            this.doUpload(imagesPath, (err, urls) => {
                if (err) {
                    line.errors.push({
                        field: 'images',
                        code: 'invalid',
                        message: err
                    })
                }
                line.images = urls.join('|')
                nextCallback()
            })
        },
        doUpload: function (imagesPath, callback, urls = []) {
            if (this.uploadCanceled) return
            this.getClient((error, SwappyClient) => {
                if (error) {
                    this.addUploadMessage('Error: ' + error, true)
                    this.uploading = false
                    return
                }
                let productsApi = new SwappyClient.ProductsApi()
                productsApi.uploadPicture(fs.createReadStream(imagesPath.pop()), {}, (err, results, response) => {
                    if (err) {
                        return callback(err, urls)
                    }
                    urls.push(results[0].url)
                    if (imagesPath.length) {
                        this.doUpload(imagesPath, callback, urls)
                    } else {
                        callback(null, urls)
                    }
                })
            })
        },
        sendReadyLines: function (lines, callback, index = 0) {
            if (this.uploadCanceled) return
            if (index >= lines.length) {
                return callback()
            }
            let nextCallback = () => {
                    this.sendReadyLines(lines, callback, index + 1)
                },
                line = lines[index]
            if (!line.areImagesReady()) {
                return nextCallback()
            }
            this.doSendLine(line, nextCallback)
        },
        doSendLine(line, callback) {
            if (this.uploadCanceled) return
            this.getClient((error, SwappyClient) => {
                if (error) {
                    this.addUploadMessage('Error: ' + error, true)
                    this.uploading = false
                    return
                }
                let productsApi = new SwappyClient.ProductsApi(),
                    product = new swappy.Product.constructFromObject(line.getJson()),
                    updating = !!line.id

                this.addUploadMessage('Importing product ' + line.title)

                let responseCallback = (err, data, response) => {
                    if (err) {
                        if (err.status == 422 && err.response.body.message == "Validation Failed") {
                            line.errors = err.response.body.errors
                            console.log('errors', err.response.body.errors)
                            this.addUploadError('Validation error importing product ' + line.title)
                            return callback()
                        } else {
                            console.error(err)
                            this.addUploadError('Unexpected error: ' + (err.response ? err.response.body.message : err))
                            this.uploadDone = true
                            return console.error(err)
                        }
                    }
                    line.selected = false
                    line.id = Number.parseInt(data.id)
                    if (updating) {
                        this.addUploadMessage('Product #' + line.id + ' updated!')
                    } else {
                        this.addUploadMessage('Product imported #' + line.id)
                    }
                    setTimeout(() => {
                        callback()
                    }, 500)
                }

                if (updating) {
                    productsApi.updateProduct(line.id, product, responseCallback)
                } else {
                    productsApi.createProduct(product, {}, responseCallback)
                }
            })
        },
        getClient(callback) {
            if (!this.access_token) {
                return this.authenticate((error) => {
                    if (error) {
                        callback(error)
                    } else {
                        this.getClient(callback)
                    }
                })
            }

            callback(null, swappy)
        },
        authenticate(callback) {
            if (this.access_token) {
                return callback(null, this.access_token)
            } else {
                console.log('No access token')
            }
            let authUrl = "https://api.swappy.com/oauth2/authorize?response_type=token&redirect_uri=https%3A%2F%2Fapi.swappy.com%2Foauth2%2Flogin_success&realm=Service&client_id=swapster&scope=addresses+sell+email&state=",
                state = Math.random()

            let win = new remote.BrowserWindow({
                resizable: false,
                parent: remote.getCurrentWindow(),
                modal: true,
                width: 520,
                height: 420,
                webPreferences: {
                    nodeIntegration: false,
                    partition: 'part' + partitionInc++
                }
            })
            let done = false
            win.loadURL(authUrl + state)
            win.webContents.on('did-get-response-details', (event, status, newURL) => {
                    if (String(newURL).match(/^https:\/\/api\.swappy\.com\/oauth2\/login_success/)) {
                        let parts = url.parse('?' + url.parse(newURL).hash.substr(1), true)
                        done = true
                        win.close()
                        if (parts.query.access_token) {
                            this.setToken(parts.query.access_token, (err, token) => {
                                if (typeof callback === 'function') {
                                    callback(err, token)
                                }
                            })
                        } else {
                            if (typeof callback === 'function') {
                                callback('Error getting access token', null)
                            }
                        }
                    }
                }
            )
            win.on('closed', () => {
                if (!done) {
                    callback('Canceled by user')
                }
                win = null
            })

        },
        setToken(token, callback) {
            this.access_token = token
            swappy.ApiClient.instance.authentications.oauth.accessToken = token
            swappy.ApiClient.instance.timeout = 10000
            settings.set('account', {
                token: token,
            })
            let oauthApi = new swappy.OauthApi()
            oauthApi.getMe({}, (err, res, response) => {
                if (err) {
                    this.resetToken()
                    if (callback && response && response.body && response.body.message == "The access token provided has expired") {
                        return this.authenticate(callback)
                    }
                    console.error(err, res, response)
                    if (callback) {
                        callback(err, null)
                    }
                    return
                }
                this.login = res.login
                if (typeof callback === 'function') {
                    callback(null, token)
                }
            })
        },
        resetToken() {
            this.access_token = null
            this.login = null;
            swappy.ApiClient.instance.authentications.oauth.accessToken = null
            settings.set('account', {
                token: null,
            })
        },
        selectLine(ev, index, line){
            if (ev.altKey) return
            if (!ev.ctrlKey) {
                for (let l of this.lines) {
                    l.selected = false
                }
            }

            line.selected = !line.selected
            if (ev.shiftKey && this.lastClickedLine) {
                for (let i = Math.min(index, this.lastClickedLine); i <= Math.max(index, this.lastClickedLine); i++) {
                    console.log('Line', i, line.selected)
                    this.lines[i].selected = line.selected
                }
            }
            this.lastClickedLine = index
        },
        showLineInfos(index, line) {
            console.log(line.getJson())
            this.showLine = {
                index: index,
                line: line
            }
        }
    }
})

let previousJson = ''
app.$watch('lines', () => {
    let json = []
    for (let line of app.lines) {
        json.push(line.getJson())
    }
    json = JSON.stringify(json)
    if (json != previousJson) {
        console.log('File Modified')
        ipcRenderer.send('fileModified', true)
        previousJson = json
    }
}, {deep: true})

ipcRenderer.on('saveFile', () => {
    app.saveFile()
})

ipcRenderer.on('openFile', (ev, file) => {
    app.openFile(file)
})<commit_msg>Ajout de la suppression des lignes<commit_after>const {remote, ipcRenderer} = require('electron')
const csv = require('fast-csv')
const swappy = require('swappy-client')
const url = require('url')
const path = require('path')
const fs = require('fs')
const Line = require('../Line')
const settings = require('electron-settings')

settings.get('account.token').then(val => {
    console.log('Fetched token', val)
    if (val) {
        app.setToken(val)
    }
})

let partitionInc = 1;

const app = new Vue({
    el: '#app',
    data: {
        headers: Line.getHeaders(),
        lastClickedLine: null,
        access_token: null,
        login: null,
        filePath: null,
        lines: [],
        uploading: false,
        uploadMessages: [],
        uploadDone: false,
        uploadCanceled: false,
        showLine: {
            index: null,
            line: null
        }
    },
    computed: {
        selectedLines() {
            return this.lines.filter((line) => {
                return line.selected
            })
        }
    },
    methods: {
        cancelUpload() {
            console.error('Cancel upload')
            this.uploadCanceled = true
            this.uploadDone = true
        },
        addUploadMessage(message, error = false) {
            this.uploadMessages.unshift({
                message: message,
                error: error
            })
        },
        addUploadError(error) {
            this.addUploadMessage(error, true)
        },
        pushLine(data) {
            let line = new Line(data)
            this.lines.push(line)
        },
        openDialog() {

            let file = remote.dialog.showOpenDialog({
                properties: ['openFile'],
                filters: [
                    {name: 'Comma-Separated Values (CSV)', extensions: ['csv', 'txt']},
                    {name: 'All Files', extensions: ['*']}
                ]
            })
            if (file) {
                this.openFile(file[0])
            }
        },
        openFile(filePath) {
            //Save base dir
            this.filePath = filePath

            //Import CSV file
            this.lines = []
            csv
                .fromPath(filePath, {
                    headers: true,
                    delimiter: ',',
                    quote: '"',
                    escape: '"',
                    trim: true,
                })
                .on("data", (data) => {
                    this.pushLine(data)
                })
                .on("end", () => {
                    console.log('file', filePath, 'loaded')
                    ipcRenderer.send('fileModified', false)
                })
        },
        saveFile() {
            let csvStream = csv.createWriteStream({
                    headers: true,
                    delimiter: ',',
                    quote: '"',
                    escape: '"',
                }),
                writableStream = fs.createWriteStream(this.filePath)

            writableStream.on("finish", function () {
                ipcRenderer.send('fileModified', false)
            })

            csvStream.pipe(writableStream)
            for (let line of this.lines) {
                csvStream.write(line)
            }
            csvStream.end()

        },
        sendLines() {
            if (!this.lines.length) {
                return alert('Please select a CSV file first!')
            }
            if (!this.access_token) {
                return this.authenticate((error) => {
                    if (error) {
                        this.addUploadMessage('Auth error: ' + error, true)
                        console.error('Authenticate error', error)
                        this.uploading = false
                        return
                    }
                    this.sendLines()
                })
            }
            let lines = this.selectedLines
            if (!lines.length) {
                lines = this.lines
            }

            //Reset errors
            for (let line of lines) {
                line.errors = []
            }

            this.uploadMessages = []
            this.uploading = lines.length
            this.addUploadMessage('Uploading ' + lines.length + ' lines...')
            this.uploadImages(lines, () => {
                this.addUploadMessage('All images ready, sending lines...')
                this.sendReadyLines(lines, () => {
                    this.addUploadMessage('Done!')
                    this.uploadDone = true
                })
            })
        },
        uploadImages(lines, callback, index = 0) {
            if (this.uploadCanceled) return
            if (index >= lines.length) {
                return callback()
            }
            let nextCallback = () => {
                    this.uploadImages(lines, callback, index + 1)
                },
                line = lines[index]
            if (line.areImagesReady()) {
                return nextCallback()
            }
            this.selectLine({}, index, line)

            let imagesPath = []

            for (let image of line.getJson().images) {
                let imagePath = path.join(path.dirname(this.filePath), image.url)
                try {
                    let stats = fs.lstatSync(imagePath)
                    if (stats.isDirectory()) {
                        let fileNames = fs.readdirSync(imagePath)
                        for (let fileName of fileNames) {
                            if (fileName.substr(0, 1) !== '.') {
                                imagesPath.push(path.join(imagePath, fileName))
                            }
                        }
                    } else if (stats.isFile()) {
                        imagesPath.push(imagePath)
                    }
                } catch (e) {
                    let err = 'File/Directory not found ' + imagePath
                    line.errors.push({
                        field: 'images',
                        code: 'invalid',
                        message: err
                    })
                    this.addUploadError('File/Directory not found ' + err)
                    return nextCallback()
                }
            }
            this.addUploadMessage('Uploading ' + imagesPath.length + ' images for ' + line.title)
            this.doUpload(imagesPath, (err, urls) => {
                if (err) {
                    line.errors.push({
                        field: 'images',
                        code: 'invalid',
                        message: err
                    })
                }
                line.images = urls.join('|')
                nextCallback()
            })
        },
        doUpload: function (imagesPath, callback, urls = []) {
            if (this.uploadCanceled) return
            this.getClient((error, SwappyClient) => {
                if (error) {
                    this.addUploadMessage('Error: ' + error, true)
                    this.uploading = false
                    return
                }
                let productsApi = new SwappyClient.ProductsApi()
                productsApi.uploadPicture(fs.createReadStream(imagesPath.pop()), {}, (err, results, response) => {
                    if (err) {
                        return callback(err, urls)
                    }
                    urls.push(results[0].url)
                    if (imagesPath.length) {
                        this.doUpload(imagesPath, callback, urls)
                    } else {
                        callback(null, urls)
                    }
                })
            })
        },
        sendReadyLines: function (lines, callback, index = 0) {
            if (this.uploadCanceled) return
            if (index >= lines.length) {
                return callback()
            }
            let nextCallback = () => {
                    this.sendReadyLines(lines, callback, index + 1)
                },
                line = lines[index]
            if (!line.areImagesReady()) {
                return nextCallback()
            }
            this.doSendLine(line, nextCallback)
        },
        doSendLine(line, callback) {
            if (this.uploadCanceled) return
            this.getClient((error, SwappyClient) => {
                if (error) {
                    this.addUploadMessage('Error: ' + error, true)
                    this.uploading = false
                    return
                }
                let productsApi = new SwappyClient.ProductsApi(),
                    product = new swappy.Product.constructFromObject(line.getJson()),
                    updating = !!line.id

                this.addUploadMessage('Importing product ' + line.title)

                let responseCallback = (err, data, response) => {
                    if (err) {
                        if (err.status == 422 && err.response.body.message == "Validation Failed") {
                            line.errors = err.response.body.errors
                            console.log('errors', err.response.body.errors)
                            this.addUploadError('Validation error importing product ' + line.title)
                            return callback()
                        } else {
                            console.error(err)
                            this.addUploadError('Unexpected error: ' + (err.response ? err.response.body.message : err))
                            this.uploadDone = true
                            return console.error(err)
                        }
                    }
                    line.selected = false
                    line.id = Number.parseInt(data.id)
                    if (updating) {
                        this.addUploadMessage('Product #' + line.id + ' updated!')
                    } else {
                        this.addUploadMessage('Product imported #' + line.id)
                    }
                    setTimeout(() => {
                        callback()
                    }, 500)
                }

                if (updating) {
                    productsApi.updateProduct(line.id, product, responseCallback)
                } else {
                    productsApi.createProduct(product, {}, responseCallback)
                }
            })
        },
        getClient(callback) {
            if (!this.access_token) {
                return this.authenticate((error) => {
                    if (error) {
                        callback(error)
                    } else {
                        this.getClient(callback)
                    }
                })
            }

            callback(null, swappy)
        },
        authenticate(callback) {
            if (this.access_token) {
                return callback(null, this.access_token)
            } else {
                console.log('No access token')
            }
            let authUrl = "https://api.swappy.com/oauth2/authorize?response_type=token&redirect_uri=https%3A%2F%2Fapi.swappy.com%2Foauth2%2Flogin_success&realm=Service&client_id=swapster&scope=addresses+sell+email&state=",
                state = Math.random()

            let win = new remote.BrowserWindow({
                resizable: false,
                parent: remote.getCurrentWindow(),
                modal: true,
                width: 520,
                height: 420,
                webPreferences: {
                    nodeIntegration: false,
                    partition: 'part' + partitionInc++
                }
            })
            let done = false
            win.loadURL(authUrl + state)
            win.webContents.on('did-get-response-details', (event, status, newURL) => {
                    if (String(newURL).match(/^https:\/\/api\.swappy\.com\/oauth2\/login_success/)) {
                        let parts = url.parse('?' + url.parse(newURL).hash.substr(1), true)
                        done = true
                        win.close()
                        if (parts.query.access_token) {
                            this.setToken(parts.query.access_token, (err, token) => {
                                if (typeof callback === 'function') {
                                    callback(err, token)
                                }
                            })
                        } else {
                            if (typeof callback === 'function') {
                                callback('Error getting access token', null)
                            }
                        }
                    }
                }
            )
            win.on('closed', () => {
                if (!done) {
                    callback('Canceled by user')
                }
                win = null
            })

        },
        setToken(token, callback) {
            this.access_token = token
            swappy.ApiClient.instance.authentications.oauth.accessToken = token
            swappy.ApiClient.instance.timeout = 10000
            settings.set('account', {
                token: token,
            })
            let oauthApi = new swappy.OauthApi()
            oauthApi.getMe({}, (err, res, response) => {
                if (err) {
                    this.resetToken()
                    if (callback && response && response.body && response.body.message == "The access token provided has expired") {
                        return this.authenticate(callback)
                    }
                    console.error(err, res, response)
                    if (callback) {
                        callback(err, null)
                    }
                    return
                }
                this.login = res.login
                if (typeof callback === 'function') {
                    callback(null, token)
                }
            })
        },
        resetToken() {
            this.access_token = null
            this.login = null;
            swappy.ApiClient.instance.authentications.oauth.accessToken = null
            settings.set('account', {
                token: null,
            })
        },
        selectLine(ev, index, line){
            if (ev.altKey) return
            if (!ev.ctrlKey) {
                for (let l of this.lines) {
                    l.selected = false
                }
            }

            line.selected = !line.selected
            if (ev.shiftKey && this.lastClickedLine) {
                for (let i = Math.min(index, this.lastClickedLine); i <= Math.max(index, this.lastClickedLine); i++) {
                    console.log('Line', i, line.selected)
                    this.lines[i].selected = line.selected
                }
            }
            this.lastClickedLine = index
        },
        showLineInfos(index, line) {
            console.log(line.getJson())
            this.showLine = {
                index: index,
                line: line
            }
        },
        deleteSelectedLines() {
            let message;
            switch(this.selectedLines.length) {
                case 0:
                    return;
                case 1:
                    message = 'Do you really want to delete this line?';
                    break;
                default:
                    message = 'Do you really want to delete this ' + this.selectedLines.length + ' lines?';
                    break;
            }
            if(confirm(message)) {
                for(let line of this.selectedLines) {
                    let index = this.lines.indexOf(line);
                    this.lines.splice(index, 1);
                }
            }
        }
    }
})

let previousJson = ''
app.$watch('lines', () => {
    let json = []
    for (let line of app.lines) {
        json.push(line.getJson())
    }
    json = JSON.stringify(json)
    if (json != previousJson) {
        console.log('File Modified')
        ipcRenderer.send('fileModified', true)
        previousJson = json
    }
}, {deep: true})

ipcRenderer.on('saveFile', () => {
    app.saveFile()
})

ipcRenderer.on('openFile', (ev, file) => {
    app.openFile(file)
})

window.addEventListener('keypress', function (ev) {
    if (ev.key == 'Delete' && !ev.shiftKey && !ev.altKey && !ev.ctrlKey) {
        app.deleteSelectedLines();
    }
});<|endoftext|>


<commit_before>'use strict';
var util = require('util');
var path = require('path');
var yeoman = require('yeoman-generator');
var generators = yeoman.generators;
var yosay = require('yosay');
var chalk = require('chalk');

var HotTowelGenerator = generators.Base.extend({

    constructor: function() {
        // arguments and options should be
        // defined in the constructor.
        generators.Base.apply(this, arguments);

        this.argument('appName', { type: String, required: false });
        this.appName = this._.camelize(this._.slugify(this._.humanize(this.appName)));
    },

    welcome: function() {
        this.log(yosay(
            'Welcome to the HotTowel AngularJS generator!'
        ));
    },

    prompting: function () {
        // If we passed in the app name, don't prompt the user for it
        if(this.appName) {
            return;
        }

        var done = this.async();

        var prompts = [{
            type: 'input',
            name: 'appName',
            message: 'What would you like to name the app?',
            default: this.appName || path.basename(process.cwd())
        }];

        this.prompt(prompts, function (answers) {
            this.appName = answers.appName;
            this.appName = this.appName || 'hottowel'; //path.basename(process.cwd());
            done();
        }.bind(this));
    },

    displayName: function() {
        this.log('Creating ' + this.appName + ' app based on HotTowel.');
    },

    scaffoldFolders: function () {
        this.mkdir('src');
        this.mkdir('src/client');
        this.mkdir('src/client/app');
        this.mkdir('src/server');
    },

    packageFiles: function () {
        var context = {
            appName: this.appName
        };

        this.copy('_package.json', 'package.json');
        this.template('_bower.json', 'bower.json');
        this.template('_gulpfile.js', 'gulpfile.js');
        this.template('_gulp.config.js', 'gulp.config.js');
        this.template('_karma.conf.js', 'karma.conf.js');
        this.template('_README.md', 'README.md');
    },

    assets: function () {
        this.copy('gulp.png', 'gulp.png');
    },

    testRunnerFiles: function () {
        this.template('src/client/_specs.html', 'src/client/specs.html');
    },

    appFiles: function () {
        this.directory('src/client/app');
        this.directory('src/client/content');
        this.directory('src/client/test-helpers');

        this.template('src/client/_index.html', 'src/client/index.html');

        this.template('src/server/_app.js', 'src/server/app.js');
        this.copy('src/server/favicon.ico');
    },

    projectfiles: function () {
        this.copy('editorconfig', '.editorconfig');
        this.copy('jshintrc', '.jshintrc');
        this.copy('jscsrc', '.jscsrc');
        this.copy('bowerrc', '.bowerrc');
    },

    runNpm: function () {
//        var done = this.async();
//        this.npmInstall('', function () {
//            console.log('\nEverything Setup!\n');
//            done();
//        });
              this.npmInstall();
//              this.bowerInstall();
              console.log('\nEverything Setup !!!\n');
    },

    end: function () {
//        this.installDependencies();
    }
});

module.exports = HotTowelGenerator;
<commit_msg>copy images and styles folders<commit_after>'use strict';
var util = require('util');
var path = require('path');
var yeoman = require('yeoman-generator');
var generators = yeoman.generators;
var yosay = require('yosay');
var chalk = require('chalk');

var HotTowelGenerator = generators.Base.extend({

    constructor: function() {
        // arguments and options should be
        // defined in the constructor.
        generators.Base.apply(this, arguments);

        this.argument('appName', { type: String, required: false });
        this.appName = this._.camelize(this._.slugify(this._.humanize(this.appName)));
    },

    welcome: function() {
        this.log(yosay(
            'Welcome to the HotTowel AngularJS generator!'
        ));
    },

    prompting: function () {
        // If we passed in the app name, don't prompt the user for it
        if(this.appName) {
            return;
        }

        var done = this.async();

        var prompts = [{
            type: 'input',
            name: 'appName',
            message: 'What would you like to name the app?',
            default: this.appName || path.basename(process.cwd())
        }];

        this.prompt(prompts, function (answers) {
            this.appName = answers.appName;
            this.appName = this.appName || 'hottowel'; //path.basename(process.cwd());
            done();
        }.bind(this));
    },

    displayName: function() {
        this.log('Creating ' + this.appName + ' app based on HotTowel.');
    },

    scaffoldFolders: function () {
        this.mkdir('src');
        this.mkdir('src/client');
        this.mkdir('src/client/app');
        this.mkdir('src/server');
    },

    packageFiles: function () {
        var context = {
            appName: this.appName
        };

        this.copy('_package.json', 'package.json');
        this.template('_bower.json', 'bower.json');
        this.template('_gulpfile.js', 'gulpfile.js');
        this.template('_gulp.config.js', 'gulp.config.js');
        this.template('_karma.conf.js', 'karma.conf.js');
        this.template('_README.md', 'README.md');
    },

    assets: function () {
        this.copy('gulp.png', 'gulp.png');
    },

    testRunnerFiles: function () {
        this.template('src/client/_specs.html', 'src/client/specs.html');
    },

    appFiles: function () {
        this.directory('src/client/app');
        this.directory('src/client/images');
        this.directory('src/client/styles');
        this.directory('src/client/test-helpers');

        this.template('src/client/_index.html', 'src/client/index.html');

        this.template('src/server/_app.js', 'src/server/app.js');
        this.copy('src/server/favicon.ico');
    },

    projectfiles: function () {
        this.copy('editorconfig', '.editorconfig');
        this.copy('jshintrc', '.jshintrc');
        this.copy('jscsrc', '.jscsrc');
        this.copy('bowerrc', '.bowerrc');
    },

    runNpm: function () {
//        var done = this.async();
//        this.npmInstall('', function () {
//            console.log('\nEverything Setup!\n');
//            done();
//        });
              this.npmInstall();
//              this.bowerInstall();
              console.log('\nEverything Setup !!!\n');
    },

    end: function () {
//        this.installDependencies();
    }
});

module.exports = HotTowelGenerator;
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @constructor
 * @implements {WebInspector.TargetManager.Observer}
 */
WebInspector.CSSWorkspaceBinding = function()
{
    /** @type {!Map.<!WebInspector.Target, !WebInspector.CSSWorkspaceBinding.TargetInfo>} */
    this._targetToTargetInfo = new Map();
    WebInspector.targetManager.observeTargets(this);

    WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameCreatedOrNavigated, this);
}

WebInspector.CSSWorkspaceBinding.prototype = {
    /**
     * @param {!WebInspector.Target} target
     */
    targetAdded: function(target)
    {
        this._targetToTargetInfo.put(target, new WebInspector.CSSWorkspaceBinding.TargetInfo(target, WebInspector.workspace, WebInspector.networkWorkspaceBinding));
    },

    /**
     * @param {!WebInspector.Target} target
     */
    targetRemoved: function(target)
    {
        this._targetToTargetInfo.remove(target)._dispose();
    },

    /**
     * @param {!WebInspector.CSSStyleSheetHeader} header
     * @param {!WebInspector.SourceMapping} mapping
     */
    pushSourceMapping: function(header, mapping)
    {
        this._ensureInfoForHeader(header)._pushSourceMapping(mapping);
    },

    /**
     * @param {!WebInspector.CSSStyleSheetHeader} header
     * @return {?WebInspector.CSSWorkspaceBinding.HeaderInfo}
     */
    _headerInfo: function(header)
    {
        var map = this._targetToTargetInfo.get(header.target());
        return map._headerInfo(header.id) || null;
    },

    /**
     * @param {!WebInspector.CSSStyleSheetHeader} header
     * @return {!WebInspector.CSSWorkspaceBinding.HeaderInfo}
     */
    _ensureInfoForHeader: function(header)
    {
        var targetInfo = this._targetToTargetInfo.get(header.target());
        if (!targetInfo) {
            targetInfo = new WebInspector.CSSWorkspaceBinding.TargetInfo(header.target(), WebInspector.workspace, WebInspector.networkWorkspaceBinding);
            this._targetToTargetInfo.put(header.target(), targetInfo);
        }
        return targetInfo._ensureInfoForHeader(header);
    },

    /**
     * @param {!WebInspector.Event} event
     */
    _mainFrameCreatedOrNavigated: function(event)
    {
        var target = /** @type {!WebInspector.ResourceTreeModel} */ (event.target).target();
        var info = this._targetToTargetInfo.remove(target);
        if (info)
            info._dispose();
        this._targetToTargetInfo.put(target, new WebInspector.CSSWorkspaceBinding.TargetInfo(target, WebInspector.workspace, WebInspector.networkWorkspaceBinding));
    },

    /**
     * @param {!WebInspector.CSSStyleSheetHeader} header
     */
    updateLocations: function(header)
    {
        var info = this._headerInfo(header);
        if (info)
            info._updateLocations();
    },

    /**
     * @param {!WebInspector.CSSLocation} rawLocation
     * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate
     * @return {!WebInspector.CSSWorkspaceBinding.LiveLocation}
     */
    createLiveLocation: function(rawLocation, updateDelegate)
    {
        var header = rawLocation.styleSheetId ? rawLocation.target().cssModel.styleSheetHeaderForId(rawLocation.styleSheetId) : null;
        return new WebInspector.CSSWorkspaceBinding.LiveLocation(rawLocation.target().cssModel, header, rawLocation, updateDelegate);
    },

    /**
     * @param {!WebInspector.CSSWorkspaceBinding.LiveLocation} location
     */
    _addLiveLocation: function(location)
    {
        this._ensureInfoForHeader(location._header)._addLocation(location);
    },

    /**
     * @param {!WebInspector.CSSWorkspaceBinding.LiveLocation} location
     */
    _removeLiveLocation: function(location)
    {
        var info = this._headerInfo(location._header);
        if (info)
            info._removeLocation(location);
    },

    /**
     * @param {!WebInspector.CSSProperty} cssProperty
     * @param {boolean} forName
     * @return {?WebInspector.UILocation}
     */
    propertyUILocation: function(cssProperty, forName)
    {
        var style = cssProperty.ownerStyle;
        if (!style || !style.parentRule || !style.styleSheetId)
            return null;

        var range = cssProperty.range;
        if (!range)
            return null;

        var url = style.parentRule.resourceURL();
        if (!url)
            return null;

        var line = forName ? range.startLine : range.endLine;
        // End of range is exclusive, so subtract 1 from the end offset.
        var column = forName ? range.startColumn : range.endColumn - (cssProperty.text && cssProperty.text.endsWith(";") ? 2 : 1);
        var rawLocation = new WebInspector.CSSLocation(style.target(), style.styleSheetId, url, line, column);
        return this.rawLocationToUILocation(rawLocation);
    },

    /**
     * @param {?WebInspector.CSSLocation} rawLocation
     * @return {?WebInspector.UILocation}
     */
    rawLocationToUILocation: function(rawLocation)
    {
        if (!rawLocation)
            return null;
        var cssModel = rawLocation.target().cssModel;
        var frameIdToSheetIds = cssModel.styleSheetIdsByFrameIdForURL(rawLocation.url);
        if (!Object.values(frameIdToSheetIds).length)
            return null;
        var styleSheetIds = [];
        for (var frameId in frameIdToSheetIds)
            styleSheetIds = styleSheetIds.concat(frameIdToSheetIds[frameId]);
        var uiLocation;
        for (var i = 0; !uiLocation && i < styleSheetIds.length; ++i) {
            var header = cssModel.styleSheetHeaderForId(styleSheetIds[i]);
            if (!header)
                continue;
            var info = this._headerInfo(header);
            if (info)
                uiLocation = info._rawLocationToUILocation(rawLocation.lineNumber, rawLocation.columnNumber);
        }
        return uiLocation || null;
    }
}

/**
 * @constructor
 * @param {!WebInspector.Target} target
 * @param {!WebInspector.Workspace} workspace
 * @param {!WebInspector.NetworkWorkspaceBinding} networkWorkspaceBinding
 */
WebInspector.CSSWorkspaceBinding.TargetInfo = function(target, workspace, networkWorkspaceBinding)
{
    this._target = target;
    this._workspace = workspace;

    var cssModel = target.cssModel;
    this._stylesSourceMapping = new WebInspector.StylesSourceMapping(cssModel, workspace);
    this._sassSourceMapping = new WebInspector.SASSSourceMapping(cssModel, workspace, networkWorkspaceBinding);

    /** @type {!StringMap.<!WebInspector.CSSWorkspaceBinding.HeaderInfo>} */
    this._headerInfoById = new StringMap();

    cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
    cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
}

WebInspector.CSSWorkspaceBinding.TargetInfo.prototype = {
    /**
     * @param {!WebInspector.Event} event
     */
    _styleSheetAdded: function(event)
    {
        var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data);
        this._stylesSourceMapping.addHeader(header);
        this._sassSourceMapping.addHeader(header);
    },

    /**
     * @param {!WebInspector.Event} event
     */
    _styleSheetRemoved: function(event)
    {
        var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data);
        this._stylesSourceMapping.removeHeader(header);
        this._sassSourceMapping.removeHeader(header);
        this._headerInfoById.remove(header.id);
    },

    /**
     * @param {!CSSAgent.StyleSheetId} id
     */
    _headerInfo: function(id)
    {
        return this._headerInfoById.get(id);
    },

    _ensureInfoForHeader: function(header)
    {
        var info = this._headerInfoById.get(header.id);
        if (!info) {
            info = new WebInspector.CSSWorkspaceBinding.HeaderInfo(header);
            this._headerInfoById.put(header.id, info);
        }
        return info;
    },

    _dispose: function()
    {
        this._target.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
        this._target.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
    }
}

/**
 * @constructor
 * @param {!WebInspector.CSSStyleSheetHeader} header
 */
WebInspector.CSSWorkspaceBinding.HeaderInfo = function(header)
{
    this._header = header;

    /** @type {!Array.<!WebInspector.SourceMapping>} */
    this._sourceMappings = [];

    /** @type {!Set.<!WebInspector.LiveLocation>} */
    this._locations = new Set();
}

WebInspector.CSSWorkspaceBinding.HeaderInfo.prototype = {
    /**
     * @param {!WebInspector.LiveLocation} location
     */
    _addLocation: function(location)
    {
        this._locations.add(location);
        location.update();
    },

    /**
     * @param {!WebInspector.LiveLocation} location
     */
    _removeLocation: function(location)
    {
        this._locations.remove(location);
    },

    _updateLocations: function()
    {
        var items = this._locations.values();
        for (var i = 0; i < items.length; ++i)
            items[i].update();
    },

    /**
     * @param {number} lineNumber
     * @param {number=} columnNumber
     * @return {?WebInspector.UILocation}
     */
    _rawLocationToUILocation: function(lineNumber, columnNumber)
    {
        var uiLocation = null;
        var rawLocation = new WebInspector.CSSLocation(this._header.target(), this._header.id, this._header.resourceURL(), lineNumber, columnNumber);
        for (var i = this._sourceMappings.length - 1; !uiLocation && i >= 0; --i)
            uiLocation = this._sourceMappings[i].rawLocationToUILocation(rawLocation);
        return uiLocation;
    },

    /**
     * @param {!WebInspector.SourceMapping} sourceMapping
     */
    _pushSourceMapping: function(sourceMapping)
    {
        this._sourceMappings.push(sourceMapping);
        this._updateLocations();
    }
}

/**
 * @constructor
 * @extends {WebInspector.LiveLocation}
 * @param {!WebInspector.CSSStyleModel} cssModel
 * @param {?WebInspector.CSSStyleSheetHeader} header
 * @param {!WebInspector.CSSLocation} rawLocation
 * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate
 */
WebInspector.CSSWorkspaceBinding.LiveLocation = function(cssModel, header, rawLocation, updateDelegate)
{
    WebInspector.LiveLocation.call(this, rawLocation, updateDelegate);
    this._cssModel = cssModel;
    if (!header)
        this._clearStyleSheet();
    else
        this._setStyleSheet(header);
}

WebInspector.CSSWorkspaceBinding.LiveLocation.prototype = {
    /**
     * @param {!WebInspector.Event} event
     */
    _styleSheetAdded: function(event)
    {
        console.assert(!this._header);
        var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data);
        if (header.sourceURL && header.sourceURL === this.rawLocation().url)
            this._setStyleSheet(header);
    },

    /**
     * @param {!WebInspector.Event} event
     */
    _styleSheetRemoved: function(event)
    {
        console.assert(this._header);
        var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data);
        if (this._header !== header)
            return;
        WebInspector.cssWorkspaceBinding._removeLiveLocation(this);
        this._clearStyleSheet();
    },

    /**
     * @param {!WebInspector.CSSStyleSheetHeader} header
     */
    _setStyleSheet: function(header)
    {
        this._header = header;
        WebInspector.cssWorkspaceBinding._addLiveLocation(this);
        this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
        this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
    },

    _clearStyleSheet: function()
    {
        delete this._header;
        this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
        this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
    },

    /**
     * @return {?WebInspector.UILocation}
     */
    uiLocation: function()
    {
        var cssLocation = /** @type WebInspector.CSSLocation */ (this.rawLocation());
        if (this._header) {
            var headerInfo = WebInspector.cssWorkspaceBinding._headerInfo(this._header);
            return headerInfo._rawLocationToUILocation(cssLocation.lineNumber, cssLocation.columnNumber);
        }
        var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(cssLocation.url);
        if (!uiSourceCode)
            return null;
        return uiSourceCode.uiLocation(cssLocation.lineNumber, cssLocation.columnNumber);
    },

    dispose: function()
    {
        WebInspector.LiveLocation.prototype.dispose.call(this);
        if (this._header)
            WebInspector.cssWorkspaceBinding._removeLiveLocation(this);
        this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
        this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
    },

    __proto__: WebInspector.LiveLocation.prototype
}

/**
 * @type {!WebInspector.CSSWorkspaceBinding}
 */
WebInspector.cssWorkspaceBinding;
<commit_msg>DevTools: Do not re-create CSSWorkspaceBinding TargetInfo on MainFrameNavigated<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @constructor
 * @implements {WebInspector.TargetManager.Observer}
 */
WebInspector.CSSWorkspaceBinding = function()
{
    /** @type {!Map.<!WebInspector.Target, !WebInspector.CSSWorkspaceBinding.TargetInfo>} */
    this._targetToTargetInfo = new Map();
    WebInspector.targetManager.observeTargets(this);

    WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameCreatedOrNavigated, this);
}

WebInspector.CSSWorkspaceBinding.prototype = {
    /**
     * @param {!WebInspector.Target} target
     */
    targetAdded: function(target)
    {
        this._targetToTargetInfo.put(target, new WebInspector.CSSWorkspaceBinding.TargetInfo(target, WebInspector.workspace, WebInspector.networkWorkspaceBinding));
    },

    /**
     * @param {!WebInspector.Target} target
     */
    targetRemoved: function(target)
    {
        this._targetToTargetInfo.remove(target)._dispose();
    },

    /**
     * @param {!WebInspector.CSSStyleSheetHeader} header
     * @param {!WebInspector.SourceMapping} mapping
     */
    pushSourceMapping: function(header, mapping)
    {
        this._ensureInfoForHeader(header)._pushSourceMapping(mapping);
    },

    /**
     * @param {!WebInspector.CSSStyleSheetHeader} header
     * @return {?WebInspector.CSSWorkspaceBinding.HeaderInfo}
     */
    _headerInfo: function(header)
    {
        var map = this._targetToTargetInfo.get(header.target());
        return map._headerInfo(header.id) || null;
    },

    /**
     * @param {!WebInspector.CSSStyleSheetHeader} header
     * @return {!WebInspector.CSSWorkspaceBinding.HeaderInfo}
     */
    _ensureInfoForHeader: function(header)
    {
        var targetInfo = this._targetToTargetInfo.get(header.target());
        if (!targetInfo) {
            targetInfo = new WebInspector.CSSWorkspaceBinding.TargetInfo(header.target(), WebInspector.workspace, WebInspector.networkWorkspaceBinding);
            this._targetToTargetInfo.put(header.target(), targetInfo);
        }
        return targetInfo._ensureInfoForHeader(header);
    },

    /**
     * @param {!WebInspector.Event} event
     */
    _mainFrameCreatedOrNavigated: function(event)
    {
        var target = /** @type {!WebInspector.ResourceTreeModel} */ (event.target).target();
        this._targetToTargetInfo.get(target)._reset();
    },

    /**
     * @param {!WebInspector.CSSStyleSheetHeader} header
     */
    updateLocations: function(header)
    {
        var info = this._headerInfo(header);
        if (info)
            info._updateLocations();
    },

    /**
     * @param {!WebInspector.CSSLocation} rawLocation
     * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate
     * @return {!WebInspector.CSSWorkspaceBinding.LiveLocation}
     */
    createLiveLocation: function(rawLocation, updateDelegate)
    {
        var header = rawLocation.styleSheetId ? rawLocation.target().cssModel.styleSheetHeaderForId(rawLocation.styleSheetId) : null;
        return new WebInspector.CSSWorkspaceBinding.LiveLocation(rawLocation.target().cssModel, header, rawLocation, updateDelegate);
    },

    /**
     * @param {!WebInspector.CSSWorkspaceBinding.LiveLocation} location
     */
    _addLiveLocation: function(location)
    {
        this._ensureInfoForHeader(location._header)._addLocation(location);
    },

    /**
     * @param {!WebInspector.CSSWorkspaceBinding.LiveLocation} location
     */
    _removeLiveLocation: function(location)
    {
        var info = this._headerInfo(location._header);
        if (info)
            info._removeLocation(location);
    },

    /**
     * @param {!WebInspector.CSSProperty} cssProperty
     * @param {boolean} forName
     * @return {?WebInspector.UILocation}
     */
    propertyUILocation: function(cssProperty, forName)
    {
        var style = cssProperty.ownerStyle;
        if (!style || !style.parentRule || !style.styleSheetId)
            return null;

        var range = cssProperty.range;
        if (!range)
            return null;

        var url = style.parentRule.resourceURL();
        if (!url)
            return null;

        var line = forName ? range.startLine : range.endLine;
        // End of range is exclusive, so subtract 1 from the end offset.
        var column = forName ? range.startColumn : range.endColumn - (cssProperty.text && cssProperty.text.endsWith(";") ? 2 : 1);
        var rawLocation = new WebInspector.CSSLocation(style.target(), style.styleSheetId, url, line, column);
        return this.rawLocationToUILocation(rawLocation);
    },

    /**
     * @param {?WebInspector.CSSLocation} rawLocation
     * @return {?WebInspector.UILocation}
     */
    rawLocationToUILocation: function(rawLocation)
    {
        if (!rawLocation)
            return null;
        var cssModel = rawLocation.target().cssModel;
        var frameIdToSheetIds = cssModel.styleSheetIdsByFrameIdForURL(rawLocation.url);
        if (!Object.values(frameIdToSheetIds).length)
            return null;
        var styleSheetIds = [];
        for (var frameId in frameIdToSheetIds)
            styleSheetIds = styleSheetIds.concat(frameIdToSheetIds[frameId]);
        var uiLocation;
        for (var i = 0; !uiLocation && i < styleSheetIds.length; ++i) {
            var header = cssModel.styleSheetHeaderForId(styleSheetIds[i]);
            if (!header)
                continue;
            var info = this._headerInfo(header);
            if (info)
                uiLocation = info._rawLocationToUILocation(rawLocation.lineNumber, rawLocation.columnNumber);
        }
        return uiLocation || null;
    }
}

/**
 * @constructor
 * @param {!WebInspector.Target} target
 * @param {!WebInspector.Workspace} workspace
 * @param {!WebInspector.NetworkWorkspaceBinding} networkWorkspaceBinding
 */
WebInspector.CSSWorkspaceBinding.TargetInfo = function(target, workspace, networkWorkspaceBinding)
{
    this._target = target;
    this._workspace = workspace;

    var cssModel = target.cssModel;
    this._stylesSourceMapping = new WebInspector.StylesSourceMapping(cssModel, workspace);
    this._sassSourceMapping = new WebInspector.SASSSourceMapping(cssModel, workspace, networkWorkspaceBinding);

    /** @type {!StringMap.<!WebInspector.CSSWorkspaceBinding.HeaderInfo>} */
    this._headerInfoById = new StringMap();

    cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
    cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
}

WebInspector.CSSWorkspaceBinding.TargetInfo.prototype = {
    /**
     * @param {!WebInspector.Event} event
     */
    _styleSheetAdded: function(event)
    {
        var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data);
        this._stylesSourceMapping.addHeader(header);
        this._sassSourceMapping.addHeader(header);
    },

    /**
     * @param {!WebInspector.Event} event
     */
    _styleSheetRemoved: function(event)
    {
        var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data);
        this._stylesSourceMapping.removeHeader(header);
        this._sassSourceMapping.removeHeader(header);
        this._headerInfoById.remove(header.id);
    },

    /**
     * @param {!CSSAgent.StyleSheetId} id
     */
    _headerInfo: function(id)
    {
        return this._headerInfoById.get(id);
    },

    _ensureInfoForHeader: function(header)
    {
        var info = this._headerInfoById.get(header.id);
        if (!info) {
            info = new WebInspector.CSSWorkspaceBinding.HeaderInfo(header);
            this._headerInfoById.put(header.id, info);
        }
        return info;
    },

    _dispose: function()
    {
        this._reset();
        this._target.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
        this._target.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
    },

    _reset: function()
    {
        this._headerInfoById.clear();
    }
}

/**
 * @constructor
 * @param {!WebInspector.CSSStyleSheetHeader} header
 */
WebInspector.CSSWorkspaceBinding.HeaderInfo = function(header)
{
    this._header = header;

    /** @type {!Array.<!WebInspector.SourceMapping>} */
    this._sourceMappings = [];

    /** @type {!Set.<!WebInspector.LiveLocation>} */
    this._locations = new Set();
}

WebInspector.CSSWorkspaceBinding.HeaderInfo.prototype = {
    /**
     * @param {!WebInspector.LiveLocation} location
     */
    _addLocation: function(location)
    {
        this._locations.add(location);
        location.update();
    },

    /**
     * @param {!WebInspector.LiveLocation} location
     */
    _removeLocation: function(location)
    {
        this._locations.remove(location);
    },

    _updateLocations: function()
    {
        var items = this._locations.values();
        for (var i = 0; i < items.length; ++i)
            items[i].update();
    },

    /**
     * @param {number} lineNumber
     * @param {number=} columnNumber
     * @return {?WebInspector.UILocation}
     */
    _rawLocationToUILocation: function(lineNumber, columnNumber)
    {
        var uiLocation = null;
        var rawLocation = new WebInspector.CSSLocation(this._header.target(), this._header.id, this._header.resourceURL(), lineNumber, columnNumber);
        for (var i = this._sourceMappings.length - 1; !uiLocation && i >= 0; --i)
            uiLocation = this._sourceMappings[i].rawLocationToUILocation(rawLocation);
        return uiLocation;
    },

    /**
     * @param {!WebInspector.SourceMapping} sourceMapping
     */
    _pushSourceMapping: function(sourceMapping)
    {
        this._sourceMappings.push(sourceMapping);
        this._updateLocations();
    }
}

/**
 * @constructor
 * @extends {WebInspector.LiveLocation}
 * @param {!WebInspector.CSSStyleModel} cssModel
 * @param {?WebInspector.CSSStyleSheetHeader} header
 * @param {!WebInspector.CSSLocation} rawLocation
 * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate
 */
WebInspector.CSSWorkspaceBinding.LiveLocation = function(cssModel, header, rawLocation, updateDelegate)
{
    WebInspector.LiveLocation.call(this, rawLocation, updateDelegate);
    this._cssModel = cssModel;
    if (!header)
        this._clearStyleSheet();
    else
        this._setStyleSheet(header);
}

WebInspector.CSSWorkspaceBinding.LiveLocation.prototype = {
    /**
     * @param {!WebInspector.Event} event
     */
    _styleSheetAdded: function(event)
    {
        console.assert(!this._header);
        var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data);
        if (header.sourceURL && header.sourceURL === this.rawLocation().url)
            this._setStyleSheet(header);
    },

    /**
     * @param {!WebInspector.Event} event
     */
    _styleSheetRemoved: function(event)
    {
        console.assert(this._header);
        var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data);
        if (this._header !== header)
            return;
        WebInspector.cssWorkspaceBinding._removeLiveLocation(this);
        this._clearStyleSheet();
    },

    /**
     * @param {!WebInspector.CSSStyleSheetHeader} header
     */
    _setStyleSheet: function(header)
    {
        this._header = header;
        WebInspector.cssWorkspaceBinding._addLiveLocation(this);
        this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
        this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
    },

    _clearStyleSheet: function()
    {
        delete this._header;
        this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
        this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
    },

    /**
     * @return {?WebInspector.UILocation}
     */
    uiLocation: function()
    {
        var cssLocation = /** @type WebInspector.CSSLocation */ (this.rawLocation());
        if (this._header) {
            var headerInfo = WebInspector.cssWorkspaceBinding._headerInfo(this._header);
            return headerInfo._rawLocationToUILocation(cssLocation.lineNumber, cssLocation.columnNumber);
        }
        var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(cssLocation.url);
        if (!uiSourceCode)
            return null;
        return uiSourceCode.uiLocation(cssLocation.lineNumber, cssLocation.columnNumber);
    },

    dispose: function()
    {
        WebInspector.LiveLocation.prototype.dispose.call(this);
        if (this._header)
            WebInspector.cssWorkspaceBinding._removeLiveLocation(this);
        this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this);
        this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this);
    },

    __proto__: WebInspector.LiveLocation.prototype
}

/**
 * @type {!WebInspector.CSSWorkspaceBinding}
 */
WebInspector.cssWorkspaceBinding;
<|endoftext|>


<commit_before>/*jslint browser: true, node: true */
/*global window */

/*!

   Thumbnail image plugin for Flowplayer HTML5

   Copyright (c) 2015-2016, Flowplayer Oy

   Released under the MIT License:
   http://www.opensource.org/licenses/mit-license.php

   requires:
   - Flowplayer HTML5 version 6.x or greater
   revision: $GIT_ID$

*/

(function (flowplayer) {
    "use strict";
    flowplayer(function (api, root) {
        var common = flowplayer.common,
            bean = flowplayer.bean,
            support = flowplayer.support,
            timeline = common.find('.fp-timeline', root)[0],
            timelineTooltip = common.find('.fp-timeline-tooltip', root)[0];

        if (support.touch || !support.inlineVideo) {
            return;
        }

        api.on('ready', function (ev, a, video) {
            // cleanup
            bean.off(root, '.thumbnails');
            common.css(timelineTooltip, {
                width: '',
                height: '',
                'background-image': '',
                'background-repeat': '',
                'background-size': '',
                'background-position': '',
                'border': '',
                'text-shadow': ''
            });

            var c = video.thumbnails || api.conf.thumbnails;

            if (!c) {
                return;
            }

            var height = c.height || 80,
                ratio = video.height / video.width,
                preloadImages = function (tmpl, max, start) {
                    if (start === undefined) {
                        start = 1;
                    }
                    function load() {
                        if (start > max) {
                            return;
                        }
                        var img = new Image();
                        img.src = tmpl.replace('{time}', start);
                        img.onload = function () {
                            start += 1;
                            load();
                        };
                    }
                    load();
                };

            if (c.preload !== false) {
                preloadImages(c.template, video.duration);
            }

            bean.on(root, 'mousemove.thumbnails', '.fp-timeline', function (ev) {
                var x = ev.pageX || ev.clientX,
                    delta = x - common.offset(timeline).left,
                    percentage = delta / common.width(timeline),
                    seconds = Math.round(percentage * api.video.duration);

                // 2nd condition safeguards at out of range retrieval attempts
                if (seconds < 0 || seconds > Math.round(api.video.duration)) {
                    return;
                }
                /* enables greater interval than one second between thumbnails */
                if (c.interval !== undefined && c.interval > 1 && seconds > 0) {
                    seconds = Math.ceil(seconds / c.interval) - 1;
                }

                common.css(timelineTooltip, {
                    width: (height / ratio) + 'px',
                    height: height + 'px',
                    // {time} template expected to start at 1, video time/first frame starts at 0
                    'background-image': "url('" + c.template.replace('{time}', seconds + 1) + "')",
                    'background-repeat': 'no-repeat',
                    'background-size': 'cover',
                    'background-position': 'center',
                    'border': '1px solid #333',
                    'text-shadow': '1px 1px #000'
                });
            });
        });

    });

}((typeof module === "object" && module.exports)
    ? require('flowplayer')
    : window.flowplayer));
<commit_msg>Make interval default to 1 in code<commit_after>/*jslint browser: true, node: true */
/*global window */

/*!

   Thumbnail image plugin for Flowplayer HTML5

   Copyright (c) 2015-2016, Flowplayer Oy

   Released under the MIT License:
   http://www.opensource.org/licenses/mit-license.php

   requires:
   - Flowplayer HTML5 version 6.x or greater
   revision: $GIT_ID$

*/

(function (flowplayer) {
    "use strict";
    flowplayer(function (api, root) {
        var common = flowplayer.common,
            bean = flowplayer.bean,
            support = flowplayer.support,
            timeline = common.find('.fp-timeline', root)[0],
            timelineTooltip = common.find('.fp-timeline-tooltip', root)[0];

        if (support.touch || !support.inlineVideo) {
            return;
        }

        api.on('ready', function (ev, a, video) {
            // cleanup
            bean.off(root, '.thumbnails');
            common.css(timelineTooltip, {
                width: '',
                height: '',
                'background-image': '',
                'background-repeat': '',
                'background-size': '',
                'background-position': '',
                'border': '',
                'text-shadow': ''
            });

            var c = video.thumbnails || api.conf.thumbnails;

            if (!c) {
                return;
            }

            var height = c.height || 80,
                interval = c.interval || 1,
                ratio = video.height / video.width,
                preloadImages = function (tmpl, max, start) {
                    if (start === undefined) {
                        start = 1;
                    }
                    function load() {
                        if (start > max) {
                            return;
                        }
                        var img = new Image();
                        img.src = tmpl.replace('{time}', start);
                        img.onload = function () {
                            start += 1;
                            load();
                        };
                    }
                    load();
                };

            if (c.preload !== false) {
                preloadImages(c.template, video.duration);
            }

            bean.on(root, 'mousemove.thumbnails', '.fp-timeline', function (ev) {
                var x = ev.pageX || ev.clientX,
                    delta = x - common.offset(timeline).left,
                    percentage = delta / common.width(timeline),
                    seconds = Math.round(percentage * api.video.duration);

                // 2nd condition safeguards at out of range retrieval attempts
                if (seconds < 0 || seconds > Math.round(api.video.duration)) {
                    return;
                }
                // enables greater interval than one second between thumbnails
                if (interval > 1 && seconds > 0) {
                    seconds = Math.ceil(seconds / interval) - 1;
                }

                common.css(timelineTooltip, {
                    width: (height / ratio) + 'px',
                    height: height + 'px',
                    // {time} template expected to start at 1, video time/first frame starts at 0
                    'background-image': "url('" + c.template.replace('{time}', seconds + 1) + "')",
                    'background-repeat': 'no-repeat',
                    'background-size': 'cover',
                    'background-position': 'center',
                    'border': '1px solid #333',
                    'text-shadow': '1px 1px #000'
                });
            });
        });

    });

}((typeof module === "object" && module.exports)
    ? require('flowplayer')
    : window.flowplayer));
<|endoftext|>


<commit_before>/* global Components, document, window */
{
  const { DOMLocalization } =
    Components.utils.import('resource://gre/modules/DOMLocalization.jsm');

  /**
   * Polyfill for document.ready polyfill.
   * See: https://github.com/whatwg/html/issues/127 for details.
   *
   * @returns {Promise}
   */
  function documentReady() {
    const rs = document.readyState;
    if (rs === 'interactive' || rs === 'completed') {
      return Promise.resolve();
    }

    return new Promise(
      resolve => document.addEventListener(
        'readystatechange', resolve, { once: true }
      )
    );
  }

  /**
   * Scans the `elem` for links with localization resources.
   *
   * @param {Element} elem
   * @returns {Array<string>}
   */
  function getResourceLinks(elem) {
    return Array.from(elem.querySelectorAll('link[rel="localization"]')).map(
      el => el.getAttribute('href')
    );
  }

  const resourceIds = getResourceLinks(document.head || document);

  document.l10n = new DOMLocalization(window, resourceIds);

  // trigger first context to be fetched eagerly
  document.l10n.ctxs.touchNext();

  document.l10n.ready = documentReady().then(() => {
    document.l10n.registerObservers();
    window.addEventListener('unload', () => {
      document.l10n.unregisterObservers();
    });
    document.l10n.connectRoot(document.documentElement);
    return document.l10n.translateRoots();
  });
}
<commit_msg>Move XUL documentReady to use MozBeforeInitialXULLayout (#142)<commit_after>/* global Components, document, window */
{
  const { DOMLocalization } =
    Components.utils.import('resource://gre/modules/DOMLocalization.jsm');

  /**
   * Polyfill for document.ready polyfill.
   * See: https://github.com/whatwg/html/issues/127 for details.
   *
   * @returns {Promise}
   */
  function documentReady() {
    if (document.contentType === 'application/vnd.mozilla.xul+xml') {
      // XUL
      return new Promise(
        resolve => document.addEventListener(
          'MozBeforeInitialXULLayout', resolve, { once: true }
        )
      );
    }

    // HTML
    const rs = document.readyState;
    if (rs === 'interactive' || rs === 'completed') {
      return Promise.resolve();
    }
    return new Promise(
      resolve => document.addEventListener(
        'readystatechange', resolve, { once: true }
      )
    );
  }

  /**
   * Scans the `elem` for links with localization resources.
   *
   * @param {Element} elem
   * @returns {Array<string>}
   */
  function getResourceLinks(elem) {
    return Array.from(elem.querySelectorAll('link[rel="localization"]')).map(
      el => el.getAttribute('href')
    );
  }

  const resourceIds = getResourceLinks(document.head || document);

  document.l10n = new DOMLocalization(window, resourceIds);

  // trigger first context to be fetched eagerly
  document.l10n.ctxs.touchNext();

  document.l10n.ready = documentReady().then(() => {
    document.l10n.registerObservers();
    window.addEventListener('unload', () => {
      document.l10n.unregisterObservers();
    });
    document.l10n.connectRoot(document.documentElement);
    return document.l10n.translateRoots();
  });
}
<|endoftext|>