<commit_before>const neo4jDriver = require('neo4j-driver').v1;
const logger = require('./../../applogger');
const config = require('./../../config');
const graphConsts = require('./../common/graphConstants');

let getPublishAddNode = function(subject, object) {

    logger.debug(subject.nodeName);
    let promise = new Promise(function(resolve, reject) {
        logger.debug("Now proceeding to publish subject: ", subject.nodeName);
        let driver = neo4jDriver.driver(config.NEO4J.neo4jURL,
            neo4jDriver.auth.basic(config.NEO4J.usr, config.NEO4J.pwd), {
                encrypted: false
            }
        );

        let session = driver.session();
        logger.debug("obtained connection with neo4j");

        var predicateWeight = '';
        var subjectDomainname = subject.domainName;
        var subjectNodeType = subject.nodeType;
        var subjectNodeName = subject.nodeName;
        var attributesVar = '';
        for (k in object.attributes) {
            attributesVar = attributesVar + ',' + k + ':"' + object.attributes[k] + '"';
        }

        var attributesVar = '';

        for (k in object.attributes) {
            attributesVar = attributesVar + ',' + k + ':"' + object.attributes[k] + '"';
        }

        let query = '';
        let params = {};

        for (var i = 0; i < object.objects.length; i++) {

            splitArray = object.objects[i].name.split('/');

            var objectDomainname = splitArray[2];
            var objectNodeType = splitArray[4];
            var objectNodeName = splitArray[5];

            for (j = 0; j < object.objects[i].predicates.length; j++) {
                var predicateName = object.objects[i].predicates[j].name;
                var predicateDirection = object.objects[i].predicates[j].direction;

                if (objectNodeType == graphConsts.NODE_TERM && predicateName == graphConsts.REL_INDICATOR_OF) {
                    predicateWeight = '{weight:5}';
                } else if (objectNodeType == graphConsts.NODE_TERM && predicateName == graphConsts.REL_COUNTER_INDICATOR_OF) {
                    predicateWeight = '{weight:-5}';
                }

                if (predicateDirection == 'I') {
                    query = 'merge (s:' + subjectNodeType + '{name:{subjectNodeName}' + attributesVar + '})'
                    query += ' merge(o:' + objectNodeType + '{name:{objectNodeName}})'
                    query += ' merge(o)-[r:' + predicateName + predicateWeight + ']->(s)'
                    query += ' return r'
                } else if (predicateDirection == 'O') {
                    query = 'merge (s:' + subjectNodeType + '{name:{subjectNodeName}' + attributesVar + '})'
                    query += ' merge(o:' + objectNodeType + '{name:{objectNodeName}})'
                    query += ' merge(o)<-[r:' + predicateName + predicateWeight + ']-(s)'
                    query += ' return r'
                }

                params = {
                    subjectNodeName: subjectNodeName,
                    objectNodeName: objectNodeName
                };

                logger.debug(params.subjectNodeName);
                session.run(query, params).then(function(result) {
                        if (result) {
                            logger.debug(result);
                        }
                        session.close();
                        resolve(result);
                    })
                    .catch(function(error) {
                        logger.error("Error in NODE_CONCEPT query: ", error, ' query is: ', query);
                        reject(error);
                    });
            }
        }
    });
    return promise;
};

let deleteObject = function(deleteObj) {
    let subType = deleteObj.subNodeType.toLowerCase(),
        sub = subType.charAt(0),
        objType = deleteObj.objNodeType.toLowerCase(),
        obj = objType.charAt(0);

    let promise = new Promise(function(resolve, reject) {
        logger.debug("Now proceeding to delete " +
            "the Object ", deleteObj.objNodeName);
        let driver = neo4jDriver.driver(config.NEO4J.neo4jURL,
            neo4jDriver.auth.basic(config.NEO4J.usr, config.NEO4J.pwd), {
                encrypted: false
            });
        let session = driver.session();
        logger.debug("Obtained connection with neo4j");
        let query = 'match(d:Domain{name:{domainName}})'
        query += 'match(d)<-[r1]-(' + sub + ':' + deleteObj.subNodeType + '{name:{subNodeName}})'
        query += 'match(' + sub + ')<-[r2:' + deleteObj.predicateName + ']-(' + obj + ':' + deleteObj.objNodeType + '{name:{objNodeName}})'
        query += 'detach delete(r2)';

        let params = {
            domainName: deleteObj.domainName,
            subNodeName: deleteObj.subNodeName,
            objNodeName: deleteObj.objNodeName
        };

        session.run(query, params)
            .then(function(result) {
                if (result) {
                    session.close();
                    resolve(deleteObj.objNodeName);
                }
            })
            .catch(function(err) {
                logger.error("Error in the query: ", err, ' query is: ',
                    query);
                reject(err);
            });
    });
    return promise;
};

let deleteOrphans = function(deleteObj) {
    let nodeType = deleteObj.nodeType.toLowerCase();
    let nodeRef = nodeType.charAt(0);
    let promise = new Promise(function(resolve, reject) {
        logger.info("Now proceeding to delete the orphaned node:",
            deleteObj
        );
        logger.info("nodeRef is",
            nodeRef
        );
        let cypher = require('cypher-stream')(config.NEO4J.neo4jURL, config.NEO4J.usr,
            config.NEO4J.pwd);
        let fs = require('fs');
        let promise = new Promise(function(resolve, reject) {
            logger.debug(subject.nodename);
            let driver = neo4jDriver.driver(config.NEO4J.neo4jURL,
                neo4jDriver.auth.basic(config.NEO4J.usr, config.NEO4J.pwd), {
                    encrypted: false
                });
            let session = driver.session();
            logger.debug("obtained connection with neo4j");
            let query = '';
            let params = {};
            if (deleteObj.cascade == 1) {
                query += 'match (s:' + deleteObj.nodeType + ')<-[r]-(allRelatedNodes)'
                query += 'WHERE s.name = {nodeName}'
                query += 'AND size((allRelatedNodes)--()) = 1 '
                query += 'DETACH DELETE s, allRelatedNodes';
                params = {
                    // nodeType: nodetype,
                    nodeName: deleteObj.nodeName
                };
            } else {
                query += 'match (s:' + deleteObj.nodeType + ')<-[r]-(allRelatedNodes)'
                query += 'WHERE s.name = {nodeName}'
                query += 'detach delete s';
                params = {
                    // nodeType: nodetype,
                    nodeName: deleteObj.nodeName
                };
            }
            logger.debug("Query ", query);
            session.run(query, params).then(function(result) {
                    if (result) {
                        logger.debug(result);
                    }
                    session.close();
                    resolve(result);
                })
                .catch(function(error) {
                    logger.error("Error in query: ", error, ' query is: ', query);
                    reject(error);
                });
        });
        return promise;
    });
};

let getRelations = function(subject) {
    let promise = new Promise(function(resolve, reject) {
        logger.debug(subject.nodename);
        let driver = neo4jDriver.driver(config.NEO4J.neo4jURL,
            neo4jDriver.auth.basic(config.NEO4J.usr, config.NEO4J.pwd), {
                encrypted: false
            });
        let session = driver.session();
        logger.debug("obtained connection with neo4j");
        logger.debug("subject", subject.predicates)
        var subjectDomainname = subject.domainname;
        var subjectNodeType = subject.nodetype;
        var subjectNodeName = subject.nodename;
        var objectNodeType = subject.nodetype1;
        var objectNodeName = subject.nodename1;
        var predicateName = subject.predicates;
        // MATCH (:Person { name: 'Oliver Stone' })-->(movie)
        // RETURN movie.title
        query = 'match (s:' + subjectNodeType + '{name: {subjectNodeName}})<-[r:' + predicateName + ']-(o:' + objectNodeType + '{name:{objectNodeName}})'
        query += ' return r'
        params = {
            subjectNodeName: subjectNodeName,
            objectNodeName: objectNodeName,
            subjectNodeType: subjectNodeType,
            objectNodeType: objectNodeType,
            predicateName: predicateName
        };
        //  logger.debug("subjectNodeName", params.subjectNodeName)
        session.run(query, params).then(function(result) {
                if (result) {
                    logger.debug(result);
                }
                session.close();
                resolve(result);
            })
            .catch(function(error) {
                logger.error("Error in query: ", error, ' query is: ', query);
                reject(error);
            });
    });
    return promise;
};

let getAllRelations = function(subject) {
    let promise = new Promise(function(resolve, reject) {
        logger.debug(subject.nodename);
        let driver = neo4jDriver.driver(config.NEO4J.neo4jURL,
            neo4jDriver.auth.basic(config.NEO4J.usr, config.NEO4J.pwd), {
                encrypted: false
            });
        let session = driver.session();
        var subjectDomainname = subject.domainname;
        var subjectNodeType = subject.nodetype;
        var subjectNodeName = subject.nodename;
        var objectNodeType = subject.nodetype1;
        var objectNodeName = subject.nodename1;

        query = 'match (s:' + subjectNodeType + '{name:{subjectNodeName}})<-[r*]-(o:' + objectNodeType + '{name:{objectNodeName}})'
        query += 'return s, r, o'
        params = {
            subjectNodeType: subjectNodeType,
            subjectNodeName: subjectNodeName,
            objectNodeType: objectNodeType,
            objectNodeName: objectNodeName
        }
        session.run(query, params).then(function(result) {
                if (result) {
                    logger.debug(result);
                }
                session.close();
                resolve(result);
            })
            .catch(function(error) {
                logger.error("Error in deleting the query: ", error, ' query is: ', query);
                reject(error);
            });
    });
    return promise;
};

let getPublishAddNodeCallback = function(subject, object, callback) {
    logger.debug("from the callback : " + subject.nodename);
    getPublishAddNode(subject, object).then(function(nodename) {
        callback(null, nodename);
    }, function(err) {
        callback(err, null);
    });
};

let deleteObjectCallback = function(deleteObj, callback) {
    logger.debug("from the callback : ", deleteObj.objNodeName);
    deleteObject(deleteObj).then(function(result) {
        callback(null, result);
    }, function(err) {
        callback(err, null);
    });
};

let deleteOrphansCallback = function(deleteObj, callback) {
    logger.debug("In the callback ", deleteObj);
    deleteOrphans(deleteObj).then(function(result) {
            callback(null, result);
        },
        function(error) {
            callback(error, null);
        });
};

let getRelationsCallback = function(subject, callback) {
    logger.debug("from the callback : " + subject.nodename);
    getRelations(subject).then(function(nodename) {
        callback(null, nodename);
    }, function(err) {
        callback(err, null);
    });
};

let getAllRelationsCallback = function(subject, callback) {
    logger.debug("from the callback : " + subject.nodename);
    getAllRelations(subject).then(function(nodename) {
        callback(null, nodename);
    }, function(err) {
        callback(err, null);
    });
};

module.exports = {
    getPublishAddNodeCallback: getPublishAddNodeCallback,
    deleteObjectCallback: deleteObjectCallback,
    deleteOrphansCallback: deleteOrphansCallback,
    getRelationsCallback: getRelationsCallback,
    getAllRelationsCallback: getAllRelationsCallback
};
<commit_msg>Update in fetching the predicates<commit_after>const neo4jDriver = require('neo4j-driver').v1;
const logger = require('./../../applogger');
const config = require('./../../config');
const graphConsts = require('./../common/graphConstants');

let getPublishAddNode = function(subject, object) {

    logger.debug(subject.nodeName);
    let promise = new Promise(function(resolve, reject) {
        logger.debug("Now proceeding to publish subject: ", subject.nodeName);
        let driver = neo4jDriver.driver(config.NEO4J.neo4jURL,
            neo4jDriver.auth.basic(config.NEO4J.usr, config.NEO4J.pwd), {
                encrypted: false
            }
        );

        let session = driver.session();
        logger.debug("obtained connection with neo4j");

        var predicateWeight = '';
        var subjectDomainname = subject.domainName;
        var subjectNodeType = subject.nodeType;
        var subjectNodeName = subject.nodeName;
        var attributesVar = '';
        for (k in object.attributes) {
            attributesVar = attributesVar + ',' + k + ':"' + object.attributes[k] + '"';
        }

        var attributesVar = '';

        for (k in object.attributes) {
            attributesVar = attributesVar + ',' + k + ':"' + object.attributes[k] + '"';
        }

        let query = '';
        let params = {};

        for (var i = 0; i < object.objects.length; i++) {

            splitArray = object.objects[i].name.split('/');

            var objectDomainname = splitArray[2];
            var objectNodeType = splitArray[4];
            var objectNodeName = splitArray[5];

            for (j = 0; j < object.objects[i].predicates.length; j++) {
                var predicateName = object.objects[i].predicates[j].name;
                var predicateDirection = object.objects[i].predicates[j].direction;

                if (objectNodeType == graphConsts.NODE_TERM && predicateName == graphConsts.REL_INDICATOR_OF) {
                    predicateWeight = '{weight:5}';
                } else if (objectNodeType == graphConsts.NODE_TERM && predicateName == graphConsts.REL_COUNTER_INDICATOR_OF) {
                    predicateWeight = '{weight:-5}';
                }

                if (predicateDirection == 'I') {
                    query = 'merge (s:' + subjectNodeType + '{name:{subjectNodeName}' + attributesVar + '})'
                    query += ' merge(o:' + objectNodeType + '{name:{objectNodeName}})'
                    query += ' merge(o)-[r:' + predicateName + predicateWeight + ']->(s)'
                    query += ' return r'
                } else if (predicateDirection == 'O') {
                    query = 'merge (s:' + subjectNodeType + '{name:{subjectNodeName}' + attributesVar + '})'
                    query += ' merge(o:' + objectNodeType + '{name:{objectNodeName}})'
                    query += ' merge(o)<-[r:' + predicateName + predicateWeight + ']-(s)'
                    query += ' return r'
                }

                params = {
                    subjectNodeName: subjectNodeName,
                    objectNodeName: objectNodeName
                };

                logger.debug(params.subjectNodeName);
                session.run(query, params).then(function(result) {
                        if (result) {
                            logger.debug(result);
                        }
                        session.close();
                        resolve(result);
                    })
                    .catch(function(error) {
                        logger.error("Error in NODE_CONCEPT query: ", error, ' query is: ', query);
                        reject(error);
                    });
            }
        }
    });
    return promise;
};

let deleteObject = function(deleteObj) {
    let subType = deleteObj.subNodeType.toLowerCase(),
        sub = subType.charAt(0),
        objType = deleteObj.objNodeType.toLowerCase(),
        obj = objType.charAt(0);

    let promise = new Promise(function(resolve, reject) {
        logger.debug("Now proceeding to delete " +
            "the Object ", deleteObj.objNodeName);
        let driver = neo4jDriver.driver(config.NEO4J.neo4jURL,
            neo4jDriver.auth.basic(config.NEO4J.usr, config.NEO4J.pwd), {
                encrypted: false
            });
        let session = driver.session();
        logger.debug("Obtained connection with neo4j");
        let query = 'match(d:Domain{name:{domainName}})'
        query += 'match(d)<-[r1]-(' + sub + ':' + deleteObj.subNodeType + '{name:{subNodeName}})'
        query += 'match(' + sub + ')<-[r2:' + deleteObj.predicateName + ']-(' + obj + ':' + deleteObj.objNodeType + '{name:{objNodeName}})'
        query += 'detach delete(r2)';

        let params = {
            domainName: deleteObj.domainName,
            subNodeName: deleteObj.subNodeName,
            objNodeName: deleteObj.objNodeName
        };

        session.run(query, params)
            .then(function(result) {
                if (result) {
                    session.close();
                    resolve(deleteObj.objNodeName);
                }
            })
            .catch(function(err) {
                logger.error("Error in the query: ", err, ' query is: ',
                    query);
                reject(err);
            });
    });
    return promise;
};

let deleteOrphans = function(deleteObj) {
    let nodeType = deleteObj.nodeType.toLowerCase();
    let nodeRef = nodeType.charAt(0);
    let promise = new Promise(function(resolve, reject) {
        logger.info("Now proceeding to delete the orphaned node:",
            deleteObj
        );
        logger.info("nodeRef is",
            nodeRef
        );
        let cypher = require('cypher-stream')(config.NEO4J.neo4jURL, config.NEO4J.usr,
            config.NEO4J.pwd);
        let fs = require('fs');
        let promise = new Promise(function(resolve, reject) {
            logger.debug(subject.nodename);
            let driver = neo4jDriver.driver(config.NEO4J.neo4jURL,
                neo4jDriver.auth.basic(config.NEO4J.usr, config.NEO4J.pwd), {
                    encrypted: false
                });
            let session = driver.session();
            logger.debug("obtained connection with neo4j");
            let query = '';
            let params = {};
            if (deleteObj.cascade == 1) {
                query += 'match (s:' + deleteObj.nodeType + ')<-[r]-(allRelatedNodes)'
                query += 'WHERE s.name = {nodeName}'
                query += 'AND size((allRelatedNodes)--()) = 1 '
                query += 'DETACH DELETE s, allRelatedNodes';
                params = {
                    // nodeType: nodetype,
                    nodeName: deleteObj.nodeName
                };
            } else {
                query += 'match (s:' + deleteObj.nodeType + ')<-[r]-(allRelatedNodes)'
                query += 'WHERE s.name = {nodeName}'
                query += 'detach delete s';
                params = {
                    // nodeType: nodetype,
                    nodeName: deleteObj.nodeName
                };
            }
            logger.debug("Query ", query);
            session.run(query, params).then(function(result) {
                    if (result) {
                        logger.debug(result);
                    }
                    session.close();
                    resolve(result);
                })
                .catch(function(error) {
                    logger.error("Error in query: ", error, ' query is: ', query);
                    reject(error);
                });
        });
        return promise;
    });
};

let getRelations = function(subject) {
    let promise = new Promise(function(resolve, reject) {
        logger.debug(subject.nodename);
        let driver = neo4jDriver.driver(config.NEO4J.neo4jURL,
            neo4jDriver.auth.basic(config.NEO4J.usr, config.NEO4J.pwd), {
                encrypted: false
            });
        let session = driver.session();
        logger.debug("obtained connection with neo4j");
        logger.debug("subject", subject.predicates)
        var subjectDomainname = subject.domainname;
        var subjectNodeType = subject.nodetype;
        var subjectNodeName = subject.nodename;
        var objectNodeType = subject.nodetype1;
        var objectNodeName = subject.nodename1;
        var predicateName = subject.predicates;
        // MATCH (:Person { name: 'Oliver Stone' })-->(movie)
        // RETURN movie.title
        query = 'match (s:' + subjectNodeType + '{name: {subjectNodeName}})<-[r:' + predicateName + ']-(o:' + objectNodeType + '{name:{objectNodeName}})'
        query += ' return r'
        params = {
            subjectNodeName: subjectNodeName,
            objectNodeName: objectNodeName,
            subjectNodeType: subjectNodeType,
            objectNodeType: objectNodeType,
            predicateName: predicateName
        };
        //  logger.debug("subjectNodeName", params.subjectNodeName)
        session.run(query, params).then(function(result) {
                if (result) {
                    logger.debug(result);
                }
                session.close();
                resolve(result.records[0]._fields[0]['properties']['weight']);
            })
            .catch(function(error) {
                logger.error("Error in query: ", error, ' query is: ', query);
                reject(error);
            });
    });
    return promise;
};

let getAllRelations = function(subject) {
    let promise = new Promise(function(resolve, reject) {
        logger.debug(subject.nodename);
        let driver = neo4jDriver.driver(config.NEO4J.neo4jURL,
            neo4jDriver.auth.basic(config.NEO4J.usr, config.NEO4J.pwd), {
                encrypted: false
            });
        let session = driver.session();
        var subjectDomainname = subject.domainname;
        var subjectNodeType = subject.nodetype;
        var subjectNodeName = subject.nodename;
        var objectNodeType = subject.nodetype1;
        var objectNodeName = subject.nodename1;

        query = 'match (s:' + subjectNodeType + '{name:{subjectNodeName}})<-[r*]-(o:' + objectNodeType + '{name:{objectNodeName}})'
        query += 'return s, r, o'
        params = {
            subjectNodeType: subjectNodeType,
            subjectNodeName: subjectNodeName,
            objectNodeType: objectNodeType,
            objectNodeName: objectNodeName
        }
        session.run(query, params).then(function(result) {
                if (result) {
                    logger.debug(result);
                }
                session.close();
                resolve(result);
            })
            .catch(function(error) {
                logger.error("Error in deleting the query: ", error, ' query is: ', query);
                reject(error);
            });
    });
    return promise;
};

let getPublishAddNodeCallback = function(subject, object, callback) {
    logger.debug("from the callback : " + subject.nodename);
    getPublishAddNode(subject, object).then(function(nodename) {
        callback(null, nodename);
    }, function(err) {
        callback(err, null);
    });
};

let deleteObjectCallback = function(deleteObj, callback) {
    logger.debug("from the callback : ", deleteObj.objNodeName);
    deleteObject(deleteObj).then(function(result) {
        callback(null, result);
    }, function(err) {
        callback(err, null);
    });
};

let deleteOrphansCallback = function(deleteObj, callback) {
    logger.debug("In the callback ", deleteObj);
    deleteOrphans(deleteObj).then(function(result) {
            callback(null, result);
        },
        function(error) {
            callback(error, null);
        });
};

let getRelationsCallback = function(subject, callback) {
    logger.debug("from the callback : " + subject.nodename);
    getRelations(subject).then(function(nodename) {
        callback(null, nodename);
    }, function(err) {
        callback(err, null);
    });
};

let getAllRelationsCallback = function(subject, callback) {
    logger.debug("from the callback : " + subject.nodename);
    getAllRelations(subject).then(function(nodename) {
        callback(null, nodename);
    }, function(err) {
        callback(err, null);
    });
};

module.exports = {
    getPublishAddNodeCallback: getPublishAddNodeCallback,
    deleteObjectCallback: deleteObjectCallback,
    deleteOrphansCallback: deleteOrphansCallback,
    getRelationsCallback: getRelationsCallback,
    getAllRelationsCallback: getAllRelationsCallback
};
<|endoftext|>


<commit_before>
// instead of "about %d hours"
$.timeago.settings.strings.hour = 'an hour';
$.timeago.settings.strings.hours = '%d hours';
$.timeago.settings.localeTitle = true;

/*
var JobMonitor = function () {
  window.socket = this.socket = window.socket || io.connect();
  this.attach(this.socket);
};

JobMonitor.prototype = {
  attach: function (sock) {
    sock.on('start', function (data) {
    });
  }
};
*/

function startJob(url, job_type, $scope) {
  $('.tooltip').hide();

  // Default job type is TEST_AND_DEPLOY
  if (job_type === undefined) {
    job_type = "TEST_AND_DEPLOY";
  }

  var data = {url:url, type:job_type};

  $.ajax("/api/jobs/start", {
    data: data,
    dataType: "json",
    error: function(xhr, ts, e) {
      $('#spinner')
        .removeClass('alert alert-error alert-success alert-info').addClass('alert alert-error')
        .text(xhr.responseText);
    },
    success: function(data, ts, xhr) {
      return;

      gotNewJob(data.job);
      // startProgressMeter(job);
    },
    type: "POST"
  });
};

function gotNewJob(newjob, $scope) {
  var job = null;
  console.log('new job', newjob);

  for (var i=0; i<$scope.jobs.length; i++) {
    if ($scope.jobs[i].repo_url === newjob.repo_url) {
      job = i;
      break;
    }
  }
  if (!job) {
    console.log("can't find job");
  } else {
    newjob.past_duration = $scope.jobs[job].duration;
    $scope.jobs.splice(job, 1);
  }
  newjob.time_elapsed = newjob.past_duration / 20;
  $scope.jobs.push(newjob);
  $scope.$digest();
}

function monitor($scope) {
  window.socket = window.socket || io.connect();
  window.socket.on('new', function (data) {
    gotNewJob(data, $scope);
  }).on('update', function (data) {
    $scope.jobs.forEach(function(job) {
      if (job.id === data.job_id) {
        job.time_elapsed = data.time_elapsed;
      }
    });
    $scope.$digest();
  }).on('done', function (data) {
    var ind = null;
    for (var i=0; i<$scope.jobs.length; i++) {
      if ($scope.jobs[i].repo_url === data.repo_url) {
        ind = i;
        break;
      }
    }
    if (ind !== null) {
      $scope.jobs.splice(ind, 1);
    }
    data.finished_time = new Date(data.finished_timestamp);
    $scope.jobs.push(data);
    $scope.$digest();
  });
}

angular.module('dashboard', [], function ($interpolateProvider) {
  $interpolateProvider.startSymbol('[[');
  $interpolateProvider.endSymbol(']]');
}).directive("toggle", function($compile) {
  return {
    restrict: "A",
    link: function(scope, element, attrs) {
      if (attrs.toggle !== 'tooltip') return;
      setTimeout(function() {
        $(element).tooltip();
      }, 0);
    }
  };
}).directive("time", function($compile) {
  return {
    restrict: "E",
    link: function(scope, element, attrs) {
      var date = new Date(attrs.datetime);
      $(element).tooltip({title: date.toLocaleString()});
      // $(element).text($.timeago(date));
      // setInterval(function () {
        // $(element).text($.timeago(date));
      // }, 60000);
      setTimeout(function () {
        $(element).timeago();
      }, 0);
    }
  };
}).controller('Dashboard', ['$scope', '$element', function ($scope, $element) {
    $scope.jobs = [];
    $scope.loading = true;
    monitor($scope);
    $scope.startDeploy = function (job) {
      startJob(job.repo_url, 'TEST_AND_DEPLOY', $scope);
    };
    $scope.startTest = function (job) {
      startJob(job.repo_url, 'TEST_ONLY', $scope);
    };
    $.ajax('/api/jobs', {
      dataType: 'json',
      success: function (data) {
        $scope.loading = false;
        $scope.jobs = data;
        for (var i=0;i<data.length; i++) {
          if (!data[i].running) {
            data[i].finished_time = new Date(data[i].finished_timestamp);
          }
        }
        $scope.$digest();
        // $('time.timeago').timeago();
        // $('[data-toggle="tooltip"]').tooltip();
      }
    });
  }]);

<commit_msg>bugfixes<commit_after>
// instead of "about %d hours"
$.timeago.settings.strings.hour = 'an hour';
$.timeago.settings.strings.hours = '%d hours';
$.timeago.settings.localeTitle = true;

/*
var JobMonitor = function () {
  window.socket = this.socket = window.socket || io.connect();
  this.attach(this.socket);
};

JobMonitor.prototype = {
  attach: function (sock) {
    sock.on('start', function (data) {
    });
  }
};
*/

function startJob(url, job_type, $scope) {
  $('.tooltip').hide();

  // Default job type is TEST_AND_DEPLOY
  if (job_type === undefined) {
    job_type = "TEST_AND_DEPLOY";
  }

  var data = {url:url, type:job_type};

  $.ajax("/api/jobs/start", {
    data: data,
    dataType: "json",
    error: function(xhr, ts, e) {
      $('#spinner')
        .removeClass('alert alert-error alert-success alert-info').addClass('alert alert-error')
        .text(xhr.responseText);
    },
    success: function(data, ts, xhr) {
      return;

      gotNewJob(data.job);
      // startProgressMeter(job);
    },
    type: "POST"
  });
};

function gotNewJob(newjob, $scope) {
  var job = null;
  console.log('new job', newjob);

  for (var i=0; i<$scope.jobs.length; i++) {
    if ($scope.jobs[i].repo_url === newjob.repo_url) {
      job = i;
      break;
    }
  }
  if (job === null) {
    console.log("can't find job");
  } else {
    newjob.past_duration = $scope.jobs[job].duration;
    $scope.jobs.splice(job, 1);
  }
  newjob.time_elapsed = newjob.past_duration / 20;
  $scope.jobs.push(newjob);
  $scope.$digest();
}

function monitor($scope) {
  window.socket = window.socket || io.connect();
  window.socket.on('new', function (data) {
    gotNewJob(data, $scope);
  }).on('update', function (data) {
    $scope.jobs.forEach(function(job) {
      if (job.id === data.id) {
        job.time_elapsed = data.time_elapsed;
      }
    });
    $scope.$digest();
  }).on('done', function (data) {
    var ind = null;
    for (var i=0; i<$scope.jobs.length; i++) {
      if ($scope.jobs[i].repo_url === data.repo_url) {
        ind = i;
        break;
      }
    }
    if (ind !== null) {
      $scope.jobs.splice(ind, 1);
    }
    data.finished_time = new Date(data.finished_timestamp);
    $scope.jobs.push(data);
    $scope.$digest();
  });
}

angular.module('dashboard', [], function ($interpolateProvider) {
  $interpolateProvider.startSymbol('[[');
  $interpolateProvider.endSymbol(']]');
}).directive("toggle", function($compile) {
  return {
    restrict: "A",
    link: function(scope, element, attrs) {
      if (attrs.toggle !== 'tooltip') return;
      setTimeout(function() {
        $(element).tooltip();
      }, 0);
    }
  };
}).directive("time", function($compile) {
  return {
    restrict: "E",
    link: function(scope, element, attrs) {
      var date = new Date(attrs.datetime);
      $(element).tooltip({title: date.toLocaleString()});
      // $(element).text($.timeago(date));
      // setInterval(function () {
        // $(element).text($.timeago(date));
      // }, 60000);
      setTimeout(function () {
        $(element).timeago();
      }, 0);
    }
  };
}).controller('Dashboard', ['$scope', '$element', function ($scope, $element) {
    $scope.jobs = [];
    $scope.loading = true;
    monitor($scope);
    $scope.startDeploy = function (job) {
      startJob(job.repo_url, 'TEST_AND_DEPLOY', $scope);
    };
    $scope.startTest = function (job) {
      startJob(job.repo_url, 'TEST_ONLY', $scope);
    };
    $.ajax('/api/jobs', {
      dataType: 'json',
      success: function (data) {
        $scope.loading = false;
        $scope.jobs = data;
        for (var i=0;i<data.length; i++) {
          if (!data[i].running) {
            data[i].finished_time = new Date(data[i].finished_timestamp);
          }
        }
        $scope.$digest();
        // $('time.timeago').timeago();
        // $('[data-toggle="tooltip"]').tooltip();
      }
    });
  }]);

<|endoftext|>


<commit_before>const Promise = require('bluebird');

const warpjsUtils = require('@warp-works/warpjs-utils');

const Document = require('./../../../lib/core/first-class/document');

// const debug = require('./debug')('breadcrumbs-by-entity');

module.exports = async (persistence, entity, instance) => {
    const breadcrumbs = await entity.getInstancePath(persistence, instance);

    const domain = entity.getDomain();

    return Promise.map(
        breadcrumbs,
        async (breadcrumb) => {
            const entity = domain.getEntityByInstance(breadcrumb);
            const document = await entity.getInstance(persistence, breadcrumb.id);

            const href = await Document.getPortalUrl(persistence, entity, document);
            return warpjsUtils.createResource(href, breadcrumb);
        }
    );
};
<commit_msg>- Display a page with broken breadcrumb instead of breaking page.<commit_after>const Promise = require('bluebird');

const warpjsUtils = require('@warp-works/warpjs-utils');

const Document = require('./../../../lib/core/first-class/document');

// const debug = require('./debug')('breadcrumbs-by-entity');

module.exports = async (persistence, entity, instance) => {
    const breadcrumbs = await entity.getInstancePath(persistence, instance);

    const domain = entity.getDomain();

    return Promise.map(
        breadcrumbs,
        async (breadcrumb) => {
            try {
                const entity = domain.getEntityByInstance(breadcrumb);
                const document = await entity.getInstance(persistence, breadcrumb.id);

                const href = await Document.getPortalUrl(persistence, entity, document);
                return warpjsUtils.createResource(href, breadcrumb);
            } catch (err) {
                // eslint-disable-next-line no-console
                console.error(`*** Breadcrumb error for breadcrumb=`, breadcrumb);
                // eslint-disable-next-line no-console
                console.error(`*** ERROR ***:`, err);
                return null;
            }
        }
    );
};
<|endoftext|>


<commit_before>(function (window, THREE, Worker) {
  'use strict'

  window.myApp.
  service('videoProjection', function (util) {
    var last_pix // this needs to be refactored

    function CameraIntrinsics (c) {
      return new THREE.Matrix4(
        c.fx, 0, c.cu, 0,
        0, c.fy, c.cv, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
      )
    }

    function create_R_from_l_to_c (cam) {
      var coordinate_change = new THREE.Matrix4(
        0, -1, 0, 0,
        0, 0, -1, 0,
        1, 0, 0, 0,
        0, 0, 0, 1)
      coordinate_change.multiplyMatrices(util.Matrix4FromJSON3x3(cam.R_to_c_from_l_in_camera_frame), coordinate_change)
      return coordinate_change
    }

    function create_T_from_l_to_c (cam) {
      var R_from_l_to_c = create_R_from_l_to_c(cam)
      var trans = cam.displacement_from_l_to_c_in_lidar_frame
      var T = new THREE.Matrix4()
      T.makeTranslation(trans[0], trans[1], trans[2])
      T.multiplyMatrices(R_from_l_to_c, T)
      return T
    }

    function processWorkerMessage (oEvent) {
      var msg = oEvent.data

      var canvasId = msg.canvasId
      var c = document.getElementById(canvasId)
      var ctx = c.getContext('2d')
      var pix = msg.pix
      last_pix = pix
      return
    }

    function computeProjectionMatrix (imu_loc_t, params) {
      var p = params
      var imu_transforms_t = util.Matrix4FromJSON4x4(imu_loc_t)
      var inv_imu_transforms_t = new THREE.Matrix4()
      inv_imu_transforms_t.getInverse(imu_transforms_t)

      var T = new THREE.Matrix4()
      // read this backwards
      T.multiply(p.KK) // camera intrinsics
      T.multiply(p.T_Extrinsics) // camera extrinsics
      T.multiply(p.T_from_l_to_c) // lidar_t -> camera_t
      T.multiply(p.T_from_i_to_l) // imu_t -> lidar_t
      T.multiply(inv_imu_transforms_t) // imu_0 -> imu_t
      T.multiply(p.T_THREE_to_imu_0)// from THREE_JS frame to imu_0
      var M = T.elements

      return M

    }

    function projectPoints (canvasId, data, color_data, imu_loc_t, params) {
      var p = params
      var M = computeProjectionMatrix(imu_loc_t, params)
      p.worker.postMessage({
        data: data.buffer,
        color_data: color_data.buffer,
        M: M.buffer,
        canvasId: canvasId
      })
    }

    function synchronizeState (tracking_clouds, target_state, worker) {
      for (var idx in tracking_clouds) {
        var updateState = false
        if (tracking_clouds[idx] === undefined &&
          target_state[idx] === undefined) {
          continue
        } else if (tracking_clouds[idx] !== undefined &&
          target_state[idx] === undefined) {
          updateState = true
        } else if (tracking_clouds[idx].geometry.uuid !== target_state[idx].uuid ||
          tracking_clouds[idx].geometry.attributes.position.needsUpdate) {
          updateState = true
        }

        if (updateState) {
          // console.log("updating state")
          var uuid = tracking_clouds[idx].geometry.uuid
          var attr = tracking_clouds[idx].geometry.attributes
          var positions = new Float32Array(attr.position.array)
          var colors = new Float32Array(attr.color.array)
          target_state[idx] = {
            uuid: uuid,
            positions: positions,
            colors: colors
          }
          // also update worker state
          if (worker) {
            worker.postMessage({
              cmd: 'update_state',
              idx: idx,
              state: target_state[idx]
            })
          }
        }
      }

      for (var id in target_state) {
        if (tracking_clouds[id] === undefined) {
          delete target_state[id]
          // also update worker state
          if (worker) {
            worker.postMessage({
              cmd: 'delete_state',
              idx: id
            })
          }
        }
      }
    }

    return {
      init: function (calibration_params, camera_idx, clouds) {
        var params = calibration_params
        var cam_idx = camera_idx
        var cam = params.cam[cam_idx]

        var T_imu_0_to_THREE = new THREE.Matrix4(
          0, 1, 0, 0,
          0, 0, 1, 0,
          1, 0, 0, 0,
          0, 0, 0, 1)

        var T_THREE_to_imu_0 = new THREE.Matrix4()
        T_THREE_to_imu_0.getInverse(T_imu_0_to_THREE)
        var T_from_l_to_i = util.Matrix4FromJSON4x4(params.lidar.T_from_l_to_i)
        var T_from_i_to_l = new THREE.Matrix4()
        T_from_i_to_l.getInverse(T_from_l_to_i)

        var KK = CameraIntrinsics(cam)
        var T_from_l_to_c = create_T_from_l_to_c(cam)
        var T_Extrinsics = util.Matrix4FromJSON4x4(cam.E)

        var worker = new Worker('/javascripts/projectionWorker.js')
        worker.onmessage = processWorkerMessage

        return {
          T_imu_0_to_THREE: T_imu_0_to_THREE,
          T_THREE_to_imu_0: T_THREE_to_imu_0,
          T_from_l_to_i: T_from_l_to_i,
          T_from_i_to_l: T_from_i_to_l,
          T_from_l_to_c: T_from_l_to_c,
          T_Extrinsics: T_Extrinsics,
          params: params,
          cam_idx: cam_idx,
          cam: cam,
          KK: KK,
          worker: worker,
          scene_state: {},
          tracking_clouds: clouds
        }
      },
      projectScene: function (canvasId, imu_loc_t, params) {
        var p = params
        synchronizeState(p.tracking_clouds, p.scene_state, p.worker)
        var M = computeProjectionMatrix(imu_loc_t, params)
        p.worker.postMessage({
          cmd: 'project_state',
          M: M.buffer,
          canvasId: canvasId
        })

        var c = document.getElementById(canvasId)
        var ctx = c.getContext('2d')
        for (var idx in last_pix) {
          var px = last_pix[idx][0]
          var py = last_pix[idx][1]
          var r = last_pix[idx][2]
          var g = last_pix[idx][3]
          var b = last_pix[idx][4]
          var a = 255
          ctx.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + (a / 255) + ')'
          ctx.fillRect(px, py, 2, 2)
        }
      },

      projectCloud: function (canvasId, cloud, imu_loc_t, params) {
        var data = cloud.geometry.attributes.position.array
        var color_data = cloud.geometry.attributes.color.array
        projectPoints(canvasId, data, color_data, imu_loc_t, params)
      }
    }
  })
})(window, window.THREE, window.Worker)
<commit_msg>updates lane color in video projection<commit_after>(function (window, THREE, Worker) {
  'use strict'

  window.myApp.
  service('videoProjection', function (util) {
    var last_pix // this needs to be refactored

    function CameraIntrinsics (c) {
      return new THREE.Matrix4(
        c.fx, 0, c.cu, 0,
        0, c.fy, c.cv, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
      )
    }

    function create_R_from_l_to_c (cam) {
      var coordinate_change = new THREE.Matrix4(
        0, -1, 0, 0,
        0, 0, -1, 0,
        1, 0, 0, 0,
        0, 0, 0, 1)
      coordinate_change.multiplyMatrices(util.Matrix4FromJSON3x3(cam.R_to_c_from_l_in_camera_frame), coordinate_change)
      return coordinate_change
    }

    function create_T_from_l_to_c (cam) {
      var R_from_l_to_c = create_R_from_l_to_c(cam)
      var trans = cam.displacement_from_l_to_c_in_lidar_frame
      var T = new THREE.Matrix4()
      T.makeTranslation(trans[0], trans[1], trans[2])
      T.multiplyMatrices(R_from_l_to_c, T)
      return T
    }

    function processWorkerMessage (oEvent) {
      var msg = oEvent.data

      var canvasId = msg.canvasId
      var c = document.getElementById(canvasId)
      var ctx = c.getContext('2d')
      var pix = msg.pix
      last_pix = pix
      return
    }

    function computeProjectionMatrix (imu_loc_t, params) {
      var p = params
      var imu_transforms_t = util.Matrix4FromJSON4x4(imu_loc_t)
      var inv_imu_transforms_t = new THREE.Matrix4()
      inv_imu_transforms_t.getInverse(imu_transforms_t)

      var T = new THREE.Matrix4()
      // read this backwards
      T.multiply(p.KK) // camera intrinsics
      T.multiply(p.T_Extrinsics) // camera extrinsics
      T.multiply(p.T_from_l_to_c) // lidar_t -> camera_t
      T.multiply(p.T_from_i_to_l) // imu_t -> lidar_t
      T.multiply(inv_imu_transforms_t) // imu_0 -> imu_t
      T.multiply(p.T_THREE_to_imu_0)// from THREE_JS frame to imu_0
      var M = T.elements

      return M

    }

    function projectPoints (canvasId, data, color_data, imu_loc_t, params) {
      var p = params
      var M = computeProjectionMatrix(imu_loc_t, params)
      p.worker.postMessage({
        data: data.buffer,
        color_data: color_data.buffer,
        M: M.buffer,
        canvasId: canvasId
      })
    }

    function synchronizeState (tracking_clouds, target_state, worker) {
      for (var idx in tracking_clouds) {
        var updateState = false
        if (tracking_clouds[idx] === undefined &&
          target_state[idx] === undefined) {
          continue
        } else if (tracking_clouds[idx] !== undefined &&
          target_state[idx] === undefined) {
          updateState = true
        } else if (tracking_clouds[idx].geometry.uuid !== target_state[idx].uuid ||
          tracking_clouds[idx].geometry.attributes.position.needsUpdate ||
          tracking_clouds[idx].geometry.attributes.color.needsUpdate) {
          updateState = true
        }

        if (updateState) {
          // console.log("updating state")
          var uuid = tracking_clouds[idx].geometry.uuid
          var attr = tracking_clouds[idx].geometry.attributes
          var positions = new Float32Array(attr.position.array)
          var colors = new Float32Array(attr.color.array)
          target_state[idx] = {
            uuid: uuid,
            positions: positions,
            colors: colors
          }
          // also update worker state
          if (worker) {
            worker.postMessage({
              cmd: 'update_state',
              idx: idx,
              state: target_state[idx]
            })
          }
        }
      }

      for (var id in target_state) {
        if (tracking_clouds[id] === undefined) {
          delete target_state[id]
          // also update worker state
          if (worker) {
            worker.postMessage({
              cmd: 'delete_state',
              idx: id
            })
          }
        }
      }
    }

    return {
      init: function (calibration_params, camera_idx, clouds) {
        var params = calibration_params
        var cam_idx = camera_idx
        var cam = params.cam[cam_idx]

        var T_imu_0_to_THREE = new THREE.Matrix4(
          0, 1, 0, 0,
          0, 0, 1, 0,
          1, 0, 0, 0,
          0, 0, 0, 1)

        var T_THREE_to_imu_0 = new THREE.Matrix4()
        T_THREE_to_imu_0.getInverse(T_imu_0_to_THREE)
        var T_from_l_to_i = util.Matrix4FromJSON4x4(params.lidar.T_from_l_to_i)
        var T_from_i_to_l = new THREE.Matrix4()
        T_from_i_to_l.getInverse(T_from_l_to_i)

        var KK = CameraIntrinsics(cam)
        var T_from_l_to_c = create_T_from_l_to_c(cam)
        var T_Extrinsics = util.Matrix4FromJSON4x4(cam.E)

        var worker = new Worker('/javascripts/projectionWorker.js')
        worker.onmessage = processWorkerMessage

        return {
          T_imu_0_to_THREE: T_imu_0_to_THREE,
          T_THREE_to_imu_0: T_THREE_to_imu_0,
          T_from_l_to_i: T_from_l_to_i,
          T_from_i_to_l: T_from_i_to_l,
          T_from_l_to_c: T_from_l_to_c,
          T_Extrinsics: T_Extrinsics,
          params: params,
          cam_idx: cam_idx,
          cam: cam,
          KK: KK,
          worker: worker,
          scene_state: {},
          tracking_clouds: clouds
        }
      },
      projectScene: function (canvasId, imu_loc_t, params) {
        var p = params
        synchronizeState(p.tracking_clouds, p.scene_state, p.worker)
        var M = computeProjectionMatrix(imu_loc_t, params)
        p.worker.postMessage({
          cmd: 'project_state',
          M: M.buffer,
          canvasId: canvasId
        })

        var c = document.getElementById(canvasId)
        var ctx = c.getContext('2d')
        for (var idx in last_pix) {
          var px = last_pix[idx][0]
          var py = last_pix[idx][1]
          var r = last_pix[idx][2]
          var g = last_pix[idx][3]
          var b = last_pix[idx][4]
          var a = 255
          ctx.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + (a / 255) + ')'
          ctx.fillRect(px, py, 2, 2)
        }
      },

      projectCloud: function (canvasId, cloud, imu_loc_t, params) {
        var data = cloud.geometry.attributes.position.array
        var color_data = cloud.geometry.attributes.color.array
        projectPoints(canvasId, data, color_data, imu_loc_t, params)
      }
    }
  })
})(window, window.THREE, window.Worker)
<|endoftext|>


<commit_before>Werld.Views.Character = function(model) {
  this.model = model;
  this.x = this.model.column * Werld.Config.PIXELS_PER_TILE;
  this.y = this.model.row * Werld.Config.PIXELS_PER_TILE;
  this.destinationX = this.x;
  this.destinationY = this.y;
  this.spriteSheet = new Image();
  this.spriteSheet.src = '/images/sprite_sheets/character.png';
  this.spriteSheet.onload = this.draw.bind(this);
  this.currentFrame = 0;
  this.directionFrame = 0;
  this.movement = {};
  $(this.model).bind('move', this.updateDestination.bind(this));
  $(this.model.messages).bind('add', this.draw.bind(this));
};

Werld.Views.Character.prototype = {
  updateDestination: function() {
    this.destinationX = this.model.destinationColumn * Werld.Config.PIXELS_PER_TILE;
    this.destinationY = this.model.destinationRow * Werld.Config.PIXELS_PER_TILE;
  },
  updateDirectionFrame: function() {
    if (this.movement.directionX === 'left' && this.movement.directionY === 'up') {
      this.directionFrame = 120;
    } else if (this.movement.directionX === 'left' && this.movement.directionY === 'down') {
      this.directionFrame = 0;
    } else if (this.movement.directionX === 'left' && this.movement.directionY === 'none') {
      this.directionFrame = 40;
    } else if (this.movement.directionX === 'right' && this.movement.directionY === 'up') {
      this.directionFrame = 120;
    } else if (this.movement.directionX === 'right' && this.movement.directionY === 'down') {
      this.directionFrame = 0;
    } else if (this.movement.directionX === 'right' && this.movement.directionY === 'none') {
      this.directionFrame = 80;
    } else if (this.movement.directionX === 'none' && this.movement.directionY === 'up') {
      this.directionFrame = 120;
    } else if (this.movement.directionX === 'none' && this.movement.directionY === 'down') {
      this.directionFrame = 0;
    }
  },
  advanceFrame: function() {
    if (this.movement.directionX !== 'none' || this.movement.directionY !== 'none') {
      this.currentFrame = this.currentFrame > 2 ? 0 : (this.currentFrame + 1);
    }
  },
  draw: function() {
    if (this.x > this.destinationX) {
      this.movement.directionX = 'left';
      this.x -= Werld.Config.CHARACTER_MOVEMENT_SPEED;
    } else if (this.x < this.destinationX) {
      this.movement.directionX = 'right';
      this.x += Werld.Config.CHARACTER_MOVEMENT_SPEED;
    } else {
      this.movement.directionX = 'none';
      this.model.column = Math.floor(this.x / Werld.PIXELS_PER_TILE);
    }

    if (this.y > this.destinationY) {
      this.movement.directionY = 'up';
      this.y -= Werld.Config.CHARACTER_MOVEMENT_SPEED;
    } else if (this.y < this.destinationY) {
      this.movement.directionY = 'down';
      this.y += Werld.Config.CHARACTER_MOVEMENT_SPEED;
    } else {
      this.movement.directionY = 'none';
      this.model.row = Math.floor(this.y / Werld.PIXELS_PER_TILE);
    }

    this.updateDirectionFrame();

    Werld.canvas.context.shadowColor = '#3300ff';
    Werld.canvas.context.shadowOffsetX = 1;
    Werld.canvas.context.shadowOffsetY = 1;
    Werld.canvas.context.fillStyle = '#00ccff';
    Werld.canvas.context.font = '20px "PowellAntique" serif';
    Werld.canvas.context.textBaseline = 'top';
    Werld.canvas.context.textAlign = 'center';
    Werld.canvas.context.fillText(this.model.name, this.x + 20, this.y - 30);
    Werld.canvas.context.drawImage(
      this.spriteSheet, this.currentFrame * 40, this.directionFrame, 40, 40,
      this.x, this.y, 40, 40
    );

    Werld.canvas.context.shadowOffsetX = 0;
    Werld.canvas.context.shadowOffsetY = 0;
    Werld.canvas.context.fillStyle = '#cccccc';
    Werld.canvas.context.font = '16px "PowellAntique" serif';
    var y = this.y;
    this.model.messages.forEach(function(message) {
      if (message.content !== '') {
        y -= 20;
        Werld.canvas.context.fillText(message.content, this.x + 20, y - 30);
      }
    });

    this.advanceFrame();
  },
};
<commit_msg>Fix broken messages.<commit_after>Werld.Views.Character = function(model) {
  this.model = model;
  this.x = this.model.column * Werld.Config.PIXELS_PER_TILE;
  this.y = this.model.row * Werld.Config.PIXELS_PER_TILE;
  this.destinationX = this.x;
  this.destinationY = this.y;
  this.spriteSheet = new Image();
  this.spriteSheet.src = '/images/sprite_sheets/character.png';
  this.spriteSheet.onload = this.draw.bind(this);
  this.currentFrame = 0;
  this.directionFrame = 0;
  this.movement = {};
  $(this.model).bind('move', this.updateDestination.bind(this));
  $(this.model.messages).bind('add', this.draw.bind(this));
};

Werld.Views.Character.prototype = {
  updateDestination: function() {
    this.destinationX = this.model.destinationColumn * Werld.Config.PIXELS_PER_TILE;
    this.destinationY = this.model.destinationRow * Werld.Config.PIXELS_PER_TILE;
  },
  updateDirectionFrame: function() {
    if (this.movement.directionX === 'left' && this.movement.directionY === 'up') {
      this.directionFrame = 120;
    } else if (this.movement.directionX === 'left' && this.movement.directionY === 'down') {
      this.directionFrame = 0;
    } else if (this.movement.directionX === 'left' && this.movement.directionY === 'none') {
      this.directionFrame = 40;
    } else if (this.movement.directionX === 'right' && this.movement.directionY === 'up') {
      this.directionFrame = 120;
    } else if (this.movement.directionX === 'right' && this.movement.directionY === 'down') {
      this.directionFrame = 0;
    } else if (this.movement.directionX === 'right' && this.movement.directionY === 'none') {
      this.directionFrame = 80;
    } else if (this.movement.directionX === 'none' && this.movement.directionY === 'up') {
      this.directionFrame = 120;
    } else if (this.movement.directionX === 'none' && this.movement.directionY === 'down') {
      this.directionFrame = 0;
    }
  },
  advanceFrame: function() {
    if (this.movement.directionX !== 'none' || this.movement.directionY !== 'none') {
      this.currentFrame = this.currentFrame > 2 ? 0 : (this.currentFrame + 1);
    }
  },
  draw: function() {
    if (this.x > this.destinationX) {
      this.movement.directionX = 'left';
      this.x -= Werld.Config.CHARACTER_MOVEMENT_SPEED;
    } else if (this.x < this.destinationX) {
      this.movement.directionX = 'right';
      this.x += Werld.Config.CHARACTER_MOVEMENT_SPEED;
    } else {
      this.movement.directionX = 'none';
      this.model.column = Math.floor(this.x / Werld.PIXELS_PER_TILE);
    }

    if (this.y > this.destinationY) {
      this.movement.directionY = 'up';
      this.y -= Werld.Config.CHARACTER_MOVEMENT_SPEED;
    } else if (this.y < this.destinationY) {
      this.movement.directionY = 'down';
      this.y += Werld.Config.CHARACTER_MOVEMENT_SPEED;
    } else {
      this.movement.directionY = 'none';
      this.model.row = Math.floor(this.y / Werld.PIXELS_PER_TILE);
    }

    this.updateDirectionFrame();

    Werld.canvas.context.shadowColor = '#3300ff';
    Werld.canvas.context.shadowOffsetX = 1;
    Werld.canvas.context.shadowOffsetY = 1;
    Werld.canvas.context.fillStyle = '#00ccff';
    Werld.canvas.context.font = '20px "PowellAntique" serif';
    Werld.canvas.context.textBaseline = 'top';
    Werld.canvas.context.textAlign = 'center';
    Werld.canvas.context.fillText(this.model.name, this.x + 20, this.y - 30);
    Werld.canvas.context.drawImage(
      this.spriteSheet,
      this.currentFrame * 40, this.directionFrame, 40, 40,
      this.x, this.y, 40, 40
    );

    Werld.canvas.context.shadowOffsetX = 0;
    Werld.canvas.context.shadowOffsetY = 0;
    Werld.canvas.context.fillStyle = '#cccccc';
    Werld.canvas.context.font = '16px "PowellAntique" serif';
    var x = this.x;
    var y = this.y;
    this.model.messages.forEach(function(message) {
      if (message.content !== '') {
        y -= 20;
        Werld.canvas.context.fillText(message.content, x + 20, y - 30);
      }
    });

    this.advanceFrame();
  },
};
<|endoftext|>


<commit_before>/*global define*/
define([
	'jQuery-2.1.4.min',
	'underscore_1.3.3',
	'backbone_0.9.2',
  'tinymce/tinymce.min',
  '../model/FrontEndWidgetModel.js',
  'text!../../../js/app/templates/editWidget.html'
], function ($, _, Backbone, TinyMCE, FrontEndWidgetModel, EditWidgetTemplate) {
	'use strict';

	var FrontEndWidgetView = Backbone.View.extend({

		tagName:  'div',

    el: '#widgetEditor',

		template: _.template(EditWidgetTemplate),

    // The DOM events specific to an item.
    events: {
      'click #addHTMLBtn': 'addHTML',
      'click #addImgRowBtn': 'addImgRow',
      //'click #addWidget': 'addWidget',
      'change #widgetTitle': 'updateWidget',
      'change #widgetDesc': 'updateWidget',
      'change .widgetText': 'updateWidget'
    },

    initialize: function () {
      this.targetWidget = -1; //Index that points to the currently loaded Widget.
      this.targetImage = -1; //Index that points to the currently selected image within a widget.
    },

    render: function (index) {
      //debugger;

      this.$el.html(this.template);

      if(index != undefined) {
        this.model = global.frontEndWidgetCollection.models[index];

        this.targetWidget = index;
      }

      this.$el.find('#widgetTitle').val(this.model.get('title'));
      this.$el.find('#widgetDesc').val(this.model.get('desc'));

      var htmlArray = this.model.get('contentArray');
      var imgArray = this.model.get('imgUrlArray');

      //BEGIN POPULATION OF HTML ARRAY

      //if the htmlArray is empty.
      if((htmlArray.length == 0) || (htmlArray.length == undefined)) {
        //Do nothing. Leave the default HTML the way it is.
        //debugger;

        this.loadTinyMCE('.widgetText')

      //if the htmlArray is NOT empty.
      } else {

        this.$el.find('#widgetHTML').find('.scaffold').hide();

        //Create a new text area for each htmlArray element.
        for(var i=0; i < htmlArray.length; i++) {
          var tmpEntry = this.$el.find('#widgetHTML').find('.scaffold').clone(); //Clone the scaffolding
          var contentSelector = 'content'+i;

          tmpEntry.removeClass('scaffold'); //Remove the scaffold class
          tmpEntry.addClass(contentSelector);

          tmpEntry.show();

          tmpEntry.find('button').click([i],this.deleteHtml); //Assign a click handler to the delete button

          tmpEntry.prepend('contentArray['+i+']');

          this.$el.find('#widgetHTML').append(tmpEntry); //Add it to the DOM

          //tmpEntry.find('textarea').val(htmlArray[i]); //Populate the text box
          debugger;
          global.tinymce.currentModelIndex = i;
          this.loadTinyMCE('.'+contentSelector); //Load the TinyMCE Editor into this new textarea
          debugger;

          //tinymce.activeEditor.setContent(htmlArray[i]); //Load the content from the array.
        }

        //Remove the scaffolding element
        //this.$el.find('#widgetHTML').find('.scaffold').remove();
        //Hide the scaffolding element
        //this.$el.find('#widgetHTML').find('.scaffold').hide();
      }
      //END POPULATION OF HTML ARRAY

      //BEGIN POPULATION OF IMAGE ARRAY
      if((imgArray.length == 0) || (imgArray.length == undefined)) {
        //Do nothing. Leave the default image layout the way it is.
        //debugger;
      } else {

        //Initialize
        var colIndex = 0;
        var tmpRow = this.$el.find('#widgetImages').find('.scaffold').clone();
        tmpRow.removeClass('scaffold');

        //Loop through all the images
        for(var i=0; i < imgArray.length; i++) {
          var imgSelector = '.img'+colIndex;

          var thisImg = tmpRow.find(imgSelector);

          thisImg.find('button').click([i], this.deleteImg); //Assign a click handler to the delete button.

          thisImg.prepend('imgUrlArray['+i+']');

          thisImg.find('img').attr('onclick', ''); //Remove the default click handler.
          thisImg.find('img').click([i], this.swapImg); //Assign a click handler to the image to swap out the image with a new one.
          thisImg.find('img').attr('src', imgArray[i]); //Swap out the image with the one assigned to the widget.

          //Manage the column index
          colIndex++;
          if(colIndex > 2) {
            colIndex = 0;

            this.$el.find('#widgetImages').prepend(tmpRow);
            var tmpRow = this.$el.find('#widgetImages').find('.scaffold').clone();
            //tmpRow.find('.label').remove(); //Remove the label.
            tmpRow.removeClass('scaffold');

            //Corner case: if colIndex > 2 AND this is the last entry in imgArray
            if(i == imgArray.length-1) {
              this.$el.find('#widgetImages').find('.scaffold').hide();
              return this;
            }
          }
        }

        //this.$el.find('#widgetImages').find('.scaffold').remove();
        this.$el.find('#widgetImages').prepend(tmpRow);

        this.$el.find('#widgetImages').find('.scaffold').hide();
      }
      //END POPULATION OF IMAGE ARRAY

			return this;
		},

    //This function is called when the user clicks on the delete button assigned to an HTML array
    //element. It's purpose is to remove the array entry from the model.
    deleteHtml: function(event) {
      //debugger;

      //Get the contentArray from the model.
      //var this.model = global.frontEndWidgetCollection.models[global.editWidgetView.targetWidget];
      var thisModel = global.editWidgetView.model;
      var contentArray = thisModel.get('contentArray');

      //Create a handle for the parent

      var textDiv = $(event.target).parent();
      //Fixes bug where user clicks on fa icon instead of button.
      var textDivClass = textDiv.attr('class');
      if(textDivClass.indexOf('btn') != -1)
        textDiv = textDiv.parent();

      var isContent0 = (textDiv.attr('class').indexOf('content0') != -1);

      if(isContent0) {
        textDiv.find('textarea').val(''); //Clear the text area

        var contentArrayNotEmpty = ((contentArray[0] != "") && (contentArray[0] != undefined))

        //Delete contentArray element 0 if it exists
        if(contentArrayNotEmpty) {
          contentArray.splice(0,1);
          thisModel.set('contentArray', contentArray);

          thisModel.refreshWidget = true;
          thisModel.save();
        }
      } else {

        //Find out what contentArray element this text box is associated with
        var classIndex = textDiv.attr('class').indexOf('content');
        //I might consider adding error handling code here to test. if(classIndex == -1) error
        var contentClass = textDiv.attr('class').slice(classIndex);
        var contentIndex = Number(contentClass.slice(7));

        //Delete that element from the contentArray (if it exists)
        contentArray.splice(contentIndex,1);
        thisModel.set('contentArray', contentArray);

        //Rerender the UI
        thisModel.refreshWidget = true;
        thisModel.save();
      }

    },

    //This function is called when the user clicks on the delete button assigned to the image.
    //It's purpose is to remove the image from the current front end widget.
    deleteImg: function(index) {
      //debugger;

      //If index is a click event object, then retrieve the data passed in.
      if(typeof(index) == "object")
        index = index.data[0];

      var thisModel = global.editWidgetView.model;

      var r = confirm("Are you sure you want to delete this image?");
      if (r == true) {
        var imgArray = thisModel.get('imgUrlArray');
        imgArray.splice(index,1);
        thisModel.set('imgUrlArray', imgArray);
        thisModel.refreshWidget = true;
        thisModel.save();
      }
    },

    swapImg: function(index) {
      //debugger;

      //If index is a click event object, then retrieve the data passed in.
      if(typeof(index) == "object") {
        index = index.data[0];
        global.editWidgetView.targetImage = index;
      }

      //Modal has exited and returns the URL to a selected image
      if(typeof(index) == "string") {
        var imgArray = this.model.get('imgUrlArray');

        //An empty image was selected. A new image needs to be pushed into the array.
        if(this.targetImage == -1) {
          imgArray.push(index);

        //An existing image was clicked and the selected image needs to replace it.
        } else {
          imgArray[this.targetImage] = index;
        }

        this.model.set('imgUrlArray', imgArray);
        this.model.refreshWidget = true;
        this.model.save();

        return;
      }

      if(index == -1) {
        //console.log('Empty image was clicked');
        global.editWidgetView.targetImage = -1;
      }

      global.modalView.browseImageLibrary();

    },

    //This function is called when the user clicks on the 'Add HTML' button.
    //This function adds a new textarea element to the DOM for additional content.
    addHTML: function() {
      //debugger;

      var contentArray = this.model.get('contentArray');
      var contentIndex = contentArray.length;

      var tmpEntry = this.$el.find('#widgetHTML').find('.scaffold').clone(); //Clone the scaffolding
      tmpEntry.removeClass('scaffold'); //Remove the scaffold class
      tmpEntry.addClass('content'+contentIndex);
      tmpEntry.find('button').click([contentIndex],this.deleteHtml); //Assign a click handler to the delete button
      this.$el.find('#widgetHTML').append(tmpEntry);
      tmpEntry.show();
    },

    //This function is called when the suer clicks on the 'Add Image Row' button.
    addImgRow: function() {
      //debugger;

      var tmpRow = this.$el.find('#widgetImages').find('.scaffold').clone();
      tmpRow.removeClass('scaffold');
      this.$el.find('#widgetImages').prepend(tmpRow);
      tmpRow.show();
    },

    //This function gets called anytime any of the input fields are changed.
    //The purpose is to save data in an event-driven way and then sync those changes with the server.
    updateWidget: function(event) {
      debugger;
      //var thisModel = global.frontEndWidgetCollection.models[global.editWidgetView.targetWidget];

      this.model.set('title', this.$el.find('#widgetTitle').val());
      this.model.set('desc', this.$el.find('#widgetDesc').val());

      // BEGIN SAVING CONTENT ARRAY
      var contentArray = this.model.get('contentArray');

      var widgetTextElems = this.$el.find('.widgetText');
      var widgetTextDivs = widgetTextElems.parent();
      for(var i=0; i < widgetTextDivs.length; i++) {
        var thisElem = $(widgetTextDivs[i]);
        var thisClass = thisElem.attr('class');

        //Skip the scaffold element if there are other entries.
        if(thisElem.hasClass('scaffold')) {
          if(widgetTextDivs.length != 1) {
            continue;
          //If this is the only textarea, then save the content and break out of the loop.
          } else {

            debugger;
            //var content = thisElem.find('textarea').val();
            var content = tinymce.activeEditor.getContent();

            contentArray.push(content);

            break;
          }
        }

        //Get the contentArray index this textarray element represents
        var classIndex = $(widgetTextDivs[i]).attr('class').indexOf('content');
        //I might consider adding error handling code here to test. if(classIndex == -1) error
        var contentClass = $(widgetTextDivs[i]).attr('class').slice(classIndex);
        var contentIndex = Number(contentClass.slice(7));

        //var content = thisElem.find('textarea').val();
        var content = tinymce.activeEditor.getContent();

        if(contentIndex >= contentArray.length) {
          contentArray.push(content);
        } else {
          contentArray[contentIndex] = content;
        }

      }

      this.model.set('contentArray', contentArray);

      global.frontEndWidgetCollection.refreshView = true;
      this.model.refreshWidget = true;
      this.model.save();
      // END SAVING CONTENT ARRAY

    },

    //This function loads the TinyMCE editor into a textarea element with the given jQuery element ID.
    //e.g.: elemId = "#myDiv"; elemId = ".classSelector"
    loadTinyMCE: function(elemId) {
      debugger;

      try {

        //if( tinymce.editors.length == 0 ) {
        if( (global.tinymce.initialized == false) || (global.tinymce.currentView != "frontendwidgets") ) {

          //Fix corner case where the tinyMCE needs to be removed in order to get the init event to fire.
          if((global.tinymce.currentView != "frontendwidgets")) {
            if((global.tinymce.initialized == true)) {
              //debugger;
              tinymce.remove();
              global.tinymce.initialized = false;
            }
          }

          log.push('Initializing TinyMCE editor...')

          //Rendering the template destroys the existing TinyMCE editor. I only want to render the template if the TinyMCE editor
          //hasn't been created yet.
          //this.$el.html(this.template);
          //render?
          debugger;

          tinymce.init({
            selector: elemId,
            //menubar: 'edit view format insert',
            menubar: false,
            toolbar: 'bold, italic, underline, strikethrough, alignleft, aligncenter, alignright, alignjustify, bullist, numlist, outdent, indent, removeformat, subscript, superscript, link, formatselect, fontselect, image_gallery, file_link, code',
            plugins: 'code, image_gallery, link, file_link',
            extended_valid_elements: "a[class|name|href|target|title|onclick|rel|id|download],button[class|name|href|target|title|onclick|rel|id],script[type|src],iframe[src|style|width|height|scrolling|marginwidth|marginheight|frameborder|allowfullscreen],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],$elements",
            relative_urls: false,
            convert_urls: false,
            remove_script_host: false,
            browser_spellcheck: true,
            image_caption: true,

            //The setup function runs when the TinyMCE editor has finished loading. It's kind of like the document.ready() function.
            setup: function (ed) {

              //This code runs with the TinyMCE editor is initialized
              ed.on('init', function(args) {
                debugger;

                global.tinymce.initialized = true;
                global.tinymce.currentView = 'frontendwidgets';
                log.push('TinyMCE editor initialized.')

                //User clicked on existing page and wants to edit it.
                if( global.tinymce.currentModelIndex != null ) {
                  //global.pagesAddNewView.loadPage(global.tinymce.currentModelIndex);
                  tinymce.activeEditor.setContent(global.editWidgetView.model.attributes.contentArray[global.tinymce.currentModelIndex]);
                  global.tinymce.currentModelIndex = null; //Clear to signal that this request has been processed.
                }
                //User clicked on Add New link in left menu and wants to create a new page.
                //} else {
                //  global.pagesAddNewView.newPage();
                //}
              });

              //This function gets called when the user clicks out of the TinyMCE editor
              ed.on('blur', function(event) {
                debugger;
                global.editWidgetView.updateWidget(event);
              });
            },

          });
        //If the TinyMCE editor has already been loaded...
        } else {

          //User clicked the 'Add HTML' button?
          debugger;

          tinymce.remove();
          global.tinymce.initialized = false;
          this.loadTinyMCE(elemId);

          //User clicked on existing page and wants to edit it.
          //if( global.tinymce.currentModelIndex != null ) {
          //  global.pagesAddNewView.loadPage(global.tinymce.currentModelIndex);
          //  global.tinymce.currentModelIndex = null; //Clear to signal that this request has been processed.

          //User clicked on Add New link in left menu and wants to create a new page.
          //} else {
          //  global.pagesAddNewView.newPage();
          //}
        }

      } catch(err) {
        console.error('Error while trying to render tinyMCE editor in Front End Widgets View. Error message: ');
        console.error(err.message);

        log.push('Error while trying to render inyMCE editor in Front End Widgets View. Error message: ');
        log.push(err.message);
        sendLog();
      }
    }

	});

	return FrontEndWidgetView;
});<commit_msg>Developing the combintaion of TinyMCE and the Front End Widget View.<commit_after>/*global define*/
define([
	'jQuery-2.1.4.min',
	'underscore_1.3.3',
	'backbone_0.9.2',
  'tinymce/tinymce.min',
  '../model/FrontEndWidgetModel.js',
  'text!../../../js/app/templates/editWidget.html'
], function ($, _, Backbone, TinyMCE, FrontEndWidgetModel, EditWidgetTemplate) {
	'use strict';

	var FrontEndWidgetView = Backbone.View.extend({

		tagName:  'div',

    el: '#widgetEditor',

		template: _.template(EditWidgetTemplate),

    // The DOM events specific to an item.
    events: {
      'click #addHTMLBtn': 'addHTML',
      'click #addImgRowBtn': 'addImgRow',
      //'click #addWidget': 'addWidget',
      'change #widgetTitle': 'updateWidget',
      'change #widgetDesc': 'updateWidget',
      'change .widgetText': 'updateWidget'
    },

    initialize: function () {
      this.targetWidget = -1; //Index that points to the currently loaded Widget.
      this.targetImage = -1; //Index that points to the currently selected image within a widget.
    },

    render: function (index) {
      //debugger;

      this.$el.html(this.template);

      if(index != undefined) {
        this.model = global.frontEndWidgetCollection.models[index];

        this.targetWidget = index;
      }

      this.$el.find('#widgetTitle').val(this.model.get('title'));
      this.$el.find('#widgetDesc').val(this.model.get('desc'));

      var htmlArray = this.model.get('contentArray');
      var imgArray = this.model.get('imgUrlArray');

      //BEGIN POPULATION OF HTML ARRAY

      //if the htmlArray is empty.
      if((htmlArray.length == 0) || (htmlArray.length == undefined)) {
        //Do nothing. Leave the default HTML the way it is.
        //debugger;

        this.loadTinyMCE('.widgetText')

      //if the htmlArray is NOT empty.
      } else {

        this.$el.find('#widgetHTML').find('.scaffold').hide();

        //Create a new text area for each htmlArray element.
        for(var i=0; i < htmlArray.length; i++) {
          var tmpEntry = this.$el.find('#widgetHTML').find('.scaffold').clone(); //Clone the scaffolding
          var contentSelector = 'content'+i;

          tmpEntry.removeClass('scaffold'); //Remove the scaffold class
          tmpEntry.addClass(contentSelector);

          //Tag the <textarea> element with a unique class.
          tmpEntry.find('.widgetText').addClass(contentSelector+'Text');
          tmpEntry.find('.widgetText').removeClass('.widgetText');

          tmpEntry.show();

          tmpEntry.find('button').click([i],this.deleteHtml); //Assign a click handler to the delete button

          tmpEntry.prepend('contentArray['+i+']');

          this.$el.find('#widgetHTML').append(tmpEntry); //Add it to the DOM

          //tmpEntry.find('textarea').val(htmlArray[i]); //Populate the text box
          debugger;
          global.tinymce.currentModelIndex = i;
          this.loadTinyMCE('.'+contentSelector+'Text'); //Load the TinyMCE Editor into this new textarea
          debugger;

          //tinymce.activeEditor.setContent(htmlArray[i]); //Load the content from the array.
        }

        //Remove the scaffolding element
        //this.$el.find('#widgetHTML').find('.scaffold').remove();
        //Hide the scaffolding element
        //this.$el.find('#widgetHTML').find('.scaffold').hide();
      }
      //END POPULATION OF HTML ARRAY

      //BEGIN POPULATION OF IMAGE ARRAY
      if((imgArray.length == 0) || (imgArray.length == undefined)) {
        //Do nothing. Leave the default image layout the way it is.
        //debugger;
      } else {

        //Initialize
        var colIndex = 0;
        var tmpRow = this.$el.find('#widgetImages').find('.scaffold').clone();
        tmpRow.removeClass('scaffold');

        //Loop through all the images
        for(var i=0; i < imgArray.length; i++) {
          var imgSelector = '.img'+colIndex;

          var thisImg = tmpRow.find(imgSelector);

          thisImg.find('button').click([i], this.deleteImg); //Assign a click handler to the delete button.

          thisImg.prepend('imgUrlArray['+i+']');

          thisImg.find('img').attr('onclick', ''); //Remove the default click handler.
          thisImg.find('img').click([i], this.swapImg); //Assign a click handler to the image to swap out the image with a new one.
          thisImg.find('img').attr('src', imgArray[i]); //Swap out the image with the one assigned to the widget.

          //Manage the column index
          colIndex++;
          if(colIndex > 2) {
            colIndex = 0;

            this.$el.find('#widgetImages').prepend(tmpRow);
            var tmpRow = this.$el.find('#widgetImages').find('.scaffold').clone();
            //tmpRow.find('.label').remove(); //Remove the label.
            tmpRow.removeClass('scaffold');

            //Corner case: if colIndex > 2 AND this is the last entry in imgArray
            if(i == imgArray.length-1) {
              this.$el.find('#widgetImages').find('.scaffold').hide();
              return this;
            }
          }
        }

        //this.$el.find('#widgetImages').find('.scaffold').remove();
        this.$el.find('#widgetImages').prepend(tmpRow);

        this.$el.find('#widgetImages').find('.scaffold').hide();
      }
      //END POPULATION OF IMAGE ARRAY

			return this;
		},

    //This function is called when the user clicks on the delete button assigned to an HTML array
    //element. It's purpose is to remove the array entry from the model.
    deleteHtml: function(event) {
      //debugger;

      //Get the contentArray from the model.
      //var this.model = global.frontEndWidgetCollection.models[global.editWidgetView.targetWidget];
      var thisModel = global.editWidgetView.model;
      var contentArray = thisModel.get('contentArray');

      //Create a handle for the parent

      var textDiv = $(event.target).parent();
      //Fixes bug where user clicks on fa icon instead of button.
      var textDivClass = textDiv.attr('class');
      if(textDivClass.indexOf('btn') != -1)
        textDiv = textDiv.parent();

      var isContent0 = (textDiv.attr('class').indexOf('content0') != -1);

      if(isContent0) {
        textDiv.find('textarea').val(''); //Clear the text area

        var contentArrayNotEmpty = ((contentArray[0] != "") && (contentArray[0] != undefined))

        //Delete contentArray element 0 if it exists
        if(contentArrayNotEmpty) {
          contentArray.splice(0,1);
          thisModel.set('contentArray', contentArray);

          thisModel.refreshWidget = true;
          thisModel.save();
        }
      } else {

        //Find out what contentArray element this text box is associated with
        var classIndex = textDiv.attr('class').indexOf('content');
        //I might consider adding error handling code here to test. if(classIndex == -1) error
        var contentClass = textDiv.attr('class').slice(classIndex);
        var contentIndex = Number(contentClass.slice(7));

        //Delete that element from the contentArray (if it exists)
        contentArray.splice(contentIndex,1);
        thisModel.set('contentArray', contentArray);

        //Rerender the UI
        thisModel.refreshWidget = true;
        thisModel.save();
      }

    },

    //This function is called when the user clicks on the delete button assigned to the image.
    //It's purpose is to remove the image from the current front end widget.
    deleteImg: function(index) {
      //debugger;

      //If index is a click event object, then retrieve the data passed in.
      if(typeof(index) == "object")
        index = index.data[0];

      var thisModel = global.editWidgetView.model;

      var r = confirm("Are you sure you want to delete this image?");
      if (r == true) {
        var imgArray = thisModel.get('imgUrlArray');
        imgArray.splice(index,1);
        thisModel.set('imgUrlArray', imgArray);
        thisModel.refreshWidget = true;
        thisModel.save();
      }
    },

    swapImg: function(index) {
      //debugger;

      //If index is a click event object, then retrieve the data passed in.
      if(typeof(index) == "object") {
        index = index.data[0];
        global.editWidgetView.targetImage = index;
      }

      //Modal has exited and returns the URL to a selected image
      if(typeof(index) == "string") {
        var imgArray = this.model.get('imgUrlArray');

        //An empty image was selected. A new image needs to be pushed into the array.
        if(this.targetImage == -1) {
          imgArray.push(index);

        //An existing image was clicked and the selected image needs to replace it.
        } else {
          imgArray[this.targetImage] = index;
        }

        this.model.set('imgUrlArray', imgArray);
        this.model.refreshWidget = true;
        this.model.save();

        return;
      }

      if(index == -1) {
        //console.log('Empty image was clicked');
        global.editWidgetView.targetImage = -1;
      }

      global.modalView.browseImageLibrary();

    },

    //This function is called when the user clicks on the 'Add HTML' button.
    //This function adds a new textarea element to the DOM for additional content.
    addHTML: function() {
      //debugger;

      var contentArray = this.model.get('contentArray');
      var contentIndex = contentArray.length;

      var tmpEntry = this.$el.find('#widgetHTML').find('.scaffold').clone(); //Clone the scaffolding
      tmpEntry.removeClass('scaffold'); //Remove the scaffold class
      tmpEntry.addClass('content'+contentIndex);
      tmpEntry.find('button').click([contentIndex],this.deleteHtml); //Assign a click handler to the delete button
      this.$el.find('#widgetHTML').append(tmpEntry);
      tmpEntry.show();
    },

    //This function is called when the suer clicks on the 'Add Image Row' button.
    addImgRow: function() {
      //debugger;

      var tmpRow = this.$el.find('#widgetImages').find('.scaffold').clone();
      tmpRow.removeClass('scaffold');
      this.$el.find('#widgetImages').prepend(tmpRow);
      tmpRow.show();
    },

    //This function gets called anytime any of the input fields are changed.
    //The purpose is to save data in an event-driven way and then sync those changes with the server.
    updateWidget: function(event) {
      debugger;
      //var thisModel = global.frontEndWidgetCollection.models[global.editWidgetView.targetWidget];

      this.model.set('title', this.$el.find('#widgetTitle').val());
      this.model.set('desc', this.$el.find('#widgetDesc').val());

      // BEGIN SAVING CONTENT ARRAY
      var contentArray = this.model.get('contentArray');

      var widgetTextElems = this.$el.find('.widgetText');
      var widgetTextDivs = widgetTextElems.parent();
      for(var i=0; i < widgetTextDivs.length; i++) {
        var thisElem = $(widgetTextDivs[i]);
        var thisClass = thisElem.attr('class');

        //Skip the scaffold element if there are other entries.
        if(thisElem.hasClass('scaffold')) {
          if(widgetTextDivs.length != 1) {
            continue;
          //If this is the only textarea, then save the content and break out of the loop.
          } else {

            debugger;
            //var content = thisElem.find('textarea').val();
            var content = tinymce.activeEditor.getContent();

            contentArray.push(content);

            break;
          }
        }

        //Get the contentArray index this textarray element represents
        var classIndex = $(widgetTextDivs[i]).attr('class').indexOf('content');
        //I might consider adding error handling code here to test. if(classIndex == -1) error
        var contentClass = $(widgetTextDivs[i]).attr('class').slice(classIndex);
        var contentIndex = Number(contentClass.slice(7));

        //var content = thisElem.find('textarea').val();
        var content = tinymce.activeEditor.getContent();

        if(contentIndex >= contentArray.length) {
          contentArray.push(content);
        } else {
          contentArray[contentIndex] = content;
        }

      }

      this.model.set('contentArray', contentArray);

      global.frontEndWidgetCollection.refreshView = true;
      this.model.refreshWidget = true;
      this.model.save();
      // END SAVING CONTENT ARRAY

    },

    //This function loads the TinyMCE editor into a textarea element with the given jQuery element ID.
    //e.g.: elemId = "#myDiv"; elemId = ".classSelector"
    loadTinyMCE: function(elemId) {
      debugger;

      try {

        //if( tinymce.editors.length == 0 ) {
        if( (global.tinymce.initialized == false) || (global.tinymce.currentView != "frontendwidgets") ) {

          //Fix corner case where the tinyMCE needs to be removed in order to get the init event to fire.
          if((global.tinymce.currentView != "frontendwidgets")) {
            if((global.tinymce.initialized == true)) {
              //debugger;
              tinymce.remove();
              global.tinymce.initialized = false;
            }
          }

          log.push('Initializing TinyMCE editor...')

          //Rendering the template destroys the existing TinyMCE editor. I only want to render the template if the TinyMCE editor
          //hasn't been created yet.
          //this.$el.html(this.template);
          //render?
          debugger;

          tinymce.init({
            selector: elemId,
            //menubar: 'edit view format insert',
            menubar: false,
            toolbar: 'bold, italic, underline, strikethrough, alignleft, aligncenter, alignright, alignjustify, bullist, numlist, outdent, indent, removeformat, subscript, superscript, link, formatselect, fontselect, image_gallery, file_link, code',
            plugins: 'code, image_gallery, link, file_link',
            extended_valid_elements: "a[class|name|href|target|title|onclick|rel|id|download],button[class|name|href|target|title|onclick|rel|id],script[type|src],iframe[src|style|width|height|scrolling|marginwidth|marginheight|frameborder|allowfullscreen],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],$elements",
            relative_urls: false,
            convert_urls: false,
            remove_script_host: false,
            browser_spellcheck: true,
            image_caption: true,

            //The setup function runs when the TinyMCE editor has finished loading. It's kind of like the document.ready() function.
            setup: function (ed) {

              //This code runs with the TinyMCE editor is initialized
              ed.on('init', function(args) {
                debugger;

                global.tinymce.initialized = true;
                global.tinymce.currentView = 'frontendwidgets';
                log.push('TinyMCE editor initialized.')

                //User clicked on existing page and wants to edit it.
                if( global.tinymce.currentModelIndex != null ) {
                  //global.pagesAddNewView.loadPage(global.tinymce.currentModelIndex);
                  tinymce.activeEditor.setContent(global.editWidgetView.model.attributes.contentArray[global.tinymce.currentModelIndex]);
                  global.tinymce.currentModelIndex = null; //Clear to signal that this request has been processed.
                }
                //User clicked on Add New link in left menu and wants to create a new page.
                //} else {
                //  global.pagesAddNewView.newPage();
                //}
              });

              //This function gets called when the user clicks out of the TinyMCE editor
              ed.on('blur', function(event) {
                debugger;
                global.editWidgetView.updateWidget(event);
              });
            },

          });
        //If the TinyMCE editor has already been loaded...
        } else {

          //User clicked the 'Add HTML' button?
          debugger;

          tinymce.remove();
          global.tinymce.initialized = false;
          this.loadTinyMCE(elemId);

          //User clicked on existing page and wants to edit it.
          //if( global.tinymce.currentModelIndex != null ) {
          //  global.pagesAddNewView.loadPage(global.tinymce.currentModelIndex);
          //  global.tinymce.currentModelIndex = null; //Clear to signal that this request has been processed.

          //User clicked on Add New link in left menu and wants to create a new page.
          //} else {
          //  global.pagesAddNewView.newPage();
          //}
        }

      } catch(err) {
        console.error('Error while trying to render tinyMCE editor in Front End Widgets View. Error message: ');
        console.error(err.message);

        log.push('Error while trying to render inyMCE editor in Front End Widgets View. Error message: ');
        log.push(err.message);
        sendLog();
      }
    }

	});

	return FrontEndWidgetView;
});<|endoftext|>


<commit_before>var Canvas = require('../canvas/canvas.js'),
		Vector = require('../actors/vector.js'),
		Target = require('../actors/target.js'),
		Sauron = require('../sauron/sauron.js');
		config = require('../level/playgroundConfig');

function initPlayground() {
	// Create objects needed for game
	var inputCanvas = new Canvas(config.inputCanvasSettings),
			inputVector = new Vector(config.inputVectorSettings),
			outputVector = new Vector(config.outputVectorSettings),
			outputCanvas = new Canvas(config.outputCanvasSettings),
			outputTarget = new Target(config.targetSettings);

	// draw grid(s)
	inputCanvas.drawCanvas();
	outputCanvas.drawCanvas();
	outputCanvas.drawProgressBar();

	// draw vector(s)
	inputVector.init();
	outputVector.init();

	// generate target(s)
	outputTarget.init()
	console.log(outputVector.color)
}

function startPlayground() {
	initPlayground();
}

// think of this as the main function :)
startPlayground();
<commit_msg>inserted playground inside of level 1.<commit_after>var Canvas = require('../canvas/canvas.js'),
		Vector = require('../actors/vector.js'),
		Target = require('../actors/target.js'),
		Sauron = require('../sauron/sauron.js');
		config = require('../level/playgroundConfig');

function initPlayground() {
	// Create objects needed for game
	var inputCanvas = new Canvas(config.inputCanvasSettings),
			inputVector = new Vector(config.inputVectorSettings),
			outputVector = new Vector(config.outputVectorSettings),
			outputCanvas = new Canvas(config.outputCanvasSettings),
			outputTarget = new Target(config.targetSettings);

	// draw grid(s)
	inputCanvas.drawCanvas();
	outputCanvas.drawCanvas();
	outputCanvas.drawProgressBar();

	// draw vector(s)
	inputVector.init();
	outputVector.init();

	// generate target(s)
	outputTarget.init()
}

// think of this as the main function :)
startPlayground = function startPlayground() {
	initPlayground();
}

module.exports = {

	initPlayground: function() {
		// Create objects needed for game
		var inputCanvas = new Canvas(config.inputCanvasSettings),
				inputVector = new Vector(config.inputVectorSettings),
				outputVector = new Vector(config.outputVectorSettings),
				outputCanvas = new Canvas(config.outputCanvasSettings),
				outputTarget = new Target(config.targetSettings);

		// draw grid(s)
		inputCanvas.drawCanvas();
		outputCanvas.drawCanvas();
		outputCanvas.drawProgressBar();

		// draw vector(s)
		inputVector.init();
		outputVector.init();

		// generate target(s)
		outputTarget.init()
	},

	startPlayground: function() {
		this.initPlayground();
	}

};<|endoftext|>


<commit_before>module.exports = {

};<commit_msg>adding some web client test data<commit_after>module.exports = {

  'listen start': {
    robot: 'rob',
  },
  'listen end': {
    robot: 'rob',
  },
  'command result': {
    robot: 'rob',
    parameters: [true, 'a test command result'],
  }

};<|endoftext|>