<commit_before>import React, { Component } from 'react';
import { Animated, StyleSheet, Text, View, I18nManager } from 'react-native';

import { RectButton } from 'react-native-gesture-handler';

import Swipeable from 'react-native-gesture-handler/Swipeable';

export default class AppleStyleSwipeableRow extends Component {
  renderLeftActions = (progress, dragX) => {
    const trans = dragX.interpolate({
      inputRange: [0, 50, 100, 101],
      outputRange: [-20, 0, 0, 1],
    });
    return (
      <RectButton style={styles.leftAction} onPress={this.close}>
        <Animated.Text
          style={[
            styles.actionText,
            {
              transform: [{ translateX: trans }],
            },
          ]}>
          Archive
        </Animated.Text>
      </RectButton>
    );
  };
  renderRightAction = (text, color, x, progress) => {
    const trans = progress.interpolate({
      inputRange: [0, 1],
      outputRange: [x, 0],
    });
    const pressHandler = () => {
      this.close();
      alert(text);
    };
    return (
      <Animated.View style={{ flex: 1, transform: [{ translateX: trans }] }}>
        <RectButton
          style={[styles.rightAction, { backgroundColor: color }]}
          onPress={pressHandler}>
          <Text style={styles.actionText}>{text}</Text>
        </RectButton>
      </Animated.View>
    );
  };
  renderRightActions = progress => (
    <View
      style={{
        width: 192,
        flexDirection: I18nManager.isRTL ? 'row-reverse' : 'row',
      }}>
      {this.renderRightAction('More', '#C8C7CD', 192, progress)}
      {this.renderRightAction('Flag', '#ffab00', 128, progress)}
      {this.renderRightAction('More', '#dd2c00', 64, progress)}
    </View>
  );
  updateRef = ref => {
    this._swipeableRow = ref;
  };
  close = () => {
    this._swipeableRow.close();
  };
  render() {
    const { children } = this.props;
    return (
      <Swipeable
        ref={this.updateRef}
        friction={2}
        enableTrackpadTwoFingerGesture
        leftThreshold={30}
        rightThreshold={40}
        renderLeftActions={this.renderLeftActions}
        renderRightActions={this.renderRightActions}>
        {children}
      </Swipeable>
    );
  }
}

const styles = StyleSheet.create({
  leftAction: {
    flex: 1,
    backgroundColor: '#497AFC',
    justifyContent: 'center',
  },
  actionText: {
    color: 'white',
    fontSize: 16,
    backgroundColor: 'transparent',
    padding: 10,
  },
  rightAction: {
    alignItems: 'center',
    flex: 1,
    justifyContent: 'center',
  },
});
<commit_msg>Clamp swipe animation in examples (#1290)<commit_after>import React, { Component } from 'react';
import { Animated, StyleSheet, Text, View, I18nManager } from 'react-native';

import { RectButton } from 'react-native-gesture-handler';

import Swipeable from 'react-native-gesture-handler/Swipeable';

export default class AppleStyleSwipeableRow extends Component {
  renderLeftActions = (progress, dragX) => {
    const trans = dragX.interpolate({
      inputRange: [0, 50, 100, 101],
      outputRange: [-20, 0, 0, 1],
      extrapolate: 'clamp'
    });
    return (
      <RectButton style={styles.leftAction} onPress={this.close}>
        <Animated.Text
          style={[
            styles.actionText,
            {
              transform: [{ translateX: trans }],
            },
          ]}>
          Archive
        </Animated.Text>
      </RectButton>
    );
  };
  renderRightAction = (text, color, x, progress) => {
    const trans = progress.interpolate({
      inputRange: [0, 1],
      outputRange: [x, 0],
    });
    const pressHandler = () => {
      this.close();
      alert(text);
    };
    return (
      <Animated.View style={{ flex: 1, transform: [{ translateX: trans }] }}>
        <RectButton
          style={[styles.rightAction, { backgroundColor: color }]}
          onPress={pressHandler}>
          <Text style={styles.actionText}>{text}</Text>
        </RectButton>
      </Animated.View>
    );
  };
  renderRightActions = progress => (
    <View
      style={{
        width: 192,
        flexDirection: I18nManager.isRTL ? 'row-reverse' : 'row',
      }}>
      {this.renderRightAction('More', '#C8C7CD', 192, progress)}
      {this.renderRightAction('Flag', '#ffab00', 128, progress)}
      {this.renderRightAction('More', '#dd2c00', 64, progress)}
    </View>
  );
  updateRef = ref => {
    this._swipeableRow = ref;
  };
  close = () => {
    this._swipeableRow.close();
  };
  render() {
    const { children } = this.props;
    return (
      <Swipeable
        ref={this.updateRef}
        friction={2}
        enableTrackpadTwoFingerGesture
        leftThreshold={30}
        rightThreshold={40}
        renderLeftActions={this.renderLeftActions}
        renderRightActions={this.renderRightActions}>
        {children}
      </Swipeable>
    );
  }
}

const styles = StyleSheet.create({
  leftAction: {
    flex: 1,
    backgroundColor: '#497AFC',
    justifyContent: 'center',
  },
  actionText: {
    color: 'white',
    fontSize: 16,
    backgroundColor: 'transparent',
    padding: 10,
  },
  rightAction: {
    alignItems: 'center',
    flex: 1,
    justifyContent: 'center',
  },
});
<|endoftext|>


<commit_before>//============================================
// Menu Plugin
// This menu plugin comes from the custom menu example. I will use it to
// understand adding to/making the schema
//============================================

class MenuView {
    constructor(items, editorView) {
        this.items = items
        this.editorView = editorView

        this.dom = document.createElement("div")
        this.dom.className = "menubar"
        items.forEach(({dom}) => this.dom.appendChild(dom))
        this.update()

        this.dom.addEventListener("mousedown", e => {
            e.preventDefault()
            editorView.focus()
            items.forEach(({command, dom}) => {
                if(dom.contains(e.target))
                    command(editorView.state, editorView.dispatch, editorView)
            })
        })
    }

    update() {
        this.items.forEach(({command, dom}) => {
            let active = command(this.editorView.state, null, this.editorView)
            dom.style.display = active ? "" : "none"
        })
    }

    destroy() {
        this.dom.remove()
    }
}

const {Plugin} = require("prosemirror-state")

function menuPlugin(items) {
    return new Plugin({
        view(editorView) {
            let menuView = new MenuView(items, editorView)
            editorView.dom.parentNode.insertBefore(menuView.dom, editorView.dom)
            return menuView
        }
    })
}

//===================================
// Custom Schema
//===================================

const {Schema} = require("prosemirror-model")

const pDOM = ["p", 0], blockquoteDOM = ["blockquote", 0], hrDOM = ["hr"],
      preDOM = ["pre", ["code", 0]], brDOM = ["br"]

// :: Object
// [Specs](#model.NodeSpec) for the nodes defined in this schema.
const nodes = {
  // :: NodeSpec The top level document node.
  doc: {
    content: "block+"
  },

  // :: NodeSpec A plain paragraph textblock. Represented in the DOM
  // as a `<p>` element.
  paragraph: {
    content: "inline*",
    group: "block",
    parseDOM: [{tag: "p"}],
    toDOM() { return pDOM }
  },

  // :: NodeSpec A blockquote (`<blockquote>`) wrapping one or more blocks.
  blockquote: {
    content: "block+",
    group: "block",
    defining: true,
    parseDOM: [{tag: "blockquote"}],
    toDOM() { return blockquoteDOM }
  },

  // :: NodeSpec A horizontal rule (`<hr>`).
  horizontal_rule: {
    group: "block",
    parseDOM: [{tag: "hr"}],
    toDOM() { return hrDOM }
  },

  // :: NodeSpec A heading textblock, with a `level` attribute that
  // should hold the number 1 to 6. Parsed and serialized as `<h1>` to
  // `<h6>` elements.
  heading: {
    attrs: {level: {default: 1}},
    content: "inline*",
    group: "block",
    defining: true,
    parseDOM: [{tag: "h1", attrs: {level: 1}},
               {tag: "h2", attrs: {level: 2}},
               {tag: "h3", attrs: {level: 3}},
               {tag: "h4", attrs: {level: 4}},
               {tag: "h5", attrs: {level: 5}},
               {tag: "h6", attrs: {level: 6}}],
    toDOM(node) { return ["h" + node.attrs.level, 0] }
  },

  // :: NodeSpec A code listing. Disallows marks or non-text inline
  // nodes by default. Represented as a `<pre>` element with a
  // `<code>` element inside of it.
  code_block: {
    content: "text*",
    marks: "",
    group: "block",
    code: true,
    defining: true,
    parseDOM: [{tag: "pre", preserveWhitespace: "full"}],
    toDOM() { return preDOM }
  },

  // :: NodeSpec The text node.
  text: {
    group: "inline"
  },

  // :: NodeSpec An inline image (`<img>`) node. Supports `src`,
  // `alt`, and `href` attributes. The latter two default to the empty
  // string.
  image: {
    inline: true,
    attrs: {
      src: {},
      alt: {default: null},
      title: {default: null}
    },
    group: "inline",
    draggable: true,
    parseDOM: [{tag: "img[src]", getAttrs(dom) {
      return {
        src: dom.getAttribute("src"),
        title: dom.getAttribute("title"),
        alt: dom.getAttribute("alt")
      }
    }}],
    toDOM(node) { let {src, alt, title} = node.attrs; return ["img", {src, alt, title}] }
  },

  // :: NodeSpec A hard line break, represented in the DOM as `<br>`.
  hard_break: {
    inline: true,
    group: "inline",
    selectable: false,
    parseDOM: [{tag: "br"}],
    toDOM() { return brDOM }
  }
}

const emDOM = ["em", 0], strongDOM = ["strong", 0], codeDOM = ["code", 0]

// :: Object [Specs](#model.MarkSpec) for the marks in the schema.
const marks = {
  // :: MarkSpec A link. Has `href` and `title` attributes. `title`
  // defaults to the empty string. Rendered and parsed as an `<a>`
  // element.
  link: {
    attrs: {
      href: {},
      title: {default: null}
    },
    inclusive: false,
    parseDOM: [{tag: "a[href]", getAttrs(dom) {
      return {href: dom.getAttribute("href"), title: dom.getAttribute("title")}
    }}],
    toDOM(node) { let {href, title} = node.attrs; return ["a", {href, title}, 0] }
  },

  // :: MarkSpec An emphasis mark. Rendered as an `<em>` element.
  // Has parse rules that also match `<i>` and `font-style: italic`.
  em: {
    parseDOM: [{tag: "i"}, {tag: "em"}, {style: "font-style=italic"}],
    toDOM() { return emDOM }
  },

  // :: MarkSpec A strong mark. Rendered as `<strong>`, parse rules
  // also match `<b>` and `font-weight: bold`.
  strong: {
    parseDOM: [{tag: "strong"},
               // This works around a Google Docs misbehavior where
               // pasted content will be inexplicably wrapped in `<b>`
               // tags with a font-weight normal.
               {tag: "b", getAttrs: node => node.style.fontWeight != "normal" && null},
               {style: "font-weight", getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null}],
    toDOM() { return strongDOM }
  },

  //------------------------
  //test
  //------------------------
  // an attempt at text color, with style
  color: {
    attrs: {
      color: {default: "black"}
    },
    parseDOM: [{tag: "span", style: "color"}],
    toDOM(node) { return ["span", {"style":"color:"+node.attrs["color"]+";"}, 0] }
  },

  highlight: {
    attrs: {
      highlightcolor: {default: "white"}
    },
    parseDOM: [{tag: "span", style: "background-color"}],
    toDOM(node) { return ["span", {"style":"background-color:"+node.attrs["highlightcolor"]+";"}, 0] }
  },

//  colorblue: {
//    parseDOM: [{tag: "span", {style: "color=blue"}],
//    toDOM() { return emDOM }
//  },

  //------------------------
  //end test
  //------------------------

  // :: MarkSpec Code font mark. Represented as a `<code>` element.
  code: {
    parseDOM: [{tag: "code"}],
    toDOM() { return codeDOM }
  }
}

// :: Schema
// This schema rougly corresponds to the document schema used by
// [CommonMark](http://commonmark.org/), minus the list elements,
// which are defined in the [`prosemirror-schema-list`](#schema-list)
// module.
//
// To reuse elements from this schema, extend or read from its
// `spec.nodes` and `spec.marks` [properties](#model.Schema.spec).
const schema = new Schema({nodes, marks})

//===================================
// Menu Items
// Our menu plugn lets us toggle marks, set block type and wrap in (which I won't use for starters)
//===================================

const {toggleMark, setBlockType, wrapIn} = require("prosemirror-commands")

// Helper function to create menu icons
function icon(text, name) {
    let span = document.createElement("span")
    span.className = "menuicon " + name
    span.title = name
    span.textContent = text
    return span
}

// Create an icon for a heading at the given level
function heading(level) {
    return {
        command: setBlockType(schema.nodes.heading, {level}),
        dom: icon("H" + level, "heading")
    }
}

function colorItem(color) {
    return {
        command: toggleMark(schema.marks.color, {color}),
        dom: icon("Text: " + color, "color")
    }
}

function highlightItem(highlightcolor) {
    return {
        command: toggleMark(schema.marks.highlight, {highlightcolor}),
        dom: icon("Highlight: " + highlightcolor, "highlight")
    }
}

let menu = menuPlugin([
    {command: toggleMark(schema.marks.strong), dom: icon("B", "strong")},
    {command: toggleMark(schema.marks.em), dom: icon("i", "em")},
    colorItem("blue"),colorItem("red"),colorItem("green"),
    highlightItem("yellow"),highlightItem("cyan"),highlightItem("lightblue"),
    {command: setBlockType(schema.nodes.paragraph), dom: icon("p", "paragraph")},
    heading(1), heading(2), heading(3),
    {command: wrapIn(schema.nodes.blockquote), dom: icon(">", "blockquote")}
])

//===================================
// Menu Items
//===================================

const {EditorState} = require("prosemirror-state")
const {EditorView} = require("prosemirror-view")
const {undo, redo, history} = require("prosemirror-history")
const {keymap} = require("prosemirror-keymap")
const {baseKeymap} = require("prosemirror-commands")

var element = document.getElementById("editor");

let state = EditorState.create({
  schema,
  plugins: [
    history(),
    keymap({"Mod-z": undo, "Mod-y": redo}),
    keymap(baseKeymap),
    menu
  ]
})
let view = new EditorView(element, {state});

<commit_msg>worked on styles in prose mirror test page<commit_after>//============================================
// Menu Plugin
// This menu plugin comes from the custom menu example. I will use it to
// understand adding to/making the schema
//============================================

class MenuView {
    constructor(items, editorView) {
        this.items = items
        this.editorView = editorView

        this.dom = document.createElement("div")
        this.dom.className = "menubar"
        items.forEach(({dom}) => this.dom.appendChild(dom))
        this.update()

        this.dom.addEventListener("mousedown", e => {
            e.preventDefault()
            editorView.focus()
            items.forEach(({command, dom}) => {
                if(dom.contains(e.target))
                    command(editorView.state, editorView.dispatch, editorView)
            })
        })
    }

    update() {
        this.items.forEach(({command, dom}) => {
            let active = command(this.editorView.state, null, this.editorView)
            dom.style.display = active ? "" : "none"
        })
    }

    destroy() {
        this.dom.remove()
    }
}

const {Plugin} = require("prosemirror-state")

function menuPlugin(items) {
    return new Plugin({
        view(editorView) {
            let menuView = new MenuView(items, editorView)
            editorView.dom.parentNode.insertBefore(menuView.dom, editorView.dom)
            return menuView
        }
    })
}

//===================================
// Custom Schema
//===================================

const {Schema} = require("prosemirror-model")

const pDOM = ["p", 0], blockquoteDOM = ["blockquote", 0], hrDOM = ["hr"],
      preDOM = ["pre", ["code", 0]], brDOM = ["br"]

// :: Object
// [Specs](#model.NodeSpec) for the nodes defined in this schema.
const nodes = {
  // :: NodeSpec The top level document node.
  doc: {
    content: "block+"
  },

  // :: NodeSpec A plain paragraph textblock. Represented in the DOM
  // as a `<p>` element.
  paragraph: {
    content: "inline*",
    group: "block",
    parseDOM: [{tag: "p"}],
    toDOM() { return pDOM }
  },

  // :: NodeSpec A blockquote (`<blockquote>`) wrapping one or more blocks.
  blockquote: {
    content: "block+",
    group: "block",
    defining: true,
    parseDOM: [{tag: "blockquote"}],
    toDOM() { return blockquoteDOM }
  },

  // :: NodeSpec A horizontal rule (`<hr>`).
  horizontal_rule: {
    group: "block",
    parseDOM: [{tag: "hr"}],
    toDOM() { return hrDOM }
  },

  // :: NodeSpec A heading textblock, with a `level` attribute that
  // should hold the number 1 to 6. Parsed and serialized as `<h1>` to
  // `<h6>` elements.
  heading: {
    attrs: {level: {default: 1}},
    content: "inline*",
    group: "block",
    defining: true,
    parseDOM: [{tag: "h1", attrs: {level: 1}},
               {tag: "h2", attrs: {level: 2}},
               {tag: "h3", attrs: {level: 3}},
               {tag: "h4", attrs: {level: 4}},
               {tag: "h5", attrs: {level: 5}},
               {tag: "h6", attrs: {level: 6}}],
    toDOM(node) { return ["h" + node.attrs.level, 0] }
  },

  // :: NodeSpec A code listing. Disallows marks or non-text inline
  // nodes by default. Represented as a `<pre>` element with a
  // `<code>` element inside of it.
  code_block: {
    content: "text*",
    marks: "",
    group: "block",
    code: true,
    defining: true,
    parseDOM: [{tag: "pre", preserveWhitespace: "full"}],
    toDOM() { return preDOM }
  },

  // :: NodeSpec The text node.
  text: {
    group: "inline"
  },

  // :: NodeSpec An inline image (`<img>`) node. Supports `src`,
  // `alt`, and `href` attributes. The latter two default to the empty
  // string.
  image: {
    inline: true,
    attrs: {
      src: {},
      alt: {default: null},
      title: {default: null}
    },
    group: "inline",
    draggable: true,
    parseDOM: [{tag: "img[src]", getAttrs(dom) {
      return {
        src: dom.getAttribute("src"),
        title: dom.getAttribute("title"),
        alt: dom.getAttribute("alt")
      }
    }}],
    toDOM(node) { let {src, alt, title} = node.attrs; return ["img", {src, alt, title}] }
  },

  // :: NodeSpec A hard line break, represented in the DOM as `<br>`.
  hard_break: {
    inline: true,
    group: "inline",
    selectable: false,
    parseDOM: [{tag: "br"}],
    toDOM() { return brDOM }
  }
}

const emDOM = ["em", 0], strongDOM = ["strong", 0], codeDOM = ["code", 0]

// :: Object [Specs](#model.MarkSpec) for the marks in the schema.
const marks = {
  // :: MarkSpec A link. Has `href` and `title` attributes. `title`
  // defaults to the empty string. Rendered and parsed as an `<a>`
  // element.
  link: {
    attrs: {
      href: {},
      title: {default: null}
    },
    inclusive: false,
    parseDOM: [{tag: "a[href]", getAttrs(dom) {
      return {href: dom.getAttribute("href"), title: dom.getAttribute("title")}
    }}],
    toDOM(node) { let {href, title} = node.attrs; return ["a", {href, title}, 0] }
  },

  // :: MarkSpec An emphasis mark. Rendered as an `<em>` element.
  // Has parse rules that also match `<i>` and `font-style: italic`.
  em: {
    parseDOM: [{tag: "i"}, {tag: "em"}, {style: "font-style=italic"}],
    toDOM() { return emDOM }
  },

  // :: MarkSpec A strong mark. Rendered as `<strong>`, parse rules
  // also match `<b>` and `font-weight: bold`.
  strong: {
    parseDOM: [{tag: "strong"},
               // This works around a Google Docs misbehavior where
               // pasted content will be inexplicably wrapped in `<b>`
               // tags with a font-weight normal.
               {tag: "b", getAttrs: node => node.style.fontWeight != "normal" && null},
               {style: "font-weight", getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null}],
    toDOM() { return strongDOM }
  },

  //------------------------
  //test
  //------------------------
  // an attempt at text color, with style
  //I SHOULD FORMALLY DEFINE THE CUSTOM TAGS!

  color: {
    attrs: {
      color: {default: "black"}
    },
    parseDOM: [{tag: "clr-tag", style: "color", getAttrs(dom) {
        return {color: dom.style.color};
    }}],
    toDOM(node) { return ["clr-tag", {"style":"color:"+node.attrs["color"]+";"}, 0] }
  },

  fontsize: {
    attrs: {
      fontsize: {default: ""}
    },
    parseDOM: [{tag: "fntsz-tag", style: "font-size", getAttrs(dom) {
        return {fontsize: dom.style["font-size"]};
    }}],
    toDOM(node) { return ["fntsz-tag", {"style":"font-size:"+node.attrs["fontsize"]+";"}, 0] }
  },

  highlight: {
    attrs: {
      highlightcolor: {default: "white"}
    },
    parseDOM: [{tag: "bgd-tag", style: "background-color", getAttrs(dom) {
        return {"highlightcolor": dom.style["background-color"]};
    }}],
    toDOM(node) { return ["bgd-tag", {"style":"background-color:"+node.attrs["highlightcolor"]+";"}, 0] }
  },

//  span: {
//    attrs: {
//        color: {default: null},
//        highlightcolor: {default: null}
//    },
//    parseDOM: [{tag: "span", getAttrs(dom) {
//        let attrs = {};
//        //only keep non empty styles
//        if(dom.style.color) attrs.color = dom.style.color;
//        if(dom.style["background-color"]) attrs.highlightcolor = dom.style["background-color"];
//        return attrs;
//    }}],
//    toDOM(node) {
//        let styleString = "";
//        //only keep non empty styles
//        if(node.attrs.color) styleString += "color:" + node.attrs.color + ";";
//        if(node.attrs.highlightcolor) styleString += "background-color:" + node.attrs.highlightcolor + ";";
//        return ["span", {style:styleString}, 0] }
//  },

//  colorblue: {
//    parseDOM: [{tag: "span", {style: "color=blue"}],
//    toDOM() { return emDOM }
//  },

  //------------------------
  //end test
  //------------------------

  // :: MarkSpec Code font mark. Represented as a `<code>` element.
  code: {
    parseDOM: [{tag: "code"}],
    toDOM() { return codeDOM }
  }
}

// :: Schema
// This schema rougly corresponds to the document schema used by
// [CommonMark](http://commonmark.org/), minus the list elements,
// which are defined in the [`prosemirror-schema-list`](#schema-list)
// module.
//
// To reuse elements from this schema, extend or read from its
// `spec.nodes` and `spec.marks` [properties](#model.Schema.spec).
const schema = new Schema({nodes, marks})

//===================================
// Menu Items
// Our menu plugn lets us toggle marks, set block type and wrap in (which I won't use for starters)
//===================================

const {toggleMark, setBlockType, wrapIn} = require("prosemirror-commands")

function markApplies(doc, ranges, type) {
  for (let i = 0; i < ranges.length; i++) {
    let {$from, $to} = ranges[i]
    let can = $from.depth == 0 ? doc.type.allowsMarkType(type) : false
    doc.nodesBetween($from.pos, $to.pos, node => {
      if (can) return false
      can = node.inlineContent && node.type.allowsMarkType(type)
    })
    if (can) return true
  }
  return false
}

function wrapInMark(markType, attrs) {
    return function(state, dispatch) {
        let {empty, $cursor, ranges} = state.selection
        if ((empty && !$cursor) || !markApplies(state.doc, ranges, markType)) return false
        if (dispatch) {
            if ($cursor) {
                dispatch(state.tr.addStoredMark(markType.create(attrs)))
            }
            else {
//                let has = false, tr = state.tr
//                for (let i = 0; !has && i < ranges.length; i++) {
//                  let {$from, $to} = ranges[i]
//                  has = state.doc.rangeHasMark($from.pos, $to.pos, markType)
//                }

                let tr = state.tr
                for (let i = 0; i < ranges.length; i++) {
                    let {$from, $to} = ranges[i]
                    tr.addMark($from.pos, $to.pos, markType.create(attrs))
                }
                dispatch(tr.scrollIntoView())
            }
        }
        return true
    }
}

// Helper function to create menu icons
function icon(text, name) {
    let span = document.createElement("span")
    span.className = "menuicon " + name
    span.title = name
    span.textContent = text
    return span
}

// Create an icon for a heading at the given level
function heading(level) {
    return {
        command: setBlockType(schema.nodes.heading, {level}),
        dom: icon("H" + level, "heading")
    }
}

function colorItem(color) {
    return {
        command: wrapInMark(schema.marks.color, {color}),
        dom: icon("Text: " + color, "color")
    }
}

function highlightItem(highlightcolor) {
    return {
        command: wrapInMark(schema.marks.highlight, {highlightcolor}),
        dom: icon("Highlight: " + highlightcolor, "highlight")
    }
}

function fontSizeItem(fontsize) {
    return {
        command: wrapInMark(schema.marks.fontsize, {fontsize}),
        dom: icon("Font size: " + fontsize, "fontsize")
    }
}

let menu = menuPlugin([
    {command: toggleMark(schema.marks.strong), dom: icon("B", "strong")},
    {command: toggleMark(schema.marks.em), dom: icon("i", "em")},
    colorItem("blue"),colorItem("red"),colorItem("green"),
    highlightItem("yellow"),highlightItem("cyan"),highlightItem("lightblue"),
    fontSizeItem("6px"),fontSizeItem("12px"),fontSizeItem("inherit"),fontSizeItem("24px"),
    {command: setBlockType(schema.nodes.paragraph), dom: icon("p", "paragraph")},
    heading(1), heading(2), heading(3),
    {command: wrapIn(schema.nodes.blockquote), dom: icon(">", "blockquote")}
])

//===================================
// Menu Items
//===================================

const {EditorState} = require("prosemirror-state")
const {EditorView} = require("prosemirror-view")
const {undo, redo, history} = require("prosemirror-history")
const {keymap} = require("prosemirror-keymap")
const {baseKeymap} = require("prosemirror-commands")

var element = document.getElementById("editor");

let state = EditorState.create({
  schema,
  plugins: [
    history(),
    keymap({"Mod-z": undo, "Mod-y": redo}),
    keymap(baseKeymap),
    menu
  ]
})
let view = new EditorView(element, {state});

<|endoftext|>


<commit_before>/*globals sparks $ */

(function() {

  var activity = sparks.Activity;

  activity.Question = function () {
      this.prompt = '';
      this.correct_answer = '';
      this.answer = '';
      this.correct_units = '';
      this.units = '';
      this.answerIsCorrect = false;
      this.unitsIsCorrect = false;
      this.start_time = null;
      this.end_time = null;
      this.score = 1;
  };

  activity.Assessment = function (activityLog) {
    this.activityLog = activityLog;
    this.questions = [];
    this.forms = [];
    this.userQuestions = [];
  };

  activity.Assessment.prototype =
  {
    addQuestion: function(prompt, correct_answer, correct_units, score) {
      var question = new activity.Question();
      question.prompt = prompt;
      question.correct_answer = correct_answer;
      question.correct_units = correct_units;
      question.score = score;
      this.questions.push(question);
    },

    addMeasurmentQuestion: function (prompt, value, units, score){

      function html_entity_decode(str) {
        var ta=document.createElement("textarea");
        ta.innerHTML=str.replace(/</g,"<").replace(/>/g,">");
        return ta.value;
      }

      function round(num, dec) {
      	var result = Math.round( Math.round( num * Math.pow( 10, dec + 1 ) ) / Math.pow( 10, 1 ) ) / Math.pow(10,dec);
      	return result;
      }

      if (value >= 1000000){
        var MUnits = html_entity_decode('M'+units);
        this.addQuestion(prompt, round(value/1000000,2), MUnits, score);
      } else if (value >= 1000){
        var kUnits = html_entity_decode('k'+units);
        this.addQuestion(prompt, round(value/1000,2), kUnits, score);
      } else if (value < 0.001){
        var uUnits = html_entity_decode('µ'+units);
        this.addQuestion(prompt, round(value * 1000000,2), uUnits, score);
      } else if (value < 1) {
        var mUnits = html_entity_decode('m'+units);
        this.addQuestion(prompt, round(value * 1000,2), mUnits, score);
      } else {
        var units = html_entity_decode(units);
        this.addQuestion(prompt, round(value,2), units, score);
      }
    },

    serializeQuestions: function(jqForms) {
      var self = this;
      jqForms.each(function (i) {
        var form = $(this);
        form.questions = [];
        self.forms.push(form);
        var inputs = form.find('input');
        inputs.each(function (j) {
          var question = [];
          question.input = $(this).val();
          var next = $(this).next();
          if ($(next).is('select')){
            question.select = next.val();
          }
          form.questions.push(question);
          self.userQuestions.push(question);
        });
      });
    },

    scoreAnswers: function() {
      var self = this;
      $.each(this.questions, function(i, question) {
        if (!!self.userQuestions[i]){
          var userQuestion = self.userQuestions[i];
          question.answer = userQuestion.input;
          if (question.answer == question.correct_answer){
            question.answerIsCorrect = true;
          }

          if (!!question.correct_units){
            question.units = userQuestion.select;
            if (question.units == question.correct_units){
              question.unitsIsCorrect = true;
            }
          } else {
            question.unitsIsCorrect = true;
          }
        }
      });
    },

    generateReport: function() {
      var $tbl = $('<table>').attr('id', 'basicTable');

      $tbl.append(
        $('<tr>').append(
          $('<th>').text("Question"),
          $('<th>').text("Your answer"),
          $('<th>').text("Correct answer"),
          $('<th>').text("Score"),
          $('<th>').text("Notes")
        )
      );

      var totalScore = 0;
      var totalPossibleScore = 0;

      $.each(this.questions, function(i, question){
        var answer = !!question.answer ? question.answer + (!!question.units ? " "+question.units : '') : '';
        var correctAnswer = question.correct_answer + (!!question.correct_units ? " "+question.correct_units : '');
        var score = question.answerIsCorrect && question.unitsIsCorrect ? question.score : 0;
        totalScore += score;
        totalPossibleScore += question.score;
        var feedback = "";
        if (answer === '') {

        } else if (!question.answerIsCorrect){
          feedback += "The value was wrong";
          if (!question.unitsIsCorrect){
            feedback += " and the units were wrong";
          }
        } else if (!question.unitsIsCorrect){
          feedback += "The units were wrong";
        }

        $tbl.append(
          $('<tr>').append(
            $('<td>').text(question.prompt),
            $('<td>').text(answer),
            $('<td>').text(correctAnswer),
            $('<td>').text(score +"/" + question.score),
            $('<td>').text(feedback)
          )
        );
      });

      $tbl.append(
        $('<tr>').append(
          $('<th>').text("Total Score:"),
          $('<th>').text(""),
          $('<th>').text(""),
          $('<th>').text(totalScore + "/" + totalPossibleScore),
          $('<th>').text("")
        )
      );

      return $tbl;
    }
  };
})();<commit_msg>Improve scoring algorithm (round to 3 s.f, then allow error of +-0.05)<commit_after>/*globals sparks $ */

(function() {

  var activity = sparks.Activity;

  activity.Question = function () {
      this.prompt = '';
      this.correct_answer = '';
      this.answer = '';
      this.correct_units = '';
      this.units = '';
      this.answerIsCorrect = false;
      this.unitsIsCorrect = false;
      this.start_time = null;
      this.end_time = null;
      this.score = 1;
  };

  activity.Assessment = function (activityLog) {
    this.activityLog = activityLog;
    this.questions = [];
    this.forms = [];
    this.userQuestions = [];
  };

  activity.Assessment.prototype =
  {
    addQuestion: function(prompt, correct_answer, correct_units, score) {
      var question = new activity.Question();
      question.prompt = prompt;
      question.correct_answer = correct_answer;
      question.correct_units = correct_units;
      question.score = score;
      this.questions.push(question);
    },

    addMeasurmentQuestion: function (prompt, value, units, score){

      function html_entity_decode(str) {
        var ta=document.createElement("textarea");
        ta.innerHTML=str.replace(/</g,"<").replace(/>/g,">");
        return ta.value;
      }

      if (value >= 1000000){
        var MUnits = html_entity_decode('M'+units);
        this.addQuestion(prompt, this._round(value/1000000,2), MUnits, score);
      } else if (value >= 1000){
        var kUnits = html_entity_decode('k'+units);
        this.addQuestion(prompt, this._round(value/1000,2), kUnits, score);
      } else if (value < 0.001){
        var uUnits = html_entity_decode('µ'+units);
        this.addQuestion(prompt, this._round(value * 1000000,2), uUnits, score);
      } else if (value < 1) {
        var mUnits = html_entity_decode('m'+units);
        this.addQuestion(prompt, this._round(value * 1000,2), mUnits, score);
      } else {
        units = html_entity_decode(units);
        this.addQuestion(prompt, this._round(value,2), units, score);
      }
    },

    serializeQuestions: function(jqForms) {
      var self = this;
      jqForms.each(function (i) {
        var form = $(this);
        form.questions = [];
        self.forms.push(form);
        var inputs = form.find('input');
        inputs.each(function (j) {
          var question = [];
          question.input = $(this).val();
          var next = $(this).next();
          if ($(next).is('select')){
            question.select = next.val();
          }
          form.questions.push(question);
          self.userQuestions.push(question);
        });
      });
    },

    scoreAnswers: function() {
      var self = this;
      $.each(this.questions, function(i, question) {
        if (!!self.userQuestions[i]){
          var userQuestion = self.userQuestions[i];
          question.answer = userQuestion.input;
          question.answer = parseFloat(question.answer);

          // first get numbers to 3 sig figs, then allow errors of 0.05 (rounding differences)
          var dif = self._sigFigs(question.answer,3) - self._sigFigs(question.correct_answer,3);
          if (dif <= 0.5 && dif >= -0.05){
            question.answerIsCorrect = true;
          }

          if (!!question.correct_units){
            question.units = userQuestion.select;
            if (question.units == question.correct_units){
              question.unitsIsCorrect = true;
            }
          } else {
            question.unitsIsCorrect = true;
          }
        }
      });
    },

    generateReport: function() {
      var $tbl = $('<table>').attr('id', 'basicTable');

      $tbl.append(
        $('<tr>').append(
          $('<th>').text("Question"),
          $('<th>').text("Your answer"),
          $('<th>').text("Correct answer"),
          $('<th>').text("Score"),
          $('<th>').text("Notes")
        )
      );

      var totalScore = 0;
      var totalPossibleScore = 0;

      $.each(this.questions, function(i, question){
        var answer = !!question.answer ? question.answer + (!!question.units ? " "+question.units : '') : '';
        var correctAnswer = question.correct_answer + (!!question.correct_units ? " "+question.correct_units : '');
        var score = question.answerIsCorrect && question.unitsIsCorrect ? question.score : 0;
        totalScore += score;
        totalPossibleScore += question.score;
        var feedback = "";
        if (answer === '') {

        } else if (!question.answerIsCorrect){
          feedback += "The value was wrong";
          if (!question.unitsIsCorrect){
            feedback += " and the units were wrong";
          }
        } else if (!question.unitsIsCorrect){
          feedback += "The units were wrong";
        }

        $tbl.append(
          $('<tr>').append(
            $('<td>').text(question.prompt),
            $('<td>').text(answer),
            $('<td>').text(correctAnswer),
            $('<td>').text(score +"/" + question.score),
            $('<td>').text(feedback)
          )
        );
      });

      $tbl.append(
        $('<tr>').append(
          $('<th>').text("Total Score:"),
          $('<th>').text(""),
          $('<th>').text(""),
          $('<th>').text(totalScore + "/" + totalPossibleScore),
          $('<th>').text("")
        )
      );

      return $tbl;
    },

    _round: function(num, dec) {
    	var result = Math.round( Math.round( num * Math.pow( 10, dec + 1 ) ) / Math.pow( 10, 1 ) ) / Math.pow(10,dec);
    	return result;
    },

    _sigFigs: function(n, sig) {
        var mult = Math.pow(10,
            sig - Math.floor(Math.log(n) / Math.LN10) - 1);
        return Math.round(n * mult) / mult;
    }

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


<commit_before>export { test };

import * as Base64ToUint8Array from "../Base64ToUint8Array.js";
import * as PartTime from "../PartTime.js";
import * as Random from "../Random.js";
import * as ScriptLoader from "../ScriptLoader.js";
import * as ValueMax from "../ValueMax.js";

// This string will not fit to ASCII when base64 decoded. So can not be used to test.
//const base64EncodedString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// Use all printable ASCII codes form a string of 3-divisible length.
// (So its base64-encoded codes will divisible by 4.)
let originalArray = [];
{
  const ORIGINAL_TEST_STRING_LENGTH = 3 * 4;

  const PRINTABLE_ASCII_MIN = 32;
  const PRINTABLE_ASCII_MAX = 126;

  for (let i = 0; i < ORIGINAL_TEST_STRING_LENGTH; ++i) {
    let c = Random.getIntInclusive(PRINTABLE_ASCII_MIN, PRINTABLE_ASCII_MAX);
    originalArray.push( String.fromCodePoint( c ) );
  }
}

const originalString = originalArray.join("");
const base64EncodedString = btoa(originalString);
const base64DecodedString = atob(base64EncodedString);

const base64EncodedStrings_extra = [
  // Test empty base64 content.
  "",
  "\n",
  "\r",
  "\r\n",
  "\n\r",

  // Test extra has 0 to 3 bytes. (They should be ignored.)
  base64EncodedString,
  base64EncodedString + base64EncodedString.slice(0, 1),
  base64EncodedString + base64EncodedString.slice(0, 2),
  base64EncodedString + base64EncodedString.slice(0, 3),

  // Test extra non-base64 codes inside. (They should be ignored.)
  base64EncodedString.slice(0, 3) + "\n"   + base64EncodedString.slice(3),
  base64EncodedString.slice(0, 3) + "\r"   + base64EncodedString.slice(3),
  base64EncodedString.slice(0, 3) + "\r\n" + base64EncodedString.slice(3),
  base64EncodedString.slice(0, 3) + "\n\r" + base64EncodedString.slice(3),

  // Test skip 3 lines. Test multiple non-base64 codes. (They should be ignored.)
  "qwerty5ASDFG7\n\n\r"
    + base64EncodedString.slice(0, 2) + "\n\n\r\r\r\n\r\n"
    + base64EncodedString.slice(2, 7) + "\n\n\r\r\r\n\r\n"
    + base64EncodedString.slice(7, 9) + "\n\n\r\r\r\n\r\n"
    + base64EncodedString.slice(9)    + "\n\n\r\r\r\n\r\n",
];

let tEncoder = new TextEncoder();
let tDecoder = new TextDecoder();

//const base64EncodedUint8Array = tDecoder.decode(base64EncodedString);
const base64DecodedUint8Array = tEncoder.encode(base64DecodedString);
const emptyUint8Array = new Uint8Array(0);

class TestCase {
  constructor(source, skipLineCount, result, suspendByteCount, note) {
    this.source = source;
    this.skipLineCount = skipLineCount;
    this.result = result;
    this.suspendByteCount = suspendByteCount;
    this.note = note;
  }
}

let testCases = [
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 0]), 1, emptyUint8Array, undefined, "Empty. Not enough lines." ),

  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 0]), 0, emptyUint8Array,         3, "Empty" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 1]), 1, emptyUint8Array,         2, "LF Empty" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 2]), 1, emptyUint8Array,         5, "CR Empty" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 3]), 1, emptyUint8Array, undefined, "CRLF Empty" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 4]), 2, emptyUint8Array,         5, "LFCR Empty" ),

  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 5]), 0, base64DecodedUint8Array,        15, "Extra 0 bytes" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 6]), 0, base64DecodedUint8Array,         7, "Extra 1 bytes" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 7]), 0, base64DecodedUint8Array,        17, "Extra 2 bytes" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 8]), 0, base64DecodedUint8Array,         8, "Extra 3 bytes" ),

  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 9]), 0, base64DecodedUint8Array,         4, "Extra LF inside" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[10]), 0, base64DecodedUint8Array,         3, "Extra CR inside" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[11]), 0, base64DecodedUint8Array,         5, "Extra CRLF inside" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[12]), 0, base64DecodedUint8Array,        11, "Extra LFCR inside" ),

  new TestCase( tEncoder.encode("\n"   + base64EncodedString), 1, base64DecodedUint8Array,         5, "Begin LF" ),
  new TestCase( tEncoder.encode("\r"   + base64EncodedString), 1, base64DecodedUint8Array,         5, "Begin CR" ),
  new TestCase( tEncoder.encode("\r\n" + base64EncodedString), 1, base64DecodedUint8Array,         5, "Begin CRLF" ),
  new TestCase( tEncoder.encode("\n\r" + base64EncodedString), 2, base64DecodedUint8Array,         5, "Begin LFCR" ),

  new TestCase( tEncoder.encode("qwerty\n"   + base64EncodedString), 1, base64DecodedUint8Array,         6, "Text LF" ),
  new TestCase( tEncoder.encode("qwerty\r"   + base64EncodedString), 1, base64DecodedUint8Array, undefined, "Text CR" ),
  new TestCase( tEncoder.encode("qwerty\r\n" + base64EncodedString), 1, base64DecodedUint8Array,      2048, "Text CRLF" ),
  new TestCase( tEncoder.encode("qwerty\n\r" + base64EncodedString), 2, base64DecodedUint8Array,         7, "Text LFCR" ),

  new TestCase( tEncoder.encode(base64EncodedStrings_extra[13]), 3, base64DecodedUint8Array, 8, "Multiple LF and CR inside" ),
];

/** Aggregate all progress about downloading, JSON parsing, characters scanning, and weights scanning.  */
class Progress extends ValueMax.Percentage.Aggregate {
  constructor() {
    let children = new Array( testCases.length );
    for (let i = 0; i < testCases.length; ++i) {
      children[ i ] = new ValueMax.Percentage.Aggregate(); // Increased when parsing the downloaded data to Uint8Array.
    }

    super(children);
  }
}

window.addEventListener("load", event => {
  ScriptLoader.createPromise("https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.7.0/dist/tf.min.js").then(test); });

/**
 *
 * @param {ValueMax.Percentage.Aggregate} progressParent
 *   Some new progressToAdvance will be created and added to progressParent. The created progressToAdvance will be
 * increased when every time advanced. The progressParent.getRoot() will be returned when every time yield.
 *
 */
function test( progressParent ) {
  console.log("Base64 decode testing...");
  let delayMilliseconds = 1000;

  let progress = progressParent.addChild( new Progress() );
  let progressReceiver = new ValueMax.Receiver.HTMLProgress.createByTitle_or_getDummy("TestProgressBar");

  let testPromiseAll = [];
  for (let i = 0; i < testCases.length; ++i) {
    let testCase = testCases[ i ];

    let decoder = Base64ToUint8Array.decoder_FromArrayBuffer(
        testCase.source, testCase.skipLineCount, progress.children[ i ], testCase.suspendByteCount);

    let testPromise = PartTime.forOf(
      decoder,
      ( valueMax ) => { progressReceiver.setValueMax( valueMax.valuePercentage, valueMax.maxPercentage ); }, // Report progress to UI.
      delayMilliseconds
    ).then(r => {
      progressReceiver.informDone(r); // Inform UI progress done.
      tf.util.assert(
        r.toString() == testCase.result.toString(),
        `[${i}]`
          + ` Skip ${testCase.skipLineCount} lines.`
          + ` suspendByteCount=${testCase.suspendByteCount}.`
          + ` ${testCase.note} [${r}] != [${testCase.result}]`);
    });

    testPromiseAll.push( testPromise );
  }

  Promise.all(testPromiseAll).then(values => {
    console.log("Base64 decode testing... Done.");
  });
}
<commit_msg>Update Base64ToUint8Array_tester.js<commit_after>export { tester };

import * as Base64ToUint8Array from "../Base64ToUint8Array.js";
import * as PartTime from "../PartTime.js";
import * as Random from "../Random.js";
import * as ScriptLoader from "../ScriptLoader.js";
import * as ValueMax from "../ValueMax.js";

// This string will not fit to ASCII when base64 decoded. So can not be used to test.
//const base64EncodedString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// Use all printable ASCII codes form a string of 3-divisible length.
// (So its base64-encoded codes will divisible by 4.)
let originalArray = [];
{
  const ORIGINAL_TEST_STRING_LENGTH = 3 * 4;

  const PRINTABLE_ASCII_MIN = 32;
  const PRINTABLE_ASCII_MAX = 126;

  for (let i = 0; i < ORIGINAL_TEST_STRING_LENGTH; ++i) {
    let c = Random.getIntInclusive(PRINTABLE_ASCII_MIN, PRINTABLE_ASCII_MAX);
    originalArray.push( String.fromCodePoint( c ) );
  }
}

const originalString = originalArray.join("");
const base64EncodedString = btoa(originalString);
const base64DecodedString = atob(base64EncodedString);

const base64EncodedStrings_extra = [
  // Test empty base64 content.
  "",
  "\n",
  "\r",
  "\r\n",
  "\n\r",

  // Test extra has 0 to 3 bytes. (They should be ignored.)
  base64EncodedString,
  base64EncodedString + base64EncodedString.slice(0, 1),
  base64EncodedString + base64EncodedString.slice(0, 2),
  base64EncodedString + base64EncodedString.slice(0, 3),

  // Test extra non-base64 codes inside. (They should be ignored.)
  base64EncodedString.slice(0, 3) + "\n"   + base64EncodedString.slice(3),
  base64EncodedString.slice(0, 3) + "\r"   + base64EncodedString.slice(3),
  base64EncodedString.slice(0, 3) + "\r\n" + base64EncodedString.slice(3),
  base64EncodedString.slice(0, 3) + "\n\r" + base64EncodedString.slice(3),

  // Test skip 3 lines. Test multiple non-base64 codes. (They should be ignored.)
  "qwerty5ASDFG7\n\n\r"
    + base64EncodedString.slice(0, 2) + "\n\n\r\r\r\n\r\n"
    + base64EncodedString.slice(2, 7) + "\n\n\r\r\r\n\r\n"
    + base64EncodedString.slice(7, 9) + "\n\n\r\r\r\n\r\n"
    + base64EncodedString.slice(9)    + "\n\n\r\r\r\n\r\n",
];

let tEncoder = new TextEncoder();
let tDecoder = new TextDecoder();

//const base64EncodedUint8Array = tDecoder.decode(base64EncodedString);
const base64DecodedUint8Array = tEncoder.encode(base64DecodedString);
const emptyUint8Array = new Uint8Array(0);

class TestCase {
  constructor(source, skipLineCount, result, suspendByteCount, note) {
    this.source = source;
    this.skipLineCount = skipLineCount;
    this.result = result;
    this.suspendByteCount = suspendByteCount;
    this.note = note;
  }
}

let testCases = [
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 0]), 1, emptyUint8Array, undefined, "Empty. Not enough lines." ),

  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 0]), 0, emptyUint8Array,         3, "Empty" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 1]), 1, emptyUint8Array,         2, "LF Empty" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 2]), 1, emptyUint8Array,         5, "CR Empty" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 3]), 1, emptyUint8Array, undefined, "CRLF Empty" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 4]), 2, emptyUint8Array,         5, "LFCR Empty" ),

  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 5]), 0, base64DecodedUint8Array,        15, "Extra 0 bytes" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 6]), 0, base64DecodedUint8Array,         7, "Extra 1 bytes" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 7]), 0, base64DecodedUint8Array,        17, "Extra 2 bytes" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 8]), 0, base64DecodedUint8Array,         8, "Extra 3 bytes" ),

  new TestCase( tEncoder.encode(base64EncodedStrings_extra[ 9]), 0, base64DecodedUint8Array,         4, "Extra LF inside" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[10]), 0, base64DecodedUint8Array,         3, "Extra CR inside" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[11]), 0, base64DecodedUint8Array,         5, "Extra CRLF inside" ),
  new TestCase( tEncoder.encode(base64EncodedStrings_extra[12]), 0, base64DecodedUint8Array,        11, "Extra LFCR inside" ),

  new TestCase( tEncoder.encode("\n"   + base64EncodedString), 1, base64DecodedUint8Array,         5, "Begin LF" ),
  new TestCase( tEncoder.encode("\r"   + base64EncodedString), 1, base64DecodedUint8Array,         5, "Begin CR" ),
  new TestCase( tEncoder.encode("\r\n" + base64EncodedString), 1, base64DecodedUint8Array,         5, "Begin CRLF" ),
  new TestCase( tEncoder.encode("\n\r" + base64EncodedString), 2, base64DecodedUint8Array,         5, "Begin LFCR" ),

  new TestCase( tEncoder.encode("qwerty\n"   + base64EncodedString), 1, base64DecodedUint8Array,         6, "Text LF" ),
  new TestCase( tEncoder.encode("qwerty\r"   + base64EncodedString), 1, base64DecodedUint8Array, undefined, "Text CR" ),
  new TestCase( tEncoder.encode("qwerty\r\n" + base64EncodedString), 1, base64DecodedUint8Array,      2048, "Text CRLF" ),
  new TestCase( tEncoder.encode("qwerty\n\r" + base64EncodedString), 2, base64DecodedUint8Array,         7, "Text LFCR" ),

  new TestCase( tEncoder.encode(base64EncodedStrings_extra[13]), 3, base64DecodedUint8Array, 8, "Multiple LF and CR inside" ),
];

/** Aggregate all progress about downloading, JSON parsing, characters scanning, and weights scanning.  */
class Progress extends ValueMax.Percentage.Aggregate {
  constructor() {
    let children = new Array( testCases.length );
    for (let i = 0; i < testCases.length; ++i) {
      children[ i ] = new ValueMax.Percentage.Aggregate(); // Increased when parsing the downloaded data to Uint8Array.
    }

    super(children);
  }
}

window.addEventListener("load", event => {
  ScriptLoader.createPromise("https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.7.0/dist/tf.min.js").then(test); });

/**
 *
 * @param {ValueMax.Percentage.Aggregate} progressParent
 *   Some new progressToAdvance will be created and added to progressParent. The created progressToAdvance will be
 * increased when every time advanced. The progressParent.getRoot() will be returned when every time yield.
 *
 */
function* tester( progressParent ) {
  console.log("Base64 decode testing...");

  let progress = progressParent.addChild( new Progress() );

  for (let i = 0; i < testCases.length; ++i) {
    let testCase = testCases[ i ];

    let decoder = Base64ToUint8Array.decoder_FromArrayBuffer(
        testCase.source, testCase.skipLineCount, progress.children[ i ], testCase.suspendByteCount);

    let r = yield* decoder;

    tf.util.assert(
      r.toString() == testCase.result.toString(),
      `[${i}]`
        + ` Skip ${testCase.skipLineCount} lines.`
        + ` suspendByteCount=${testCase.suspendByteCount}.`
        + ` ${testCase.note} [${r}] != [${testCase.result}]`);
  }

  console.log("Base64 decode testing... Done.");
}

/*!!! Old (2020/12/13 Remarked)
function test( progressParent ) {
  console.log("Base64 decode testing...");
  let delayMilliseconds = 1000;

  let progress = progressParent.addChild( new Progress() );
  let progressReceiver = new ValueMax.Receiver.HTMLProgress.createByTitle_or_getDummy("TestProgressBar");

  let testPromiseAll = [];
  for (let i = 0; i < testCases.length; ++i) {
    let testCase = testCases[ i ];

    let decoder = Base64ToUint8Array.decoder_FromArrayBuffer(
        testCase.source, testCase.skipLineCount, progress.children[ i ], testCase.suspendByteCount);

    let testPromise = PartTime.forOf(
      decoder,
      ( valueMax ) => { progressReceiver.setValueMax( valueMax.valuePercentage, valueMax.maxPercentage ); }, // Report progress to UI.
      delayMilliseconds
    ).then(r => {
      progressReceiver.informDone(r); // Inform UI progress done.
      tf.util.assert(
        r.toString() == testCase.result.toString(),
        `[${i}]`
          + ` Skip ${testCase.skipLineCount} lines.`
          + ` suspendByteCount=${testCase.suspendByteCount}.`
          + ` ${testCase.note} [${r}] != [${testCase.result}]`);
    });

    testPromiseAll.push( testPromise );
  }

  Promise.all(testPromiseAll).then(values => {
    console.log("Base64 decode testing... Done.");
  });
}
*/
<|endoftext|>


<commit_before>'use strict';

// <%= name %>-model.js - A sequelize model
//
// See http://docs.sequelizejs.com/en/latest/docs/models-definition/
// for more of what you can do here.

const Sequelize = require('sequelize');

module.exports = function(sequelize) {
  const <%= name %> = sequelize.define('<%= name %>', {
    <% if(name === 'user') { %>email: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: true
    }, password: {
      type: Sequelize.STRING,
      allowNull: false
    }<% } else { %>text: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: true,
      validate: {
        isAlphanumeric: { msg: '`text` must only contain alpha numeric characters' }
      }
    }<% } %>
  }, {
    freezeTableName: true
  });

  <%= name %>.sync({ force: true });

  return <%= name %>;
};
<commit_msg>Remove sequelize default model constraints<commit_after>'use strict';

// <%= name %>-model.js - A sequelize model
//
// See http://docs.sequelizejs.com/en/latest/docs/models-definition/
// for more of what you can do here.

const Sequelize = require('sequelize');

module.exports = function(sequelize) {
  const <%= name %> = sequelize.define('<%= name %>', {
    <% if(name === 'user') { %>email: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: true
    }, password: {
      type: Sequelize.STRING,
      allowNull: false
    }<% } else { %>text: {
      type: Sequelize.STRING,
      allowNull: false
    }<% } %>
  }, {
    freezeTableName: true
  });

  <%= name %>.sync({ force: true });

  return <%= name %>;
};
<|endoftext|>


<commit_before>const CodecProvider = require('../../codec/codec_provider');
const EventEmitter  = require('../../misc/event_emitter');

class Property {
	constructor(builder) {
		this.target_ = builder.getTarget();
		this.propName_ = builder.getPropertyName();
		this.label_ = builder.getLabel();
		this.id_ = builder.getId();
		this.forMonitor_ = builder.isForMonitor();

		this.model_ = builder.getModel();
		this.codec_ = CodecProvider.provide(this.model_);

		this.emitter_ = new EventEmitter();
	}

	getEmitter() {
		return this.emitter_;
	}

	getTarget() {
		return this.target_;
	}

	getPropertyName() {
		return this.propName_;
	}

	getId() {
		return this.id_;
	}

	getLabel() {
		return this.label_;
	}

	getModel() {
		return this.model_;
	}

	getCodec() {
		return this.codec_;
	}

	getValue() {
		return this.codec_.encode(
			this.model_.getValue()
		);
	}

	isForMonitor() {
		return this.forMonitor_;
	}

	setValue(value, opt_updatesSource) {
		if (!this.codec_.canDecode(value)) {
			return false;
		}

		const decodedValue = this.codec_.decode(value);

		const updatesSource = (opt_updatesSource !== undefined) ?
			opt_updatesSource :
			false;
		if (updatesSource) {
			this.target_[this.propName_] = decodedValue;
		}

		this.model_.setValue(decodedValue);

		return true;
	}

	applySourceValue() {
		this.setValue(this.target_[this.propName_]);
	}
}

Property.EVENT_MODEL_CHANGE = 'modelchange';

module.exports = Property;
<commit_msg>Remove unused event<commit_after>const CodecProvider = require('../../codec/codec_provider');
const EventEmitter  = require('../../misc/event_emitter');

class Property {
	constructor(builder) {
		this.target_ = builder.getTarget();
		this.propName_ = builder.getPropertyName();
		this.label_ = builder.getLabel();
		this.id_ = builder.getId();
		this.forMonitor_ = builder.isForMonitor();

		this.model_ = builder.getModel();
		this.codec_ = CodecProvider.provide(this.model_);

		this.emitter_ = new EventEmitter();
	}

	getEmitter() {
		return this.emitter_;
	}

	getTarget() {
		return this.target_;
	}

	getPropertyName() {
		return this.propName_;
	}

	getId() {
		return this.id_;
	}

	getLabel() {
		return this.label_;
	}

	getModel() {
		return this.model_;
	}

	getCodec() {
		return this.codec_;
	}

	getValue() {
		return this.codec_.encode(
			this.model_.getValue()
		);
	}

	isForMonitor() {
		return this.forMonitor_;
	}

	setValue(value, opt_updatesSource) {
		if (!this.codec_.canDecode(value)) {
			return false;
		}

		const decodedValue = this.codec_.decode(value);

		const updatesSource = (opt_updatesSource !== undefined) ?
			opt_updatesSource :
			false;
		if (updatesSource) {
			this.target_[this.propName_] = decodedValue;
		}

		this.model_.setValue(decodedValue);

		return true;
	}

	applySourceValue() {
		this.setValue(this.target_[this.propName_]);
	}
}

module.exports = Property;
<|endoftext|>


<commit_before>/**
 * This file contains code to setup the SDK client and detect whether the user is logged in.
 */

// Setup the SDK client
var client = new FamilySearch({

  // A client ID for sandbox is obtained by registering with the FamilySearch developer's website
  client_id: 'a02j0000008gOCiAAM',

  // When using the JavaScript SDK, the redirect uri doesn't need to be a
  // page that actually exists, it just needs to be a page on the same domain.
  // Here we programmatically set the redirect uri to the base path of the
  // current domain. That helps the sample app work wherever it runs so
  // that we don't have to change this between development and production.
  redirect_uri: document.location.origin + '/',

  // Store the access token in a cookie so that the user doesn't have to
  // login every time the page loads
  save_access_token: true,

  // Sandbox is the testing environment
  environment: 'sandbox'
});

// In this next section we are populating the username in the header.
// First we check if the username is stored in a cookie. If we are logged in
// (have an access token) but don't have a username then we request the
// current user from the API and save the username in a cookie.
var promise;
if(cookiesUtil.getItem('username')){
  promise = Promise.resolve(cookiesUtil.getItem('username'));
} else if(client.hasAccessToken()){
  promise = client.getCurrentUser().then(function(response){
    var username = response.getUser().getContactName();
    // Expire cookie after 24 hours (86400 seconds)
    cookiesUtil.setItem('username', username, 86400);
    return username;
  });
}

// Here we know that the user is not logged in. Show a warning on all example
// pages telling the user that they need to login for the example to work.
else {
  if(document.location.pathname.indexOf('/examples/') === 0 && document.location.pathname.indexOf('authentication') === -1){
    $('
')
      .addClass('alert alert-warning')
      .html('You need to sign in first for the examples to work. Sign in with the FamilySearch Authentication example.')
      .appendTo('#main');
  }
}

// If we have a username then add it to the header
if(promise){
  promise.then(function(username){
    $('#username').text(username);
    $('#signOut').click(signOut).show();
  });
}

function signOut(){
  client.invalidateAccessToken();
  cookiesUtil.removeItem('username');
  document.location.reload();
}<commit_msg>fix #1<commit_after>/**
 * This file contains code to setup the SDK client and detect whether the user is logged in.
 */

// Setup the SDK client
var client = new FamilySearch({

  // A client ID for sandbox is obtained by registering with the FamilySearch developer's website
  client_id: 'a02j0000008gOCiAAM',

  // When using the JavaScript SDK, the redirect uri doesn't need to be a
  // page that actually exists, it just needs to be a page on the same domain.
  // Here we programmatically set the redirect uri to the base path of the
  // current domain. That helps the sample app work wherever it runs so
  // that we don't have to change this between development and production.
  redirect_uri: document.location.protocol + '//' + document.location.host + '/',

  // Store the access token in a cookie so that the user doesn't have to
  // login every time the page loads
  save_access_token: true,

  // Sandbox is the testing environment
  environment: 'sandbox'
});

// In this next section we are populating the username in the header.
// First we check if the username is stored in a cookie. If we are logged in
// (have an access token) but don't have a username then we request the
// current user from the API and save the username in a cookie.
var promise;
if(cookiesUtil.getItem('username')){
  promise = Promise.resolve(cookiesUtil.getItem('username'));
} else if(client.hasAccessToken()){
  promise = client.getCurrentUser().then(function(response){
    var username = response.getUser().getContactName();
    // Expire cookie after 24 hours (86400 seconds)
    cookiesUtil.setItem('username', username, 86400);
    return username;
  });
}

// Here we know that the user is not logged in. Show a warning on all example
// pages telling the user that they need to login for the example to work.
else {
  if(document.location.pathname.indexOf('/examples/') === 0 && document.location.pathname.indexOf('authentication') === -1){
    $('
')
      .addClass('alert alert-warning')
      .html('You need to sign in first for the examples to work. Sign in with the FamilySearch Authentication example.')
      .appendTo('#main');
  }
}

// If we have a username then add it to the header
if(promise){
  promise.then(function(username){
    $('#username').text(username);
    $('#signOut').click(signOut).show();
  });
}

function signOut(){
  client.invalidateAccessToken();
  cookiesUtil.removeItem('username');
  document.location.reload();
}<|endoftext|>


<commit_before>const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const SplitByPathPlugin = require('webpack-split-by-path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
const path = require('path');

const { NODE_ENV } = process.env;

const plugins = [
    new webpack.ProvidePlugin({
        RealDOM: path.join(__dirname, '../packages/frontend/js/realdom')
    }),
    new ExtractTextPlugin({
        filename: 'css/style.css',
        allChunks: true
    }),
    new HtmlWebpackPlugin({
        template: 'index.html',
        chunksSortMode: (a, b) => {
            const order = ['manifest', 'vendor', 'app'];
            const nameA = a.names[0];
            const nameB = b.names[0];

            return order.indexOf(nameA) - order.indexOf(nameB);
        }
    }),
    new CopyWebpackPlugin([{ from: 'icons', to: 'icons' }]),
    new SplitByPathPlugin([{
        name: 'vendor',
        path: path.join(__dirname, '..', 'packages/frontend/node_modules/')
    }], {
        // fix https://github.com/webpack/extract-text-webpack-plugin/issues/92
        ignore: [/\.css/]
    })
];

if (NODE_ENV === 'production') {
    plugins.push(
        new UglifyJsPlugin({
            compress: {
                warnings: false
            }
        })
    );
}

if (NODE_ENV === 'development') {
    plugins.push(
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.HotModuleReplacementPlugin()
    );
}

module.exports = plugins;
<commit_msg>fix: Typo at webpack file<commit_after>const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const SplitByPathPlugin = require('webpack-split-by-path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const path = require('path');

const { NODE_ENV } = process.env;

const plugins = [
    new webpack.ProvidePlugin({
        RealDOM: path.join(__dirname, '../packages/frontend/js/realdom')
    }),
    new ExtractTextPlugin({
        filename: 'css/style.css',
        allChunks: true
    }),
    new HtmlWebpackPlugin({
        template: 'index.html',
        chunksSortMode: (a, b) => {
            const order = ['manifest', 'vendor', 'app'];
            const nameA = a.names[0];
            const nameB = b.names[0];

            return order.indexOf(nameA) - order.indexOf(nameB);
        }
    }),
    new CopyWebpackPlugin([{ from: 'icons', to: 'icons' }]),
    new SplitByPathPlugin([{
        name: 'vendor',
        path: path.join(__dirname, '..', 'packages/frontend/node_modules/')
    }], {
        // fix https://github.com/webpack/extract-text-webpack-plugin/issues/92
        ignore: [/\.css/]
    })
];

if (NODE_ENV === 'production') {
    plugins.push(
        new UglifyJSPlugin({
            compress: {
                warnings: false
            }
        })
    );
}

if (NODE_ENV === 'development') {
    plugins.push(
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.HotModuleReplacementPlugin()
    );
}

module.exports = plugins;
<|endoftext|>


<commit_before>/*********************************************************************
* #### CI File Browser Awesome v01 ####
* Coded by Ican Bachors 2015.
* https://github.com/bachors/CI-FIle-Browser-Awesome
* Updates will be posted to this site.
*********************************************************************/

// Setting: Base_URL/Controllers_name
var baseurl = 'http://your-domain.com/file';

// Folder yang akan discan
var browser = 'download';

/* Testing di localhost */
var fix = /\\/;

/* atau jika tombol back bermasalah ketika sudah di hosting gunakan script dibawah ini:
var fix = /\//;
*/

var value = getParameterByName('dir');
if(value != ''){
	if(value.indexOf('.') === -1){
		ibc_fba(baseurl,sub=value,fix,browser);
	}else{
		var valust = value.substring(value.lastIndexOf('/') + 1),
		gehu = value.replace('/'+valust, "");
		ibc_fba(baseurl,sub=gehu,fix,browser);
		ibc_fba_file(baseurl,browser+value);
	}
}else{
	ibc_fba(baseurl,sub="",fix,browser)
}

function ibc_fba(baseurl,sub,fix,browser) {
	$.ajax( {
		url:baseurl+'?sub='+sub,
		crossDomain:true,
		dataType:"json"
	}).done(function(data) {
		var r="";
		r+="
";
		r+='

Name	Size	Last Modified

';
		if(data.back!="") {
			r+='
 '+data.root+unescape( '%3C%61%20%68%72%65%66%3D%27%68%74%74%70%3A%2F%2F%69%62%61%63%6F%72%2E%63%6F%6D%2F%6C%61%62%73%2F%6A%71%75%65%72%79%2D%66%69%6C%65%2D%62%72%6F%77%73%65%72%2D%61%77%65%73%6F%6D%65%27%20%74%69%74%6C%65%3D%27%6A%51%75%65%72%79%20%46%69%6C%65%20%42%72%6F%77%73%65%72%20%41%77%65%73%6F%6D%65%27%20%73%74%79%6C%65%3D%27%66%6C%6F%61%74%3A%72%69%67%68%74%27%20%74%61%72%67%65%74%3D%27%5F%42%4C%41%4E%4B%27%3E%3C%69%20%63%6C%61%73%73%3D%27%66%61%20%66%61%2D%69%6E%66%6F%2D%63%69%72%63%6C%65%27%3E%3C%2F%69%3E%3C%2F%61%3E%3C%2F%74%64%3E%3C%2F%74%72%3E' )
		}
		$.each(data.items,function(i,item) {
			var size=ibc_ukurana(data.items[i].size);
			if(data.items[i].type=="folder") {
				r+='
 '+data.items[i].name+'	'+data.items[i].items.length+' item	'+data.items[i].modif+'
';
			} else {
				var s=data.items[i].path.substr(data.items[i].path.lastIndexOf(".")+1);
				switch(s) {
					// List read file. Custom/add example case"asp":case"jsp" etc
					case"html":
					case"php":
					case"js":
					case"css":
					case"txt":
					r+='
 '+data.items[i].name+'	'+size+'	'+data.items[i].modif+'
';
					break;
					// List download file
					default:
					r+='
 '+data.items[i].name+'	'+size+'	'+data.items[i].modif+'
';
				}
			}
		});
		r+="

";
		$(".ibc_fba").html(r);
		$(".sub").click(function() {
			var t=$(this).data("sub");
			ibc_fba(baseurl,t,fix,browser);
			window.history.pushState(null, null, "?dir="+t);
			return false
		});
		$(".bsub").click(function() {
			var t=$(this).data("bsub");
			ibc_fba(baseurl,t,fix,browser);
			window.history.pushState(null, null, "?dir="+t);
			return false
		});
		$(".rfile").click(function() {
			var file=$(this).data("rfile");
			ibc_fba_file(baseurl,file);
			window.history.pushState(null, null, "?dir="+file.replace(browser, ""));
			return false
		});
	});
}

function ibc_fba_file(baseurl,file) {
	$.ajax( {
		url:baseurl+'?file='+file,
		crossDomain:true,
		dataType:"json"
	}).done(function(data) {
		editor.setValue(data.text);
	});
}

function ibc_ukurana(e) {
	var t=["Bytes","KB","MB","GB","TB"];
	if(e==0)return"0 Bytes";
	var n=parseInt(Math.floor(Math.log(e)/Math.log(1024)));
	return Math.round(e/Math.pow(1024,n),2)+" "+t[n]
}

function getParameterByName(name) {
	name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
	var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
	results = regex.exec(location.search);
	return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
<commit_msg>Update fba.js<commit_after>/*********************************************************************
* #### CI File Browser Awesome v01 ####
* Coded by Ican Bachors 2015.
* https://github.com/bachors/CI-FIle-Browser-Awesome
* Updates will be posted to this site.
*********************************************************************/

// Setting: Base_URL/Controllers_name
var baseurl = 'http://your-domain.com/file';

// Folder yang akan discan
var browser = 'download';

/* Testing di localhost */
var fix = /\\/;

/* atau jika tombol back bermasalah ketika sudah di hosting gunakan script dibawah ini:
var fix = /\//;
*/

var value = getParameterByName('dir');
if(value != ''){
	if(value.indexOf('.') === -1){
		ibc_fba(baseurl,value,fix,browser);
	}else{
		var valust = value.substring(value.lastIndexOf('/') + 1),
		gehu = value.replace('/'+valust, "");
		ibc_fba(baseurl,gehu,fix,browser);
		ibc_fba_file(baseurl,browser+value);
	}
}else{
	ibc_fba(baseurl,"",fix,browser)
}

function ibc_fba(baseurl,sub,fix,browser) {
	$.ajax( {
		url:baseurl+'?sub='+sub,
		crossDomain:true,
		dataType:"json"
	}).done(function(data) {
		var r="";
		r+="
";
		r+='

Name	Size	Last Modified

';
		if(data.back!="") {
			r+='
 '+data.root+unescape( '%3C%61%20%68%72%65%66%3D%27%68%74%74%70%3A%2F%2F%69%62%61%63%6F%72%2E%63%6F%6D%2F%6C%61%62%73%2F%6A%71%75%65%72%79%2D%66%69%6C%65%2D%62%72%6F%77%73%65%72%2D%61%77%65%73%6F%6D%65%27%20%74%69%74%6C%65%3D%27%6A%51%75%65%72%79%20%46%69%6C%65%20%42%72%6F%77%73%65%72%20%41%77%65%73%6F%6D%65%27%20%73%74%79%6C%65%3D%27%66%6C%6F%61%74%3A%72%69%67%68%74%27%20%74%61%72%67%65%74%3D%27%5F%42%4C%41%4E%4B%27%3E%3C%69%20%63%6C%61%73%73%3D%27%66%61%20%66%61%2D%69%6E%66%6F%2D%63%69%72%63%6C%65%27%3E%3C%2F%69%3E%3C%2F%61%3E%3C%2F%74%64%3E%3C%2F%74%72%3E' )
		}
		$.each(data.items,function(i,item) {
			var size=ibc_ukurana(data.items[i].size);
			if(data.items[i].type=="folder") {
				r+='
 '+data.items[i].name+'	'+data.items[i].items.length+' item	'+data.items[i].modif+'
';
			} else {
				var s=data.items[i].path.substr(data.items[i].path.lastIndexOf(".")+1);
				switch(s) {
					// List read file. Custom/add example case"asp":case"jsp" etc
					case"html":
					case"php":
					case"js":
					case"css":
					case"txt":
					r+='
 '+data.items[i].name+'	'+size+'	'+data.items[i].modif+'
';
					break;
					// List download file
					default:
					r+='
 '+data.items[i].name+'	'+size+'	'+data.items[i].modif+'
';
				}
			}
		});
		r+="

";
		$(".ibc_fba").html(r);
		$(".sub").click(function() {
			var t=$(this).data("sub");
			ibc_fba(baseurl,t,fix,browser);
			window.history.pushState(null, null, "?dir="+t);
			return false
		});
		$(".bsub").click(function() {
			var t=$(this).data("bsub");
			ibc_fba(baseurl,t,fix,browser);
			window.history.pushState(null, null, "?dir="+t);
			return false
		});
		$(".rfile").click(function() {
			var file=$(this).data("rfile");
			ibc_fba_file(baseurl,file);
			window.history.pushState(null, null, "?dir="+file.replace(browser, ""));
			return false
		});
	});
}

function ibc_fba_file(baseurl,file) {
	$.ajax( {
		url:baseurl+'?file='+file,
		crossDomain:true,
		dataType:"json"
	}).done(function(data) {
		editor.setValue(data.text);
	});
}

function ibc_ukurana(e) {
	var t=["Bytes","KB","MB","GB","TB"];
	if(e==0)return"0 Bytes";
	var n=parseInt(Math.floor(Math.log(e)/Math.log(1024)));
	return Math.round(e/Math.pow(1024,n),2)+" "+t[n]
}

function getParameterByName(name) {
	name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
	var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
	results = regex.exec(location.search);
	return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
<|endoftext|>


<commit_before>/////////////////////////////////////////
//                                     //
// ADD METHODS TO SPOT_MESSAGE OBJECTS //
//                                     //
/////////////////////////////////////////
//
// method to identify TRACK only type messages
SPOT_MESSAGE.prototype.isTrack = function()
{
	if("TRACK" == this.type)
		return true;
	return false;
}

// Get earlier data
FEEDS.getHistory=function()
{
// *******************************************************************************
// Should this check for SPOT only???
	for(var ix=0; ix<FEEDS.feed.length; ix++)
		FEEDS.feed[ix].update(FEEDS.feed[ix].onUpdate, null, true);
}

// Display a feed
// Separating this out makes it easier to cope with non-referesh updates
SPOT_FEED.prototype.onUpdate = function(feed)
{
	var insertCell=function(tblRow, html, align)
	{
		if(!align)
			align="right";

		var newCell=tblRow.insertCell(-1);
		newCell.align=align;
		newCell.innerHTML=html;
	};

	// We have a TBODY for each feed, not TRACKER
	var tbody=document.createElement("tbody");

	tbody.innerHTML=
		"
"
		+feed.name+
		"
";

	for(var trackerIx=0; trackerIx<feed.tracker.length; trackerIx++)
	{
		var tracker=feed.tracker[trackerIx];

		// Define additional variable to store whether to display all tracks
		if(!tracker.trackMsgs)
			tracker.trackMsgs="hide"	// Default: Hide non-latest

		tbody.insertRow(-1).innerHTML=
			""
			+tracker.name+
			"	";

		// First we count the number of TRACK messages if hiding them
		var trackMsgCount=-1;
		if("hide"==tracker.trackMsgs)
		{
			trackMsgCount=0;
			for(var msgIx=0; msgIx<tracker.message.length; msgIx++)
				if(tracker.message[msgIx].isTrack())
					trackMsgCount++;
		}

		//Messages are already in reverse Chronological order
		for(var msgIx=0; msgIx<tracker.message.length; msgIx++)
		{
			var message=tracker.message[msgIx];

			var osgb=message.getOSGB();

			var row=tbody.insertRow(-1);
			row.title=message.type;

			insertCell(row,DAYS[message.time.getDay()]);
			insertCell(row,message.time.toLocaleTimeString());
			insertCell(row,"");
			insertCell(row,""+
				osgb.getGridRef(3)+"");

			if(tracker.message.length-1 > msgIx)
			{
				// Reverse chronological order, hence previous in time
				// is next in the array
				var previousMessage=tracker.message[msgIx+1];

				// Speed
				// km/s =           dist(km) /  time(s)
				// km/h = 3600    * dist(km) / (time(ms) / 1000)
				// km/h = 3600000 * dist(km) / time(ms)
				insertCell(row,(
					3600000*message.getDistance(previousMessage) /
					(message.time.getTime()-previousMessage.time.getTime())
					).toFixed(1)+" km/h");

				insertCell(row,
					previousMessage.getHeading(message).toFixed(0)
					+" deg");
			}
			else
			{
				row.insertCell(-1);
				row.insertCell(-1);
			}

			if(message.isTrack())
			{
				if("hide"==tracker.trackMsgs)
				{
					if(0==trackMsgCount)
						row.style.display="none";	// Hidden row
					else
					{
						insertCell(row,"TRACK ("+(trackMsgCount-1)+" hidden)","left");
						trackMsgCount=0;
					}
				}
				else
					insertCell(row,"TRACK (hide old)","left");
			}
			else
				insertCell(row,message.type,"left");
		}
	}

	// Now paste the tbody over the existing TBODY
	var table=document.getElementById("tblMessages");
	if(table.tBodies[feed.id])
		table.tBodies[feed.id].innerHTML=tbody.innerHTML;
	else
	{
		tbody.id=feed.id;
		table.appendChild(tbody);
	}

	// Update the timestamp
	console.log(FEEDS);
	document.getElementById("updateTimestamp").innerHTML=
		FEEDS.feed[0].lastUpdated.toLocaleTimeString() + " " +
		DAYS[FEEDS.feed[0].lastUpdated.getDay()]       + " " +
		FEEDS.feed[0].lastUpdated.toLocaleDateString();

	// Reset the auto update timer
	FEEDS.updateTimer();
}

// This function sets the displayability of the trackMsgs
// hide=hide all bar latest
// show=show all
FEEDS.trackMsgDisplay=function(type, feedId, tracker, trackMsgs)
{
	var feed=FEEDS.getFeed(type, feedId);
	feed.tracker[tracker].trackMsgs=trackMsgs;
	feed.onUpdate(feed);
}

FEEDS.updateTimeout=null;
// This function sets the updateTimer
// based on the menu setting & last update timestamp
FEEDS.updateTimer=function()
{
	// Clear existing timer (if applicable)
	if(FEEDS.updateTimeout)
		clearTimeout(FEEDS.updateTimeout);

	// Get the timer setting
	var timerList=document.getElementById("updateInterval");
	var timeout=timerList.options[timerList.selectedIndex].value;

	if(timeout>0)
	{
		var now=new Date();

		// Timer is specified in minutes. Needs milliseconds
		timeout *= 60000;

		// Now we need to adjust the timeout based on the last update
		// & current time
		timeout -= (now.getTime() - FEEDS.feed[0].lastUpdated.getTime());

		console.log(timeout);

		if(timeout > 0)
			FEEDS.updateTimeout=setTimeout(FEEDS.refresh, timeout);
		else	 // Cover off getting a negative number
			FEEDS.update();
	}
}

////////////////////
//                //
// INITIALISATION //
//                //
////////////////////

// Day of week -> Name conversion
var DAYS=new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");

// Get feed, or use example
var feed=getURLParameter("SPOT");
if (!feed)
	feed = 0;

FEEDS.feed.push(new SPOT_FEED(feed));

// Go get the data!
//FEEDS.refresh();

// Try out LKGPS
//function loadDoc() {
//  var xhttp = new XMLHttpRequest();
//  xhttp.onreadystatechange = function() {
//    if (this.readyState == 4 && this.status == 200) {
//     console.log(this.responseText);
//    }
//  };
//  xhttp.open("GET", "https://anyorigin.com/go/?url=http%3A//www.lkgps.net%3A8080/openapiv3.asmx/GetTracking%3FDeviceID%3D23636%26Model%3D102%26Timezones%3D%26MapType%3D%26Language%3D%26Key%3D7DU2DJFDR8321", true);
//  xhttp.send();
//}
//loadDoc();
var lkgps=document.createElement("iframe");
lkgps.src = "http://www.lkgps.net:8080/openapiv3.asmx/GetTracking?DeviceID=23636&Model=102&Timezones=&MapType=&Language=&Key=7DU2DJFDR8321";
lkgps.onload = function()
{
	console.log("loaded")
	console.log(this.contentDocument.innerHTML);
};
document.body.appendChild(lkgps);
//		J50Npi.getJSON("http://www.lkgps.net/Ajax/DevicesAjax.asmx/GetDevicesByUserID?UserID=1546&isFirst=true&TimeZones=China%20Standard%20Time&DeviceID=23636", FEEDS.feed[0].json, function(json)
	//	{
		//	console.log(json);
//		}
//		);

// vim: ts=2:sw=2
<commit_msg>whateverorigin<commit_after>/////////////////////////////////////////
//                                     //
// ADD METHODS TO SPOT_MESSAGE OBJECTS //
//                                     //
/////////////////////////////////////////
//
// method to identify TRACK only type messages
SPOT_MESSAGE.prototype.isTrack = function()
{
	if("TRACK" == this.type)
		return true;
	return false;
}

// Get earlier data
FEEDS.getHistory=function()
{
// *******************************************************************************
// Should this check for SPOT only???
	for(var ix=0; ix<FEEDS.feed.length; ix++)
		FEEDS.feed[ix].update(FEEDS.feed[ix].onUpdate, null, true);
}

// Display a feed
// Separating this out makes it easier to cope with non-referesh updates
SPOT_FEED.prototype.onUpdate = function(feed)
{
	var insertCell=function(tblRow, html, align)
	{
		if(!align)
			align="right";

		var newCell=tblRow.insertCell(-1);
		newCell.align=align;
		newCell.innerHTML=html;
	};

	// We have a TBODY for each feed, not TRACKER
	var tbody=document.createElement("tbody");

	tbody.innerHTML=
		"
"
		+feed.name+
		"
";

	for(var trackerIx=0; trackerIx<feed.tracker.length; trackerIx++)
	{
		var tracker=feed.tracker[trackerIx];

		// Define additional variable to store whether to display all tracks
		if(!tracker.trackMsgs)
			tracker.trackMsgs="hide"	// Default: Hide non-latest

		tbody.insertRow(-1).innerHTML=
			""
			+tracker.name+
			"	";

		// First we count the number of TRACK messages if hiding them
		var trackMsgCount=-1;
		if("hide"==tracker.trackMsgs)
		{
			trackMsgCount=0;
			for(var msgIx=0; msgIx<tracker.message.length; msgIx++)
				if(tracker.message[msgIx].isTrack())
					trackMsgCount++;
		}

		//Messages are already in reverse Chronological order
		for(var msgIx=0; msgIx<tracker.message.length; msgIx++)
		{
			var message=tracker.message[msgIx];

			var osgb=message.getOSGB();

			var row=tbody.insertRow(-1);
			row.title=message.type;

			insertCell(row,DAYS[message.time.getDay()]);
			insertCell(row,message.time.toLocaleTimeString());
			insertCell(row,"");
			insertCell(row,""+
				osgb.getGridRef(3)+"");

			if(tracker.message.length-1 > msgIx)
			{
				// Reverse chronological order, hence previous in time
				// is next in the array
				var previousMessage=tracker.message[msgIx+1];

				// Speed
				// km/s =           dist(km) /  time(s)
				// km/h = 3600    * dist(km) / (time(ms) / 1000)
				// km/h = 3600000 * dist(km) / time(ms)
				insertCell(row,(
					3600000*message.getDistance(previousMessage) /
					(message.time.getTime()-previousMessage.time.getTime())
					).toFixed(1)+" km/h");

				insertCell(row,
					previousMessage.getHeading(message).toFixed(0)
					+" deg");
			}
			else
			{
				row.insertCell(-1);
				row.insertCell(-1);
			}

			if(message.isTrack())
			{
				if("hide"==tracker.trackMsgs)
				{
					if(0==trackMsgCount)
						row.style.display="none";	// Hidden row
					else
					{
						insertCell(row,"TRACK ("+(trackMsgCount-1)+" hidden)","left");
						trackMsgCount=0;
					}
				}
				else
					insertCell(row,"TRACK (hide old)","left");
			}
			else
				insertCell(row,message.type,"left");
		}
	}

	// Now paste the tbody over the existing TBODY
	var table=document.getElementById("tblMessages");
	if(table.tBodies[feed.id])
		table.tBodies[feed.id].innerHTML=tbody.innerHTML;
	else
	{
		tbody.id=feed.id;
		table.appendChild(tbody);
	}

	// Update the timestamp
	console.log(FEEDS);
	document.getElementById("updateTimestamp").innerHTML=
		FEEDS.feed[0].lastUpdated.toLocaleTimeString() + " " +
		DAYS[FEEDS.feed[0].lastUpdated.getDay()]       + " " +
		FEEDS.feed[0].lastUpdated.toLocaleDateString();

	// Reset the auto update timer
	FEEDS.updateTimer();
}

// This function sets the displayability of the trackMsgs
// hide=hide all bar latest
// show=show all
FEEDS.trackMsgDisplay=function(type, feedId, tracker, trackMsgs)
{
	var feed=FEEDS.getFeed(type, feedId);
	feed.tracker[tracker].trackMsgs=trackMsgs;
	feed.onUpdate(feed);
}

FEEDS.updateTimeout=null;
// This function sets the updateTimer
// based on the menu setting & last update timestamp
FEEDS.updateTimer=function()
{
	// Clear existing timer (if applicable)
	if(FEEDS.updateTimeout)
		clearTimeout(FEEDS.updateTimeout);

	// Get the timer setting
	var timerList=document.getElementById("updateInterval");
	var timeout=timerList.options[timerList.selectedIndex].value;

	if(timeout>0)
	{
		var now=new Date();

		// Timer is specified in minutes. Needs milliseconds
		timeout *= 60000;

		// Now we need to adjust the timeout based on the last update
		// & current time
		timeout -= (now.getTime() - FEEDS.feed[0].lastUpdated.getTime());

		console.log(timeout);

		if(timeout > 0)
			FEEDS.updateTimeout=setTimeout(FEEDS.refresh, timeout);
		else	 // Cover off getting a negative number
			FEEDS.update();
	}
}

////////////////////
//                //
// INITIALISATION //
//                //
////////////////////

// Day of week -> Name conversion
var DAYS=new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");

// Get feed, or use example
var feed=getURLParameter("SPOT");
if (!feed)
	feed = 0;

FEEDS.feed.push(new SPOT_FEED(feed));

// Go get the data!
//FEEDS.refresh();

// Try out LKGPS
function loadDoc() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
     console.log(this.responseText);
    }
  };
//  xhttp.open("GET", "https://anyorigin.com/go/?url=http%3A//www.lkgps.net%3A8080/openapiv3.asmx/GetTracking%3FDeviceID%3D23636%26Model%3D102%26Timezones%3D%26MapType%3D%26Language%3D%26Key%3D7DU2DJFDR8321", true);//  xhttp.send();
  xhttp.open("GET", "https://whateverorigin.org/get?url=http%3A//www.lkgps.net%3A8080/openapiv3.asmx/GetTracking%3FDeviceID%3D23636%26Model%3D102%26Timezones%3D%26MapType%3D%26Language%3D%26Key%3D7DU2DJFDR8321", true);//  xhttp.send();
}
loadDoc();
//var lkgps=document.createElement("iframe");
//lkgps.src = "http://www.lkgps.net:8080/openapiv3.asmx/GetTracking?DeviceID=23636&Model=102&Timezones=&MapType=&Language=&Key=7DU2DJFDR8321";
//lkgps.onload = function()
//{
//	console.log("loaded")
//	console.log(this.contentDocument.innerHTML);
//};
//document.body.appendChild(lkgps);
//		J50Npi.getJSON("http://www.lkgps.net/Ajax/DevicesAjax.asmx/GetDevicesByUserID?UserID=1546&isFirst=true&TimeZones=China%20Standard%20Time&DeviceID=23636", FEEDS.feed[0].json, function(json)
	//	{
		//	console.log(json);
//		}
//		);

// vim: ts=2:sw=2
<|endoftext|>


<commit_before>var silab = silab || {};

silab.laboratory  = {
    moduleName : "silab.laboratory"
}

silab.laboratory.templates = {
    inventory: {
        card: silab.helpers.getTemplate({
                source: "#silab-template-card",
              }),
        list: silab.helpers.getTemplate({
                source: "#silab-template-list",
              }),
    }
}

var sLaboratoryTemplates = silab.laboratory.templates;

silab.laboratory.activeInventoryDataTable = function(target)
{
    let sLaboratory = silab.laboratory;

    if(silab.needs(['jQuery.fn.DataTable'], sLaboratory.moduleName))
    {
        $(target).DataTable();
        expanderHandler(target);
        appendDivs(target);

        function appendDivs(target)
        {
            $(target + ' tr[data-row]').each(function(index, key){
                let row     = $(this);

                row.after("
\
                                 \

" + lorem + "
\
                                	\

"
                    );
            });
        }

        function expanderHandler(target)
        {
            if(silab.needs())
            {
                $(target + ' button[data-role="row-expander"]').on('click', function(){
                    let me              = $(this);
                    let parentId        = $(this).data("parent");
                    let expandSection   = $(target + " tr[data-brother='" + parentId + "']");
                    let isOpen          = expandSection.hasClass("open");
                    // 1. expand or collapse
                    expandSection.removeClass( isOpen ?  "open" : "")
                                 .addClass(!isOpen ?  "open" : "");

                    // 2. change the button icon
                    me.children("i").removeClass(isOpen ?  "fa-minus" : "fa-plus")
                                    .addClass(!isOpen ?  "fa-minus" : "fa-plus");
                    console.log("parent", parentId);
                })
            }
        }
    }

}

silab.laboratory.init = function()
{
    var sLaboratory = silab.laboratory;

    if(silab.needs()) {
        sLaboratory.renderInventories();
        inventoryLinkOverlay();
    }

    function inventoryLinkOverlay()
    {
        $("body").on('click', '#inventory-spot .layout-base a[data-overlay-loader]', function(e){
            e.preventDefault();
            let me           = $(this);
            let baseLayer    = me.closest("[class*='layout']");
            let overlayLayer = baseLayer.next();
            let overContent  = overlayLayer.find( "[data-content]" );

            baseLayer.addClass("hide");
            overlayLayer.removeClass("hide");

            silab.overlay.toggle("load");

            overContent.load( me.attr('href'), function(data) {
                silab.overlay.toggle("load");
            });

        });

        $("body").on('click', '#inventory-spot a[data-overlay-back]', function(e){
            e.preventDefault();
            let me           = $(this);
            let overlayLayer = me.closest("[class*='layout']");
            let baseLayer = overlayLayer.prev();

            overlayLayer.find( "[data-content]" ).html("");

            baseLayer.removeClass("hide");
            overlayLayer.addClass("hide");
        });
    }
}

silab.laboratory.renderInventories = function(params) {
    if(silab.needs()) {
        var params = params || {
            mode: "card",
            data: window.inventories,
            target: "#inventory-spot .layout-base",
            loader: true
        };

        if(params.loader) {
            silab.overlay.toggle("process", "Cargando inventarios");
        }

        let template  = sLaboratoryTemplates.inventory[ params.mode ];
        let count     = params.data.length;
        let sizeCount = ( (count % 2 == 0) && !(count % 3 == 0) ) ? 6 : 4;
            sizeCount = ( sizeCount == 4 ) ? 3 : 2;

        let html = "";
        let row  = "
{inventories}
";
        let inve = "";

        for(var i = 0, lap = 0; i < count; i++) {
            var inv = params.data[ i ];
            inve += _.template( template )( {
                model: {
                    id: inv.INVE_ID,
                    name: inv.INVE_NOMBRE,
                    description: inv.INVE_DESCRIPCION,
                    isCaducated: "VIGENTE",
                    itemsCount: 15,
                    entriesCount: 15,
                    outsCount: 0
                },
                data: {
                    link: [
                        "overlay-loader"
                    ]
                }
            } );

            if( i % (sizeCount - 1) == 0 && i > 0 ) {
                html +=  row.replace( "{inventories}", inve );
                sizeCount *= 2;
                lap++;
                inve = "";
            }
            else if( lap > 0 && i == count - 1 ) {
                html +=  row.replace( "{inventories}", inve );
                lap++;
                inve = "";
            }
        }

        $(params.target).html( html );

        if(params.loader) {
            silab.overlay.toggle("process");
        }

    }
}

silab.laboratory.init();

<commit_msg>:coffee: Añadido Laboratorio en renderInventories<commit_after>var silab = silab || {};

silab.laboratory  = {
    moduleName : "silab.laboratory"
}

silab.laboratory.templates = {
    inventory: {
        card: silab.helpers.getTemplate({
                source: "#silab-template-card",
              }),
        list: silab.helpers.getTemplate({
                source: "#silab-template-list",
              }),
    }
}

var sLaboratoryTemplates = silab.laboratory.templates;

silab.laboratory.activeInventoryDataTable = function(target)
{
    let sLaboratory = silab.laboratory;

    if(silab.needs(['jQuery.fn.DataTable'], sLaboratory.moduleName))
    {
        $(target).DataTable();
        expanderHandler(target);
        appendDivs(target);

        function appendDivs(target)
        {
            $(target + ' tr[data-row]').each(function(index, key){
                let row     = $(this);

                row.after("
\
                                 \

" + lorem + "
\
                                	\

"
                    );
            });
        }

        function expanderHandler(target)
        {
            if(silab.needs())
            {
                $(target + ' button[data-role="row-expander"]').on('click', function(){
                    let me              = $(this);
                    let parentId        = $(this).data("parent");
                    let expandSection   = $(target + " tr[data-brother='" + parentId + "']");
                    let isOpen          = expandSection.hasClass("open");
                    // 1. expand or collapse
                    expandSection.removeClass( isOpen ?  "open" : "")
                                 .addClass(!isOpen ?  "open" : "");

                    // 2. change the button icon
                    me.children("i").removeClass(isOpen ?  "fa-minus" : "fa-plus")
                                    .addClass(!isOpen ?  "fa-minus" : "fa-plus");
                    console.log("parent", parentId);
                })
            }
        }
    }

}

silab.laboratory.init = function()
{
    var sLaboratory = silab.laboratory;

    if(silab.needs()) {
        sLaboratory.renderInventories();
        inventoryLinkOverlay();
    }

    function inventoryLinkOverlay()
    {
        $("body").on('click', '#inventory-spot .layout-base a[data-overlay-loader]', function(e){
            e.preventDefault();
            let me           = $(this);
            let baseLayer    = me.closest("[class*='layout']");
            let overlayLayer = baseLayer.next();
            let overContent  = overlayLayer.find( "[data-content]" );

            baseLayer.addClass("hide");
            overlayLayer.removeClass("hide");

            silab.overlay.toggle("load");

            overContent.load( me.attr('href'), function(data) {
                silab.overlay.toggle("load");
            });

        });

        $("body").on('click', '#inventory-spot a[data-overlay-back]', function(e){
            e.preventDefault();
            let me           = $(this);
            let overlayLayer = me.closest("[class*='layout']");
            let baseLayer = overlayLayer.prev();

            overlayLayer.find( "[data-content]" ).html("");

            baseLayer.removeClass("hide");
            overlayLayer.addClass("hide");
        });
    }
}

silab.laboratory.renderInventories = function(params) {
    if(silab.needs()) {
        var params = params || {
            mode: "card",
            data: window.inventories,
            target: "#inventory-spot .layout-base",
            loader: true
        };

        if(params.loader) {
            silab.overlay.toggle("process", "Cargando inventarios");
        }

        let template  = sLaboratoryTemplates.inventory[ params.mode ];
        let count     = params.data.length;
        let sizeCount = ( (count % 2 == 0) && !(count % 3 == 0) ) ? 6 : 4;
            sizeCount = ( sizeCount == 4 ) ? 3 : 2;

        let html = "";
        let row  = "
{inventories}
";
        let inve = "";

        for(var i = 0, lap = 0; i < count; i++) {
            var inv = params.data[ i ];
            inve += _.template( template )( {
                model: {
                    id: inv.INVE_ID,
                    name: inv.INVE_NOMBRE,
                    description: inv.INVE_DESCRIPCION,
                    isCaducated: "VIGENTE",
                    itemsCount: 15,
                    entriesCount: 15,
                    outsCount: 0,
                    laboratoryId : window.laboratoryId
                },
                data: {
                    link: [
                        "overlay-loader"
                    ]
                }
            } );

            if( i % (sizeCount - 1) == 0 && i > 0 ) {
                html +=  row.replace( "{inventories}", inve );
                sizeCount *= 2;
                lap++;
                inve = "";
            }
            else if( lap > 0 && i == count - 1 ) {
                html +=  row.replace( "{inventories}", inve );
                lap++;
                inve = "";
            }
        }

        $(params.target).html( html );

        if(params.loader) {
            silab.overlay.toggle("process");
        }

    }
}

silab.laboratory.init();

<|endoftext|>