<commit_before>/* global vfs */
import { platform } from 'substance'
import { test } from 'substance-test'
import { TextureArchive, checkArchive } from '../index'
import { getMountPoint, diff } from './shared/testHelpers'
import { applyNOP, toUnix, setupTestVfs } from './shared/integrationTestHelpers'
import setupTestApp from './shared/setupTestApp'

PersistenceTest('blank')

PersistenceTest('kitchen-sink')

function PersistenceTest (archiveId) {
  test(`Persistence: loading and saving article ${archiveId}`, t => {
    // create a vfs where we can store the data during save without harming the global vfs instance
    let testVfs = setupTestVfs(vfs, archiveId)
    let {app, archive, manuscriptSession} = setupTestApp(t, {
      vfs: testVfs,
      archiveId
    })

    let originalRawArchive
    archive.storage.read(archiveId, (err, rawArchive) => {
      if (err) throw new Error(err)
      originalRawArchive = rawArchive
    })

    // trigger a save
    applyNOP(manuscriptSession)
    // Note: with VFS these calls are actually not asynchronous, i.e. calling back instantly
    app._save(err => {
      if (err) throw new Error(err)
    })

    // get the updated raw archive
    let newRawArchive
    archive.storage.read(archiveId, (err, rawArchive) => {
      if (err) throw new Error(err)
      newRawArchive = rawArchive
    })

    let originalManuscriptXML = toUnix(originalRawArchive.resources['manuscript.xml'].data)
    let newManuscriptXML = toUnix(newRawArchive.resources['manuscript.xml'].data)

    // check the new archive for validator errors
    let err = checkArchive(TextureArchive, newRawArchive)
    let details = err ? err.detail : null
    t.nil(details, 'There should be no error.')

    if (newManuscriptXML !== originalManuscriptXML) {
      // we are not using the built-in equal assertion
      // because the error message is not helpful
      // instead we fail with a general message and an extra that
      // will be displayed in the browser
      let msg = 'XML should not have changed'
      if (platform.inBrowser) {
        t._assert(false, {
          message: msg,
          operator: 'equal',
          actual: newManuscriptXML,
          expected: originalManuscriptXML
        })
      } else {
        t.fail(msg)
        console.log('Diff:')
        console.log(diff(newManuscriptXML, originalManuscriptXML))
      }
    } else {
      t.pass('XML did not change')
    }

    // finally try to let the app load the new archive
    getMountPoint(t).empty()
    t.doesNotThrow(() => {
      setupTestApp(t, {
        vfs: testVfs,
        archiveId
      })
    }, 'The persisted file should be loaded and rendered without problems')

    t.end()
  })
}
<commit_msg>Add test revealing issue with deserialization of manifest.xml.<commit_after>/* global vfs */
import { platform } from 'substance'
import { test } from 'substance-test'
import { TextureArchive, checkArchive } from '../index'
import { getMountPoint, diff } from './shared/testHelpers'
import { applyNOP, toUnix, setupTestVfs, openManuscriptEditor, PseudoFileEvent, getEditorSession, setSelection } from './shared/integrationTestHelpers'
import setupTestApp from './shared/setupTestApp'

InvariantLoadSaveTest('blank')

InvariantLoadSaveTest('kitchen-sink')

LoadSaveShouldNotThrow('blank', 'saving and loading an article after inserting a figure', _INSERT_FIGURE)

function InvariantLoadSaveTest (archiveId) {
  test(`Persistence: loading and saving article ${archiveId}`, t => {
    // create a vfs where we can store the data during save without harming the global vfs instance
    let testVfs = setupTestVfs(vfs, archiveId)
    let {app, archive, manuscriptSession} = setupTestApp(t, {
      vfs: testVfs,
      archiveId
    })

    let originalRawArchive
    archive.storage.read(archiveId, (err, rawArchive) => {
      if (err) throw new Error(err)
      originalRawArchive = rawArchive
    })

    // trigger a save
    _NOP({manuscriptSession})

    // Note: with VFS these calls are actually not asynchronous, i.e. calling back instantly
    app._save(err => {
      if (err) throw new Error(err)
    })

    // get the updated raw archive
    let newRawArchive
    archive.storage.read(archiveId, (err, rawArchive) => {
      if (err) throw new Error(err)
      newRawArchive = rawArchive
    })

    let originalManuscriptXML = toUnix(originalRawArchive.resources['manuscript.xml'].data)
    let newManuscriptXML = toUnix(newRawArchive.resources['manuscript.xml'].data)

    // check the new archive for validator errors
    let err = checkArchive(TextureArchive, newRawArchive)
    let details = err ? err.detail : null
    t.nil(details, 'There should be no error.')

    if (newManuscriptXML !== originalManuscriptXML) {
      // we are not using the built-in equal assertion
      // because the error message is not helpful
      // instead we fail with a general message and an extra that
      // will be displayed in the browser
      let msg = 'XML should not have changed'
      if (platform.inBrowser) {
        t._assert(false, {
          message: msg,
          operator: 'equal',
          actual: newManuscriptXML,
          expected: originalManuscriptXML
        })
      } else {
        t.fail(msg)
        console.log('Diff:')
        console.log(diff(newManuscriptXML, originalManuscriptXML))
      }
    } else {
      t.pass('XML did not change')
    }

    // finally try to let the app load the new archive
    getMountPoint(t).empty()
    t.doesNotThrow(() => {
      setupTestApp(t, {
        vfs: testVfs,
        archiveId
      })
    }, 'The persisted file should be loaded and rendered without problems')

    t.end()
  })
}

function LoadSaveShouldNotThrow (archiveId, title, change) {
  test(`Persistence: ${title}`, t => {
    // create a vfs where we can store the data during save without harming the global vfs instance
    let testVfs = setupTestVfs(vfs, archiveId)
    let {app, archive, manuscriptSession} = setupTestApp(t, {
      vfs: testVfs,
      archiveId
    })
    // change the content
    change({app, archive, manuscriptSession})
    // trigger a save
    // Note: with VFS these calls are actually not asynchronous, i.e. calling back instantly
    app._save(err => {
      if (err) throw new Error(err)
    })
    // let the app load the new archive
    getMountPoint(t).empty()
    t.doesNotThrow(() => {
      setupTestApp(t, {
        vfs: testVfs,
        archiveId
      })
    }, 'The persisted file should be loaded and rendered without problems')
    t.end()
  })
}

function _NOP ({manuscriptSession}) {
  applyNOP(manuscriptSession)
}

function _INSERT_FIGURE ({app}) {
  let editor = openManuscriptEditor(app)
  let editorSession = getEditorSession(editor)
  let doc = editorSession.getDocument()
  let p = doc.get('body').getChildAt(0)
  setSelection(editor, p.getPath(), 0)
  // TODO: more 'transparent' way to create 'files'
  let fe = new PseudoFileEvent()
  editor.send('executeCommand', 'insert-fig', {
    files: fe.currentTarget.files
  })
}
<|endoftext|>


<commit_before>'use strict';

var cr = require('complexity-report'),
    settings = require('./settings'),
    partials = require('./views/partials'),
    models = {
        title: require('./models/title'),
        menu: require('./models/menu'),
        options: require('./models/options'),
        metrics: require('./models/metrics'),
        functions: require('./models/functions')
    };

module.exports = [
    { path: settings.home.path, method: 'get', handler: getMain },
    { path: settings.home.path, method: 'post', handler: postMain },
    { path: settings.complexity.path, method: 'get', handler: getComplexity },
    { path: settings.about.path, method: 'get', handler: getAbout }
];

function getMain (request, response) {
    var data = getViewData('home');

    data.options = models.options.get([ 'logicalor', 'switchcase' ]);
    data.nosource = true;

    setHeaders(request, response);

    response.render(partials.main, data);
}

function getViewData (page) {
    return {
        title: models.title.get(page),
        menu: models.menu.get(page)
    };
}

function setHeaders (request, response) {
    var userAgent = request.headers['user-agent'];

    if (userAgent && userAgent.indexOf('MSIE')) {
        response.setHeader('X-UA-Compatible', 'IE=Edge,chrome=1');
    }
}

function postMain (request, response) {
    var report, data = getViewData('home');

    try {
        data.source = request.body.source;
        data.options = models.options.get(request.body.options);

        report = cr.run(request.body.source, {
            forin: request.body.forin || false,
            trycatch: request.body.trycatch || false,
            logicalor: !request.body.logicalor,
            switchcase: !request.body.switchcase
        });

        data.metrics = models.metrics.get(report);
        data.functions = models.functions.get(report.functions);
    } catch (error) {
        // TODO: Select/highlight errorneous code in view?
        console.log(error.stack);
        data.error = error;
    }

    setHeaders(request, response);
    response.render(partials.main, data);
}

function postWs (request, response) {
    // TODO: Get report, create model, call reponse.jsonp()
}

function getComplexity (request, response) {
    setHeaders(request, response);
    response.render(partials.complexity, getViewData('complexity'));
}

function getAbout (request, response) {
    setHeaders(request, response);
    response.render(partials.about, getViewData('about'));
}
<commit_msg>Wire in meta descriptions.<commit_after>'use strict';

var cr = require('complexity-report'),
    settings = require('./settings'),
    partials = require('./views/partials'),
    models = {
        title: require('./models/title'),
        menu: require('./models/menu'),
        options: require('./models/options'),
        metrics: require('./models/metrics'),
        functions: require('./models/functions')
    };

module.exports = [
    { path: settings.home.path, method: 'get', handler: getMain },
    { path: settings.home.path, method: 'post', handler: postMain },
    { path: settings.complexity.path, method: 'get', handler: getComplexity },
    { path: settings.about.path, method: 'get', handler: getAbout }
];

function getMain (request, response) {
    var data = getViewData('home');

    data.options = models.options.get([ 'logicalor', 'switchcase' ]);
    data.nosource = true;

    setHeaders(request, response);

    response.render(partials.main, data);
}

function getViewData (page) {
    return {
        title: models.title.get(page),
        description: settings[page].description,
        menu: models.menu.get(page)
    };
}

function setHeaders (request, response) {
    var userAgent = request.headers['user-agent'];

    if (userAgent && userAgent.indexOf('MSIE')) {
        response.setHeader('X-UA-Compatible', 'IE=Edge,chrome=1');
    }
}

function postMain (request, response) {
    var report, data = getViewData('home');

    try {
        data.source = request.body.source;
        data.options = models.options.get(request.body.options);

        report = cr.run(request.body.source, {
            forin: request.body.forin || false,
            trycatch: request.body.trycatch || false,
            logicalor: !request.body.logicalor,
            switchcase: !request.body.switchcase
        });

        data.metrics = models.metrics.get(report);
        data.functions = models.functions.get(report.functions);
    } catch (error) {
        // TODO: Select/highlight errorneous code in view?
        console.log(error.stack);
        data.error = error;
    }

    setHeaders(request, response);
    response.render(partials.main, data);
}

function postWs (request, response) {
    // TODO: Get report, create model, call reponse.jsonp()
}

function getComplexity (request, response) {
    setHeaders(request, response);
    response.render(partials.complexity, getViewData('complexity'));
}

function getAbout (request, response) {
    setHeaders(request, response);
    response.render(partials.about, getViewData('about'));
}
<|endoftext|>


<commit_before>var card_model = require('./models/modelCard');
var media_model = require('./models/modelMedia');
var deck_model = require('./models/modelDeck');
var crypto = require('crypto');
var fs = require('fs');

exports.get_all_cards = function(req, res, next){
    card_model.find(function(err, docs){
        if(err) return next(err);
        return res.send(docs);
    });
   // next(); Creates error
}

exports.index = function(req, res){
    console.log("connection from " + req.ip);
    res.sendFile('public/html/index.html', {"root":__dirname})
};

var CARD_KEYS = ['media']

exports.get_cards = function(req, res){
    console.log("connection from " + req.ip);
    card_model.find({_id: req.params.id}, function(err, cards){
        if(err) return console.err(err);
        if(cards.length!=1){
            res.send([]);
        }
        else{
            res.send(cards[0]);
        }
    });
};

exports.upload_file = function(req,res){
    var file_type = req.file.mimetype.split('/')[0]
    var new_dir = 'static/'+file_type+'/';
    if(!fs.existsSync(new_dir)){
        fs.mkdirSync(new_dir);
    }
    var hash = crypto.createHash('sha256')
    var hashed_file = hash.update(fs.readFileSync(req.file.path)).digest('hex');
    var filename=new_dir + hashed_file;
    fs.rename(req.file.path, filename, function(){
        res.send(filename);
    });
};

/*
 * request object:
 * {
 *     media: [
 *        {
 *           type: _____,
 *           url: _____,
 *        }, ...
 *     ]
 * }
 */
exports.create_card = function(req, res, next){
    var media_list =[];
    console.log(req.body)
    for(var m of req.body.media){
        media_list.push( new media_model({
            type: m.type,
            url: m.url
        }));
    }
    var new_card = new card_model({media:media_list});
    new_card.save();
    res.send(new_card._id);
    next();
};

exports.get_decks = function(req, res, next){
    card_model.find().distinct('decks', function(err, cols){
        if(err){
            console.log(err);
        }
        res.send(cols);
    });
}

exports.get_deck = function(req, res){
    deck_id = req.params.deck
    card_model.findOne({'decks._id': deck_id}, function(err, cards){
        if(err){
            console.log(err);
        }
        res.send(cards);
    });
}

exports.create_deck = function(req, res){
    var new_deck = new deck_model({title: req.body.title, desc: req.body.desc});
    new_deck.save(function(error, deck, n){
        card_model.findByIdAndUpdate(
                req.body.cards,
                {$push: {"decks": deck}},
                {safe: true, upsert:true},
                function(err, _){
                    console.log(deck._id);
                    res.send(deck._id);
                }
        );
    });
}
<commit_msg>Getting upload url json object. Merge branch 'master' of https://github.com/computations/flashcards-3<commit_after>var card_model = require('./models/modelCard');
var media_model = require('./models/modelMedia');
var deck_model = require('./models/modelDeck');
var crypto = require('crypto');
var fs = require('fs');

exports.get_all_cards = function(req, res, next){
    card_model.find(function(err, docs){
        if(err) return next(err);
        return res.send(docs);
    });
   // next(); Creates error
}

exports.index = function(req, res){
    console.log("connection from " + req.ip);
    res.sendFile('public/html/index.html', {"root":__dirname})
};

var CARD_KEYS = ['media']

exports.get_cards = function(req, res){
    console.log("connection from " + req.ip);
    card_model.find({_id: req.params.id}, function(err, cards){
        if(err) return console.err(err);
        if(cards.length!=1){
            res.send([]);
        }
        else{
            res.send(cards[0]);
        }
    });
};

exports.upload_file = function(req,res){
    var file_type = req.file.mimetype.split('/')[0]
    var new_dir = 'static/'+file_type+'/';
    if(!fs.existsSync(new_dir)){
        fs.mkdirSync(new_dir);
    }
    var hash = crypto.createHash('sha256')
    var hashed_file = hash.update(fs.readFileSync(req.file.path)).digest('hex');
    var filename=new_dir + hashed_file;
    fs.rename(req.file.path, filename, function(){
        res.send({'url': filename, 'media_type': file_type});
    });
};

/*
 * request object:
 * {
 *     media: [
 *        {
 *           type: _____,
 *           url: _____,
 *        }, ...
 *     ]
 * }
 */
exports.create_card = function(req, res, next){
    var media_list =[];
    console.log(req.body)
    for(var m of req.body.media){
        media_list.push( new media_model({
            type: m.type,
            url: m.url
        }));
    }
    var new_card = new card_model({media:media_list});
    new_card.save();
    res.send(new_card._id);
    next();
};

exports.get_decks = function(req, res, next){
    card_model.find().distinct('decks', function(err, cols){
        if(err){
            console.log(err);
        }
        res.send(cols);
    });
}

exports.get_deck = function(req, res){
    deck_id = req.params.deck
    card_model.findOne({'decks._id': deck_id}, function(err, cards){
        if(err){
            console.log(err);
        }
        res.send(cards);
    });
}

exports.create_deck = function(req, res){
    var new_deck = new deck_model({title: req.body.title, desc: req.body.desc});
    new_deck.save(function(error, deck, n){
        card_model.findByIdAndUpdate(
                req.body.cards,
                {$push: {"decks": deck}},
                {safe: true, upsert:true},
                function(err, _){
                    console.log(deck._id);
                    res.send(deck._id);
                }
        );
    });
}
<|endoftext|>


<commit_before>module.exports = function(app) {
app.get('/', function(request, response) {
  response.sendFile(__dirname + '/site.htm');
});

app.get('/home', function(request, response) {
  response.sendFile(__dirname + '/signin.html');
});

app.get('/workoutentry', function(request, response) {
  response.sendFile(__dirname + '/workoutentry.htm');
});

app.get('/myworkouts', function(request, response) {
	response.sendFile(__dirname + '/myworkouts.htm');
});

app.get('/admin_athlete_vis', function(request, response) {
	response.sendFile(__dirname + '/admin_athlete_vis.htm');
});

app.get('/admin_add_user', function(request, response) {
	response.sendFile(__dirname + '/admin_add_user.htm');
});

app.get('/site', function(request, response) {
	response.sendFile(__dirname + '/site.htm');
});

};
<commit_msg>separated routes of add user and remove user<commit_after>module.exports = function(app) {
app.get('/', function(request, response) {
  response.sendFile(__dirname + '/site.htm');
});

app.get('/home', function(request, response) {
  response.sendFile(__dirname + '/signin.html');
});

app.get('/workoutentry', function(request, response) {
  response.sendFile(__dirname + '/workoutentry.htm');
});

app.get('/myworkouts', function(request, response) {
	response.sendFile(__dirname + '/myworkouts.htm');
});

app.get('/admin_athlete_vis', function(request, response) {
	response.sendFile(__dirname + '/admin_athlete_vis.htm');
});

app.get('/admin_add_user', function(request, response) {
	response.sendFile(__dirname + '/admin_add_user.htm');
});

app.get('/admin_remove_user', function(request,response) {
	response.sendFile(__dirname + '/admin_remove_user.htm');
});

};
<|endoftext|>


<commit_before>// dependencies ------------------------------------

import express    from 'express';
import users      from './handlers/users';
import jobs       from './handlers/jobs';
import validation from './handlers/validation';
import datasets   from './handlers/datasets';
import auth       from './libs/auth';
import scitran    from './libs/scitran';

let routes = [

    // users ---------------------------------------

    {
        method: 'get',
        url: '/users/self',
        middleware: [],
        handler: scitran.verifyUser
    },
    {
        method: 'post',
        url: '/users',
        middleware: [],
        handler: users.create
    },
    {
        method: 'post',
        url: '/users/blacklist',
        middleware: [auth.superuser],
        handler: users.blacklist
    },
    {
        method: 'get',
        url: '/users/blacklist',
        middleware: [auth.superuser],
        handler: users.getBlacklist
    },
    {
        method: 'delete',
        url: '/users/blacklist/:id',
        middleware: [auth.superuser],
        handler: users.unBlacklist
    },

    // datasets ------------------------------------
        // Note: most dataset interactions are sent directly to Scitran.
        // These manage those that need to be modified or proxied.

    {
        method: 'post',
        url: '/datasets/:datasetId/permissions',
        middleware: [],
        handler: datasets.share
    },

    // validation ----------------------------------

    {
        method: 'post',
        url: '/datasets/:datasetId/validate',
        middleware: [auth.user],
        handler: validation.validate
    },

    // jobs ----------------------------------------

    {
        method: 'get',
        url: '/apps',
        middleware: [],
        handler: jobs.getApps
    },
    {
        method: 'post',
        url: '/datasets/:datasetId/jobs',
        middleware: [auth.datasetAccess()],
        handler: jobs.postJob
    },
    {
        method: 'get',
        url: '/datasets/:datasetId/jobs',
        middleware: [auth.datasetAccess({optional: true})],
        handler: jobs.getDatasetJobs
    },
    {
        method: 'delete',
        url: '/datasets/:datasetId/jobs',
        middleware: [auth.datasetAccess()],
        handler: jobs.deleteDatasetJobs
    },
    {
        method: 'post',
        url: '/jobs/:jobId/results',
        middleware: [],
        handler: jobs.postResults
    },
    {
        method: 'get',
        url: '/datasets/:datasetId/jobs/:jobId',
        middleware: [auth.datasetAccess()],
        handler: jobs.getJob
    },
    {
        method: 'post',
        url: '/datasets/:datasetId/jobs/:jobId/retry',
        middleware: [auth.datasetAccess()],
        handler: jobs.retry
    },
    {
        method: 'get',
        url: '/datasets/:datasetId/jobs/:jobId/results/ticket',
        middleware: [auth.datasetAccess()],
        handler: jobs.getDownloadTicket
    },
    {
        method: 'get',
        url: '/jobs',
        middleware: [auth.optional],
        handler: jobs.getJobs
    },
    {
        method: 'get',
        url: '/jobs/:jobId/results/:fileName',
        middleware: [auth.ticket],
        handler: jobs.getFile
    }

];

// initialize routes -------------------------------

let router = express.Router();

for (let route of routes) {
    let arr = route.middleware;
    arr.unshift(route.url);
    arr.push(route.handler);
    router[route.method].apply(router, arr);
}

// export ------------------------------------------

export default router;
<commit_msg>Add routes for proxying dataset/snapshot creation<commit_after>// dependencies ------------------------------------

import express    from 'express';
import users      from './handlers/users';
import jobs       from './handlers/jobs';
import validation from './handlers/validation';
import datasets   from './handlers/datasets';
import auth       from './libs/auth';
import scitran    from './libs/scitran';

let routes = [

    // users ---------------------------------------

    {
        method: 'get',
        url: '/users/self',
        middleware: [],
        handler: scitran.verifyUser
    },
    {
        method: 'post',
        url: '/users',
        middleware: [],
        handler: users.create
    },
    {
        method: 'post',
        url: '/users/blacklist',
        middleware: [auth.superuser],
        handler: users.blacklist
    },
    {
        method: 'get',
        url: '/users/blacklist',
        middleware: [auth.superuser],
        handler: users.getBlacklist
    },
    {
        method: 'delete',
        url: '/users/blacklist/:id',
        middleware: [auth.superuser],
        handler: users.unBlacklist
    },

    // datasets ------------------------------------
        // Note: most dataset interactions are sent directly to Scitran.
        // These manage those that need to be modified or proxied.

    {
        method: 'post',
        url: '/datasets',
        middleware: [],
        handler: datasets.create
    },

    {
        method: 'post',
        url: '/datasets/:datasetId/snapshot',
        middleware: [],
        handler: datasets.snapshot
    },

    {
        method: 'post',
        url: '/datasets/:datasetId/permissions',
        middleware: [],
        handler: datasets.share
    },

    // validation ----------------------------------

    {
        method: 'post',
        url: '/datasets/:datasetId/validate',
        middleware: [auth.user],
        handler: validation.validate
    },

    // jobs ----------------------------------------

    {
        method: 'get',
        url: '/apps',
        middleware: [],
        handler: jobs.getApps
    },
    {
        method: 'post',
        url: '/datasets/:datasetId/jobs',
        middleware: [auth.datasetAccess()],
        handler: jobs.postJob
    },
    {
        method: 'get',
        url: '/datasets/:datasetId/jobs',
        middleware: [auth.datasetAccess({optional: true})],
        handler: jobs.getDatasetJobs
    },
    {
        method: 'delete',
        url: '/datasets/:datasetId/jobs',
        middleware: [auth.datasetAccess()],
        handler: jobs.deleteDatasetJobs
    },
    {
        method: 'post',
        url: '/jobs/:jobId/results',
        middleware: [],
        handler: jobs.postResults
    },
    {
        method: 'get',
        url: '/datasets/:datasetId/jobs/:jobId',
        middleware: [auth.datasetAccess()],
        handler: jobs.getJob
    },
    {
        method: 'post',
        url: '/datasets/:datasetId/jobs/:jobId/retry',
        middleware: [auth.datasetAccess()],
        handler: jobs.retry
    },
    {
        method: 'get',
        url: '/datasets/:datasetId/jobs/:jobId/results/ticket',
        middleware: [auth.datasetAccess()],
        handler: jobs.getDownloadTicket
    },
    {
        method: 'get',
        url: '/jobs',
        middleware: [auth.optional],
        handler: jobs.getJobs
    },
    {
        method: 'get',
        url: '/jobs/:jobId/results/:fileName',
        middleware: [auth.ticket],
        handler: jobs.getFile
    }

];

// initialize routes -------------------------------

let router = express.Router();

for (let route of routes) {
    let arr = route.middleware;
    arr.unshift(route.url);
    arr.push(route.handler);
    router[route.method].apply(router, arr);
}

// export ------------------------------------------

export default router;
<|endoftext|>


<commit_before>Skull.Form = {
  checkInput: function(event){
    var $target = this.$(event.currentTarget);
    var customValidation = $target.data('custom-validation') || function(){ return true; };
    if(event.currentTarget.checkValidity() && customValidation($target)){
      $target.removeClass("error");
      $target.parents('.field_with_errors').removeClass('field_with_errors');
      this.$('[data-error-for=' + $target.prop('id') + ']').hide();
    }
  },

  setupForm: function(){
    this.$('input,select,textarea').on('invalid', this.invalid);
    this.preventInvalidSubmit();
  },

  invalid: function(event){
    var $target = this.$(event.currentTarget);
    $target.addClass("error");
    this.$('[data-error-for=' + $target.prop('id') + ']').show();
  },

  validate: function(){
    var valid = true;
    this.$('input:visible,select:visible,textarea:visible').each(function(){
      var $input = $(this);
      var customValidation = $input.data('custom-validation') || function(){ return true; };
      valid = this.checkValidity() && customValidation($input) && valid;
    });
    if(!valid){
      $.smoothScroll({
        scrollTarget: '[required].error:visible:first',
        speed: 800
      });
      this.$('[required].error:visible:first').select();
      this.$('.text-error').slideDown('slow');
    }
    return valid;
  },

  preventInvalidSubmit: function(){
    var that = this;
    this.$('input[type="submit"]').on('click', function(e){
      return that.validate();
    });
  },
};
<commit_msg>use each on error to check if parent has an input that have error class, to avoid show error messages for non invalid fields<commit_after>Skull.Form = {
  checkInput: function(event){
    var $target = this.$(event.currentTarget);
    var customValidation = $target.data('custom-validation') || function(){ return true; };
    if(event.currentTarget.checkValidity() && customValidation($target)){
      if($target.prop('id') != "" && $target.prop('id') != undefined) {
        $target.removeClass("error");
        $target.parents('.field_with_errors').removeClass('field_with_errors');
        this.$('[data-error-for=' + $target.prop('id') + ']').hide();
      }
    }
  },

  setupForm: function(){
    this.$('input,select,textarea').on('invalid', this.invalid);
    this.preventInvalidSubmit();
  },

  invalid: function(event){
    var $target = this.$(event.currentTarget);
    $target.addClass("error");
    this.$('[data-error-for=' + $target.prop('id') + ']').show();
  },

  validate: function(){
    var valid = true;
    var that = this;
    this.$('input:visible,select:visible,textarea:visible').each(function(){
      var $input = $(this);
      var customValidation = $input.data('custom-validation') || function(){ return true; };
      valid = this.checkValidity() && customValidation($input) && valid;
    });
    if(!valid){
      $.smoothScroll({
        scrollTarget: '[required].error:visible:first',
        speed: 800
      });
      this.$('[required].error:visible:first').select();
      //this.$('.text-error').slideDown('slow');
      $.each(this.$('.text-error'), function(i, item){
        if(that.$(item.parent).hasClass('error')) {
          that.$(item).slideDown('slow');
        }
      })
    }
    return valid;
  },

  preventInvalidSubmit: function(){
    var that = this;
    this.$('input[type="submit"]').on('click', function(e){
      return that.validate();
    });
  },
};
<|endoftext|>


<commit_before>// Lightbox

function href_return_to (a) {
  if (!a.getAttribute('return_to')) return a.href;
  var r = 'return_to=' + encodeURIComponent(a.getAttribute('return_to'));
  return a.href.indexOf('?') > -1 ? a.href + '&' + r : a.href + '?' + r;
}

$(document).ready(function(){
  var lightbox_wrapper = $('#lightbox_wrapper');

  function closeLightbox(e) {
    e.preventDefault();
    lightbox_wrapper.removeClass('overlayed');
    setTimeout(function () { lightbox_wrapper.removeClass('loaded'); }, 20);

    setTimeout(function () {
      lightbox_wrapper.addClass('hidden');
      $(lightbox_wrapper).find('section.lightbox').remove();
    }, 10);
  };

  $(lightbox_wrapper).find('.overlay').click(closeLightbox);

  function openLightbox (e) {
    e.preventDefault();

    var to_remove = $(lightbox_wrapper).find('section.lightbox');

    if (to_remove.length > 0) {
      to_remove.css('opacity', 0);
      to_remove.remove();
      lightbox_wrapper.removeClass('loaded');
    }

    lightbox_wrapper.removeClass('hidden');
    lightbox_wrapper.addClass('loading');

    setTimeout(function () { lightbox_wrapper.addClass('overlayed'); }, 50);

    $.ajax({
      url: href_return_to(this),
      type: 'get',
      success: function(data, status, xhr) {
        lightbox_wrapper.removeClass('loading');
        lightbox_wrapper.addClass('loaded');
        $(lightbox_wrapper).append(data);
        $(lightbox_wrapper).find('.close').click(closeLightbox);

        $(lightbox_wrapper).find('[interaction=lightbox]').click(openLightbox);
      }
    });
  }

  $('[interaction=lightbox]').click(openLightbox);
});<commit_msg>clean code<commit_after>// Lightbox

$(document).ready(function(){
  var lightbox_wrapper = $('#lightbox_wrapper');

  function closeLightbox(e) {
    e.preventDefault();
    lightbox_wrapper.removeClass('overlayed');
    setTimeout(function () { lightbox_wrapper.removeClass('loaded'); }, 20);

    setTimeout(function () {
      lightbox_wrapper.addClass('hidden');
      $(lightbox_wrapper).find('section.lightbox').remove();
    }, 10);
  };

  $(lightbox_wrapper).find('.overlay').click(closeLightbox);

  function openLightbox (e) {
    e.preventDefault();

    var to_remove = $(lightbox_wrapper).find('section.lightbox');

    if (to_remove.length > 0) {
      to_remove.css('opacity', 0);
      to_remove.remove();
      lightbox_wrapper.removeClass('loaded');
    }

    lightbox_wrapper.removeClass('hidden');
    lightbox_wrapper.addClass('loading');

    setTimeout(function () { lightbox_wrapper.addClass('overlayed'); }, 50);

    $.ajax({
      url: this.href,
      type: 'get',
      success: function(data, status, xhr) {
        lightbox_wrapper.removeClass('loading');
        lightbox_wrapper.addClass('loaded');
        $(lightbox_wrapper).append(data);
        $(lightbox_wrapper).find('.close').click(closeLightbox);

        $(lightbox_wrapper).find('[interaction=lightbox]').click(openLightbox);
      }
    });
  }

  $('[interaction=lightbox]').click(openLightbox);
});<|endoftext|>


<commit_before>/*SuperGamer 6.0*/
/*Copyright Arjay07 2014*/

var mainGUI;

function mainMenu(){

	var ctx = com.mojang.minecraftpe.MainActivity.currentMainActivity.get();

	ctx.runOnUiThread(new java.lang.Runnable(){

		run: function(){

			try{

				var editMode = false;

				var sgBtn = new android.widget.Button(ctx);
				sgButton.setText("SG");
				sgBtn.setTextColor(android.graphics.Color.GREEN);

				sgBtn.setOnLongClickListener(new android.view.View.onLongClickListener(){

					onLongClick: function(v){

						if(!editMode){

							editMode = true;

						}

						return true;

					}

				});

				sgBtn.setOnTouchListener(new android.view.View.onTouchListener(){

					onTouch: function(v, me){

						if(editMode){

							sgBtn.setX(me.getX());
							sgBtn.setY(me.getY());

						}

						if(me.getAction() == me.ACTION_UP){

							editMode = false;

						}

					}

				});

			}catch(e){

			}

		}

	});

}<commit_msg>Added SuperGamer 7.0<commit_after>/*SuperGamer 7.0*/
/*Copyright Arjay07 2014*/

var mainGUI;

function mainMenu(){

	var ctx = com.mojang.minecraftpe.MainActivity.currentMainActivity.get();

	ctx.runOnUiThread(new java.lang.Runnable(){

		run: function(){

			try{

				var editMode = false;

				var sgBtn = new android.widget.Button(ctx);
				sgButton.setText("SG");
				sgBtn.setTextColor(android.graphics.Color.GREEN);

				sgBtn.setOnLongClickListener(new android.view.View.onLongClickListener(){

					onLongClick: function(v){

						if(!editMode){

							editMode = true;

						}

						return true;

					}

				});

				sgBtn.setOnTouchListener(new android.view.View.onTouchListener(){

					onTouch: function(v, me){

						if(editMode){

							sgBtn.setX(me.getX());
							sgBtn.setY(me.getY());

						}

						if(me.getAction() == me.ACTION_UP){

							editMode = false;

						}

					}

				});

				mainGUI = new android.widget.PopupWindow(sgBtn, android.view.ViewGroup.LayoutParams.WRAP_CONTENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
				mainGUI.showAtLocation(ctx.getWindow().getDecorView(), android.view.Gravity.BOTTOM | android.view.Gravity.RIGHT, 0, 0);

			}catch(e){

			}

		}

	});

}

function newLevel(){

	mainMenu();

}<|endoftext|>


<commit_before>/**
@fileOverview

@toc

*/

(function (root, factory) {
	"use strict";

	/*global define*/
	if (typeof define === 'function' && define.amd) {
		define(['angular', 'sweetalert'], factory);  // AMD
	} else if (typeof module === 'object' && module.exports) {
		module.exports = factory(require('angular'), require('sweetalert')); // Node
	} else {
		factory(root.angular, root.swal);					// Browser
	}

}(this, function (angular, swal) {
	"use strict";

	angular.module('oitozero.ngSweetAlert', [])
		.factory('SweetAlert', [ '$rootScope', function ( $rootScope ) {
			//public methods
			var self = {

				swal: function ( arg1, arg2, arg3 ) {
					$rootScope.$evalAsync(function(){
						if( typeof(arg2) === 'function' ) {
							swal( arg1, function(isConfirm){
								$rootScope.$evalAsync( function(){
									arg2(isConfirm);
								});
							}, arg3 );
						} else {
							swal( arg1, arg2, arg3 );
						}
					});
				},
				success: function(title, message) {
					$rootScope.$evalAsync(function(){
						swal( title, message, 'success' );
					});
				},
				error: function(title, message) {
					$rootScope.$evalAsync(function(){
						swal( title, message, 'error' );
					});
				},
				warning: function(title, message) {
					$rootScope.$evalAsync(function(){
						swal( title, message, 'warning' );
					});
				},
				info: function(title, message) {
					$rootScope.$evalAsync(function(){
						swal( title, message, 'info' );
					});
				},
				showInputError: function(message) {
					$rootScope.$evalAsync(function(){
						swal.showInputError( message );
					});
				},
				close: function() {
					$rootScope.$evalAsync(function(){
						swal.close();
					});
				}
			};

			return self;
		}]);
}));

<commit_msg>SweetAlertConfig<commit_after>/**
 @fileOverview

 @toc

 */

(function (root, factory) {
    "use strict";

    /*global define*/
    if (typeof define === 'function' && define.amd) {
        define(['angular', 'sweetalert'], factory);  // AMD
    } else if (typeof module === 'object' && module.exports) {
        module.exports = factory(require('angular'), require('sweetalert')); // Node
    } else {
        factory(root.angular, root.swal);					// Browser
    }

}(this, function (angular, swal) {
    "use strict";

    angular.module('oitozero.ngSweetAlert', [])
        .factory('SweetAlert', ['$rootScope', 'SweetAlertConfig', function ($rootScope, SweetAlertConfig) {
            //public methods
            var self = {

                swal: function (arg1, arg2, arg3) {

                    //merge with default config
                    var arg1 = angular.extend(SweetAlertConfig, arg1);

                    $rootScope.$evalAsync(function () {
                        if (typeof(arg2) === 'function') {
                            swal(arg1, function (isConfirm) {
                                $rootScope.$evalAsync(function () {
                                    arg2(isConfirm);
                                });
                            }, arg3);
                        } else {
                            swal(arg1, arg2, arg3);
                        }
                    });
                },
                success: function (title, message) {
                    $rootScope.$evalAsync(function () {
                        swal(title, message, 'success');
                    });
                },
                error: function (title, message) {
                    $rootScope.$evalAsync(function () {
                        swal(title, message, 'error');
                    });
                },
                warning: function (title, message) {
                    $rootScope.$evalAsync(function () {
                        swal(title, message, 'warning');
                    });
                },
                info: function (title, message) {
                    $rootScope.$evalAsync(function () {
                        swal(title, message, 'info');
                    });
                },
                showInputError: function (message) {
                    $rootScope.$evalAsync(function () {
                        swal.showInputError(message);
                    });
                },
                close: function () {
                    $rootScope.$evalAsync(function () {
                        swal.close();
                    });
                }
            };

            return self;
        }]).constant('SweetAlertConfig', {
        title: '',
        text: '',
        type: null,
        allowOutsideClick: false,
        showConfirmButton: true,
        showCancelButton: false,
        closeOnConfirm: true,
        closeOnCancel: true,
        confirmButtonText: 'OK',
        confirmButtonColor: '#8CD4F5',
        cancelButtonText: 'Cancel',
        imageUrl: null,
        imageSize: null,
        timer: null,
        customClass: '',
        html: false,
        animation: true,
        allowEscapeKey: true,
        inputType: 'text',
        inputPlaceholder: '',
        inputValue: '',
        showLoaderOnConfirm: false
    });
}));
<|endoftext|>


<commit_before>function submit_new_city(passedInput) {
    console.log("submitted " + passedInput);
    if (passedInput !== undefined) {
        var user_input = passedInput;
    } else if (parseInt($("#new-city").val()) * 0 === 0) {
        console.log("Input is a number and not a valid city");
        $("#invalid_city").text("Not a valid city");
        console.log(("result: " + parseInt($("#new-city").val()) % 2));
        return false;
    } else {
        var user_input = $("#new-city").val();
    }

    $("#invalid_city").text(" ");
    $("#invalid_city").append(" ");

    var user_input = $("#new-city").val();

    console.log("submitted via ajax: " + user_input);

    function city_results(json) {
        console.log("city results wooo");
    }

    $.ajax({
        type: "GET",
        jsonpCallback: "city_results",
        url: "http://autocomplete.wunderground.com/aq?cb=city_results&query=" + user_input,
        dataType: 'jsonp',
        success: function(response) {
          var i = 0;

          function findCityArray(i) {
              if (response.RESULTS.length === 0){
                $("#invalid_city").text("Please enter a valid city");
                console.log("Successful response and marked as undefined, nothing in the results array")
                console.log("response: "+response.RESULTS[i]);
                return;
              } else if (response.RESULTS[i].type === "country" || response.RESULTS[i].lon === "-9999.000000") {
                $("#invalid_city").text("Please enter a city and country");
                console.log("Successful response and marked as a country, not a city");
                console.log("response: "+response.RESULTS[i]);
                return;
              } else if (response.RESULTS[i].name.match(/(international|school|S.A.R.)/i)) {
                $("#invalid_city").text("That right there is an airport, try again");
                console.log("Successful response and marked as an International airport, not a city");
                console.log("response: "+response.RESULTS[i].name);
                console.log("value of i = "+i++);
                return findCityArray(i++);
              } else {
                var first_result = response.RESULTS[i].name;
                console.log(response);
                console.log(response.RESULTS);
                var cityname = first_result.match(/(\D+)(,\s+)(\D+)/)[1];
                var bigger_thing = first_result.match(/(\D+)(,\s+)(\D+)/)[3];
                var lat = response.RESULTS[i].lat;
                var lon = response.RESULTS[i].lon;
                var country = response.RESULTS[i].c;
                var lastClock = $(" #clock-container ").children('div').eq(4).data('city');
                console.log("new city form success: " + first_result + ". Cityname = " + cityname + " and bigger thing= " + bigger_thing);
                return [cityname, bigger_thing, lat, lon, country, lastClock];
                }

            }

                var cityArray = findCityArray(i);

                console.log("city name: "+cityArray[0]);
                console.log("last clock: "+cityArray[5]);

                $("#new-city").val("");
                console.log("finished");

            $.ajax({
                type: "POST",
                url: "/cities",
                data: {
                    city: {
                        name: cityArray[0],
                        bigger_thing: cityArray[1],
                        lat: cityArray[2],
                        lon: cityArray[3],
                        country: cityArray[4],
                        lastClock: cityArray[5]
                    }
                },
                success: function (response) {
                    if (response == "this city already exists") {
                        $("#invalid_city").text("You're already tracking that city");
                        console.log("Saving city denied - city is already on page.");
                    } else {
                        $("#invalid_city").text(cityArray[0] + ", " + cityArray[1] + " added");
                        console.log("Saving city successful: " + response);
                        makeClock(response);
                    }
                },
                error: function (response) {
                    console.log("Saving city failed.");
                    console.log(response);
                }
            });
        },
        error: function (response) {
            // var first_result = response['results'][0]['name']
            console.log("new city form failure: " + response);
            $("#invalid-city").prepend("Not a valid city");
            $("#new-city").val("");
            console.log("finished");
        }
    });

    return false;
}
<commit_msg>Adds custom filter for specific terms (more solidifed now)<commit_after>function submit_new_city(passedInput) {
    console.log("submitted " + passedInput);
    if (passedInput !== undefined) {
        var user_input = passedInput;
    } else if (parseInt($("#new-city").val()) * 0 === 0) {
        console.log("Input is a number and not a valid city");
        $("#invalid_city").text("Not a valid city");
        console.log(("result: " + parseInt($("#new-city").val()) % 2));
        return false;
    } else {
        var user_input = $("#new-city").val();
    }

    $("#invalid_city").text(" ");
    $("#invalid_city").append(" ");

    var user_input = $("#new-city").val();

    console.log("submitted via ajax: " + user_input);

    function city_results(json) {
        console.log("city results wooo");
    }

    $.ajax({
        type: "GET",
        jsonpCallback: "city_results",
        url: "http://autocomplete.wunderground.com/aq?cb=city_results&query=" + user_input,
        dataType: 'jsonp',
        success: function(response) {
          var i = 0;

          function findCityArray(i) {
              if (response.RESULTS.length === 0){
                $("#invalid_city").text("Please enter a valid city");
                console.log("Successful response and marked as undefined, nothing in the results array")
                console.log("response: "+response.RESULTS[i]);
                return;
              } else if (response.RESULTS[i].type === "country" || response.RESULTS[i].lon === "-9999.000000") {
                $("#invalid_city").text("Please enter a city and country");
                console.log("Successful response and marked as a country, not a city");
                console.log("response: "+response.RESULTS[i]);
                return;
              } else if (response.RESULTS[i].name.match(/(kong international|S.A.R.)/i)) {
                $("#invalid_city").text("Please enter a valid city");
                console.log("Successful response and marked as an International airport, not a city");
                console.log("response: "+response.RESULTS[i].name);
                console.log("value of i = "+i++);
                return findCityArray(i++);
              } else {
                var first_result = response.RESULTS[i].name;
                console.log(response);
                console.log(response.RESULTS);
                var cityname = first_result.match(/(\D+)(,\s+)(\D+)/)[1];
                var bigger_thing = first_result.match(/(\D+)(,\s+)(\D+)/)[3];
                var lat = response.RESULTS[i].lat;
                var lon = response.RESULTS[i].lon;
                var country = response.RESULTS[i].c;
                var lastClock = $(" #clock-container ").children('div').eq(4).data('city');
                console.log("new city form success: " + first_result + ". Cityname = " + cityname + " and bigger thing= " + bigger_thing);
                return [cityname, bigger_thing, lat, lon, country, lastClock];
                }

            }

                var cityArray = findCityArray(i);

                console.log("city name: "+cityArray[0]);
                console.log("last clock: "+cityArray[5]);

                $("#new-city").val("");
                console.log("finished");

            $.ajax({
                type: "POST",
                url: "/cities",
                data: {
                    city: {
                        name: cityArray[0],
                        bigger_thing: cityArray[1],
                        lat: cityArray[2],
                        lon: cityArray[3],
                        country: cityArray[4],
                        lastClock: cityArray[5]
                    }
                },
                success: function (response) {
                    if (response == "this city already exists") {
                        $("#invalid_city").text("You're already tracking that city");
                        console.log("Saving city denied - city is already on page.");
                    } else {
                        $("#invalid_city").text(cityArray[0] + ", " + cityArray[1] + " added");
                        console.log("Saving city successful: " + response);
                        makeClock(response);
                    }
                },
                error: function (response) {
                    console.log("Saving city failed.");
                    console.log(response);
                }
            });
        },
        error: function (response) {
            // var first_result = response['results'][0]['name']
            console.log("new city form failure: " + response);
            $("#invalid-city").prepend("Not a valid city");
            $("#new-city").val("");
            console.log("finished");
        }
    });

    return false;
}
<|endoftext|>


<commit_before>function writeGame(ResponsiveCanvas) {

  // Load Mobile Text2Speech feature
  document.addEventListener("click", responsiveVoice.clickEvent);

  var canvasPlay = new ResponsiveCanvas('canvas-play');
  var canvasPalette = new ResponsiveCanvas('canvas-palette');

  fabric.Object.prototype.hasControls = false;

  canvasPlay.setDimensions({width: '98vw', height: '35vw'}, {
    cssOnly: true
  });

  canvasPalette.setDimensions({width: '98vw', height: '13vw'}, {
    cssOnly: true
  });

  canvasPlay.selection = false;
  canvasPalette.selectable = false;
  canvasPalette.selection = false;

  generatePalette();
  boundCanvas();
  wiggleLetter();
  createBroom();
  createPencils();

  function createBroom(){
    var broomElement = document.getElementById('clear-img');

		var broom = new fabric.Image(broomElement, {
		  button: true,
		  left: 80,
		  top: 20,
		  width: 80,
		  height: 100
		});

		broom.lockMovementX = true;
		broom.lockMovementY = true;
		broom.lockScalingX = broom.lockScalingY = true;
		broom.lockRotation = true;

		broom.on('selected', function() {
      animateBroom();
      setTimeout(function() {
        canvasPlay.clear();
      }, 1600);
	});
		canvasPalette.add(broom);
  };

function moveBroom(broom) {
		broom.bringToFront();

		setTimeout(function() {
			broom.animate('left', -250, {
			  onChange: canvasPlay.renderAll.bind(canvasPlay),
			  duration: 1000,
			  onComplete: function() { canvasPlay.remove(broom); }
			});
		}, 1000);

		setTimeout(function() {
			var audio = new Audio('audio/Swish.m4a');
			audio.play();
		}, 1500);
	};

	function animateBroom() {

		var clearElement = document.getElementById('clear-img');

		var broom = new fabric.Image(clearElement, {
		  left: 1000,
		  top: 0,
			width: 250,
			height: 500
		});

		broom.lockMovementX = true;
		broom.lockMovementY = true;
		broom.lockScalingX = broom.lockScalingY = true;
		broom.lockRotation = true;

		canvasPlay.add(broom);
		canvasPlay.renderAll();

		moveBroom(broom);

	};

  function generatePalette() {

  var letterImages = $('#letter-images').children();
	var percentage = 0.04;

	$.each(letterImages, function(i, el) {

		var letter = new fabric.Image(el, {
      char: String.fromCharCode(65 + i),
		  left: i >= 13 ? ((40 * (i - 9)) + (9 * (i - 10))) : ((40 * (i + 4)) + (10 * (i + 2))),
		  top: i >= 13 ? 64 : 13,
		  width: canvasPalette.width*percentage,
		  height: canvasPalette.width*percentage
		});

    canvasPalette.renderAll();
		letter.lockMovementX = true;
		letter.lockMovementY = true;
		letter.lockScalingX = letter.lockScalingY = true;
		letter.lockRotation = true;

		letter.on('selected', function() {
      console.log(this.char);
      responsiveVoice.speak(this.char);
			if (this.canvas.lowerCanvasEl.id === "canvas-palette") {
				var clone = fabric.util.object.clone(this);
        clone.left =  230;
        clone.top = 0;
	    	clone.lockMovementX = true;
				clone.lockMovementY = true;

				clone.animate('height', 320, {
				  onChange: canvasPlay.renderAll.bind(canvasPlay),
				  duration: 1000,
				  easing: fabric.util.ease.easeOutBounce
				});

				clone.animate('width', 200,  {
					onChange: canvasPlay.renderAll.bind(canvasPlay),
					duration: 1000,
					easing: fabric.util.ease.easeOutBounce
				});

        canvasPalette.deactivateAll().renderAll();
        canvasPlay.add(clone);
        createPencils(clone);
			}
		});
		canvasPalette.add(letter);
	});

  setTimeout(function() {
    canvasPalette.renderAll();
  }, 500);

};

function createPencils(clone){
  var percentage = 0.04
  var greenPencilElement = document.getElementById('green-pencil');

  var greenPencilButton = new fabric.Image(greenPencilElement, {
    left: 850,
    top: 10,
    width: canvasPalette.width*(percentage*1.3),
    height: canvasPalette.width*(percentage*1.3)
  })

  greenPencilButton.lockMovementX = true;
  greenPencilButton.lockMovementY = true;
  greenPencilButton.lockScalingX = greenPencilButton.lockScalingY = true;
  greenPencilButton.lockRotation = true;

  canvasPalette.add(greenPencilButton);

  greenPencilButton.on('selected', function(){
    canvasPlay.isDrawingMode = true;
    canvasPlay.freeDrawingBrush.color = 'red';
    canvasPlay.freeDrawingBrush.width = 10;
  });

  var redPencilElement = document.getElementById('red-pencil');

  var redPencilButton = new fabric.Image(redPencilElement, {
    left: 850,
    top: 65,
    width: canvasPalette.width*(percentage*1.3),
    height: canvasPalette.width*(percentage*1.3)
  })

  redPencilButton.lockMovementX = true;
  redPencilButton.lockMovementY = true;
  redPencilButton.lockScalingX = redPencilButton.lockScalingY = true;
  redPencilButton.lockRotation = true;

  canvasPalette.add(redPencilButton);

  redPencilButton.on('selected', function(){
    canvasPlay.isDrawingMode = false;
    clone.animate('left', '+=380', { onChange: canvasPlay.renderAll.bind(canvasPlay) });
  });
  responsiveVoice.speak(this.char);
};

function boundCanvas() {
	canvasPlay.on ("object:moving", function(event) {
		     var el = event.target;

		el.left = el.left < el.getBoundingRectWidth() / 2 ? el.getBoundingRectWidth() / 5 : el.left;
		el.top = el.top < el.getBoundingRectHeight () / 2 ? el.getBoundingRectHeight() / 5 : el.top;

		var right = el.left + el.getBoundingRectWidth() / 2;
		var bottom = el.top + el.getBoundingRectHeight() / 2;

		el.left = right > canvasPlay.width - el.getBoundingRectWidth() / 2 ? canvasPlay.width - el.getBoundingRectWidth() / 1 : el.left;
		el.top = bottom > canvasPlay.height - el.getBoundingRectHeight() / 2 ? canvasPlay.height - el.getBoundingRectHeight() / 1 : el.top;
	});
};

function wiggleLetter(){
	canvasPlay.hoverCursor = 'pointer';
	function animate(e, dir){
	if (e.target) {
		fabric.util.animate({
			startValue: e.target.get('scaleY'),
			endValue: e.target.get('scaleY') + (dir ? 0 : -1 ),
			duration: 100,
			onChange: function(value) {
				e.target.setAngle(value);
				canvasPlay.renderAll();
			},
			onComplete: function() {
				e.target.setCoords();
			}
		});
		fabric.util.animate({
			startValue: e.target.get('scaleX'),
			endValue: e.target.get('scaleX') + (dir ?  -1 : 0  ),
			duration: 100,
			onChange: function(value) {
				e.target.scale(value);
				canvasPlay.renderAll();
			},
			onComplete: function() {
				e.target.setCoords();
			}
	  });
	 }
 };
 canvasPlay.on('mouse:down', function(e) { animate(e, 0); });
 canvasPlay.on('mouse:up', function(e) { animate(e, 0); });
	};

  canvasPlay.on('selected', function(){
    responsiveVoice.speak(this.char);
  });
};
<commit_msg>Fix indentation<commit_after>function writeGame(ResponsiveCanvas) {

  document.addEventListener("click", responsiveVoice.clickEvent);

  var canvasPlay = new ResponsiveCanvas('canvas-play');
  var canvasPalette = new ResponsiveCanvas('canvas-palette');

  fabric.Object.prototype.hasControls = false;

  canvasPlay.setDimensions({width: '98vw', height: '35vw'}, {
    cssOnly: true
  });

  canvasPalette.setDimensions({width: '98vw', height: '13vw'}, {
    cssOnly: true
  });

  canvasPlay.selection = false;
  canvasPalette.selectable = false;
  canvasPalette.selection = false;

  generatePalette();
  boundCanvas();
  wiggleLetter();
  createBroom();
  createPencils();

  function createBroom(){
    var broomElement = document.getElementById('clear-img');

		var broom = new fabric.Image(broomElement, {
		  button: true,
		  left: 80,
		  top: 20,
		  width: 80,
		  height: 100
		});

		broom.lockMovementX = true;
		broom.lockMovementY = true;
		broom.lockScalingX = broom.lockScalingY = true;
		broom.lockRotation = true;

		broom.on('selected', function() {
      animateBroom();
      setTimeout(function() {
        canvasPlay.clear();
      }, 1600);
	});
		canvasPalette.add(broom);
  };

  function moveBroom(broom) {
		broom.bringToFront();

		setTimeout(function() {
			broom.animate('left', -250, {
			  onChange: canvasPlay.renderAll.bind(canvasPlay),
			  duration: 1000,
			  onComplete: function() { canvasPlay.remove(broom); }
			});
		}, 1000);

		setTimeout(function() {
			var audio = new Audio('audio/Swish.m4a');
			audio.play();
		}, 1500);
	};

	function animateBroom() {
		var clearElement = document.getElementById('clear-img');

		var broom = new fabric.Image(clearElement, {
		  left: 1000,
		  top: 0,
			width: 250,
			height: 500
		});

		broom.lockMovementX = true;
		broom.lockMovementY = true;
		broom.lockScalingX = broom.lockScalingY = true;
		broom.lockRotation = true;

		canvasPlay.add(broom);
		canvasPlay.renderAll();

		moveBroom(broom);
	};

  function generatePalette() {
    var letterImages = $('#letter-images').children();
	  var percentage = 0.04;

	  $.each(letterImages, function(i, el) {

		var letter = new fabric.Image(el, {
      char: String.fromCharCode(65 + i),
		  left: i >= 13 ? ((40 * (i - 9)) + (9 * (i - 10))) : ((40 * (i + 4)) + (10 * (i + 2))),
		  top: i >= 13 ? 64 : 13,
		  width: canvasPalette.width*percentage,
		  height: canvasPalette.width*percentage
		});

    canvasPalette.renderAll();
		letter.lockMovementX = true;
		letter.lockMovementY = true;
		letter.lockScalingX = letter.lockScalingY = true;
		letter.lockRotation = true;

		letter.on('selected', function() {
      console.log(this.char);
      responsiveVoice.speak(this.char);
			if (this.canvas.lowerCanvasEl.id === "canvas-palette") {
				var clone = fabric.util.object.clone(this);
        clone.left =  230;
        clone.top = 0;
	    	clone.lockMovementX = true;
				clone.lockMovementY = true;

				clone.animate('height', 320, {
				  onChange: canvasPlay.renderAll.bind(canvasPlay),
				  duration: 1000,
				  easing: fabric.util.ease.easeOutBounce
				});

				clone.animate('width', 200,  {
					onChange: canvasPlay.renderAll.bind(canvasPlay),
					duration: 1000,
					easing: fabric.util.ease.easeOutBounce
				});

        canvasPalette.deactivateAll().renderAll();
        canvasPlay.add(clone);
        createPencils(clone);
			}
		});
		canvasPalette.add(letter);
	});

  setTimeout(function() {
    canvasPalette.renderAll();
    }, 500);
  };

  function createPencils(clone){
    var percentage = 0.04
    var greenPencilElement = document.getElementById('green-pencil');

    var greenPencilButton = new fabric.Image(greenPencilElement, {
      left: 850,
      top: 10,
      width: canvasPalette.width*(percentage*1.3),
      height: canvasPalette.width*(percentage*1.3)
    })

    greenPencilButton.lockMovementX = true;
    greenPencilButton.lockMovementY = true;
    greenPencilButton.lockScalingX = greenPencilButton.lockScalingY = true;
    greenPencilButton.lockRotation = true;

    canvasPalette.add(greenPencilButton);

    greenPencilButton.on('selected', function(){
      canvasPlay.isDrawingMode = true;
      canvasPlay.freeDrawingBrush.color = 'red';
      canvasPlay.freeDrawingBrush.width = 10;
    });

    var redPencilElement = document.getElementById('red-pencil');

    var redPencilButton = new fabric.Image(redPencilElement, {
      left: 850,
      top: 65,
      width: canvasPalette.width*(percentage*1.3),
      height: canvasPalette.width*(percentage*1.3)
    })

    redPencilButton.lockMovementX = true;
    redPencilButton.lockMovementY = true;
    redPencilButton.lockScalingX = redPencilButton.lockScalingY = true;
    redPencilButton.lockRotation = true;

    canvasPalette.add(redPencilButton);

    redPencilButton.on('selected', function(){
      canvasPlay.isDrawingMode = false;
      clone.animate('left', '+=380', { onChange: canvasPlay.renderAll.bind(canvasPlay) });
    });
    responsiveVoice.speak(this.char);
  };

  function boundCanvas() {
	   canvasPlay.on ("object:moving", function(event) {
       var el = event.target;

       el.left = el.left < el.getBoundingRectWidth() / 2 ? el.getBoundingRectWidth() / 5 : el.left;
       el.top = el.top < el.getBoundingRectHeight () / 2 ? el.getBoundingRectHeight() / 5 : el.top;

       var right = el.left + el.getBoundingRectWidth() / 2;
       var bottom = el.top + el.getBoundingRectHeight() / 2;

       el.left = right > canvasPlay.width - el.getBoundingRectWidth() / 2 ? canvasPlay.width - el.getBoundingRectWidth() / 1 : el.left;
       el.top = bottom > canvasPlay.height - el.getBoundingRectHeight() / 2 ? canvasPlay.height - el.getBoundingRectHeight() / 1 : el.top;
	  });
  };

  function wiggleLetter(){
	   canvasPlay.hoverCursor = 'pointer';

    function animate(e, dir){
	     if (e.target) {
         fabric.util.animate({
           startValue: e.target.get('scaleY'),
           endValue: e.target.get('scaleY') + (dir ? 0 : -1 ),
           duration: 100,
           onChange: function(value) {
             e.target.setAngle(value);
             canvasPlay.renderAll();
           },
           onComplete: function() {
             e.target.setCoords();
           }
         });

         fabric.util.animate({
           startValue: e.target.get('scaleX'),
           endValue: e.target.get('scaleX') + (dir ?  -1 : 0  ),
           duration: 100,
           onChange: function(value) {
             e.target.scale(value);
             canvasPlay.renderAll();
           },
           onComplete: function() {
             e.target.setCoords();
           }
         });
       }
     };
     canvasPlay.on('mouse:down', function(e) { animate(e, 0); });
     canvasPlay.on('mouse:up', function(e) { animate(e, 0); });
   };

   canvasPlay.on('selected', function(){
     responsiveVoice.speak(this.char);
   });
};
<|endoftext|>


<commit_before>import './customBlockly';
import blocks from './blocks';
import {
    isMainBlock,
    save,
    disable,
    deleteBlocksLoadedBy,
    addLoadersFirst,
    cleanUpOnLoad,
    addDomAsBlock,
    backwardCompatibility,
    fixCollapsedBlocks,
    fixArgumentAttribute,
    removeUnavailableMarkets,
    strategyHasValidTradeTypeCategory,
    cleanBeforeExport,
} from './utils';
import Interpreter from '../../bot/Interpreter';
import createError from '../../common/error';
import { translate, xml as translateXml } from '../../../common/i18n';
import { getLanguage } from '../../../common/lang';
import { get as getStorage, remove } from '../../../common/utils/storageManager';
import { observer as globalObserver } from '../../../common/utils/observer';
import { showDialog } from '../../bot/tools';
import GTM from '../../../common/gtm';
import { AppConstants } from '../../../common/appId';

const setBeforeUnload = off => {
    if (off) {
        window.onbeforeunload = null;
    } else {
        window.onbeforeunload = () => 'You have some unsaved blocks, do you want to save them before you exit?';
    }
};

const disableStrayBlocks = () => {
    const topBlocks = Blockly.mainWorkspace.getTopBlocks();
    topBlocks.forEach(block => {
        if (
            !isMainBlock(block.type) &&
            ['block_holder', 'tick_analysis', 'loader', 'procedures_defreturn', 'procedures_defnoreturn'].indexOf(
                block.type
            ) < 0 &&
            !block.disabled
        ) {
            disable(block, translate('Blocks must be inside block holders, main blocks or functions'));
        }
    });
};
const disposeBlocksWithLoaders = () => {
    Blockly.mainWorkspace.addChangeListener(ev => {
        setBeforeUnload();
        if (ev.type === 'delete' && ev.oldXml.getAttribute('type') === 'loader' && ev.group !== 'undo') {
            deleteBlocksLoadedBy(ev.blockId, ev.group);
        }
    });
};
const marketsWereRemoved = xml => {
    if (!Array.from(xml.children).every(block => !removeUnavailableMarkets(block))) {
        if (window.trackJs) {
            trackJs.track('Invalid financial market');
        }
        showDialog({
            title  : translate('Warning'),
            text   : [translate('This strategy is not available in your country.')],
            buttons: [
                {
                    text : translate('OK'),
                    class: 'button-primary',
                    click() {
                        $(this).dialog('close');
                    },
                },
            ],
        })
            .then(() => {})
            .catch(() => {});
        return true;
    }
    return false;
};
export const loadWorkspace = xml => {
    if (!strategyHasValidTradeTypeCategory(xml)) return;
    if (marketsWereRemoved(xml)) return;

    Blockly.Events.setGroup('load');
    Blockly.mainWorkspace.clear();

    Array.from(xml.children).forEach(block => {
        backwardCompatibility(block);
    });

    fixArgumentAttribute(xml);
    Blockly.Xml.domToWorkspace(xml, Blockly.mainWorkspace);
    addLoadersFirst(xml).then(
        () => {
            fixCollapsedBlocks();
            Blockly.Events.setGroup(false);
            globalObserver.emit('ui.log.success', translate('Blocks are loaded successfully'));
        },
        e => {
            Blockly.Events.setGroup(false);
            throw e;
        }
    );
};

export const loadBlocks = (xml, dropEvent = {}) => {
    if (!strategyHasValidTradeTypeCategory(xml)) return;
    if (marketsWereRemoved(xml)) return;

    const variables = xml.getElementsByTagName('variables');
    if (variables.length > 0) {
        Blockly.Xml.domToVariables(variables[0], Blockly.mainWorkspace);
    }
    Blockly.Events.setGroup('load');
    addLoadersFirst(xml).then(
        loaders => {
            const addedBlocks = [
                ...loaders,
                ...Array.from(xml.children)
                    .map(block => addDomAsBlock(block))
                    .filter(b => b),
            ];
            cleanUpOnLoad(addedBlocks, dropEvent);
            fixCollapsedBlocks();
            globalObserver.emit('ui.log.success', translate('Blocks are loaded successfully'));
        },
        e => {
            throw e;
        }
    );
};
const xmlToStr = xml => {
    const serializer = new XMLSerializer();
    return serializer.serializeToString(xml);
};
const addBlocklyTranslation = () => {
    $.ajaxPrefilter(options => {
        options.async = true; // eslint-disable-line no-param-reassign
    });
    let lang = getLanguage();
    if (lang === 'ach') {
        lang = 'en';
    } else if (lang === 'zh_cn') {
        lang = 'zh-hans';
    } else if (lang === 'zh_tw') {
        lang = 'zh-hant';
    }
    return new Promise(resolve => {
        $.getScript(`translations/${lang}.js`, resolve);
    });
};
const onresize = () => {
    let element = document.getElementById('blocklyArea');
    const blocklyArea = element;
    const blocklyDiv = document.getElementById('blocklyDiv');
    let x = 0;
    let y = 0;
    do {
        x += element.offsetLeft;
        y += element.offsetTop;
        element = element.offsetParent;
    } while (element);
    // Position blocklyDiv over blocklyArea.
    blocklyDiv.style.left = `${x}px`;
    blocklyDiv.style.top = `${y}px`;
    blocklyDiv.style.width = `${blocklyArea.offsetWidth}px`;
    blocklyDiv.style.height = `${blocklyArea.offsetHeight}px`;
};
const render = workspace => () => {
    onresize();
    Blockly.svgResize(workspace);
};
const overrideBlocklyDefaultShape = () => {
    const addDownloadToMenu = block => {
        if (block instanceof Object) {
            // eslint-disable-next-line no-param-reassign, max-len
            block.customContextMenu = function customContextMenu(options) {
                options.push({
                    text    : translate('Download'),
                    enabled : true,
                    callback: () => {
                        const xml = Blockly.Xml.textToDom(
                            '<xml xmlns="http://www.w3.org/1999/xhtml" collection="false"></xml>'
                        );
                        xml.appendChild(Blockly.Xml.blockToDom(this));
                        save('binary-bot-block', true, xml);
                    },
                });
            };
        }
    };
    Object.keys(Blockly.Blocks).forEach(blockName => {
        const downloadDisabledBlocks = ['controls_forEach', 'controls_for', 'variables_get', 'variables_set'];
        if (!downloadDisabledBlocks.includes(blockName)) {
            addDownloadToMenu(Blockly.Blocks[blockName]);
        }
    });
};
const repaintDefaultColours = () => {
    Blockly.Msg.LOGIC_HUE = '#DEDEDE';
    Blockly.Msg.LOOPS_HUE = '#DEDEDE';
    Blockly.Msg.MATH_HUE = '#DEDEDE';
    Blockly.Msg.TEXTS_HUE = '#DEDEDE';
    Blockly.Msg.LISTS_HUE = '#DEDEDE';
    Blockly.Msg.COLOUR_HUE = '#DEDEDE';
    Blockly.Msg.VARIABLES_HUE = '#DEDEDE';
    Blockly.Msg.VARIABLES_DYNAMIC_HUE = '#DEDEDE';
    Blockly.Msg.PROCEDURES_HUE = '#DEDEDE';

    Blockly.Blocks.logic.HUE = '#DEDEDE';
    Blockly.Blocks.loops.HUE = '#DEDEDE';
    Blockly.Blocks.math.HUE = '#DEDEDE';
    Blockly.Blocks.texts.HUE = '#DEDEDE';
    Blockly.Blocks.lists.HUE = '#DEDEDE';
    Blockly.Blocks.colour.HUE = '#DEDEDE';
    Blockly.Blocks.variables.HUE = '#DEDEDE';
    Blockly.Blocks.procedures.HUE = '#DEDEDE';
};

export default class _Blockly {
    constructor() {
        this.blocksXmlStr = '';
        this.generatedJs = '';
        // eslint-disable-next-line no-underscore-dangle
        Blockly.WorkspaceSvg.prototype.preloadAudio_ = () => {}; // https://github.com/google/blockly/issues/299
        this.initPromise = new Promise(resolve => {
            $.get('xml/toolbox.xml', toolboxXml => {
                blocks();
                const workspace = Blockly.inject('blocklyDiv', {
                    toolbox: xmlToStr(translateXml(toolboxXml.getElementsByTagName('xml')[0])),
                    zoom   : {
                        wheel: false,
                    },
                    trashcan: false,
                });
                workspace.addChangeListener(event => {
                    if (event.type === Blockly.Events.BLOCK_CREATE) {
                        event.ids.forEach(id => {
                            const block = workspace.getBlockById(id);
                            if (block) {
                                GTM.pushDataLayer({
                                    event     : 'Block Event',
                                    blockEvent: event.type,
                                    blockType : block.type,
                                });
                            }
                        });
                    } else if (event.type === Blockly.Events.BLOCK_DELETE) {
                        const dom = Blockly.Xml.textToDom(`<xml>${event.oldXml.outerHTML}</xml>`);
                        const blockNodes = dom.getElementsByTagName('block');
                        Array.from(blockNodes).forEach(blockNode => {
                            GTM.pushDataLayer({
                                event     : 'Block Event',
                                blockEvent: event.type,
                                blockType : blockNode.getAttribute('type'),
                            });
                        });
                    }
                });

                const renderInstance = render(workspace);
                window.addEventListener('resize', renderInstance, false);
                renderInstance();
                addBlocklyTranslation().then(() => {
                    const defaultStrat = getStorage(AppConstants.STORAGE_STRATEGY);
                    const xmlFile = defaultStrat ? `xml/${defaultStrat}.xml` : 'xml/main.xml';

                    $.get(xmlFile, main => {
                        repaintDefaultColours();
                        overrideBlocklyDefaultShape();
                        this.blocksXmlStr = Blockly.Xml.domToPrettyText(main);
                        Blockly.Xml.domToWorkspace(main.getElementsByTagName('xml')[0], workspace);
                        this.zoomOnPlusMinus();
                        disposeBlocksWithLoaders();
                        setTimeout(() => {
                            setBeforeUnload(true);
                            Blockly.mainWorkspace.cleanUp();
                            Blockly.mainWorkspace.clearUndo();
                        }, 0);
                        resolve();
                    }).then(() => {
                        remove(AppConstants.STORAGE_STRATEGY);
                    });
                });
            });
        });
    }
    /* eslint-disable class-methods-use-this */
    zoomOnPlusMinus(zoomIn) {
        const metrics = Blockly.mainWorkspace.getMetrics();
        if (zoomIn) {
            Blockly.mainWorkspace.zoom(metrics.viewWidth / 2, metrics.viewHeight / 2, 1);
        } else {
            Blockly.mainWorkspace.zoom(metrics.viewWidth / 2, metrics.viewHeight / 2, -1);
        }
    }
    resetWorkspace() {
        Blockly.Events.setGroup('reset');
        Blockly.mainWorkspace.clear();
        Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(this.blocksXmlStr), Blockly.mainWorkspace);
        Blockly.Events.setGroup(false);
    }
    /* eslint-disable class-methods-use-this */
    cleanUp() {
        Blockly.Events.setGroup(true);
        const topBlocks = Blockly.mainWorkspace.getTopBlocks(true);
        let cursorY = 0;
        topBlocks.forEach(block => {
            if (block.getSvgRoot().style.display !== 'none') {
                const xy = block.getRelativeToSurfaceXY();
                block.moveBy(-xy.x, cursorY - xy.y);
                block.snapToGrid();
                cursorY =
                    block.getRelativeToSurfaceXY().y + block.getHeightWidth().height + Blockly.BlockSvg.MIN_BLOCK_Y;
            }
        });
        Blockly.Events.setGroup(false);
        // Fire an event to allow scrollbars to resize.
        Blockly.mainWorkspace.resizeContents();
    }
    /* eslint-disable class-methods-use-this */
    load(blockStr = '', dropEvent = {}) {
        let xml;

        try {
            xml = Blockly.Xml.textToDom(blockStr);
        } catch (e) {
            throw createError('FileLoad', translate('Unrecognized file format'));
        }

        try {
            if (xml.hasAttribute('collection') && xml.getAttribute('collection') === 'true') {
                loadBlocks(xml, dropEvent);
            } else {
                loadWorkspace(xml);
            }
        } catch (e) {
            throw createError('FileLoad', translate('Unable to load the block file'));
        }
    }
    /* eslint-disable class-methods-use-this */
    save(arg) {
        const { filename, collection } = arg;

        setBeforeUnload(true);

        const xml = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace);
        cleanBeforeExport(xml);

        save(filename, collection, xml);
    }
    run(limitations = {}) {
        disableStrayBlocks();
        let code;
        try {
            code = `
var BinaryBotPrivateInit, BinaryBotPrivateStart, BinaryBotPrivateBeforePurchase, BinaryBotPrivateDuringPurchase, BinaryBotPrivateAfterPurchase;

var BinaryBotPrivateLastTickTime
var BinaryBotPrivateTickAnalysisList = [];

function BinaryBotPrivateRun(f, arg) {
 if (f) return f(arg);
 return false;
}

function BinaryBotPrivateTickAnalysis() {
 var currentTickTime = Bot.getLastTick(true).epoch
 if (currentTickTime === BinaryBotPrivateLastTickTime) {
   return
 }
 BinaryBotPrivateLastTickTime = currentTickTime
 for (var BinaryBotPrivateI = 0; BinaryBotPrivateI < BinaryBotPrivateTickAnalysisList.length; BinaryBotPrivateI++) {
   BinaryBotPrivateRun(BinaryBotPrivateTickAnalysisList[BinaryBotPrivateI]);
 }
}

var BinaryBotPrivateLimitations = ${JSON.stringify(limitations)};

${Blockly.JavaScript.workspaceToCode(Blockly.mainWorkspace)}

BinaryBotPrivateRun(BinaryBotPrivateInit);

while(true) {
 BinaryBotPrivateTickAnalysis();
 BinaryBotPrivateRun(BinaryBotPrivateStart)
 while(watch('before')) {
   BinaryBotPrivateTickAnalysis();
   BinaryBotPrivateRun(BinaryBotPrivateBeforePurchase);
 }
 while(watch('during')) {
   BinaryBotPrivateTickAnalysis();
   BinaryBotPrivateRun(BinaryBotPrivateDuringPurchase);
 }
 BinaryBotPrivateTickAnalysis();
 if(!BinaryBotPrivateRun(BinaryBotPrivateAfterPurchase)) {
   break;
 }
}
       `;
            this.generatedJs = code;
            if (code) {
                this.stop(true);
                this.interpreter = new Interpreter();
                this.interpreter.run(code).catch(e => {
                    globalObserver.emit('Error', e);
                    this.stop();
                });
            }
        } catch (e) {
            globalObserver.emit('Error', e);
            this.stop();
        }
    }
    stop(stopBeforeStart) {
        if (!stopBeforeStart) {
            const $runButtons = $('#runButton, #summaryRunButton');
            const $stopButtons = $('#stopButton, #summaryStopButton');
            if ($runButtons.is(':visible') || $stopButtons.is(':visible')) {
                $runButtons.show();
                $stopButtons.hide();
            }
        }
        if (this.interpreter) {
            this.interpreter.stop();
            this.interpreter = null;
        }
    }
    /* eslint-disable class-methods-use-this */
    undo() {
        Blockly.Events.setGroup('undo');
        Blockly.mainWorkspace.undo();
        Blockly.Events.setGroup(false);
    }
    /* eslint-disable class-methods-use-this */
    redo() {
        Blockly.mainWorkspace.undo(true);
    }
    /* eslint-disable class-methods-use-this */
    hasStarted() {
        return this.interpreter && this.interpreter.hasStarted();
    }
    /* eslint-enable */
}
<commit_msg>changes<commit_after>import './customBlockly';
import blocks from './blocks';
import {
    isMainBlock,
    save,
    disable,
    deleteBlocksLoadedBy,
    addLoadersFirst,
    cleanUpOnLoad,
    addDomAsBlock,
    backwardCompatibility,
    fixCollapsedBlocks,
    fixArgumentAttribute,
    removeUnavailableMarkets,
    strategyHasValidTradeTypeCategory,
    cleanBeforeExport,
} from './utils';
import Interpreter from '../../bot/Interpreter';
import createError from '../../common/error';
import { translate, xml as translateXml } from '../../../common/i18n';
import { getLanguage } from '../../../common/lang';
import { observer as globalObserver } from '../../../common/utils/observer';
import { showDialog } from '../../bot/tools';
import GTM from '../../../common/gtm';
import { parseQueryString } from '../../../common/utils/tools';

const setBeforeUnload = off => {
    if (off) {
        window.onbeforeunload = null;
    } else {
        window.onbeforeunload = () => 'You have some unsaved blocks, do you want to save them before you exit?';
    }
};

const disableStrayBlocks = () => {
    const topBlocks = Blockly.mainWorkspace.getTopBlocks();
    topBlocks.forEach(block => {
        if (
            !isMainBlock(block.type) &&
            ['block_holder', 'tick_analysis', 'loader', 'procedures_defreturn', 'procedures_defnoreturn'].indexOf(
                block.type
            ) < 0 &&
            !block.disabled
        ) {
            disable(block, translate('Blocks must be inside block holders, main blocks or functions'));
        }
    });
};
const disposeBlocksWithLoaders = () => {
    Blockly.mainWorkspace.addChangeListener(ev => {
        setBeforeUnload();
        if (ev.type === 'delete' && ev.oldXml.getAttribute('type') === 'loader' && ev.group !== 'undo') {
            deleteBlocksLoadedBy(ev.blockId, ev.group);
        }
    });
};
const marketsWereRemoved = xml => {
    if (!Array.from(xml.children).every(block => !removeUnavailableMarkets(block))) {
        if (window.trackJs) {
            trackJs.track('Invalid financial market');
        }
        showDialog({
            title  : translate('Warning'),
            text   : [translate('This strategy is not available in your country.')],
            buttons: [
                {
                    text : translate('OK'),
                    class: 'button-primary',
                    click() {
                        $(this).dialog('close');
                    },
                },
            ],
        })
            .then(() => {})
            .catch(() => {});
        return true;
    }
    return false;
};
export const loadWorkspace = xml => {
    if (!strategyHasValidTradeTypeCategory(xml)) return;
    if (marketsWereRemoved(xml)) return;

    Blockly.Events.setGroup('load');
    Blockly.mainWorkspace.clear();

    Array.from(xml.children).forEach(block => {
        backwardCompatibility(block);
    });

    fixArgumentAttribute(xml);
    Blockly.Xml.domToWorkspace(xml, Blockly.mainWorkspace);
    addLoadersFirst(xml).then(
        () => {
            fixCollapsedBlocks();
            Blockly.Events.setGroup(false);
            globalObserver.emit('ui.log.success', translate('Blocks are loaded successfully'));
        },
        e => {
            Blockly.Events.setGroup(false);
            throw e;
        }
    );
};

export const loadBlocks = (xml, dropEvent = {}) => {
    if (!strategyHasValidTradeTypeCategory(xml)) return;
    if (marketsWereRemoved(xml)) return;

    const variables = xml.getElementsByTagName('variables');
    if (variables.length > 0) {
        Blockly.Xml.domToVariables(variables[0], Blockly.mainWorkspace);
    }
    Blockly.Events.setGroup('load');
    addLoadersFirst(xml).then(
        loaders => {
            const addedBlocks = [
                ...loaders,
                ...Array.from(xml.children)
                    .map(block => addDomAsBlock(block))
                    .filter(b => b),
            ];
            cleanUpOnLoad(addedBlocks, dropEvent);
            fixCollapsedBlocks();
            globalObserver.emit('ui.log.success', translate('Blocks are loaded successfully'));
        },
        e => {
            throw e;
        }
    );
};
const xmlToStr = xml => {
    const serializer = new XMLSerializer();
    return serializer.serializeToString(xml);
};
const addBlocklyTranslation = () => {
    $.ajaxPrefilter(options => {
        options.async = true; // eslint-disable-line no-param-reassign
    });
    let lang = getLanguage();
    if (lang === 'ach') {
        lang = 'en';
    } else if (lang === 'zh_cn') {
        lang = 'zh-hans';
    } else if (lang === 'zh_tw') {
        lang = 'zh-hant';
    }
    return new Promise(resolve => {
        $.getScript(`translations/${lang}.js`, resolve);
    });
};
const onresize = () => {
    let element = document.getElementById('blocklyArea');
    const blocklyArea = element;
    const blocklyDiv = document.getElementById('blocklyDiv');
    let x = 0;
    let y = 0;
    do {
        x += element.offsetLeft;
        y += element.offsetTop;
        element = element.offsetParent;
    } while (element);
    // Position blocklyDiv over blocklyArea.
    blocklyDiv.style.left = `${x}px`;
    blocklyDiv.style.top = `${y}px`;
    blocklyDiv.style.width = `${blocklyArea.offsetWidth}px`;
    blocklyDiv.style.height = `${blocklyArea.offsetHeight}px`;
};
const render = workspace => () => {
    onresize();
    Blockly.svgResize(workspace);
};
const overrideBlocklyDefaultShape = () => {
    const addDownloadToMenu = block => {
        if (block instanceof Object) {
            // eslint-disable-next-line no-param-reassign, max-len
            block.customContextMenu = function customContextMenu(options) {
                options.push({
                    text    : translate('Download'),
                    enabled : true,
                    callback: () => {
                        const xml = Blockly.Xml.textToDom(
                            '<xml xmlns="http://www.w3.org/1999/xhtml" collection="false"></xml>'
                        );
                        xml.appendChild(Blockly.Xml.blockToDom(this));
                        save('binary-bot-block', true, xml);
                    },
                });
            };
        }
    };
    Object.keys(Blockly.Blocks).forEach(blockName => {
        const downloadDisabledBlocks = ['controls_forEach', 'controls_for', 'variables_get', 'variables_set'];
        if (!downloadDisabledBlocks.includes(blockName)) {
            addDownloadToMenu(Blockly.Blocks[blockName]);
        }
    });
};
const repaintDefaultColours = () => {
    Blockly.Msg.LOGIC_HUE = '#DEDEDE';
    Blockly.Msg.LOOPS_HUE = '#DEDEDE';
    Blockly.Msg.MATH_HUE = '#DEDEDE';
    Blockly.Msg.TEXTS_HUE = '#DEDEDE';
    Blockly.Msg.LISTS_HUE = '#DEDEDE';
    Blockly.Msg.COLOUR_HUE = '#DEDEDE';
    Blockly.Msg.VARIABLES_HUE = '#DEDEDE';
    Blockly.Msg.VARIABLES_DYNAMIC_HUE = '#DEDEDE';
    Blockly.Msg.PROCEDURES_HUE = '#DEDEDE';

    Blockly.Blocks.logic.HUE = '#DEDEDE';
    Blockly.Blocks.loops.HUE = '#DEDEDE';
    Blockly.Blocks.math.HUE = '#DEDEDE';
    Blockly.Blocks.texts.HUE = '#DEDEDE';
    Blockly.Blocks.lists.HUE = '#DEDEDE';
    Blockly.Blocks.colour.HUE = '#DEDEDE';
    Blockly.Blocks.variables.HUE = '#DEDEDE';
    Blockly.Blocks.procedures.HUE = '#DEDEDE';
};

export default class _Blockly {
    constructor() {
        this.blocksXmlStr = '';
        this.generatedJs = '';
        // eslint-disable-next-line no-underscore-dangle
        Blockly.WorkspaceSvg.prototype.preloadAudio_ = () => {}; // https://github.com/google/blockly/issues/299
        this.initPromise = new Promise(resolve => {
            $.get('xml/toolbox.xml', toolboxXml => {
                blocks();
                const workspace = Blockly.inject('blocklyDiv', {
                    toolbox: xmlToStr(translateXml(toolboxXml.getElementsByTagName('xml')[0])),
                    zoom   : {
                        wheel: false,
                    },
                    trashcan: false,
                });
                workspace.addChangeListener(event => {
                    if (event.type === Blockly.Events.BLOCK_CREATE) {
                        event.ids.forEach(id => {
                            const block = workspace.getBlockById(id);
                            if (block) {
                                GTM.pushDataLayer({
                                    event     : 'Block Event',
                                    blockEvent: event.type,
                                    blockType : block.type,
                                });
                            }
                        });
                    } else if (event.type === Blockly.Events.BLOCK_DELETE) {
                        const dom = Blockly.Xml.textToDom(`<xml>${event.oldXml.outerHTML}</xml>`);
                        const blockNodes = dom.getElementsByTagName('block');
                        Array.from(blockNodes).forEach(blockNode => {
                            GTM.pushDataLayer({
                                event     : 'Block Event',
                                blockEvent: event.type,
                                blockType : blockNode.getAttribute('type'),
                            });
                        });
                    }
                });

                const renderInstance = render(workspace);
                window.addEventListener('resize', renderInstance, false);
                renderInstance();
                addBlocklyTranslation().then(() => {
                    const defaultStrat = parseQueryString().strategy;
                    const xmlFile = defaultStrat ? `xml/${defaultStrat}.xml` : 'xml/main.xml';

                    $.get(xmlFile, main => {
                        repaintDefaultColours();
                        overrideBlocklyDefaultShape();
                        this.blocksXmlStr = Blockly.Xml.domToPrettyText(main);
                        Blockly.Xml.domToWorkspace(main.getElementsByTagName('xml')[0], workspace);
                        this.zoomOnPlusMinus();
                        disposeBlocksWithLoaders();
                        setTimeout(() => {
                            setBeforeUnload(true);
                            Blockly.mainWorkspace.cleanUp();
                            Blockly.mainWorkspace.clearUndo();
                        }, 0);
                        resolve();
                    });
                });
            });
        });
    }
    /* eslint-disable class-methods-use-this */
    zoomOnPlusMinus(zoomIn) {
        const metrics = Blockly.mainWorkspace.getMetrics();
        if (zoomIn) {
            Blockly.mainWorkspace.zoom(metrics.viewWidth / 2, metrics.viewHeight / 2, 1);
        } else {
            Blockly.mainWorkspace.zoom(metrics.viewWidth / 2, metrics.viewHeight / 2, -1);
        }
    }
    resetWorkspace() {
        Blockly.Events.setGroup('reset');
        Blockly.mainWorkspace.clear();
        Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(this.blocksXmlStr), Blockly.mainWorkspace);
        Blockly.Events.setGroup(false);
    }
    /* eslint-disable class-methods-use-this */
    cleanUp() {
        Blockly.Events.setGroup(true);
        const topBlocks = Blockly.mainWorkspace.getTopBlocks(true);
        let cursorY = 0;
        topBlocks.forEach(block => {
            if (block.getSvgRoot().style.display !== 'none') {
                const xy = block.getRelativeToSurfaceXY();
                block.moveBy(-xy.x, cursorY - xy.y);
                block.snapToGrid();
                cursorY =
                    block.getRelativeToSurfaceXY().y + block.getHeightWidth().height + Blockly.BlockSvg.MIN_BLOCK_Y;
            }
        });
        Blockly.Events.setGroup(false);
        // Fire an event to allow scrollbars to resize.
        Blockly.mainWorkspace.resizeContents();
    }
    /* eslint-disable class-methods-use-this */
    load(blockStr = '', dropEvent = {}) {
        let xml;

        try {
            xml = Blockly.Xml.textToDom(blockStr);
        } catch (e) {
            throw createError('FileLoad', translate('Unrecognized file format'));
        }

        try {
            if (xml.hasAttribute('collection') && xml.getAttribute('collection') === 'true') {
                loadBlocks(xml, dropEvent);
            } else {
                loadWorkspace(xml);
            }
        } catch (e) {
            throw createError('FileLoad', translate('Unable to load the block file'));
        }
    }
    /* eslint-disable class-methods-use-this */
    save(arg) {
        const { filename, collection } = arg;

        setBeforeUnload(true);

        const xml = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace);
        cleanBeforeExport(xml);

        save(filename, collection, xml);
    }
    run(limitations = {}) {
        disableStrayBlocks();
        let code;
        try {
            code = `
var BinaryBotPrivateInit, BinaryBotPrivateStart, BinaryBotPrivateBeforePurchase, BinaryBotPrivateDuringPurchase, BinaryBotPrivateAfterPurchase;

var BinaryBotPrivateLastTickTime
var BinaryBotPrivateTickAnalysisList = [];

function BinaryBotPrivateRun(f, arg) {
 if (f) return f(arg);
 return false;
}

function BinaryBotPrivateTickAnalysis() {
 var currentTickTime = Bot.getLastTick(true).epoch
 if (currentTickTime === BinaryBotPrivateLastTickTime) {
   return
 }
 BinaryBotPrivateLastTickTime = currentTickTime
 for (var BinaryBotPrivateI = 0; BinaryBotPrivateI < BinaryBotPrivateTickAnalysisList.length; BinaryBotPrivateI++) {
   BinaryBotPrivateRun(BinaryBotPrivateTickAnalysisList[BinaryBotPrivateI]);
 }
}

var BinaryBotPrivateLimitations = ${JSON.stringify(limitations)};

${Blockly.JavaScript.workspaceToCode(Blockly.mainWorkspace)}

BinaryBotPrivateRun(BinaryBotPrivateInit);

while(true) {
 BinaryBotPrivateTickAnalysis();
 BinaryBotPrivateRun(BinaryBotPrivateStart)
 while(watch('before')) {
   BinaryBotPrivateTickAnalysis();
   BinaryBotPrivateRun(BinaryBotPrivateBeforePurchase);
 }
 while(watch('during')) {
   BinaryBotPrivateTickAnalysis();
   BinaryBotPrivateRun(BinaryBotPrivateDuringPurchase);
 }
 BinaryBotPrivateTickAnalysis();
 if(!BinaryBotPrivateRun(BinaryBotPrivateAfterPurchase)) {
   break;
 }
}
       `;
            this.generatedJs = code;
            if (code) {
                this.stop(true);
                this.interpreter = new Interpreter();
                this.interpreter.run(code).catch(e => {
                    globalObserver.emit('Error', e);
                    this.stop();
                });
            }
        } catch (e) {
            globalObserver.emit('Error', e);
            this.stop();
        }
    }
    stop(stopBeforeStart) {
        if (!stopBeforeStart) {
            const $runButtons = $('#runButton, #summaryRunButton');
            const $stopButtons = $('#stopButton, #summaryStopButton');
            if ($runButtons.is(':visible') || $stopButtons.is(':visible')) {
                $runButtons.show();
                $stopButtons.hide();
            }
        }
        if (this.interpreter) {
            this.interpreter.stop();
            this.interpreter = null;
        }
    }
    /* eslint-disable class-methods-use-this */
    undo() {
        Blockly.Events.setGroup('undo');
        Blockly.mainWorkspace.undo();
        Blockly.Events.setGroup(false);
    }
    /* eslint-disable class-methods-use-this */
    redo() {
        Blockly.mainWorkspace.undo(true);
    }
    /* eslint-disable class-methods-use-this */
    hasStarted() {
        return this.interpreter && this.interpreter.hasStarted();
    }
    /* eslint-enable */
}
<|endoftext|>