<commit_before>//-*- coding: utf-8 -*-
//############################################################################
//
//   OpenERP, Open Source Management Solution
//   This module copyright (C) 2014 Therp BV (<http://therp.nl>).
//
//   This program is free software: you can redistribute it and/or modify
//   it under the terms of the GNU Affero General Public License as
//   published by the Free Software Foundation, either version 3 of the
//   License, or (at your option) any later version.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Affero General Public License for more details.
//
//   You should have received a copy of the GNU Affero General Public License
//   along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
//############################################################################

openerp.attachment_preview = function(instance)
{
    var _t = instance.web._t;
    openerp.attachment_preview.show_preview = function(
            attachment_id, attachment_url, attachment_extension,
            attachment_title)
    {
        var url = (window.location.origin || '') +
            '/attachment_preview/static/lib/ViewerJS/index.html#' +
            attachment_url.replace(window.location.origin, '') +
            '&title=' + encodeURIComponent(attachment_title) +
            '&ext=.' + encodeURIComponent(attachment_extension);
        window.open(url);
    };
    openerp.attachment_preview.can_preview = function(extension)
    {
        return jQuery.inArray(
            extension, ['odt', 'odp', 'ods', 'fodt', 'pdf']) > -1;
    };
    instance.web.Sidebar.include(
    {
        init: function(parent, form_view)
        {
            this.attachment_title_preview = function(name)
            {
                return _.str.sprintf(
                    instance.web._t("Preview attachment %s"), name);
            };
            return this._super.apply(this, arguments);
        },
        on_attachments_loaded: function(attachments)
        {
            var result = this._super.apply(this, arguments);
            this.$el.find('.oe-sidebar-attachment-preview')
                .click(this.on_attachment_preview);
            this.update_preview_buttons();
            return result;
        },
        on_attachment_preview: function(e)
        {
            e.preventDefault();
            e.stopPropagation();
            var self = this,
                $target = jQuery(e.currentTarget),
                attachment_id = parseInt($target.attr('data-id')),
                attachment_url = $target.attr('data-url'),
                attachment_extension = $target.attr('data-extension'),
                attachment_title = $target.attr('original-title');
            if(attachment_extension)
            {
                openerp.attachment_preview.show_preview(
                    attachment_id, attachment_url, attachment_extension,
                    attachment_title);
            }
            else
            {
                (new instance.web.Model('ir.attachment')).call(
                    'get_attachment_extension', [attachment_id], {})
                .then(function(extension)
                {
                    openerp.attachment_preview.show_preview(
                        attachment_id, attachment_url, extension);
                });
            }
        },
        update_preview_buttons: function()
        {
            var self = this;
            return (new instance.web.Model('ir.attachment')).call(
                'get_attachment_extension',
                [
                    this.$el.find('.oe-sidebar-attachment-preview')
                    .map(function()
                    {
                        return parseInt(jQuery(this).attr('data-id'));
                    })
                    .get()
                ],
                {})
                .then(function(extensions)
                {
                    _(extensions).each(function(extension, id)
                    {
                        var $element = jQuery(
                            'a.oe-sidebar-attachment-preview[data-id="'
                            + id + '"]');
                        if(openerp.attachment_preview.can_preview(extension))
                        {
                            $element.attr('data-extension', extension);
                        }
                        else
                        {
                            $element.remove();
                        }
                    });
                });
        },
    });
    instance.web.ListView.include(
    {
        reload_content: function()
        {
            var deferred = this._super.apply(this, arguments),
                self = this;
            deferred.then(function()
            {
                var $elements = self.$el.find('.oe-binary-preview');
                if(!$elements.length)
                {
                    return;
                }
                $elements.click(function(e)
                {
                    e.stopPropagation();
                    var $target = jQuery(e.currentTarget),
                        attachment_id = parseInt($target.attr('data-id')),
                        attachment_extension = $target.attr('data-extension');
                    openerp.attachment_preview.show_preview(
                        attachment_id,
                        $target.siblings('a').attr('href'),
                        attachment_extension,
                        _t('Preview'));
                });
                return (new instance.web.Model('ir.attachment')).call(
                    'get_binary_extension',
                    [
                        $elements.attr('data-model'),
                        $elements
                        .map(function()
                        {
                            return parseInt(jQuery(this).attr('data-id'));
                        })
                        .get(),
                        $elements.attr('data-field'),
                        $elements.attr('data-filename'),
                    ],
                    {})
                    .then(function(extensions)
                    {
                        _(extensions).each(function(extension, id)
                        {
                            var $element = $elements.filter(
                                '[data-id="' + id + '"]');
                            if(openerp.attachment_preview.can_preview(extension))
                            {
                                $element.attr('data-extension', extension);
                            }
                            else
                            {
                                $element.remove();
                            }
                        });
                    });
            });
            return deferred;
        }
    });
    instance.web.list.Binary.include(
    {
        _format: function (row_data, options)
        {
            var link = this._super.apply(this, arguments);
            link += _.template(
                '<img class="oe-binary-preview" alt="<%-preview_text%>" data-id="<%-preview_id%>" data-model="<%-preview_model%>" data-field="<%-preview_field%>" data-filename="<%-preview_filename%>" src="/web/static/src/img/icons/gtk-print-preview.png" />',
                {
                    preview_id: options.id,
                    preview_text: _t('Preview'),
                    preview_model: options.model,
                    preview_field: this.id,
                    preview_filename: this.filename or '',
                });
            return link;
        }
    });
    instance.web.form.FieldBinaryFile.include(
    {
        render_value: function()
        {
            this._super.apply(this, arguments);
            if(this.get("effective_readonly") && this.get('value'))
            {
                var self = this;
                (new instance.web.Model('ir.attachment')).call(
                    'get_binary_extension',                                                                    [
                    this.view.dataset.model,
                    this.view.datarecord.id ? [this.view.datarecord.id] : [],
                    this.name,
                    this.node.attrs.filename,
                    ],
                    {})
                .then(function(extensions)
                {
                    _(extensions).each(function(extension)
                    {
                        var $element = self.$el.find('.oe-binary-preview');
                        if(openerp.attachment_preview.can_preview(extension))
                        {
                            $element.click(function()
                            {
                                openerp.attachment_preview.show_preview(
                                    null,
                                    _.str.sprintf(
                                        '/web/binary/saveas?session_id=%s&model=%s&field=%s&id=%d',
                                        instance.session.session_id,
                                        self.view.dataset.model,
                                        self.name,
                                        self.view.datarecord.id),
                                    extension,
                                    self.view.datarecord[self.node.attrs.filename]);
                            });
                        }
                        else
                        {
                            $element.remove();
                        }
                    });
                });
            }
        },
    });
}
<commit_msg>[FIX] js != py<commit_after>//-*- coding: utf-8 -*-
//############################################################################
//
//   OpenERP, Open Source Management Solution
//   This module copyright (C) 2014 Therp BV (<http://therp.nl>).
//
//   This program is free software: you can redistribute it and/or modify
//   it under the terms of the GNU Affero General Public License as
//   published by the Free Software Foundation, either version 3 of the
//   License, or (at your option) any later version.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Affero General Public License for more details.
//
//   You should have received a copy of the GNU Affero General Public License
//   along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
//############################################################################

openerp.attachment_preview = function(instance)
{
    var _t = instance.web._t;
    openerp.attachment_preview.show_preview = function(
            attachment_id, attachment_url, attachment_extension,
            attachment_title)
    {
        var url = (window.location.origin || '') +
            '/attachment_preview/static/lib/ViewerJS/index.html#' +
            attachment_url.replace(window.location.origin, '') +
            '&title=' + encodeURIComponent(attachment_title) +
            '&ext=.' + encodeURIComponent(attachment_extension);
        window.open(url);
    };
    openerp.attachment_preview.can_preview = function(extension)
    {
        return jQuery.inArray(
            extension, ['odt', 'odp', 'ods', 'fodt', 'pdf']) > -1;
    };
    instance.web.Sidebar.include(
    {
        init: function(parent, form_view)
        {
            this.attachment_title_preview = function(name)
            {
                return _.str.sprintf(
                    instance.web._t("Preview attachment %s"), name);
            };
            return this._super.apply(this, arguments);
        },
        on_attachments_loaded: function(attachments)
        {
            var result = this._super.apply(this, arguments);
            this.$el.find('.oe-sidebar-attachment-preview')
                .click(this.on_attachment_preview);
            this.update_preview_buttons();
            return result;
        },
        on_attachment_preview: function(e)
        {
            e.preventDefault();
            e.stopPropagation();
            var self = this,
                $target = jQuery(e.currentTarget),
                attachment_id = parseInt($target.attr('data-id')),
                attachment_url = $target.attr('data-url'),
                attachment_extension = $target.attr('data-extension'),
                attachment_title = $target.attr('original-title');
            if(attachment_extension)
            {
                openerp.attachment_preview.show_preview(
                    attachment_id, attachment_url, attachment_extension,
                    attachment_title);
            }
            else
            {
                (new instance.web.Model('ir.attachment')).call(
                    'get_attachment_extension', [attachment_id], {})
                .then(function(extension)
                {
                    openerp.attachment_preview.show_preview(
                        attachment_id, attachment_url, extension);
                });
            }
        },
        update_preview_buttons: function()
        {
            var self = this;
            return (new instance.web.Model('ir.attachment')).call(
                'get_attachment_extension',
                [
                    this.$el.find('.oe-sidebar-attachment-preview')
                    .map(function()
                    {
                        return parseInt(jQuery(this).attr('data-id'));
                    })
                    .get()
                ],
                {})
                .then(function(extensions)
                {
                    _(extensions).each(function(extension, id)
                    {
                        var $element = jQuery(
                            'a.oe-sidebar-attachment-preview[data-id="'
                            + id + '"]');
                        if(openerp.attachment_preview.can_preview(extension))
                        {
                            $element.attr('data-extension', extension);
                        }
                        else
                        {
                            $element.remove();
                        }
                    });
                });
        },
    });
    instance.web.ListView.include(
    {
        reload_content: function()
        {
            var deferred = this._super.apply(this, arguments),
                self = this;
            deferred.then(function()
            {
                var $elements = self.$el.find('.oe-binary-preview');
                if(!$elements.length)
                {
                    return;
                }
                $elements.click(function(e)
                {
                    e.stopPropagation();
                    var $target = jQuery(e.currentTarget),
                        attachment_id = parseInt($target.attr('data-id')),
                        attachment_extension = $target.attr('data-extension');
                    openerp.attachment_preview.show_preview(
                        attachment_id,
                        $target.siblings('a').attr('href'),
                        attachment_extension,
                        _t('Preview'));
                });
                return (new instance.web.Model('ir.attachment')).call(
                    'get_binary_extension',
                    [
                        $elements.attr('data-model'),
                        $elements
                        .map(function()
                        {
                            return parseInt(jQuery(this).attr('data-id'));
                        })
                        .get(),
                        $elements.attr('data-field'),
                        $elements.attr('data-filename'),
                    ],
                    {})
                    .then(function(extensions)
                    {
                        _(extensions).each(function(extension, id)
                        {
                            var $element = $elements.filter(
                                '[data-id="' + id + '"]');
                            if(openerp.attachment_preview.can_preview(extension))
                            {
                                $element.attr('data-extension', extension);
                            }
                            else
                            {
                                $element.remove();
                            }
                        });
                    });
            });
            return deferred;
        }
    });
    instance.web.list.Binary.include(
    {
        _format: function (row_data, options)
        {
            var link = this._super.apply(this, arguments);
            link += _.template(
                '<img class="oe-binary-preview" alt="<%-preview_text%>" data-id="<%-preview_id%>" data-model="<%-preview_model%>" data-field="<%-preview_field%>" data-filename="<%-preview_filename%>" src="/web/static/src/img/icons/gtk-print-preview.png" />',
                {
                    preview_id: options.id,
                    preview_text: _t('Preview'),
                    preview_model: options.model,
                    preview_field: this.id,
                    preview_filename: this.filename || '',
                });
            return link;
        }
    });
    instance.web.form.FieldBinaryFile.include(
    {
        render_value: function()
        {
            this._super.apply(this, arguments);
            if(this.get("effective_readonly") && this.get('value'))
            {
                var self = this;
                (new instance.web.Model('ir.attachment')).call(
                    'get_binary_extension',                                                                    [
                    this.view.dataset.model,
                    this.view.datarecord.id ? [this.view.datarecord.id] : [],
                    this.name,
                    this.node.attrs.filename,
                    ],
                    {})
                .then(function(extensions)
                {
                    _(extensions).each(function(extension)
                    {
                        var $element = self.$el.find('.oe-binary-preview');
                        if(openerp.attachment_preview.can_preview(extension))
                        {
                            $element.click(function()
                            {
                                openerp.attachment_preview.show_preview(
                                    null,
                                    _.str.sprintf(
                                        '/web/binary/saveas?session_id=%s&model=%s&field=%s&id=%d',
                                        instance.session.session_id,
                                        self.view.dataset.model,
                                        self.name,
                                        self.view.datarecord.id),
                                    extension,
                                    self.view.datarecord[self.node.attrs.filename]);
                            });
                        }
                        else
                        {
                            $element.remove();
                        }
                    });
                });
            }
        },
    });
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012, Mozilla Foundation and contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

var Promise = require('../util/promise').Promise;
var Conversion = require('./types').Conversion;
var Status = require('./types').Status;

/**
 * The types we expose for registration
 */
exports.items = [
  // A type for "we don't know right now, but hope to soon"
  {
    item: 'type',
    name: 'delegate',

    constructor: function() {
      if (typeof this.delegateType !== 'function' &&
          typeof this.delegateType !== 'string') {
        throw new Error('Instances of DelegateType need typeSpec.delegateType' +
                        ' to be a function that returns a type');
      }
    },

    getSpec: function(commandName, paramName) {
      return {
        name: 'delegate',
        param: paramName
      };
    },

    // Child types should implement this method to return an instance of the type
    // that should be used. If no type is available, or some sort of temporary
    // placeholder is required, BlankType can be used.
    delegateType: function(context) {
      throw new Error('Not implemented');
    },

    stringify: function(value, context) {
      return this.getType(context).then(function(delegated) {
        return delegated.stringify(value, context);
      }.bind(this));
    },

    parse: function(arg, context) {
      return this.getType(context).then(function(delegated) {
        return delegated.parse(arg, context);
      }.bind(this));
    },

    decrement: function(value, context) {
      return this.getType(context).then(function(delegated) {
        return delegated.decrement ?
               delegated.decrement(value, context) :
               undefined;
      }.bind(this));
    },

    increment: function(value, context) {
      return this.getType(context).then(function(delegated) {
        return delegated.increment ?
               delegated.increment(value, context) :
               undefined;
      }.bind(this));
    },

    getType: function(context) {
      var type = this.delegateType(context);
      if (typeof type.parse !== 'function') {
        type = this.types.createType(type);
      }
      return Promise.resolve(type);
    },

    // DelegateType is designed to be inherited from, so DelegateField needs a
    // way to check if something works like a delegate without using 'name'
    isDelegate: true,

    // Technically we perhaps should proxy this, except that properties are
    // inherently synchronous, so we can't. It doesn't seem important enough to
    // change the function definition to accommodate this right now
    isImportant: false
  },
  {
    item: 'type',
    name: 'remote',
    param: undefined,

    stringify: function(value, context) {
      // remote types are client only, and we don't attempt to transfer value
      // objects to the client (we can't be sure the are jsonable) so it is a
      // but strange to be asked to stringify a value object, however since
      // parse creates a Conversion with a (fake) value object we might be
      // asked to stringify that. We can stringify fake value objects.
      if (typeof value.stringified === 'string') {
        return value.stringified;
      }
      throw new Error('Can\'t stringify that value');
    },

    parse: function(arg, context) {
      var args = { typed: context.typed, param: this.param };
      return this.connection.call('typeparse', args).then(function(json) {
        var status = Status.fromString(json.status);
        var val = { stringified: arg.text };
        return new Conversion(val, arg, status, json.message, json.predictions);
      });
    },

    decrement: function(value, context) {
      var args = { typed: context.typed, param: this.param };
      return this.connection.call('typedecrement', args).then(function(json) {
        return { stringified: json.arg };
      });
    },

    increment: function(value, context) {
      var args = { typed: context.typed, param: this.param };
      return this.connection.call('typeincrement', args).then(function(json) {
        return { stringified: json.arg };
      });
    }
  },
  // 'blank' is a type for use with DelegateType when we don't know yet.
  // It should not be used anywhere else.
  {
    item: 'type',
    name: 'blank',

    getSpec: function(commandName, paramName) {
      return 'blank';
    },

    stringify: function(value, context) {
      return '';
    },

    parse: function(arg, context) {
      return Promise.resolve(new Conversion(undefined, arg));
    }
  }
];
<commit_msg>runat-1128988: Use a blank type when we can't resolve the delegate type<commit_after>/*
 * Copyright 2012, Mozilla Foundation and contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

var Promise = require('../util/promise').Promise;
var Conversion = require('./types').Conversion;
var Status = require('./types').Status;

/**
 * The types we expose for registration
 */
exports.items = [
  // A type for "we don't know right now, but hope to soon"
  {
    item: 'type',
    name: 'delegate',

    getSpec: function(commandName, paramName) {
      return {
        name: 'delegate',
        param: paramName
      };
    },

    // Child types should implement this method to return an instance of the type
    // that should be used. If no type is available, or some sort of temporary
    // placeholder is required, BlankType can be used.
    delegateType: undefined,

    stringify: function(value, context) {
      return this.getType(context).then(function(delegated) {
        return delegated.stringify(value, context);
      }.bind(this));
    },

    parse: function(arg, context) {
      return this.getType(context).then(function(delegated) {
        return delegated.parse(arg, context);
      }.bind(this));
    },

    decrement: function(value, context) {
      return this.getType(context).then(function(delegated) {
        return delegated.decrement ?
               delegated.decrement(value, context) :
               undefined;
      }.bind(this));
    },

    increment: function(value, context) {
      return this.getType(context).then(function(delegated) {
        return delegated.increment ?
               delegated.increment(value, context) :
               undefined;
      }.bind(this));
    },

    getType: function(context) {
      if (this.delegateType === undefined) {
        return Promise.resolve(this.types.createType('blank'));
      }

      var type = this.delegateType(context);
      if (typeof type.parse !== 'function') {
        type = this.types.createType(type);
      }
      return Promise.resolve(type);
    },

    // DelegateType is designed to be inherited from, so DelegateField needs a
    // way to check if something works like a delegate without using 'name'
    isDelegate: true,

    // Technically we perhaps should proxy this, except that properties are
    // inherently synchronous, so we can't. It doesn't seem important enough to
    // change the function definition to accommodate this right now
    isImportant: false
  },
  {
    item: 'type',
    name: 'remote',
    param: undefined,

    stringify: function(value, context) {
      // remote types are client only, and we don't attempt to transfer value
      // objects to the client (we can't be sure the are jsonable) so it is a
      // but strange to be asked to stringify a value object, however since
      // parse creates a Conversion with a (fake) value object we might be
      // asked to stringify that. We can stringify fake value objects.
      if (typeof value.stringified === 'string') {
        return value.stringified;
      }
      throw new Error('Can\'t stringify that value');
    },

    parse: function(arg, context) {
      var args = { typed: context.typed, param: this.param };
      return this.connection.call('typeparse', args).then(function(json) {
        var status = Status.fromString(json.status);
        var val = { stringified: arg.text };
        return new Conversion(val, arg, status, json.message, json.predictions);
      });
    },

    decrement: function(value, context) {
      var args = { typed: context.typed, param: this.param };
      return this.connection.call('typedecrement', args).then(function(json) {
        return { stringified: json.arg };
      });
    },

    increment: function(value, context) {
      var args = { typed: context.typed, param: this.param };
      return this.connection.call('typeincrement', args).then(function(json) {
        return { stringified: json.arg };
      });
    }
  },
  // 'blank' is a type for use with DelegateType when we don't know yet.
  // It should not be used anywhere else.
  {
    item: 'type',
    name: 'blank',

    getSpec: function(commandName, paramName) {
      return 'blank';
    },

    stringify: function(value, context) {
      return '';
    },

    parse: function(arg, context) {
      return Promise.resolve(new Conversion(undefined, arg));
    }
  }
];
<|endoftext|>


<commit_before>/*************************************************
 * Copyright (c) 2015 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

import stringFilters from 'tower/shared/string-filters/main';

var $injector = angular.injector(['ng', stringFilters.name]);
var $interpolate = $injector.get('$interpolate');

function parseFactTemplate(factTemplate, fact) {
    if (_.isFunction(factTemplate)) {
        return factTemplate(fact);
    } else {
        return factTemplate;
    }
}

function renderFactTemplate(template, fact) {
    return $interpolate(template)(fact);
}

function slotFactValues(basisPosition, basisValue, comparatorValue) {
    var leftValue, rightValue;

    if (basisPosition === 'left') {
        leftValue = basisValue;
        rightValue = comparatorValue;
    } else {
        rightValue = basisValue;
        leftValue = comparatorValue;
    }

    return  {    left: leftValue,
                 right: rightValue
            };
}

export default
    function flatCompare(basisFacts, comparatorFacts, nameKey, compareKeys, factTemplate) {

        return basisFacts.reduce(function(arr, basisFact) {
            var searcher = {};
            searcher[nameKey] = basisFact[nameKey];

            var isNestedDisplay = false;
            var basisTemplate, comparatorTemplate, slottedValues, basisValue, comparatorValue;

            var matchingFact = _.where(comparatorFacts, searcher);
            var diffs;

            if (_.isEmpty(matchingFact)) {

                if (!_.isUndefined(factTemplate)) {

                    basisTemplate = parseFactTemplate(factTemplate, basisFact);

                    basisValue = renderFactTemplate(basisTemplate, basisFact);
                    slottedValues = slotFactValues(basisFacts.position, basisValue, 'absent');

                    diffs =
                        {   keyName: basisFact[nameKey],
                            isNestedDisplay: false,
                            value1: slottedValues.left,
                            value2: slottedValues.right
                        };

                } else {

                    isNestedDisplay = true;
                    diffs =
                        _.map(basisFact, function(value, key) {
                            var slottedValues = slotFactValues(basisFacts.position, value, 'absent');

                            return {   keyName: key,
                                        value1: slottedValues.left,
                                        value2: slottedValues.right
                                    };
                        });
                }
            } else {

                matchingFact = matchingFact[0];

                if (!_.isUndefined(factTemplate)) {

                    basisTemplate = parseFactTemplate(factTemplate, basisFact);
                    comparatorTemplate = parseFactTemplate(factTemplate, matchingFact);

                    basisValue = renderFactTemplate(basisTemplate, basisFact);
                    comparatorValue = renderFactTemplate(comparatorTemplate, matchingFact);

                    slottedValues = slotFactValues(basisFacts.position, basisValue, comparatorValue);

                    diffs =
                        {   keyName: basisFact[nameKey],
                            isNestedDisplay: false,
                            value1: slottedValues.left,
                            value2: slottedValues.right
                        };

                } else {

                    isNestedDisplay = true;

                    diffs = _(compareKeys)
                        .map(function(key) {
                            var slottedValues = slotFactValues(basisFacts.position,
                                                               basisFact[key],
                                                               matchingFact[key]);

                            if (slottedValues.left !== slottedValues.right) {
                                return {
                                    keyName: key,
                                    value1: slottedValues.left,
                                    value2: slottedValues.right
                                };
                            }
                        }).compact()
                        .value();
                }

            }

            var descriptor =
                    {   displayKeyPath: basisFact[nameKey],
                        isNestedDisplay: isNestedDisplay,
                        nestingLevel: 0,
                        facts: diffs
                    };

            return arr.concat(descriptor);
        }, []).filter(function(diff) {
            return !_.isEmpty(diff.facts);
        });

    }
<commit_msg>Track fact presence with property<commit_after>/*************************************************
 * Copyright (c) 2015 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/

import stringFilters from 'tower/shared/string-filters/main';

var $injector = angular.injector(['ng', stringFilters.name]);
var $interpolate = $injector.get('$interpolate');

function parseFactTemplate(factTemplate, fact) {
    if (_.isFunction(factTemplate)) {
        return factTemplate(fact);
    } else {
        return factTemplate;
    }
}

function renderFactTemplate(template, fact) {
    return $interpolate(template)(fact);
}

function slotFactValues(basisPosition, basisValue, comparatorValue) {
    var leftValue, rightValue;

    if (basisPosition === 'left') {
        leftValue = basisValue;
        rightValue = comparatorValue;
    } else {
        rightValue = basisValue;
        leftValue = comparatorValue;
    }

    return  {    left: leftValue,
                 right: rightValue
            };
}

export default
    function flatCompare(basisFacts, comparatorFacts, nameKey, compareKeys, factTemplate) {

        return basisFacts.reduce(function(arr, basisFact) {
            var searcher = {};
            searcher[nameKey] = basisFact[nameKey];

            var isNestedDisplay = false;
            var basisTemplate, comparatorTemplate, slottedValues, basisValue, comparatorValue;

            var matchingFact = _.where(comparatorFacts, searcher);
            var diffs;

            if (_.isEmpty(matchingFact)) {

                if (!_.isUndefined(factTemplate)) {

                    basisTemplate = parseFactTemplate(factTemplate, basisFact);

                    basisValue = renderFactTemplate(basisTemplate, basisFact);
                    slottedValues = slotFactValues(basisFacts.position, basisValue, 'absent');

                    diffs =
                        {   keyName: basisFact[nameKey],
                            isNestedDisplay: false,
                            value1: slottedValues.left,
                            value2: slottedValues.right
                        };

                } else {

                    isNestedDisplay = true;
                    diffs =
                        _.map(basisFact, function(value, key) {
                            var slottedValues = slotFactValues(basisFacts.position, value, 'absent');

                            return {   keyName: key,
                                        value1: slottedValues.left,
                                        value1IsAbsent: slottedValues.left === 'absent',
                                        value2: slottedValues.right,
                                        value2IsAbsent: slotFactValues.right === 'absent'
                                    };
                        });
                }
            } else {

                matchingFact = matchingFact[0];

                if (!_.isUndefined(factTemplate)) {

                    basisTemplate = parseFactTemplate(factTemplate, basisFact);
                    comparatorTemplate = parseFactTemplate(factTemplate, matchingFact);

                    basisValue = renderFactTemplate(basisTemplate, basisFact);
                    comparatorValue = renderFactTemplate(comparatorTemplate, matchingFact);

                    slottedValues = slotFactValues(basisFacts.position, basisValue, comparatorValue);

                    diffs =
                        {   keyName: basisFact[nameKey],
                            isNestedDisplay: false,
                            value1: slottedValues.left,
                            value2: slottedValues.right
                        };

                } else {

                    isNestedDisplay = true;

                    diffs = _(compareKeys)
                        .map(function(key) {
                            var slottedValues = slotFactValues(basisFacts.position,
                                                               basisFact[key],
                                                               matchingFact[key]);

                            if (slottedValues.left !== slottedValues.right) {
                                return {
                                    keyName: key,
                                    value1: slottedValues.left,
                                    value2: slottedValues.right
                                };
                            }
                        }).compact()
                        .value();
                }

            }

            var descriptor =
                    {   displayKeyPath: basisFact[nameKey],
                        isNestedDisplay: isNestedDisplay,
                        nestingLevel: 0,
                        facts: diffs
                    };

            return arr.concat(descriptor);
        }, []).filter(function(diff) {
            return !_.isEmpty(diff.facts);
        });

    }
<|endoftext|>


<commit_before>import RavenLogger from 'ember-cli-sentry/services/raven';

export default RavenLogger.extend({
  ignoreError(error) {
    return error.name === 'TransitionAborted';
  },
});
<commit_msg>services/raven: Fix ignoreError() edge case<commit_after>import RavenLogger from 'ember-cli-sentry/services/raven';

export default RavenLogger.extend({
  ignoreError(error) {
    return error && error.name === 'TransitionAborted';
  },
});
<|endoftext|>


<commit_before>// https://www.shadertoy.com/view/Xsl3zf
function hash(n) {
    return Shade.fract(Math.sin(n)*43758.5453123);
}

function shade(env) {
    var p = this.normalizedCoords.xy().mul(2).sub(1);

    var n = p.x(this.width / this.height);

    if (Math.abs(p.y()) > .8 || Math.floor(this.coords.y()) % 3.0 > 0.0) {
        return new Vec3(0);
    }

    var c = env.channel0 ? env.channel0.sample2D(this.normalizedCoords).xyz() : new Vec3(0);

    // flicker, grain, vignette, fade in
    c = c.add(Math.sin(hash(env.time)) * 0.01);
    c = c.add(hash((hash(n.x()) + n.y()) * env.time) * 0.4);
    c = c.mul(Shade.smoothstep(n.length() * 0.18, 0.8, 0.4));
    c = c.mul(1.9);
    c = c.mul(Shade.smoothstep(0.001, 3.5, env.time));

    var s = c.dot(0.2126, 0.7152, 0.0722);
    return new Vec3(0.2, 1.5 - hash(env.time) * 0.1, 0.4).mul(s);
}
<commit_msg>Examples: Bugfixes and imrpovments in nightvision.js<commit_after>// https://www.shadertoy.com/view/Xsl3zf
function hash(n) {
    return Shade.fract(Math.sin(n)*43758.5453123);
}

function shade(env) {
    var time = env.time || 10.0;
    var p = this.normalizedCoords.xy().mul(2).sub(1);

    var n = p.mul(this.width / this.height, 1.0);

    if (Math.abs(p.y()) > .8 || Math.floor(this.coords.y()) % 3.0 > 0.0) {
        return new Vec3(0);
    }

    var c = env.channel0 ? env.channel0.sample2D(this.normalizedCoords).xyz() : new Vec3(0,1,0);

    // flicker, grain, vignette, fade in
    c = c.add(Math.sin(hash(time)) * 0.01);
    c = c.add(hash((hash(n.x()) + n.y()) * time) * 0.4);
    c = c.mul(Shade.smoothstep(n.mul(0.18).length(), 0.8, 0.4));
    c = c.mul(1.9);
    c = c.mul(Shade.smoothstep(0.001, 3.5, time));

    var s = c.dot(0.2126, 0.7152, 0.0722);
    return new Vec3(0.2, 1.5 - hash(time) * 0.1, 0.4).mul(s);
}
<|endoftext|>


<commit_before>/*
 * C S O U N D
 *
 * L I C E N S E
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 */

var CsoundObj = function() {

    var that = this;
    var _new = cwrap('CsoundObj_new', ['number'], null);
    var _compileCSD = cwrap('CsoundObj_compileCSD', null, ['number', 'string']);
    var _evaluateCode = cwrap('CsoundObj_evaluateCode', ['number'], ['number', 'string']);
    var _readScore = cwrap('CsoundObj_readScore', ['number'], ['number', 'string']);
    var _reset = cwrap('CsoundObj_reset', null, ['number']);
    var _getOutputBuffer = cwrap('CsoundObj_getOutputBuffer', ['number'], ['number']);
    var _getInputBuffer = cwrap('CsoundObj_getInputBuffer', ['number'], ['number']);
    var _getControlChannel = cwrap('CsoundObj_getControlChannel', ['number'], ['number', 'string']);
    var _setControlChannel = cwrap('CsoundObj_setControlChannel', null, ['number', 'string', 'number']);
    var _setStringChannel = cwrap('CsoundObj_setStringChannel', null, ['number', 'string', 'string']);
    var _getKsmps = cwrap('CsoundObj_getKsmps', ['number'], ['number']);
    var _performKsmps = cwrap('CsoundObj_performKsmps', ['number'], ['number']);
    var _render = cwrap('CsoundObj_render', null, ['number']);
    var _getInputChannelCount = cwrap('CsoundObj_getInputChannelCount', ['number'], ['number']);
    var _getOutputChannelCount = cwrap('CsoundObj_getOutputChannelCount', ['number'], ['number']);
    var _getTableLength = cwrap('CsoundObj_getTableLength', ['number'], ['number', 'number']);
    var _getTable = cwrap('CsoundObj_getTable', ['number'], ['number', 'number']);
    var _getZerodBFS = cwrap('CsoundObj_getZerodBFS', ['number'], ['number']);
    var _setMidiCallbacks = cwrap('CsoundObj_setMidiCallbacks', null, ['number']);
    var _pushMidiMessage = cwrap('CsoundObj_pushMidiMessage', null, ['number', 'number', 'number', 'number']);
    var _setOutputChannelCallback = cwrap('CsoundObj_setOutputChannelCallback', null, ['number', 'number']);
    var _compileOrc = cwrap('CsoundObj_compileOrc', 'number', ['number', 'string']);
    var _prepareRT = cwrap('CsoundObj_prepareRT', null, ['number']);
    var _getScoreTime = cwrap('CsoundObj_getScoreTime', null, ['number']);
    var _setTable = cwrap('CsoundObj_setTable', null, ['number', 'number', 'number', 'number']);
    var _openAudioOut = cwrap('CsoundObj_openAudioOut', null, ['number']);
    var _closeAudioOut = cwrap('CsoundObj_closeAudioOut', null, ['number']);
    var _play = cwrap('CsoundObj_play', null, ['number']);
    var _paude = cwrap('CsoundObj_pause', null, ['number']);
    var bufferSize;
    var _self = _new();
    var _destroy = cwrap('CsoundObj_destroy', null, ['number']);
    var running;

    var getAudioContext = function() {

	try {
	    window.AudioContext = window.AudioContext || window.webkitAudioContext;
	    return new AudioContext();
	}
	catch(error) {

	    alert('Web Audio API is not supported in this browser');
	}
    };

    this.setMidiCallbacks = function() {
	_setMidiCallbacks(_self);
    }

    var microphoneNode = null;

    this.disableAudioInput = function (){
	microphoneNode = null;
    }

    this.midiMessage = function(byte1, byte2, byte3) {
        _pushMidiMessage(_self, byte1, byte2, byte3);
    }

    this.enableAudioInput = function(audioInputCallback) {

	window.navigator = window.navigator || {};
	navigator.getUserMedia = navigator.getUserMedia||navigator.webkitGetUserMedia ||navigator.mozGetUserMedia||null;

	if (navigator.getUserMedia === null) {

	    Module['print']("Audio Input not supported in this browser");
	    audioInputCallback(false);
	}
	else{
	    function onSuccess(stream) {

		microphoneNode = audioContext.createMediaStreamSource(stream);
		audioInputCallback(true);
	    };
	    function onFailure(error) {

		microphoneNode = null;
		audioInputCallback(false);
		Module['print']("Could not initialise audio input, error:" +  error);
	    };
	    navigator.getUserMedia({audio:true}, onSuccess, onFailure);
	}

    };

    this.enableMidiInput = function(midiInputCallback) {

	var handleMidiInput = function(event) {

	    _pushMidiMessage(_self, event.data[0], event.data[1], event.data[2]);
	};

	var midiSuccess = function(midiInterface) {

	    var inputs = midiInterface.inputs.values();

	    for (var input = inputs.next(); input && !input.done; input = inputs.next() ){

		input = input.value;
		input.onmidimessage = handleMidiInput;
	    }
	    _setMidiCallbacks(_self);
	    midiInputCallback(true);
	};

	var midiFail = function(error) {

	    Module['print']("MIDI failed to start, error:" + error);
	    midiInputCallback(false);
	};
	if (navigator.requestMIDIAccess) {

	    navigator.requestMIDIAccess().then(midiSuccess, midiFail);
	}
	else {

	    Module['print']("MIDI not supported in this browser");
	    midiInputCallback(false);
	}
    };

    var audioContext = getAudioContext();
    var samplerate = audioContext.sampleRate;
    var compiled = false;

    this.compileCSD = function(filePath) {
        _prepareRT(_self);
	_compileCSD(_self, filePath);
	compiled = true;
    };

    this.compileOrc = function(orcString)
    {
	_prepareRT(_self);
	_compileOrc(_self, orcString);
	compiled = true;

    };

    this.render = function(filePath) {

	_compileCSD(_self, filePath);
	_render(_self);
	compiled = false;
    }

    this.evaluateCode = function(codeString) {

	_evaluateCode(_self, codeString);
    };

    this.readScore = function(scoreString) {

	_readScore(_self, scoreString);
    };

    this.setControlChannel = function(channelName, value) {

	_setControlChannel(_self, channelName, value);
    };

    this.getControlChannel = function(channelName) {

	return _getControlChannel(_self, channelName);
    };

    this.setStringChannel = function(channelName, value) {

	_setStringChannel(_self, channelName, value);
    };

    this.setOutputChannelCallback = function(callback) {

        function csoundCallback(csoundPtr, stringPtr, valuePtr, typePtr) {

            var string = Pointer_stringify(stringPtr);
            var value = getValue(valuePtr, 'float');
            callback(string, value);
        };
        var functionPointer = Runtime.addFunction(csoundCallback);
        _setOutputChannelCallback(_self, functionPointer);
    };

    this.getTable = function(tableNumber) {

	var tableLength = _getTableLength(_self, tableNumber);
	var tablePointer = _getTable(_self, tableNumber);
	var table = new Float32Array(Module.HEAP8.buffer, tablePointer, tableLength);
	return table;
    };

    this.setTable  = function(num, index, val) {
        _setTable(_self, num, index, val);
    }

    this.getScoreTime = function() {
        _getScoreTime(_self);
    }

    var getAudioProcessNode = function() {

	var inputChannelCount = _getInputChannelCount(_self);
	var outputChannelCount = _getOutputChannelCount(_self);
	var audioProcessNode = audioContext.createScriptProcessor(0, inputChannelCount, outputChannelCount);
	bufferSize = audioProcessNode.bufferSize;
	// console.error("bufferSize = " + bufferSize);
	audioProcessNode.inputCount = inputChannelCount;
	audioProcessNode.outputCount = outputChannelCount;
	return audioProcessNode;
    };

    this.start = function() {
	if(that.running == true)  return;
	var ksmps = _getKsmps(_self);
	// console.error("ksmps = " + ksmps);
	var audioProcessNode = getAudioProcessNode();
	var inputChannelCount = audioProcessNode.inputCount;
	var outputChannelCount = audioProcessNode.outputCount;
	var outputPointer = _getOutputBuffer(_self);
	var csoundOutputBuffer = new Float32Array(Module.HEAP8.buffer, outputPointer, ksmps * outputChannelCount);
	var inputPointer = _getInputBuffer(_self);
	var csoundInputBuffer = new Float32Array(Module.HEAP8.buffer, inputPointer, ksmps * inputChannelCount);
	var zerodBFS = _getZerodBFS(_self);
	var offset = ksmps;
	that.running = true;
	var processBuffers = function (e, sample_count, src_offset, dst_offset) {
	    var i, j;
	    var contextOutputBuffer;
	    var contextInputBuffer;
	    if (microphoneNode !== null) {
		for (i = 0; i < inputChannelCount; ++i) {
		    contextInputBuffer = e.inputBuffer.getChannelData(i);
		    for (j = 0; j < sample_count; ++j) {
			csoundInputBuffer[src_offset + j] = contextInputBuffer[(dst_offset + j) * inputChannelCount + i] * zerodBFS;
		    }
		}
	    }
	    for (i = 0; i < outputChannelCount; ++i) {
		contextOutputBuffer = e.outputBuffer.getChannelData(i);
		for (j = 0; j < sample_count; ++j) {
		    contextOutputBuffer[dst_offset + j] = csoundOutputBuffer[(src_offset + j) * outputChannelCount + i] / zerodBFS;
		}
	    }
	};

	if (microphoneNode !== null) {

	    if (inputChannelCount >= microphoneNode.numberOfInputs) {

		microphoneNode.connect(audioProcessNode);
	    }
	    else {

		alert("Insufficient number of Csound inputs: nchnls_i, not starting");
		return;
	    }
	}

	audioProcessNode.connect(audioContext.destination);
	audioProcessNode.onaudioprocess = function(e) {
	    var idx = 0;
	    var sample_count;

	    sample_count = ksmps - offset;
	    //console.error("1: sample_count = " + sample_count);
	    if (sample_count > 0) {
		processBuffers(e, sample_count, offset, 0);
		idx += sample_count;
	    }
		while (idx < bufferSize) {
		    var result = _performKsmps(_self);
		    if (result != 0) {
			compiled = false;
			that.stop();
		    }
		    if (isNaN(csoundOutputBuffer[0])) {
			console.error("NaN! outputPointer = " + outputPointer);
		    }
		    sample_count = Math.min(ksmps, bufferSize - idx);
		    //console.error("2: sample_count = " + sample_count);
		    processBuffers(e, sample_count, 0, idx);
		    idx += sample_count;
		}
		offset = sample_count;
	    //console.error("3: offset = " + offset);
        };

	that.stop = function() {

	    if (microphoneNode !== null) {
		microphoneNode.disconnect();
	    }

	    audioProcessNode.disconnect();
	    audioProcessNode.onaudioprocess = null;
	    that.running = false;
	};
   };

    this.reset = function() {
	_reset(_self);
	compiled = false;
    };

    this.destroy = function() {
        _destroy(_self);
    };

    this.openAudioOut = function() {
        _openAudioOut(_self);
    }

    this.closeAudioOut = function() {
        _closeAudioOut(_self);
    }

    this.play = function() {
        _play(_self);
     }

     this.stop = function() {
        _openAudioOut(_self);
    }
};
<commit_msg>A little API compatibility for WASM.<commit_after>/*
 * C S O U N D
 *
 * L I C E N S E
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 */

var CsoundObj = function() {

    var that = this;
    var _new = cwrap('CsoundObj_new', ['number'], null);
    var _compileCSD = cwrap('CsoundObj_compileCSD', null, ['number', 'string']);
    var _evaluateCode = cwrap('CsoundObj_evaluateCode', ['number'], ['number', 'string']);
    var _readScore = cwrap('CsoundObj_readScore', ['number'], ['number', 'string']);
    var _reset = cwrap('CsoundObj_reset', null, ['number']);
    var _getOutputBuffer = cwrap('CsoundObj_getOutputBuffer', ['number'], ['number']);
    var _getInputBuffer = cwrap('CsoundObj_getInputBuffer', ['number'], ['number']);
    var _getControlChannel = cwrap('CsoundObj_getControlChannel', ['number'], ['number', 'string']);
    var _setControlChannel = cwrap('CsoundObj_setControlChannel', null, ['number', 'string', 'number']);
    var _setStringChannel = cwrap('CsoundObj_setStringChannel', null, ['number', 'string', 'string']);
    var _getKsmps = cwrap('CsoundObj_getKsmps', ['number'], ['number']);
    var _performKsmps = cwrap('CsoundObj_performKsmps', ['number'], ['number']);
    var _render = cwrap('CsoundObj_render', null, ['number']);
    var _getInputChannelCount = cwrap('CsoundObj_getInputChannelCount', ['number'], ['number']);
    var _getOutputChannelCount = cwrap('CsoundObj_getOutputChannelCount', ['number'], ['number']);
    var _getTableLength = cwrap('CsoundObj_getTableLength', ['number'], ['number', 'number']);
    var _getTable = cwrap('CsoundObj_getTable', ['number'], ['number', 'number']);
    var _getZerodBFS = cwrap('CsoundObj_getZerodBFS', ['number'], ['number']);
    var _setMidiCallbacks = cwrap('CsoundObj_setMidiCallbacks', null, ['number']);
    var _pushMidiMessage = cwrap('CsoundObj_pushMidiMessage', null, ['number', 'number', 'number', 'number']);
    var _setOutputChannelCallback = cwrap('CsoundObj_setOutputChannelCallback', null, ['number', 'number']);
    var _compileOrc = cwrap('CsoundObj_compileOrc', 'number', ['number', 'string']);
    var _prepareRT = cwrap('CsoundObj_prepareRT', null, ['number']);
    var _getScoreTime = cwrap('CsoundObj_getScoreTime', null, ['number']);
    var _setTable = cwrap('CsoundObj_setTable', null, ['number', 'number', 'number', 'number']);
    var _openAudioOut = cwrap('CsoundObj_openAudioOut', null, ['number']);
    var _closeAudioOut = cwrap('CsoundObj_closeAudioOut', null, ['number']);
    var _play = cwrap('CsoundObj_play', null, ['number']);
    var _paude = cwrap('CsoundObj_pause', null, ['number']);
    var bufferSize;
    var _self = _new();
    var _destroy = cwrap('CsoundObj_destroy', null, ['number']);
    var running;

    var getAudioContext = function() {

	try {
	    window.AudioContext = window.AudioContext || window.webkitAudioContext;
	    return new AudioContext();
	}
	catch(error) {

	    alert('Web Audio API is not supported in this browser');
	}
    };

    this.setMidiCallbacks = function() {
	_setMidiCallbacks(_self);
    }

    var microphoneNode = null;

    this.disableAudioInput = function (){
	microphoneNode = null;
    }

    this.midiMessage = function(byte1, byte2, byte3) {
        _pushMidiMessage(_self, byte1, byte2, byte3);
    }

    this.enableAudioInput = function(audioInputCallback) {

	window.navigator = window.navigator || {};
	navigator.getUserMedia = navigator.getUserMedia||navigator.webkitGetUserMedia ||navigator.mozGetUserMedia||null;

	if (navigator.getUserMedia === null) {

	    Module['print']("Audio Input not supported in this browser");
	    audioInputCallback(false);
	}
	else{
	    function onSuccess(stream) {

		microphoneNode = audioContext.createMediaStreamSource(stream);
		audioInputCallback(true);
	    };
	    function onFailure(error) {

		microphoneNode = null;
		audioInputCallback(false);
		Module['print']("Could not initialise audio input, error:" +  error);
	    };
	    navigator.getUserMedia({audio:true}, onSuccess, onFailure);
	}

    };

    this.enableMidiInput = function(midiInputCallback) {

	var handleMidiInput = function(event) {

	    _pushMidiMessage(_self, event.data[0], event.data[1], event.data[2]);
	};

	var midiSuccess = function(midiInterface) {

	    var inputs = midiInterface.inputs.values();

	    for (var input = inputs.next(); input && !input.done; input = inputs.next() ){

		input = input.value;
		input.onmidimessage = handleMidiInput;
	    }
	    _setMidiCallbacks(_self);
	    midiInputCallback(true);
	};

	var midiFail = function(error) {

	    Module['print']("MIDI failed to start, error:" + error);
	    midiInputCallback(false);
	};
	if (navigator.requestMIDIAccess) {

	    navigator.requestMIDIAccess().then(midiSuccess, midiFail);
	}
	else {

	    Module['print']("MIDI not supported in this browser");
	    midiInputCallback(false);
	}
    };

    var audioContext = getAudioContext();
    var samplerate = audioContext.sampleRate;
    var compiled = false;

    this.compileCSD = function(filePath) {
        _prepareRT(_self);
	_compileCSD(_self, filePath);
	compiled = true;
    };

    this.compileOrc = function(orcString)
    {
	_prepareRT(_self);
	_compileOrc(_self, orcString);
	compiled = true;

    };

    this.render = function(filePath) {

	_compileCSD(_self, filePath);
	_render(_self);
	compiled = false;
    }

    this.evaluateCode = function(codeString) {

	_evaluateCode(_self, codeString);
    };

    this.readScore = function(scoreString) {

	_readScore(_self, scoreString);
    };

    this.setControlChannel = function(channelName, value) {

	_setControlChannel(_self, channelName, value);
    };

    this.getControlChannel = function(channelName) {

	return _getControlChannel(_self, channelName);
    };

    this.setStringChannel = function(channelName, value) {

	_setStringChannel(_self, channelName, value);
    };

    this.setOutputChannelCallback = function(callback) {

        function csoundCallback(csoundPtr, stringPtr, valuePtr, typePtr) {

            var string = Pointer_stringify(stringPtr);
            var value = getValue(valuePtr, 'float');
            callback(string, value);
        };
        var functionPointer = Runtime.addFunction(csoundCallback);
        _setOutputChannelCallback(_self, functionPointer);
    };

    this.getTable = function(tableNumber) {

	var tableLength = _getTableLength(_self, tableNumber);
	var tablePointer = _getTable(_self, tableNumber);
	var table = new Float32Array(Module.HEAP8.buffer, tablePointer, tableLength);
	return table;
    };

    this.setTable  = function(num, index, val) {
        _setTable(_self, num, index, val);
    }

    this.getScoreTime = function() {
        _getScoreTime(_self);
    }

    var getAudioProcessNode = function() {

	var inputChannelCount = _getInputChannelCount(_self);
	var outputChannelCount = _getOutputChannelCount(_self);
	var audioProcessNode = audioContext.createScriptProcessor(0, inputChannelCount, outputChannelCount);
	bufferSize = audioProcessNode.bufferSize;
	// console.error("bufferSize = " + bufferSize);
	audioProcessNode.inputCount = inputChannelCount;
	audioProcessNode.outputCount = outputChannelCount;
	return audioProcessNode;
    };

    this.start = function() {
	if(that.running == true)  return;
	var ksmps = _getKsmps(_self);
	// console.error("ksmps = " + ksmps);
	var audioProcessNode = getAudioProcessNode();
	var inputChannelCount = audioProcessNode.inputCount;
	var outputChannelCount = audioProcessNode.outputCount;
	var outputPointer = _getOutputBuffer(_self);
	var csoundOutputBuffer = new Float32Array(Module.HEAP8.buffer, outputPointer, ksmps * outputChannelCount);
	var inputPointer = _getInputBuffer(_self);
	var csoundInputBuffer = new Float32Array(Module.HEAP8.buffer, inputPointer, ksmps * inputChannelCount);
	var zerodBFS = _getZerodBFS(_self);
	var offset = ksmps;
	that.running = true;
	var processBuffers = function (e, sample_count, src_offset, dst_offset) {
	    var i, j;
	    var contextOutputBuffer;
	    var contextInputBuffer;
	    if (microphoneNode !== null) {
		for (i = 0; i < inputChannelCount; ++i) {
		    contextInputBuffer = e.inputBuffer.getChannelData(i);
		    for (j = 0; j < sample_count; ++j) {
			csoundInputBuffer[src_offset + j] = contextInputBuffer[(dst_offset + j) * inputChannelCount + i] * zerodBFS;
		    }
		}
	    }
	    for (i = 0; i < outputChannelCount; ++i) {
		contextOutputBuffer = e.outputBuffer.getChannelData(i);
		for (j = 0; j < sample_count; ++j) {
		    contextOutputBuffer[dst_offset + j] = csoundOutputBuffer[(src_offset + j) * outputChannelCount + i] / zerodBFS;
		}
	    }
	};

	if (microphoneNode !== null) {

	    if (inputChannelCount >= microphoneNode.numberOfInputs) {

		microphoneNode.connect(audioProcessNode);
	    }
	    else {

		alert("Insufficient number of Csound inputs: nchnls_i, not starting");
		return;
	    }
	}

	audioProcessNode.connect(audioContext.destination);
	audioProcessNode.onaudioprocess = function(e) {
	    var idx = 0;
	    var sample_count;

	    sample_count = ksmps - offset;
	    //console.error("1: sample_count = " + sample_count);
	    if (sample_count > 0) {
		processBuffers(e, sample_count, offset, 0);
		idx += sample_count;
	    }
		while (idx < bufferSize) {
		    var result = _performKsmps(_self);
		    if (result != 0) {
			compiled = false;
			that.stop();
		    }
		    if (isNaN(csoundOutputBuffer[0])) {
			console.error("NaN! outputPointer = " + outputPointer);
		    }
		    sample_count = Math.min(ksmps, bufferSize - idx);
		    //console.error("2: sample_count = " + sample_count);
		    processBuffers(e, sample_count, 0, idx);
		    idx += sample_count;
		}
		offset = sample_count;
	    //console.error("3: offset = " + offset);
        };

	that.stop = function() {

	    if (microphoneNode !== null) {
		microphoneNode.disconnect();
	    }

	    audioProcessNode.disconnect();
	    audioProcessNode.onaudioprocess = null;
	    that.running = false;
	};
   };

    this.reset = function() {
	_reset(_self);
	compiled = false;
    };

    this.destroy = function() {
        _destroy(_self);
    };

    this.openAudioOut = function() {
        _openAudioOut(_self);
    }

    this.closeAudioOut = function() {
        _closeAudioOut(_self);
    }

    this.play = function() {
        _play(_self);
     }

    /**
     * This is a stub to enable cross-platform compatibility of the core Csound API
     * across WASM, csound.node, CsoundQt, and Csound for Android.
     */
    this.perform = function() {
        console.log("CsoundObj.perform()...");
        return 0;
    }

    this.stop = function() {
        _openAudioOut(_self);
    }
};
<|endoftext|>


<commit_before>/*
==================================================================================================
  Jasy - JavaScript Tooling Framework
  Copyright 2010-2011 Sebastian Werner
==================================================================================================
*/

/**
 * Contains information about images (size, format, clipping, ...) and
 * other assets like CSS files, local data, ...
 */
(function(global)
{
	// TODO: Implement using permutation injection
	// jasy.Env.getValue("assets");
	var assets = global.$$assets;
	if (!assets) {
		console.warn("Asset data is not available!");
	}

	var cache = {};
	var sprites = {};

	/**
	 * Get information about an asset.
	 *
	 * @param id {String} The asset to get the information for
	 * @return {Array} Registered data or null
	 */
	var getData = assets ? function(id)
	{
		var file = cache[id];
		if (file != null) {
			return file;
		}

		var files = assets.files;
		var images = assets.images;

		var lastSlash = id.lastIndexOf("/");
		var dirName = id.substring(0, lastSlash);
		var fileName = id.substring(lastSlash+1);

		var file = (files[dirName] && files[dirName][fileName]) || (images[dirName] && images[dirName][fileName]) || null;
		if (jasy.Env.isSet("debug")) {
			jasy.Test.assertNotNull(file, "Invalid asset identifier: " + id);
		}

		return cache[id] = file;
	} : function(id) {
		return null;
	};

	Module("jasy.Asset",
	{
		/**
		 * Whether the registry has information about the given asset.
		 *
		 * @param id {String} The asset to get the information for
		 * @return {Boolean} true when the asset is known.
		 */
		has : function(id) {
			return cache[id] || getData(id) != null;
		},

		/**
		 * Returns the dimensions of the given image ID
		 */
		getImageSize : function(id)
		{
			var data = cache[id] || getData(id);
			if (data)
			{
				return {
					width: data[1],
					height: data[2]
				};
			}
		},

		/**
		 * Returns sprite details for being used for the given image ID.
		 *
		 * Nothing is returned when the given ID is not available as part of an image sprite.
		 *
		 * @param id {String} Asset identifier
		 * @return {Map}
		 */
		getImageSprite : function(id)
		{
			var result = sprites[id];
			if (!result)
			{
				var data = cache[id] || getData(id);
				if (data.length > 3)
				{
					var lastSlash = id.lastIndexOf("/");
					var dirName = id.substring(0, lastSlash);
					var spriteData = assets.sprites[dirName][data[3]];
					var needsPosX = spriteData[4] == 1;
					var needsPosY = spriteData[5] == 1;

					sprites[id] = result = {
						uri : assets.roots[spriteData[1]] + "/" + dirName + "/" + spriteData[0],
						left : needsPosX ? data[4] : 0,
						top : needsPosY ? needsPosX ? data[5] : data[4] : 0,
						width : spriteData[2],
						height : spriteData[3]
					};
				}
			}

			return result;
		},

		/**
		 * Converts the given asset ID to a full qualified URI
		 *
		 * @param id {String} Asset ID
		 * @return {String} Resulting URI
		 * @throws when the asset ID is unknown
		 */
		toUri : function(id)
		{
			if (id == null) {
				return id;
			}

			var data = cache[id] || getData(id);

			// Differ between images (first case) and files (second case)
			var root = assets.roots[data.join ? data[0] : data];

			// Replace project identifier with root
			var project = id.slice(0, id.indexOf("/"));
			var url = id.replace(project, root);

			return url;
		}
	});
})(this);<commit_msg>Fixed implementation of has(). Refactored some structure and names. Finer grained error handling.<commit_after>/*
==================================================================================================
  Jasy - JavaScript Tooling Framework
  Copyright 2010-2011 Sebastian Werner
==================================================================================================
*/

/**
 * Contains information about images (size, format, clipping, ...) and
 * other assets like CSS files, local data, ...
 */
(function(global)
{
	var entryCache = {};
	var spriteCache = {};

	var getEntry = function(id)
	{
		if (jasy.Env.isSet("debug")) {
			Test.assetString(id, "Invalid asset identifier: " + id);
		}

		var entry = entryCache[id];
		if (entry != null) {
			return entry;
		}

		var lastSlash = id.lastIndexOf("/");
		var dirName = id.substring(0, lastSlash);
		var fileName = id.substring(lastSlash+1);

		var images = assets.images;
		if (images && images[dirName]) {
			var entry = images[dirName][fileName];
		}

		if (!entry)
		{
			var files = assets.files;
			if (files && files[dirName]) {
				var entry = files[dirName][fileName];
			}
		}

		if (entry) {
			return entryCache[id] = entry;
		}
	};

	// TODO: Implement using permutation injection
	// jasy.Env.getValue("assets");
	var assets = global.$$assets;
	if (!assets)
	{
		console.warn("Asset data is not available!");

		// override getter to always return undefined
		getEntry = new Function;
	}

	Module("jasy.Asset",
	{
		/**
		 * Whether the registry has information about the given asset.
		 *
		 * @param id {String} The asset to get the information for
		 * @return {Boolean} true when the asset is known.
		 */
		has : function(id) {
			return entryCache[id] || getEntry(id) != null;
		},

		/**
		 * Returns the dimensions of the given image ID
		 */
		getImageSize : function(id)
		{
			var entry = entryCache[id] || getEntry(id);
			if (jasy.Env.isSet("debug") && (!entry || entry.length < 3)) {
				throw new Error("Unknown image: " + id);
			}

			return {
				width: entry[1],
				height: entry[2]
			};
		},

		/**
		 * Returns sprite details for being used for the given image ID.
		 *
		 * Nothing is returned when the given ID is not available as part of an image sprite.
		 *
		 * @param id {String} Asset identifier
		 * @return {Map}
		 */
		getImageSprite : function(id)
		{
			var result = spriteCache[id];
			if (!result)
			{
				var entry = entryCache[id] || getEntry(id);
				if (jasy.Env.isSet("debug") && (!entry || entry.length < 5)) {
					throw new Error("Unknown image sprite: " + id);
				}

				var lastSlash = id.lastIndexOf("/");
				var dirName = id.substring(0, lastSlash);
				var spriteData = assets.sprites[dirName][entry[3]];
				var needsPosX = spriteData[4] == 1;
				var needsPosY = spriteData[5] == 1;

				spriteCache[id] = result = {
					uri : assets.roots[spriteData[1]] + "/" + dirName + "/" + spriteData[0],
					left : needsPosX ? entry[4] : 0,
					top : needsPosY ? needsPosX ? entry[5] : entry[4] : 0,
					width : spriteData[2],
					height : spriteData[3]
				};
			}

			return result;
		},

		/**
		 * Converts the given asset ID to a full qualified URI
		 *
		 * @param id {String} Asset ID
		 * @return {String} Resulting URI
		 * @throws when the asset ID is unknown
		 */
		toUri : function(id)
		{
			if (id == null) {
				return id;
			}

			var entry = entryCache[id] || getEntry(id);
			if (jasy.Env.isSet("debug") && !entry) {
				throw new Error("Could not figure out URL for asset: " + id);
			}

			// Differ between files (first case) and images (second case)
			var root = assets.roots[typeof entry == "number" ? entry : entry[0]];

			// Merge to full qualified URI
			return root + id.slice(id.indexOf("/"));
		}
	});
})(this);<|endoftext|>


<commit_before>// Client side code for the Problem Builder Dashboard XBlock
// So far, this code is only used to generate a downloadable report.
function ExportBase(runtime, element, initData) {
    "use strict";

    var reportTemplate = initData.reportTemplate;

    var generateDataUriFromImageURL = function(imgURL) {
        // Given the URL to an image, IF the image has already been cached by the browser,
        // returns a data: URI with the contents of the image (image will be converted to PNG)

        // Expand relative urls and urls without an explicit protocol into absolute urls
        var a = document.createElement('a');
        a.href = imgURL;
        imgURL = a.href;

        // If the image is from another domain, just return its URL. We can't
        // create a data URL from cross-domain images:
        // https://html.spec.whatwg.org/multipage/scripting.html#dom-canvas-todataurl
        if (a.origin !== window.location.origin)
            return imgURL;

        var img = new Image();
        img.src = imgURL;
        if (!img.complete)
            return imgURL;

        // Create an in-memory canvas from which we can extract a data URL:
        var canvas = document.createElement("canvas");
        canvas.width = img.naturalWidth;
        canvas.height = img.naturalHeight;
        // Draw the image onto our temporary canvas:
        canvas.getContext('2d').drawImage(img, 0, 0);
        return canvas.toDataURL("image/png");
    };

    var unicodeStringToBase64 = function(str) {
        // Convert string to base64. A bit weird in order to support unicode, per
        // https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/btoa
        return window.btoa(unescape(encodeURIComponent(str)));
    };

    var downloadReport = function(ev) {
        // Download Report:
        // Change the URL to a data: URI before continuing with the click event.
        if ($(this).attr('href').charAt(0) == '#') {
            var $report = $(initData.reportContentSelector, element).clone();
            // Convert all images in $report to data URIs:
            $report.find('image').each(function() {
                var origURL = $(this).attr('xlink:href');
                $(this).attr('xlink:href', generateDataUriFromImageURL(origURL));
            });
            // Take the resulting HTML and put it into the template we have:

            var wrapperHTML = reportTemplate.replace('REPORT_GOES_HERE', $report.html());
            // console.log($.parseHTML(wrapperHTML, document));
            // console.log($.parseHTML(wrapperHTML, document)[9]);
            // console.log(typeof $.parseHTML(wrapperHTML, document)[9]);
            // console.log($report);
            // console.log(typeof $report);
            // console.log($report.context);
            // console.log(typeof $report.context);
            // console.log($.parseHTML($.parseHTML(wrapperHTML, document)[9].innerHTML));
            var doc = new jsPDF();
            var ele = document.createElement('div')
            ele.innerHTML = $.parseHTML(wrapperHTML, document)[9].innerHTML
            console.log(ele);
            console.log(document.body);
            // doc.addHTML(document.body, function() {
            //     doc.save('report.pdf');
            // });

            doc.fromHTML($report.context, 15, 15, {
                'width': 170
            });

            doc.save('report.pdf');

            var dataURI = "data:text/html;base64," + unicodeStringToBase64(wrapperHTML);
            $(this).attr('href', dataURI);
        }
    };

    var $downloadLink = $('.report-download-link', element);
    $downloadLink.on('click', downloadReport);
}

function PBDashboardBlock(runtime, element, initData) {
    new ExportBase(runtime, element, initData);
}

function MentoringTableBlock(runtime, element, initData) {
    // Display an excerpt for long answers, with a "more" link to display the full text

    var $element = $(element),
        $shareButton = $element.find('.mentoring-share-button'),
        $doShareButton = $element.find('.do-share-button'),
        $shareMenu = $element.find('.mentoring-share-with'),
        $displayDropdown = $element.find('.mentoring-display-dropdown'),
        $errorHolder = $element.find('.share-errors'),
        $deleteShareButton = $element.find('.remove-share'),
        $newShareContainer = $($element.find('.new-share-container')[0]),
        $addShareField = $($element.find('.add-share-field')[0]),
        $notification = $($element.find('.share-notification')),
        $closeNotification = $($element.find('.notification-close')),
        tableLoadURL = runtime.handlerUrl(element, 'table_render'),
        deleteShareUrl = runtime.handlerUrl(element, 'remove_share'),
        sharedListLoadUrl = runtime.handlerUrl(element, 'get_shared_list'),
        clearNotificationUrl = runtime.handlerUrl(element, 'clear_notification'),
        shareResultsUrl = runtime.handlerUrl(element, 'share_results');

    function loadTable(data) {
        $element.find('.mentoring-table-target').html(data['content']);
        $('.answer-table', element).shorten({
            moreText: 'more',
            lessText: 'less',
            showChars: '500'
        });
    }

    function errorMessage(event) {
        $errorHolder.text(JSON.parse(event.responseText)['error'])
    }

    function sharedRefresh(data) {
        $element.find('.shared-with-container').html(data['content']);
        $deleteShareButton = $($deleteShareButton.selector);
        $deleteShareButton.on('click', deleteShare);
    }

    function postShareRefresh(data) {
        sharedRefresh(data);
        $element.find(".new-share-container").each(function(index, container) {
            if (index === 0) {
                var $container = $(container);
                $container.find('.add-share-username').val('');
                $container.find('.add-share-field').show();
                return;
            }
            $(container).remove()
        });
        $errorHolder.html('');
    }

    function postShare() {
        $.ajax({
            type: "POST",
            url: sharedListLoadUrl,
            data: JSON.stringify({}),
            success: postShareRefresh,
            error: errorMessage
        });
    }

    function updateShare() {
        var usernames = [];
        $element.find('.add-share-username').each(function(index, username) {
            usernames.push($(username).val())
        });
        $.ajax({
            type: "POST",
            url: shareResultsUrl,
            data: JSON.stringify({'usernames': usernames}),
            success: postShare,
            error: errorMessage
        });
    }

    function menuHider(event) {
        if (!$(event.target).closest($shareMenu).length) {
            // We're clicking outside of the menu, so hide it.
            $shareMenu.hide();
            $(document).off('click.mentoring_share_menu_hide');
        }
    }

    $shareButton.on('click', function (event) {
        if (!$shareMenu.is(':visible')){
            event.stopPropagation();
            $(document).on('click.mentoring_share_menu_hide', menuHider);
            $shareMenu.show();
        }
    });
    $doShareButton.on('click', updateShare);

    function postLoad(data) {
        loadTable(data);
        new ExportBase(runtime, element, initData);
    }

    $.ajax({
        type: "POST",
        url: tableLoadURL,
        data: JSON.stringify({'target_username': $displayDropdown.val()}),
        success: postLoad
    });

    $.ajax({
        type: "POST",
        url: sharedListLoadUrl,
        data: JSON.stringify({}),
        success: sharedRefresh
    });

    $displayDropdown.on('change', function () {
        if ($displayDropdown[0].selectedIndex !== 0) {
            $shareButton.prop('disabled', true);
            $element.find('.report-download-container').hide();
        } else {
            $shareButton.prop('disabled', false);
            $element.find('.report-download-container').show();
        }
        $.ajax({
            type: "POST",
            url: tableLoadURL,
            data: JSON.stringify({'target_username': $displayDropdown.val()}),
            success: loadTable
        })
    });

    function addShare() {
        var container = $newShareContainer.clone();
        container.find('.add-share-username').val('');
        container.insertAfter($element.find('.new-share-container').last());
        container.find('.add-share-field').on('click', addShare);
        var buttons = $element.find('.new-share-container .add-share-field');
        buttons.hide();
        buttons.last().show();
    }

    function deleteShare(event) {
        event.preventDefault();
        $.ajax({
            type: "POST",
            url: deleteShareUrl,
            data: JSON.stringify({'username': $(event.target).parent().prev()[0].innerHTML}),
            success: function () {
                $(event.target).parent().parent().remove();
                $errorHolder.html('');
            },
            error: errorMessage
        });
    }

    $closeNotification.on('click', function () {
        // Don't need server approval to hide it.
        $notification.hide();
        $.ajax({
            type: "POST",
            url: clearNotificationUrl,
            data: JSON.stringify({'usernames': $notification.data('shared')})
        })
    });

    $addShareField.on('click', addShare);
}
<commit_msg>log log log<commit_after>// Client side code for the Problem Builder Dashboard XBlock
// So far, this code is only used to generate a downloadable report.
function ExportBase(runtime, element, initData) {
    "use strict";

    var reportTemplate = initData.reportTemplate;

    var generateDataUriFromImageURL = function(imgURL) {
        // Given the URL to an image, IF the image has already been cached by the browser,
        // returns a data: URI with the contents of the image (image will be converted to PNG)

        // Expand relative urls and urls without an explicit protocol into absolute urls
        var a = document.createElement('a');
        a.href = imgURL;
        imgURL = a.href;

        // If the image is from another domain, just return its URL. We can't
        // create a data URL from cross-domain images:
        // https://html.spec.whatwg.org/multipage/scripting.html#dom-canvas-todataurl
        if (a.origin !== window.location.origin)
            return imgURL;

        var img = new Image();
        img.src = imgURL;
        if (!img.complete)
            return imgURL;

        // Create an in-memory canvas from which we can extract a data URL:
        var canvas = document.createElement("canvas");
        canvas.width = img.naturalWidth;
        canvas.height = img.naturalHeight;
        // Draw the image onto our temporary canvas:
        canvas.getContext('2d').drawImage(img, 0, 0);
        return canvas.toDataURL("image/png");
    };

    var unicodeStringToBase64 = function(str) {
        // Convert string to base64. A bit weird in order to support unicode, per
        // https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/btoa
        return window.btoa(unescape(encodeURIComponent(str)));
    };

    var downloadReport = function(ev) {
        // Download Report:
        // Change the URL to a data: URI before continuing with the click event.
        if ($(this).attr('href').charAt(0) == '#') {
            var $report = $(initData.reportContentSelector, element).clone();
            // Convert all images in $report to data URIs:
            $report.find('image').each(function() {
                var origURL = $(this).attr('xlink:href');
                $(this).attr('xlink:href', generateDataUriFromImageURL(origURL));
            });
            // Take the resulting HTML and put it into the template we have:

            var wrapperHTML = reportTemplate.replace('REPORT_GOES_HERE', $report.html());
            console.log($.parseHTML(wrapperHTML, document).context);
            // console.log($.parseHTML(wrapperHTML, document)[9]);
            // console.log(typeof $.parseHTML(wrapperHTML, document)[9]);
            // console.log($report);
            // console.log(typeof $report);
            // console.log($report.context);
            // console.log(typeof $report.context);
            // console.log($.parseHTML($.parseHTML(wrapperHTML, document)[9].innerHTML));
            var doc = new jsPDF();
            // var ele = document.createElement('div')
            // ele.innerHTML = $.parseHTML(wrapperHTML, document)[9].innerHTML
            // console.log(ele);
            // console.log(document.body);
            // doc.addHTML(document.body, function() {
            //     doc.save('report.pdf');
            // });

            doc.fromHTML($report.context, 15, 15, {
                'width': 170
            });

            doc.save('report.pdf');

            var dataURI = "data:text/html;base64," + unicodeStringToBase64(wrapperHTML);
            $(this).attr('href', dataURI);
        }
    };

    var $downloadLink = $('.report-download-link', element);
    $downloadLink.on('click', downloadReport);
}

function PBDashboardBlock(runtime, element, initData) {
    new ExportBase(runtime, element, initData);
}

function MentoringTableBlock(runtime, element, initData) {
    // Display an excerpt for long answers, with a "more" link to display the full text

    var $element = $(element),
        $shareButton = $element.find('.mentoring-share-button'),
        $doShareButton = $element.find('.do-share-button'),
        $shareMenu = $element.find('.mentoring-share-with'),
        $displayDropdown = $element.find('.mentoring-display-dropdown'),
        $errorHolder = $element.find('.share-errors'),
        $deleteShareButton = $element.find('.remove-share'),
        $newShareContainer = $($element.find('.new-share-container')[0]),
        $addShareField = $($element.find('.add-share-field')[0]),
        $notification = $($element.find('.share-notification')),
        $closeNotification = $($element.find('.notification-close')),
        tableLoadURL = runtime.handlerUrl(element, 'table_render'),
        deleteShareUrl = runtime.handlerUrl(element, 'remove_share'),
        sharedListLoadUrl = runtime.handlerUrl(element, 'get_shared_list'),
        clearNotificationUrl = runtime.handlerUrl(element, 'clear_notification'),
        shareResultsUrl = runtime.handlerUrl(element, 'share_results');

    function loadTable(data) {
        $element.find('.mentoring-table-target').html(data['content']);
        $('.answer-table', element).shorten({
            moreText: 'more',
            lessText: 'less',
            showChars: '500'
        });
    }

    function errorMessage(event) {
        $errorHolder.text(JSON.parse(event.responseText)['error'])
    }

    function sharedRefresh(data) {
        $element.find('.shared-with-container').html(data['content']);
        $deleteShareButton = $($deleteShareButton.selector);
        $deleteShareButton.on('click', deleteShare);
    }

    function postShareRefresh(data) {
        sharedRefresh(data);
        $element.find(".new-share-container").each(function(index, container) {
            if (index === 0) {
                var $container = $(container);
                $container.find('.add-share-username').val('');
                $container.find('.add-share-field').show();
                return;
            }
            $(container).remove()
        });
        $errorHolder.html('');
    }

    function postShare() {
        $.ajax({
            type: "POST",
            url: sharedListLoadUrl,
            data: JSON.stringify({}),
            success: postShareRefresh,
            error: errorMessage
        });
    }

    function updateShare() {
        var usernames = [];
        $element.find('.add-share-username').each(function(index, username) {
            usernames.push($(username).val())
        });
        $.ajax({
            type: "POST",
            url: shareResultsUrl,
            data: JSON.stringify({'usernames': usernames}),
            success: postShare,
            error: errorMessage
        });
    }

    function menuHider(event) {
        if (!$(event.target).closest($shareMenu).length) {
            // We're clicking outside of the menu, so hide it.
            $shareMenu.hide();
            $(document).off('click.mentoring_share_menu_hide');
        }
    }

    $shareButton.on('click', function (event) {
        if (!$shareMenu.is(':visible')){
            event.stopPropagation();
            $(document).on('click.mentoring_share_menu_hide', menuHider);
            $shareMenu.show();
        }
    });
    $doShareButton.on('click', updateShare);

    function postLoad(data) {
        loadTable(data);
        new ExportBase(runtime, element, initData);
    }

    $.ajax({
        type: "POST",
        url: tableLoadURL,
        data: JSON.stringify({'target_username': $displayDropdown.val()}),
        success: postLoad
    });

    $.ajax({
        type: "POST",
        url: sharedListLoadUrl,
        data: JSON.stringify({}),
        success: sharedRefresh
    });

    $displayDropdown.on('change', function () {
        if ($displayDropdown[0].selectedIndex !== 0) {
            $shareButton.prop('disabled', true);
            $element.find('.report-download-container').hide();
        } else {
            $shareButton.prop('disabled', false);
            $element.find('.report-download-container').show();
        }
        $.ajax({
            type: "POST",
            url: tableLoadURL,
            data: JSON.stringify({'target_username': $displayDropdown.val()}),
            success: loadTable
        })
    });

    function addShare() {
        var container = $newShareContainer.clone();
        container.find('.add-share-username').val('');
        container.insertAfter($element.find('.new-share-container').last());
        container.find('.add-share-field').on('click', addShare);
        var buttons = $element.find('.new-share-container .add-share-field');
        buttons.hide();
        buttons.last().show();
    }

    function deleteShare(event) {
        event.preventDefault();
        $.ajax({
            type: "POST",
            url: deleteShareUrl,
            data: JSON.stringify({'username': $(event.target).parent().prev()[0].innerHTML}),
            success: function () {
                $(event.target).parent().parent().remove();
                $errorHolder.html('');
            },
            error: errorMessage
        });
    }

    $closeNotification.on('click', function () {
        // Don't need server approval to hide it.
        $notification.hide();
        $.ajax({
            type: "POST",
            url: clearNotificationUrl,
            data: JSON.stringify({'usernames': $notification.data('shared')})
        })
    });

    $addShareField.on('click', addShare);
}
<|endoftext|>