<commit_before>$(document).ready(function(){
  //var $clock = $('canvas#clock');
  var clock = document.getElementById('clock');
  if (clock.getContext) {
    var ctx = clock.getContext("2d");

    function Hand(center, clockSize) {
      this.step = null;
      this.scale = 60;
      this.outset = -15;
      this.end = null;
      this.thickness = 5;
      this.color = '#111';
      this.center = {};
      this.center.x = center.x;
      this.center.y = center.y;
      this.offset = Math.PI * 75;
      this.halfScale = this.scale/2;
      this.stepPI = this.step * Math.PI;
    }

    Hand.prototype.getX = function(start, stop) {
      var stepPI = (this.step * Math.PI);
      var ret = start + stop * Math.cos((stepPI - this.offset)/this.halfScale);
      return ret;
    }

    Hand.prototype.getY = function(start, stop) {
      var stepPI = (this.step * Math.PI);
      var ret = start + stop * Math.sin((stepPI - this.offset)/this.halfScale);
      return ret;
    }

    Hand.prototype.draw = function(config) {

        for(option in config) {
          this[option] = config[option];

          if(option == 'step') {
            this.stepPI = this.step * Math.PI;
          }

          if(option == 'scale') {
            this.halfScale = this.scale/2;
          }
        }

        ctx.strokeStyle = this.color;
        ctx.lineWidth = this.thickness;
        ctx.beginPath();

        var new_x = this.getX(this.center.x, this.outset);
        var new_x_2 =  this.getX(this.center.x, this.end);
        var new_y = this.getY(this.center.y, this.outset);
        var new_y_2 =  this.getY(this.center.y, this.end);

        console.log(new_x);
        console.log(new_y);

        ctx.moveTo( new_x, new_y );
        ctx.lineTo( new_x_2, new_y_2 );
        ctx.stroke();
    };

    function Clock(centerX, centerY) {
      this.size = 300;// px square

      if(centerX === undefined) {
        centerX = this.size/2;
      }
      if(centerY === undefined) {
        centerY = this.size/2;
      }
      this.log = false;
      this.center = {x:centerX, y:centerY};

      //this.center.x = centerX;
      //this.center.y = centerY;
    }

    Clock.prototype.init = function() {
      // body...
    };

    Clock.prototype.draw = function() {
      this.drawCenterCircle(125);
      this.drawCenterCircle(3);
      this.drawTicks();
      this.drawCenterCircle(100);
      this.drawCenterCircle(10, 'red');
    };

    Clock.prototype.run = function() {
        var that = this;
        window.setInterval(function(){
              ctx.clearRect(that.center.x - that.size/2, that.center.y - that.size/2, that.size, that.size);
              that.draw();
              var time = new Date();
              var seconds = (time.getMilliseconds()/1000)+time.getSeconds();
              var minutes = time.getMinutes()+(seconds/60);
              var hours = (time.getHours()%12)+(minutes/60);
              var secondsHand = new Hand(that.center, that.size);
              var minutesHand = new Hand(that.center, that.size);
              var hoursHand = new Hand(that.center, that.size);
              //console.log('begin drawing');

              minutesHand.draw({step: minutes, end: 115});
              hoursHand.draw({scale: 12,step: hours, end: 65});
              secondsHand.draw({step: seconds, outset: 20, end: 95, thickness: 2, color: 'red'});
              //console.log('end drawing');

              if(that.log) {
                console.log('H:M:S '+hours+':'+minutes+':'+seconds);
              }

          }, 1000);
    };

    Clock.prototype.drawTicks = function() {
      var tickLength = 40;
      var tickOutset = 75;
      var tickEnd = tickLength + tickOutset;
      var width = 10;
      var color = '#555';
      var num_ticks = 12;
      var hourTicks = new Hand(this.center, this.size);
      var secondTicks = new Hand(this.center, this.size);

      for(var q = 0; q < num_ticks; q++) {
        secondTicks.draw({step: q, scale: num_ticks, outset: tickOutset, end: tickEnd, width: width, color: color});
      }

      for(var q = 0; q < 60; q++) {
        if(q%5 == 0) continue;
        hourTicks.draw({step: q, outset: tickOutset, end: tickEnd, width: 1, color: '#999'});
      }
    };

    Clock.prototype.drawCenterCircle = function(size, color) {
      this.drawCircle(this.center.x, this.center.y, size, color);
    }

    Clock.prototype.drawCircle = function(x, y, diameter, color) {
       if(color === undefined) {
          color = '#000';
        }

        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.strokeStyle = color;
        ctx.arc(x,y,diameter,0,Math.PI*2,true);
        ctx.stroke();
    };

    Clock.prototype.setLog = function(set){
      this.log = set;
    };

    var clock1 = new Clock();
//
    clock1.setLog(true);
    clock1.init();
    clock1.run();

    var clock2 = new Clock(300, 150);
    clock2.setLog(true);
    clock2.init();
    clock2.run();
//
    var clock3 = new Clock(150, 300);
    clock3.setLog(true);
    clock3.init();
    clock3.run();
  }
});<commit_msg>cleaned up the file some.<commit_after>$(document).ready(function(){
  //var $clock = $('canvas#clock');
  var clock = document.getElementById('clock');
  if (clock.getContext) {
    var ctx = clock.getContext("2d");

    function Hand(center, clockSize, outset) {
      this.step = null;
      this.scale = 60;
      this.outset = (outset === undefined) ? -15 : outset;
      this.end = null;
      this.thickness = 5;
      this.color = '#111';
      this.center = {};
      this.center.x = center.x;
      this.center.y = center.y;
      this.offset = Math.PI * 75;
      this.halfScale = this.scale/2;
      this.stepPI = this.step * Math.PI;
    }

    Hand.prototype.getX = function(start, stop) {
      var stepPI = (this.step * Math.PI);
      var ret = start + stop * Math.cos((stepPI - this.offset)/this.halfScale);
      return ret;
    }

    Hand.prototype.getY = function(start, stop) {
      var stepPI = (this.step * Math.PI);
      var ret = start + stop * Math.sin((stepPI - this.offset)/this.halfScale);
      return ret;
    }

    Hand.prototype.draw = function(config) {

        for(option in config) {
          this[option] = config[option];

          if(option == 'step') {
            this.stepPI = this.step * Math.PI;
          }

          if(option == 'scale') {
            this.halfScale = this.scale/2;
          }
        }

        ctx.strokeStyle = this.color;
        ctx.lineWidth = this.thickness;
        ctx.beginPath();

        var new_x = this.getX(this.center.x, this.outset);
        var new_x_2 =  this.getX(this.center.x, this.end);
        var new_y = this.getY(this.center.y, this.outset);
        var new_y_2 =  this.getY(this.center.y, this.end);

        console.log(new_x);
        console.log(new_y);

        ctx.moveTo( new_x, new_y );
        ctx.lineTo( new_x_2, new_y_2 );
        ctx.stroke();
    };

    function Clock(centerX, centerY) {
      this.size = 300;// px square

      if(centerX === undefined) {
        centerX = this.size/2;
      }
      if(centerY === undefined) {
        centerY = this.size/2;
      }
      this.log = false;
      this.center = {x:centerX, y:centerY};

      //this.center.x = centerX;
      //this.center.y = centerY;
    }

    Clock.prototype.init = function() {
      // body...
    };

    Clock.prototype.draw = function() {
      this.drawCenterCircle(125);
      this.drawCenterCircle(3);
      this.drawTicks();
      this.drawCenterCircle(100);
      this.drawCenterCircle(10, 'red');
    };

    Clock.prototype.run = function() {
        var that = this;
        window.setInterval(function(){
              ctx.clearRect(that.center.x - that.size/2, that.center.y - that.size/2, that.size, that.size);
              that.draw();
              var time = new Date();
              var seconds = (time.getMilliseconds()/1000)+time.getSeconds();
              var minutes = time.getMinutes()+(seconds/60);
              var hours = (time.getHours()%12)+(minutes/60);
              var secondsHand = new Hand(that.center, that.size);
              var minutesHand = new Hand(that.center, that.size, -25);
              var hoursHand = new Hand(that.center, that.size);
              //console.log('begin drawing');

              minutesHand.draw({step: minutes, end: 115});
              hoursHand.draw({scale: 12,step: hours, end: 65});
              secondsHand.draw({step: seconds, outset: 20, end: 95, thickness: 2, color: 'red'});
              //console.log('end drawing');

              if(that.log) {
                console.log('H:M:S '+hours+':'+minutes+':'+seconds);
              }

          }, 100);
    };

    Clock.prototype.drawTicks = function() {
      var tickLength = 40;
      var tickOutset = 75;
      var tickEnd = tickLength + tickOutset;
      var width = 10;
      var color = '#555';
      var num_ticks = 12;
      var hourTicks = new Hand(this.center, this.size);
      var secondTicks = new Hand(this.center, this.size);

      for(var q = 0; q < num_ticks; q++) {
        secondTicks.draw({step: q, scale: num_ticks, outset: tickOutset, end: tickEnd, width: width, color: color});
      }

      for(var q = 0; q < 60; q++) {
        if(q%5 == 0) continue;
        hourTicks.draw({step: q, outset: tickOutset, end: tickEnd, width: 1, color: '#999'});
      }
    };

    Clock.prototype.drawCenterCircle = function(size, color) {
      this.drawCircle(this.center.x, this.center.y, size, color);
    }

    Clock.prototype.drawCircle = function(x, y, diameter, color) {
       if(color === undefined) {
          color = 'steelblue';
        }

        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.strokeStyle = color;
        ctx.arc(x,y,diameter,0,Math.PI*2,true);
        ctx.stroke();
    };

    Clock.prototype.setLog = function(set){
      this.log = set;
    };

    var clock1 = new Clock();
//
    //clock1.setLog(true);
    clock1.init();
    clock1.run();

    //var clock2 = new Clock(300, 150);
    ////clock2.setLog(true);
    //clock2.init();
    //clock2.run();
////
    //var clock3 = new Clock(150, 300);
    ////clock3.setLog(true);
    //clock3.init();
    //clock3.run();
  }
});<|endoftext|>


<commit_before>'use strict';

/**
 * Styles
 */
require('../less/admin.less');

// Catch all errors
require('raven');

var $ = require('jquery');
require('bootstrap');

var Vue = require('vue'),
    config = require('config');

// Ensure retrocompatibily for 0.12.2 replace behavior
Vue.options.replace = false;
Vue.config.debug = config.debug;

Vue.use(require('plugins/util'));
Vue.use(require('plugins/text'));
Vue.use(require('plugins/jquery'));
Vue.use(require('plugins/i18next'));
Vue.use(require('plugins/markdown'));
Vue.use(require('plugins/scroll-to'));
Vue.use(require('plugins/router'), {prefix: config.root});

$(require('api')).on('built', function() {
    var app = new Vue(require('app.vue'));
    app.$mount('#app');
});

<commit_msg>Ensure Babel/ES6 polyfills are loaded<commit_after>'use strict';

/**
 * Styles
 */
require('../less/admin.less');

// Ensure Babel/ES6 polyfills are loaded
require('babel-core/polyfill');

// Catch all errors
require('raven');

var $ = require('jquery');
require('bootstrap');

var Vue = require('vue'),
    config = require('config');

// Ensure retrocompatibily for 0.12.2 replace behavior
Vue.options.replace = false;
Vue.config.debug = config.debug;

Vue.use(require('plugins/util'));
Vue.use(require('plugins/text'));
Vue.use(require('plugins/jquery'));
Vue.use(require('plugins/i18next'));
Vue.use(require('plugins/markdown'));
Vue.use(require('plugins/scroll-to'));
Vue.use(require('plugins/router'), {prefix: config.root});

$(require('api')).on('built', function() {
    var app = new Vue(require('app.vue'));
    app.$mount('#app');
});

<|endoftext|>


<commit_before>/**
 * NextCloud / ownCloud - fractalnote
 *
 * Licensed under the Apache License, Version 2.0
 *
 * @author Alexander Demchenko <https://github.com/alboro>
 * @copyright Alexander Demchenko 2017
 */
(function (OC, window, $, Handlebars, undefined) {
    'use strict';

    $(function () {

        // this notes object holds all our notes
        var NodeRepository = function (baseUrl, filePath) {
            this._baseUrl  = baseUrl;
            this._filePath = filePath;
            this._requestProcessing = false;
        };

        NodeRepository.prototype = {

            createNode: function (parentId, title, position, modifiedTime) {
                return this.makeRequest({
                    url: this._baseUrl + '/notes?' + this._filePath,
                    method: 'POST',
                    contentType: 'application/json',
                    data: JSON.stringify({
                        mtime   : modifiedTime,
                        parentId: this.getParentId(parentId),
                        title   : title,
                        position: position
                    })
                });
            },

            moveNode: function (nodeId, newParentId, position, modifiedTime) {
                return this.updateNode({
                        id         : nodeId,
                        newParentId: this.getParentId(newParentId),
                        position   : position
                }, modifiedTime);
            },

            updateNode: function (nodeData, modifiedTime) {
                return this.makeRequest({
                    url: this._baseUrl + '/notes/' + nodeData.id  + '?' + this._filePath,
                    method: 'PUT',
                    contentType: 'application/json',
                    data: JSON.stringify({
                        mtime   : modifiedTime,
                        nodeData: nodeData
                    })
                });
            },

            deleteNode: function (nodeModel, modifiedTime) {
                return this.makeRequest({
                    url: this._baseUrl + '/notes/' + nodeModel.id  + '?' + this._filePath,
                    method: 'DELETE',
                    contentType: 'application/json',
                    data: JSON.stringify({
                        mtime : modifiedTime,
                        nodeId: nodeModel.id
                    })
                });
            },

            getParentId: function (parentId) {
                return parentId === '#' ? 0 : parentId;
            },

            makeRequest: function (request) {
                var self = this;
                if (this._requestProcessing) {
                    alert('Cannot make new request. Previous request is still being processed!');
                    return $.Deferred(); // todo: trigger .fail callback, pass error instance with message
                }
                this._requestProcessing = true;
                return $.ajax(request).always(function () { self._requestProcessing = false; });
            }
        };

        /**
         * @param {NodeRepository} object
         */
        var View = function (noteRepo) {
            this.nodeRepo           = noteRepo;
            this.activeNode         = null;
            this.allNodes           = null;
            this.firstNode          = null;

            this.contentTplElement  = $('#note-content-tpl');
            this.editorElement      = $('#note-editor');

            this.selectorText       = '#note-editor textarea';
            this.selectorSaveButton = '#note-editor [name=save]';
            this.selectorTitle      = '#note-editor #note-node-title';

            this.searchElement      = $('#note-searchbar');
            this.navigationElement  = $('#note-navigation');

            var treeData            = $('#js-tree-data');

            this.themeName          = treeData.data('themeName');
            this.mtime              = treeData.data('mtime');
            this.treeDataSource     = treeData;
        };

        View.prototype = {

            parseNodes: function () {
                this.allNodes = JSON.parse(this.treeDataSource.text());
                this.firstNode = this.allNodes[0].id;
            },

            setTime: function (time) {
                this.mtime = time;

                return this;
            },

            getTime: function () {
                return this.mtime;
            },

            getActiveNode: function () {
                return this.activeNode;
            },

            setActiveNode: function (nodeModel) {
                this.activeNode = nodeModel;
            },

            /**
             * @access {public}
             * @returns {jQuery element}
             */
            getNavigation: function () {
                return this.navigationElement;
            },
            /**
             * @access {public}
             * @returns {undefined}
             */
            renderEditor: function (nodeToActivate) {
                this.setActiveNode(nodeToActivate);
                var areaTemplate = Handlebars.compile(this.contentTplElement.html());
                this.editorElement.html(
                    areaTemplate({note: this.getActiveNode()})
                );
                // handle saves
                $(this.selectorSaveButton).click(this.saveClick.bind(this));
            },

            /**
             * @access {public}
             */
            saveClick: function () {
                var self = this, button = $(this.selectorSaveButton), requestNode = this.getActiveNode();
                requestNode.content = $(this.selectorText).val();
                $(button).addClass('loading');
                this.nodeRepo.updateNode(requestNode, this.getTime())
                    .done(function (response) {
                        $(button).removeClass('loading');
                        if (!response) {
                            return;
                        }
                        self.setTime(response[0]);
                        var node = self.getTreeInstance().get_node(requestNode.id);
                        node.data.content = requestNode.content;
                    })
                    .fail(function (e) {
                        $(button).removeClass('loading');
                        alert(e.responseJSON && e.responseJSON.message ? e.responseJSON.message : 'Action failed');
                    });
            },

            /**
             * @access {public}
             */
            getTreeInstance: function () {
                return this.getNavigation().jstree(true);
            },

            checkChanged: function () {
                var node = this.getActiveNode();
                if (node) {
                    var currentValue = $(this.selectorText).val();
                    if (node.content != currentValue) {
                        $(this.selectorSaveButton).click();
                    }
                }
            },

            /**
             * @access {public}
             * @returns {undefined}
             */
            menuRenameNode: function (data) {
                var title, oldTitle,
                    inst = $.jstree.reference(data.reference),
                    obj = inst.get_node(data.reference);
                title = prompt('Provide new node title:', obj.text);
                if (title) {
                    oldTitle = obj.text;
                    inst.set_text(obj, title);
                    this.afterNodeRename(obj, title, oldTitle); // inst.edit(obj);
                }
                return true;
            },

            /**
             * @access {public}
             */
            afterNodeMove: function (node, newParentId, newPosition) {
                var self = this;
                self.nodeRepo.moveNode(node.id, newParentId, newPosition, self.getTime())
                    .done(function (response) {
                        self.setTime(response[0]);
                    })
                    .fail(function (e) {
                        alert(e.responseJSON && e.responseJSON.message ? e.responseJSON.message : 'Action failed');
                    });
            },

            /**
             * @access {public}
             */
            afterNodeRename: function (node, old) {
                var requestModel, self = this;
                requestModel = {
                    id: node.id,
                    title: node.text,
                    content: null
                };
                self.nodeRepo.updateNode(requestModel, self.getTime())
                    .done(function (response) {
                        self.setTime(response[0]);
                        if (self.getActiveNode().id === node.id) {
                            $(self.selectorTitle).html(node.text);
                        }
                    })
                    .fail(function (e) {
                        var node, jstree = self.getTreeInstance();
                        node = jstree.get_node(requestModel.id);
                        jstree.set_text(node, old);
                        alert(e.responseJSON && e.responseJSON.message ? e.responseJSON.message : 'Action failed');
                    });
            },

            /**
             * @access {public}
             * @returns {undefined}
             */
            menuCreateNode: function (isSubNodeCreation, data) {
                var title, newNode,
                    inst = $.jstree.reference(data.reference),
                    obj = inst.get_node(data.reference);
                title = prompt('Provide new node title:', 'New node');
                if (!title) {
                    return;
                }
                newNode = {
                    id: null,
                    type: 'txt',
                    text: title,
                    data: {
                        content: '',
                        isEditable: true,
                        isReadonly: false,
                        isRich: false
                    },
                    children: []
                };
                inst.create_node(isSubNodeCreation ? obj : obj.parent, newNode, 'last', function (newNodeObj) {
                    inst.select_node(newNodeObj);
                });
            },

            /**
             * @access {public}
             */
            afterNodeCreate: function (parent, node, position) {
                var self = this;
                self.nodeRepo.createNode(parent, node.text, position, self.getTime())
                    .done(function (response) {
                        self.setTime(response[0]);
                        self.getTreeInstance().set_id(node.id, response[1]);
                    })
                    .fail(function (e) {
                        self.getTreeInstance().delete_node(node);
                        alert(e.responseJSON && e.responseJSON.message ? e.responseJSON.message : 'Action failed');
                    });
            },

            /**
             * @access {public}
             * @returns {undefined}
             */
            menuDeleteNode: function (data) {
                var ok, self = this, inst = $.jstree.reference(data.reference),
                    node = inst.get_node(data.reference);
                ok = confirm('Are you sure to delete?');
                if (!ok) {
                    return;
                }
                this.nodeRepo.deleteNode(node, self.getTime())
                    .done(function (response) {
                        var prevNode;
                        self.setTime(response[0]);
                        inst.delete_node(node);
                        if (self.nodeRepo.getParentId(node.parent)) {
                            prevNode = inst.get_node(node.parent);
                            inst.select_node(prevNode);
                        } else {
                            self.renderEditor(null);
                        }
                    })
                    .fail(function (e, type, statusText) {
                        alert(e.responseJSON && e.responseJSON.message ? e.responseJSON.message : 'Action failed');
                    })
            },

            /**
             * @access {public}
             * @returns {undefined}
             */
            render: function () {
                var self = this;
                this.parseNodes();
                this.getNavigation().jstree({
                    "core": {
                        "themes": {
                            "name": this.themeName,
                            "responsive": true
                        },
                        "multiple" : false,
                        "animation": 0,
                        "check_callback": true,
                        "data": this.allNodes
                    },
                    "plugins": ["contextmenu", "dnd", "search", "state", "types", "wholerow"],
                    "search": {
                        "show_only_matches_children": true
                        //"search_callback": true
                    },
                    "state": {
                        "key": this.nodeRepo._filePath
                    },
                    "types" : {
                        "txt": {
                            "a_attr": {"class": "app-navigation-noclose"} // nextcloud config
                        },
                        "readonly": {
                            "icon" : "jstree-icon-no-edit",
                            "a_attr": {"class": "app-navigation-noclose"} // nextcloud config
                        },
                        "rich": {
                            "icon" : "jstree-icon-no-edit",
                            "a_attr": {"class": "app-navigation-noclose"} // nextcloud config
                        }
                    },
                    "contextmenu": {
                        "items": {
                            "create" : {
                                "separator_before"	: false,
                                "separator_after"	: false,
                                "_disabled"			: false,
                                "label"				: "Add Node",
                                "action"			: this.menuCreateNode.bind(this, false)
                            },
                            "sub-create" : {
                                "separator_before"	: false,
                                "separator_after"	: false,
                                "_disabled"			: false,
                                "label"				: "Add SubNode",
                                "action"			: this.menuCreateNode.bind(this, true)
                            },
                            "rename" : {
                                "separator_before"	: false,
                                "separator_after"	: false,
                                "_disabled"			: false,
                                "label"				: "Rename Node",
                                "shortcut"			: 113,
                                "shortcut_label"	: 'F2',
                                "icon"				: "glyphicon glyphicon-leaf",
                                "action"			: this.menuRenameNode.bind(this)
                            },
                            "remove" : {
                                "separator_before"	: true,
                                "icon"				: false,
                                "separator_after"	: false,
                                "_disabled"			: false,
                                "label"				: "Delete Node",
                                "action"			: this.menuDeleteNode.bind(this)
                            }
                        }
                    }
                })
                .on('create_node.jstree', function (e, data) {
                    self.afterNodeCreate(data.parent, data.node, data.position + 1);
                })
                .on('rename_node.jstree', function (e, data) {
                     self.afterNodeRename(data.node, data.old);
                })
                .on('state_ready.jstree', function (e, data) {
                    if (data.instance.get_state().core.selected.length == 0) {
                        data.instance.select_node(self.firstNode);
                    }
                })
                .on('set_state.jstree', function (e, data) {
                    var selected = data.instance.get_selected();
                    if (selected.length) {
                        var node = data.instance.get_node(selected[0]);
                        self.renderEditor({
                            id:      node.id,
                            title:   node.text,
                            content: node.data.content,
                            isEditable: node.data.isEditable,
                            isReadonly: node.data.isReadonly,
                            isRich: node.data.isRich
                        });
                    }
                })
                .on('select_node.jstree', function (e, data) {
                    self.checkChanged();
                    self.renderEditor({
                        id:      data.node.id,
                        title:   data.node.text,
                        content: data.node.data.content,
                        isEditable: data.node.data.isEditable,
                        isReadonly: data.node.data.isReadonly,
                        isRich: data.node.data.isRich
                    });
                })
                .on('move_node.jstree', function (e, data) {
                    self.afterNodeMove(data.node, data.parent, data.position + 1);
                });
                this.allNodes = null;
                var to = false;
                self.searchElement.keyup(function () {
                    if (to) {
                        clearTimeout(to);
                    }
                    to = setTimeout(function () {
                        self.getTreeInstance().search(self.searchElement.val());
                    }, 250);
                });
            }
        };

        var noteRepo = new NodeRepository(
            OC.generateUrl('/apps/fractalnote'),
            window.document.location.search.substring(1)
        );
        new View(noteRepo).render();
    });

})(OC, window, jQuery, Handlebars);<commit_msg>fix node edit just after node creation<commit_after>/**
 * NextCloud / ownCloud - fractalnote
 *
 * Licensed under the Apache License, Version 2.0
 *
 * @author Alexander Demchenko <https://github.com/alboro>
 * @copyright Alexander Demchenko 2017
 */
(function (OC, window, $, Handlebars, undefined) {
    'use strict';

    $(function () {

        // this notes object holds all our notes
        var NodeRepository = function (baseUrl, filePath) {
            this._baseUrl  = baseUrl;
            this._filePath = filePath;
            this._requestProcessing = false;
        };

        NodeRepository.prototype = {

            createNode: function (parentId, title, position, modifiedTime) {
                return this.makeRequest({
                    url: this._baseUrl + '/notes?' + this._filePath,
                    method: 'POST',
                    contentType: 'application/json',
                    data: JSON.stringify({
                        mtime   : modifiedTime,
                        parentId: this.getParentId(parentId),
                        title   : title,
                        position: position
                    })
                });
            },

            moveNode: function (nodeId, newParentId, position, modifiedTime) {
                return this.updateNode({
                        id         : nodeId,
                        newParentId: this.getParentId(newParentId),
                        position   : position
                }, modifiedTime);
            },

            updateNode: function (nodeData, modifiedTime) {
                return this.makeRequest({
                    url: this._baseUrl + '/notes/' + nodeData.id  + '?' + this._filePath,
                    method: 'PUT',
                    contentType: 'application/json',
                    data: JSON.stringify({
                        mtime   : modifiedTime,
                        nodeData: nodeData
                    })
                });
            },

            deleteNode: function (nodeModel, modifiedTime) {
                return this.makeRequest({
                    url: this._baseUrl + '/notes/' + nodeModel.id  + '?' + this._filePath,
                    method: 'DELETE',
                    contentType: 'application/json',
                    data: JSON.stringify({
                        mtime : modifiedTime,
                        nodeId: nodeModel.id
                    })
                });
            },

            getParentId: function (parentId) {
                return parentId === '#' ? 0 : parentId;
            },

            makeRequest: function (request) {
                var self = this;
                if (this._requestProcessing) {
                    alert('Cannot make new request. Previous request is still being processed!');
                    return $.Deferred(); // todo: trigger .fail callback, pass error instance with message
                }
                this._requestProcessing = true;
                return $.ajax(request).always(function () { self._requestProcessing = false; });
            }
        };

        /**
         * @param {NodeRepository} object
         */
        var View = function (noteRepo) {
            this.nodeRepo           = noteRepo;
            this.activeNode         = null;
            this.allNodes           = null;
            this.firstNode          = null;

            this.contentTplElement  = $('#note-content-tpl');
            this.editorElement      = $('#note-editor');

            this.selectorText       = '#note-editor textarea';
            this.selectorSaveButton = '#note-editor [name=save]';
            this.selectorTitle      = '#note-editor #note-node-title';

            this.searchElement      = $('#note-searchbar');
            this.navigationElement  = $('#note-navigation');

            var treeData            = $('#js-tree-data');

            this.themeName          = treeData.data('themeName');
            this.mtime              = treeData.data('mtime');
            this.treeDataSource     = treeData;
        };

        View.prototype = {

            parseNodes: function () {
                this.allNodes = JSON.parse(this.treeDataSource.text());
                this.firstNode = this.allNodes[0].id;
            },

            setTime: function (time) {
                this.mtime = time;

                return this;
            },

            getTime: function () {
                return this.mtime;
            },

            getActiveNode: function () {
                return this.activeNode;
            },

            setActiveNode: function (nodeModel) {
                this.activeNode = nodeModel;
            },

            /**
             * @access {public}
             * @returns {jQuery element}
             */
            getNavigation: function () {
                return this.navigationElement;
            },
            /**
             * @access {public}
             * @returns {undefined}
             */
            renderEditor: function (nodeToActivate) {
                this.setActiveNode(nodeToActivate);
                var areaTemplate = Handlebars.compile(this.contentTplElement.html());
                this.editorElement.html(
                    areaTemplate({note: this.getActiveNode()})
                );
                // handle saves
                $(this.selectorSaveButton).click(this.saveClick.bind(this));
            },

            /**
             * @access {public}
             */
            saveClick: function () {
                var self = this, button = $(this.selectorSaveButton), requestNode = this.getActiveNode();
                requestNode.content = $(this.selectorText).val();
                $(button).addClass('loading');
                this.nodeRepo.updateNode(requestNode, this.getTime())
                    .done(function (response) {
                        $(button).removeClass('loading');
                        if (!response) {
                            return;
                        }
                        self.setTime(response[0]);
                        var node = self.getTreeInstance().get_node(requestNode.id);
                        node.data.content = requestNode.content;
                    })
                    .fail(function (e) {
                        $(button).removeClass('loading');
                        alert(e.responseJSON && e.responseJSON.message ? e.responseJSON.message : 'Action failed');
                    });
            },

            /**
             * @access {public}
             */
            getTreeInstance: function () {
                return this.getNavigation().jstree(true);
            },

            checkChanged: function () {
                var node = this.getActiveNode();
                if (node) {
                    var currentValue = $(this.selectorText).val();
                    if (node.content != currentValue) {
                        $(this.selectorSaveButton).click();
                    }
                }
            },

            /**
             * @access {public}
             * @returns {undefined}
             */
            menuRenameNode: function (data) {
                var title, oldTitle,
                    inst = $.jstree.reference(data.reference),
                    obj = inst.get_node(data.reference);
                title = prompt('Provide new node title:', obj.text);
                if (title) {
                    oldTitle = obj.text;
                    inst.set_text(obj, title);
                    this.afterNodeRename(obj, title, oldTitle); // inst.edit(obj);
                }
                return true;
            },

            /**
             * @access {public}
             */
            afterNodeMove: function (node, newParentId, newPosition) {
                var self = this;
                self.nodeRepo.moveNode(node.id, newParentId, newPosition, self.getTime())
                    .done(function (response) {
                        self.setTime(response[0]);
                    })
                    .fail(function (e) {
                        alert(e.responseJSON && e.responseJSON.message ? e.responseJSON.message : 'Action failed');
                    });
            },

            /**
             * @access {public}
             */
            afterNodeRename: function (node, old) {
                var requestModel, self = this;
                requestModel = {
                    id: node.id,
                    title: node.text,
                    content: null
                };
                self.nodeRepo.updateNode(requestModel, self.getTime())
                    .done(function (response) {
                        self.setTime(response[0]);
                        if (self.getActiveNode().id === node.id) {
                            $(self.selectorTitle).html(node.text);
                        }
                    })
                    .fail(function (e) {
                        var node, jstree = self.getTreeInstance();
                        node = jstree.get_node(requestModel.id);
                        jstree.set_text(node, old);
                        alert(e.responseJSON && e.responseJSON.message ? e.responseJSON.message : 'Action failed');
                    });
            },

            /**
             * @access {public}
             * @returns {undefined}
             */
            menuCreateNode: function (isSubNodeCreation, data) {
                var title, newNode,
                    inst = $.jstree.reference(data.reference),
                    obj = inst.get_node(data.reference);
                title = prompt('Provide new node title:', 'New node');
                if (!title) {
                    return;
                }
                newNode = {
                    id: null,
                    type: 'txt',
                    text: title,
                    data: {
                        content: '',
                        isEditable: true,
                        isReadonly: false,
                        isRich: false
                    },
                    children: []
                };
                inst.create_node(isSubNodeCreation ? obj : obj.parent, newNode, 'last', function (newNodeObj) {
                    inst.select_node(newNodeObj);
                });
            },

            /**
             * @access {public}
             */
            afterNodeCreate: function (parent, node, position) {
                var self = this;
                self.nodeRepo.createNode(parent, node.text, position, self.getTime())
                    .done(function (response) {
                        self.setTime(response[0]);
                        self.getTreeInstance().set_id(node, response[1]);
                    })
                    .fail(function (e) {
                        self.getTreeInstance().delete_node(node);
                        alert(e.responseJSON && e.responseJSON.message ? e.responseJSON.message : 'Action failed');
                    });
            },

            /**
             * @access {public}
             * @returns {undefined}
             */
            menuDeleteNode: function (data) {
                var ok, self = this, inst = $.jstree.reference(data.reference),
                    node = inst.get_node(data.reference);
                ok = confirm('Are you sure to delete?');
                if (!ok) {
                    return;
                }
                this.nodeRepo.deleteNode(node, self.getTime())
                    .done(function (response) {
                        var prevNode;
                        self.setTime(response[0]);
                        inst.delete_node(node);
                        if (self.nodeRepo.getParentId(node.parent)) {
                            prevNode = inst.get_node(node.parent);
                            inst.select_node(prevNode);
                        } else {
                            self.renderEditor(null);
                        }
                    })
                    .fail(function (e, type, statusText) {
                        alert(e.responseJSON && e.responseJSON.message ? e.responseJSON.message : 'Action failed');
                    })
            },

            /**
             * @access {public}
             * @returns {undefined}
             */
            render: function () {
                var self = this;
                this.parseNodes();
                this.getNavigation().jstree({
                    "core": {
                        "themes": {
                            "name": this.themeName,
                            "responsive": true
                        },
                        "multiple" : false,
                        "animation": 0,
                        "check_callback": true,
                        "data": this.allNodes
                    },
                    "plugins": ["contextmenu", "dnd", "search", "state", "types", "wholerow"],
                    "search": {
                        "show_only_matches_children": true
                        //"search_callback": true
                    },
                    "state": {
                        "key": this.nodeRepo._filePath
                    },
                    "types" : {
                        "txt": {
                            "a_attr": {"class": "app-navigation-noclose"} // nextcloud config
                        },
                        "readonly": {
                            "icon" : "jstree-icon-no-edit",
                            "a_attr": {"class": "app-navigation-noclose"} // nextcloud config
                        },
                        "rich": {
                            "icon" : "jstree-icon-no-edit",
                            "a_attr": {"class": "app-navigation-noclose"} // nextcloud config
                        }
                    },
                    "contextmenu": {
                        "items": {
                            "create" : {
                                "separator_before"	: false,
                                "separator_after"	: false,
                                "_disabled"			: false,
                                "label"				: "Add Node",
                                "action"			: this.menuCreateNode.bind(this, false)
                            },
                            "sub-create" : {
                                "separator_before"	: false,
                                "separator_after"	: false,
                                "_disabled"			: false,
                                "label"				: "Add SubNode",
                                "action"			: this.menuCreateNode.bind(this, true)
                            },
                            "rename" : {
                                "separator_before"	: false,
                                "separator_after"	: false,
                                "_disabled"			: false,
                                "label"				: "Rename Node",
                                "shortcut"			: 113,
                                "shortcut_label"	: 'F2',
                                "icon"				: "glyphicon glyphicon-leaf",
                                "action"			: this.menuRenameNode.bind(this)
                            },
                            "remove" : {
                                "separator_before"	: true,
                                "icon"				: false,
                                "separator_after"	: false,
                                "_disabled"			: false,
                                "label"				: "Delete Node",
                                "action"			: this.menuDeleteNode.bind(this)
                            }
                        }
                    }
                })
                .on('create_node.jstree', function (e, data) {
                    self.afterNodeCreate(data.parent, data.node, data.position + 1);
                })
                .on('rename_node.jstree', function (e, data) {
                     self.afterNodeRename(data.node, data.old);
                })
                .on('state_ready.jstree', function (e, data) {
                    if (data.instance.get_state().core.selected.length == 0) {
                        data.instance.select_node(self.firstNode);
                    }
                })
                .on('set_state.jstree', function (e, data) {
                    var selected = data.instance.get_selected();
                    if (selected.length) {
                        var node = data.instance.get_node(selected[0]);
                        self.renderEditor({
                            id:      node.id,
                            title:   node.text,
                            content: node.data.content,
                            isEditable: node.data.isEditable,
                            isReadonly: node.data.isReadonly,
                            isRich: node.data.isRich
                        });
                    }
                })
                .on('select_node.jstree', function (e, data) {
                    self.checkChanged();
                    self.renderEditor({
                        id:      data.node.id,
                        title:   data.node.text,
                        content: data.node.data.content,
                        isEditable: data.node.data.isEditable,
                        isReadonly: data.node.data.isReadonly,
                        isRich: data.node.data.isRich
                    });
                })
                .on('move_node.jstree', function (e, data) {
                    self.afterNodeMove(data.node, data.parent, data.position + 1);
                });
                this.allNodes = null;
                var to = false;
                self.searchElement.keyup(function () {
                    if (to) {
                        clearTimeout(to);
                    }
                    to = setTimeout(function () {
                        self.getTreeInstance().search(self.searchElement.val());
                    }, 250);
                });
            }
        };

        var noteRepo = new NodeRepository(
            OC.generateUrl('/apps/fractalnote'),
            window.document.location.search.substring(1)
        );
        new View(noteRepo).render();
    });

})(OC, window, jQuery, Handlebars);<|endoftext|>


<commit_before>var ParaparaCanvas = require("./parapara-canvas");
var Frame = require("./frame");
var FramesController = require("./frames-controller");
var drawTools = require("./draw-tools");
var Menu = require("./menu");

var framesController;
var colorPicker, lineWidthPicker;
var menu;
document.addEventListener("DOMContentLoaded", function() {
  framesController = new FramesController(document.getElementById("frames"));
  framesController.append(0, new Frame(new ParaparaCanvas(0, framesController.element)));
  setListenerForCanvas(0);
  framesController.setCurrentFrame(0);

  colorPicker = new drawTools.ColorPicker(document.getElementById("menu-colors"), "red");
  lineWidthPicker = new drawTools.LineWidthPicker(document.getElementById("menu-line-width"), 10);
  menu = new Menu();

  document.getElementById("menu-side-btn").addEventListener("click", function() {
    menu.toggleMenu();
  });
});

function setListenerForCanvas(frameId) {
  var pCanvas = framesController.getCanvasElementByFrameId(frameId);
  pCanvas.addEventListener("mousedown", mouseDownCanvas);
  pCanvas.addEventListener("mouseup", mouseUpCanvas);
  pCanvas.addEventListener("mousemove", mouseMoveCanvas);
}
// TODO: これらは、ここで、いいのか。
// → parapara-canvas.js に取り込むような気もするが、
//   この情報をWebsocket で送ったり・・となるのであれば、
//   それを parapara-canvas.js でやっていいの？となる。
var isMouseDown = false;
var beforeMousePosition = {};
function mouseDownCanvas(event) {
  menu.hideMenu();
  menu.toggleOpenMenuButton(false);
  isMouseDown = true;
  beforeMousePosition = {x: event.clientX, y: event.clientY};
}
function mouseUpCanvas() {
  menu.toggleOpenMenuButton(true);
  isMouseDown = false;
}
function mouseMoveCanvas(event) {
  if (isMouseDown) {
    if (colorPicker.color === "white") {
      framesController.frames[framesController.currentFrameId].paraparaCanvas.eraseByLine(
        beforeMousePosition,
        {x: event.clientX, y: event.clientY},
        lineWidthPicker.lineWidth
      );
    } else {
      framesController.frames[framesController.currentFrameId].paraparaCanvas.drawLine(
        beforeMousePosition,
        {x: event.clientX, y: event.clientY},
        colorPicker.color,
        lineWidthPicker.lineWidth
      );
    }
    beforeMousePosition = {x: event.clientX, y: event.clientY};
  }
}<commit_msg>main.js beforeMousePos -> previous～ に<commit_after>var ParaparaCanvas = require("./parapara-canvas");
var Frame = require("./frame");
var FramesController = require("./frames-controller");
var drawTools = require("./draw-tools");
var Menu = require("./menu");

var framesController;
var colorPicker, lineWidthPicker;
var menu;
document.addEventListener("DOMContentLoaded", function() {
  framesController = new FramesController(document.getElementById("frames"));
  framesController.append(0, new Frame(new ParaparaCanvas(0, framesController.element)));
  setListenerForCanvas(0);
  framesController.setCurrentFrame(0);

  colorPicker = new drawTools.ColorPicker(document.getElementById("menu-colors"), "red");
  lineWidthPicker = new drawTools.LineWidthPicker(document.getElementById("menu-line-width"), 10);
  menu = new Menu();

  document.getElementById("menu-side-btn").addEventListener("click", function() {
    menu.toggleMenu();
  });
});

function setListenerForCanvas(frameId) {
  var pCanvas = framesController.getCanvasElementByFrameId(frameId);
  pCanvas.addEventListener("mousedown", mouseDownCanvas);
  pCanvas.addEventListener("mouseup", mouseUpCanvas);
  pCanvas.addEventListener("mousemove", mouseMoveCanvas);
}
// TODO: これらは、ここで、いいのか。
// → parapara-canvas.js に取り込むような気もするが、
//   この情報をWebsocket で送ったり・・となるのであれば、
//   それを parapara-canvas.js でやっていいの？となる。
var isMouseDown = false;
var previousMousePosition = {};
function mouseDownCanvas(event) {
  menu.hideMenu();
  menu.toggleOpenMenuButton(false);
  isMouseDown = true;
  previousMousePosition = {x: event.clientX, y: event.clientY};
}
function mouseUpCanvas() {
  menu.toggleOpenMenuButton(true);
  isMouseDown = false;
}
function mouseMoveCanvas(event) {
  if (isMouseDown) {
    if (colorPicker.color === "white") {
      framesController.frames[framesController.currentFrameId].paraparaCanvas.eraseByLine(
        previousMousePosition,
        {x: event.clientX, y: event.clientY},
        lineWidthPicker.lineWidth
      );
    } else {
      framesController.frames[framesController.currentFrameId].paraparaCanvas.drawLine(
        previousMousePosition,
        {x: event.clientX, y: event.clientY},
        colorPicker.color,
        lineWidthPicker.lineWidth
      );
    }
    previousMousePosition = {x: event.clientX, y: event.clientY};
  }
}<|endoftext|>


<commit_before>function redirectToHomePage() {
  window.location.pathname = 'index';
}

/**
 * Look for a query param in an url
 * return this param or undefined if not found
 * @param {*} name of the query param
 * @param {*} url url
 */
function getParameterByName(name, url) {
  if (!url) url = window.location.href;
  name = name.replace(/[\[\]]/g, '\\$&');
  var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
    results = regex.exec(url);
  if (!results) return null;
  if (!results[2]) return '';
  return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

function getApiKeyIfOneTimeLoginTokenIsPresent() {
  const oneTimeLoginToken = getParameterByName('oneTimeLoginToken', window.location.href);
  removeQueryParamsFromUrl();
  if (oneTimeLoginToken) {
    console.log('getting api key from q-cloud');
    getAPIKeyWithOneTimeLoginToken(oneTimeLoginToken);
  } else {
    updateLoginDisplayElements(undefined);
    replaceALLApiKeyByStoredApiKey(undefined);
  }
}

function getCurrentUser() {
  const localAPIKey = getStoredAPIKey();
  $.getJSON("https://q.daskeyboard.com/api/1.0/users/me", localAPIKey)
    // post request success
    .done(function (data) {
      // store email
      localStorage.setItem('email', data.email);
      // update the view with the new user info
      updateLoginDisplayElements(data.email);
      replaceALLApiKeyByStoredApiKey(localAPIKey);
    })
    // error with POST request
    .fail(function () {
      // notify user that error happened
      logout();
    });
}

function onLoginToQCloud() {
  const callbackUrl = window.location.pathname;
  window.location = "https://qapp.daskeyboard.com?source=q-documentation"
    + '&callbackUrl=' + callbackUrl;
}

/**
 *
 * redefine jquery post request to use application/json and stringify the data
 */
$.postJSON = function (url, data, callback) {
  return jQuery.ajax({
    'type': 'POST',
    'url': url,
    'contentType': 'application/json',
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
  });
};

/**
 *
 * redefine jquery post request to use application/json and stringify the data
 */
$.getJSON = function (url, apiKey, callback) {
  return jQuery.ajax({
    'type': 'GET',
    'url': url,
    headers: { 'X-API-KEY': apiKey },
    'contentType': 'application/json',
    'dataType': 'json',
    'success': callback
  });
};

/**
 * Get API key from the Q Cloud using a one time login token and store it in the local
 * storage
 * @param {*} loginToken
 */
function getAPIKeyWithOneTimeLoginToken(loginToken) {
  if (!loginToken) {
    console.error('no login token provided');
    return;
  }
  $.postJSON("https://q.daskeyboard.com/api/1.0/users/api_key", { oneTimeLoginToken: loginToken })
    // post request success
    .done(function (data) {
      // store apiKey in local storage
      const apiKey = data.value;
      localStorage.setItem('APIKey', apiKey);
      // notify user that the API key was fetched
      displayFlashNotice('info',
        'You are  logged in: sample code will contain your API key so you can copy paste and experiment easily. Enjoy!');
      getCurrentUser();
    })
    // error with POST request
    .fail(function () {
      // notify user that error happened
      updateLoginDisplayElements(undefined);
      replaceALLApiKeyByStoredApiKey(undefined);
      displayFlashNotice('error', 'Error while fetching API KEY');
    });
}

function getStoredAPIKey() {
  const apiKey = localStorage.getItem('APIKey');
  return apiKey;
}

/************************************************************************
 *
 *  code used to display a notice popover for the user
 *
 *
 * ***********************************************************************
 */

/**
 * Displays a bootstrap alert depending on the noticeType
 * noticeType can be 'info' and the bootstrap alert will be blue
 * or can be 'error' and the bootstrap alert will be red
 * @param {*} noticeType
 * @param {*} message
 */
function displayFlashNotice(noticeType, message) {
  // get the bootstrap alert div
  const flashNoticeDivId = '#flash-notice-section';
  const flashNoticeMessageId = '#flash-notice-message';
  const alertDiv = $(flashNoticeDivId);
  const alertMessage = $(flashNoticeMessageId);

  if (alertDiv && alertMessage) {
    // populate the content of the div with the message
    alertMessage.html(message);
    // remove the previous class lists
    alertDiv.removeClass(['alert-info', 'alert-danger']);
    switch (noticeType) {
      case 'info':
        alertDiv.addClass(['alert-primary']);
        break;

      case 'error':
        alertDiv.addClass(['alert-danger']);
        break;
    }

    // show the div
    alertDiv.css('display', 'block');

  }
}

/**
 * closes the flash notice component by hiding the element in the DOM
 */
function onCloseFlashNotice() {
  const flashNoticeDivId = 'flash-notice-section';
  const alertDiv = document.getElementById(flashNoticeDivId);
  if (alertDiv) {
    alertDiv.style.display = 'none';
  }
}

/************************************************************************
 *
 *  END OF code used to display a notice popover for the user
 *
 *
 * ***********************************************************************
 */

function removeQueryParamsFromUrl() {
  var newurl = window.location.pathname;
  window.history.pushState({ path: newurl }, '', newurl);
}

/**
 * Remove the stored apiKey
 * and update the views to display a none logged user
 */
function logout() {

  // remove api key and email from local storage
  localStorage.removeItem('APIKey');
  localStorage.removeItem('email');

  // reload page
  window.location.reload();
}

function updateLoginDisplayElements(currentUserEmail) {
  if (currentUserEmail) {
    // hide login message
    $('#header-login-message').css('display', 'none');
    // display welcome message
    $('#header-welcome-message').text('Welcome ' + currentUserEmail);
    $('#header-welcome-message').css('display', 'inline-block');
    $('#header-welcome-message').css('font-weight', 'bold');
    // display logout action
    $('#logout-action').css('display', 'inline-block');
  } else {
    // hide logout action
    $('#logout-action').css('display', 'none');
    // hide welcome message
    $('#header-welcome-message').css('display', 'none');
    // display login message
    $('#header-login-message').css('display', 'inline-block');
  }
}

/************************************************************************
 *
 *  code used to display the dynamic content in the code pages
 *
 *
 * ***********************************************************************
 */

function formatJSONCode() {
  var jsonCode = document.getElementsByClassName('json-code');
  for (var i = 0; i < jsonCode.length; i++) {
    var content = jsonCode[i].textContent;
    jsonCode[i].innerHTML = syntaxHighlight(content);
  }
};

function replaceALLApiKeyByStoredApiKey(apiKey) {
  $("body").children().each(function () {
    if (!apiKey) {

      // TODO change with the root to the API Key explanation page
      const apiKeyMoreDetails = window.location.origin + '/get-started/download/';
      $(this).html($(this).html().replace(/\$API_KEY/g,
        // ""
        // + "login to retrieve your api-key"));
        "<button class='login-code-button' data-toggle='tooltip' data-html='true' title='This is a sample API key. Login to see examples "
        + "pre-filled with your keys.'>login to retrieve your api-key</button>"));
    } else {
      $(this).html($(this).html().replace(/\$API_KEY/g, apiKey));
    }
  });
}

/**
 * Use to beautify json code
 * @param {*} json
 */
function syntaxHighlight(json) {
  if (typeof json != 'string') {
    json = JSON.stringify(json, undefined, 2);
  }
  json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
  return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
    var cls = 'number';
    if (/^"/.test(match)) {
      if (/:$/.test(match)) {
        cls = 'key';
      } else {
        cls = 'string';
      }
    } else if (/true|false/.test(match)) {
      cls = 'boolean';
    } else if (/null/.test(match)) {
      cls = 'null';
    }
    // if (cls === 'string') {
    //   return '' + match + '
';
    // } else {
    //   return '' + match + '';
    // }
    return '' + match + '';
  });
}

/************************************************************************
 *
 *  End of code used to display the dynamic content in the code pages
 *
 *
 * ***********************************************************************
 */

/**
 * Detects the os platform and architechture and change the download link of the Q software
 * depending on this informations
 */
function loadDownloadLinkDependingOnOsArchitechture() {
  if (navigator.platform.includes('Win32')) {
    if (navigator.userAgent.indexOf("WOW64") != -1 ||
      navigator.userAgent.indexOf("Win64") != -1) {
      $('#windows-software-download-link').attr("href", "https://s3-us-west-2.amazonaws.com/q-desktop/2.0.1/Das-Keyboard-Q-x64-Setup-2.0.1.exe");
      $('#windows-software-download-link').append(" 64 bit");

    } else {
      $('#windows-software-download-link').attr("href", "https://s3-us-west-2.amazonaws.com/q-desktop/2.0.1/Das-Keyboard-Q-ia32-Setup-2.0.1.exe");
      $('#windows-software-download-link').append(" 32 bit");

    }
  }
}

$(document).ready(function () {
  const email = localStorage.getItem('email');
  const apiKey = getStoredAPIKey();
  console.log('apiKey', apiKey);
  console.log('email', email);

  if (email && apiKey) {
    updateLoginDisplayElements(email);
    replaceALLApiKeyByStoredApiKey(apiKey);
  } else {
    //get ApiKey if one time login token present in url
    getApiKeyIfOneTimeLoginTokenIsPresent();
  }

  formatJSONCode();
 // loadDownloadLinkDependingOnOsArchitechture();

  // enable bootstrap tooltips
  $('[data-toggle="tooltip"]').tooltip();

  // enable bootstrap popovers
  $('[data-toggle="popover"]').popover();

  $('.popover-dismiss').popover({
    trigger: 'focus'
  });
});
<commit_msg>Rollback previous commit<commit_after>function redirectToHomePage() {
  window.location.pathname = 'index';
}

/**
 * Look for a query param in an url
 * return this param or undefined if not found
 * @param {*} name of the query param
 * @param {*} url url
 */
function getParameterByName(name, url) {
  if (!url) url = window.location.href;
  name = name.replace(/[\[\]]/g, '\\$&');
  var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
    results = regex.exec(url);
  if (!results) return null;
  if (!results[2]) return '';
  return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

function getApiKeyIfOneTimeLoginTokenIsPresent() {
  const oneTimeLoginToken = getParameterByName('oneTimeLoginToken', window.location.href);
  removeQueryParamsFromUrl();
  if (oneTimeLoginToken) {
    console.log('getting api key from q-cloud');
    getAPIKeyWithOneTimeLoginToken(oneTimeLoginToken);
  } else {
    updateLoginDisplayElements(undefined);
    replaceALLApiKeyByStoredApiKey(undefined);
  }
}

function getCurrentUser() {
  const localAPIKey = getStoredAPIKey();
  $.getJSON("https://q.daskeyboard.com/api/1.0/users/me", localAPIKey)
    // post request success
    .done(function (data) {
      // store email
      localStorage.setItem('email', data.email);
      // update the view with the new user info
      updateLoginDisplayElements(data.email);
      replaceALLApiKeyByStoredApiKey(localAPIKey);
    })
    // error with POST request
    .fail(function () {
      // notify user that error happened
      logout();
    });
}

function onLoginToQCloud() {
  const callbackUrl = window.location.pathname;
  window.location = "https://qapp.daskeyboard.com?source=q-documentation"
    + '&callbackUrl=' + callbackUrl;
}

/**
 *
 * redefine jquery post request to use application/json and stringify the data
 */
$.postJSON = function (url, data, callback) {
  return jQuery.ajax({
    'type': 'POST',
    'url': url,
    'contentType': 'application/json',
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
  });
};

/**
 *
 * redefine jquery post request to use application/json and stringify the data
 */
$.getJSON = function (url, apiKey, callback) {
  return jQuery.ajax({
    'type': 'GET',
    'url': url,
    headers: { 'X-API-KEY': apiKey },
    'contentType': 'application/json',
    'dataType': 'json',
    'success': callback
  });
};

/**
 * Get API key from the Q Cloud using a one time login token and store it in the local
 * storage
 * @param {*} loginToken
 */
function getAPIKeyWithOneTimeLoginToken(loginToken) {
  if (!loginToken) {
    console.error('no login token provided');
    return;
  }
  $.postJSON("https://q.daskeyboard.com/api/1.0/users/api_key", { oneTimeLoginToken: loginToken })
    // post request success
    .done(function (data) {
      // store apiKey in local storage
      const apiKey = data.value;
      localStorage.setItem('APIKey', apiKey);
      // notify user that the API key was fetched
      displayFlashNotice('info',
        'You are  logged in: sample code will contain your API key so you can copy paste and experiment easily. Enjoy!');
      getCurrentUser();
    })
    // error with POST request
    .fail(function () {
      // notify user that error happened
      updateLoginDisplayElements(undefined);
      replaceALLApiKeyByStoredApiKey(undefined);
      displayFlashNotice('error', 'Error while fetching API KEY');
    });
}

function getStoredAPIKey() {
  const apiKey = localStorage.getItem('APIKey');
  return apiKey;
}

/************************************************************************
 *
 *  code used to display a notice popover for the user
 *
 *
 * ***********************************************************************
 */

/**
 * Displays a bootstrap alert depending on the noticeType
 * noticeType can be 'info' and the bootstrap alert will be blue
 * or can be 'error' and the bootstrap alert will be red
 * @param {*} noticeType
 * @param {*} message
 */
function displayFlashNotice(noticeType, message) {
  // get the bootstrap alert div
  const flashNoticeDivId = '#flash-notice-section';
  const flashNoticeMessageId = '#flash-notice-message';
  const alertDiv = $(flashNoticeDivId);
  const alertMessage = $(flashNoticeMessageId);

  if (alertDiv && alertMessage) {
    // populate the content of the div with the message
    alertMessage.html(message);
    // remove the previous class lists
    alertDiv.removeClass(['alert-info', 'alert-danger']);
    switch (noticeType) {
      case 'info':
        alertDiv.addClass(['alert-primary']);
        break;

      case 'error':
        alertDiv.addClass(['alert-danger']);
        break;
    }

    // show the div
    alertDiv.css('display', 'block');

  }
}

/**
 * closes the flash notice component by hiding the element in the DOM
 */
function onCloseFlashNotice() {
  const flashNoticeDivId = 'flash-notice-section';
  const alertDiv = document.getElementById(flashNoticeDivId);
  if (alertDiv) {
    alertDiv.style.display = 'none';
  }
}

/************************************************************************
 *
 *  END OF code used to display a notice popover for the user
 *
 *
 * ***********************************************************************
 */

function removeQueryParamsFromUrl() {
  var newurl = window.location.pathname;
  window.history.pushState({ path: newurl }, '', newurl);
}

/**
 * Remove the stored apiKey
 * and update the views to display a none logged user
 */
function logout() {

  // remove api key and email from local storage
  localStorage.removeItem('APIKey');
  localStorage.removeItem('email');

  // reload page
  window.location.reload();
}

function updateLoginDisplayElements(currentUserEmail) {
  if (currentUserEmail) {
    // hide login message
    $('#header-login-message').css('display', 'none');
    // display welcome message
    $('#header-welcome-message').text('Welcome ' + currentUserEmail);
    $('#header-welcome-message').css('display', 'inline-block');
    $('#header-welcome-message').css('font-weight', 'bold');
    // display logout action
    $('#logout-action').css('display', 'inline-block');
  } else {
    // hide logout action
    $('#logout-action').css('display', 'none');
    // hide welcome message
    $('#header-welcome-message').css('display', 'none');
    // display login message
    $('#header-login-message').css('display', 'inline-block');
  }
}

/************************************************************************
 *
 *  code used to display the dynamic content in the code pages
 *
 *
 * ***********************************************************************
 */

function formatJSONCode() {
  var jsonCode = document.getElementsByClassName('json-code');
  for (var i = 0; i < jsonCode.length; i++) {
    var content = jsonCode[i].textContent;
    jsonCode[i].innerHTML = syntaxHighlight(content);
  }
};

function replaceALLApiKeyByStoredApiKey(apiKey) {
  $("body").children().each(function () {
    if (!apiKey) {

      // TODO change with the root to the API Key explanation page
      const apiKeyMoreDetails = window.location.origin + '/get-started/download/';
      $(this).html($(this).html().replace(/\$API_KEY/g,
        // ""
        // + "login to retrieve your api-key"));
        "<button class='login-code-button' data-toggle='tooltip' data-html='true' title='This is a sample API key. Login to see examples "
        + "pre-filled with your keys.'>login to retrieve your api-key</button>"));
    } else {
      $(this).html($(this).html().replace(/\$API_KEY/g, apiKey));
    }
  });
}

/**
 * Use to beautify json code
 * @param {*} json
 */
function syntaxHighlight(json) {
  if (typeof json != 'string') {
    json = JSON.stringify(json, undefined, 2);
  }
  json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
  return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
    var cls = 'number';
    if (/^"/.test(match)) {
      if (/:$/.test(match)) {
        cls = 'key';
      } else {
        cls = 'string';
      }
    } else if (/true|false/.test(match)) {
      cls = 'boolean';
    } else if (/null/.test(match)) {
      cls = 'null';
    }
    // if (cls === 'string') {
    //   return '' + match + '
';
    // } else {
    //   return '' + match + '';
    // }
    return '' + match + '';
  });
}

/************************************************************************
 *
 *  End of code used to display the dynamic content in the code pages
 *
 *
 * ***********************************************************************
 */

/**
 * Detects the os platform and architechture and change the download link of the Q software
 * depending on this informations
 */
function loadDownloadLinkDependingOnOsArchitechture() {
  if (navigator.platform.includes('Win32')) {
    if (navigator.userAgent.indexOf("WOW64") != -1 ||
      navigator.userAgent.indexOf("Win64") != -1) {
      $('#windows-software-download-link').attr("href", "https://s3-us-west-2.amazonaws.com/q-desktop/2.0.1/Das-Keyboard-Q-x64-Setup-2.0.1.exe");
      $('#windows-software-download-link').append(" 64 bit");

    } else {
      $('#windows-software-download-link').attr("href", "https://s3-us-west-2.amazonaws.com/q-desktop/2.0.1/Das-Keyboard-Q-ia32-Setup-2.0.1.exe");
      $('#windows-software-download-link').append(" 32 bit");

    }
  }
}

$(document).ready(function () {
  const email = localStorage.getItem('email');
  const apiKey = getStoredAPIKey();
  console.log('apiKey', apiKey);
  console.log('email', email);

  if (email && apiKey) {
    updateLoginDisplayElements(email);
    replaceALLApiKeyByStoredApiKey(apiKey);
  } else {
    //get ApiKey if one time login token present in url
    getApiKeyIfOneTimeLoginTokenIsPresent();
  }

  formatJSONCode();
 loadDownloadLinkDependingOnOsArchitechture();

  // enable bootstrap tooltips
  $('[data-toggle="tooltip"]').tooltip();

  // enable bootstrap popovers
  $('[data-toggle="popover"]').popover();

  $('.popover-dismiss').popover({
    trigger: 'focus'
  });
});
<|endoftext|>