<commit_before>// dark #326599
// light #4591c4
define(['/customize/messages.js'], function (Messages) {
    var loadingStyle = (function(){/*
@font-face {
  font-family: 'Open Sans';
  src: url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.eot');
  src: url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.eot?#iefix') format('embedded-opentype'),
       url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.woff') format('woff'),
       url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.ttf') format('truetype'),
       url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.svg#OpenSansRegular') format('svg');
  font-weight: normal;
  font-style: normal;
}

#cp-loading {
  visibility: visible;
  position: fixed;
  z-index: 10000000;
  top: 0px;
  bottom: 0px;
  left: 0px;
  right: 0px;
  background: linear-gradient(to right, #326599 0%, #326599 50%, #4591c4 50%, #4591c4 100%);
  color: #fafafa;
  font-size: 1.3em;
  line-height: 120%;
  opacity: 1;
  display: flex;
  flex-flow: column;
  justify-content: center;
  align-items: center;
  font: 20px 'Open Sans', 'Helvetica Neue', sans-serif !important;
}
#cp-loading.cp-loading-hidden {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.75s, visibility 0s 0.75s;
}
#cp-loading .cp-loading-logo {
    height: 300px;
    width: 300px;
    margin-top: 50px;
    flex: 0 1 auto;
    min-height: 0;
    text-align: center;
}
#cp-loading .cp-loading-logo img {
    max-width: 100%;
    max-height: 100%;
}
#cp-loading .cp-loading-container {
    width: 700px;
    max-width: 90vw;
    height: 500px;
    max-height: calc(100vh - 20px);
    margin: 50px;
    flex-shrink: 0;
    display: flex;
    flex-flow: column;
    justify-content: space-around;
    align-items: center;
}
@media screen and (max-height: 800px) {
    #cp-loading .cp-loading-container {
        height: auto;
    }
}
@media screen and (max-width: 600px) {
    #cp-loading .cp-loading-container {
        height: auto;
    }
}
#cp-loading .cp-loading-cryptofist {
  margin-left: auto;
  margin-right: auto;
  //height: 300px;
  max-width: 90vw;
  max-height: 300px;
  width: auto;
  height: auto;
  margin-bottom: 2em;
}
@media screen and (max-height: 500px) {
  #cp-loading .cp-loading-logo {
      display: none;
  }
}
#cp-loading-message {
    background: #FFF;
    padding: 20px;
    width: 100%;
    color: #3F4141;
    text-align: left;
    display: none;
}

#cp-loading-password-prompt p.cp-password-error {
    color: white;
    background: #9e0000;
    padding: 5px;
    margin-bottom: 15px;
}
#cp-loading-password-prompt .cp-password-info {
    text-align: left;
    margin-bottom: 15px;
}
#cp-loading-burn-after-reading .cp-password-info {
    margin-bottom: 15px;
}

p.cp-password-info{
    text-align: left;
}
#cp-loading-password-prompt .cp-password-form {
    display: flex;
    flex-wrap: wrap;
}
#cp-loading-password-prompt .cp-password-form button{
    background-color: #4591c4;
    color: white;
    border: 1px solid #4591c4;
}

.cp-password-input{
    font-size:16px;
    border: 1px solid #4591c4;
    background-color: white;
    border-radius 0;
}

.cp-password-form button{
    padding: 8px 12px;
    font-weight: bold;
    text-transform: uppercase;
}

#cp-loading-password-prompt .cp-password-form{
    width: 100%;
}

#cp-loading-password-prompt .cp-password-form .cp-password-container {
    flex-shrink: 1;
    min-width: 0;
}

#cp-loading-password-prompt .cp-password-form .cp-password-container .cp-password-reveal{
    color: #4591c4;
    padding: 0px 24px;
}

#cp-loading-password-prompt .cp-password-form input {
    flex: 1;
    padding: 12px;
    min-width: 0;
    text-overflow: ellipsis;
}
#cp-loading-password-prompt .cp-password-form button:hover {
    background-color: #326599;
}
#cp-loading-password-prompt ::placeholder {
    color: #999999;
    opacity: 1;
}
#cp-loading-password-prompt :-ms-input-placeholder {
    color: #d9d9d9;
}
#cp-loading-password-prompt ::-ms-input-placeholder {
    color: #d9d9d9;
}
#cp-loading .cp-loading-spinner-container {
  position: relative;
  height: 100px;
}
#cp-loading .cp-loading-spinner-container > div {
  height: 100px;
}
.cp-loading-progress {
    width: 100%;
    margin: 20px;
}
.cp-loading-progress p {
    margin: 5px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.cp-loading-progress-list ul {
    list-style: none;
    padding-left: 0;
}
.cp-loading-progress-list li {
    padding: 0px 5px;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
.cp-loading-progress-list li i {
    width: 22px;
}
.cp-loading-progress-list li span{
    margin-left: 20px;
}

.cp-loading-progress-bar {
    height: 24px;
    background: white;
}
.cp-loading-progress-bar-value {
    height: 100%;
    background: #5cb85c;
}

@keyframes spin {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(1800deg);
    }
}

.cp-spinner {
    display: inline-block;
    box-sizing: border-box;
    width: 80px;
    height: 80px;
    border: 11px solid white;
    border-radius: 50%;
    border-top-color: transparent;
    animation: spin infinite 3s;
    animation-timing-function: cubic-bezier(.6,0.15,0.4,0.85);
}

button.primary{
    border: 1px solid #4591c4;
    padding: 8px 12px;
    text-transform: uppercase;
    background-color: #4591c4;
    color: white;
    font-weight: bold;
}

button.primary:hover{
    background-color: rgb(52, 118, 162);
}

*/}).toString().slice(14, -3);
    var urlArgs = window.location.href.replace(/^.*\?([^\?]*)$/, function (all, x) { return x; });
    var elem = document.createElement('div');
    elem.setAttribute('id', 'cp-loading');
    elem.innerHTML = [
        '',
        '
',
            '',
        '
',
        '
',
            '
',
                '',
            '
',
            '
',
                '

',
                '

',
            '
',
            '

',
        '
'
    ].join('');
    var built = false;

    // XXX
    var types = ['less', 'drive', 'migrate', 'sf', 'team', 'pad', 'end'];
    Messages.loading_state_0 = "Less";
    Messages.loading_state_1 = "Drive";
    Messages.loading_state_2 = "Migrate";
    Messages.loading_state_3 = "SF";
    Messages.loading_state_4 = "Team";
    Messages.loading_state_5 = "Pad";
    var current;
    var makeList = function (data) {
        var c = types.indexOf(data.type);
        current = c;
        var getLi = function (i) {
            var check = (i < c || (i === c && data.progress >= 100)) ? 'fa-check-square-o'
                                                                      : 'fa-square-o';
            var p = Math.min(Math.floor(data.progress), 100);
            var percent = i < c ? '(100%)' : (i === c ? '('+p+'%)' : '(0%)');
            return '
'+Messages['loading_state_'+i]+'' +
                   ''+percent+'';
        };
        var list = '
';
        types.forEach(function (el, i) {
            if (i >= 6) { return; }
            list += getLi(i);
        });
        list += '
';
        return list;
    };
    var makeBar = function (data) {
        var c = types.indexOf(data.type);
        var l = types.length;
        var progress = Math.min(data.progress, 100);
        var p = (progress / l) + (100 * c / l);
        var bar = '
'+
                    '

'+
                  '
';
        return bar;
    };

    var updateLoadingProgress = function (data) {
        if (!built) { return; }
        var c = types.indexOf(data.type);
        if (c < current) { return console.error(data); }
        try {
            document.querySelector('.cp-loading-spinner-container').style.display = 'none';
            document.querySelector('.cp-loading-progress-list').innerHTML = makeList(data);
            document.querySelector('.cp-loading-progress-container').innerHTML = makeBar(data);
        } catch (e) { console.error(e); }
    };
    window.CryptPad_updateLoadingProgress = updateLoadingProgress;
    window.CryptPad_loadingError = function (err) {
        if (!built) { return; }
        try {
            document.querySelector('.cp-loading-spinner-container').setAttribute('style', 'display:none;');
            document.querySelector('#cp-loading-message').setAttribute('style', 'display:block;');
            document.querySelector('#cp-loading-message').innerText = err;
        } catch (e) { console.error(e); }
    };
    return function () {
        built = true;
        var intr;
        var append = function () {
            if (!document.body) { return; }
            clearInterval(intr);
            document.body.appendChild(elem);
        };
        intr = setInterval(append, 100);
        append();
    };
});
<commit_msg>Center loading steps<commit_after>// dark #326599
// light #4591c4
define(['/customize/messages.js'], function (Messages) {
    var loadingStyle = (function(){/*
@font-face {
  font-family: 'Open Sans';
  src: url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.eot');
  src: url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.eot?#iefix') format('embedded-opentype'),
       url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.woff') format('woff'),
       url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.ttf') format('truetype'),
       url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.svg#OpenSansRegular') format('svg');
  font-weight: normal;
  font-style: normal;
}

#cp-loading {
  visibility: visible;
  position: fixed;
  z-index: 10000000;
  top: 0px;
  bottom: 0px;
  left: 0px;
  right: 0px;
  background: linear-gradient(to right, #326599 0%, #326599 50%, #4591c4 50%, #4591c4 100%);
  color: #fafafa;
  font-size: 1.3em;
  line-height: 120%;
  opacity: 1;
  display: flex;
  flex-flow: column;
  justify-content: center;
  align-items: center;
  font: 20px 'Open Sans', 'Helvetica Neue', sans-serif !important;
}
#cp-loading.cp-loading-hidden {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.75s, visibility 0s 0.75s;
}
#cp-loading .cp-loading-logo {
    height: 300px;
    width: 300px;
    margin-top: 50px;
    flex: 0 1 auto;
    min-height: 0;
    text-align: center;
}
#cp-loading .cp-loading-logo img {
    max-width: 100%;
    max-height: 100%;
}
#cp-loading .cp-loading-container {
    width: 700px;
    max-width: 90vw;
    height: 500px;
    max-height: calc(100vh - 20px);
    margin: 50px;
    flex-shrink: 0;
    display: flex;
    flex-flow: column;
    justify-content: space-around;
    align-items: center;
}
@media screen and (max-height: 800px) {
    #cp-loading .cp-loading-container {
        height: auto;
    }
}
@media screen and (max-width: 600px) {
    #cp-loading .cp-loading-container {
        height: auto;
    }
}
#cp-loading .cp-loading-cryptofist {
  margin-left: auto;
  margin-right: auto;
  //height: 300px;
  max-width: 90vw;
  max-height: 300px;
  width: auto;
  height: auto;
  margin-bottom: 2em;
}
@media screen and (max-height: 500px) {
  #cp-loading .cp-loading-logo {
      display: none;
  }
}
#cp-loading-message {
    background: #FFF;
    padding: 20px;
    width: 100%;
    color: #3F4141;
    text-align: left;
    display: none;
}

#cp-loading-password-prompt p.cp-password-error {
    color: white;
    background: #9e0000;
    padding: 5px;
    margin-bottom: 15px;
}
#cp-loading-password-prompt .cp-password-info {
    text-align: left;
    margin-bottom: 15px;
}
#cp-loading-burn-after-reading .cp-password-info {
    margin-bottom: 15px;
}

p.cp-password-info{
    text-align: left;
}
#cp-loading-password-prompt .cp-password-form {
    display: flex;
    flex-wrap: wrap;
}
#cp-loading-password-prompt .cp-password-form button{
    background-color: #4591c4;
    color: white;
    border: 1px solid #4591c4;
}

.cp-password-input{
    font-size:16px;
    border: 1px solid #4591c4;
    background-color: white;
    border-radius 0;
}

.cp-password-form button{
    padding: 8px 12px;
    font-weight: bold;
    text-transform: uppercase;
}

#cp-loading-password-prompt .cp-password-form{
    width: 100%;
}

#cp-loading-password-prompt .cp-password-form .cp-password-container {
    flex-shrink: 1;
    min-width: 0;
}

#cp-loading-password-prompt .cp-password-form .cp-password-container .cp-password-reveal{
    color: #4591c4;
    padding: 0px 24px;
}

#cp-loading-password-prompt .cp-password-form input {
    flex: 1;
    padding: 12px;
    min-width: 0;
    text-overflow: ellipsis;
}
#cp-loading-password-prompt .cp-password-form button:hover {
    background-color: #326599;
}
#cp-loading-password-prompt ::placeholder {
    color: #999999;
    opacity: 1;
}
#cp-loading-password-prompt :-ms-input-placeholder {
    color: #d9d9d9;
}
#cp-loading-password-prompt ::-ms-input-placeholder {
    color: #d9d9d9;
}
#cp-loading .cp-loading-spinner-container {
  position: relative;
  height: 100px;
}
#cp-loading .cp-loading-spinner-container > div {
  height: 100px;
}
.cp-loading-progress {
    width: 100%;
    margin: 20px;
    text-align: center;
}
.cp-loading-progress p {
    margin: 5px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.cp-loading-progress-list {
    text-align: left;
    display: inline-block;
}
.cp-loading-progress-list ul {
    list-style: none;
    padding-left: 0;
}
.cp-loading-progress-list li {
    padding: 0px 5px;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
.cp-loading-progress-list li i {
    width: 22px;
}
.cp-loading-progress-list li span{
    margin-left: 10px;
}
.cp-loading-progress-list li span.percent {
    position: absolute;
}

.cp-loading-progress-bar {
    height: 24px;
    background: white;
}
.cp-loading-progress-bar-value {
    height: 100%;
    background: #5cb85c;
}

@keyframes spin {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(1800deg);
    }
}

.cp-spinner {
    display: inline-block;
    box-sizing: border-box;
    width: 80px;
    height: 80px;
    border: 11px solid white;
    border-radius: 50%;
    border-top-color: transparent;
    animation: spin infinite 3s;
    animation-timing-function: cubic-bezier(.6,0.15,0.4,0.85);
}

button.primary{
    border: 1px solid #4591c4;
    padding: 8px 12px;
    text-transform: uppercase;
    background-color: #4591c4;
    color: white;
    font-weight: bold;
}

button.primary:hover{
    background-color: rgb(52, 118, 162);
}

*/}).toString().slice(14, -3);
    var urlArgs = window.location.href.replace(/^.*\?([^\?]*)$/, function (all, x) { return x; });
    var elem = document.createElement('div');
    elem.setAttribute('id', 'cp-loading');
    elem.innerHTML = [
        '',
        '
',
            '',
        '
',
        '
',
            '
',
                '',
            '
',
            '
',
                '

',
                '

',
            '
',
            '

',
        '
'
    ].join('');
    var built = false;

    // XXX
    var types = ['less', 'drive', 'migrate', 'sf', 'team', 'pad', 'end'];
    Messages.loading_state_0 = "Less";
    Messages.loading_state_1 = "Drive";
    Messages.loading_state_2 = "Migrate";
    Messages.loading_state_3 = "SF";
    Messages.loading_state_4 = "Team";
    Messages.loading_state_5 = "Pad";
    var current;
    var makeList = function (data) {
        var c = types.indexOf(data.type);
        current = c;
        var getLi = function (i) {
            var check = (i < c || (i === c && data.progress >= 100)) ? 'fa-check-square-o'
                                                                      : 'fa-square-o';
            var percentStr = '';
            if (i === c) {
                var p = Math.min(Math.floor(data.progress), 100);
                percentStr = '('+p+'%)';
            }
            return '
'+Messages['loading_state_'+i]+'' + percentStr;
        };
        var list = '
';
        types.forEach(function (el, i) {
            if (i >= 6) { return; }
            list += getLi(i);
        });
        list += '
';
        return list;
    };
    var makeBar = function (data) {
        var c = types.indexOf(data.type);
        var l = types.length;
        var progress = Math.min(data.progress, 100);
        var p = (progress / l) + (100 * c / l);
        var bar = '
'+
                    '

'+
                  '
';
        return bar;
    };

    var updateLoadingProgress = function (data) {
        if (!built) { return; }
        var c = types.indexOf(data.type);
        if (c < current) { return console.error(data); }
        try {
            document.querySelector('.cp-loading-spinner-container').style.display = 'none';
            document.querySelector('.cp-loading-progress-list').innerHTML = makeList(data);
            document.querySelector('.cp-loading-progress-container').innerHTML = makeBar(data);
        } catch (e) { console.error(e); }
    };
    window.CryptPad_updateLoadingProgress = updateLoadingProgress;
    window.CryptPad_loadingError = function (err) {
        if (!built) { return; }
        try {
            document.querySelector('.cp-loading-spinner-container').setAttribute('style', 'display:none;');
            document.querySelector('#cp-loading-message').setAttribute('style', 'display:block;');
            document.querySelector('#cp-loading-message').innerText = err;
        } catch (e) { console.error(e); }
    };
    return function () {
        built = true;
        var intr;
        var append = function () {
            if (!document.body) { return; }
            clearInterval(intr);
            document.body.appendChild(elem);
        };
        intr = setInterval(append, 100);
        append();
    };
});
<|endoftext|>


<commit_before>// dark #326599
// light #4591c4
define([], function () {
    var loadingStyle = (function(){/*
#cp-loading {
  transition: opacity 0.75s, visibility 0s 0.75s;
  visibility: visible;
  position: fixed;
  z-index: 10000000;
  top: 0px;
  bottom: 0px;
  left: 0px;
  right: 0px;
  background: linear-gradient(to right, #326599 0%, #326599 50%, #4591c4 50%, #4591c4 100%);
  color: #fafafa;
  font-size: 1.3em;
  line-height: 120%;
  opacity: 1;
  display: flex;
  flex-flow: column;
  justify-content: center;
  align-items: center;
}
#cp-loading.cp-loading-hidden {
  opacity: 0;
  visibility: hidden;
}
#cp-loading .cp-loading-logo {
    height: 300px;
    width: 300px;
    margin-top: 50px;
    flex: 0 1 auto;
    min-height: 0;
    text-align: center;
}
#cp-loading .cp-loading-logo img {
    max-width: 100%;
    max-height: 100%;
}
#cp-loading .cp-loading-container {
    width: 700px;
    max-width: 90vw;
    height: 500px;
    max-height: calc(100vh - 20px);
    margin: 50px;
    flex-shrink: 0;
    display: flex;
    flex-flow: column;
    justify-content: space-around;
    align-items: center;
}
@media screen and (max-height: 800px) {
    #cp-loading .cp-loading-container {
        height: auto;
    }
}
@media screen and (max-width: 600px) {
    #cp-loading .cp-loading-container {
        height: auto;
    }
}
#cp-loading .cp-loading-cryptofist {
  margin-left: auto;
  margin-right: auto;
  //height: 300px;
  max-width: 90vw;
  max-height: 300px;
  width: auto;
  height: auto;
  margin-bottom: 2em;
}
@media screen and (max-height: 500px) {
  #cp-loading .cp-loading-logo {
      display: none;
  }
}
#cp-loading-message {
    background: #FFF;
    padding: 20px;
    width: 100%;
    color: #3F4141;
    text-align: left;
    display: none;
}

#cp-loading-password-prompt .cp-password-error {
    color: white;
    background: #9e0000;
    padding: 5px;
    margin-bottom: 15px;
}
#cp-loading-password-prompt .cp-password-info {
    text-align: left;
    margin-bottom: 15px;
}
p.cp-password-info{
    text-align: left;
}
#cp-loading-password-prompt .cp-password-form {
    display: flex;
    flex-wrap: wrap;
}
#cp-loading-password-prompt .cp-password-form button{
    background-color: #4591c4;
    color: white;
    border: 1px solid #4591c4;
}

.cp-password-input{
    font-size:16px;
    border: 1px solid #4591c4;
    background-color: white;
    border-radius 0;
}

.cp-password-form button{
    padding: 8px 12px;
    font-weight: bold;
    text-transform: uppercase;
}

#cp-loading-password-prompt .cp-password-form{
    width: 100%;
}

#cp-loading-password-prompt .cp-password-form .cp-password-container {
    flex-shrink: 1;
    min-width: 0;
}

#cp-loading-password-prompt .cp-password-form .cp-password-container .cp-password-reveal{
    color: #4591c4;
    padding: 0px 24px;
}

#cp-loading-password-prompt .cp-password-form input {
    flex: 1;
    padding: 12px;
    min-width: 0;
    text-overflow: ellipsis;
}
#cp-loading-password-prompt .cp-password-form button:hover {
    background-color: #326599;
}
#cp-loading-password-prompt ::placeholder {
    color: #999999;
    opacity: 1;
}
#cp-loading-password-prompt :-ms-input-placeholder {
    color: #d9d9d9;
}
#cp-loading-password-prompt ::-ms-input-placeholder {
    color: #d9d9d9;
}
#cp-loading .cp-loading-spinner-container {
  position: relative;
  height: 100px;
}
#cp-loading .cp-loading-spinner-container > div {
  height: 100px;
}
#cp-loading-tip {
  position: fixed;
  z-index: 10000000;
  top: 80%;
  left: 0;
  right: 0;
  text-align: center;
  transition: opacity 750ms;
  transition-delay: 3000ms;
}
@media screen and (max-height: 600px) {
  #cp-loading-tip {
    display: none;
  }
}
#cp-loading-tip span {
  background: #222;
  color: #fafafa;
  text-align: center;
  font-size: 1.3em;
  opacity: 0.7;
  font-family: 'Open Sans', 'Helvetica Neue', sans-serif;
  padding: 15px;
  max-width: 60%;
  display: inline-block;
}
.cp-loading-progress {
    width: 100%;
    margin: 20px;
}
.cp-loading-progress p {
    margin: 5px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.cp-loading-progress-bar {
    height: 24px;
    background: white;
}
.cp-loading-progress-bar-value {
    height: 100%;
    background: #5cb85c;
}

@keyframes spin {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(1800deg);
    }
}

.cp-spinner {
    display: inline-block;
    box-sizing: border-box;
    width: 80px;
    height: 80px;
    border: 11px solid white;
    border-radius: 50%;
    border-top-color: transparent;
    animation: spin infinite 3s;
    animation-timing-function: cubic-bezier(.6,0.15,0.4,0.85);
}

button.primary{
    border: 1px solid #4591c4;
    padding: 8px 12px;
    text-transform: uppercase;
    background-color: #4591c4;
    color: white;
    font-weight: bold;
}

button.primary:hover{
    background-color: rgb(52, 118, 162);
}

*/}).toString().slice(14, -3);
    var urlArgs = window.location.href.replace(/^.*\?([^\?]*)$/, function (all, x) { return x; });
    var elem = document.createElement('div');
    elem.setAttribute('id', 'cp-loading');
    elem.innerHTML = [
        '',
        '
',
            '',
        '
',
        '
',
            '
',
                '',
            '
',
            '

',
        '
'
    ].join('');
    return function () {
        var intr;
        var append = function () {
            if (!document.body) { return; }
            clearInterval(intr);
            document.body.appendChild(elem);
        };
        intr = setInterval(append, 100);
        append();
    };
});
<commit_msg>fix warning paragraph spacing<commit_after>// dark #326599
// light #4591c4
define([], function () {
    var loadingStyle = (function(){/*
#cp-loading {
  transition: opacity 0.75s, visibility 0s 0.75s;
  visibility: visible;
  position: fixed;
  z-index: 10000000;
  top: 0px;
  bottom: 0px;
  left: 0px;
  right: 0px;
  background: linear-gradient(to right, #326599 0%, #326599 50%, #4591c4 50%, #4591c4 100%);
  color: #fafafa;
  font-size: 1.3em;
  line-height: 120%;
  opacity: 1;
  display: flex;
  flex-flow: column;
  justify-content: center;
  align-items: center;
}
#cp-loading.cp-loading-hidden {
  opacity: 0;
  visibility: hidden;
}
#cp-loading .cp-loading-logo {
    height: 300px;
    width: 300px;
    margin-top: 50px;
    flex: 0 1 auto;
    min-height: 0;
    text-align: center;
}
#cp-loading .cp-loading-logo img {
    max-width: 100%;
    max-height: 100%;
}
#cp-loading .cp-loading-container {
    width: 700px;
    max-width: 90vw;
    height: 500px;
    max-height: calc(100vh - 20px);
    margin: 50px;
    flex-shrink: 0;
    display: flex;
    flex-flow: column;
    justify-content: space-around;
    align-items: center;
}
@media screen and (max-height: 800px) {
    #cp-loading .cp-loading-container {
        height: auto;
    }
}
@media screen and (max-width: 600px) {
    #cp-loading .cp-loading-container {
        height: auto;
    }
}
#cp-loading .cp-loading-cryptofist {
  margin-left: auto;
  margin-right: auto;
  //height: 300px;
  max-width: 90vw;
  max-height: 300px;
  width: auto;
  height: auto;
  margin-bottom: 2em;
}
@media screen and (max-height: 500px) {
  #cp-loading .cp-loading-logo {
      display: none;
  }
}
#cp-loading-message {
    background: #FFF;
    padding: 20px;
    width: 100%;
    color: #3F4141;
    text-align: left;
    display: none;
}

#cp-loading-password-prompt p.cp-password-error {
    color: white;
    background: #9e0000;
    padding: 5px;
    margin-bottom: 15px;
}
#cp-loading-password-prompt .cp-password-info {
    text-align: left;
    margin-bottom: 15px;
}
#cp-loading-burn-after-reading .cp-password-info {
    margin-bottom: 15px;
}

p.cp-password-info{
    text-align: left;
}
#cp-loading-password-prompt .cp-password-form {
    display: flex;
    flex-wrap: wrap;
}
#cp-loading-password-prompt .cp-password-form button{
    background-color: #4591c4;
    color: white;
    border: 1px solid #4591c4;
}

.cp-password-input{
    font-size:16px;
    border: 1px solid #4591c4;
    background-color: white;
    border-radius 0;
}

.cp-password-form button{
    padding: 8px 12px;
    font-weight: bold;
    text-transform: uppercase;
}

#cp-loading-password-prompt .cp-password-form{
    width: 100%;
}

#cp-loading-password-prompt .cp-password-form .cp-password-container {
    flex-shrink: 1;
    min-width: 0;
}

#cp-loading-password-prompt .cp-password-form .cp-password-container .cp-password-reveal{
    color: #4591c4;
    padding: 0px 24px;
}

#cp-loading-password-prompt .cp-password-form input {
    flex: 1;
    padding: 12px;
    min-width: 0;
    text-overflow: ellipsis;
}
#cp-loading-password-prompt .cp-password-form button:hover {
    background-color: #326599;
}
#cp-loading-password-prompt ::placeholder {
    color: #999999;
    opacity: 1;
}
#cp-loading-password-prompt :-ms-input-placeholder {
    color: #d9d9d9;
}
#cp-loading-password-prompt ::-ms-input-placeholder {
    color: #d9d9d9;
}
#cp-loading .cp-loading-spinner-container {
  position: relative;
  height: 100px;
}
#cp-loading .cp-loading-spinner-container > div {
  height: 100px;
}
#cp-loading-tip {
  position: fixed;
  z-index: 10000000;
  top: 80%;
  left: 0;
  right: 0;
  text-align: center;
  transition: opacity 750ms;
  transition-delay: 3000ms;
}
@media screen and (max-height: 600px) {
  #cp-loading-tip {
    display: none;
  }
}
#cp-loading-tip span {
  background: #222;
  color: #fafafa;
  text-align: center;
  font-size: 1.3em;
  opacity: 0.7;
  font-family: 'Open Sans', 'Helvetica Neue', sans-serif;
  padding: 15px;
  max-width: 60%;
  display: inline-block;
}
.cp-loading-progress {
    width: 100%;
    margin: 20px;
}
.cp-loading-progress p {
    margin: 5px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.cp-loading-progress-bar {
    height: 24px;
    background: white;
}
.cp-loading-progress-bar-value {
    height: 100%;
    background: #5cb85c;
}

@keyframes spin {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(1800deg);
    }
}

.cp-spinner {
    display: inline-block;
    box-sizing: border-box;
    width: 80px;
    height: 80px;
    border: 11px solid white;
    border-radius: 50%;
    border-top-color: transparent;
    animation: spin infinite 3s;
    animation-timing-function: cubic-bezier(.6,0.15,0.4,0.85);
}

button.primary{
    border: 1px solid #4591c4;
    padding: 8px 12px;
    text-transform: uppercase;
    background-color: #4591c4;
    color: white;
    font-weight: bold;
}

button.primary:hover{
    background-color: rgb(52, 118, 162);
}

*/}).toString().slice(14, -3);
    var urlArgs = window.location.href.replace(/^.*\?([^\?]*)$/, function (all, x) { return x; });
    var elem = document.createElement('div');
    elem.setAttribute('id', 'cp-loading');
    elem.innerHTML = [
        '',
        '
',
            '',
        '
',
        '
',
            '
',
                '',
            '
',
            '

',
        '
'
    ].join('');
    return function () {
        var intr;
        var append = function () {
            if (!document.body) { return; }
            clearInterval(intr);
            document.body.appendChild(elem);
        };
        intr = setInterval(append, 100);
        append();
    };
});
<|endoftext|>


<commit_before>/*
Copyright 2015 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');
var filesize = require('filesize');

var MImageTileController = require('matrix-react-sdk/lib/controllers/molecules/MImageTile')

var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
var Modal = require('matrix-react-sdk/lib/Modal');
var sdk = require('matrix-react-sdk')

module.exports = React.createClass({
    displayName: 'MImageTile',
    mixins: [MImageTileController],

    thumbHeight: function(fullWidth, fullHeight, thumbWidth, thumbHeight) {
        if (!fullWidth || !fullHeight) {
            // Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even
            // log this because it's spammy
            return undefined;
        }
        if (fullWidth < thumbWidth && fullHeight < thumbHeight) {
            // no scaling needs to be applied
            return fullHeight;
        }
        var widthMulti = thumbWidth / fullWidth;
        var heightMulti = thumbHeight / fullHeight;
        if (widthMulti < heightMulti) {
            // width is the dominant dimension so scaling will be fixed on that
            return Math.floor(widthMulti * fullHeight);
        }
        else {
            // height is the dominant dimension so scaling will be fixed on that
            return Math.floor(heightMulti * fullHeight);
        }
    },

    onClick: function(ev) {
        if (ev.button == 0 && !ev.metaKey) {
            ev.preventDefault();
            var content = this.props.mxEvent.getContent();
            var httpUrl = MatrixClientPeg.get().mxcUrlToHttp(content.url);
            var ImageView = sdk.getComponent("atoms.ImageView");
            Modal.createDialog(ImageView, {
                src: httpUrl,
                width: content.info.w,
                height: content.info.h
            });
        }
    },

    render: function() {
        var content = this.props.mxEvent.getContent();
        var cli = MatrixClientPeg.get();

        var thumbHeight = null;
        if (content.info) thumbHeight = this.thumbHeight(content.info.w, content.info.h, 320, 240);

        var imgStyle = {};
        if (thumbHeight) imgStyle['height'] = thumbHeight;

        return (

                        Download {content.body} ({ filesize(content.info.size) })

        );
    },
});
<commit_msg>Check for existence of content.size. Fixes #201.<commit_after>/*
Copyright 2015 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');
var filesize = require('filesize');

var MImageTileController = require('matrix-react-sdk/lib/controllers/molecules/MImageTile')

var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
var Modal = require('matrix-react-sdk/lib/Modal');
var sdk = require('matrix-react-sdk')

module.exports = React.createClass({
    displayName: 'MImageTile',
    mixins: [MImageTileController],

    thumbHeight: function(fullWidth, fullHeight, thumbWidth, thumbHeight) {
        if (!fullWidth || !fullHeight) {
            // Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even
            // log this because it's spammy
            return undefined;
        }
        if (fullWidth < thumbWidth && fullHeight < thumbHeight) {
            // no scaling needs to be applied
            return fullHeight;
        }
        var widthMulti = thumbWidth / fullWidth;
        var heightMulti = thumbHeight / fullHeight;
        if (widthMulti < heightMulti) {
            // width is the dominant dimension so scaling will be fixed on that
            return Math.floor(widthMulti * fullHeight);
        }
        else {
            // height is the dominant dimension so scaling will be fixed on that
            return Math.floor(heightMulti * fullHeight);
        }
    },

    onClick: function(ev) {
        if (ev.button == 0 && !ev.metaKey) {
            ev.preventDefault();
            var content = this.props.mxEvent.getContent();
            var httpUrl = MatrixClientPeg.get().mxcUrlToHttp(content.url);
            var ImageView = sdk.getComponent("atoms.ImageView");
            Modal.createDialog(ImageView, {
                src: httpUrl,
                width: content.info.w,
                height: content.info.h
            });
        }
    },

    render: function() {
        var content = this.props.mxEvent.getContent();
        var cli = MatrixClientPeg.get();

        var thumbHeight = null;
        if (content.info) thumbHeight = this.thumbHeight(content.info.w, content.info.h, 320, 240);

        var imgStyle = {};
        if (thumbHeight) imgStyle['height'] = thumbHeight;

        return (

                        Download {content.body} ({ content.info && content.info.size ? filesize(content.info.size) : "Unknwon size" })

        );
    },
});
<|endoftext|>


<commit_before>/**
 * BBB `app` generator for Yeoman
 * Scaffhold the project structure
 */

"use strict";
var util = require("util");
var path = require("path");
var _ = require("lodash");
var grunt = require("grunt");
var Tree = require("ast-query");
var InitGenerator = require("../init/index");

/**
 * Module exports
 */

module.exports = Generator;
Generator._name = "bbb:app";

/**
 * BBB Generator constructor
 * Extend the bbb:init generator
 * Launch packages manager once the installation ends
 */

function Generator(args, options, config) {

  // Extend parents generator/class
  InitGenerator.apply(this, arguments);

  // Use BBB fetched via NPM as source root for the app task
  this.sourceRoot(path.join(__dirname, "../../../node_modules/backbone-boilerplate/"));

  // Get source package.json relevant information
  // Get source package.json relevant information
  var bbbPkg = _.pick(this.src.readJSON("package.json"),
      "devDependencies", "peerDependencies", "scripts");

  _.extend(this.pkg, bbbPkg);

  // Launch packages manager once the installation ends
  this.on("end", function () {
    if( options["skip-install"] ) {
      return;
    }

    this.bowerInstall();
    this.npmInstall(undefined, { quiet: true });
  }.bind(this));
}

util.inherits(Generator, InitGenerator);

/**
 * Command prompt questions
 * Note: Directly extend these functions on the generator prototype as Yeoman run every
 * direct prototype attached method (e.g.: `.hasOwnProperty()`)
 */

Generator.prototype.askFor = InitGenerator.prototype.askFor;

/**
 * Copy boilerplate main code
 * all `app/` folder, index.html and favicon
 */

Generator.prototype.app = function app() {
  this.dest.mkdir(path.join(this.config.get("paths").base, "vendor"));

  this.src.recurse("app", function( abspath, rootdir, subdir, filename ) {
    var code = grunt.file.read(abspath);
    var dest = path.join(this.config.get("paths").base, "app", filename);

    // Manage app.js elsewhere
    if (filename === "app.js") {
      return;
    }

    if (abspath.slice(-3) === ".js") {
      code = this.normalizeJS(code);
    }

    if (abspath.slice(-5) === ".html") {
      code = this.normalizeHTML(code);
    }

    if (subdir != null) {
      dest = path.join(this.config.get("paths").base, "app", subdir, filename);
    }

    this.dest.write(dest, code);
  }.bind(this));

  this.dest.write("README.md", "");
  this.dest.write(path.join(this.config.get("paths").base, "index.html"),
      this.normalizeHTML(this.src.read("index.html")));
};

/**
 * Generate the `app/app.js` file
 * Manage Templating engine
 */

Generator.prototype.genAppJs = function genAppJs() {
  var self = this;
  var appFile = this.src.read("app/app.js");

  this.dest.write(path.join(this.config.get("paths").base, "app/app.js"), this.normalizeJS(appFile));
};

/**
 * Generate the Packages Managers configurations
 */

Generator.prototype.genPackageManager = function genPackageManager() {
  // Bower
  var bower = this.src.readJSON("bower.json");

  // If handlebars was specified ensure Handlebars is required.
  if (this.config.get("templateEngine") === "handlebars") {
    bower.dependencies.handlebars = "~1.0.0";
  }

  this.dest.write("bower.json", this.normalizeJSON(bower));

  var bowerrc = this.src.readJSON(".bowerrc");
  bowerrc.directory = path.join(this.config.get("paths").base, bowerrc.directory).replace(/\\\\/g, "/");
  this.dest.write(".bowerrc", this.normalizeJSON(bowerrc));
};

/**
 * Generate the Gruntfile
 */

Generator.prototype.genGruntfile = function genGruntfile() {
  var self = this;

  var tree = new Tree( this.src.read("Gruntfile.js") );
  _.each([ "mocha", "jasmine", "qunit" ], function (testFW) {
    if (testFW !== this.config.get("testFramework")) {
      tree.object().passedTo("grunt.initConfig").key("karma").key(testFW).delete();
      tree.toString(); // force tree to refresh
    }
  }, this);

  this.dest.write("Gruntfile.js", this.normalizeJS(tree.toString()));

};

/**
 * Scaffhold the test directory
 */

Generator.prototype.testScaffholding = function testScaffholding() {
  var root = "test/" + this.config.get("testFramework");
  this.src.recurse(root, function( abspath, rootdir, subdir, filename ) {
    var code = grunt.file.read(abspath);
    var dest = path.join(this.config.get("paths").base, root, filename);

    if (abspath.slice(-3) === ".js") {
      code = this.normalizeJS(code);
    }

    if (abspath.slice(-5) === ".html") {
      code = this.normalizeHTML(code);
    }

    if (subdir != null) {
      dest = path.join(this.config.get("paths").base, root, subdir, filename);
    }

    this.dest.write(dest, code);
  }.bind(this));
};

/**
 * Generate git related files
 */

Generator.prototype.generateGit = function generateGit() {
  this.dest.write(".gitignore", "/dist/\n/node_modules/");
};

/**
 * Generate the `package.json` file
 */

Generator.prototype.genPackageJSON = function genPackageJSON() {
  // Set package settings
  this.pkg.name = this._.slugify(this.pkg.name);
  this.pkg.version = "0.1.0";

  this.dest.write("package.json", this.normalizeJSON(this.pkg));
};
<commit_msg>Fix .bowerrc directory path normalization<commit_after>/**
 * BBB `app` generator for Yeoman
 * Scaffhold the project structure
 */

"use strict";
var util = require("util");
var path = require("path");
var _ = require("lodash");
var grunt = require("grunt");
var Tree = require("ast-query");
var InitGenerator = require("../init/index");

/**
 * Module exports
 */

module.exports = Generator;
Generator._name = "bbb:app";

/**
 * BBB Generator constructor
 * Extend the bbb:init generator
 * Launch packages manager once the installation ends
 */

function Generator(args, options, config) {

  // Extend parents generator/class
  InitGenerator.apply(this, arguments);

  // Use BBB fetched via NPM as source root for the app task
  this.sourceRoot(path.join(__dirname, "../../../node_modules/backbone-boilerplate/"));

  // Get source package.json relevant information
  // Get source package.json relevant information
  var bbbPkg = _.pick(this.src.readJSON("package.json"),
      "devDependencies", "peerDependencies", "scripts");

  _.extend(this.pkg, bbbPkg);

  // Launch packages manager once the installation ends
  this.on("end", function () {
    if( options["skip-install"] ) {
      return;
    }

    this.bowerInstall();
    this.npmInstall(undefined, { quiet: true });
  }.bind(this));
}

util.inherits(Generator, InitGenerator);

/**
 * Command prompt questions
 * Note: Directly extend these functions on the generator prototype as Yeoman run every
 * direct prototype attached method (e.g.: `.hasOwnProperty()`)
 */

Generator.prototype.askFor = InitGenerator.prototype.askFor;

/**
 * Copy boilerplate main code
 * all `app/` folder, index.html and favicon
 */

Generator.prototype.app = function app() {
  this.dest.mkdir(path.join(this.config.get("paths").base, "vendor"));

  this.src.recurse("app", function( abspath, rootdir, subdir, filename ) {
    var code = grunt.file.read(abspath);
    var dest = path.join(this.config.get("paths").base, "app", filename);

    // Manage app.js elsewhere
    if (filename === "app.js") {
      return;
    }

    if (abspath.slice(-3) === ".js") {
      code = this.normalizeJS(code);
    }

    if (abspath.slice(-5) === ".html") {
      code = this.normalizeHTML(code);
    }

    if (subdir != null) {
      dest = path.join(this.config.get("paths").base, "app", subdir, filename);
    }

    this.dest.write(dest, code);
  }.bind(this));

  this.dest.write("README.md", "");
  this.dest.write(path.join(this.config.get("paths").base, "index.html"),
      this.normalizeHTML(this.src.read("index.html")));
};

/**
 * Generate the `app/app.js` file
 * Manage Templating engine
 */

Generator.prototype.genAppJs = function genAppJs() {
  var self = this;
  var appFile = this.src.read("app/app.js");

  this.dest.write(path.join(this.config.get("paths").base, "app/app.js"), this.normalizeJS(appFile));
};

/**
 * Generate the Packages Managers configurations
 */

Generator.prototype.genPackageManager = function genPackageManager() {
  // Bower
  var bower = this.src.readJSON("bower.json");

  // If handlebars was specified ensure Handlebars is required.
  if (this.config.get("templateEngine") === "handlebars") {
    bower.dependencies.handlebars = "~1.0.0";
  }

  this.dest.write("bower.json", this.normalizeJSON(bower));

  var bowerrc = this.src.readJSON(".bowerrc");
  bowerrc.directory = path.join(this.config.get("paths").base, bowerrc.directory).replace(/(\\)/g, "/");
  this.dest.write(".bowerrc", this.normalizeJSON(bowerrc));
};

/**
 * Generate the Gruntfile
 */

Generator.prototype.genGruntfile = function genGruntfile() {
  var self = this;

  var tree = new Tree( this.src.read("Gruntfile.js") );
  _.each([ "mocha", "jasmine", "qunit" ], function (testFW) {
    if (testFW !== this.config.get("testFramework")) {
      tree.object().passedTo("grunt.initConfig").key("karma").key(testFW).delete();
      tree.toString(); // force tree to refresh
    }
  }, this);

  this.dest.write("Gruntfile.js", this.normalizeJS(tree.toString()));

};

/**
 * Scaffhold the test directory
 */

Generator.prototype.testScaffholding = function testScaffholding() {
  var root = "test/" + this.config.get("testFramework");
  this.src.recurse(root, function( abspath, rootdir, subdir, filename ) {
    var code = grunt.file.read(abspath);
    var dest = path.join(this.config.get("paths").base, root, filename);

    if (abspath.slice(-3) === ".js") {
      code = this.normalizeJS(code);
    }

    if (abspath.slice(-5) === ".html") {
      code = this.normalizeHTML(code);
    }

    if (subdir != null) {
      dest = path.join(this.config.get("paths").base, root, subdir, filename);
    }

    this.dest.write(dest, code);
  }.bind(this));
};

/**
 * Generate git related files
 */

Generator.prototype.generateGit = function generateGit() {
  this.dest.write(".gitignore", "/dist/\n/node_modules/");
};

/**
 * Generate the `package.json` file
 */

Generator.prototype.genPackageJSON = function genPackageJSON() {
  // Set package settings
  this.pkg.name = this._.slugify(this.pkg.name);
  this.pkg.version = "0.1.0";

  this.dest.write("package.json", this.normalizeJSON(this.pkg));
};
<|endoftext|>


<commit_before>(function(global) {

    global.tk = global.TaskKiller = {

        token: null,

        authorize: function(data) {
            this.perform('GET', 'http://taskkiller.com.ar/authorize', data, function(token) {
                localStorage.setItem("task_token", token);
            });
        },

        resource: function(resource) {
            var res;
            switch(resource.toLowerCase()) {
                case 'project':
                    res = new ProjectResource();
                    break;

                case 'release':
                    res = new ReleaseResource();
                    break;

                case 'column':
                    res = new ColumnResource();
                    break;

                case 'issue':
                    res = new IssueResource();
                    break;

                case 'attachment':
                    res = new AttachmentResource();
                    break;

                case 'member':
                    res = new MemberResource();
                    break;

                default:
                    throw new "Invalid resource"
            }
            return res;
        },

        xhrSetup: {
            headers: {}
        }

    },

    ProjectResource = function() {},
    ReleaseResource = function() {},
    ColumnResource = function() {},
    IssueResource = function() {},
    CommentResource = function() {},
    AttachmentResource = function() {},
    MemberResource = function() {},
    generalSuccess = function(completed, resourceConstructor, data) {
        if(typeof completed == "function") {
            if(data.error) {
                completed(data.error);
            } else {
                var result = [];
                if(data.length) {
                    data.forEach(function(resourceJson) {
                        result.push(new resourceConstructor(resourceJson));
                    });
                } else {
                    result = new resourceConstructor(data);
                }
                completed(null, result);
            }
        }
    },
    generalError = function(completed, xhr, textStatus, errorThrown) {
        typeof completed == "function" && completed(errorThrown == "Internal Server Error" ? errorThrown : (xhr.statusText || xhr.responseText));
    },
    simpleJSONSuccess = function(completed, data) {
        if(typeof completed == "function") {
            if(data.error) {
                completed(data.error);
            } else {
                completed(null, data);
            }
        }
    },
    extend = function(dest, source) {
        for(var k in source)
            if(dest[k] === void 0) dest[k] = source[k];
        return dest;
    },
    Project = function(attrs) {
        extend(this, attrs);
    },
    Release = function(attrs) {
        extend(this, attrs);
    },
    Column = function(attrs) {
        extend(this, attrs);
    },
    Issue = function(attrs) {
        extend(this, attrs);
    },
    Comment = function(attrs) {
        extend(this, attrs);
    },
    Member = function(attrs) {
        extend(this, attrs);
    }

    issueDefaults = {
        description: ''
    },

    http = {
        dataBody: 'POST|PUT|DELETE',
        perform: function(method, url, data, headers, success, error) {
            method = method.toUpperCase();
            if(typeof headers == "function") {
                error = success;
                success = headers;
                headers = {};
            }

            /*$.ajax({
                type: method, url: url, dataType: 'json',
                data: data, headers: headers, success: success, error: error
            });*/
            if(url.indexOf("http") == -1) {
                url = "/api" + url;
            }

            /* GET FIX */
            if(data && method=="GET" && Object.keys(data).length) {
                var new_data = [],
                    key, value,
                    valueLen;
                for(key in data) {
                    value = data[key];
                    valueLen = value.length
                    if(typeof value == "object" && valueLen) {
                        var ek = encodeURIComponent(key)+'[]';
                        for (var i = 0; i < valueLen; i++) new_data.push( ek+'='+encodeURIComponent(value[i]) );
                    } else {
                        new_data.push( encodeURIComponent(key)+'='+encodeURIComponent(value) );
                    }
                };
                url += '?'+new_data.join('&');
            }

            /* XHR BUILD */
            var xhr = new XMLHttpRequest();
            xhr.open(method, url, true);

            if(!("Content-Type" in headers)) {
                xhr.setRequestHeader('Accept', 'application/json');
                xhr.setRequestHeader('Content-Type', 'application/json');
            }

            /* HEADERS SETUP */
            if(tk.token) {
                headers['Authorization'] = "Bearer: " + tk.token;
            }
            var header;
            for(header in tk.xhrSetup.headers) {
                xhr.setRequestHeader(header, tk.xhrSetup.headers[header]);
            }
            for(header in headers) {
                headers[header] !== false && xhr.setRequestHeader(header, headers[header]);
            }

            /* CALLBACKS */
            xhr.onload = function() {
                if(this.status == 200) {
                    if(typeof success == "function") {
                        success.call(this, JSON.parse(this.response));
                    }
                } else {
                    if(typeof error == "function") {
                        error(this, 'error', this.statusText);
                    }
                }
            }

            /* SEND */
            if(http.dataBody.indexOf(method) !=-1) {
                if(!(data instanceof FormData)) {
                    data = JSON.stringify(data);
                }
            } else {
                data = null;
            }
            xhr.send( data );

        },

        get: function(url, data, headers, success, error) {
            this.perform("GET", url, data, headers, success, error);
        },

        post: function(url, data, headers, success, error) {
            this.perform("POST", url, data, headers, success, error);
        },

        put: function(url, data, headers, success, error) {
            this.perform("PUT", url, data, headers, success, error);
        },

        delete: function(url, data, headers, success, error) {
            this.perform("DELETE", url, data, headers, success, error);
        },
    },

    filter = function(filters, callback, url, resourceConstructor) {
        http.get(url, filters, generalSuccess.bind(this, callback, resourceConstructor), generalError.bind(this, callback));
    };

    ProjectResource.prototype.create = function(data, callback) {
        http.post('/projects', data, generalSuccess.bind(this, callback, Project), generalError.bind(this, callback));
    };

    ProjectResource.prototype.load = function(data) {
        return new Project(data);
    };

    ProjectResource.prototype.members = function(projectId, callback) {
        var url = [ '/projects', projectId, 'members' ].join('/');
        http.get(url, {}, simpleJSONSuccess.bind(this, callback), generalError.bind(this, callback));
    };

    ReleaseResource.prototype.filter = function(filters, callback) {
        filter.call(this, filters, callback, '/releases', Release);
    };

    ReleaseResource.prototype.find = function(releaseId, callback) {
        filter.call(this, null, callback, '/releases/'+releaseId, Release);
    };

    ReleaseResource.prototype.create = function(data, callback) {
        http.post('/releases', data, generalSuccess.bind(this, callback, Release), generalError.bind(this, callback));
    };

    ReleaseResource.prototype.load = function(data) {
        return new Release(data);
    };

    ReleaseResource.prototype.columns = function(releaseId, callback) {
        var url = [ '/releases', releaseId, 'columns' ].join('/');
        filter.call(this, null, callback, url, Column);
    };

    ColumnResource.prototype.load = function(data) {
        return new Column(data);
    };

    ColumnResource.prototype.find = function(columnId, callback) {
        filter.call(this, null, callback, '/columns/'+columnId, Column);
    };

    IssueResource.prototype.load = function(data) {
        return new Issue( extend(data, issueDefaults) );
    };

    IssueResource.prototype.find = function(issueId, callback) {
        filter.call(this, null, callback, '/issues/'+issueId, Issue);
    };

    IssueResource.prototype.create = function(data, callback) {
        var url = '/issues';
        http.post(url, data, generalSuccess.bind(this, callback, Issue), generalError.bind(this, callback));
    };

    AttachmentResource.prototype.delete = function(attachmentId, callback) {
        var url = '/attachments/'+attachmentId;
        http.delete(url, {}, simpleJSONSuccess.bind(this, callback), generalError.bind(this, callback));
    };

    Project.prototype.addMember = function(memberId, callback) {
        var url = [ '/projects', this.id, 'members' ].join('/');
        http.post(url, {'user_id':memberId}, generalSuccess.bind(this, callback, Member), generalError.bind(this, callback));
    };

    Release.prototype.createColumn = function(data, callback) {
        var url = [ '/releases', this.id, 'columns' ].join('/');
        http.post(url, data, generalSuccess.bind(this, callback, Column), generalError.bind(this, callback));
    };

    Column.prototype.createIssue = function(data, callback) {
        var url = [ '/columns', this.id, 'issues' ].join('/');
        http.post(url, data, generalSuccess.bind(this, callback, Issue), generalError.bind(this, callback));
    };

    Issue.prototype.moveTo = function(data, callback) {
        var url = [ '/issues', this.id, 'move' ].join('/');
        http.put(url, data, generalSuccess.bind(this, callback, Issue), generalError.bind(this, callback));
    };

    Issue.prototype.update = function(data, callback) {
        var url = [ '/issues', this.id ].join('/');
        for(var k in data) {
            this[k] = data[k];
        }
        http.put(url, this, generalSuccess.bind(this, callback, Issue), generalError.bind(this, callback));
    };

    Issue.prototype.postComment = function(commentText, callback) {
        var url = [ '/issues', this.id, 'comments' ].join('/');
        http.post(url, {text: commentText}, generalSuccess.bind(this, callback, Comment), generalError.bind(this, callback));
    };

    Issue.prototype.attach = function(file, callback) {
        var url = [ '/issues', this.id, 'attachments' ].join('/'),
            data = new FormData();

        var image = $('#input-file')[0].files[0];
        /*data.append('attachment', image);
        $.ajax({
            url: url,
            data: data,
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            },
            cache: false,
            contentType: false,
            processData: false,
            type: 'POST',
            success:function(response) {
                console.log(response);
            }
        });*/

        data.append("attachment", image);

        http.perform("POST", url, data, {'Content-Type': false}, function(response) {
            if(typeof callback == "function") {
                if(this.status == 200) {
                    if(!response.error) {
                        return callback(null, response);
                    }
                }

                callback(response.error);
            }
        });

    };

    Issue.prototype.addMember = function(memberId, callback) {
        var url = [ '/issues', this.id, 'members' ].join('/');
        http.post(url, memberId, generalSuccess.bind(this, callback, Member), generalError.bind(this, callback));
    };

    Issue.prototype.deleteMember = function(memberId, callback) {
        var url = [ '/issues', this.id, 'members' ].join('/');
        http.delete(url, memberId, generalSuccess.bind(this, callback, Issue), generalError.bind(this, callback));
    };

    MemberResource.prototype.find = function(memberId, callback) {
        filter.call(this, null, callback, '/users/'+memberId, Member);
    };

})(window);<commit_msg>authorize<commit_after>(function(global) {

    global.tk = global.TaskKiller = {

        token: null,

        emptyCallback: function(response){console.log(response)},

        authorize: function(data) {
            this.perform('POST', 'http://taskkiller.com.ar/api/authorize', data, function(response) {
                data.error || ( data.error = tk.emptyCallback );
                data.success || ( data.success = tk.emptyCallback );

                if( response.error || response.token == void 0 ) {

                    data.error(response);

                } else {

                    localStorage.setItem("tk_token", response.token);
                    data.success(response.token);

                }
            });
        },

        resource: function(resource) {
            var res;
            switch(resource.toLowerCase()) {
                case 'project':
                    res = new ProjectResource();
                    break;

                case 'release':
                    res = new ReleaseResource();
                    break;

                case 'column':
                    res = new ColumnResource();
                    break;

                case 'issue':
                    res = new IssueResource();
                    break;

                case 'attachment':
                    res = new AttachmentResource();
                    break;

                case 'member':
                    res = new MemberResource();
                    break;

                default:
                    throw new "Invalid resource"
            }
            return res;
        },

        xhrSetup: {
            headers: {}
        }

    },

    ProjectResource = function() {},
    ReleaseResource = function() {},
    ColumnResource = function() {},
    IssueResource = function() {},
    CommentResource = function() {},
    AttachmentResource = function() {},
    MemberResource = function() {},
    generalSuccess = function(completed, resourceConstructor, data) {
        if(typeof completed == "function") {
            if(data.error) {
                completed(data.error);
            } else {
                var result = [];
                if(data.length) {
                    data.forEach(function(resourceJson) {
                        result.push(new resourceConstructor(resourceJson));
                    });
                } else {
                    result = new resourceConstructor(data);
                }
                completed(null, result);
            }
        }
    },
    generalError = function(completed, xhr, textStatus, errorThrown) {
        typeof completed == "function" && completed(errorThrown == "Internal Server Error" ? errorThrown : (xhr.statusText || xhr.responseText));
    },
    simpleJSONSuccess = function(completed, data) {
        if(typeof completed == "function") {
            if(data.error) {
                completed(data.error);
            } else {
                completed(null, data);
            }
        }
    },
    extend = function(dest, source) {
        for(var k in source)
            if(dest[k] === void 0) dest[k] = source[k];
        return dest;
    },
    Project = function(attrs) {
        extend(this, attrs);
    },
    Release = function(attrs) {
        extend(this, attrs);
    },
    Column = function(attrs) {
        extend(this, attrs);
    },
    Issue = function(attrs) {
        extend(this, attrs);
    },
    Comment = function(attrs) {
        extend(this, attrs);
    },
    Member = function(attrs) {
        extend(this, attrs);
    }

    issueDefaults = {
        description: ''
    },

    http = {
        dataBody: 'POST|PUT|DELETE',
        perform: function(method, url, data, headers, success, error) {
            method = method.toUpperCase();
            if(typeof headers == "function") {
                error = success;
                success = headers;
                headers = {};
            }

            /*$.ajax({
                type: method, url: url, dataType: 'json',
                data: data, headers: headers, success: success, error: error
            });*/
            if(url.indexOf("http") == -1) {
                url = "/api" + url;
            }

            /* GET FIX */
            if(data && method=="GET" && Object.keys(data).length) {
                var new_data = [],
                    key, value,
                    valueLen;
                for(key in data) {
                    value = data[key];
                    valueLen = value.length
                    if(typeof value == "object" && valueLen) {
                        var ek = encodeURIComponent(key)+'[]';
                        for (var i = 0; i < valueLen; i++) new_data.push( ek+'='+encodeURIComponent(value[i]) );
                    } else {
                        new_data.push( encodeURIComponent(key)+'='+encodeURIComponent(value) );
                    }
                };
                url += '?'+new_data.join('&');
            }

            /* XHR BUILD */
            var xhr = new XMLHttpRequest();
            xhr.open(method, url, true);

            if(!("Content-Type" in headers)) {
                xhr.setRequestHeader('Accept', 'application/json');
                xhr.setRequestHeader('Content-Type', 'application/json');
            }

            /* HEADERS SETUP */
            if(tk.token) {
                headers['Authorization'] = "Bearer: " + tk.token;
            }
            var header;
            for(header in tk.xhrSetup.headers) {
                xhr.setRequestHeader(header, tk.xhrSetup.headers[header]);
            }
            for(header in headers) {
                headers[header] !== false && xhr.setRequestHeader(header, headers[header]);
            }

            /* CALLBACKS */
            xhr.onload = function() {
                if(this.status == 200) {
                    if(typeof success == "function") {
                        success.call(this, JSON.parse(this.response));
                    }
                } else {
                    if(typeof error == "function") {
                        error(this, 'error', this.statusText);
                    }
                }
            }

            /* SEND */
            if(http.dataBody.indexOf(method) !=-1) {
                if(!(data instanceof FormData)) {
                    data = JSON.stringify(data);
                }
            } else {
                data = null;
            }
            xhr.send( data );

        },

        get: function(url, data, headers, success, error) {
            this.perform("GET", url, data, headers, success, error);
        },

        post: function(url, data, headers, success, error) {
            this.perform("POST", url, data, headers, success, error);
        },

        put: function(url, data, headers, success, error) {
            this.perform("PUT", url, data, headers, success, error);
        },

        delete: function(url, data, headers, success, error) {
            this.perform("DELETE", url, data, headers, success, error);
        },
    },

    filter = function(filters, callback, url, resourceConstructor) {
        http.get(url, filters, generalSuccess.bind(this, callback, resourceConstructor), generalError.bind(this, callback));
    };

    ProjectResource.prototype.create = function(data, callback) {
        http.post('/projects', data, generalSuccess.bind(this, callback, Project), generalError.bind(this, callback));
    };

    ProjectResource.prototype.load = function(data) {
        return new Project(data);
    };

    ProjectResource.prototype.members = function(projectId, callback) {
        var url = [ '/projects', projectId, 'members' ].join('/');
        http.get(url, {}, simpleJSONSuccess.bind(this, callback), generalError.bind(this, callback));
    };

    ReleaseResource.prototype.filter = function(filters, callback) {
        filter.call(this, filters, callback, '/releases', Release);
    };

    ReleaseResource.prototype.find = function(releaseId, callback) {
        filter.call(this, null, callback, '/releases/'+releaseId, Release);
    };

    ReleaseResource.prototype.create = function(data, callback) {
        http.post('/releases', data, generalSuccess.bind(this, callback, Release), generalError.bind(this, callback));
    };

    ReleaseResource.prototype.load = function(data) {
        return new Release(data);
    };

    ReleaseResource.prototype.columns = function(releaseId, callback) {
        var url = [ '/releases', releaseId, 'columns' ].join('/');
        filter.call(this, null, callback, url, Column);
    };

    ColumnResource.prototype.load = function(data) {
        return new Column(data);
    };

    ColumnResource.prototype.find = function(columnId, callback) {
        filter.call(this, null, callback, '/columns/'+columnId, Column);
    };

    IssueResource.prototype.load = function(data) {
        return new Issue( extend(data, issueDefaults) );
    };

    IssueResource.prototype.find = function(issueId, callback) {
        filter.call(this, null, callback, '/issues/'+issueId, Issue);
    };

    IssueResource.prototype.create = function(data, callback) {
        var url = '/issues';
        http.post(url, data, generalSuccess.bind(this, callback, Issue), generalError.bind(this, callback));
    };

    AttachmentResource.prototype.delete = function(attachmentId, callback) {
        var url = '/attachments/'+attachmentId;
        http.delete(url, {}, simpleJSONSuccess.bind(this, callback), generalError.bind(this, callback));
    };

    Project.prototype.addMember = function(memberId, callback) {
        var url = [ '/projects', this.id, 'members' ].join('/');
        http.post(url, {'user_id':memberId}, generalSuccess.bind(this, callback, Member), generalError.bind(this, callback));
    };

    Release.prototype.createColumn = function(data, callback) {
        var url = [ '/releases', this.id, 'columns' ].join('/');
        http.post(url, data, generalSuccess.bind(this, callback, Column), generalError.bind(this, callback));
    };

    Column.prototype.createIssue = function(data, callback) {
        var url = [ '/columns', this.id, 'issues' ].join('/');
        http.post(url, data, generalSuccess.bind(this, callback, Issue), generalError.bind(this, callback));
    };

    Issue.prototype.moveTo = function(data, callback) {
        var url = [ '/issues', this.id, 'move' ].join('/');
        http.put(url, data, generalSuccess.bind(this, callback, Issue), generalError.bind(this, callback));
    };

    Issue.prototype.update = function(data, callback) {
        var url = [ '/issues', this.id ].join('/');
        for(var k in data) {
            this[k] = data[k];
        }
        http.put(url, this, generalSuccess.bind(this, callback, Issue), generalError.bind(this, callback));
    };

    Issue.prototype.postComment = function(commentText, callback) {
        var url = [ '/issues', this.id, 'comments' ].join('/');
        http.post(url, {text: commentText}, generalSuccess.bind(this, callback, Comment), generalError.bind(this, callback));
    };

    Issue.prototype.attach = function(file, callback) {
        var url = [ '/issues', this.id, 'attachments' ].join('/'),
            data = new FormData();

        var image = $('#input-file')[0].files[0];
        /*data.append('attachment', image);
        $.ajax({
            url: url,
            data: data,
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            },
            cache: false,
            contentType: false,
            processData: false,
            type: 'POST',
            success:function(response) {
                console.log(response);
            }
        });*/

        data.append("attachment", image);

        http.perform("POST", url, data, {'Content-Type': false}, function(response) {
            if(typeof callback == "function") {
                if(this.status == 200) {
                    if(!response.error) {
                        return callback(null, response);
                    }
                }

                callback(response.error);
            }
        });

    };

    Issue.prototype.addMember = function(memberId, callback) {
        var url = [ '/issues', this.id, 'members' ].join('/');
        http.post(url, memberId, generalSuccess.bind(this, callback, Member), generalError.bind(this, callback));
    };

    Issue.prototype.deleteMember = function(memberId, callback) {
        var url = [ '/issues', this.id, 'members' ].join('/');
        http.delete(url, memberId, generalSuccess.bind(this, callback, Issue), generalError.bind(this, callback));
    };

    MemberResource.prototype.find = function(memberId, callback) {
        filter.call(this, null, callback, '/users/'+memberId, Member);
    };

})(window);<|endoftext|>


<commit_before>cg.Graph = (function () {

    /**
     * Represent a graph of connected actions.
     * @extends cg.Group
     * @constructor
     */
    var Graph = pandora.class_("Graph", cg.Group, function () {
        cg.Group.call(this, null, this.constructor.typename, new pandora.Vec2(0, 0), new pandora.Vec2(0, 0));

        /**
         * Contains all the types allowed in this codegraph.
         * @type {Array<String>}
         */
        this.types = [];

        /**
         * Contains the model of actions that can be created.
         * @type {Array}
         * @private
         */
        this._models = [];
        Object.defineProperty(this, "models", {
            get: function () { return this._models; }.bind(this)
        });

        /**
         * Contains all connections of the graph.
         * @type {Array}
         * @private
         */
        this._connections = [];
        Object.defineProperty(this, "connections", {
            get: function () { return this._connections; }.bind(this)
        });

        /**
         *
         * @type {Object}
         * @private
         */
        this._registeredGroupIds = {};

        /**
         * Used to generate new ids for groups automatically.
         * @type {number}
         * @private
         */
        this._groupIdOffset = 0;

        /**
         *
         * @type {Object}
         * @private
         */
        this._registeredBlockIds = {};

        /**
         * Used to generate new ids for blocks automatically.
         * @type {number}
         * @private
         */
        this._blockIdOffset = 0;

    });

    /**
     * Return the next ID available for groups in this graph.
     * @returns {Number}
     */
    Graph.prototype.getNextGroupId = function () {
        while (this._registeredGroupIds[this._groupIdOffset] !== undefined) {
            this._groupIdOffset++;
        }
        return this._groupIdOffset;
    };

    /**
     * Return the next ID available for blocks in this graph.
     * @returns {Number}
     */
    Graph.prototype.getNextBlockId = function () {
        while (this._registeredBlockIds[this._blockIdOffset] !== undefined) {
            this._blockIdOffset++;
        }
        return this._blockIdOffset;
    };

    /**
     * Add a model of action.
     * @param model {cg.Model|cg.Variable|cg.Value|cg.Action}
     * @param append {Boolean} defines whether the model should be added at the end or the begin.
     */
    Graph.prototype.addModel = function (model, append) {
        if (append) {
            this._models.push(model);
        } else {
            this._models.unshift(model);
        }
    };

    /**
     * Get a model from its name.
     * @param name {String}
     * @returns {cg.Model}
     */
    Graph.prototype.getModel = function (name) {
        var result = null;
        pandora.forEach(this._models, function (model) {
            if (model.name === name) {
                result = model;
                return true;
            }
        });
        return result;
    };

    /**
     * Remove a model from its name.
     * @param name
     */
    Graph.prototype.deleteModel = function (name) {
        var index = -1;
        pandora.forEach(this._models, function (model, i) {
            if (model.name === name) {
                index = i;
                return true;
            }
        });
        if (index !== -1) {
            this._models.splice(index, 1);
        }
    };

    /**
     * Find models within the graph.
     * @param options {Object} some search options.
     * @option options.modelType {String?} the type of model to search
     * @option options.type {String?} search only model that has the given type in input or output
     * @option options.isInput {Boolean?} whether the type to search is an input or an output
     * @option options.limit {Number?} the maximal number of result
     * @option options.pattern {String} a pattern to match the model name
     * @returns {Array<cg.Model>}
     */
    Graph.prototype.findModels = function (options) {
        var models = [];
        options = options || {};
        options.limit = options.limit || 5;
        options.pattern = options.pattern ? new RegExp("^" + options.pattern, "g") : null;
        var _hasPoint = function (model, options) {
            if (options.isInput === undefined || options.type === undefined) {
                return true;
            }
            var _checkType = function (point) { return point.type === options.type; };
            return options.isInput ? model.inputs.filter(_checkType).length : model.outputs.filter(_checkType).length;
        };
        pandora.forEach(this.models, function (model) {
            if ((options.modelType === undefined || model.type === options.modelType) &&
                (options.pattern === null || model.name.match(options.pattern)) &&
                _hasPoint(model, options)) {
                models.push({name: model.name, data: model});
            }
            if (models.length == options.limit) {
                return true;
            }
        });
        return models;
    };

    /**
     * Add the entity to the parent in this graph.
     * @param entity {cg.Entity}
     * @param parent {cg.Group}
     * @returns {cg.Entity|null} return the entity if successfully added, or null otherwise
     */
    Graph.prototype.addEntity = function (entity, parent) {
        if (parent.graph !== this) {
            this.emit("error", new cg.GraphError("The parent does not belong to this graph.", parent));
        } else if (entity.parent) {
            this.emit("error", new cg.GraphError("This entity already has a parent, maybe you would like to call moveEntity instead", parent));
        } else {
            if (entity instanceof cg.Graph) {
                this.emit("error", new cg.GraphError("Cannot add a parent to a graph", entity));
                return null;
            }
            if (entity instanceof cg.Group) {
                if (this._registeredGroupIds[entity._id]) {
                    this.emit("error", new cg.GraphError("This id is already in use for group {0}", entity._id));
                    return null;
                }
                this._registeredGroupIds[entity._id] = entity;
            } else if (entity instanceof cg.Block) {
                if (this._registeredBlockIds[entity._id]) {
                    this.emit("error", new cg.GraphError("This id is already in use for a block {0}", entity._id));
                    return null;
                }
                this._registeredBlockIds[entity._id] = entity;
            }
            parent._addChild(entity);
            this.emit("entity.add", entity);
            return entity;
        }
        return null;
    };

    /**
     * Change the entity position in the graph by adding it to the given parent.
     * @param entity {cg.Entity}
     * @param newParent {cg.Group}
     * @returns {cg.Entity|null} return the entity if successfully added, or null otherwise
     */
    Graph.prototype.moveEntity = function (entity, newParent) {
        if (newParent.graph !== this) {
            this.emit("error", new cg.GraphError("The new parent does not belong to this graph.", newParent));
            return null;
        } else if (!entity.parent || entity.graph !== this) {
            this.emit("error", new cg.GraphError("This entity does not belong to this graph.", newParent));
        } else {
            newParent._addChild(entity);
            return entity;
        }
        return null;
    };

    /**
     * @param entity {cg.Entity|cg.Group|cg.Block}
     * @param entity
     */
    Graph.prototype.removeEntity = function (entity) {
        if (!entity.parent || entity.graph !== this) {
            this.emit("error", new cg.GraphError("This entity does not belong to this graph.", newParent));
        } else {
            if (entity instanceof cg.Group) {
                delete this._registeredGroupIds[entity._id];
            } else {
                delete this._registeredBlockIds[entity._id];
            }
            entity._remove();
        }
    };

    /**
     * Return all groups in graph.
     * @returns {Array<cg.Group>}
     */
    Graph.prototype.groups = function () {
        var groups = [];
        for (var group in this._registeredGroupIds) {
            if (this._registeredGroupIds.hasOwnProperty(group)) {
                groups.push(this._registeredGroupIds[group]);
            }
        }
        return groups;
    };

    /**
     * Return all blocks in graph.
     * @returns {Array<cg.Block>}
     */
    Graph.prototype.blocks = function () {
        var blocks = [];
        for (var block in this._registeredBlockIds) {
            if (this._registeredBlockIds.hasOwnProperty(block)) {
                blocks.push(this._registeredBlockIds[block]);
            }
        }
        return blocks;
    };

    Graph.prototype.findBlock = function (fn) {
        var result = null;
        pandora.forEach(this._registeredBlockIds, function (block) {
            if (fn(block)) {
                result = block;
                return true;
            }
        });
        return result;
    };

    Graph.prototype.findBlocks = function (fn) {
        var result = [];
        pandora.forEach(this._registeredBlockIds, function (block) {
            if (fn(block)) {
                result.push(block);
            }
        });
        return result;
    };

    /**
     * Return the group by id.
     * @param id
     * @returns {cg.Group|null}
     */
    Graph.prototype.groupById = function (id) {
        return this._registeredGroupIds[id] || null;
    };

    /**
     * Return the block by id.
     * @param id
     * @returns {cg.Block|null}
     */
    Graph.prototype.blockById = function (id) {
        return this._registeredBlockIds[id] || null;
    };

    /**
     * Add the connection object into the graph.
     * @param connection {cg.Connection}
     * @returns {cg.Connection|null} the connection if the add was successful, null otherwise
     */
    Graph.prototype.addConnection = function (connection) {
        var error = false;
        pandora.forEach(this._connections, function (currentConnection) {
            if (currentConnection.equal(connection)) {
                error = true;
                return true;
            }
        });
        if (error) {
            this.emit("error", new cg.GraphError("This connection is already in the graph"));
            return null;
        }
        var graphForInput = connection.inputPoint.block.graph;
        var graphForOutput = connection.outputPoint.block.graph;
        if (graphForInput !== this || graphForOutput !== this) {
            this.emit("error", new cg.GraphError("This connection does not belong to this graph"));
            return null;
        }
        if (!connection.inputPoint.acceptConnection(connection)) {
            this.emit("error", new cg.GraphError("The input point only accepts {0} connection(s)", connection.inputPoint.max));
            return null;
        }
        if (!connection.outputPoint.acceptConnection(connection)) {
            this.emit("error", new cg.GraphError("The output point only accepts {0} connection(s)", connection.outputPoint.max));
            return null;
        }
        if (connection.inputPoint.type !== connection.outputPoint.type) {
            this.emit("error", new cg.GraphError("Cannot create connection between types {0} and {1}",
                connection.inputPoint.type, connection.outputPoint.type));
            return null;
        }
        if (connection.inputPoint.block._id === connection.outputPoint.block._id) {
            this.emit("error", new cg.GraphError("Cannot link a block to itself"));
            return null;
        }
        if (connection.inputPoint.addConnection(connection) && connection.outputPoint.addConnection(connection)) {
            this._connections.push(connection);
            this.emit("connection.add", connection);
            return connection;
        }
        return null;
    };

    /**
     * Remove the connection object from the graph.
     * @param connection {cg.Connection}
     */
    Graph.prototype.removeConnection = function (connection) {
        var foundConnection = this._connections.indexOf(connection);
        if (foundConnection === -1) {
            this.emit("error", new cg.GraphError("This connection was not in this graph"));
            return null;
        }
        if (connection.inputPoint.removeConnection(connection) && connection.outputPoint.removeConnection(connection)) {
            this._connections.splice(foundConnection, 1);
            this.emit("connection.remove", connection);
            connection.emit("remove");
            return connection;
        }
        return null;
    };

    /**
     * You can't remove the graph entity.
     * @protected
     * @override
     */
    Graph.prototype._remove = function () {
        this.emit("error", new cg.GraphError("Cannot remove graph entity.", parent));
    };

    return Graph;

})();<commit_msg>getModel can return null<commit_after>cg.Graph = (function () {

    /**
     * Represent a graph of connected actions.
     * @extends cg.Group
     * @constructor
     */
    var Graph = pandora.class_("Graph", cg.Group, function () {
        cg.Group.call(this, null, this.constructor.typename, new pandora.Vec2(0, 0), new pandora.Vec2(0, 0));

        /**
         * Contains all the types allowed in this codegraph.
         * @type {Array<String>}
         */
        this.types = [];

        /**
         * Contains the model of actions that can be created.
         * @type {Array}
         * @private
         */
        this._models = [];
        Object.defineProperty(this, "models", {
            get: function () { return this._models; }.bind(this)
        });

        /**
         * Contains all connections of the graph.
         * @type {Array}
         * @private
         */
        this._connections = [];
        Object.defineProperty(this, "connections", {
            get: function () { return this._connections; }.bind(this)
        });

        /**
         *
         * @type {Object}
         * @private
         */
        this._registeredGroupIds = {};

        /**
         * Used to generate new ids for groups automatically.
         * @type {number}
         * @private
         */
        this._groupIdOffset = 0;

        /**
         *
         * @type {Object}
         * @private
         */
        this._registeredBlockIds = {};

        /**
         * Used to generate new ids for blocks automatically.
         * @type {number}
         * @private
         */
        this._blockIdOffset = 0;

    });

    /**
     * Return the next ID available for groups in this graph.
     * @returns {Number}
     */
    Graph.prototype.getNextGroupId = function () {
        while (this._registeredGroupIds[this._groupIdOffset] !== undefined) {
            this._groupIdOffset++;
        }
        return this._groupIdOffset;
    };

    /**
     * Return the next ID available for blocks in this graph.
     * @returns {Number}
     */
    Graph.prototype.getNextBlockId = function () {
        while (this._registeredBlockIds[this._blockIdOffset] !== undefined) {
            this._blockIdOffset++;
        }
        return this._blockIdOffset;
    };

    /**
     * Add a model of action.
     * @param model {cg.Model|cg.Variable|cg.Value|cg.Action}
     * @param append {Boolean} defines whether the model should be added at the end or the begin.
     */
    Graph.prototype.addModel = function (model, append) {
        if (append) {
            this._models.push(model);
        } else {
            this._models.unshift(model);
        }
    };

    /**
     * Get a model from its name.
     * @param name {String}
     * @returns {cg.Model|null}
     */
    Graph.prototype.getModel = function (name) {
        var result = null;
        pandora.forEach(this._models, function (model) {
            if (model.name === name) {
                result = model;
                return true;
            }
        });
        return result;
    };

    /**
     * Remove a model from its name.
     * @param name
     */
    Graph.prototype.deleteModel = function (name) {
        var index = -1;
        pandora.forEach(this._models, function (model, i) {
            if (model.name === name) {
                index = i;
                return true;
            }
        });
        if (index !== -1) {
            this._models.splice(index, 1);
        }
    };

    /**
     * Find models within the graph.
     * @param options {Object} some search options.
     * @option options.modelType {String?} the type of model to search
     * @option options.type {String?} search only model that has the given type in input or output
     * @option options.isInput {Boolean?} whether the type to search is an input or an output
     * @option options.limit {Number?} the maximal number of result
     * @option options.pattern {String} a pattern to match the model name
     * @returns {Array<cg.Model>}
     */
    Graph.prototype.findModels = function (options) {
        var models = [];
        options = options || {};
        options.limit = options.limit || 5;
        options.pattern = options.pattern ? new RegExp("^" + options.pattern, "g") : null;
        var _hasPoint = function (model, options) {
            if (options.isInput === undefined || options.type === undefined) {
                return true;
            }
            var _checkType = function (point) { return point.type === options.type; };
            return options.isInput ? model.inputs.filter(_checkType).length : model.outputs.filter(_checkType).length;
        };
        pandora.forEach(this.models, function (model) {
            if ((options.modelType === undefined || model.type === options.modelType) &&
                (options.pattern === null || model.name.match(options.pattern)) &&
                _hasPoint(model, options)) {
                models.push({name: model.name, data: model});
            }
            if (models.length == options.limit) {
                return true;
            }
        });
        return models;
    };

    /**
     * Add the entity to the parent in this graph.
     * @param entity {cg.Entity}
     * @param parent {cg.Group}
     * @returns {cg.Entity|null} return the entity if successfully added, or null otherwise
     */
    Graph.prototype.addEntity = function (entity, parent) {
        if (parent.graph !== this) {
            this.emit("error", new cg.GraphError("The parent does not belong to this graph.", parent));
        } else if (entity.parent) {
            this.emit("error", new cg.GraphError("This entity already has a parent, maybe you would like to call moveEntity instead", parent));
        } else {
            if (entity instanceof cg.Graph) {
                this.emit("error", new cg.GraphError("Cannot add a parent to a graph", entity));
                return null;
            }
            if (entity instanceof cg.Group) {
                if (this._registeredGroupIds[entity._id]) {
                    this.emit("error", new cg.GraphError("This id is already in use for group {0}", entity._id));
                    return null;
                }
                this._registeredGroupIds[entity._id] = entity;
            } else if (entity instanceof cg.Block) {
                if (this._registeredBlockIds[entity._id]) {
                    this.emit("error", new cg.GraphError("This id is already in use for a block {0}", entity._id));
                    return null;
                }
                this._registeredBlockIds[entity._id] = entity;
            }
            parent._addChild(entity);
            this.emit("entity.add", entity);
            return entity;
        }
        return null;
    };

    /**
     * Change the entity position in the graph by adding it to the given parent.
     * @param entity {cg.Entity}
     * @param newParent {cg.Group}
     * @returns {cg.Entity|null} return the entity if successfully added, or null otherwise
     */
    Graph.prototype.moveEntity = function (entity, newParent) {
        if (newParent.graph !== this) {
            this.emit("error", new cg.GraphError("The new parent does not belong to this graph.", newParent));
            return null;
        } else if (!entity.parent || entity.graph !== this) {
            this.emit("error", new cg.GraphError("This entity does not belong to this graph.", newParent));
        } else {
            newParent._addChild(entity);
            return entity;
        }
        return null;
    };

    /**
     * @param entity {cg.Entity|cg.Group|cg.Block}
     * @param entity
     */
    Graph.prototype.removeEntity = function (entity) {
        if (!entity.parent || entity.graph !== this) {
            this.emit("error", new cg.GraphError("This entity does not belong to this graph.", newParent));
        } else {
            if (entity instanceof cg.Group) {
                delete this._registeredGroupIds[entity._id];
            } else {
                delete this._registeredBlockIds[entity._id];
            }
            entity._remove();
        }
    };

    /**
     * Return all groups in graph.
     * @returns {Array<cg.Group>}
     */
    Graph.prototype.groups = function () {
        var groups = [];
        for (var group in this._registeredGroupIds) {
            if (this._registeredGroupIds.hasOwnProperty(group)) {
                groups.push(this._registeredGroupIds[group]);
            }
        }
        return groups;
    };

    /**
     * Return all blocks in graph.
     * @returns {Array<cg.Block>}
     */
    Graph.prototype.blocks = function () {
        var blocks = [];
        for (var block in this._registeredBlockIds) {
            if (this._registeredBlockIds.hasOwnProperty(block)) {
                blocks.push(this._registeredBlockIds[block]);
            }
        }
        return blocks;
    };

    Graph.prototype.findBlock = function (fn) {
        var result = null;
        pandora.forEach(this._registeredBlockIds, function (block) {
            if (fn(block)) {
                result = block;
                return true;
            }
        });
        return result;
    };

    Graph.prototype.findBlocks = function (fn) {
        var result = [];
        pandora.forEach(this._registeredBlockIds, function (block) {
            if (fn(block)) {
                result.push(block);
            }
        });
        return result;
    };

    /**
     * Return the group by id.
     * @param id
     * @returns {cg.Group|null}
     */
    Graph.prototype.groupById = function (id) {
        return this._registeredGroupIds[id] || null;
    };

    /**
     * Return the block by id.
     * @param id
     * @returns {cg.Block|null}
     */
    Graph.prototype.blockById = function (id) {
        return this._registeredBlockIds[id] || null;
    };

    /**
     * Add the connection object into the graph.
     * @param connection {cg.Connection}
     * @returns {cg.Connection|null} the connection if the add was successful, null otherwise
     */
    Graph.prototype.addConnection = function (connection) {
        var error = false;
        pandora.forEach(this._connections, function (currentConnection) {
            if (currentConnection.equal(connection)) {
                error = true;
                return true;
            }
        });
        if (error) {
            this.emit("error", new cg.GraphError("This connection is already in the graph"));
            return null;
        }
        var graphForInput = connection.inputPoint.block.graph;
        var graphForOutput = connection.outputPoint.block.graph;
        if (graphForInput !== this || graphForOutput !== this) {
            this.emit("error", new cg.GraphError("This connection does not belong to this graph"));
            return null;
        }
        if (!connection.inputPoint.acceptConnection(connection)) {
            this.emit("error", new cg.GraphError("The input point only accepts {0} connection(s)", connection.inputPoint.max));
            return null;
        }
        if (!connection.outputPoint.acceptConnection(connection)) {
            this.emit("error", new cg.GraphError("The output point only accepts {0} connection(s)", connection.outputPoint.max));
            return null;
        }
        if (connection.inputPoint.type !== connection.outputPoint.type) {
            this.emit("error", new cg.GraphError("Cannot create connection between types {0} and {1}",
                connection.inputPoint.type, connection.outputPoint.type));
            return null;
        }
        if (connection.inputPoint.block._id === connection.outputPoint.block._id) {
            this.emit("error", new cg.GraphError("Cannot link a block to itself"));
            return null;
        }
        if (connection.inputPoint.addConnection(connection) && connection.outputPoint.addConnection(connection)) {
            this._connections.push(connection);
            this.emit("connection.add", connection);
            return connection;
        }
        return null;
    };

    /**
     * Remove the connection object from the graph.
     * @param connection {cg.Connection}
     */
    Graph.prototype.removeConnection = function (connection) {
        var foundConnection = this._connections.indexOf(connection);
        if (foundConnection === -1) {
            this.emit("error", new cg.GraphError("This connection was not in this graph"));
            return null;
        }
        if (connection.inputPoint.removeConnection(connection) && connection.outputPoint.removeConnection(connection)) {
            this._connections.splice(foundConnection, 1);
            this.emit("connection.remove", connection);
            connection.emit("remove");
            return connection;
        }
        return null;
    };

    /**
     * You can't remove the graph entity.
     * @protected
     * @override
     */
    Graph.prototype._remove = function () {
        this.emit("error", new cg.GraphError("Cannot remove graph entity.", parent));
    };

    return Graph;

})();<|endoftext|>