<commit_before>// #Advanced Views
// This example will cover how to create and add sorts to collections, how to create custom view types with
// custom selectionFns, and some common PourOver view tricks

// First, let's use our set up from the [basic example](/pourover/examples/examples_build/basic_pourover_ing.html)

var monsters = [{name: "sphinx", mythology: "greek", eyes: 2, sex: "f", hobbies: ["riddles","sitting","being a wonder"]},
                {name: "hydra", mythology: "greek", eyes: 18, sex: "m", hobbies: ["coiling","terrorizing","growing"]},
                {name: "huldra", mythology: "norse", eyes: 2, sex: "f", hobbies: ["luring","terrorizing"]},
                {name: "cyclops", mythology: "greek", eyes: 1, sex: "m", hobbies: ["staring","terrorizing"]},
                {name: "fenrir", mythology: "norse", eyes: 2, sex: "m", hobbies: ["growing","god-killing"]},
                {name: "medusa",  mythology: "greek", eyes: 2, sex: "f", hobbies: ["coiling","staring"]}];

var collection = new PourOver.Collection(monsters);

var mythology_filter = PourOver.makeExactFilter("mythology", ["greek","norse"]);
var gender_filter = PourOver.makeExactFilter("sex", ["m","f"]);
var hobbies_filter = PourOver.makeInclusionFilter("hobbies",["riddles",
                                                             "sitting",
                                                             "being a wonder",
                                                             "coiling",
                                                             "terrorizing",
                                                             "growing",
                                                             "luring",
                                                             "staring",
                                                             "god-killing"]);

collection.addFilters([mythology_filter, gender_filter, hobbies_filter]);

var view = new PourOver.View("default_view", collection);

// ### Sorting

// #### Creating a custom sort
// To create a custom sort, we generally extend the Sort object with a `fn`, the comparator function used to order items.
// We also specify which attribute the sort operates over -- what it sorts with respect to --  with the `attr` attribute.
// Then, we instantiate our new sort. This attr field has no special signifigance other than convention. You must still
// manually extract values in your sort function.
var RevNameSort = PourOver.Sort.extend({
    fn: function(a,b){
        var x = a.name, y = b.name;
        if (y < x){
          return -1;
        } else if (y > x){
          return 1;
        } else {
          return 0;
        }
    }
});
var rev_name_sort = new RevNameSort("rev_name");

// Like we do with filters, we add the sort to the collection. This indexes the sort of the current items. Additionally, `addSorts`
// binds collection changes to a re-sorting operation.

collection.addSorts([rev_name_sort]);

// Once we have added the sort we can call the `setSort` method of a view with the name of a sort that has been added to its collection.
// Even though sorts are added to collections, every view can set its sort independently.

view.setSort("rev_name");

// Now, we when call `view.getCurrentItems`, the items will be sorted accordingly.
view.getCurrentItems();

// ### Sort Types

// PourOver ships with two default sorts, `explicitSort` and `reverseCidSort`

// `explicitSort` models a sort in which an explicit order of cids is passed. This is how we model
// orders that have no functional reference to items' attributes. `explicitSort`s are used for, among other things,
// user-defined orders or arbitrary orders.
// The `makeExplicitSort` constructor takes `(sort_name: String, collection: Collection, attribute_represented_in_order: String, order: [attribute])`
// Here, we define an explicit sort by passing in the order of the items, identified by their name attribute.
// Generally, the attribute that you store an `explicitSort` on will be a GUID.

var my_slideshow_sort = PourOver.makeExplicitSort("my_slideshow_order",collection,"name",["hydra","huldra","medusa","cyclops","fenrir","sphinx"])

// `reverseCidSort` is the reverse of the default sort. It sorts your items in the reverse of the order in which they were put into the collection

var rev_cid_sort = PourOver.makeReverseCidSort("rev_sort",collection)
collection.addSorts([my_slideshow_sort,rev_cid_sort])
view.setSort("my_slideshow_order")

// ### Custom View types

// Changing our attention from sorts to the views they influence, how do we define custom views: views that combine their filters in a non-standard ways.
// Keeping with the Backbone-ese pattern of extension, we simply extend the `PourOver.View` object with a new selectionFn.
// *NOTE: The selectionFn must return a `MatchSet`, not a raw array of items. This `MatchSet` gets cached on the view for subsequent queries/renders.*
// Here, we create a custom view that takes the current query on "mythology" subtracts the current query on sex and ignores hobbies entirely.
// This could model a UI in which the user selects a mythology facet to view, a sex to hide and is unable to filter on hobby.
var CustomView = PourOver.View.extend({
    selectionFn: function(){
        var mythology_query = collection.filters.mythology.current_query,
           sex_query  = collection.filters.sex.current_query;
        return mythology_query.not(sex_query);
    },
    render: function(){
        current_items = this.getCurrentItems();
        console.log(current_items);
    }
})
var custom_view = new CustomView("custom_view",collection);
custom_view.on("update",custom_view.render);

// Now, `custom_view.getCurrentItems()` will ignore the hobby query and return the result of the mythology query - that of sex.
// Whenever any query changes or the collection changes, the custom view will "render" this result

// ### Pattern: User favorites

// Say we wanted to have an app that renders a grid of items that users can filter. However, we also want to add a pop-up that will show the
// items that users have starred. Can we do this with a single collection and multiple views?

// Absolutely.

// First, lets make a new collection so as to not interfere with the previous part of the example
var collection_two = new PourOver.Collection(monsters);

// Now, we will need three new objects:
// - a filter that represents the objects a user has selected, a favorites filter
// - a grid view that intersects the hobby, mythology, and sex queries but ignores the favorites filter
// - a favorites view that ignores every filter but the favorites filter

// We use `manualFilter` to create the favorites filter. A `manualFilter` is exactly what it sounds like: a filter that you manually
// control, adding and removing items to specify which items it selects.
var favorites_filter = PourOver.makeManualFilter("favorites");
collection_two.addFilters([mythology_filter, gender_filter, hobbies_filter, favorites_filter]);

// When a user favorites an item, say the 2nd and 4th items in our collection, the hydra and the cyclops (this would happen in a callback)
var user_selection_cids = [1,3];
collection_two.filters.favorites.addItems(user_selection_cids);

// Now, we make a grid view that ignores the favorites filter
var GridView = PourOver.View.extend({
    selectionFn: function(){
        var mythology_query = collection_two.filters.mythology.current_query,
            sex_query  = collection_two.filters.sex.current_query,
            hobbies_query = collection_two.filters.hobbies.current_query;
        return mythology_query.and(sex_query).and(hobbies_query);
    }
});
var grid_view = new GridView("grid_view",collection_two)

// Finally, we make a favorite view that only considers the favorites filter
var FavView = PourOver.View.extend({
    selectionFn: function(){
        return collection_two.filters.favorites.current_query;
    }
});
var fav_view = new FavView("fav_view",collection_two)

// Now, `grid_view.getCurrentItems()` will only be affected by queries on mythology, sex, or hobbies.
// `fav_view.getCurrentItems()` will only be affected by queries (`addItems` and `removeItems`) on the favorites filter
<commit_msg>fix sort docs<commit_after>// #Advanced Views
// This example will cover how to create and add sorts to collections, how to create custom view types with
// custom selectionFns, and some common PourOver view tricks

// First, let's use our set up from the [basic example](/pourover/examples/examples_build/basic_pourover_ing.html)

var monsters = [{name: "sphinx", mythology: "greek", eyes: 2, sex: "f", hobbies: ["riddles","sitting","being a wonder"]},
                {name: "hydra", mythology: "greek", eyes: 18, sex: "m", hobbies: ["coiling","terrorizing","growing"]},
                {name: "huldra", mythology: "norse", eyes: 2, sex: "f", hobbies: ["luring","terrorizing"]},
                {name: "cyclops", mythology: "greek", eyes: 1, sex: "m", hobbies: ["staring","terrorizing"]},
                {name: "fenrir", mythology: "norse", eyes: 2, sex: "m", hobbies: ["growing","god-killing"]},
                {name: "medusa",  mythology: "greek", eyes: 2, sex: "f", hobbies: ["coiling","staring"]}];

var collection = new PourOver.Collection(monsters);

var mythology_filter = PourOver.makeExactFilter("mythology", ["greek","norse"]);
var gender_filter = PourOver.makeExactFilter("sex", ["m","f"]);
var hobbies_filter = PourOver.makeInclusionFilter("hobbies",["riddles",
                                                             "sitting",
                                                             "being a wonder",
                                                             "coiling",
                                                             "terrorizing",
                                                             "growing",
                                                             "luring",
                                                             "staring",
                                                             "god-killing"]);

collection.addFilters([mythology_filter, gender_filter, hobbies_filter]);

var view = new PourOver.View("default_view", collection);

// ### Sorting

// #### Creating a custom sort
// To create a custom sort, we generally extend the Sort object with a `fn`, the comparator function used to order items.
// We also specify which attribute the sort operates over -- what it sorts with respect to --  with the `attr` attribute.
// Then, we instantiate our new sort. This attr field has no special signifigance other than convention. You must still
// manually extract values in your sort function.
var RevNameSort = PourOver.Sort.extend({
    fn: function(a,b){
        var x = a.name, y = b.name;
        if (y < x){
          return -1;
        } else if (y > x){
          return 1;
        } else {
          return 0;
        }
    }
});

// We create a new sort and we associate it with attrs, so that when those attributes change -- if an item's name can change --
// then the sort will rebuild itself.
var rev_name_sort = new RevNameSort("rev_name", {associated_attrs: ["name"]});

// Like we do with filters, we add the sort to the collection. This indexes the sort of the current items. Additionally, `addSorts`
// binds collection changes to a re-sorting operation.

collection.addSorts([rev_name_sort]);

// Once we have added the sort we can call the `setSort` method of a view with the name of a sort that has been added to its collection.
// Even though sorts are added to collections, every view can set its sort independently.

view.setSort("rev_name");

// Now, we when call `view.getCurrentItems`, the items will be sorted accordingly.
view.getCurrentItems();

// ### Sort Types

// PourOver ships with two default sorts, `explicitSort` and `reverseCidSort`

// `explicitSort` models a sort in which an explicit order of cids is passed. This is how we model
// orders that have no functional reference to items' attributes. `explicitSort`s are used for, among other things,
// user-defined orders or arbitrary orders.
// The `makeExplicitSort` constructor takes `(sort_name: String, collection: Collection, attribute_represented_in_order: String, order: [attribute])`
// Here, we define an explicit sort by passing in the order of the items, identified by their name attribute.
// Generally, the attribute that you store an `explicitSort` on will be a GUID.

var my_slideshow_sort = PourOver.makeExplicitSort("my_slideshow_order",collection,"name",["hydra","huldra","medusa","cyclops","fenrir","sphinx"])

// `reverseCidSort` is the reverse of the default sort. It sorts your items in the reverse of the order in which they were put into the collection

var rev_cid_sort = PourOver.makeReverseCidSort("rev_sort",collection)
collection.addSorts([my_slideshow_sort,rev_cid_sort])
view.setSort("my_slideshow_order")

// ### Custom View types

// Changing our attention from sorts to the views they influence, how do we define custom views: views that combine their filters in a non-standard ways.
// Keeping with the Backbone-ese pattern of extension, we simply extend the `PourOver.View` object with a new selectionFn.
// *NOTE: The selectionFn must return a `MatchSet`, not a raw array of items. This `MatchSet` gets cached on the view for subsequent queries/renders.*
// Here, we create a custom view that takes the current query on "mythology" subtracts the current query on sex and ignores hobbies entirely.
// This could model a UI in which the user selects a mythology facet to view, a sex to hide and is unable to filter on hobby.
var CustomView = PourOver.View.extend({
    selectionFn: function(){
        var mythology_query = collection.filters.mythology.current_query,
           sex_query  = collection.filters.sex.current_query;
        return mythology_query.not(sex_query);
    },
    render: function(){
        current_items = this.getCurrentItems();
        console.log(current_items);
    }
})
var custom_view = new CustomView("custom_view",collection);
custom_view.on("update",custom_view.render);

// Now, `custom_view.getCurrentItems()` will ignore the hobby query and return the result of the mythology query - that of sex.
// Whenever any query changes or the collection changes, the custom view will "render" this result

// ### Pattern: User favorites

// Say we wanted to have an app that renders a grid of items that users can filter. However, we also want to add a pop-up that will show the
// items that users have starred. Can we do this with a single collection and multiple views?

// Absolutely.

// First, lets make a new collection so as to not interfere with the previous part of the example
var collection_two = new PourOver.Collection(monsters);

// Now, we will need three new objects:
// - a filter that represents the objects a user has selected, a favorites filter
// - a grid view that intersects the hobby, mythology, and sex queries but ignores the favorites filter
// - a favorites view that ignores every filter but the favorites filter

// We use `manualFilter` to create the favorites filter. A `manualFilter` is exactly what it sounds like: a filter that you manually
// control, adding and removing items to specify which items it selects.
var favorites_filter = PourOver.makeManualFilter("favorites");
collection_two.addFilters([mythology_filter, gender_filter, hobbies_filter, favorites_filter]);

// When a user favorites an item, say the 2nd and 4th items in our collection, the hydra and the cyclops (this would happen in a callback)
var user_selection_cids = [1,3];
collection_two.filters.favorites.addItems(user_selection_cids);

// Now, we make a grid view that ignores the favorites filter
var GridView = PourOver.View.extend({
    selectionFn: function(){
        var mythology_query = collection_two.filters.mythology.current_query,
            sex_query  = collection_two.filters.sex.current_query,
            hobbies_query = collection_two.filters.hobbies.current_query;
        return mythology_query.and(sex_query).and(hobbies_query);
    }
});
var grid_view = new GridView("grid_view",collection_two)

// Finally, we make a favorite view that only considers the favorites filter
var FavView = PourOver.View.extend({
    selectionFn: function(){
        return collection_two.filters.favorites.current_query;
    }
});
var fav_view = new FavView("fav_view",collection_two)

// Now, `grid_view.getCurrentItems()` will only be affected by queries on mythology, sex, or hobbies.
// `fav_view.getCurrentItems()` will only be affected by queries (`addItems` and `removeItems`) on the favorites filter
<|endoftext|>


<commit_before>'use strict';

const {OP, ADDR_MODE, FLAGS, BRANCH_INSTRUCTION_ALIASES, XOP} = require('./opcodes');
const {bts2n, n2bts, N_TO_BT_DIGIT, BT_DIGIT_TO_N} = require('balanced-ternary');
const {nonary2bts} = require('nonary');
const {sv2bts} = require('base27');
const {get_trit, slice_trits} = require('trit-getset');

// assembler

// syntax
// opcode operands
//
// operands
// # = immediate mode
// % = trits, 0i1, base 3                    iiiii 5
// no prefix = decimal, base 10
// $ = nonary, base 9, each digit two trits aabbcc 3
// & = base 27, each digit three trits       aabbb 2

function assemble(lines) {
  // TODO: port to run on cpu (self-hosting)
  let output = [];

  let emit = function(tryte) {
    console.log('emit',n2bts(tryte));
    output.push(tryte);
  }

  let symbols = {};

  for (let line of lines) {
    let tokens = line.split(/\s+/);
    let opcode = tokens[0];
    let operand = tokens[1];
    let addressing_mode;

    // TODO: comments, ; to end-of-line
    // TODO: labels, foo:, and resolving to 10-trit
    // TODO: defines, .equ, constants
    // TODO: .org, start assembly

    if (operand !== undefined) {

      if (operand === 'A') {
        addressing_mode = ADDR_MODE.ACCUMULATOR;
      } else {
        if (operand.charAt(0) === '#') {
          addressing_mode = ADDR_MODE.IMMEDIATE;
          operand = operand.substring(1);
        } else {
          addressing_mode = ADDR_MODE.ABSOLUTE;
        }

        switch(operand.charAt(0)) {
          case '%': // base 3, trits (%iiiii to %11111)
            operand = bts2n(operand.substring(1));
            break;
          case '$': // base 9, nonary ($imm to $144)
            operand = bts2n(nonary2bts(operand.substring(1)));
            break;
          case '&': // base 27, septemvigesimal (&QZ to &DM)
            operand = bts2n(sv2bts(operand.substring(1)));
            break;
          // TODO: ' for trit-text characters

          default:
            operand = Number.parseInt(operand, 10);
        }

        if (addressing_mode === ADDR_MODE.IMMEDIATE) {
          if (operand < -121 || operand > 121) {
            throw new Error('immediate operand out of 5-trit range: '+operand+', in line: '+line);
          }
        } else if (addressing_mode === ADDR_MODE.ABSOLUTE) {
          // %iiiiiiiiii to %1111111111
          // $mmmmm to $44444
          // &NZZZ to &AMMM
          if (operand < -29524 || operand > 29524) {
            throw new Error('absolute operand out of 10-trit range: '+operand+', in line: '+line);
          }
        }
      }
    }

    console.log(tokens,operand);

    if (opcode.charAt(0) === '.') {
      // assembler directives
      // TODO
    } else if (OP[opcode] !== undefined) {
      // alu
      let opcode_value = OP[opcode]; // aaab0 3-trits

      let tryte = opcode_value * Math.pow(3,2) +
        addressing_mode * Math.pow(3,1) +
        0;

      emit(tryte);

      switch(addressing_mode) {
        case ADDR_MODE.IMMEDIATE:
          if (!Number.isInteger(operand)) {
            throw new Error('opcode '+opcode+' (immediate) requires operand: '+operand);
          }

          emit(operand);
          break;

        case ADDR_MODE.ABSOLUTE:
          if (!Number.isInteger(operand)) {
            throw new Error('opcode '+opcode+' (absolute) requires operand: '+operand);
          }

          // TODO: endian?
          emit(slice_trits(operand, 0, 5));
          emit(slice_trits(operand, 5, 10));
          break;
      }
    } else if (XOP[opcode] !== undefined) {
      let opcode_value = XOP[opcode]; // aaaai 4-trits

      let tryte = opcode_value * Math.pow(3,1) + (-1);
      emit(tryte);
    } else if (opcode.charAt(0) === 'B') {
      // TODO: branch, beq (s=0), bne (s!=0) br s>0, s=0, s<0 brsen brgz brlp
      // convenience aliases
      if (BRANCH_INSTRUCTION_ALIASES[opcode]) opcode = BRANCH_INSTRUCTION_ALIASES[opcode];

      if (opcode.charAt(1) === 'R' && opcode.length === 5) { // BR opcodes
        let flag = opcode.charAt(2);
        let direction = opcode.charAt(3);
        let compare = opcode.charAt(4);

        let flag_value = FLAGS[flag];
        if (flag_value === undefined) {
          throw new Error('invalid flag '+flag+' in branch instruction '+opcode);
        }
        let direction_value = {
          L:-1, '<':-1,
          E:0, '=':0,
          N:1, '!':1
        }[direction];
        if (direction_value === undefined) {
          throw new Error('invalid direction '+direction+' in branch instruction '+opcode);
        }
        let compare_value = {N:-1, Z:0, P:1}[compare];
        if (compare_value === undefined) {
          throw new Error('invalid comparison trit '+compare_value+' in branch instruction '+opcode);
        }
        console.log(`branch opcode=${opcode}, flag=${flag_value}/${flag}, direction=${direction_value}/${direction} compare=${compare_value}/${compare}`);;

        // aabc1 a=flag, b=direction, c=trit for comparison
        let tryte = flag_value * Math.pow(3,3) +
          direction_value * Math.pow(3,2) +
          compare_value * Math.pow(3,1) +
          1;
        emit(tryte);
        emit(operand);
      }
    }
  }

  console.log('assembled '+lines.length+' lines into '+output.length+' trytes');
  console.log(output);
  return output;
}

module.exports = assemble;
<commit_msg>Assembler detect non-numeric operands<commit_after>'use strict';

const {OP, ADDR_MODE, FLAGS, BRANCH_INSTRUCTION_ALIASES, XOP} = require('./opcodes');
const {bts2n, n2bts, N_TO_BT_DIGIT, BT_DIGIT_TO_N} = require('balanced-ternary');
const {nonary2bts} = require('nonary');
const {sv2bts} = require('base27');
const {get_trit, slice_trits} = require('trit-getset');

// assembler

// syntax
// opcode operands
//
// operands
// # = immediate mode
// % = trits, 0i1, base 3                    iiiii 5
// no prefix = decimal, base 10
// $ = nonary, base 9, each digit two trits aabbcc 3
// & = base 27, each digit three trits       aabbb 2

function assemble(lines) {
  // TODO: port to run on cpu (self-hosting)
  let output = [];

  let emit = function(tryte) {
    console.log('emit',n2bts(tryte));
    output.push(tryte);
  }

  let symbols = {};

  for (let line of lines) {
    let tokens = line.split(/\s+/);
    let opcode = tokens[0];
    let operand = tokens[1];
    let addressing_mode;

    // TODO: comments, ; to end-of-line
    // TODO: labels, foo:, and resolving to 10-trit
    // TODO: defines, .equ, constants
    // TODO: .org, start assembly

    if (operand !== undefined) {

      if (operand === 'A') {
        addressing_mode = ADDR_MODE.ACCUMULATOR;
      } else {
        if (operand.charAt(0) === '#') {
          addressing_mode = ADDR_MODE.IMMEDIATE;
          operand = operand.substring(1);
        } else {
          addressing_mode = ADDR_MODE.ABSOLUTE;
        }

        switch(operand.charAt(0)) {
          case '%': // base 3, trits (%iiiii to %11111)
            operand = bts2n(operand.substring(1));
            break;
          case '$': // base 9, nonary ($imm to $144)
            operand = bts2n(nonary2bts(operand.substring(1)));
            break;
          case '&': // base 27, septemvigesimal (&QZ to &DM)
            operand = bts2n(sv2bts(operand.substring(1)));
            break;
          // TODO: ' for trit-text characters

          default:
            operand = Number.parseInt(operand, 10);
            if (Number.isNaN(operand)) {
              throw new Error('invalid non-numeric operand: '+operand+', in line: '+line);
            }
        }

        if (addressing_mode === ADDR_MODE.IMMEDIATE) {
          if (operand < -121 || operand > 121) {
            throw new Error('immediate operand out of 5-trit range: '+operand+', in line: '+line);
          }
        } else if (addressing_mode === ADDR_MODE.ABSOLUTE) {
          // %iiiiiiiiii to %1111111111
          // $mmmmm to $44444
          // &NZZZ to &AMMM
          if (operand < -29524 || operand > 29524) {
            throw new Error('absolute operand out of 10-trit range: '+operand+', in line: '+line);
          }
        }
      }
    }

    console.log(tokens,operand);

    if (opcode.charAt(0) === '.') {
      // assembler directives
      // TODO
    } else if (OP[opcode] !== undefined) {
      // alu
      let opcode_value = OP[opcode]; // aaab0 3-trits

      let tryte = opcode_value * Math.pow(3,2) +
        addressing_mode * Math.pow(3,1) +
        0;

      emit(tryte);

      switch(addressing_mode) {
        case ADDR_MODE.IMMEDIATE:
          if (!Number.isInteger(operand)) {
            throw new Error('opcode '+opcode+' (immediate) requires operand: '+operand+', in line: '+line);
          }

          emit(operand);
          break;

        case ADDR_MODE.ABSOLUTE:
          if (!Number.isInteger(operand)) {
            throw new Error('opcode '+opcode+' (absolute) requires operand: '+operand+', in line: '+line);
          }

          // TODO: endian?
          emit(slice_trits(operand, 0, 5));
          emit(slice_trits(operand, 5, 10));
          break;
      }
    } else if (XOP[opcode] !== undefined) {
      let opcode_value = XOP[opcode]; // aaaai 4-trits

      let tryte = opcode_value * Math.pow(3,1) + (-1);
      emit(tryte);
    } else if (opcode.charAt(0) === 'B') {
      // TODO: branch, beq (s=0), bne (s!=0) br s>0, s=0, s<0 brsen brgz brlp
      // convenience aliases
      if (BRANCH_INSTRUCTION_ALIASES[opcode]) opcode = BRANCH_INSTRUCTION_ALIASES[opcode];

      if (opcode.charAt(1) === 'R' && opcode.length === 5) { // BR opcodes
        let flag = opcode.charAt(2);
        let direction = opcode.charAt(3);
        let compare = opcode.charAt(4);

        let flag_value = FLAGS[flag];
        if (flag_value === undefined) {
          throw new Error('invalid flag '+flag+' in branch instruction '+opcode);
        }
        let direction_value = {
          L:-1, '<':-1,
          E:0, '=':0,
          N:1, '!':1
        }[direction];
        if (direction_value === undefined) {
          throw new Error('invalid direction '+direction+' in branch instruction '+opcode);
        }
        let compare_value = {N:-1, Z:0, P:1}[compare];
        if (compare_value === undefined) {
          throw new Error('invalid comparison trit '+compare_value+' in branch instruction '+opcode);
        }
        console.log(`branch opcode=${opcode}, flag=${flag_value}/${flag}, direction=${direction_value}/${direction} compare=${compare_value}/${compare}`);;

        // aabc1 a=flag, b=direction, c=trit for comparison
        let tryte = flag_value * Math.pow(3,3) +
          direction_value * Math.pow(3,2) +
          compare_value * Math.pow(3,1) +
          1;
        emit(tryte);
        emit(operand);
      }
    }
  }

  console.log('assembled '+lines.length+' lines into '+output.length+' trytes');
  console.log(output);
  return output;
}

module.exports = assemble;
<|endoftext|>


<commit_before>/*
 * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

//node.js deps
var gpio = require("pi-gpio");
const deviceModule = require('..').device;
const cmdLineProcess = require('./lib/cmdline');
//npm deps

//app deps
gpio.open(18, "output", function(err) {		// Open pin 18 for output
   console.log("10 open");
   gpio.write(18, 1, function() {			// Set pin 18 high (1)
      // gpio.close(18);
      console.log("18 write 1");
   });
});

function processTest(args) {
   //
   // The device module exports an MQTT instance, which will attempt
   // to connect to the AWS IoT endpoint configured in the arguments.
   // Once connected, it will emit events which our application can
   // handle.
   //
   const device = deviceModule({
      keyPath: args.privateKey,
      certPath: args.clientCert,
      caPath: args.caCert,
      clientId: args.clientId,
      region: args.region,
      baseReconnectTimeMs: args.baseReconnectTimeMs,
      keepalive: args.keepAlive,
      protocol: args.Protocol,
      port: args.Port,
      host: args.Host,
      debug: args.Debug
   });

   var timeout;
   var count = 0;
   const minimumDelay = 250;

   if (args.testMode === 1) {
      device.subscribe('topic_1');
   } else {
      device.subscribe('topic_2');
   }
   if ((Math.max(args.delay, minimumDelay)) !== args.delay) {
      console.log('substituting ' + minimumDelay + 'ms delay for ' + args.delay + 'ms...');
   }
   timeout = setInterval(function() {
      count++;

      if (args.testMode === 1) {
         device.publish('topic_2', JSON.stringify({
            mode1Process: count
         }));
      } else {
         device.publish('topic_1', JSON.stringify({
            mode2Process: count
         }));
      }
   }, Math.max(args.delay, minimumDelay)); // clip to minimum

   //
   // Do a simple publish/subscribe demo based on the test-mode passed
   // in the command line arguments.  If test-mode is 1, subscribe to
   // 'topic_1' and publish to 'topic_2'; otherwise vice versa.  Publish
   // a message every four seconds.
   //
   device
      .on('connect', function() {
         console.log('connected');
      });
   device
      .on('close', function() {
         console.log('close');
      });
   device
      .on('reconnect', function() {
         console.log('reconnect');
      });
   device
      .on('offline', function() {
         console.log('offline');
      });
   device
      .on('error', function(error) {
         console.log('error', error);
      });
   device
      .on('message', function(topic, payload) {
         console.log('message', topic, payload.toString());
      });
}

module.exports = cmdLineProcess;

if (require.main === module) {
   cmdLineProcess('connect to the AWS IoT service and publish/subscribe to topics using MQTT, test modes 1-2',
      process.argv.slice(2), processTest);
}<commit_msg>maybe<commit_after>/*
 * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

//node.js deps
var gpio = require('gpio');
//npm deps

//app deps
const deviceModule = require('..').device;
const cmdLineProcess = require('./lib/cmdline');

//begin module

var gpio = require("gpio");
var gpio18, gpio24, intervalTimer;

// Flashing lights if LED connected to GPIO22
gpio18 = gpio.export(18, {
   ready: function() {
      intervalTimer = setInterval(function() {
         gpio18.set();
         setTimeout(function() { gpio18.reset(); }, 500);
      }, 1000);
   }
});

// Lets assume a different LED is hooked up to pin 4, the following code
// will make that LED blink inversely with LED from pin 22
gpio24 = gpio.export(23, {
   ready: function() {
      // bind to gpio18's change event
      gpio18.on("change", function(val) {
         gpio24.set(1 - val); // set gpio24 to the opposite value
      });
   }
});

// reset the headers and unexport after 10 seconds
setTimeout(function() {
   clearInterval(intervalTimer);          // stops the voltage cycling
   gpio18.removeAllListeners('change');   // unbinds change event
   gpio18.reset();                        // sets header to low
   gpio18.unexport();                     // unexport the header

   gpio24.reset();
   gpio24.unexport(function() {
      // unexport takes a callback which gets fired as soon as unexporting is done
      process.exit(); // exits your node program
   });
}, 10000)

function processTest(args) {
   //
   // The device module exports an MQTT instance, which will attempt
   // to connect to the AWS IoT endpoint configured in the arguments.
   // Once connected, it will emit events which our application can
   // handle.
   //
   const device = deviceModule({
      keyPath: args.privateKey,
      certPath: args.clientCert,
      caPath: args.caCert,
      clientId: args.clientId,
      region: args.region,
      baseReconnectTimeMs: args.baseReconnectTimeMs,
      keepalive: args.keepAlive,
      protocol: args.Protocol,
      port: args.Port,
      host: args.Host,
      debug: args.Debug
   });

   var timeout;
   var count = 0;
   const minimumDelay = 250;

   if (args.testMode === 1) {
      device.subscribe('topic_1');
   } else {
      device.subscribe('topic_2');
   }
   if ((Math.max(args.delay, minimumDelay)) !== args.delay) {
      console.log('substituting ' + minimumDelay + 'ms delay for ' + args.delay + 'ms...');
   }
   timeout = setInterval(function() {
      count++;

      if (args.testMode === 1) {
         device.publish('topic_2', JSON.stringify({
            mode1Process: count
         }));
      } else {
         device.publish('topic_1', JSON.stringify({
            mode2Process: count
         }));
      }
   }, Math.max(args.delay, minimumDelay)); // clip to minimum

   //
   // Do a simple publish/subscribe demo based on the test-mode passed
   // in the command line arguments.  If test-mode is 1, subscribe to
   // 'topic_1' and publish to 'topic_2'; otherwise vice versa.  Publish
   // a message every four seconds.
   //
   device
      .on('connect', function() {
         console.log('connected');
      });
   device
      .on('close', function() {
         console.log('close');
      });
   device
      .on('reconnect', function() {
         console.log('reconnect');
      });
   device
      .on('offline', function() {
         console.log('offline');
      });
   device
      .on('error', function(error) {
         console.log('error', error);
      });
   device
      .on('message', function(topic, payload) {
         console.log('message', topic, payload.toString());
      });
}

module.exports = cmdLineProcess;

if (require.main === module) {
   cmdLineProcess('connect to the AWS IoT service and publish/subscribe to topics using MQTT, test modes 1-2',
      process.argv.slice(2), processTest);
}<|endoftext|>


<commit_before>/* Wrapper around tinymce to provide default values */

(function($) {

  $.enstinymce = function (el) {

    el = $(el);
    var height = el[0].className.match(/_tinymce_h_([0-9]+)/);
    var width  = el[0].className.match(/_tinymce_w_([0-9]+)/);
    el.tinymce({
      script_url: '/tiny_mce/jscripts/tiny_mce/tiny_mce.js',
      theme: "advanced",
      theme_advanced_buttons1: "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,formatselect,|,cut,copy,paste,|,charmap",
      theme_advanced_buttons2: "bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,cleanup,code,|,removeformat,visualaid,|,sub,sup,",
      theme_advanced_buttons3: "",
      theme_advanced_toolbar_location: "top",
      height: height ? height[1] : 300,
      width: width ? width[1] : 500
    });
  };

  $.fn.enstinymce = function () {

    this.each(function() {
      $.enstinymce(this);
    });

    return this;

  };
})(jQuery);
<commit_msg><commit_after>/* Wrapper around tinymce to provide default values */

(function($) {

  $.enstinymce = function (el) {

    el = $(el);
    var height = el[0].className.match(/_tinymce_h_([0-9]+)/);
    var width  = el[0].className.match(/_tinymce_w_([0-9]+)/);
    el.tinymce({
      script_url: '/tiny_mce/jscripts/tiny_mce/tiny_mce.js',
      theme: "advanced",
      theme_advanced_buttons1: "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,formatselect,|,cut,copy,paste,|,charmap",
      theme_advanced_buttons2: "bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,cleanup,code,|,removeformat,visualaid,|,sub,sup,",
      theme_advanced_buttons3: "",
      theme_advanced_toolbar_location: "top",
      height: height ? height[1] : 300,
      width: width ? width[1] : 500,
      relative_urls: false,
      convert_urls: false
    });
  };

  $.fn.enstinymce = function () {

    this.each(function() {
      $.enstinymce(this);
    });

    return this;

  };
})(jQuery);
<|endoftext|>


<commit_before>/* Copyright (c) 2012-2013 The TagSpaces Authors. All rights reserved.
 * Use of this source code is governed by a AGPL3 license that
 * can be found in the LICENSE file. */
define(function(require, exports, module) {
"use strict";

	// Activating browser specific exports modul
	console.log("Loading web.js..");

    var TSCORE = require("tscore");
    var TSPOSTIO = require("tspostioapi");

    require("webdavlib");

    var davClient;

    function connectDav() {
        console.log("Connecting webdav...");
        var useHTTPS = false;
        if(location.href.indexOf("https") === 0) {
            useHTTPS = true;
        }
        davClient = new nl.sara.webdav.Client(location.hostname, useHTTPS, location.port);
    }

    window.setTimeout(connectDav(), 2000);

    function listDirectory(dirPath) {
        console.log("Listing directory: "+dirPath);

        dirPath = encodeURI(dirPath + "/");

        davClient.propfind(
            dirPath, //encodeURI(dirPath),
            function( status, data ) {
                console.log("Dirlist Status:  "+status);
                //console.log("Dirlist Content: "+JSON.stringify(data._responses));
                var anotatedDirList = [],
                    dirList = data._responses,
                    fileName,
                    isDir,
                    filesize,
                    lmdt;

                for (var entry in dirList) {
                    var path = dirList[entry].href;
                    if(dirPath.toLowerCase() !== path.toLowerCase()) {
                        isDir = false;
                        filesize = undefined;
                        lmdt = undefined;
                        //console.log(dirList[entry]._namespaces["DAV:"]);
                        if (typeof dirList[entry]._namespaces["DAV:"].getcontentlength === 'undefined') {
                            isDir = true;
                        } else {
                            filesize = dirList[entry]._namespaces["DAV:"].getcontentlength;
                            lmdt = data._responses[entry]._namespaces["DAV:"].getlastmodified._xmlvalue[0].data;
                        }
                        fileName = getNameForPath(path);
                        anotatedDirList.push({
                            "name": fileName,
                            "isFile": !isDir,
                            "size": filesize,
                            "lmdt": lmdt,
                            "path": decodeURI(path)
                        });
                    }
                }
                TSPOSTIO.listDirectory(anotatedDirList);
            },
            1 //1 , davClient.INFINITY
        );
    }

    function getNameForPath(path) {
        if(path.lastIndexOf("/") == path.length-1) {
            path = path.substring(0,path.lastIndexOf("/"));
        }
        var encodedName = path.substring(path.lastIndexOf("/")+1, path.length);
        return decodeURI(encodedName);
    }

    function isDirectory(path) {
        return path.lastIndexOf("/") == path.length-1;
    }

    var createDirectoryIndex = function(dirPath) {
        console.log("Creating index for directory: "+dirPath);
        TSCORE.showLoadingAnimation();

        var directoryIndex = [];
        TSPOSTIO.createDirectoryIndex(directoryIndex);
    };

    var createDirectoryTree = function(dirPath) {
        console.log("Creating directory index for: "+dirPath);
        TSCORE.showLoadingAnimation();

        var directoyTree = [];
        //console.log(JSON.stringify(directoyTree));
        TSPOSTIO.createDirectoryTree(directoyTree);
    };

    var createDirectory = function(dirPath) {
        console.log("Creating directory: "+dirPath);
        davClient.mkcol(
            encodeURI(dirPath),
            function( status, data, headers ) {
                console.log("Directory Creation Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.createDirectory(dirPath);
            }
        );
    };

    var copyFile = function(filePath, newFilePath) {
        console.log("Copying file: "+filePath+" to "+newFilePath);
        davClient.copy(
            encodeURI(filePath),
            function( status, data, headers ) {
                console.log("Copy File Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.copyFile(filePath, newFilePath);
            },
            encodeURI(newFilePath),
            davClient.FAIL_ON_OVERWRITE
        );
    };

    var renameFile = function(filePath, newFilePath) {
        console.log("Renaming file: "+filePath+" to "+newFilePath);
        davClient.move(
            encodeURI(filePath),
            function( status, data, headers ) {
                console.log("Rename File Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.renameFile(filePath, newFilePath);
            },
            encodeURI(newFilePath),
            davClient.FAIL_ON_OVERWRITE
        );
    };

    var renameDirectory = function(dirPath, newDirName) {
        var newDirPath = TSCORE.TagUtils.extractParentDirectoryPath(dirPath) + TSCORE.dirSeparator + encodeURIComponent(newDirName);
        console.log("Renaming directory: "+dirPath+" to "+newDirPath);
        davClient.move(
            encodeURI(dirPath),
            function( status, data, headers ) {
                console.log("Rename Directory Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.renameDirectory(dirPath, newDirPath);
            },
            encodeURI(newDirPath),
            davClient.FAIL_ON_OVERWRITE
        );
    };

    var loadTextFile = function(filePath) {
        console.log("Loading file: "+filePath);
        davClient.get(
            encodeURI(filePath),
            function( status, data, headers ) {
                console.log("Loading File Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.loadTextFile(data);
            }
            //,customHeaders
        );
        //TODO Perform file locking and unlocking
    };

    var saveTextFile = function(filePath,content,overWrite) {
      console.log("Saving file: "+filePath); //+" content: "+content);

      var isNewFile = false; // = !pathUtils.existsSync(filePath);
      davClient.propfind( encodeURI(filePath), function( status, data ) {
            console.log("Check file exists: Status / Content: "+status+" / "+data);
            if(parseInt(status) === 404) {
                isNewFile = true;
            }
            davClient.put(
                encodeURI(filePath),
                function( status, data, headers ) {
                    console.log("Creating File Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                    TSPOSTIO.saveTextFile(filePath, isNewFile);
                },
                content,
                'application/octet-stream'
            );
        },1
      );
    };

    var saveBinaryFile = function(filePath,content) {
        console.log("Saving binary file: "+filePath); //+" content: "+content);
        /*
         // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
         var myArray = new ArrayBuffer(512);
         var longInt8View = new Uint8Array(myArray);

         for (var i=0; i< longInt8View.length; i++) {
         longInt8View[i] = i % 255;
         }

         var xhr = new XMLHttpRequest;
         xhr.open("POST", url, false);
         xhr.send(myArray);
         */
        var isNewFile = false;
        davClient.propfind( encodeURI(filePath), function( status, data ) {
            console.log("Check file exists: Status / Content: "+status+" / "+data);
            if(parseInt(status) === 404) {
                isNewFile = true;
            }
            if(isNewFile) {
                davClient.put(
                    encodeURI(filePath),
                    function( status, data, headers ) {
                        console.log("Creating File Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                        TSPOSTIO.saveBinaryFile(filePath, isNewFile);
                    },
                    content,
                    'application/octet-stream'
                );
            } else {
                TSCORE.showAlertDialog("File Already Exists.");
            }
        },1);
    };

    var deleteElement = function(path) {
      console.log("Deleting: "+path);
          davClient.remove(
              encodeURI(path),
              function( status, data, headers ) {
                  console.log("Directory/File Deletion Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                  TSPOSTIO.deleteElement(path);
              }
          );
    };

    var deleteDirectory = function(path) {
        console.log("Deleting directory: "+path);
        davClient.remove(
            encodeURI(path),
            function( status, data, headers ) {
                console.log("Directory/File Deletion Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.deleteDirectory(path);
            }
        );
    };

    var checkAccessFileURLAllowed = function() {
        console.log("checkAccessFileURLAllowed function not relevant for webdav..");
    };

    var checkNewVersion = function() {
        console.log("Checking for new version not relevant fot the webdav version");
    };

    var selectDirectory = function() {
        TSCORE.showAlertDialog("Select directory is still not implemented in the webdav edition");
    };

    var openDirectory = function(dirPath) {
        console.log("openDirectory function not relevant for webdav..");
    };

    var openFile = function(filePath) {
        console.log("openFile function not relevant for webdav..");
    };

    var selectFile = function() {
        console.log("selectFile function not relevant for webdav..");
    };

    var openExtensionsDirectory = function() {
        console.log("openExtensionsDirectory function not relevant for webdav..");
    };

    var getFileProperties = function(filePath) {
        davClient.propfind( encodeURI(filePath), function( status, data ) {
                console.log("Properties Status / Content: "+status+" / "+JSON.stringify(data._responses));
                var fileProperties = {};
                for (var entry in data._responses) {
                    fileProperties.path = filePath;
                    fileProperties.size = data._responses[entry]._namespaces["DAV:"].getcontentlength;
                    fileProperties.lmdt = data._responses[entry]._namespaces["DAV:"].getlastmodified._xmlvalue[0].data;
                }
                TSPOSTIO.getFileProperties(fileProperties);
            },1
        );
    };

    // Bring the TagSpaces window on top of the windows
    var focusWindow = function() {
        window.focus();
    };

    exports.focusWindow                 = focusWindow;
    exports.createDirectory             = createDirectory;
    exports.copyFile                    = copyFile;
    exports.renameFile                  = renameFile;
    exports.renameDirectory             = renameDirectory;
    exports.loadTextFile                = loadTextFile;
    exports.saveTextFile                = saveTextFile;
    exports.saveBinaryFile              = saveBinaryFile;
    exports.listDirectory               = listDirectory;
    exports.deleteElement               = deleteElement;
    exports.deleteDirectory             = deleteDirectory;
    exports.createDirectoryIndex        = createDirectoryIndex;
    exports.createDirectoryTree         = createDirectoryTree;
    exports.selectDirectory             = selectDirectory;
    exports.openDirectory               = openDirectory;
    exports.openFile                    = openFile;
    exports.selectFile                  = selectFile;
    exports.openExtensionsDirectory     = openExtensionsDirectory;
    exports.checkAccessFileURLAllowed   = checkAccessFileURLAllowed;
    exports.checkNewVersion             = checkNewVersion;
    exports.getFileProperties           = getFileProperties;
});<commit_msg>removing comment<commit_after>/* Copyright (c) 2012-2013 The TagSpaces Authors. All rights reserved.
 * Use of this source code is governed by a AGPL3 license that
 * can be found in the LICENSE file. */
define(function(require, exports, module) {
"use strict";

	// Activating browser specific exports modul
	console.log("Loading web.js..");

    var TSCORE = require("tscore");
    var TSPOSTIO = require("tspostioapi");

    require("webdavlib");

    var davClient;

    function connectDav() {
        console.log("Connecting webdav...");
        var useHTTPS = false;
        if(location.href.indexOf("https") === 0) {
            useHTTPS = true;
        }
        davClient = new nl.sara.webdav.Client(location.hostname, useHTTPS, location.port);
    }

    window.setTimeout(connectDav(), 2000);

    function listDirectory(dirPath) {
        console.log("Listing directory: "+dirPath);

        dirPath = encodeURI(dirPath + "/");

        davClient.propfind(
            dirPath, //encodeURI(dirPath),
            function( status, data ) {
                console.log("Dirlist Status:  "+status);
                //console.log("Dirlist Content: "+JSON.stringify(data._responses));
                var anotatedDirList = [],
                    dirList = data._responses,
                    fileName,
                    isDir,
                    filesize,
                    lmdt;

                for (var entry in dirList) {
                    var path = dirList[entry].href;
                    if(dirPath.toLowerCase() !== path.toLowerCase()) {
                        isDir = false;
                        filesize = undefined;
                        lmdt = undefined;
                        //console.log(dirList[entry]._namespaces["DAV:"]);
                        if (typeof dirList[entry]._namespaces["DAV:"].getcontentlength === 'undefined') {
                            isDir = true;
                        } else {
                            filesize = dirList[entry]._namespaces["DAV:"].getcontentlength;
                            lmdt = data._responses[entry]._namespaces["DAV:"].getlastmodified._xmlvalue[0].data;
                        }
                        fileName = getNameForPath(path);
                        anotatedDirList.push({
                            "name": fileName,
                            "isFile": !isDir,
                            "size": filesize,
                            "lmdt": lmdt,
                            "path": decodeURI(path)
                        });
                    }
                }
                TSPOSTIO.listDirectory(anotatedDirList);
            },
            1 //1 , davClient.INFINITY
        );
    }

    function getNameForPath(path) {
        if(path.lastIndexOf("/") == path.length-1) {
            path = path.substring(0,path.lastIndexOf("/"));
        }
        var encodedName = path.substring(path.lastIndexOf("/")+1, path.length);
        return decodeURI(encodedName);
    }

    function isDirectory(path) {
        return path.lastIndexOf("/") == path.length-1;
    }

    var createDirectoryIndex = function(dirPath) {
        console.log("Creating index for directory: "+dirPath);
        TSCORE.showLoadingAnimation();

        var directoryIndex = [];
        TSPOSTIO.createDirectoryIndex(directoryIndex);
    };

    var createDirectoryTree = function(dirPath) {
        console.log("Creating directory index for: "+dirPath);
        TSCORE.showLoadingAnimation();

        var directoyTree = [];
        //console.log(JSON.stringify(directoyTree));
        TSPOSTIO.createDirectoryTree(directoyTree);
    };

    var createDirectory = function(dirPath) {
        console.log("Creating directory: "+dirPath);
        davClient.mkcol(
            encodeURI(dirPath),
            function( status, data, headers ) {
                console.log("Directory Creation Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.createDirectory(dirPath);
            }
        );
    };

    var copyFile = function(filePath, newFilePath) {
        console.log("Copying file: "+filePath+" to "+newFilePath);
        davClient.copy(
            encodeURI(filePath),
            function( status, data, headers ) {
                console.log("Copy File Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.copyFile(filePath, newFilePath);
            },
            encodeURI(newFilePath),
            davClient.FAIL_ON_OVERWRITE
        );
    };

    var renameFile = function(filePath, newFilePath) {
        console.log("Renaming file: "+filePath+" to "+newFilePath);
        davClient.move(
            encodeURI(filePath),
            function( status, data, headers ) {
                console.log("Rename File Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.renameFile(filePath, newFilePath);
            },
            encodeURI(newFilePath),
            davClient.FAIL_ON_OVERWRITE
        );
    };

    var renameDirectory = function(dirPath, newDirName) {
        var newDirPath = TSCORE.TagUtils.extractParentDirectoryPath(dirPath) + TSCORE.dirSeparator + encodeURIComponent(newDirName);
        console.log("Renaming directory: "+dirPath+" to "+newDirPath);
        davClient.move(
            encodeURI(dirPath),
            function( status, data, headers ) {
                console.log("Rename Directory Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.renameDirectory(dirPath, newDirPath);
            },
            encodeURI(newDirPath),
            davClient.FAIL_ON_OVERWRITE
        );
    };

    var loadTextFile = function(filePath) {
        console.log("Loading file: "+filePath);
        davClient.get(
            encodeURI(filePath),
            function( status, data, headers ) {
                console.log("Loading File Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.loadTextFile(data);
            }
            //,customHeaders
        );
        //TODO Perform file locking and unlocking
    };

    var saveTextFile = function(filePath,content,overWrite) {
      console.log("Saving file: "+filePath); //+" content: "+content);

      var isNewFile = false; // = !pathUtils.existsSync(filePath);
      davClient.propfind( encodeURI(filePath), function( status, data ) {
            console.log("Check file exists: Status / Content: "+status+" / "+data);
            if(parseInt(status) === 404) {
                isNewFile = true;
            }
            davClient.put(
                encodeURI(filePath),
                function( status, data, headers ) {
                    console.log("Creating File Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                    TSPOSTIO.saveTextFile(filePath, isNewFile);
                },
                content,
                'application/octet-stream'
            );
        },1
      );
    };

    var saveBinaryFile = function(filePath,content) {
        console.log("Saving binary file: "+filePath); //+" content: "+content);
        var isNewFile = false;
        davClient.propfind( encodeURI(filePath), function( status, data ) {
            console.log("Check file exists: Status / Content: "+status+" / "+data);
            if(parseInt(status) === 404) {
                isNewFile = true;
            }
            if(isNewFile) {
                davClient.put(
                    encodeURI(filePath),
                    function( status, data, headers ) {
                        console.log("Creating File Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                        TSPOSTIO.saveBinaryFile(filePath, isNewFile);
                    },
                    content,
                    'application/octet-stream'
                );
            } else {
                TSCORE.showAlertDialog("File Already Exists.");
            }
        },1);
    };

    var deleteElement = function(path) {
      console.log("Deleting: "+path);
          davClient.remove(
              encodeURI(path),
              function( status, data, headers ) {
                  console.log("Directory/File Deletion Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                  TSPOSTIO.deleteElement(path);
              }
          );
    };

    var deleteDirectory = function(path) {
        console.log("Deleting directory: "+path);
        davClient.remove(
            encodeURI(path),
            function( status, data, headers ) {
                console.log("Directory/File Deletion Status/Content/Headers:  "+status+" / "+data+" / "+headers);
                TSPOSTIO.deleteDirectory(path);
            }
        );
    };

    var checkAccessFileURLAllowed = function() {
        console.log("checkAccessFileURLAllowed function not relevant for webdav..");
    };

    var checkNewVersion = function() {
        console.log("Checking for new version not relevant fot the webdav version");
    };

    var selectDirectory = function() {
        TSCORE.showAlertDialog("Select directory is still not implemented in the webdav edition");
    };

    var openDirectory = function(dirPath) {
        console.log("openDirectory function not relevant for webdav..");
    };

    var openFile = function(filePath) {
        console.log("openFile function not relevant for webdav..");
    };

    var selectFile = function() {
        console.log("selectFile function not relevant for webdav..");
    };

    var openExtensionsDirectory = function() {
        console.log("openExtensionsDirectory function not relevant for webdav..");
    };

    var getFileProperties = function(filePath) {
        davClient.propfind( encodeURI(filePath), function( status, data ) {
                console.log("Properties Status / Content: "+status+" / "+JSON.stringify(data._responses));
                var fileProperties = {};
                for (var entry in data._responses) {
                    fileProperties.path = filePath;
                    fileProperties.size = data._responses[entry]._namespaces["DAV:"].getcontentlength;
                    fileProperties.lmdt = data._responses[entry]._namespaces["DAV:"].getlastmodified._xmlvalue[0].data;
                }
                TSPOSTIO.getFileProperties(fileProperties);
            },1
        );
    };

    // Bring the TagSpaces window on top of the windows
    var focusWindow = function() {
        window.focus();
    };

    exports.focusWindow                 = focusWindow;
    exports.createDirectory             = createDirectory;
    exports.copyFile                    = copyFile;
    exports.renameFile                  = renameFile;
    exports.renameDirectory             = renameDirectory;
    exports.loadTextFile                = loadTextFile;
    exports.saveTextFile                = saveTextFile;
    exports.saveBinaryFile              = saveBinaryFile;
    exports.listDirectory               = listDirectory;
    exports.deleteElement               = deleteElement;
    exports.deleteDirectory             = deleteDirectory;
    exports.createDirectoryIndex        = createDirectoryIndex;
    exports.createDirectoryTree         = createDirectoryTree;
    exports.selectDirectory             = selectDirectory;
    exports.openDirectory               = openDirectory;
    exports.openFile                    = openFile;
    exports.selectFile                  = selectFile;
    exports.openExtensionsDirectory     = openExtensionsDirectory;
    exports.checkAccessFileURLAllowed   = checkAccessFileURLAllowed;
    exports.checkNewVersion             = checkNewVersion;
    exports.getFileProperties           = getFileProperties;
});<|endoftext|>


<commit_before>/**
 * @overview ccm component for table generating
 * @see https://github.com/mozilla/pdf.js/
 * @author Tea Kless <tea.kless@web.de>, 2018
 * @license The MIT License (MIT)
 */

{
  var component = {

    /**
     * unique component name
     * @type {string}
     */
    name: 'table',

    /**
     * recommended used framework version
     * @type {string}
     */
    ccm: 'https://akless.github.io/ccm/ccm.js',

    /**
     * default instance configuration
     * @type {object}
     */
    config: {
      html: {
        "table": {
          "id": "container",
          "inner": {
            "class": "table-responsive",
            "inner": {
              "tag": "table",
              "class": "table table-striped table-responsive",
              "inner":[
                { "tag": "thead" },
                { "tag": "tbody" }
              ]
            }
          }
        },

        "table_row": { "tag": "tr" },

        "table_col": { "tag": "td" },

        "table_head": { "tag": "th" },

        "input": {
          "tag": "input",
          "type": "text"
        },

        "textarea": {
          "tag": "textarea"
        },

        "add": {
          "tag": "button",
          "class": "btn btn-default",
          "typ": "button",
          "onclick": "%add%",
          "inner": [
            {
              "tag": "span",
              "class": "glyphicon glyphicon-plus"
            },
            " Row"
          ]
        },

        "submit": {
          "tag": "button",
          "class": "btn btn-default pull-right",
          "typ": "button",
          "inner": "Submit",
          "onclick": "%submit%"
        }
      },
      //add_row: true,
      table_row: 0,
      //table_col: 3,
      //table_head: [ "header-1", "header-2", "header-3" ],
      //col_settings: [
      //  { "type": "number", "placeholder": "Tel: 049..." },
      //  { "disabled": "true", "inner": "max.musterman@mail.com" },
      //  { "type": "date", "foo": "bar" }
      //],
      //data: [ "ccm.get", "resources/configs.js", "demo" ],
      //submit: true,
      //onfinish
      css: [ "ccm.load", "https://tkless.github.io/ccm-components/libs/bootstrap/css/bootstrap.css",
        { "context": "head", "url": "https://tkless.github.io/ccm-components/libs/bootstrap/css/font-face.css" }
      ]
    },

    Instance: function () {
      /**
       * own reference for inner functions
       * @type {Instance}
       */
      const self = this;

      /**
       * privatized instance members
       * @type {object}
       */
      let my;

      /**
       * shortcut to help functions
       * @type {Object.<string,function>}
       */
      let $;

      this.init = callback => {

        callback();
      };

      this.ready = callback => {
        // set shortcut to help functions
        $ = self.ccm.helper;

        // privatize all possible instance members
        my = $.privatize( self );

        callback();

      };

      /**
       * starts the instance
       * @param {function} [callback] - called after all synchronous and asynchronous operations are complete
       */
      this.start = callback => {

        $.dataset( my.data, data => {

          if ( !generateTable() ) return $.setContent( self.element, "Nothig to display" );

          else {
            $.setContent( self.element, generateTable() );

            if ( my.submit ) {
              const submit_button = $.html ( my.html.submit, {
                submit: function () { $.onFinish( self ); }
              } );
              self.element.querySelector( '#container' ).appendChild( submit_button );
            }

            if ( callback ) callback();
          }

          function generateTable() {
            const table = $.html ( my.html.table );
            let row;

            if ( my.table_row ) {
              row = my.data.values && ( my.data.values.length > my.table_row) ? my.data.values.length : my.table_row;

              for ( let i = 0 ; i < row; i++ ) {
                const table_row = $.html ( my.html.table_row );
                if ( my.table_col ) {
                  for ( let j = 0 ; j < my.table_col; j++ ) {
                    const table_col = $.html ( my.html.table_col );

                    if ( !my.col_settings ) {

                      if ( data ) $.setContent( table_col, i < data.length && data[ i ][ j ] ? data[ i ][ j ] : '' );

                    }
                    else {

                      const input = $.clone( my.html[ my.col_settings && my.col_settings[ j ] && my.col_settings[ j ].type === 'textarea' ? 'textarea' : 'input' ] );
                      input.name = ( i + 1 ) + '-' + ( j + 1 );

                      // consider column properties
                      if ( my.col_settings ) considerColSettings( j, input );

                      // set values of input fields
                      if ( data ) ( i < data.length ) && data[ i ][ j ] ? input.value = data[ i ][ j ] : input.value = '';

                      table_col.appendChild( $.html( input ) );

                    }

                    table_row.appendChild( table_col );

                  }
                }
                table.querySelector( 'tbody' ).appendChild( table_row );
              }

              if ( my.table_head ) {
                table.querySelector( 'thead' ).appendChild( getTableHead() );
              }
            }

            // add new row via button
            if ( my.add_row ) table.appendChild(  $.html( my.html.add, {
              add: function ( event ) {
                if ( event ) event.preventDefault();
                my.table_row = ++row;
                my.data = self.getValue();
                self.start();
              }
            } ) );
            return table;
          }

          function getTableHead() {
            const table_row = $.html(my.html.table_row);

            for ( let j = 0 ; j < my.table_col; j++ ) {
              const table_head = $.html( my.html.table_head );
              $.setContent( table_head, my.table_head[ j ] );
              table_row.appendChild( table_head );
            }

            return table_row;
          }

          function considerColSettings( col, input ) {
            // set input tag property for each input => each input tag of one column has same properties
            for ( const key in my.col_settings[ col ] ) {
              switch ( key ) {
                case 'type':
                  if ( my.col_settings[ col ][ key ] !== 'textarea' )
                    input.type = my.col_settings[ col ][ key ];
                  break;
                case 'placeholder':
                  input.placeholder = my.col_settings[ col ][ key ];
                  break;
                default:
                  input[ key ] =  my.col_settings[ col ][ key ];
                  break;
              }

            }
          }

        } );

      };

      this.getValue = () => {

        return prepareFormData();

        // reads the table values and transform it to result data
        function prepareFormData() {

          let form_data = $.formData( self.element.querySelector( 'table' ) );

          const result = [];

          for( const key in form_data ) {
            const coord = key.split( '-' );
            const row = coord[ 0 ] - 1;
            const col = coord[ 1 ] - 1;
            if ( !result[ row ] ) result[ row ] = [];
            result[ row ][ col ] = form_data[ key ];
          }

          return { values: result };
        }
      };

    }

  };

  function p(){window.ccm[v].component(component)}const f="ccm."+component.name+(component.version?"-"+component.version.join("."):"")+".js";if(window.ccm&&null===window.ccm.files[f])window.ccm.files[f]=component;else{const n=window.ccm&&window.ccm.components[component.name];n&&n.ccm&&(component.ccm=n.ccm),"string"==typeof component.ccm&&(component.ccm={url:component.ccm});var v=component.ccm.url.split("/").pop().split("-");if(v.length>1?(v=v[1].split("."),v.pop(),"min"===v[v.length-1]&&v.pop(),v=v.join(".")):v="latest",window.ccm&&window.ccm[v])p();else{const e=document.createElement("script");document.head.appendChild(e),component.ccm.integrity&&e.setAttribute("integrity",component.ccm.integrity),component.ccm.crossorigin&&e.setAttribute("crossorigin",component.ccm.crossorigin),e.onload=function(){p(),document.head.removeChild(e)},e.src=component.ccm.url}}
}<commit_msg>minor change<commit_after>/**
 * @overview ccm component for table generating
 * @see https://github.com/mozilla/pdf.js/
 * @author Tea Kless <tea.kless@web.de>, 2018
 * @license The MIT License (MIT)
 */

{
  var component = {

    /**
     * unique component name
     * @type {string}
     */
    name: 'table',

    /**
     * recommended used framework version
     * @type {string}
     */
    ccm: 'https://akless.github.io/ccm/ccm.js',

    /**
     * default instance configuration
     * @type {object}
     */
    config: {
      html: {
        "table": {
          "id": "container",
          "inner": {
            "class": "table-responsive",
            "inner": {
              "tag": "table",
              "class": "table table-striped table-responsive",
              "inner":[
                { "tag": "thead" },
                { "tag": "tbody" }
              ]
            }
          }
        },

        "table_row": { "tag": "tr" },

        "table_col": { "tag": "td" },

        "table_head": { "tag": "th" },

        "input": {
          "tag": "input",
          "type": "text"
        },

        "textarea": {
          "tag": "textarea"
        },

        "add": {
          "tag": "button",
          "class": "btn btn-default",
          "typ": "button",
          "onclick": "%add%",
          "inner": [
            {
              "tag": "span",
              "class": "glyphicon glyphicon-plus"
            },
            " Row"
          ]
        },

        "submit": {
          "tag": "button",
          "class": "btn btn-default pull-right",
          "typ": "button",
          "inner": "Submit",
          "onclick": "%submit%"
        }
      },
      //add_row: true,
      table_row: 0,
      //table_col: 3,
      //table_head: [ "header-1", "header-2", "header-3" ],
      //col_settings: [
      //  { "type": "number", "placeholder": "Tel: 049..." },
      //  { "disabled": "true", "inner": "max.musterman@mail.com" },
      //  { "type": "date", "foo": "bar" }
      //],
      //data: [ "ccm.get", "resources/configs.js", "demo" ],
      //submit: true,
      //onfinish
      css: [ "ccm.load", "https://tkless.github.io/ccm-components/libs/bootstrap/css/bootstrap.css",
        { "context": "head", "url": "https://tkless.github.io/ccm-components/libs/bootstrap/css/font-face.css" }
      ]
    },

    Instance: function () {
      /**
       * own reference for inner functions
       * @type {Instance}
       */
      const self = this;

      /**
       * privatized instance members
       * @type {object}
       */
      let my;

      /**
       * shortcut to help functions
       * @type {Object.<string,function>}
       */
      let $;

      this.init = callback => {

        callback();
      };

      this.ready = callback => {
        // set shortcut to help functions
        $ = self.ccm.helper;

        // privatize all possible instance members
        my = $.privatize( self );

        callback();

      };

      /**
       * starts the instance
       * @param {function} [callback] - called after all synchronous and asynchronous operations are complete
       */
      this.start = callback => {

        $.dataset( my.data, data => {

          if ( !generateTable() ) return $.setContent( self.element, "Nothig to display" );

          else {
            $.setContent( self.element, generateTable() );

            if ( my.submit ) {
              const submit_button = $.html ( my.html.submit, {
                submit: function () { $.onFinish( self ); }
              } );
              self.element.querySelector( '#container' ).appendChild( submit_button );
            }

            if ( callback ) callback();
          }

          function generateTable() {
            const table = $.html ( my.html.table );
            let row;

            if ( my.table_row ) {
              row = my.data && ( my.data.values.length > my.table_row) ? my.data.values.length : my.table_row;

              for ( let i = 0 ; i < row; i++ ) {
                const table_row = $.html ( my.html.table_row );
                if ( my.table_col ) {
                  for ( let j = 0 ; j < my.table_col; j++ ) {
                    const table_col = $.html ( my.html.table_col );

                    if ( !my.col_settings ) {

                      if ( data ) $.setContent( table_col, i < data.length && data[ i ][ j ] ? data[ i ][ j ] : '' );

                    }
                    else {

                      const input = $.clone( my.html[ my.col_settings && my.col_settings[ j ] && my.col_settings[ j ].type === 'textarea' ? 'textarea' : 'input' ] );
                      input.name = ( i + 1 ) + '-' + ( j + 1 );

                      // consider column properties
                      if ( my.col_settings ) considerColSettings( j, input );

                      // set values of input fields
                      if ( data ) ( i < data.length ) && data[ i ][ j ] ? input.value = data[ i ][ j ] : input.value = '';

                      table_col.appendChild( $.html( input ) );

                    }

                    table_row.appendChild( table_col );

                  }
                }
                table.querySelector( 'tbody' ).appendChild( table_row );
              }

              if ( my.table_head ) {
                table.querySelector( 'thead' ).appendChild( getTableHead() );
              }
            }

            // add new row via button
            if ( my.add_row ) table.appendChild(  $.html( my.html.add, {
              add: function ( event ) {
                if ( event ) event.preventDefault();
                my.table_row = ++row;
                my.data = self.getValue();
                self.start();
              }
            } ) );
            return table;
          }

          function getTableHead() {
            const table_row = $.html(my.html.table_row);

            for ( let j = 0 ; j < my.table_col; j++ ) {
              const table_head = $.html( my.html.table_head );
              $.setContent( table_head, my.table_head[ j ] );
              table_row.appendChild( table_head );
            }

            return table_row;
          }

          function considerColSettings( col, input ) {
            // set input tag property for each input => each input tag of one column has same properties
            for ( const key in my.col_settings[ col ] ) {
              switch ( key ) {
                case 'type':
                  if ( my.col_settings[ col ][ key ] !== 'textarea' )
                    input.type = my.col_settings[ col ][ key ];
                  break;
                case 'placeholder':
                  input.placeholder = my.col_settings[ col ][ key ];
                  break;
                default:
                  input[ key ] =  my.col_settings[ col ][ key ];
                  break;
              }

            }
          }

        } );

      };

      this.getValue = () => {

        return prepareFormData();

        // reads the table values and transform it to result data
        function prepareFormData() {

          let form_data = $.formData( self.element.querySelector( 'table' ) );

          const result = [];

          for( const key in form_data ) {
            const coord = key.split( '-' );
            const row = coord[ 0 ] - 1;
            const col = coord[ 1 ] - 1;
            if ( !result[ row ] ) result[ row ] = [];
            result[ row ][ col ] = form_data[ key ];
          }

          return { values: result };
        }
      };

    }

  };

  function p(){window.ccm[v].component(component)}const f="ccm."+component.name+(component.version?"-"+component.version.join("."):"")+".js";if(window.ccm&&null===window.ccm.files[f])window.ccm.files[f]=component;else{const n=window.ccm&&window.ccm.components[component.name];n&&n.ccm&&(component.ccm=n.ccm),"string"==typeof component.ccm&&(component.ccm={url:component.ccm});var v=component.ccm.url.split("/").pop().split("-");if(v.length>1?(v=v[1].split("."),v.pop(),"min"===v[v.length-1]&&v.pop(),v=v.join(".")):v="latest",window.ccm&&window.ccm[v])p();else{const e=document.createElement("script");document.head.appendChild(e),component.ccm.integrity&&e.setAttribute("integrity",component.ccm.integrity),component.ccm.crossorigin&&e.setAttribute("crossorigin",component.ccm.crossorigin),e.onload=function(){p(),document.head.removeChild(e)},e.src=component.ccm.url}}
}<|endoftext|>