<commit_before>import $$ from 'slot';
import virtualDom from 'virtual-dom';
var h = virtualDom.h;
import voucherTypeStore from 'store/voucher-type-store';
import voucherSubjectStore from 'store/voucher-subject-store';
import moment from 'moment';
import voucherStore from 'store/voucher-store';
import casing from 'casing';
import co from 'co';
import { $$toast } from '../toast';
import { field } from '../field';
import page from 'page';
import { $$dropdown } from '../widget/dropdown';
import R from 'ramda';
import { $$searchDropdown } from '../widget/search-dropdown';
import entityStore from '../store/entity-store';
import classNames from '../class-names';
import overlay from '../overlay';

var $$obj = $$({}, 'obj');
var $$voucherTypes = $$([], 'voucher-types');
var $$loading = $$(false, 'loading');
var $$voucherSubjects = $$([], 'voucher-subjects');
var $$errors = $$({}, 'errors');
var $$entities = $$([], 'entities');
var $$currentVoucherSubject = $$(null, 'current-voucher-subject');
// why bother make these 2 slots? to avoid refresh
// payerDropdown/recipientDropdown whenever obj changed
var $$currentPayerId = $$(null, 'current-payer-id');
var $$currentRecipientId = $$(null, 'current-recipient-id');

var copy = {};

var dirty = function (obj) {
  return !R.equals(obj, copy);
};

const vf = function([obj, form]) {
  let readonly = R.path(['accountTerm', 'closed'])(obj);
  return h('.object-app', [
    h(
      classNames('header', dirty(obj) && 'dirty'),
      obj.id? `编辑凭证-${obj.number}` + (readonly? '(已锁定)': ''): '创建新凭证'
    ),
    form,
  ]);
};

const formVf = function formVf([
  loading, obj, errors,
  voucherTypeDropdown, voucherSubjectDropdown,
  payerDropdown, recipientDropdown
]) {
  let classNames = ['form', 'relative'];
  loading && classNames.push('loading');
  classNames = classNames.map(c => '.' + c).join('');
  let readonly = R.path(['accountTerm', 'closed'])(obj);
  return h('form' + classNames, {
    onsubmit() {
      co(function*() {
        if (!dirty(obj)) {
          $$toast.val({
            type: 'info',
            message: '您没有做出任何修改',
          });
          return;
        }
        $$errors.val({});
        try {
          yield voucherStore.validate(obj);
        } catch (e) {
          $$errors.val(e);
          return;
        }
        try {
          $$loading.val(true);
          let { id } = obj;
          Object.assign(obj, yield voucherStore.save(obj));
          copy = R.clone(obj);
          $$toast.val({
            type: 'success',
            message: '提交成功',
          });
          !id && page('/voucher/' + obj.id);
        } catch (e) {
          console.error(e);
          if (e.response && e.response.status == 400) {
            $$errors.val(e.response.data);
          }
        } finally {
          $$loading.val(false);
        }
      });
      return false;
    }
  }, [
    obj.id? field({
      label: '经办人',
      input: h('.text', R.path(['creator', 'username'])(obj)),
    }): void 0,
    obj.id? field({
      label: '创建于',
      input: h('.text', moment(obj.created).format('YYYY-MM-DD HH:mm')),
    }): void 0,
    obj.id? field({
      label: '账期',
      input: h('.text', h('span', [
        R.path(['accountTerm', 'name'])(obj),
        ...readonly?
          [h('span', '('), h('i.fa.fa-lock'), h('span', '已关闭'), h('span', ')')]:
          []
      ])),
    }): void 0,
    readonly?
    field({
      label: '凭证类型',
      input: h('.text', R.path(['voucherType', 'name'])(obj))
    }):
    field({
      key: 'voucherTypeId',
      label: '凭证类型',
      input: voucherTypeDropdown,
      errors,
      required: true,
    }),
    readonly?
    field({
      label: '科目',
      input: h('.text', R.path(['voucherSubject', 'name'])(obj))
    }):
    field({
      key: 'voucherSubjectId',
      label: '科目',
      input: voucherSubjectDropdown,
      errors,
      required: true,
    }),
    readonly?
    field({
      label: '金额',
      input: h('.text', '' + obj.amount),
    }):
    field({
      key: 'amount',
      label: '金额(元)',
      input: h('input', {
        type: 'number',
        oninput() {
          $$obj.patch({ amount: this.value });
        },
        value: obj.amount,
      }),
      errors,
      required: true,
    }),
    readonly?
    field({
      label: '日期',
      input: h('.text', obj.date)
    }):
    field({
      key: 'date',
      label: '日期',
      input: h('input', {
        type: 'date',
        value: obj.date,
        oninput() {
          $$obj.patch({
            date: this.value,
          });
        }
      }),
      errors,
      required: true
    }),
    readonly?
    field({ label: '凭证号', input: h('.text', obj.number) }):
    field({
      key: 'number',
      label: '凭证号',
      input: h('input', {
        placeholder: '请输入凭证号',
        value: obj.number,
        oninput() {
          $$obj.patch({ number: this.value });
        }
      }),
      errors,
      required: true
    }),
    readonly?
    field({
      label: '(实际)支付方',
      input: h('.text', R.path(['payer', 'name'])(obj)),
    }):
    field({
      key: 'payerId',
      label: '(实际)支付方',
      input: payerDropdown,
      errors,
      required: true
    }),
    readonly?
    field({
      label: '(实际)收入方',
      input: h('.text', R.path(['recipient', 'name'])(obj))
    }):
    field({
      key: 'recipientId',
      label: '(实际)收入方',
      input: recipientDropdown,
      errors,
      required: true
    }),
    h('.clearfix'),
    h('hr'),
    readonly && obj.id? void 0: h('button.primary', '提交'),
    readonly? void 0: h('a.btn.btn-outline.ca', {
      onclick() {
        overlay.$$content.val({
          type: 'warning',
          title: '您确认要删除该凭证?',
          message: [
            h('.ca.pt4.pb4', '该操作将不可逆!'),
            h('a.btn.btn-outline', {
              onclick() {
                overlay.$$content.val(null);
                return false;
              }
            }, '取消'),
            h('a.btn.btn-outline.ca', {
              onclick() {
                voucherStore.del(obj.id)
                .then(function () {
                  overlay.$$content.val({
                    type: 'success',
                    title: '删除成功!',
                    message: h('a.btn.btn-outline', {
                      onclick() {
                        overlay.$$content.val(null);
                        page('/voucher-list');
                        return false;
                      }
                    }, 'OK')
                  });
                });
                return false;
              }
            }, '确认')
          ],
        });
        return false;
      }
    }, '删除'),
    h('a.btn.btn-outline', {
      href: '/voucher-list',
    }, '返回'),
  ]);
};

var $$voucherTypeDropdown = $$dropdown({
  defaultText: '请选择凭证类型',
  onchange(voucherTypeId) {
    $$obj.patch({
      voucherTypeId
    });
  },
  $$options: $$voucherTypes.trans(R.map(it => ({
    value: it.id,
    text: it.name
  }))),
  $$value: $$obj.trans(R.prop('voucherTypeId')),
});

var $$voucherSubjectDropdown = $$searchDropdown({
  defaultText: '请选择凭证科目',
  $$value: $$obj.trans(R.prop('voucherSubjectId')),
  $$options: $$voucherSubjects.trans(R.map(it => ({
    value: it.id,
    text: it.name,
    acronym: it.acronym,
  }))),
  onchange(voucherSubjectId) {
    $$obj.patch({
      voucherSubjectId
    });
    $$currentVoucherSubject.val(
      R.find(R.propEq('id', voucherSubjectId))($$voucherSubjects.val())
    );
  },
});

var $$payerDropdown = $$searchDropdown({
  defaultText: '请选择支付方',
  onchange(payerId) {
    $$obj.patch({ payerId });
    $$currentPayerId.val(payerId);
  },
  $$options: $$.connect(
    [$$currentVoucherSubject, $$entities],
    function([currentVoucherSubject, entities]) {
      let payerType = R.prop('payerType')(currentVoucherSubject || {});
      if (payerType) {
        return entities.filter(R.propEq('type', payerType)).map(it => ({
          value: it.id,
          text: it.name,
          acronym: it.acronym,
        }));
      }
      return [];
    }
  ),
  $$value: $$currentPayerId
});

var $$recipientDropdown = $$searchDropdown({
  defaultText: '请选择支付方',
  onchange(recipientId) {
    $$obj.patch({ recipientId });
    $$currentRecipientId.val(recipientId);
  },
  $$options: $$.connect(
    [$$currentVoucherSubject, $$entities],
    function([currentVoucherSubject, entities]) {
      let recipientType = R.prop('recipientType')(currentVoucherSubject || {});
      if (recipientType) {
        return entities.filter(R.propEq('type', recipientType)).map(it => ({
          value: it.id,
          text: it.name,
          acronym: it.acronym,
        }));
      }
      return [];
    }
  ),
  $$value: $$currentRecipientId,
});

var $$form = $$.connect([
  $$loading, $$obj, $$errors,
  $$voucherTypeDropdown, $$voucherSubjectDropdown,
  $$payerDropdown, $$recipientDropdown
], formVf, 'voucher-form');

const $$view = $$.connect(
  [$$obj, $$form],
  vf,
  'voucher-object-app');

export
default {
  page: {
    $$view,
  },
  get dirty() {
    return dirty($$obj.val());
  },
  init(ctx) {
    let {
      id
    } = ctx.params;
    $$loading.val(true);
    let promises = [
      voucherTypeStore.list,
      voucherSubjectStore.list,
      entityStore.list,
      id ? voucherStore.get(id) : Object.assign({
        date: moment().format('YYYY-MM-DD')
      }, casing.camelize(ctx.query)),
    ];
    Promise.all(promises)
      .then(function([voucherTypes, voucherSubjects, entities, obj]) {
        copy = R.clone(obj);
        $$.update(
          [$$voucherTypes, voucherTypes],
          // why not R.propEq, since it use '===' instead of '=='
          [
            $$currentVoucherSubject,
            R.find(it => it.id == obj.voucherSubjectId)(voucherSubjects)
          ],
          [$$currentPayerId, obj.payerId],
          [$$currentRecipientId, obj.recipientId],
          [$$loading, false],
          [$$voucherSubjects, voucherSubjects],
          [$$obj, obj],
          [$$entities, entities]
        );
      });
  }
};
<commit_msg>hide delete button when create voucher<commit_after>import $$ from 'slot';
import virtualDom from 'virtual-dom';
var h = virtualDom.h;
import voucherTypeStore from 'store/voucher-type-store';
import voucherSubjectStore from 'store/voucher-subject-store';
import moment from 'moment';
import voucherStore from 'store/voucher-store';
import casing from 'casing';
import co from 'co';
import { $$toast } from '../toast';
import { field } from '../field';
import page from 'page';
import { $$dropdown } from '../widget/dropdown';
import R from 'ramda';
import { $$searchDropdown } from '../widget/search-dropdown';
import entityStore from '../store/entity-store';
import classNames from '../class-names';
import overlay from '../overlay';

var $$obj = $$({}, 'obj');
var $$voucherTypes = $$([], 'voucher-types');
var $$loading = $$(false, 'loading');
var $$voucherSubjects = $$([], 'voucher-subjects');
var $$errors = $$({}, 'errors');
var $$entities = $$([], 'entities');
var $$currentVoucherSubject = $$(null, 'current-voucher-subject');
// why bother make these 2 slots? to avoid refresh
// payerDropdown/recipientDropdown whenever obj changed
var $$currentPayerId = $$(null, 'current-payer-id');
var $$currentRecipientId = $$(null, 'current-recipient-id');

var copy = {};

var dirty = function (obj) {
  return !R.equals(obj, copy);
};

const vf = function([obj, form]) {
  let readonly = R.path(['accountTerm', 'closed'])(obj);
  return h('.object-app', [
    h(
      classNames('header', dirty(obj) && 'dirty'),
      obj.id? `编辑凭证-${obj.number}` + (readonly? '(已锁定)': ''): '创建新凭证'
    ),
    form,
  ]);
};

const formVf = function formVf([
  loading, obj, errors,
  voucherTypeDropdown, voucherSubjectDropdown,
  payerDropdown, recipientDropdown
]) {
  let classNames = ['form', 'relative'];
  loading && classNames.push('loading');
  classNames = classNames.map(c => '.' + c).join('');
  let readonly = R.path(['accountTerm', 'closed'])(obj);
  return h('form' + classNames, {
    onsubmit() {
      co(function*() {
        if (!dirty(obj)) {
          $$toast.val({
            type: 'info',
            message: '您没有做出任何修改',
          });
          return;
        }
        $$errors.val({});
        try {
          yield voucherStore.validate(obj);
        } catch (e) {
          $$errors.val(e);
          return;
        }
        try {
          $$loading.val(true);
          let { id } = obj;
          Object.assign(obj, yield voucherStore.save(obj));
          copy = R.clone(obj);
          $$toast.val({
            type: 'success',
            message: '提交成功',
          });
          !id && page('/voucher/' + obj.id);
        } catch (e) {
          console.error(e);
          if (e.response && e.response.status == 400) {
            $$errors.val(e.response.data);
          }
        } finally {
          $$loading.val(false);
        }
      });
      return false;
    }
  }, [
    obj.id? field({
      label: '经办人',
      input: h('.text', R.path(['creator', 'username'])(obj)),
    }): void 0,
    obj.id? field({
      label: '创建于',
      input: h('.text', moment(obj.created).format('YYYY-MM-DD HH:mm')),
    }): void 0,
    obj.id? field({
      label: '账期',
      input: h('.text', h('span', [
        R.path(['accountTerm', 'name'])(obj),
        ...readonly?
          [h('span', '('), h('i.fa.fa-lock'), h('span', '已关闭'), h('span', ')')]:
          []
      ])),
    }): void 0,
    readonly?
    field({
      label: '凭证类型',
      input: h('.text', R.path(['voucherType', 'name'])(obj))
    }):
    field({
      key: 'voucherTypeId',
      label: '凭证类型',
      input: voucherTypeDropdown,
      errors,
      required: true,
    }),
    readonly?
    field({
      label: '科目',
      input: h('.text', R.path(['voucherSubject', 'name'])(obj))
    }):
    field({
      key: 'voucherSubjectId',
      label: '科目',
      input: voucherSubjectDropdown,
      errors,
      required: true,
    }),
    readonly?
    field({
      label: '金额',
      input: h('.text', '' + obj.amount),
    }):
    field({
      key: 'amount',
      label: '金额(元)',
      input: h('input', {
        type: 'number',
        oninput() {
          $$obj.patch({ amount: this.value });
        },
        value: obj.amount,
      }),
      errors,
      required: true,
    }),
    readonly?
    field({
      label: '日期',
      input: h('.text', obj.date)
    }):
    field({
      key: 'date',
      label: '日期',
      input: h('input', {
        type: 'date',
        value: obj.date,
        oninput() {
          $$obj.patch({
            date: this.value,
          });
        }
      }),
      errors,
      required: true
    }),
    readonly?
    field({ label: '凭证号', input: h('.text', obj.number) }):
    field({
      key: 'number',
      label: '凭证号',
      input: h('input', {
        placeholder: '请输入凭证号',
        value: obj.number,
        oninput() {
          $$obj.patch({ number: this.value });
        }
      }),
      errors,
      required: true
    }),
    readonly?
    field({
      label: '(实际)支付方',
      input: h('.text', R.path(['payer', 'name'])(obj)),
    }):
    field({
      key: 'payerId',
      label: '(实际)支付方',
      input: payerDropdown,
      errors,
      required: true
    }),
    readonly?
    field({
      label: '(实际)收入方',
      input: h('.text', R.path(['recipient', 'name'])(obj))
    }):
    field({
      key: 'recipientId',
      label: '(实际)收入方',
      input: recipientDropdown,
      errors,
      required: true
    }),
    h('.clearfix'),
    h('hr'),
    readonly? void 0: h('button.primary', '提交'),
    readonly || !obj.id? void 0 : h('a.btn.btn-outline.ca', {
      onclick() {
        overlay.$$content.val({
          type: 'warning',
          title: '您确认要删除该凭证?',
          message: [
            h('.ca.pt4.pb4', '该操作将不可逆!'),
            h('a.btn.btn-outline', {
              onclick() {
                overlay.$$content.val(null);
                return false;
              }
            }, '取消'),
            h('a.btn.btn-outline.ca', {
              onclick() {
                voucherStore.del(obj.id)
                .then(function () {
                  overlay.$$content.val({
                    type: 'success',
                    title: '删除成功!',
                    message: h('a.btn.btn-outline', {
                      onclick() {
                        overlay.$$content.val(null);
                        page('/voucher-list');
                        return false;
                      }
                    }, 'OK')
                  });
                });
                return false;
              }
            }, '确认')
          ],
        });
        return false;
      }
    }, '删除'),
    h('a.btn.btn-outline', {
      href: '/voucher-list',
    }, '返回'),
  ]);
};

var $$voucherTypeDropdown = $$dropdown({
  defaultText: '请选择凭证类型',
  onchange(voucherTypeId) {
    $$obj.patch({
      voucherTypeId
    });
  },
  $$options: $$voucherTypes.trans(R.map(it => ({
    value: it.id,
    text: it.name
  }))),
  $$value: $$obj.trans(R.prop('voucherTypeId')),
});

var $$voucherSubjectDropdown = $$searchDropdown({
  defaultText: '请选择凭证科目',
  $$value: $$obj.trans(R.prop('voucherSubjectId')),
  $$options: $$voucherSubjects.trans(R.map(it => ({
    value: it.id,
    text: it.name,
    acronym: it.acronym,
  }))),
  onchange(voucherSubjectId) {
    $$obj.patch({
      voucherSubjectId
    });
    $$currentVoucherSubject.val(
      R.find(R.propEq('id', voucherSubjectId))($$voucherSubjects.val())
    );
  },
});

var $$payerDropdown = $$searchDropdown({
  defaultText: '请选择支付方',
  onchange(payerId) {
    $$obj.patch({ payerId });
    $$currentPayerId.val(payerId);
  },
  $$options: $$.connect(
    [$$currentVoucherSubject, $$entities],
    function([currentVoucherSubject, entities]) {
      let payerType = R.prop('payerType')(currentVoucherSubject || {});
      if (payerType) {
        return entities.filter(R.propEq('type', payerType)).map(it => ({
          value: it.id,
          text: it.name,
          acronym: it.acronym,
        }));
      }
      return [];
    }
  ),
  $$value: $$currentPayerId
});

var $$recipientDropdown = $$searchDropdown({
  defaultText: '请选择支付方',
  onchange(recipientId) {
    $$obj.patch({ recipientId });
    $$currentRecipientId.val(recipientId);
  },
  $$options: $$.connect(
    [$$currentVoucherSubject, $$entities],
    function([currentVoucherSubject, entities]) {
      let recipientType = R.prop('recipientType')(currentVoucherSubject || {});
      if (recipientType) {
        return entities.filter(R.propEq('type', recipientType)).map(it => ({
          value: it.id,
          text: it.name,
          acronym: it.acronym,
        }));
      }
      return [];
    }
  ),
  $$value: $$currentRecipientId,
});

var $$form = $$.connect([
  $$loading, $$obj, $$errors,
  $$voucherTypeDropdown, $$voucherSubjectDropdown,
  $$payerDropdown, $$recipientDropdown
], formVf, 'voucher-form');

const $$view = $$.connect(
  [$$obj, $$form],
  vf,
  'voucher-object-app');

export
default {
  page: {
    $$view,
  },
  get dirty() {
    return dirty($$obj.val());
  },
  init(ctx) {
    let {
      id
    } = ctx.params;
    $$loading.val(true);
    let promises = [
      voucherTypeStore.list,
      voucherSubjectStore.list,
      entityStore.list,
      id ? voucherStore.get(id) : Object.assign({
        date: moment().format('YYYY-MM-DD')
      }, casing.camelize(ctx.query)),
    ];
    Promise.all(promises)
      .then(function([voucherTypes, voucherSubjects, entities, obj]) {
        console.log(obj);
        copy = R.clone(obj);
        $$.update(
          [$$voucherTypes, voucherTypes],
          // why not R.propEq, since it use '===' instead of '=='
          [
            $$currentVoucherSubject,
            R.find(it => it.id == obj.voucherSubjectId)(voucherSubjects)
          ],
          [$$currentPayerId, obj.payerId],
          [$$currentRecipientId, obj.recipientId],
          [$$loading, false],
          [$$voucherSubjects, voucherSubjects],
          [$$obj, obj],
          [$$entities, entities]
        );
      });
  }
};
<|endoftext|>


<commit_before>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Renders the children of an element filterable via a callback and a textinput
//>>label: Filterable
//>>group: Widgets

define( [ "jquery", "./forms/textinput" ], function( jQuery ) {
//>>excludeEnd("jqmBuildExclude");
(function( $, undefined ) {

	// TODO rename filterCallback/deprecate and default to the item itself as the first argument
	var defaultfilterCallback = function( text, searchValue /*, item */) {
		return text.toString().toLowerCase().indexOf( searchValue ) === -1;
	};

	$.widget( "mobile.filterable", $.extend( {

			options: {
				theme: "a",
				filterPlaceholder: "Filter items...",
				filterReveal: false,
				filterCallback: defaultfilterCallback,
				wrapperClass: "",
				inset: false,
				enhanced: false,
				target: null,
				mini: false,
				selector: null
			},

			_onKeyUp: function() {
				var search = this._search[ 0 ],
					o = this.options,
					getAttrFixed = $.mobile.getAttribute,
					val = search.value.toLowerCase(),
					lastval = getAttrFixed( search, "lastval", true ) + "";

				if ( lastval && lastval === val ) {
					// Execute the handler only once per value change
					return;
				}

				if (o.timer !== undefined) {
					window.clearTimeout(o.timer);
				}

				o.timer = this._delay(function() {
					this._trigger( "beforefilter", "beforefilter", { input: search } );

					// Change val as lastval for next execution
					search.setAttribute( "data-" + $.mobile.ns + "lastval" , val );

					this._filterItems( search, val, lastval );
				}, 250 );
			},

			_getFilterableItems: function() {
				var el = this.element,
					o = this.options,
					items = [];

				if (typeof o.selector === "string") {
					items = $("." + o.selector).children();
				} else {
					items = el.find("> li, > option, tbody tr, .ui-controlgroup-controls .ui-btn");
				}
				return items;
			},

			_setFilterableItems: function(val, lastval) {
				var o = this.options,
					filterItems = [],
					isCustomfilterCallback = o.filterCallback !== defaultfilterCallback,
					_getFilterableItems = this._getFilterableItems();

				if ( isCustomfilterCallback || val.length < lastval.length || val.indexOf( lastval ) !== 0 ) {

					// Custom filter callback applies or removed chars or pasted something totally different, check all items
					filterItems = _getFilterableItems;
				} else {

					// Only chars added, not removed, only use visible subset
					filterItems = _getFilterableItems.filter( ":not(.ui-screen-hidden)" );

					if ( !filterItems.length && o.filterReveal ) {
						filterItems = _getFilterableItems.filter( ".ui-screen-hidden" );
					}
				}
				return filterItems;
			},

			_filterItems: function( search, val, lastval ){
				var o = this.options,
					getAttrFixed = $.mobile.getAttribute,
					filterItems = this._setFilterableItems(val, lastval),
					_getFilterableItems = this._getFilterableItems(),
					childItems = false,
					itemtext = "",
					item,
					select = this.element.parents( ".ui-select" ),
					i;

				this._setOption( "timer", undefined );

				if ( val ) {

					for ( i = filterItems.length - 1; i >= 0; i-- ) {
						item = $( filterItems[ i ] );
						// NOTE: should itemtext be stored somewhere? Will text() change much
						// and does this need to be re-parsed on every iteration? Also, no
						// chance to run data-filtertext on anything that JQM wraps, because
						// we filter the wrapper and can't access the input/a. Can we?
						itemtext = getAttrFixed(filterItems[ i ], "filtertext", true) || item.text();

						if ( item.is( ".ui-li-divider" ) ) {

							item.toggleClass( "ui-filter-hidequeue" , !childItems );

							// New bucket!
							childItems = false;

						} else if ( o.filterCallback( itemtext, val, item ) ) {

							//mark to be hidden
							item.toggleClass( "ui-filter-hidequeue" , true );
						} else {

							// There's a shown item in the bucket
							childItems = true;
						}
					}

					this._toggleFilterableItems( filterItems, select, o.filterReveal , true);
				} else {
					this._toggleFilterableItems( filterItems, select, o.filterReveal );
				}
				if ( typeof o.selector !== "string" ) {
					this._addFirstLastClasses( _getFilterableItems, this._getVisibles( _getFilterableItems, false ), false );
				}
			},

			_toggleFilterableItems: function( filterItems, select, reveal, isVal )	{

				if (isVal) {
					// Show items, not marked to be hidden
					filterItems
						.filter( ":not(.ui-filter-hidequeue)" )
						.toggleClass( "ui-screen-hidden", false );

					// Hide items, marked to be hidden
					filterItems
						.filter( ".ui-filter-hidequeue" )
						.toggleClass( "ui-screen-hidden", true )
						.toggleClass( "ui-filter-hidequeue", false );

					// select - hide parent when no options match?
					if ( select ) {
						if ( filterItems.length === filterItems.filter( ".ui-screen-hidden").length ) {
							select.addClass( "ui-screen-hidden" );
						}
					}
				} else {
					//filtervalue is empty => show all
					filterItems.toggleClass( "ui-screen-hidden", !!reveal );
					// select
					if ( select ) {
						select.removeClass( "ui-screen-hidden", !!reveal );
					}
				}
			},

			_enhance: function ( items ) {
				var el = this.element,
					o = this.options,
					wrapper = $( "<div>", {
						"class":  "ui-filter " + o.wrapperClass,
						"role": "search",
						"id" : "ui-filter-" + this.uuid
					}),
					search = $( "<input>", {
						placeholder: o.filterPlaceholder
					})
					.attr( "data-" + $.mobile.ns + "type", "search" )
					.appendTo( wrapper )
					.textinput({
						theme: o.filterTheme,
						mini: o.mini
					});

				if ( o.inset ) {
					wrapper.addClass( "ui-filter-inset" );
				}

				if ( o.filterReveal ) {
					items.addClass( "ui-screen-hidden" );
				}

				if ( typeof o.target === "string" ) {
					wrapper.prependTo( $( "." + o.target + "" ) );
				} else {
					wrapper.insertBefore( el );
				}

				return search;
			},

			_create: function() {
				var search,
					o = this.options,
					items = this._getFilterableItems();

				this._setOption( "timer", undefined );

				if ( !o.enhanced ) {
					search = this._enhance( items );
				} else {
					search = $( "." + o.wrapperClass ).find( "input" );
				}

				this._on( search, {
					keyup: "_onKeyUp",
					change: "_onKeyUp",
					input: "_onKeyUp"
				});

				$.extend( this, {
					_search: search
				});

				// NOTE: since the filter was based on the listview, some unit tests seem
				// to listen for the initial addFirstLastClasses call when the listview
				// is setup (at least I cannot recreate a refreshCornerCount in Qunit
				// without setting first and last classes on the filterable elements on
				// create). If refresh corners is to be run on the filter, I would prefer
				// it being solely called by the filter being triggered and not be the
				// "_super()-widget" calling it. So 2x input on the filter should trigger
				// 2x addFirstLastClasses vs. currently 3x because of including the call
				// when setting up the parent listview.

				// no classes if multiple datasets are used
				if ( typeof o.selector !== "string" ) {
					this._addFirstLastClasses( items, this._getVisibles( items, true ), true );
				}
			},

			_setOption: function( key, value ) {
				var o = this.options,
					wrapper = document.getElementById( "ui-filter-" + this.uuid ),
					$input = $( wrapper ).find( "input" );

				// always update
				o[ key ] = value;

				if ( key === "disabled" ) {
					$input
						.toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
						.attr( "aria-disabled", value )
						.textinput( value ? "disable" : "enable" );
				}
				return this;
			},

			widget: function() {
				return this.element;
			},

			_destroy: function() {
				var o = this.options,
					wrapper = document.getElementById( "ui-filter-" + this.uuid );

				if ( !o.enhanced ) {
					wrapper.parentNode.removeChild( wrapper );
				}
				this._toggleFilterableItems( this._getFilterableItems(), false, false );
			}

	}, $.mobile.behaviors.addFirstLastClasses ) );

	$.mobile.filterable.initSelector = ":jqmData(filter='true')";

	//auto self-init widgets
	$.mobile._enhancer.add( "mobile.filterable" );

})( jQuery );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");
<commit_msg>Filterable: Whitespace fixes and removing timer from options.<commit_after>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Renders the children of an element filterable via a callback and a textinput
//>>label: Filterable
//>>group: Widgets

define( [
	"jquery",
	"./forms/textinput",
	"./addFirstLastClasses" ], function( jQuery ) {
//>>excludeEnd("jqmBuildExclude");
(function( $, undefined ) {

	// TODO rename filterCallback/deprecate and default to the item itself as the first argument
	var defaultfilterCallback = function( text, searchValue /*, item */) {
		return text.toString().toLowerCase().indexOf( searchValue ) === -1;
	};

	$.widget( "mobile.filterable", $.extend( {

			options: {
				theme: "a",
				filterPlaceholder: "Filter items...",
				filterReveal: false,
				filterCallback: defaultfilterCallback,
				wrapperClass: "",
				inset: false,
				enhanced: false,
				target: null,
				mini: false,
				selector: null
			},

			_onKeyUp: function() {
				var search = this._search[ 0 ],
					opts = this.options,
					getAttrFixed = $.mobile.getAttribute,
					val = search.value.toLowerCase(),
					lastval = getAttrFixed( search, "lastval", true ) + "";

				if ( lastval && lastval === val ) {
					// Execute the handler only once per value change
					return;
				}

				if ( this._timer ) {
					window.clearTimeout( this._timer );
				}

				this._timer = this._delay( function() {
					this._trigger( "beforefilter", "beforefilter", { input: search } );

					// Change val as lastval for next execution
					search.setAttribute( "data-" + $.mobile.ns + "lastval", val );

					this._filterItems( search, val, lastval );
				}, 250 );
			},

			_getFilterableItems: function() {
				var el = this.element,
					opts = this.options,
					items = [];

				if ( typeof opts.selector === "string" ) {
					items = $( "." + opts.selector ).children();
				} else {
					items = el.find( "> li, > option, tbody tr, .ui-controlgroup-controls .ui-btn" );
				}
				return items;
			},

			_setFilterableItems: function( val, lastval ) {
				var opts = this.options,
					filterItems = [],
					isCustomfilterCallback = opts.filterCallback !== defaultfilterCallback,
					_getFilterableItems = this._getFilterableItems();

				if ( isCustomfilterCallback || val.length < lastval.length || val.indexOf( lastval ) !== 0 ) {

					// Custom filter callback applies or removed chars or pasted something totally different, check all items
					filterItems = _getFilterableItems;
				} else {

					// Only chars added, not removed, only use visible subset
					filterItems = _getFilterableItems.filter( ":not(.ui-screen-hidden)" );

					if ( !filterItems.length && opts.filterReveal ) {
						filterItems = _getFilterableItems.filter( ".ui-screen-hidden" );
					}
				}
				return filterItems;
			},

			_filterItems: function( search, val, lastval ){
				var opts = this.options,
					getAttrFixed = $.mobile.getAttribute,
					filterItems = this._setFilterableItems( val, lastval ),
					_getFilterableItems = this._getFilterableItems(),
					childItems = false,
					itemtext = "",
					item,
					select = this.element.parents( ".ui-select" ),
					i;

				if ( val ) {

					for ( i = filterItems.length - 1; i >= 0; i-- ) {
						item = $( filterItems[ i ] );
						// NOTE: should itemtext be stored somewhere? Will text() change much
						// and does this need to be re-parsed on every iteration? Also, no
						// chance to run data-filtertext on anything that JQM wraps, because
						// we filter the wrapper and can't access the input/a. Can we?
						itemtext = getAttrFixed(filterItems[ i ], "filtertext", true) || item.text();

						if ( item.is( ".ui-li-divider" ) ) {

							item.toggleClass( "ui-filter-hidequeue" , !childItems );

							// New bucket!
							childItems = false;

						} else if ( opts.filterCallback( itemtext, val, item ) ) {

							//mark to be hidden
							item.toggleClass( "ui-filter-hidequeue" , true );
						} else {

							// There's a shown item in the bucket
							childItems = true;
						}
					}

					this._toggleFilterableItems( filterItems, select, opts.filterReveal, true);
				} else {
					this._toggleFilterableItems( filterItems, select, opts.filterReveal );
				}
				if ( typeof opts.selector !== "string" ) {
					this._addFirstLastClasses( _getFilterableItems, this._getVisibles( _getFilterableItems, false ), false );
				}
			},

			_toggleFilterableItems: function( filterItems, select, reveal, isVal )	{

				if ( isVal ) {
					// Show items not marked to be hidden
					filterItems
						.filter( ":not(.ui-filter-hidequeue)" )
						.toggleClass( "ui-screen-hidden", false );

					// Hide items marked to be hidden
					filterItems
						.filter( ".ui-filter-hidequeue" )
						.toggleClass( "ui-screen-hidden", true )
						.toggleClass( "ui-filter-hidequeue", false );

					// select - hide parent when no options match?
					if ( select ) {
						if ( filterItems.length === filterItems.filter( ".ui-screen-hidden").length ) {
							select.addClass( "ui-screen-hidden" );
						}
					}
				} else {
					//filtervalue is empty => show all
					filterItems.toggleClass( "ui-screen-hidden", !!reveal );
					// select
					if ( select ) {
						select.removeClass( "ui-screen-hidden", !!reveal );
					}
				}
			},

			_enhance: function ( items ) {
				var el = this.element,
					opts = this.options,
					wrapper = $( "<div>", {
						"class":  "ui-filter " + opts.wrapperClass,
						"role": "search",
						"id" : "ui-filter-" + this.uuid
					}),
					search = $( "<input>", {
						placeholder: opts.filterPlaceholder
					})
					.attr( "data-" + $.mobile.ns + "type", "search" )
					.appendTo( wrapper )
					.textinput({
						theme: opts.filterTheme,
						mini: opts.mini
					});

				if ( opts.inset ) {
					wrapper.addClass( "ui-filter-inset" );
				}

				if ( opts.filterReveal ) {
					items.addClass( "ui-screen-hidden" );
				}

				if ( typeof opts.target === "string" ) {
					wrapper.prependTo( $( "." + opts.target + "" ) );
				} else {
					wrapper.insertBefore( el );
				}

				return search;
			},

			_create: function() {
				var search,
					opts = this.options,
					items = this._getFilterableItems();

				if ( !opts.enhanced ) {
					search = this._enhance( items );
				} else {
					search = $( "." + opts.wrapperClass ).find( "input" );
				}

				this._on( search, {
					keyup: "_onKeyUp",
					change: "_onKeyUp",
					input: "_onKeyUp"
				});

				$.extend( this, {
					_search: search,
					_timer: 0
				});

				// NOTE: since the filter was based on the listview, some unit tests seem
				// to listen for the initial addFirstLastClasses call when the listview
				// is setup (at least I cannot recreate a refreshCornerCount in Qunit
				// without setting first and last classes on the filterable elements on
				// create). If refresh corners is to be run on the filter, I would prefer
				// it being solely called by the filter being triggered and not be the
				// "_super()-widget" calling it. So 2x input on the filter should trigger
				// 2x addFirstLastClasses vs. currently 3x because of including the call
				// when setting up the parent listview.

				// no classes if multiple datasets are used
				if ( typeof opts.selector !== "string" ) {
					this._addFirstLastClasses( items, this._getVisibles( items, true ), true );
				}
			},

			_setOption: function( key, value ) {
				var opts = this.options,
					wrapper = document.getElementById( "ui-filter-" + this.uuid ),
					$input = $( wrapper ).find( "input" );

				// always update
				opts[ key ] = value;

				if ( key === "disabled" ) {
					$input
						.toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
						.attr( "aria-disabled", value )
						.textinput( value ? "disable" : "enable" );
				}
				return this;
			},

			widget: function() {
				return this.element;
			},

			_destroy: function() {
				var opts = this.options,
					wrapper = document.getElementById( "ui-filter-" + this.uuid );

				if ( !opts.enhanced ) {
					wrapper.parentNode.removeChild( wrapper );
				}
				this._toggleFilterableItems( this._getFilterableItems(), false, false );
			}

	}, $.mobile.behaviors.addFirstLastClasses ) );

	$.mobile.filterable.initSelector = ":jqmData(filter='true')";

	//auto self-init widgets
	$.mobile._enhancer.add( "mobile.filterable" );

})( jQuery );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");
<|endoftext|>


<commit_before>//use browser url to find socket to connect to

var parser = document.createElement('a');
parser.href = document.URL;

var socket = new WebSocket("ws://" + parser.host + parser.pathname + parser.hash.substring(1));

//initialize socket using text for communication, used to initialize our output
socket.binaryType = "text";

function createOutputCanvas(outputInfo){
    //make canvas & context global
    canvas = document.createElement('canvas');
    ctx = canvas.getContext('2d');

    //TODO map canvas geometry to reported server output
    canvas.id     = "output";
    canvas.width  = 800;
    canvas.height = 600;
    canvas.style.position = "absolute";
    canvas.style.border   = "1px solid";

    //add canvas input listeners
    canvas.addEventListener('mousedown',function(ev){
        //p(ointer):d(own):b(utton):xxxx:t(ime):xxxxxxx
        socket.send("p:d:b:"+ev.button+":t:"+Date.now())
    },false);
    canvas.addEventListener('mouseup',function(ev){
        //p(ointer):u(p):b(utton):0:t(ime):xxxxxxx
        socket.send("p:u:b:"+ev.button+":t:"+Date.now())
    },false);
    canvas.addEventListener('contextmenu', function(ev) {
        ev.preventDefault();
        return false;
    }, false);
    canvas.addEventListener('mousemove', function(ev) {
        var rect = canvas.getBoundingClientRect();
        var x = Math.round((ev.clientX-rect.left)/(rect.right-rect.left)*canvas.width);
        var y = Math.round((ev.clientY-rect.top)/(rect.bottom-rect.top)*canvas.height);
        //p(ointer):m(otion):x:xxxx:y:xxxx:t(ime):xxxxxxx
        socket.send("p:m:x:"+x+":y:"+y+":t:"+Date.now())
    }, false);
    canvas.addEventListener('keydown', function(ev) {
        //k(ey):d(own):c(ode):xxxx:t(ime):xxxxxx
        socket.send("k:d:c:"+ev.keyCode+":t:"+Date.now());
    }, false);
    canvas.addEventListener('keyup', function(ev) {
        //k(ey):u(p):c(ode):xxxx:t(ime):xxxxxx
        socket.send("k:u:c:"+ev.keyCode+":t:"+Date.now());
    }, false);

    document.body.appendChild(canvas);

    //output canvas created, switch to binary mode so we can receive output frames as blobs
    socket.binaryType = "blob";
    //replace text handler with blob handler
    socket.onmessage = function (e) {
        //read binary data as image & put it in the canvas
        var img = new Image();
        img.onload = function() {
            ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        };
        var imgSrc = URL.createObjectURL(e.data);
        img.src = imgSrc;
    };
    //notify server we have created the output canvas and are now ready to receive binary frames
    socket.send("ack-output-info");
}

socket.onopen = function () {
    //request output info so we can initialize our html5 canvas with the correct size
    socket.onmessage = function (e) {

        //TODO validate reply
        //create canvas object based on output info reply
        createOutputCanvas(e.data);
    }
    socket.send("req-output-info");
};

socket.onerror = function (error) {
  //TODO show error on screen
};

socket.onclose = function (event) {
    //TODO should we attempt to reconnect?
};

<commit_msg>reuse img object, free img data when no longer needed<commit_after>//use browser url to find socket to connect to

var parser = document.createElement('a');
parser.href = document.URL;

var socket = new WebSocket("ws://" + parser.host + parser.pathname + parser.hash.substring(1));

//initialize socket using text for communication, used to initialize our output
socket.binaryType = "text";

function createOutputCanvas(outputInfo){
    //make canvas & context global
    canvas = document.createElement('canvas');
    ctx = canvas.getContext('2d');

    img = new Image();
    img.onload = function() {
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height);
        URL.revokeObjectURL(img.src);
    };

    //TODO map canvas geometry to reported server output
    canvas.id     = "output";
    canvas.width  = 800;
    canvas.height = 600;
    canvas.style.position = "absolute";
    canvas.style.border   = "1px solid";

    //add canvas input listeners
    canvas.addEventListener('mousedown',function(ev){
        //p(ointer):d(own):b(utton):xxxx:t(ime):xxxxxxx
        socket.send("p:d:b:"+ev.button+":t:"+Date.now())
    },false);
    canvas.addEventListener('mouseup',function(ev){
        //p(ointer):u(p):b(utton):0:t(ime):xxxxxxx
        socket.send("p:u:b:"+ev.button+":t:"+Date.now())
    },false);
    canvas.addEventListener('contextmenu', function(ev) {
        ev.preventDefault();
        return false;
    }, false);
    canvas.addEventListener('mousemove', function(ev) {
        var rect = canvas.getBoundingClientRect();
        var x = Math.round((ev.clientX-rect.left)/(rect.right-rect.left)*canvas.width);
        var y = Math.round((ev.clientY-rect.top)/(rect.bottom-rect.top)*canvas.height);
        //p(ointer):m(otion):x:xxxx:y:xxxx:t(ime):xxxxxxx
        socket.send("p:m:x:"+x+":y:"+y+":t:"+Date.now())
    }, false);
    canvas.addEventListener('keydown', function(ev) {
        //k(ey):d(own):c(ode):xxxx:t(ime):xxxxxx
        socket.send("k:d:c:"+ev.keyCode+":t:"+Date.now());
    }, false);
    canvas.addEventListener('keyup', function(ev) {
        //k(ey):u(p):c(ode):xxxx:t(ime):xxxxxx
        socket.send("k:u:c:"+ev.keyCode+":t:"+Date.now());
    }, false);

    document.body.appendChild(canvas);

    //replace text handler with blob handler
    socket.onmessage = function (e) {
        //read binary data as image & put it in the canvas
        img.src = URL.createObjectURL(e.data);
    };
    //notify server we have created the output canvas and are now ready to receive binary frames
    socket.send("ack-output-info");
}

socket.onopen = function () {
    //request output info so we can initialize our html5 canvas with the correct size
    socket.onmessage = function (e) {

        //TODO validate reply
        //create canvas object based on output info reply
        createOutputCanvas(e.data);
    }
    socket.send("req-output-info");
};

socket.onerror = function (error) {
  //TODO show error on screen
};

socket.onclose = function (event) {
    //TODO should we attempt to reconnect?
};

<|endoftext|>


<commit_before>var boxHeight = 80;
var textHeight = 14;
var textMargin = 6;

template = {
  "name": "Four fields 0.2",
  "settings": {
    "nodeSize": {
      "width": boxHeight * 1.5,
      "height": boxHeight * 2.0
    }
  },
  "svg": {
    "node-big-rect": {
      "type": "rect",
      "attributes": {
        "x": - boxHeight / 2,
        "y": 0,
        "rx": boxHeight * 0.1,
        "width": boxHeight,
        "height": boxHeight
      }
    },
    "node-vertical-line": {
      "type": "line",
      "attributes": {
        "x1": 0,
        "y1": 0,
        "x2": 0,
        "y2": boxHeight
      }
    },
    "node-horizontal-line": {
      "type": "line",
      "attributes": {
        "x1": - boxHeight / 2,
        "y1": boxHeight / 2,
        "x2": boxHeight / 2,
        "y2": boxHeight / 2
      }
    },
    "node-central-rect": {
      "type": "rect",
      "attributes": {
        "x": - boxHeight * 0.22,
        "y": boxHeight * 0.28,
        "rx": boxHeight * 0.1,
        "width": boxHeight * 0.44,
        "height": boxHeight * 0.44
      }
    },
  },
  "fields": [
    {
      "header": "id",
      "initial": 0,
      "description": "Id",
      "type": null
    },
    {
      "header": "parentId",
      "initial": null,
      "description": "Parent",
      "type": null
    },
    {
      "header": "name",
      "initial": "Name",
      "description": "Name",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": 0,
          "y": -textMargin
        }
      }
    },
    {
      "header": "coach",
      "initial": "Coach",
      "description": "Coach",
      "type": "text"
      // svg defined currently in genmapper.js
    },
    {
      "header": "field1",
      "initial": 0,
      "description": "Field 1 (# unbelievers)",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": - boxHeight / 2 + textMargin,
          "y": textHeight + textMargin
        },
        "style": {
          "text-anchor": "start"
        }
      }
    },
    {
      "header": "field2",
      "initial": 0,
      "description": "Field 2 (# believers)",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": boxHeight / 2 - textMargin,
          "y": textHeight + textMargin
        },
        "style": {
          "text-anchor": "end"
        }
      }
    },
    {
      "header": "field3",
      "initial": 0,
      "description": "Field 3 (# accountable)",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": boxHeight / 2 - textMargin,
          "y": boxHeight - textMargin
        },
        "style": {
          "text-anchor": "end"
        }
      }
    },
    {
      "header": "field4",
      "initial": 0,
      "description": "Field 4 (church?)",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": - boxHeight / 2 + textMargin,
          "y": boxHeight - textMargin
        },
        "style": {
          "text-anchor": "start"
        }
      }
    },
    {
      "header": "field5",
      "initial": 0,
      "description": "Field 5 (# reproducing)",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": 0,
          "y": boxHeight / 2 + textHeight / 2
        }
      }
    },
    {
      "header": "placeDate",
      "initial": "Place & Date",
      "description": "Place & Date",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": 0,
          "y": boxHeight + textHeight + textMargin
        }
      }
    },
    {
      "header": "active",
      "initial": true,
      "description": "Active",
      "type": "checkbox"
      // svg defined currently in genmapper.js
    }
  ]
};
<commit_msg>Four Fields template - initial field4 set to “No”<commit_after>var boxHeight = 80;
var textHeight = 14;
var textMargin = 6;

template = {
  "name": "Four fields 0.3",
  "settings": {
    "nodeSize": {
      "width": boxHeight * 1.5,
      "height": boxHeight * 2.0
    }
  },
  "svg": {
    "node-big-rect": {
      "type": "rect",
      "attributes": {
        "x": - boxHeight / 2,
        "y": 0,
        "rx": boxHeight * 0.1,
        "width": boxHeight,
        "height": boxHeight
      }
    },
    "node-vertical-line": {
      "type": "line",
      "attributes": {
        "x1": 0,
        "y1": 0,
        "x2": 0,
        "y2": boxHeight
      }
    },
    "node-horizontal-line": {
      "type": "line",
      "attributes": {
        "x1": - boxHeight / 2,
        "y1": boxHeight / 2,
        "x2": boxHeight / 2,
        "y2": boxHeight / 2
      }
    },
    "node-central-rect": {
      "type": "rect",
      "attributes": {
        "x": - boxHeight * 0.22,
        "y": boxHeight * 0.28,
        "rx": boxHeight * 0.1,
        "width": boxHeight * 0.44,
        "height": boxHeight * 0.44
      }
    },
  },
  "fields": [
    {
      "header": "id",
      "initial": 0,
      "description": "Id",
      "type": null
    },
    {
      "header": "parentId",
      "initial": null,
      "description": "Parent",
      "type": null
    },
    {
      "header": "name",
      "initial": "Name",
      "description": "Name",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": 0,
          "y": -textMargin
        }
      }
    },
    {
      "header": "coach",
      "initial": "Coach",
      "description": "Coach",
      "type": "text"
      // svg defined currently in genmapper.js
    },
    {
      "header": "field1",
      "initial": 0,
      "description": "Field 1 (# unbelievers)",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": - boxHeight / 2 + textMargin,
          "y": textHeight + textMargin
        },
        "style": {
          "text-anchor": "start"
        }
      }
    },
    {
      "header": "field2",
      "initial": 0,
      "description": "Field 2 (# believers)",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": boxHeight / 2 - textMargin,
          "y": textHeight + textMargin
        },
        "style": {
          "text-anchor": "end"
        }
      }
    },
    {
      "header": "field3",
      "initial": 0,
      "description": "Field 3 (# accountable)",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": boxHeight / 2 - textMargin,
          "y": boxHeight - textMargin
        },
        "style": {
          "text-anchor": "end"
        }
      }
    },
    {
      "header": "field4",
      "initial": "No",
      "description": "Field 4 (church?)",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": - boxHeight / 2 + textMargin,
          "y": boxHeight - textMargin
        },
        "style": {
          "text-anchor": "start"
        }
      }
    },
    {
      "header": "field5",
      "initial": 0,
      "description": "Field 5 (# reproducing)",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": 0,
          "y": boxHeight / 2 + textHeight / 2
        }
      }
    },
    {
      "header": "placeDate",
      "initial": "Place & Date",
      "description": "Place & Date",
      "type": "text",
      "svg": {
        "type": "text",
        "attributes": {
          "x": 0,
          "y": boxHeight + textHeight + textMargin
        }
      }
    },
    {
      "header": "active",
      "initial": true,
      "description": "Active",
      "type": "checkbox"
      // svg defined currently in genmapper.js
    }
  ]
};
<|endoftext|>


<commit_before>Physics.Line = function(config) {
  this.one = config.one || new Vector2();
  this.two = config.two || new Vector2();

  /** Bounce Coefficient **/
  this.bcf = config.bcf || 0.75;

  /** Radius **/
  this.rad = config.rad || 4;
};
Physics.Line.prototype.draw = function() {
  ctx.beginPath();
  ctx.strokeStyle = "#000";
  ctx.lineWidth = this.rad * 2;
  ctx.moveTo(this.one.x, this.one.y);
  ctx.lineTo(this.two.x, this.two.y);
  ctx.stroke();
};
<commit_msg>Update line.js<commit_after>if (!Physics.Line) {
  Physics.Line = function(config) {
    this.one = config.one || new Vector2();
    this.two = config.two || new Vector2();

    /** Bounce Coefficient **/
    this.bcf = config.bcf || 0.75;

    /** Radius **/
    this.rad = config.rad || 4;
  };
  Physics.Line.prototype.draw = function() {
    ctx.beginPath();
    ctx.strokeStyle = "#000";
    ctx.lineWidth = this.rad * 2;
    ctx.moveTo(this.one.x, this.one.y);
    ctx.lineTo(this.two.x, this.two.y);
    ctx.stroke();
  };
}
<|endoftext|>


<commit_before>/**
 * @license
 * MIT License
 *
 * Copyright (c) 2016 Xiao Huang Fan
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

// ==UserScript==
// @name        Piperka Open All
// @namespace   https://github.com/NAR8789
// @description Adds an open all button to piperka updates page
// @version     1.0
// @grant       none
// @match       http://piperka.net/updates.html
// ==/UserScript==

// this script relies on jquery, but does not @require it...
// potentially it ought to, but piperka already includes jquery on the page

$(function() {
    var piperkaList = $('#piperka_list');
    var links = piperkaList.find('a[target="_blank"]');

    var openAll = $(document.createElement("input")).attr({
        type: "button",
        value: "Open All"
    }).click(function() {
        links.each(function(i,link) {
            window.open(link.href, link.target);
        });
    });

    openAll.insertBefore(piperkaList);
});
<commit_msg>also match https<commit_after>/**
 * @license
 * MIT License
 *
 * Copyright (c) 2016 Xiao Huang Fan
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

// ==UserScript==
// @name        Piperka Open All
// @namespace   https://github.com/NAR8789
// @description Adds an open all button to piperka updates page
// @version     1.0.1
// @grant       none
// @match       http://piperka.net/updates.html
// @match       https://piperka.net/updates.html
// ==/UserScript==

// this script relies on jquery, but does not @require it...
// potentially it ought to, but piperka already includes jquery on the page

$(function() {
    var piperkaList = $('#piperka_list');
    var links = piperkaList.find('a[target="_blank"]');

    var openAll = $(document.createElement("input")).attr({
        type: "button",
        value: "Open All"
    }).click(function() {
        links.each(function(i,link) {
            window.open(link.href, link.target);
        });
    });

    openAll.insertBefore(piperkaList);
});
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React from 'react';

import Icon from '../../icon';
import './step-sequence-item.scss';

const baseClass = 'carbon-step-sequence-item';
const classes = status => `${baseClass} ${baseClass}--${status}`;

const stepMarker = (status, indicator) => {
  return status === 'complete' ? <Icon type='tick' /> : indicator;
};

const ariaRoleProp = (status) => {
  return status === 'current' ? { 'aria-current': 'step' } : {};
};

const completeLabel = (label, status) => {
  if (label && status === 'complete') {
    return { label };
  }

  return null;
};

const currentLabel = (label, status) => {
  if (label && status === 'current') {
    return { label };
  }

  return null;
};

const StepSequenceItem = ({
  children,
  indicator,
  status,
  hiddenCompleteLabel,
  hiddenCurrentLabel,
  ...props
}) => (

    { completeLabel(hiddenCompleteLabel, status) }
    { currentLabel(hiddenCurrentLabel, status) }

      { stepMarker(status, indicator) }
      { children }

);

StepSequenceItem.propTypes = {
  ariaLabel: PropTypes.string,
  children: PropTypes.node.isRequired,
  indicator: PropTypes.string.isRequired,
  status: PropTypes.oneOf([
    'complete',
    'current',
    'incomplete'
  ]),
  hiddenCompleteLabel: PropTypes.string,
  hiddenCurrentLabel: PropTypes.string
};

StepSequenceItem.defaultProps = {
  status: 'incomplete'
};

export default StepSequenceItem;
<commit_msg>Remove unneeded propType #1865<commit_after>import PropTypes from 'prop-types';
import React from 'react';

import Icon from '../../icon';
import './step-sequence-item.scss';

const baseClass = 'carbon-step-sequence-item';
const classes = status => `${baseClass} ${baseClass}--${status}`;

const stepMarker = (status, indicator) => {
  return status === 'complete' ? <Icon type='tick' /> : indicator;
};

const ariaRoleProp = (status) => {
  return status === 'current' ? { 'aria-current': 'step' } : {};
};

const completeLabel = (label, status) => {
  if (label && status === 'complete') {
    return { label };
  }

  return null;
};

const currentLabel = (label, status) => {
  if (label && status === 'current') {
    return { label };
  }

  return null;
};

const StepSequenceItem = ({
  children,
  indicator,
  status,
  hiddenCompleteLabel,
  hiddenCurrentLabel,
  ...props
}) => (

    { completeLabel(hiddenCompleteLabel, status) }
    { currentLabel(hiddenCurrentLabel, status) }

      { stepMarker(status, indicator) }
      { children }

);

StepSequenceItem.propTypes = {
  children: PropTypes.node.isRequired,
  indicator: PropTypes.string.isRequired,
  status: PropTypes.oneOf([
    'complete',
    'current',
    'incomplete'
  ]),
  hiddenCompleteLabel: PropTypes.string,
  hiddenCurrentLabel: PropTypes.string
};

StepSequenceItem.defaultProps = {
  status: 'incomplete'
};

export default StepSequenceItem;
<|endoftext|>


<commit_before>/*
 * Special care was taken to ensure the ability to place multiple comments
 * tools on one page.  Please keep this in mind when changing this code.
 */

var commentItemToReload = null;
var deleteDialogCommentUrl = null;
var originalDeleteDialogText = null;
var noEditor = true;
var userAgent = navigator.userAgent;
var fckEditor = false;
var ckEditor = false;

$(function() {

	noEditor = ($(".using-editor").size() == 0);
	if (!noEditor) {
	    try {
		if (sakai.editor.editors.ckeditor==undefined)
		    fckEditor = true;
	    } catch (err) {
		fckEditor = true;
	    }
	}
	if (!noEditor && !fckEditor)
	    ckEditor = true;

	if (noEditor) {
		$(".evolved-box").hide();
	}else if(fckEditor) {
		$(".evolved-box :not(textarea)").hide();
	}else {
		$(".evolved-box").hide();
	}

	$(".submitButton").hide().val(msg("simplepage.add-comment"));
	$(".cancelButton").hide().val(msg("simplepage.cancel_message"));

	$(".cancelButton").click(function() {
		switchEditors($(this), false);
		return false;
	});

	$.ajaxSetup ({
		cache: false
	});

	$(".replaceWithComments").each(function(index) {
		var pageToRequest = $(this).parent().parent().children(".commentsBlock").attr("href");
		// remove  pda/SITEID/. We don't want the portal to hack on this
		//pageToRequest = pageToRequest.replace(new RegExp("pda/[^/]*/",""),"");
                var i = pageToRequest.indexOf("Comment");
                pageToRequest = "/sakai-lessonbuildertool-tool/faces/" + pageToRequest.substring(i);
		$(this).load(pageToRequest, commentsLoaded);
		//$.PeriodicalUpdater(pageToRequest, {minTimeout:5000, maxTimeout:120000}, function(data) {
		//	$(".deleteLink").attr("title", msg("simplepage.comment_delete"));
		//	$(".editLink").attr("title", msg("simplepage.edit-comment"));
		//	$(".replaceWithComments").html(data);
		//});
	});

	$("#delete-dialog").dialog({
		autoOpen: false,
		width: 400,
		modal: false,
		resizable: false,
		buttons: {
			"Cancel": function() {
				if(originalDeleteDialogText != null) {
					$("#delete-comment-confirm").text(originalDeleteDialogText);
				}

				$(this).dialog("close");
			},

			"Delete Comment": function() {
				confirmDelete();
			}
		}
	});
});

function commentsLoaded() {
	setMainFrameHeight(window.name);

	$(".pointsBox").unbind("keyup");

	$(".pointsBox").each(function(index, value) {
		$(value).parent().children("img").attr("id", "statusImg" + index);
		$(value).val($(value).parent().children(".pointsSpan").text());
	});

	$(".pointsBox").live('change', function(){
		var img = $(this).parent().children("img");
		img.attr("src", getStrippedImgSrc(img.attr("id")) + "no-status.png");
		$(this).addClass("unsubmitted");
	});

	$(".pointsBox").keyup(function(event){
		if(event.keyCode == 13) {
			var img = $(this).parent().children("img");

			$(this).removeClass("unsubmitted");
			img.attr("src", getStrippedImgSrc(img.attr("id")) + "loading.gif");

			$(".idField").val($(this).parent().children(".uuidBox").text()).change();
			$(".jsIdField").val(img.attr("id")).change();
			$(".typeField").val("comment");

			// This one triggers the update
			$(".pointsField").val($(this).val()).change();
		}
	});
}

function loadMore(link) {
	$.ajaxSetup ({
		cache: false
	});

	var pageToRequest = $(link).parent().parent().find(".to-load").attr("href");
	var i = pageToRequest.indexOf("Comment");
	pageToRequest = "/sakai-lessonbuildertool-tool/faces/" + pageToRequest.substring(i);

	$(link).parents(".replaceWithComments").load(pageToRequest, commentsLoaded);

	setMainFrameHeight(window.name);
}

function performHighlight() {
	$(".highlight-comment").effect("highlight", {}, 4000);
}

function replyToComment(link, replytext) {

	var evolved = $(link).parents(".commentsDiv").find(".evolved-box");

	if(noEditor) {
	    var body = $(link).parent().children(".commentBody");
	    // this should get the text out of the comment with newlines
	    // however innertext doesn't work on FF and I've heard rumors
	    // about IE 9. Hence provide a standard backup. It will handle
	    // newlines if they were entered via this text box, but
	    // may not if entered in the editor
	    body = body.get(0).innerText || body.text().replace(/^\s*/,"").replace(/\n\s*/g,"\n");
	    body = replytext + '\n\n' + body.replace(/^/,"|  ").replace(/\n/g,"\n|  ") + '\n\n';
	    evolved.val(body);
	} else if(fckEditor) {
		FCKeditorAPI.GetInstance(evolved.children("textarea").attr("name")).SetHTML(replytext + '
' + (link).parent().children(".commentBody").html() + '
\n

');
	}else {
		CKEDITOR.instances[evolved.children("textarea").attr("name")].setData(replytext + '
' + $(link).parent().children(".commentBody").html() + '
\n

');
	}

	$(link).parents(".commentsDiv").find(".comment-edit-id").val(null);
	$(link).parents(".commentsDiv").find(".submitButton").val(msg("simplepage.add-comment"));

        switchEditors(link);

	return false;
}

function switchEditors(link, show) {
	if(show==undefined) show = true;

	var evolved;

	if (noEditor) {
		evolved = $(link).parents(".commentsDiv").find(".evolved-box");
		evolved.css('width', '600px');
		evolved.css('height', '175px');
	}else if(fckEditor) {
		evolved = $(link).parents(".commentsDiv").find(".evolved-box :not(textarea)");
	}else {
		evolved = $(link).parents(".commentsDiv").find(".evolved-box");
	}

	if(show) {

 	    evolved.show();
 	    //$(link).parents(".commentsDiv").find(".editarea").show();

 		if(noEditor) {
 		    evolved.focus();
 		} else if(fckEditor) {
 		    var evolvedbox = $(link).parents(".commentsDiv").find(".evolved-box");
 		    FCKeditorAPI.GetInstance(evolvedbox.children("textarea").attr("name")).Focus();
 		}else {
 		    var frame = $(link).parents(".commentsDiv").find("iframe");

 		    // the builtin title is grossly too long, and not internationalized
 		    if (frame != null) {
 		    	frame.attr("title", msg("simplepage.ckeditor"));
		    }

 		    // seem to need this to make focus show up in VoiceOver. Looks like it's
 		    // not seeing into the iframe, although Safari shows it as selected
 		    if (frame != null) {
 			frame.focus();
 		    }
 		    CKEDITOR.instances[evolved.children("textarea").attr("name")].focus();
 		}

		var pos = evolved.offset();
		window.scrollTo(pos.left, pos.top);

		if (noEditor) {
		    // the submit expects HTML, so stick BRs at every newline
		    var submit = $(link).parents(".commentsDiv").find(".submitButton");
		   submit.click(function(link) {
			    var text = $(this).parents(".commentsDiv").find(".evolved-box");
			    text.val(text.val().replace(/\r\n/g, "
\n").replace(/[\r\n]/g, "
\n"));
			    return true;
			});
		}

		$(link).parents(".commentsDiv").find(".submitButton").show();
		$(link).parents(".commentsDiv").find(".cancelButton").show();

		$(link).parents(".commentsDiv").find(".switchLink").hide();
	}else {
		evolved.hide();

		if(fckEditor) {
			evolved = $(link).parents(".commentsDiv").find(".evolved-box");
		}

		if (noEditor) {
			evolved.val("");
		} else if(fckEditor) {
			FCKeditorAPI.GetInstance(evolved.children("textarea").attr("name")).SetHTML("");
		}else {
			CKEDITOR.instances[evolved.children("textarea").attr("name")].setData("");
		}

		$(link).parents(".commentsDiv").find(".submitButton").hide().val(msg("simplepage.add-comment"));
		$(link).parents(".commentsDiv").find(".cancelButton").hide().val(msg("simplepage.cancel_message"));

		$(link).parents(".commentsDiv").find(".switchLink").show();
		$(link).parents(".commentsDiv").find(".comment-edit-id").val("");

	}

	if(ckEditor) {
		evolved.find("textarea").hide();
	}

	setMainFrameHeight(window.name);
	$(document).height($('body').height());
}

function deleteComment(link) {
	$.ajaxSetup ({
		cache: false
	});

	deleteDialogCommentURL = $(link).parent().children(".deleteComment").attr("href");
	var i = deleteDialogCommentURL.indexOf("Comment");
	deleteDialogCommentURL = "/sakai-lessonbuildertool-tool/faces/" + deleteDialogCommentURL.substring(i);

	//var dialog = $(link).parents(".replaceWithComments").find(".delete-dialog");
	//$("#delete-dialog").children(".delete-dialog-comment-url").text(pageToRequest);

	originalDeleteDialogText = $("#delete-comment-confirm").text();
	$("#delete-comment-confirm").text(
			originalDeleteDialogText.replace("{}", link.parents(".commentDiv").find(".author").text()));

	$("#delete-dialog").dialog("open");

	commentToReload = $(link).parents(".replaceWithComments");

	//$(link).parents(".replaceWithComments").load(pageToRequest);

	//setMainFrameHeight(window.name);
}

function confirmDelete() {
	$(commentToReload).load(deleteDialogCommentURL, commentsLoaded);
	//$("#delete-dialog").parents(".replaceWithComments").load($(dialog).children(".delete-dialog-comment-url").text());
	setMainFrameHeight(window.name);
	$("#delete-dialog").dialog("close");
	$("#delete-comment-confirm").text(originalDeleteDialogText);
}

function edit(link, id) {
	var evolved = $(link).parents(".commentsDiv").find(".evolved-box");

	if(noEditor) {
	    var body = $(link).parent().children(".commentBody");
	    // this should get the text out of the comment with newlines
	    // however innertext doesn't work on FF and I've heard rumors
	    // about IE 9. Hence provide a standard backup. It will handle
	    // newlines if they were entered via this text box, but
	    // may not if entered in the editor
	    body = body.get(0).innerText || body.text().replace(/^\s*/,"").replace(/\n\s*/g,"\n");
	    evolved.val(body);

	} else if(fckEditor) {
		FCKeditorAPI.GetInstance(evolved.children("textarea").attr("name")).SetHTML($(link).parent().children(".commentBody").html());
	}else {
		CKEDITOR.instances[evolved.children("textarea").attr("name")].setData($(link).parent().children(".commentBody").html());
	}

	$(link).parents(".commentsDiv").find(".comment-edit-id").val(id);
	$(link).parents(".commentsDiv").find(".submitButton").val(msg("simplepage.edit-comment"));

	switchEditors(link);
}
<commit_msg>LSNBLDR-107 fix comments for new RSF version<commit_after>/*
 * Special care was taken to ensure the ability to place multiple comments
 * tools on one page.  Please keep this in mind when changing this code.
 */

var commentItemToReload = null;
var deleteDialogCommentUrl = null;
var originalDeleteDialogText = null;
var noEditor = true;
var userAgent = navigator.userAgent;
var fckEditor = false;
var ckEditor = false;

$(function() {

	noEditor = ($(".using-editor").size() == 0);
	if (!noEditor) {
	    try {
		if (sakai.editor.editors.ckeditor==undefined)
		    fckEditor = true;
	    } catch (err) {
		fckEditor = true;
	    }
	}
	if (!noEditor && !fckEditor)
	    ckEditor = true;

	if (noEditor) {
		$(".evolved-box").hide();
	}else if(fckEditor) {
		$(".evolved-box :not(textarea)").hide();
	}else {
		$(".evolved-box").hide();
	}

	$(".submitButton").hide().val(msg("simplepage.add-comment"));
	$(".cancelButton").hide().val(msg("simplepage.cancel_message"));

	$(".cancelButton").click(function() {
		switchEditors($(this), false);
		return false;
	});

	$.ajaxSetup ({
		cache: false
	});

	$(".replaceWithComments").each(function(index) {
		var pageToRequest = $(this).parent().parent().children(".commentsBlock").attr("href");
		// remove  pda/SITEID/. We don't want the portal to hack on this
		//pageToRequest = pageToRequest.replace(new RegExp("pda/[^/]*/",""),"");
                var i = pageToRequest.indexOf("/tool/");
		//http://heidelberg.rutgers.edu/portal/tool/NNNN/Comments
		//http://heidelberg.rutgers.edu/portal/pda/SITE/tool/NNNN/Comments
		pageToRequest = "/portal" + pageToRequest.substring(i);
		$(this).load(pageToRequest, commentsLoaded);
		//$.PeriodicalUpdater(pageToRequest, {minTimeout:5000, maxTimeout:120000}, function(data) {
		//	$(".deleteLink").attr("title", msg("simplepage.comment_delete"));
		//	$(".editLink").attr("title", msg("simplepage.edit-comment"));
		//	$(".replaceWithComments").html(data);
		//});
	});

	$("#delete-dialog").dialog({
		autoOpen: false,
		width: 400,
		modal: false,
		resizable: false,
		buttons: {
			"Cancel": function() {
				if(originalDeleteDialogText != null) {
					$("#delete-comment-confirm").text(originalDeleteDialogText);
				}

				$(this).dialog("close");
			},

			"Delete Comment": function() {
				confirmDelete();
			}
		}
	});
});

function commentsLoaded() {
	setMainFrameHeight(window.name);

	$(".pointsBox").unbind("keyup");

	$(".pointsBox").each(function(index, value) {
		$(value).parent().children("img").attr("id", "statusImg" + index);
		$(value).val($(value).parent().children(".pointsSpan").text());
	});

	$(".pointsBox").live('change', function(){
		var img = $(this).parent().children("img");
		img.attr("src", getStrippedImgSrc(img.attr("id")) + "no-status.png");
		$(this).addClass("unsubmitted");
	});

	$(".pointsBox").keyup(function(event){
		if(event.keyCode == 13) {
			var img = $(this).parent().children("img");

			$(this).removeClass("unsubmitted");
			img.attr("src", getStrippedImgSrc(img.attr("id")) + "loading.gif");

			$(".idField").val($(this).parent().children(".uuidBox").text()).change();
			$(".jsIdField").val(img.attr("id")).change();
			$(".typeField").val("comment");

			// This one triggers the update
			$(".pointsField").val($(this).val()).change();
		}
	});
}

function loadMore(link) {
	$.ajaxSetup ({
		cache: false
	});

	var pageToRequest = $(link).parent().parent().find(".to-load").attr("href");
	var i = pageToRequest.indexOf("/tool/");
	pageToRequest = "/portal" + pageToRequest.substring(i);

	$(link).parents(".replaceWithComments").load(pageToRequest, commentsLoaded);

	setMainFrameHeight(window.name);
}

function performHighlight() {
	$(".highlight-comment").effect("highlight", {}, 4000);
}

function replyToComment(link, replytext) {

	var evolved = $(link).parents(".commentsDiv").find(".evolved-box");

	if(noEditor) {
	    var body = $(link).parent().children(".commentBody");
	    // this should get the text out of the comment with newlines
	    // however innertext doesn't work on FF and I've heard rumors
	    // about IE 9. Hence provide a standard backup. It will handle
	    // newlines if they were entered via this text box, but
	    // may not if entered in the editor
	    body = body.get(0).innerText || body.text().replace(/^\s*/,"").replace(/\n\s*/g,"\n");
	    body = replytext + '\n\n' + body.replace(/^/,"|  ").replace(/\n/g,"\n|  ") + '\n\n';
	    evolved.val(body);
	} else if(fckEditor) {
		FCKeditorAPI.GetInstance(evolved.children("textarea").attr("name")).SetHTML(replytext + '
' + (link).parent().children(".commentBody").html() + '
\n

');
	}else {
		CKEDITOR.instances[evolved.children("textarea").attr("name")].setData(replytext + '
' + $(link).parent().children(".commentBody").html() + '
\n

');
	}

	$(link).parents(".commentsDiv").find(".comment-edit-id").val(null);
	$(link).parents(".commentsDiv").find(".submitButton").val(msg("simplepage.add-comment"));

        switchEditors(link);

	return false;
}

function switchEditors(link, show) {
	if(show==undefined) show = true;

	var evolved;

	if (noEditor) {
		evolved = $(link).parents(".commentsDiv").find(".evolved-box");
		evolved.css('width', '600px');
		evolved.css('height', '175px');
	}else if(fckEditor) {
		evolved = $(link).parents(".commentsDiv").find(".evolved-box :not(textarea)");
	}else {
		evolved = $(link).parents(".commentsDiv").find(".evolved-box");
	}

	if(show) {

 	    evolved.show();
 	    //$(link).parents(".commentsDiv").find(".editarea").show();

 		if(noEditor) {
 		    evolved.focus();
 		} else if(fckEditor) {
 		    var evolvedbox = $(link).parents(".commentsDiv").find(".evolved-box");
 		    FCKeditorAPI.GetInstance(evolvedbox.children("textarea").attr("name")).Focus();
 		}else {
 		    var frame = $(link).parents(".commentsDiv").find("iframe");

 		    // the builtin title is grossly too long, and not internationalized
 		    if (frame != null) {
 		    	frame.attr("title", msg("simplepage.ckeditor"));
		    }

 		    // seem to need this to make focus show up in VoiceOver. Looks like it's
 		    // not seeing into the iframe, although Safari shows it as selected
 		    if (frame != null) {
 			frame.focus();
 		    }
 		    CKEDITOR.instances[evolved.children("textarea").attr("name")].focus();
 		}

		var pos = evolved.offset();
		window.scrollTo(pos.left, pos.top);

		if (noEditor) {
		    // the submit expects HTML, so stick BRs at every newline
		    var submit = $(link).parents(".commentsDiv").find(".submitButton");
		   submit.click(function(link) {
			    var text = $(this).parents(".commentsDiv").find(".evolved-box");
			    text.val(text.val().replace(/\r\n/g, "
\n").replace(/[\r\n]/g, "
\n"));
			    return true;
			});
		}

		$(link).parents(".commentsDiv").find(".submitButton").show();
		$(link).parents(".commentsDiv").find(".cancelButton").show();

		$(link).parents(".commentsDiv").find(".switchLink").hide();
	}else {
		evolved.hide();

		if(fckEditor) {
			evolved = $(link).parents(".commentsDiv").find(".evolved-box");
		}

		if (noEditor) {
			evolved.val("");
		} else if(fckEditor) {
			FCKeditorAPI.GetInstance(evolved.children("textarea").attr("name")).SetHTML("");
		}else {
			CKEDITOR.instances[evolved.children("textarea").attr("name")].setData("");
		}

		$(link).parents(".commentsDiv").find(".submitButton").hide().val(msg("simplepage.add-comment"));
		$(link).parents(".commentsDiv").find(".cancelButton").hide().val(msg("simplepage.cancel_message"));

		$(link).parents(".commentsDiv").find(".switchLink").show();
		$(link).parents(".commentsDiv").find(".comment-edit-id").val("");

	}

	if(ckEditor) {
		evolved.find("textarea").hide();
	}

	setMainFrameHeight(window.name);
	$(document).height($('body').height());
}

function deleteComment(link) {
	$.ajaxSetup ({
		cache: false
	});

	deleteDialogCommentURL = $(link).parent().children(".deleteComment").attr("href");
	var i = deleteDialogCommentURL.indexOf("Comment");
	deleteDialogCommentURL = "/sakai-lessonbuildertool-tool/faces/" + deleteDialogCommentURL.substring(i);

	//var dialog = $(link).parents(".replaceWithComments").find(".delete-dialog");
	//$("#delete-dialog").children(".delete-dialog-comment-url").text(pageToRequest);

	originalDeleteDialogText = $("#delete-comment-confirm").text();
	$("#delete-comment-confirm").text(
			originalDeleteDialogText.replace("{}", link.parents(".commentDiv").find(".author").text()));

	$("#delete-dialog").dialog("open");

	commentToReload = $(link).parents(".replaceWithComments");

	//$(link).parents(".replaceWithComments").load(pageToRequest);

	//setMainFrameHeight(window.name);
}

function confirmDelete() {
	$(commentToReload).load(deleteDialogCommentURL, commentsLoaded);
	//$("#delete-dialog").parents(".replaceWithComments").load($(dialog).children(".delete-dialog-comment-url").text());
	setMainFrameHeight(window.name);
	$("#delete-dialog").dialog("close");
	$("#delete-comment-confirm").text(originalDeleteDialogText);
}

function edit(link, id) {
	var evolved = $(link).parents(".commentsDiv").find(".evolved-box");

	if(noEditor) {
	    var body = $(link).parent().children(".commentBody");
	    // this should get the text out of the comment with newlines
	    // however innertext doesn't work on FF and I've heard rumors
	    // about IE 9. Hence provide a standard backup. It will handle
	    // newlines if they were entered via this text box, but
	    // may not if entered in the editor
	    body = body.get(0).innerText || body.text().replace(/^\s*/,"").replace(/\n\s*/g,"\n");
	    evolved.val(body);

	} else if(fckEditor) {
		FCKeditorAPI.GetInstance(evolved.children("textarea").attr("name")).SetHTML($(link).parent().children(".commentBody").html());
	}else {
		CKEDITOR.instances[evolved.children("textarea").attr("name")].setData($(link).parent().children(".commentBody").html());
	}

	$(link).parents(".commentsDiv").find(".comment-edit-id").val(id);
	$(link).parents(".commentsDiv").find(".submitButton").val(msg("simplepage.edit-comment"));

	switchEditors(link);
}
<|endoftext|>


<commit_before>import MappingService from '../services/MappingService';
import constants from '../Constants';
import getIconPrefixer from '../../../../../utils/handlebars/getIconPrefixer';
import LocalizationService from '../../../../../services/LocalizationService';

export default {
    getAutoCompleteContext() {
        let result;
        switch (this.autoCompleteContext) {
            case constants.autoCompleteContext.functions:
                result = constants.autoCompleteContext.functions;
                break;
            case constants.autoCompleteContext.attributes:
                result = constants.autoCompleteContext.attributes;
                break;
            case constants.autoCompleteContext.templates:
                result = constants.autoCompleteContext.templates;
                break;
            default:
                result = null;
        }

        return result;
    },

    findAutoCompleteContext(sourceCode, pos, autoCompleteModel) {
        const str = sourceCode.substr(pos - 3, 4);
        if (str === constants.activeSymbol.dbArrayRight) {
            this.autoCompleteContext = constants.autoCompleteContext.templates;
            return autoCompleteModel.get(constants.autoCompleteContext.templates);
        }
        this.autoCompleteContext = constants.autoCompleteContext.attributes;
        return autoCompleteModel.get(constants.autoCompleteContext.attributes);
    },

    async getDataRequest(options, type) {
        let result;
        if (type === constants.autoCompleteContext.attributes && options.templateId) {
            result = await options.intelliAssist.getAttributes(options.templateId);
        }
        if (type === constants.autoCompleteContext.templates && options.completeHoverQuery) {
            result = await options.intelliAssist.getTemplates(options.completeHoverQuery);
        }
        if (!result) {
            return [];
        }
        const arr = MappingService.mapOntologyArrayToAutoCompleteArray(result, type);
        return arr;
    },

    async getAutoCompleteObject(options = {}) {
        let completion = [];
        let currentArray = [];
        let autoCompleteObject = {};
        if (options.token.type === constants.tokenTypes.identifier || options.types[options.token.type]) {
            if (options.completeHoverQuery.sourceCode[options.token.start - 1] === constants.activeSymbol.dollar) {
                currentArray = options.autoCompleteModel.get(constants.autoCompleteContext.attributes);
            } else if (options.completeHoverQuery.sourceCode[options.token.start - 1] === constants.activeSymbol.rightAngleBracket) {
                currentArray = this.findAutoCompleteContext(options.completeHoverQuery.sourceCode, options.token.start - 1, options.autoCompleteModel);
            } else {
                currentArray = options.autoCompleteModel.get(constants.autoCompleteContext.functions);
                this.autoCompleteContext = constants.autoCompleteContext.functions;
            }
            if (options.token.string === null) {
                return;
            }
            if (currentArray.length) {
                completion = currentArray.filter(item => item.text.toLowerCase().indexOf(options.token.string.toLowerCase()) > -1);
                autoCompleteObject = {
                    from: {
                        line: options.cursor.line,
                        ch: options.token.start
                    },
                    to: {
                        line: options.cursor.line,
                        ch: options.token.end
                    },
                    list: completion
                };
            } else {
                autoCompleteObject = {
                    from: options.cursor,
                    to: options.cursor,
                    list: [{ text: LocalizationService.get('CORE.FORM.EDITORS.CODE.NOSUGGESTIONS') }]
                };
            }
        } else if (options.token.string === constants.activeSymbol.dollar) {
            let listToolbar;
            const result = await this.getDataRequest(options, constants.autoCompleteContext.attributes);
            if (result.length) {
                options.autoCompleteModel.set({ attributes: result });
                this.autoCompleteContext = constants.autoCompleteContext.attributes;
                listToolbar = this.__renderConfigListToolbar(result);
            } else {
                listToolbar = [{ text: LocalizationService.get('CORE.FORM.EDITORS.CODE.NOSUGGESTIONS') }];
            }
            autoCompleteObject = {
                from: options.cursor,
                to: options.cursor,
                list: listToolbar
            };
        } else if (options.token.string === constants.activeSymbol.arrayRight) {
            const result = await this.getDataRequest(options, constants.autoCompleteContext.templates);
            options.autoCompleteModel.set({ templates: result });
            this.autoCompleteContext = constants.autoCompleteContext.templates;
            autoCompleteObject = {
                from: options.cursor,
                to: options.cursor,
                list: this.__renderConfigListToolbar(result)
            };
        } else if (options.token.string === constants.activeSymbol.openParenthesis || options.codemirror.getValue().trim() === '') {
            autoCompleteObject = {
                from: options.cursor,
                to: options.cursor,
                list: this.__renderConfigListToolbar(options.autoCompleteModel.get(constants.autoCompleteContext.functions))
            };
        } else {
            autoCompleteObject = {
                from: options.cursor,
                to: options.cursor,
                list: this.__renderConfigListToolbar(completion)
            };
        }
        return autoCompleteObject;
    },

    __renderConfigListToolbar(list) {
        if (list.length) {
            list?.forEach(item => {
                item.render = function(el, cm, data) {
                    const icon = document.createElement('i');
                    const text = document.createElement('span');
                    text.innerText = data.text;
                    const type = data.type;
                    const getIcon = getIconPrefixer(type);
                    icon.className = getIcon(type);
                    el.appendChild(icon);
                    el.appendChild(text);
                };
            });
            return list;
        }
    }
};
<commit_msg>Bugfix - fix check array<commit_after>import MappingService from '../services/MappingService';
import constants from '../Constants';
import getIconPrefixer from '../../../../../utils/handlebars/getIconPrefixer';
import LocalizationService from '../../../../../services/LocalizationService';

export default {
    getAutoCompleteContext() {
        let result;
        switch (this.autoCompleteContext) {
            case constants.autoCompleteContext.functions:
                result = constants.autoCompleteContext.functions;
                break;
            case constants.autoCompleteContext.attributes:
                result = constants.autoCompleteContext.attributes;
                break;
            case constants.autoCompleteContext.templates:
                result = constants.autoCompleteContext.templates;
                break;
            default:
                result = null;
        }

        return result;
    },

    findAutoCompleteContext(sourceCode, pos, autoCompleteModel) {
        const str = sourceCode.substr(pos - 3, 4);
        if (str === constants.activeSymbol.dbArrayRight) {
            this.autoCompleteContext = constants.autoCompleteContext.templates;
            return autoCompleteModel.get(constants.autoCompleteContext.templates);
        }
        this.autoCompleteContext = constants.autoCompleteContext.attributes;
        return autoCompleteModel.get(constants.autoCompleteContext.attributes);
    },

    async getDataRequest(options, type) {
        let result;
        if (type === constants.autoCompleteContext.attributes && options.templateId) {
            result = await options.intelliAssist.getAttributes(options.templateId);
        }
        if (type === constants.autoCompleteContext.templates && options.completeHoverQuery) {
            result = await options.intelliAssist.getTemplates(options.completeHoverQuery);
        }
        if (!result) {
            return [];
        }
        const arr = MappingService.mapOntologyArrayToAutoCompleteArray(result, type);
        return arr;
    },

    async getAutoCompleteObject(options = {}) {
        let completion = [];
        let currentArray = [];
        let autoCompleteObject = {};
        if (options.token.type === constants.tokenTypes.identifier || options.types[options.token.type]) {
            if (options.completeHoverQuery.sourceCode[options.token.start - 1] === constants.activeSymbol.dollar) {
                currentArray = options.autoCompleteModel.get(constants.autoCompleteContext.attributes);
            } else if (options.completeHoverQuery.sourceCode[options.token.start - 1] === constants.activeSymbol.rightAngleBracket) {
                currentArray = this.findAutoCompleteContext(options.completeHoverQuery.sourceCode, options.token.start - 1, options.autoCompleteModel);
            } else {
                currentArray = options.autoCompleteModel.get(constants.autoCompleteContext.functions);
                this.autoCompleteContext = constants.autoCompleteContext.functions;
            }
            if (options.token.string === null) {
                return;
            }
            if (currentArray && currentArray.length) {
                completion = currentArray.filter(item => item.text.toLowerCase().indexOf(options.token.string.toLowerCase()) > -1);
                autoCompleteObject = {
                    from: {
                        line: options.cursor.line,
                        ch: options.token.start
                    },
                    to: {
                        line: options.cursor.line,
                        ch: options.token.end
                    },
                    list: completion
                };
            } else {
                autoCompleteObject = {
                    from: options.cursor,
                    to: options.cursor,
                    list: [{ text: LocalizationService.get('CORE.FORM.EDITORS.CODE.NOSUGGESTIONS') }]
                };
            }
        } else if (options.token.string === constants.activeSymbol.dollar) {
            let listToolbar;
            const result = await this.getDataRequest(options, constants.autoCompleteContext.attributes);
            if (result.length) {
                options.autoCompleteModel.set({ attributes: result });
                this.autoCompleteContext = constants.autoCompleteContext.attributes;
                listToolbar = this.__renderConfigListToolbar(result);
            } else {
                listToolbar = [{ text: LocalizationService.get('CORE.FORM.EDITORS.CODE.NOSUGGESTIONS') }];
            }
            autoCompleteObject = {
                from: options.cursor,
                to: options.cursor,
                list: listToolbar
            };
        } else if (options.token.string === constants.activeSymbol.arrayRight) {
            const result = await this.getDataRequest(options, constants.autoCompleteContext.templates);
            options.autoCompleteModel.set({ templates: result });
            this.autoCompleteContext = constants.autoCompleteContext.templates;
            autoCompleteObject = {
                from: options.cursor,
                to: options.cursor,
                list: this.__renderConfigListToolbar(result)
            };
        } else if (options.token.string === constants.activeSymbol.openParenthesis || options.codemirror.getValue().trim() === '') {
            autoCompleteObject = {
                from: options.cursor,
                to: options.cursor,
                list: this.__renderConfigListToolbar(options.autoCompleteModel.get(constants.autoCompleteContext.functions))
            };
        } else {
            autoCompleteObject = {
                from: options.cursor,
                to: options.cursor,
                list: this.__renderConfigListToolbar(completion)
            };
        }
        return autoCompleteObject;
    },

    __renderConfigListToolbar(list) {
        if (list.length) {
            list?.forEach(item => {
                item.render = function(el, cm, data) {
                    const icon = document.createElement('i');
                    const text = document.createElement('span');
                    text.innerText = data.text;
                    const type = data.type;
                    const getIcon = getIconPrefixer(type);
                    icon.className = getIcon(type);
                    el.appendChild(icon);
                    el.appendChild(text);
                };
            });
            return list;
        }
    }
};
<|endoftext|>