<commit_before>var _ = require('underscore');
var BaseAnalysisFormModel = require('./base-analysis-form-model');
var template = require('./data-observatory-multiple-measure.tpl');
var templateList = require('./data-observatory-multiple-measure-list.tpl');
var templateItem = require('./data-observatory-multiple-measure-list-item.tpl');
var NestedMeasurement = require('./data-observatory-multiple-nested-measure-model');
var DataObservatoryRegions = require('../../../../../data/data-observatory/regions-collection');
var camshaftReference = require('../../../../../data/camshaft-reference');
var itemRegionListTemplate = require('./data-observatory-multiple-region-list-item.tpl');

var DENOMINATORS_BLACKLIST = ['', 'area'];

module.exports = BaseAnalysisFormModel.extend({
  initialize: function () {
    BaseAnalysisFormModel.prototype.initialize.apply(this, arguments);

    this.nodeDefModel = this._layerDefinitionModel.findAnalysisDefinitionNodeModel(this.get('source'));

    this.regions = new DataObservatoryRegions(null, {
      configModel: this._configModel,
      nodeDefModel: this.nodeDefModel
    });

    this._initBinds();

    this._setSchema = this._setSchema.bind(this);
    // check if the geometry type is available, if not wait until it's finished
    if (this.nodeDefModel.queryGeometryModel.isFetched()) {
      this._fetchRegions();
    } else {
      this.nodeDefModel.queryGeometryModel.once('change:status', this._fetchRegions, this);
    }

    this._setSchema();
  },

  parse: function (attributes) {
    var ATTRIBUTES = ['numerators', 'column_names', 'denominators', 'numerator_timespans', 'geom_ids', 'normalizations'];

    var numerators = attributes.numerators;
    var column_names = attributes.column_names;
    var denominators = attributes.denominators;
    var normalizations = attributes.normalizations;
    var timespans = attributes.numerator_timespans;
    var geom_ids = attributes.geom_ids;

    var measurements = _.reduce(numerators, function (memo, numerator, index) {
      memo.push({
        segment_name: numerator,
        column_name: column_names[index],
        normalize: denominators[index],
        timespan: timespans[index],
        boundaries: geom_ids[index],
        normalization: normalizations[index]
      });
      return memo;
    }, []);

    return _.extend(_.omit(attributes, ATTRIBUTES), {
      measurements: measurements
    });
  },

  getTemplate: function () {
    return template;
  },

  getTemplateData: function () {
    var fields = [];
    var data = {
      fields: ''
    };

    // Don't show measurements until user selects a region
    if (this.get('area')) {
      fields.push('measurements');
    }

    data.fields = fields.join(',');
    return data;
  },

  _formatAttrs: function (formAttrs) {
    var numerators = this._getNumerators();
    var columnNames = this._getColumnNames();
    var normalizers = this._getDenominators();
    var normalization = this._getNormalization();
    var timespans = this._getTimespan();
    var boundaries = this._getBoundaries();

    var attributes = _.extend(
      {},
      _.omit(formAttrs, 'measurements'),
      {
        numerators: numerators,
        column_names: columnNames,
        denominators: normalizers,
        normalizations: normalization,
        numerator_timespans: timespans,
        geom_ids: boundaries
      }
    );

    return _.omit(camshaftReference.parse(attributes), 'persisted');
  },

  validate: function () {
    var source = this.get('source');
    var type = this.get('type');
    var region = this.get('area');
    var numerators = this._getNumerators();
    var columnNames = this._getColumnNames();
    var normalizers = this._getDenominators();
    var normalizations = this._getNormalization();
    var timespans = this._getTimespan();
    var boundaries = this._getBoundaries();

    var errors = _.extend(
      {},
      this._validRegion(region),
      this._validateMatchSegmentsColumnNames(numerators, columnNames),
      this._isCollectionValid(numerators),
      this._isCollectionValid(columnNames),
      this._areUniqueMeasurements(columnNames),
      camshaftReference.validate({
        source: source,
        type: type,
        numerators: numerators,
        column_names: columnNames,
        denominators: normalizers,
        normalizations: normalizations,
        numerator_timespans: timespans,
        geom_ids: boundaries
      }),
      this._formValidationErrors
    );

    if (!_.isEmpty(errors)) {
      return errors;
    }
  },

  // DRY
  _getNumerators: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      return measurement.segment_name;
    });
  },

  _getTimespan: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      return measurement.timespan;
    });
  },

  _getBoundaries: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      return measurement.boundaries;
    });
  },

  _getNormalization: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      return measurement.normalization;
    });
  },

  _getDenominators: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      var normalize = measurement.normalize;
      // We are inserting area option manually, so we need to filter that value for the backend
      normalize = (DENOMINATORS_BLACKLIST.indexOf(normalize) >= 0) ? null : normalize;
      return normalize;
    });
  },

  _getColumnNames: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      return measurement.column_name;
    });
  },

  _validRegion: function (region) {
    if (region == null) {
      return {
        error: true,
        message: _t('analyses.data-observatory-measure.errors.mandatory-region')
      };
    }
  },

  _validateMatchSegmentsColumnNames: function (segments, columnNames) {
    if (segments.length !== 0 && columnNames.length !== 0 && segments.length !== columnNames.length) {
      return {
        error: true,
        message: _t('analyses.data-observatory-measure.errors.column-name-mismatch')
      };
    }
  },

  _isCollectionValid: function (collection) {
    var allFilled = _.every(collection, function (item) {
      return item && item !== '';
    });

    if (!allFilled) {
      return {
        error: true,
        message: _t('analyses.data-observatory-measure.errors.invalid-selection')
      };
    }
  },

  _areUniqueMeasurements: function (columnNames) {
    var uniques = _.unique(columnNames);
    if (!_.isEqual(uniques, columnNames)) {
      return {
        error: true,
        message: _t('analyses.data-observatory-measure.errors.measurement-twice')
      };
    }
  },

  _fetchRegions: function () {
    this.regions.fetch({
      success: this._setSchema,
      error: this._setSchema
    });
  },

  _initBinds: function () {
    this.listenTo(this.regions, 'sync', this._setSchema);
    this.on('change:area', this._setSchema, this);
  },

  _getRegionOptions: function () {
    var regions = this.regions;
    var state = regions.getState();
    if (state === 'error') {
      return _t('editor.layers.analysis-form.data-observatory.region.error');
    } else if (state === 'fetching') {
      return _t('editor.layers.analysis-form.loading');
    } else {
      // remove Global for the moment since it only includes Boundaries
      return regions.filter(function (f) {
        var matches = /^Global/.test(f.get('label'));
        return !matches;
      }).sort();
    }
  },

  /**
   * @override {BaseAnalysisFormModel._setSchema}
   */
  _setSchema: function () {
    var schema = {
      source: this._primarySourceSchemaItem(_t('editor.layers.analysis-form.data-observatory.source.label')),
      area: {
        type: 'Select',
        title: _t('editor.layers.analysis-form.data-observatory.region.label'),
        options: this._getRegionOptions(),
        dialogMode: 'float',
        loading: this.regions.stateModel.get('state') === 'fetching',
        itemListTemplate: itemRegionListTemplate,
        editorAttrs: {
          disabled: this.regions.length === 0
        },
        validators: ['required']
      },
      measurements: {
        type: 'List',
        itemType: 'MeasurementModel',
        model: NestedMeasurement,
        listTemplate: templateList,
        itemTemplate: templateItem,
        title: '',
        editorAttrs: {
          configModel: this._configModel,
          regions: this.regions,
          nodeDefModel: this.nodeDefModel,
          notAddItemByDefault: true
        },
        validators: [ function (value, formValues) {
          var hasError = value.segment_name === undefined;
          if (hasError) {
            return {
              error: true,
              message: _t('analyses.data-observatory-measure.errors.measurement-required')
            };
          }

          return null;
        } ]
      }
    };

    BaseAnalysisFormModel.prototype._setSchema.call(this, schema);
  }

});
<commit_msg>Safer validation.<commit_after>var _ = require('underscore');
var BaseAnalysisFormModel = require('./base-analysis-form-model');
var template = require('./data-observatory-multiple-measure.tpl');
var templateList = require('./data-observatory-multiple-measure-list.tpl');
var templateItem = require('./data-observatory-multiple-measure-list-item.tpl');
var NestedMeasurement = require('./data-observatory-multiple-nested-measure-model');
var DataObservatoryRegions = require('../../../../../data/data-observatory/regions-collection');
var camshaftReference = require('../../../../../data/camshaft-reference');
var itemRegionListTemplate = require('./data-observatory-multiple-region-list-item.tpl');

var DENOMINATORS_BLACKLIST = ['', 'area'];

module.exports = BaseAnalysisFormModel.extend({
  initialize: function () {
    BaseAnalysisFormModel.prototype.initialize.apply(this, arguments);

    this.nodeDefModel = this._layerDefinitionModel.findAnalysisDefinitionNodeModel(this.get('source'));

    this.regions = new DataObservatoryRegions(null, {
      configModel: this._configModel,
      nodeDefModel: this.nodeDefModel
    });

    this._initBinds();

    this._setSchema = this._setSchema.bind(this);
    // check if the geometry type is available, if not wait until it's finished
    if (this.nodeDefModel.queryGeometryModel.isFetched()) {
      this._fetchRegions();
    } else {
      this.nodeDefModel.queryGeometryModel.once('change:status', this._fetchRegions, this);
    }

    this._setSchema();
  },

  parse: function (attributes) {
    var ATTRIBUTES = ['numerators', 'column_names', 'denominators', 'numerator_timespans', 'geom_ids', 'normalizations'];

    var numerators = attributes.numerators;
    var column_names = attributes.column_names;
    var denominators = attributes.denominators;
    var normalizations = attributes.normalizations;
    var timespans = attributes.numerator_timespans;
    var geom_ids = attributes.geom_ids;

    var measurements = _.reduce(numerators, function (memo, numerator, index) {
      memo.push({
        segment_name: numerator,
        column_name: column_names[index],
        normalize: denominators[index],
        timespan: timespans[index],
        boundaries: geom_ids[index],
        normalization: normalizations[index]
      });
      return memo;
    }, []);

    return _.extend(_.omit(attributes, ATTRIBUTES), {
      measurements: measurements
    });
  },

  getTemplate: function () {
    return template;
  },

  getTemplateData: function () {
    var fields = [];
    var data = {
      fields: ''
    };

    // Don't show measurements until user selects a region
    if (this.get('area')) {
      fields.push('measurements');
    }

    data.fields = fields.join(',');
    return data;
  },

  _formatAttrs: function (formAttrs) {
    var numerators = this._getNumerators();
    var columnNames = this._getColumnNames();
    var normalizers = this._getDenominators();
    var normalization = this._getNormalization();
    var timespans = this._getTimespan();
    var boundaries = this._getBoundaries();

    var attributes = _.extend(
      {},
      _.omit(formAttrs, 'measurements'),
      {
        numerators: numerators,
        column_names: columnNames,
        denominators: normalizers,
        normalizations: normalization,
        numerator_timespans: timespans,
        geom_ids: boundaries
      }
    );

    return _.omit(camshaftReference.parse(attributes), 'persisted');
  },

  validate: function () {
    var source = this.get('source');
    var type = this.get('type');
    var region = this.get('area');
    var numerators = this._getNumerators();
    var columnNames = this._getColumnNames();
    var normalizers = this._getDenominators();
    var normalizations = this._getNormalization();
    var timespans = this._getTimespan();
    var boundaries = this._getBoundaries();

    var errors = _.extend(
      {},
      this._validRegion(region),
      this._validateMatchSegmentsColumnNames(numerators, columnNames),
      this._isCollectionValid(numerators),
      this._isCollectionValid(columnNames),
      this._areUniqueMeasurements(columnNames),
      camshaftReference.validate({
        source: source,
        type: type,
        numerators: numerators,
        column_names: columnNames,
        denominators: normalizers,
        normalizations: normalizations,
        numerator_timespans: timespans,
        geom_ids: boundaries
      }),
      this._formValidationErrors
    );

    if (!_.isEmpty(errors)) {
      return errors;
    }
  },

  // DRY
  _getNumerators: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      return measurement.segment_name;
    });
  },

  _getTimespan: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      return measurement.timespan;
    });
  },

  _getBoundaries: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      return measurement.boundaries;
    });
  },

  _getNormalization: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      return measurement.normalization;
    });
  },

  _getDenominators: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      var normalize = measurement.normalize;
      // We are inserting area option manually, so we need to filter that value for the backend
      normalize = (DENOMINATORS_BLACKLIST.indexOf(normalize) >= 0) ? null : normalize;
      return normalize;
    });
  },

  _getColumnNames: function () {
    var measurements = this.get('measurements');
    return _.map(measurements, function (measurement) {
      return measurement.column_name;
    });
  },

  _validRegion: function (region) {
    if (region == null) {
      return {
        error: true,
        message: _t('analyses.data-observatory-measure.errors.mandatory-region')
      };
    }
  },

  _validateMatchSegmentsColumnNames: function (segments, columnNames) {
    if (segments.length !== 0 && columnNames.length !== 0 && segments.length !== columnNames.length) {
      return {
        error: true,
        message: _t('analyses.data-observatory-measure.errors.column-name-mismatch')
      };
    }
  },

  _isCollectionValid: function (collection) {
    var allFilled = _.every(collection, function (item) {
      return item && item !== '';
    });

    if (!allFilled) {
      return {
        error: true,
        message: _t('analyses.data-observatory-measure.errors.invalid-selection')
      };
    }
  },

  _areUniqueMeasurements: function (columnNames) {
    var uniques = _.unique(columnNames);
    if (!_.isEqual(uniques, columnNames)) {
      return {
        error: true,
        message: _t('analyses.data-observatory-measure.errors.measurement-twice')
      };
    }
  },

  _fetchRegions: function () {
    this.regions.fetch({
      success: this._setSchema,
      error: this._setSchema
    });
  },

  _initBinds: function () {
    this.listenTo(this.regions, 'sync', this._setSchema);
    this.on('change:area', this._setSchema, this);
  },

  _getRegionOptions: function () {
    var regions = this.regions;
    var state = regions.getState();
    if (state === 'error') {
      return _t('editor.layers.analysis-form.data-observatory.region.error');
    } else if (state === 'fetching') {
      return _t('editor.layers.analysis-form.loading');
    } else {
      // remove Global for the moment since it only includes Boundaries
      return regions.filter(function (f) {
        var matches = /^Global/.test(f.get('label'));
        return !matches;
      }).sort();
    }
  },

  /**
   * @override {BaseAnalysisFormModel._setSchema}
   */
  _setSchema: function () {
    var schema = {
      source: this._primarySourceSchemaItem(_t('editor.layers.analysis-form.data-observatory.source.label')),
      area: {
        type: 'Select',
        title: _t('editor.layers.analysis-form.data-observatory.region.label'),
        options: this._getRegionOptions(),
        dialogMode: 'float',
        loading: this.regions.stateModel.get('state') === 'fetching',
        itemListTemplate: itemRegionListTemplate,
        editorAttrs: {
          disabled: this.regions.length === 0
        },
        validators: ['required']
      },
      measurements: {
        type: 'List',
        itemType: 'MeasurementModel',
        model: NestedMeasurement,
        listTemplate: templateList,
        itemTemplate: templateItem,
        title: '',
        editorAttrs: {
          configModel: this._configModel,
          regions: this.regions,
          nodeDefModel: this.nodeDefModel,
          notAddItemByDefault: true
        },
        validators: [ function (value, formValues) {
          var hasError = value.segment_name == null || value.segment_name === '';
          if (hasError) {
            return {
              error: true,
              message: _t('analyses.data-observatory-measure.errors.measurement-required')
            };
          }

          return null;
        } ]
      }
    };

    BaseAnalysisFormModel.prototype._setSchema.call(this, schema);
  }

});
<|endoftext|>


<commit_before>/**
 * ActivateAnalyticsCTA component.
 *
 * Site Kit by Google, Copyright 2022 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import useActivateModuleCallback from '../../../../../hooks/useActivateModuleCallback';
import Button from '../../../../../components/Button';
import PreviewGraph from './PreviewGraph';
import VisitorsGraph from '../../../../../../svg/graphics/cta-graph-visitors.svg';
import GoalsGraph from '../../../../../../svg/graphics/cta-graph-goals.svg';

export default function ActivateAnalyticsCTA() {
	const activateModuleCallback = useActivateModuleCallback( 'analytics' );

	if ( ! activateModuleCallback ) return null;

	return (

					{ __(
						'See how many people visit your site from Search and track how you’re achieving your goals:',
						'google-site-kit'
					) }

						{ __( 'install Google Analytics.', 'google-site-kit' ) }

				<Button onClick={ activateModuleCallback }>
					{ __( 'Set up Google Analytics', 'google-site-kit' ) }
				</Button>

					<PreviewGraph
						title={ __(
							'Unique visitors from Search',
							'google-site-kit'
						) }
						GraphSVG={ VisitorsGraph }
					/>
					<PreviewGraph
						title={ __( 'Goals completed', 'google-site-kit' ) }
						GraphSVG={ GoalsGraph }
					/>

	);
}
<commit_msg>Use regular space, not non-breaking.<commit_after>/**
 * ActivateAnalyticsCTA component.
 *
 * Site Kit by Google, Copyright 2022 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import useActivateModuleCallback from '../../../../../hooks/useActivateModuleCallback';
import Button from '../../../../../components/Button';
import PreviewGraph from './PreviewGraph';
import VisitorsGraph from '../../../../../../svg/graphics/cta-graph-visitors.svg';
import GoalsGraph from '../../../../../../svg/graphics/cta-graph-goals.svg';

export default function ActivateAnalyticsCTA() {
	const activateModuleCallback = useActivateModuleCallback( 'analytics' );

	if ( ! activateModuleCallback ) return null;

	return (

					{ __(
						'See how many people visit your site from Search and track how you’re achieving your goals:',
						'google-site-kit'
					) }{ ' ' }

						{ __( 'install Google Analytics.', 'google-site-kit' ) }

				<Button onClick={ activateModuleCallback }>
					{ __( 'Set up Google Analytics', 'google-site-kit' ) }
				</Button>

					<PreviewGraph
						title={ __(
							'Unique visitors from Search',
							'google-site-kit'
						) }
						GraphSVG={ VisitorsGraph }
					/>
					<PreviewGraph
						title={ __( 'Goals completed', 'google-site-kit' ) }
						GraphSVG={ GoalsGraph }
					/>

	);
}
<|endoftext|>


<commit_before>/*jslint indent:8, devel:true, browser:true, vars:true*/
/*global jQuery, $, console*/
// ==UserScript==
// @name        AnchorMe
// @namespace   http://userscripts.org/smux
// @description Set a reading mark in the pages you choose. Never forget where your reading finish last time.
// @include     https://developer.mozilla.org/*
// @include     http://www.2ality.com/2013/06/basic-javascript.html*
// @include     http://www.atareao.es/*
// @include     http://addyosmani.github.io/backbone-fundamentals/*
// @include     https://github.com/Nijikokun/the-zen-approach/blob/master/*
// @version     0.1
// @grant       none
// ==/UserScript==
// Puede que la página ya disponga de jQuery, por lo que no hay que importarlo
// -@-require     http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js
//
/*
 * Haciendo doble click sobre un texto se crea un marcador.
 * Solo se permite un marcador, así que si se vuelve a hacer doble click el primer marcador se elimina.
 * Debe guardarse el marcador en localStorage para añadirlo al cargar la página
 *
 * TODO:
 * - Al pasar el ratón por encima de un elemento "marcable" que aparezca un mensaje o se coloré o algo..
 * - Si no hay marcador en la página hacer que el botón no responda ante hover y click
 */

/*
        The MIT License (MIT)

        Copyright (c) 2013 Samuel González Izquierdo

        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.
*/

'use strict';

//Activa o desactiva el logging
var DEBUG = true;

var log = function (logString) {
        if (DEBUG && console) {
                console.log(logString);
        }
};
log('>>> Greasemonkey\'s working!');

// Objeto de utilidades: Get y Set del marcador de la página
var util = {
        cache: {
                setBookMark: function (key, obj) {
                        log("key:" + key + " \nobj.type:" + obj.type + "\nobj.position: " + obj.position);
                        localStorage.setItem(key, JSON.stringify(obj));
                },
                getBookMark: function (key) {
                        var objStored = localStorage.getItem(key);
                        if (objStored) {
                                objStored = JSON.parse(objStored);
                                log("key:" + key + " \nobj.type:" + objStored.type + "\nobj.position: " + objStored.position);
                                return objStored;
                        }
                        return undefined;
                },
                deleteBookMark: function (key) {
                        localStorage.removeItem(key);
                        log("Marcador eliminado para página: " + key);
                }
        },
        textos: {
                btoIrHayMarcador: "Ir al marcador!",
                btoIrNoHayMarcador: "No hay marcador"
        }
};

//Objeto principal de la aplicación
var App = {

        key: window.location.href.split("#")[0],
        ANCHOR: "smuxAnchor",
        marcador: {
                type: "",
                position: 0
        },

        //Estilos necesarios para el script.
        //Deben prefijarse para evitar repetir nombres de clases que ya pudiesen existir en la página (Me ha pasado!!!!)
        //Mi prefijo será: smx-
        estilos: "" +
        "@font-face{" +
                "font-family: smx-FontAwesome;" +
                "src:url(https://netdna.bootstrapcdn.com/font-awesome/2.0/font//fontawesome-webfont.eot?#iefix) format('eot')," +
                "url(https://netdna.bootstrapcdn.com/font-awesome/2.0/font//fontawesome-webfont.woff) format('woff')," +
                "url(https://netdna.bootstrapcdn.com/font-awesome/2.0/font//fontawesome-webfont.ttf) format('truetype')," +
                "url(https://netdna.bootstrapcdn.com/font-awesome/2.0/font//fontawesome-webfont.svg#FontAwesome) format('svg');" +
                "font-weight:400;" +
                "font-style:normal;" +
        "}" +
        ".smx-info {" +
                "font: 14px/1.5 sans-serif;" +
                "display: inline;" +
                "background: #d04848;" +
                "color: white;" +
                "opacity: 0;" +
                "padding-right: 20px;" +
                "text-align: right;" +
                "box-sizing: border-box;" +
                "position: fixed;" +
                "z-index: 99998;" +
                "top: 10px;" +
                "left: 10px;" +
                "width: 160px;" +
                "box-shadow: #b5b5b5 0 2px 6px 2px;" +
                "border-radius: 5px;" +
                "transition: width 0.3s ease-out;" +
        "}" +
        ".smx-info-activo {" +
                "opacity: 1;" +
        "}" +
        ".smx-contenedor {" +
                "font: 14px/1.5 sans-serif;" +
                "background: black;" +
                "color: white;" +
                "opacity: 0.3;" +
                "text-align: center;" +
                "position: fixed;" +
                "z-index: 99999;" +
                "top: 10px;" +
                "left: 10px;" +
                "width: 160px;" +
                "border-radius: 5px;" +
                "box-shadow: #b5b5b5 0 2px 6px 2px;" +
                "cursor: pointer;" +
        "}" +
        ".smx-contenedor-activo {" +
                "opacity: 1;" +
        "}" +
        ".smx-boton {" +
                "display: inline;" +
        "}" +
        ".smx-boton:hover {" +
                "opacity: 0.6;" +
        "}" +
        ".smx-boton:active {" +
                "opacity: 0.3;" +
        "}" +
        ".smx-eliminar {" +
                "font-family: smx-FontAwesome; " +
                "padding-left: 10px;" +
        "}" +
        ".smx-eliminar::after {" +
                "content: '\\f014';" +
                "font-size: 1em;" +
        "}" +
        ".smx-eliminar:hover::after {" +
                "opacity: 0.6;" +
        "}" +
        ".smx-eliminar:active::after {" +
                "opacity: 0.3;" +
        "}",

        loadScript: function () {
                this.cargarInterfaz();
                this.agregarMarcadorAlmacenado();
                this.bindElements();

        },

        //Carga los elementos de la interfaz y los cachea
        cargarInterfaz: function () {

                //Añado los estilos a la página
                $("head").append("");

                //Añado el botón de Ir al Marcador
                $("body").append("

Ir al marcador!

Marcador añadido
");

                //Cacheo
                this.btoIr = $(".smx-boton");
                this.infoNuevoMarcador = $(".smx-info");
                this.contenedor = $(".smx-contenedor");
                this.eliminar = $(".smx-eliminar");
        },

        // Función ejecutada al iniciar que recoge de localStorage el marcador
        // y añade en el lugar adecuado
        agregarMarcadorAlmacenado: function () {
                var marcadorTemporal = util.cache.getBookMark(this.key),
                        elementos;
                if (marcadorTemporal) {
                        //Colección de los elementos del tipo del elemento marcado
                        elementos = $(marcadorTemporal.type);
                        var that = this;

                        $.each(elementos, function (i) {
                                if (i === marcadorTemporal.position) {
                                        $(this).before("");
                                        //FIXME: Por alguna razón 'break' falla ?¿?¿?
                                        //break;
                                }
                        });

                        this.activarBoton();

                        log("Marcador Temporal Almacenado agregado.");
                } else {
                        //No existe marcador para esta página
                        this.desactivarBoton();
                }

        },

        bindElements: function () {

                //Solo es posible añadir un marcador a los elementos h1, h2, h3, h4, y p.
                $('h1, h2, h3, h4, p').on('dblclick', this.setMarcador.bind(this));
                this.eliminar.on("click", this.eliminarMarcador.bind(this));

                var that = this;
                this.btoIr.on('click', function () {
                        window.location.hash = that.ANCHOR;
                });
        },

        setMarcador: function (event) {

                //Llamada a la función que guarda la información en localStorage
                //Machaca si existe un marcador anterior
                $("a[name='" + this.ANCHOR + "']").remove();

                this.marcador.type = $(event.target)[0].tagName;

                var that = this;

                //Selector con todos los elementos del mismo tipo que el seleccionado
                var elementos = $($(event.target)[0].tagName);
                $.each(elementos, function (i) {
                        if (this === event.target) {
                                that.marcador.position = i;
                        }
                });

                this.key = window.location.href.split("#")[0];

                //Guarda en localStorage el marcador de la página
                util.cache.setBookMark(this.key, this.marcador);

                //Se incluye el marcador en la página para ser usuado en esta sesión
                $(event.target).before("");

                this.activarBoton();

                var that = this;
                //Muestra, mediante animación, que se ha añadido un marcador
                this.infoNuevoMarcador.css('width', '320px')
                        .delay(2000).queue(function () {
                                that.infoNuevoMarcador.css('width', '160px').dequeue();
                        });
                log('Marcador añadido: ' + $(event.target)[0].tagName);
        },

        eliminarMarcador: function () {
                util.cache.deleteBookMark(this.key);
                $("a[name='" + this.ANCHOR + "']").remove();
                this.desactivarBoton();
        },

        desactivarBoton: function () {
                this.infoNuevoMarcador.removeClass("smx-info-activo");
                this.contenedor.removeClass("smx-contenedor-activo").css("cursor", "text");
                this.btoIr.text(util.textos.btoIrNoHayMarcador);
        },

        activarBoton: function () {
                this.infoNuevoMarcador.addClass("smx-info-activo");
                this.contenedor.addClass("smx-contenedor-activo").css("cursor", "pointer");
                this.btoIr.text(util.textos.btoIrHayMarcador);
        }

};

//Cargar jQuery si la página no lo tiene.
var isJQuery = (typeof jQuery === "undefined") ? false : true;

// Si la página no dispone de jQuery hay que incluirlo, por lo que se debe esperar un tiempo
// a que la biblioteca cargue
if (!isJQuery) {
        log(">>No se ha detectado jQuery en la página, por lo que se procede a su carga...");
        var script = document.createElement("script");
        script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js";
        document.head.appendChild(script);

        //NOTE: setTimeout() causes javascript to use the global scope ('this' is 'window')
        setTimeout(App.loadScript.bind(App), 6000);
} else {

        //Si se dispone de jQuery se podrá esperar menos, pero hay que dar tiempo a que la página cargue completamente
        //Las páginas maś complejas se cargan desde varias fuentes, por lo que el "ready" de jQuery no es definitivo.
        log(">>La página ya dispone de jQuery. Se comenzará con el Script en 2 segundos.");
        //NOTE: setTimeout() causes javascript to use the global scope ('this' is 'window')

        setTimeout(App.loadScript.bind(App), 2000);
}
<commit_msg>Resaltado de elementos 'Marcables'<commit_after>/*jslint indent:8, devel:true, browser:true, vars:true*/
/*global jQuery, $, console*/
// ==UserScript==
// @name        AnchorMe
// @namespace   http://userscripts.org/smux
// @description Set a reading mark in the pages you choose. Never forget where your reading finish last time.
// @include     https://developer.mozilla.org/*
// @include     http://www.2ality.com/2013/06/basic-javascript.html*
// @include     http://www.atareao.es/*
// @include     http://addyosmani.github.io/backbone-fundamentals/*
// @include     https://github.com/Nijikokun/the-zen-approach/blob/master/*
// @version     0.1
// @grant       none
// ==/UserScript==
// Puede que la página ya disponga de jQuery, por lo que no hay que importarlo
// -@-require     http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js
//
/*
 * Haciendo doble click sobre un texto se crea un marcador.
 * Solo se permite un marcador, así que si se vuelve a hacer doble click el primer marcador se elimina.
 * Debe guardarse el marcador en localStorage para añadirlo al cargar la página
 *
 * TODO:
 * - Al pasar el ratón por encima de un elemento "marcable" que aparezca un mensaje mejor que colorearse el fondo.
 * - Si no hay marcador en la página hacer que el botón no responda ante hover y click.
 * - ¿Añadir confirmación para borrar el marcador? Dudo.
 */

/*
        The MIT License (MIT)

        Copyright (c) 2013 Samuel González Izquierdo

        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.
*/

'use strict';

//Activa o desactiva el logging
var DEBUG = true;

var log = function (logString) {
        if (DEBUG && console) {
                console.log(logString);
        }
};
log('>>> Greasemonkey\'s working!');

// Objeto de utilidades: Get y Set del marcador de la página
var util = {
        cache: {
                setBookMark: function (key, obj) {
                        log("key:" + key + " \nobj.type:" + obj.type + "\nobj.position: " + obj.position);
                        localStorage.setItem(key, JSON.stringify(obj));
                },
                getBookMark: function (key) {
                        var objStored = localStorage.getItem(key);
                        if (objStored) {
                                objStored = JSON.parse(objStored);
                                log("key:" + key + " \nobj.type:" + objStored.type + "\nobj.position: " + objStored.position);
                                return objStored;
                        }
                        return undefined;
                },
                deleteBookMark: function (key) {
                        localStorage.removeItem(key);
                        log("Marcador eliminado para página: " + key);
                }
        },
        textos: {
                btoIrHayMarcador: "Ir al marcador!",
                btoIrNoHayMarcador: "No hay marcador"
        }
};

//Objeto principal de la aplicación
var App = {

        key: window.location.href.split("#")[0],
        ANCHOR: "smuxAnchor",
        marcador: {
                type: "",
                position: 0
        },

        //Estilos necesarios para el script.
        //Deben prefijarse para evitar repetir nombres de clases que ya pudiesen existir en la página (Me ha pasado!!!!)
        //Mi prefijo será: smx-
        estilos: "" +
        "@font-face{" +
                "font-family: smx-FontAwesome;" +
                "src:url(https://netdna.bootstrapcdn.com/font-awesome/2.0/font//fontawesome-webfont.eot?#iefix) format('eot')," +
                "url(https://netdna.bootstrapcdn.com/font-awesome/2.0/font//fontawesome-webfont.woff) format('woff')," +
                "url(https://netdna.bootstrapcdn.com/font-awesome/2.0/font//fontawesome-webfont.ttf) format('truetype')," +
                "url(https://netdna.bootstrapcdn.com/font-awesome/2.0/font//fontawesome-webfont.svg#FontAwesome) format('svg');" +
                "font-weight:400;" +
                "font-style:normal;" +
        "}" +
        ".smx-info {" +
                "font: 14px/1.5 sans-serif;" +
                "display: inline;" +
                "background: #d04848;" +
                "color: white;" +
                "opacity: 0;" +
                "padding-right: 20px;" +
                "text-align: right;" +
                "box-sizing: border-box;" +
                "position: fixed;" +
                "z-index: 99998;" +
                "top: 10px;" +
                "left: 10px;" +
                "width: 160px;" +
                "box-shadow: #b5b5b5 0 2px 6px 2px;" +
                "border-radius: 5px;" +
                "transition: width 0.3s ease-out;" +
        "}" +
        ".smx-info-activo {" +
                "opacity: 1;" +
        "}" +
        ".smx-contenedor {" +
                "font: 14px/1.5 sans-serif;" +
                "background: black;" +
                "color: white;" +
                "opacity: 0.3;" +
                "text-align: center;" +
                "position: fixed;" +
                "z-index: 99999;" +
                "top: 10px;" +
                "left: 10px;" +
                "width: 160px;" +
                "border-radius: 5px;" +
                "box-shadow: #b5b5b5 0 2px 6px 2px;" +
                "cursor: pointer;" +
        "}" +
        ".smx-contenedor-activo {" +
                "opacity: 1;" +
        "}" +
        ".smx-boton {" +
                "display: inline;" +
        "}" +
        ".smx-boton:hover {" +
                "opacity: 0.6;" +
        "}" +
        ".smx-boton:active {" +
                "opacity: 0.3;" +
        "}" +
        ".smx-eliminar {" +
                "font-family: smx-FontAwesome; " +
                "padding-left: 10px;" +
        "}" +
        ".smx-eliminar::after {" +
                "content: '\\f014';" +
                "font-size: 1em;" +
        "}" +
        ".smx-eliminar:hover::after {" +
                "opacity: 0.6;" +
        "}" +
        ".smx-eliminar:active::after {" +
                "opacity: 0.3;" +
        "}" +
        ".smx-marcable {" +
                "background-color: #f4cece;" +
                "" +
        "}",

        loadScript: function () {
                this.cargarInterfaz();
                this.agregarMarcadorAlmacenado();
                this.bindElements();

        },

        //Carga los elementos de la interfaz y los cachea
        cargarInterfaz: function () {

                //Añado los estilos a la página
                $("head").append("");

                //Añado el botón de Ir al Marcador
                $("body").append("

Ir al marcador!

Marcador añadido
");

                //Cacheo
                this.btoIr = $(".smx-boton");
                this.infoNuevoMarcador = $(".smx-info");
                this.contenedor = $(".smx-contenedor");
                this.eliminar = $(".smx-eliminar");
        },

        // Función ejecutada al iniciar que recoge de localStorage el marcador
        // y añade en el lugar adecuado
        agregarMarcadorAlmacenado: function () {
                var marcadorTemporal = util.cache.getBookMark(this.key),
                        elementos;
                if (marcadorTemporal) {
                        //Colección de los elementos del tipo del elemento marcado
                        elementos = $(marcadorTemporal.type);
                        var that = this;

                        $.each(elementos, function (i) {
                                if (i === marcadorTemporal.position) {
                                        $(this).before("");
                                        //FIXME: Por alguna razón 'break' falla ?¿?¿?
                                        //break;
                                }
                        });

                        this.activarBoton();

                        log("Marcador Temporal Almacenado agregado.");
                } else {
                        //No existe marcador para esta página
                        this.desactivarBoton();
                }

        },

        bindElements: function () {

                //Solo es posible añadir un marcador a los elementos h1, h2, h3, h4, y p.
                $("h1, h2, h3, h4, p").on("dblclick", this.setMarcador.bind(this));
                $("h1, h2, h3, h4, p").on("mouseover", function () {
                        $(this).addClass("smx-marcable");
                });
                $("h1, h2, h3, h4, p").on("mouseout", function () {
                        $(this).removeClass("smx-marcable");
                });
                this.eliminar.on("click", this.eliminarMarcador.bind(this));

                var that = this;
                this.btoIr.on('click', function () {
                        window.location.hash = that.ANCHOR;
                });
        },

        setMarcador: function (event) {

                //Llamada a la función que guarda la información en localStorage
                //Machaca si existe un marcador anterior
                $("a[name='" + this.ANCHOR + "']").remove();

                this.marcador.type = $(event.target)[0].tagName;

                var that = this;

                //Selector con todos los elementos del mismo tipo que el seleccionado
                var elementos = $($(event.target)[0].tagName);
                $.each(elementos, function (i) {
                        if (this === event.target) {
                                that.marcador.position = i;
                        }
                });

                this.key = window.location.href.split("#")[0];

                //Guarda en localStorage el marcador de la página
                util.cache.setBookMark(this.key, this.marcador);

                //Se incluye el marcador en la página para ser usuado en esta sesión
                $(event.target).before("");

                this.activarBoton();

                var that = this;
                //Muestra, mediante animación, que se ha añadido un marcador
                this.infoNuevoMarcador.css('width', '320px')
                        .delay(2000).queue(function () {
                                that.infoNuevoMarcador.css('width', '160px').dequeue();
                        });
                log('Marcador añadido: ' + $(event.target)[0].tagName);
        },

        eliminarMarcador: function () {
                util.cache.deleteBookMark(this.key);
                $("a[name='" + this.ANCHOR + "']").remove();
                this.desactivarBoton();
        },

        desactivarBoton: function () {
                this.infoNuevoMarcador.removeClass("smx-info-activo");
                this.contenedor.removeClass("smx-contenedor-activo").css("cursor", "text");
                this.btoIr.text(util.textos.btoIrNoHayMarcador);
        },

        activarBoton: function () {
                this.infoNuevoMarcador.addClass("smx-info-activo");
                this.contenedor.addClass("smx-contenedor-activo").css("cursor", "pointer");
                this.btoIr.text(util.textos.btoIrHayMarcador);
        }

};

//Cargar jQuery si la página no lo tiene.
var isJQuery = (typeof jQuery === "undefined") ? false : true;

// Si la página no dispone de jQuery hay que incluirlo, por lo que se debe esperar un tiempo
// a que la biblioteca cargue
if (!isJQuery) {
        log(">>No se ha detectado jQuery en la página, por lo que se procede a su carga...");
        var script = document.createElement("script");
        script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js";
        document.head.appendChild(script);

        //NOTE: setTimeout() causes javascript to use the global scope ('this' is 'window')
        setTimeout(App.loadScript.bind(App), 6000);
} else {

        //Si se dispone de jQuery se podrá esperar menos, pero hay que dar tiempo a que la página cargue completamente
        //Las páginas maś complejas se cargan desde varias fuentes, por lo que el "ready" de jQuery no es definitivo.
        log(">>La página ya dispone de jQuery. Se comenzará con el Script en 2 segundos.");
        //NOTE: setTimeout() causes javascript to use the global scope ('this' is 'window')

        setTimeout(App.loadScript.bind(App), 2000);
}
<|endoftext|>


<commit_before>/**
 * Animable.js
 *
 * https://github.com/JWhile/Animable.js
 *
 * version 1.1.0
 */

var anime,stopAnime;

(function(){ // namespace

// class Animation
function Animation(id, from, to, time, update)
{
    this.id = id; // :int

    this.from = from; // :float
    this.diff = to - from; // :float

    this.start = Date.now(); // :long
    this.time = time; // :int

    this.update = update; // :function
}
// function next(long now):boolean
Animation.prototype.next = function(now)
{
    var n = (now - this.start) / this.time;

    if(n >= 1)
    {
        this.update(this.diff + this.from);

        return true;
    }

    this.update(n * this.diff + this.from);

    return false;
};

var lastAnimId = 0; // :int
var animations = []; // :Array<Animation>
var loop = false; // :boolean

// function next():void
var next = function()
{
    loop = (animations.length > 0);

    if(loop)
    {
        newFrame(next);

        var now = Date.now();

        for(var i = 0; i < animations.length; ++i)
        {
            if(animations[i].next(now))
            {
                animations.splice(i, 1);

                --i;
            }
        }
    }
};

// function anime(function update, float from, float to, int time):int
anime = function(update, from, to, time)
{
    animations.push(new Animation(++lastAnimId, from, to, time, update));

    if(!loop)
    {
        newFrame(next);
    }

    return lastAnimId;
};

// function stopAnime(int id):void
stopAnime = function(id)
{
    for(var i = 0; i < animations.length; ++i)
    {
        if(animations[i].id === id)
        {
            animations.splice(i, 1);

            --i;
        }
    }
};

if(typeof Builder === 'function')
{
    // function anime(String property, int to, int time, function callback = null):@Chainable
    Builder.prototype.anime = function(property, to, time, callback)
    {
        this._animations = this._animations || {}; // Map<String, int>

        if(this._animations[property])
        {
            stopAnime(this._animations[property]);
        }

        var self = this;

        var style = Builder.getStyle(this.node, property);
        var unit = (style.match(/em$|px$|%$/i) || [''])[0];

        this._animations[property] = anime(function(value)
        {
            if(value === to)
            {
                delete self._animations[property];

                if(callback != null)
                {
                    callback();
                }
            }

            self.node.style[property] = value + unit;

        }, parseInt(style), to, time);

        return this;
    };

    // function stopAnime(String property = null):void
    Builder.prototype.stopAnime = function(property)
    {
        this._animations = this._animations || {}; // Map<String, int>

        if(typeof property === 'string')
        {
            if(this._animations[property])
            {
                stopAnime(this._animations[property]);

                delete this._animations[property];
            }
        }
        else
        {
            for(var key in this._animations)
            {
                if(this._animations.hasOwnProperty(key))
                {
                    stopAnime(this._animations[key]);
                }
            }

            this._animations = {};
        }
    };
}

})();
<commit_msg>Use Builder::stopAnime() to stop similar animations<commit_after>/**
 * Animable.js
 *
 * https://github.com/JWhile/Animable.js
 *
 * version 1.1.0
 */

var anime,stopAnime;

(function(){ // namespace

// class Animation
function Animation(id, from, to, time, update)
{
    this.id = id; // :int

    this.from = from; // :float
    this.diff = to - from; // :float

    this.start = Date.now(); // :long
    this.time = time; // :int

    this.update = update; // :function
}
// function next(long now):boolean
Animation.prototype.next = function(now)
{
    var n = (now - this.start) / this.time;

    if(n >= 1)
    {
        this.update(this.diff + this.from);

        return true;
    }

    this.update(n * this.diff + this.from);

    return false;
};

var lastAnimId = 0; // :int
var animations = []; // :Array<Animation>
var loop = false; // :boolean

// function next():void
var next = function()
{
    loop = (animations.length > 0);

    if(loop)
    {
        newFrame(next);

        var now = Date.now();

        for(var i = 0; i < animations.length; ++i)
        {
            if(animations[i].next(now))
            {
                animations.splice(i, 1);

                --i;
            }
        }
    }
};

// function anime(function update, float from, float to, int time):int
anime = function(update, from, to, time)
{
    animations.push(new Animation(++lastAnimId, from, to, time, update));

    if(!loop)
    {
        newFrame(next);
    }

    return lastAnimId;
};

// function stopAnime(int id):void
stopAnime = function(id)
{
    for(var i = 0; i < animations.length; ++i)
    {
        if(animations[i].id === id)
        {
            animations.splice(i, 1);

            --i;
        }
    }
};

if(typeof Builder === 'function')
{
    // function anime(String property, int to, int time, function callback = null):@Chainable
    Builder.prototype.anime = function(property, to, time, callback)
    {
        this.stopAnime(''+ property);

        var self = this;

        var style = Builder.getStyle(this.node, property);
        var unit = (style.match(/em$|px$|%$/i) || [''])[0];

        this._animations[property] = anime(function(value)
        {
            if(value === to)
            {
                delete self._animations[property];

                if(callback != null)
                {
                    callback();
                }
            }

            self.node.style[property] = value + unit;

        }, parseInt(style), to, time);

        return this;
    };

    // function stopAnime(String property = null):void
    Builder.prototype.stopAnime = function(property)
    {
        this._animations = this._animations || {}; // Map<String, int>

        if(typeof property === 'string')
        {
            if(this._animations[property])
            {
                stopAnime(this._animations[property]);

                delete this._animations[property];
            }
        }
        else
        {
            for(var key in this._animations)
            {
                if(this._animations.hasOwnProperty(key))
                {
                    stopAnime(this._animations[key]);
                }
            }

            this._animations = {};
        }
    };
}

})();
<|endoftext|>


<commit_before>/* eslint-disable no-underscore-dangle */
'use strict';

// MODULES //

var isNodeDuplexStreamLike = require( '@stdlib/utils/is-node-duplex-stream-like' );

// MAIN //

/**
* Tests if a value is Node transform stream-like.
*
* @param {*} value - value to test
* @returns {boolean} boolean indicating if a value is Node transform stream-like
*
* @examples
* var transformStream = require( '@stdlib/streams/utils/transform' );
*
* var stream = transformStream();
*
* var bool = isNodeTransformStreamLike( stream );
* // returns true
*
* bool = isNodeTransformStreamLike( {} );
* // returns false
*/
function isNodeTransformStreamLike( value ) {
	return (
		// Must be duplex stream-like:
		isNodeDuplexStreamLike( value ) &&

		// Should have transform stream methods:
		typeof value._transform === 'function' &&

		// Should have transform stream state:
		typeof value._transformState === 'object'
	);
} // end FUNCTION isNodeTransformStreamLike()

// EXPORTS //

module.exports = isNodeTransformStreamLike;
<commit_msg>Fix JSDoc example annotation<commit_after>/* eslint-disable no-underscore-dangle */
'use strict';

// MODULES //

var isNodeDuplexStreamLike = require( '@stdlib/utils/is-node-duplex-stream-like' );

// MAIN //

/**
* Tests if a value is Node transform stream-like.
*
* @param {*} value - value to test
* @returns {boolean} boolean indicating if a value is Node transform stream-like
*
* @example
* var transformStream = require( '@stdlib/streams/utils/transform' );
*
* var stream = transformStream();
*
* var bool = isNodeTransformStreamLike( stream );
* // returns true
*
* bool = isNodeTransformStreamLike( {} );
* // returns false
*/
function isNodeTransformStreamLike( value ) {
	return (
		// Must be duplex stream-like:
		isNodeDuplexStreamLike( value ) &&

		// Should have transform stream methods:
		typeof value._transform === 'function' &&

		// Should have transform stream state:
		typeof value._transformState === 'object'
	);
} // end FUNCTION isNodeTransformStreamLike()

// EXPORTS //

module.exports = isNodeTransformStreamLike;
<|endoftext|>


<commit_before>import '/resources/polymer/@polymer/polymer/polymer-legacy.js';
import '/resources/polymer/@polymer/iron-flex-layout/iron-flex-layout.js';
import '/resources/polymer/@polymer/iron-autogrow-textarea/iron-autogrow-textarea.js';

import {html} from '/resources/polymer/@polymer/polymer/polymer-element.js';
import { tearDownEvent } from '/resources/reflection/tg-polymer-utils.js';

import { TgEditor,  createEditorTemplate} from '/resources/editors/tg-editor.js';

const additionalTemplate = html`
    <style>
        :host {
            @apply --layout-vertical;
        }
        iron-autogrow-textarea {
            min-height: -webkit-fit-content;
            min-height: -moz-fit-content;
            min-height: fit-content;
            overflow: hidden;
            --iron-autogrow-textarea: {
                font-weight: 500;
            }
            @apply --layout-flex;
        }
        .upper-case {
            --iron-autogrow-textarea: {
                text-transform: uppercase;
            };
        }
        paper-input-container {
            @apply --layout-vertical;
            flex: 1 0 auto;
        }
        .main-container {
            @apply --layout-flex;
        }
    </style>`;
const customInputTemplate = html`
    <iron-autogrow-textarea
            id="input"
            class="paper-input-input custom-input multiline-text-input"
            max-rows="[[maxRows]]"
            bind-value="{{_editingValue}}"
            max-length="[[maxLength]]"
            on-input="_onInput"
            on-mouseup="_onMouseUp"
            on-mousedown="_onMouseDown"
            on-keydown="_onKeydown"
            readonly$="[[_disabled]]"
            tooltip-text$="[[_getTooltip(_editingValue)]]"
            autocomplete="off"
            selectable-elements-container>
        </iron-autogrow-textarea>`;
const propertyActionTemplate = html`<slot name="property-action"></slot>`;

export class TgMultilineTextEditor extends TgEditor {

    static get template () {
        return createEditorTemplate(additionalTemplate, html``, customInputTemplate, html``, html``, propertyActionTemplate);
    }

    static get properties() {
        return {
            /////////////////////////////////////////////////////////////////////////////////////////////////////////
            ////////////////////////////////////////// EXTERNAL PROPERTIES //////////////////////////////////////////
            /////////////////////////////////////////////////////////////////////////////////////////////////////////
            // These mandatory properties must be specified in attributes, when constructing <tg-*-editor>s.       //
            // No default values are allowed in this case.														   //
            /////////////////////////////////////////////////////////////////////////////////////////////////////////

            /**
             * The maximum number of characters for this text editor
             */
            maxLength: {
                type: Number
            },

            /**
             * The maximum count for textarea rows.
             */
            maxRows: {
                type: Number,
                value: 5
            },

            _onMouseDown: {
                type: Function,
                value: function () {
                    return (function (event) {
                        if (this.shadowRoot.activeElement !== this.decoratedInput()) {
                            this.decoratedInput().textarea.select();
                            this._tearDownEventOnUp = true;
                        }
                    }).bind(this);
                }
            },

            /**
             * OVERRIDDEN FROM TgEditorBehavior: this specific textArea's event is invoked after some key has been pressed.
             *
             * Designated to be bound to child elements.
             */
            _onKeydown: {
                type: Function,
                value: function () {
                    return (function (event) {
                    // need to invoke base function-property? Just do it like this:
                    //   var parentFunction = TgEditorBehaviorImpl.properties._onKeydown.value.call(this);
                    //   parentFunction.call(this, event);
                    //console.log("_onKeydown (for text area):", event);
                        // TODO potentially, commit on CTRL+Enter?
                    }).bind(this);
                }
            }
        };
    }

    constructor () {
        super();
        this._editorKind = "MULTILINE_TEXT";
    }

    ready () {
        super.ready();
        const inputWrapper = this.decorator().$$(".input-wrapper");
        inputWrapper.style.flexGrow = "1";
        const labelAndInputContainer = this.decorator().$.labelAndInputContainer;
        labelAndInputContainer.style.alignSelf = "stretch";
        labelAndInputContainer.style.display = "flex";
        labelAndInputContainer.style.flexDirection = "column";
        labelAndInputContainer.style.overflow = "auto";
        const prefix = this.decorator().$$(".prefix");
        prefix.style.alignSelf = "flex-start";
        const suffix = this.decorator().$$(".suffix");
        suffix.style.alignSelf = "flex-start";
        this.decoratedInput().textarea.addEventListener("change", this._onChange);
    }

    /**
     * Converts the value into string representation (which is used in edititing / comm values).
     */
    convertToString (value) {
        return value === null ? "" : "" + value;
    }

    /**
     * Converts the value from string representation (which is used in edititing / comm values) into concrete type of this editor component (String).
     */
    convertFromString (strValue) {
        return strValue === '' ? null : strValue;
    }
}

customElements.define('tg-multiline-text-editor', TgMultilineTextEditor);<commit_msg>#1344 Changed font weight for multiline text editor.<commit_after>import '/resources/polymer/@polymer/polymer/polymer-legacy.js';
import '/resources/polymer/@polymer/iron-flex-layout/iron-flex-layout.js';
import '/resources/polymer/@polymer/iron-autogrow-textarea/iron-autogrow-textarea.js';

import {html} from '/resources/polymer/@polymer/polymer/polymer-element.js';
import { tearDownEvent } from '/resources/reflection/tg-polymer-utils.js';

import { TgEditor,  createEditorTemplate} from '/resources/editors/tg-editor.js';

const additionalTemplate = html`
    <style>
        :host {
            @apply --layout-vertical;
        }
        iron-autogrow-textarea {
            min-height: -webkit-fit-content;
            min-height: -moz-fit-content;
            min-height: fit-content;
            overflow: hidden;
            --iron-autogrow-textarea: {
                font-weight: 500;
            };
            @apply --layout-flex;
        }
        .upper-case {
            --iron-autogrow-textarea: {
                font-weight: 500;
                text-transform: uppercase;
            };
        }
        paper-input-container {
            @apply --layout-vertical;
            flex: 1 0 auto;
        }
        .main-container {
            @apply --layout-flex;
        }
    </style>`;
const customInputTemplate = html`
    <iron-autogrow-textarea
            id="input"
            class="paper-input-input custom-input multiline-text-input"
            max-rows="[[maxRows]]"
            bind-value="{{_editingValue}}"
            max-length="[[maxLength]]"
            on-input="_onInput"
            on-mouseup="_onMouseUp"
            on-mousedown="_onMouseDown"
            on-keydown="_onKeydown"
            readonly$="[[_disabled]]"
            tooltip-text$="[[_getTooltip(_editingValue)]]"
            autocomplete="off"
            selectable-elements-container>
        </iron-autogrow-textarea>`;
const propertyActionTemplate = html`<slot name="property-action"></slot>`;

export class TgMultilineTextEditor extends TgEditor {

    static get template () {
        return createEditorTemplate(additionalTemplate, html``, customInputTemplate, html``, html``, propertyActionTemplate);
    }

    static get properties() {
        return {
            /////////////////////////////////////////////////////////////////////////////////////////////////////////
            ////////////////////////////////////////// EXTERNAL PROPERTIES //////////////////////////////////////////
            /////////////////////////////////////////////////////////////////////////////////////////////////////////
            // These mandatory properties must be specified in attributes, when constructing <tg-*-editor>s.       //
            // No default values are allowed in this case.														   //
            /////////////////////////////////////////////////////////////////////////////////////////////////////////

            /**
             * The maximum number of characters for this text editor
             */
            maxLength: {
                type: Number
            },

            /**
             * The maximum count for textarea rows.
             */
            maxRows: {
                type: Number,
                value: 5
            },

            _onMouseDown: {
                type: Function,
                value: function () {
                    return (function (event) {
                        if (this.shadowRoot.activeElement !== this.decoratedInput()) {
                            this.decoratedInput().textarea.select();
                            this._tearDownEventOnUp = true;
                        }
                    }).bind(this);
                }
            },

            /**
             * OVERRIDDEN FROM TgEditorBehavior: this specific textArea's event is invoked after some key has been pressed.
             *
             * Designated to be bound to child elements.
             */
            _onKeydown: {
                type: Function,
                value: function () {
                    return (function (event) {
                    // need to invoke base function-property? Just do it like this:
                    //   var parentFunction = TgEditorBehaviorImpl.properties._onKeydown.value.call(this);
                    //   parentFunction.call(this, event);
                    //console.log("_onKeydown (for text area):", event);
                        // TODO potentially, commit on CTRL+Enter?
                    }).bind(this);
                }
            }
        };
    }

    constructor () {
        super();
        this._editorKind = "MULTILINE_TEXT";
    }

    ready () {
        super.ready();
        const inputWrapper = this.decorator().$$(".input-wrapper");
        inputWrapper.style.flexGrow = "1";
        const labelAndInputContainer = this.decorator().$.labelAndInputContainer;
        labelAndInputContainer.style.alignSelf = "stretch";
        labelAndInputContainer.style.display = "flex";
        labelAndInputContainer.style.flexDirection = "column";
        labelAndInputContainer.style.overflow = "auto";
        const prefix = this.decorator().$$(".prefix");
        prefix.style.alignSelf = "flex-start";
        const suffix = this.decorator().$$(".suffix");
        suffix.style.alignSelf = "flex-start";
        this.decoratedInput().textarea.addEventListener("change", this._onChange);
    }

    /**
     * Converts the value into string representation (which is used in edititing / comm values).
     */
    convertToString (value) {
        return value === null ? "" : "" + value;
    }

    /**
     * Converts the value from string representation (which is used in edititing / comm values) into concrete type of this editor component (String).
     */
    convertFromString (strValue) {
        return strValue === '' ? null : strValue;
    }
}

customElements.define('tg-multiline-text-editor', TgMultilineTextEditor);<|endoftext|>


<commit_before>//OXYGEN for firebase by Hideki Yamamoto
/*TODO URGENT!!!!!!
	-Add index for _subcollections
	-Add index only for hashed words
	-Add index only for title words* - use for autocomplete
	-Actually perform  Z=Y-X  during the indexing to remove old entries.
	-CLEAN INDEXES ON DOCUMENT REMOVAL
*/
f$={oxyprefix:'oxy_',
inoe:function(v){if(!v)return true;if(typeof v!='string')return true;if(v.length==0)return true;return false;},
login:function(provider,method){if(!method){method='redirect'}
	if (!firebase.auth().currentUser){var provider;
		if(provider=='twitter'){provider=new firebase.auth.TwitterAuthProvider();}
		else if(provider=='google'){provider=new firebase.auth.GoogleAuthProvider();provider.addScope('https://www.googleapis.com/auth/plus.login');}
		else if(provider=='github'){provider=new firebase.auth.GithubAuthProvider();provider.addScope('repo');}
		else if(provider=='facebook'){provider=new firebase.auth.FacebookAuthProvider();provider.addScope('user_likes');}
		if(method=='redirect'){firebase.auth().signInWithRedirect(provider);}
	}else{console.log('Already logged in');}
},
logout:function(){firebase.auth().signOut();},
initAuth:function(nextToken){if(!nextToken){nextToken=function(r){var i=0;}}firebase.auth().getRedirectResult().then(function(result){
 if(result.credential){nextToken(result);}
	else{nextToken(false);}
		var user = result.user;
  }).catch(function(error) {
        var errorCode = error.code;var errorMessage = error.message;
        var email = error.email;
        var credential = error.credential;
        if (errorCode === 'auth/account-exists-with-different-credential') {
          alert('You have already signed up with a different auth provider for that email.');
          // If you are using multiple auth providers on your app you should handle linking
          // the user's accounts here.
        }else{console.error(error);}
      });},

 /* ----------------------------------------------------------------------------------------------------------- */
	/* ------------------------------------------------------------------- FIREBASE DATABASE NAMESPACE - start --- */
db:{docnamefield:"doctitle",db:function(ref){return firebase.database().ref(ref)},
	start:function(key,event,next){this.db(key.replace('-','/-')).on(event,function(d){var v=d.val();if(v){v.$key=key.split('-')[0]+d.key;next(v);}});},
	end:function(key,event){this.db(key.replace('-','/-')).off(event);},
	/*SUBCOLLECTION start*/
	_add:function(stype,dkey,json){return this.db(stype+'_'+dkey.replace('-','/-')).push(json).key;},
	_set:function(stype,dkey,key,json){delete json.subkey;this.db(stype+'_'+dkey.replace('-','/-')+'/'+key).set(json);},
	_del:function(stype,dkey,key){this.db(stype+'_'+dkey.replace('-','/-')+'/'+key).remove();},
	_get:function(stype,dkey,next){this.db(stype+'_'+dkey.replace('-','/-')).on('child_added',function(data){var v=data.val();v.$subkey=data.key;next(v);});},
	_getone:function(stype,dkey,key,next){this.db(stype+'_'+dkey.replace('-','/-')+'/'+key).once('value',function(data){var v=data.val();v.$subkey=data.key;next(v);});},
    _getall:function(stype,dkey,key,next){},
	/*SUBCOLLECTION end*/
	/*COLLECTIONS start*/
	getone:function(key,next){this.db(key.replace('-','/')).once('value',function(d){var v=d.val();if(v){v.$key=key.split('-')[0]+'-'+d.key;next(v);}});},
 getall:function(col,next){this.db('/'+col).on('child_added',function(d){var v=d.val();v.$key=col+d.key;next(v)})},
	add:function(otype,doc){if(f$.inoe(doc[this.docnamefield])){doc[this.docnamefield]='new '+otype;}var x=this.db(otype).push(doc).key;this._add(f$.oxyprefix+'log',otype+x,{text:"Object Created"});
	var nkey=otype+x;this._doindex(doc,nkey,this.docnamefield);return nkey;},
	del:function(key){var _this=this;var doend=function(){_this.db('/'+f$.oxyprefix+'log_'+key.replace('-','/')).remove();_this.db('/'+f$.oxyprefix+'ver_'+key.replace('-','/')).remove();_this.db('/'+key.replace('-','/')).remove();};
		this.getone(key,function(d){for(var k in d.rels){_this.db(k.replace('-','/')+'/rels/'+key).remove();
			_this._add(f$.oxyprefix+'log',k,{text:'Unlinked from '+d[_this.docnamefield]+'['+key+'] because it\'s getting deleted.'});
		}doend();/*TODO CLEAN WINDEX*/});},
	set:function(doc,log){var k=doc.$key;this._doindex(doc,k,this.docnamefield);var _this=this;delete doc.$key;if(!log){log='Object Modified'}
			this.getone(k,function(d){delete d.$key;var verk=_this._add(f$.oxyprefix+"ver",k,d);
			_this.db(k.replace('-','/')).set(doc);_this._add(f$.oxyprefix+'log',k,{text:log,prev:verk});});},
	/*COLLECTIONS end*//*RELATIONS start*/
	link:function(k1,k2,json){if(!json){json={role:'default'}}if(f$.inoe(k1)||(f$.inoe(k2))){console.log('only valid keys')}else{
		var _this=this;this.getone(k1,function(d){_this.getone(k2,function(dd){
			_this.db(k1.replace('-','/-')+'/rels/'+k2).set(json);_this._add(f$.oxyprefix+'log',k1,{text:'Linked with '+dd[_this.docnamefield]+'['+k2+']'});
			_this.db(k2.replace('-','/-')+'/rels/'+k1).set(json);_this._add(f$.oxyprefix+'log',k2,{text:'Linked with '+d[_this.docnamefield]+'['+k1+']'});
	});});}},
	unlink:function(k1,k2){if(f$.inoe(k1)||(f$.inoe(k2))){console.log('only valid keys')}else{
var _this=this;this.getone(k1,function(d){_this.getone(k2,function(dd){
			_this.db(k1.replace('-','/-')+'/rels/'+k2).remove();_this._add(f$.oxyprefix+'log',k1,{text:'Unlinked from '+dd[_this.docnamefield]+'['+k2+']'});
			_this.db(k2.replace('-','/-')+'/rels/'+k1).remove();_this._add(f$.oxyprefix+'log',k2,{text:'Unlinked from '+d[_this.docnamefield]+'['+k1+']'});
	});});}},
	linkmany:function(k1,kk,json){var _this=this;this.getone(k1,function(dd){for(var k=0;k<kk.length;k++){_this.getone(kk[k],function(ddd){
			_this.db(k1.replace('-','/-')+'/rels/'+kk[k]).set(json);_this._add(f$.oxyprefix+'log',k1,{text:'Linked with '+ddd[_this.docnamefield]+'['+kk[k]+']'});
			_this.db(kk[k].replace('-','/-')+'/rels/'+k1).set(json);_this._add(f$.oxyprefix+'log',kk[k],{text:'Linked with '+dd[_this.docnamefield]+'['+k1+']'});
	});}});},
	unlinkmany:function(k1,kk){var _this=this;this.getone(k1,function(dd){for(var k=0;k<kk.length;k++){this.getone(kk[k],function(ddd){
			_this.db(k1.replace('-','/-')+'/rels/'+kk[k]).remove();_this._add(f$.oxyprefix+'log',k1,{text:'Unlinked with '+ddd[_this.docnamefield]+'['+kk[k]+']'});
			_this.db(kk[k].replace('-','/-')+'/rels/'+k1).remove();_this._add(f$.oxyprefix+'log',kk[k],{text:'Unlinked with '+dd[_this.docnamefield]+'['+k1+']'});
	});}});},/*RELATIONS end*//*WORD INDEX START*/
	find:function(s,next,_collection){var _this=this;var popped=[];
	 s=s.replace(/ |{|}|\||<|>|\\|!|"||$|%|&|\/|\(|\)|=|\?|'|"|^|\*|\+|\[|\]|||@|\.|,|;|:/g,' ');
  s=s.replace(/# /g,' ');s=s.replace(/   /g,' ');s=s.replace(/  /g,' ');s=s.toLowerCase();
		var uninext=function(d){if(!popped[d.$key]){popped[d.$key]=true;next(d);}};var step;
		if(_collection){step=function(d){if(d.key.indexOf(_collection)==0){_this.getone(d.key,uninext);}}}
		else{step=function(d){_this.getone(d.key,uninext);}}
	 var xx=s.split(' ');var xlen=xx.length;for(var x=0;x<xlen;x++){console.log('->');xx[x]=xx[x].trim();if(xx[x].length>0){
		this.db('/'+f$.oxyprefix+'Wndex/'+xx[x]+'/keys').on('child_added',step);}}},

	_doindex:function(o,k,f){var RT=this._relevantText(o);var _this=this;var j;
	 var IDX=this._indexAllandHashedWords(RT);
		/* TODO URGENT : REMOVE OLD INDEX INFO ON REINDEX
		this.db('/'+f$.oxyprefix+'Wndex_inv/'+k).once('value',function(data){var yy=data.val();if(yy){var zz=[];
		//TODO:PERFORM Z=Y-X
		var zlen=zz.length;for(var z=0;z<zlen;z++){_this.db('/'+f$.oxyprefix+'Wndex/'+IDX.all[x].v+'/keys/'+zz[z]).remove();}
		}_this.db('/'+f$.oxyprefix+'Wndex_inv/'+k).set(IDX.all);});

		this.db('/'+f$.oxyprefix+'Hndex_inv/'+k).once('value',function(data){var yy=data.val();if(yy){var zz=[];
		//TODO:PERFORM Z=Y-X
		var zlen=zz.length;for(var z=0;z<zlen;z++){_this.db('/'+f$.oxyprefix+'Wndex/'+IDX.hash[x].v+'/keys/'+zz[z]).remove();}
		}_this.db('/'+f$.oxyprefix+'Hndex_inv/'+k).set(IDX.hash);});
		*/
		for(j in IDX.all){if(IDX.all[j].v!=''){this.db('/'+f$.oxyprefix+'Wndex/'+IDX.all[j].v+'/keys/'+k).set({ct:IDX.all[j].c});}}
		for(j in IDX.hash){if(IDX.hash[j].v!=''){this.db('/'+f$.oxyprefix+'Hndex/'+IDX.hash[j].v+'/keys/'+k).set({ct:IDX.hash[j].c});}}
		if(o[f]){this.db('/'+f$.oxyprefix+'Nndex/'+k).set({n:o[f]});}},
	_relevantText:function(o){var s=JSON.stringify(o);
		s=s.replace(/,"([^"]*)":/g,'');s=s.replace(/{"([^"]*)":/g,'');
		s=s.replace(/","/g,' ');s=s.replace(/""/g,' ');s=s.replace(/"/g,' ');
		s=s.replace(/<.*\/>/g,' ');
		s=s.replace(/<!--.*-->/g,' ');
		s=s.replace(/<.*>(.+)<\/.*>/g,' $1 ');
		s=s.replace(/<link .*>/g,' ');
		s=s.replace(/ |{|}|\||<|>|\\|!|"||$|%|&|\/|\(|\)|=|\?|'|"|^|\*|\+|\[|\]|||@|\.|,|;|:/g,' ');
		s=s.replace(/  /g,' ');s=s.replace(/   /g,' ');s=s.replace(/  /g,' ');
		return s.toLowerCase()},
	_indexAllandHashedWords:function(s){var out={all:{},hash:{}};var c=0;var cw='';var ct=1;var gh=''
		var ss=s.split(' ').sort();var len=ss.length;
		while((c<len)&&(ss[c].trim()=='')){c++}
		while(c<len){gh=ss[c].trim();if(cw!=gh){if(cw!=''){if(cw.length>2){out.all[cw.replace('#','')]={v:cw.replace('#',''),c:ct}};if(cw[0]=='#'){out.hash[cw.replace('#','')]={v:cw.replace('#',''),c:ct};}}cw=gh;ct=1;}else{ct++}c++}
	 out.all[cw]={v:cw,c:ct};return out;
	}
		/*------------------------------------------------------------------------------------------------WORD INDEX END*/
	}
  };

		<commit_msg>update<commit_after>//OXYGEN for firebase by Hideki Yamamoto
/*TODO URGENT!!!!!!
	-Add index for _subcollections
	-Add index only for hashed words
	-Add index only for title words* - use for autocomplete
	-Actually perform  Z=Y-X  during the indexing to remove old entries.
	-CLEAN INDEXES ON DOCUMENT REMOVAL
*/
f$={oxyprefix:'oxy_',
inoe:function(v){if(!v)return true;if(typeof v!='string')return true;if(v.length==0)return true;return false;},
login:function(provider,method){if(!method){method='redirect'}
	if (!firebase.auth().currentUser){var provider;
		if(provider=='twitter'){provider=new firebase.auth.TwitterAuthProvider();}
		else if(provider=='google'){provider=new firebase.auth.GoogleAuthProvider();provider.addScope('https://www.googleapis.com/auth/plus.login');}
		else if(provider=='github'){provider=new firebase.auth.GithubAuthProvider();provider.addScope('repo');}
		else if(provider=='facebook'){provider=new firebase.auth.FacebookAuthProvider();provider.addScope('user_likes');}
		if(method=='redirect'){firebase.auth().signInWithRedirect(provider);}
	}else{console.log('Already logged in');}
},
logout:function(){firebase.auth().signOut();},
initAuth:function(nextToken){if(!nextToken){nextToken=function(r){var i=0;}}firebase.auth().getRedirectResult().then(function(result){
 if(result.credential){nextToken(result);}
	else{nextToken(false);}
		f$.user = result.user;
  }).catch(function(error) {
        var errorCode = error.code;var errorMessage = error.message;
        var email = error.email;
        var credential = error.credential;
        if (errorCode === 'auth/account-exists-with-different-credential') {
          alert('You have already signed up with a different auth provider for that email.');
          // If you are using multiple auth providers on your app you should handle linking
          // the user's accounts here.
        }else{console.error(error);}
      });},

 /* ----------------------------------------------------------------------------------------------------------- */
	/* ------------------------------------------------------------------- FIREBASE DATABASE NAMESPACE - start --- */
db:{docnamefield:"doctitle",db:function(ref){return firebase.database().ref(ref)},
	start:function(key,event,next){this.db(key.replace('-','/-')).on(event,function(d){var v=d.val();if(v){v.$key=key.split('-')[0]+d.key;next(v);}});},
	end:function(key,event){this.db(key.replace('-','/-')).off(event);},
	/*SUBCOLLECTION start*/
	_add:function(stype,dkey,json){return this.db(stype+'_'+dkey.replace('-','/-')).push(json).key;},
	_set:function(stype,dkey,key,json){delete json.subkey;this.db(stype+'_'+dkey.replace('-','/-')+'/'+key).set(json);},
	_del:function(stype,dkey,key){this.db(stype+'_'+dkey.replace('-','/-')+'/'+key).remove();},
	_get:function(stype,dkey,next){this.db(stype+'_'+dkey.replace('-','/-')).on('child_added',function(data){var v=data.val();v.$subkey=data.key;next(v);});},
	_getone:function(stype,dkey,key,next){this.db(stype+'_'+dkey.replace('-','/-')+'/'+key).once('value',function(data){var v=data.val();v.$subkey=data.key;next(v);});},
    _getall:function(stype,dkey,key,next){},
	/*SUBCOLLECTION end*/
	/*COLLECTIONS start*/
	getone:function(key,next){this.db(key.replace('-','/')).once('value',function(d){var v=d.val();if(v){v.$key=key.split('-')[0]+'-'+d.key;next(v);}});},
 getall:function(col,next){this.db('/'+col).on('child_added',function(d){var v=d.val();v.$key=col+d.key;next(v)})},
	add:function(otype,doc){if(f$.inoe(doc[this.docnamefield])){doc[this.docnamefield]='new '+otype;}var x=this.db(otype).push(doc).key;this._add(f$.oxyprefix+'log',otype+x,{text:"Object Created"});
	var nkey=otype+x;this._doindex(doc,nkey,this.docnamefield);return nkey;},
	del:function(key){var _this=this;var doend=function(){_this.db('/'+f$.oxyprefix+'log_'+key.replace('-','/')).remove();_this.db('/'+f$.oxyprefix+'ver_'+key.replace('-','/')).remove();_this.db('/'+key.replace('-','/')).remove();};
		this.getone(key,function(d){for(var k in d.rels){_this.db(k.replace('-','/')+'/rels/'+key).remove();
			_this._add(f$.oxyprefix+'log',k,{text:'Unlinked from '+d[_this.docnamefield]+'['+key+'] because it\'s getting deleted.'});
		}doend();/*TODO CLEAN WINDEX*/});},
	set:function(doc,log){var k=doc.$key;this._doindex(doc,k,this.docnamefield);var _this=this;delete doc.$key;if(!log){log='Object Modified'}
			this.getone(k,function(d){delete d.$key;var verk=_this._add(f$.oxyprefix+"ver",k,d);
			_this.db(k.replace('-','/')).set(doc);_this._add(f$.oxyprefix+'log',k,{text:log,prev:verk});});},
	/*COLLECTIONS end*//*RELATIONS start*/
	link:function(k1,k2,json){if(!json){json={role:'default'}}if(f$.inoe(k1)||(f$.inoe(k2))){console.log('only valid keys')}else{
		var _this=this;this.getone(k1,function(d){_this.getone(k2,function(dd){
			_this.db(k1.replace('-','/-')+'/rels/'+k2).set(json);_this._add(f$.oxyprefix+'log',k1,{text:'Linked with '+dd[_this.docnamefield]+'['+k2+']'});
			_this.db(k2.replace('-','/-')+'/rels/'+k1).set(json);_this._add(f$.oxyprefix+'log',k2,{text:'Linked with '+d[_this.docnamefield]+'['+k1+']'});
	});});}},
	unlink:function(k1,k2){if(f$.inoe(k1)||(f$.inoe(k2))){console.log('only valid keys')}else{
var _this=this;this.getone(k1,function(d){_this.getone(k2,function(dd){
			_this.db(k1.replace('-','/-')+'/rels/'+k2).remove();_this._add(f$.oxyprefix+'log',k1,{text:'Unlinked from '+dd[_this.docnamefield]+'['+k2+']'});
			_this.db(k2.replace('-','/-')+'/rels/'+k1).remove();_this._add(f$.oxyprefix+'log',k2,{text:'Unlinked from '+d[_this.docnamefield]+'['+k1+']'});
	});});}},
	linkmany:function(k1,kk,json){var _this=this;this.getone(k1,function(dd){for(var k=0;k<kk.length;k++){_this.getone(kk[k],function(ddd){
			_this.db(k1.replace('-','/-')+'/rels/'+kk[k]).set(json);_this._add(f$.oxyprefix+'log',k1,{text:'Linked with '+ddd[_this.docnamefield]+'['+kk[k]+']'});
			_this.db(kk[k].replace('-','/-')+'/rels/'+k1).set(json);_this._add(f$.oxyprefix+'log',kk[k],{text:'Linked with '+dd[_this.docnamefield]+'['+k1+']'});
	});}});},
	unlinkmany:function(k1,kk){var _this=this;this.getone(k1,function(dd){for(var k=0;k<kk.length;k++){this.getone(kk[k],function(ddd){
			_this.db(k1.replace('-','/-')+'/rels/'+kk[k]).remove();_this._add(f$.oxyprefix+'log',k1,{text:'Unlinked with '+ddd[_this.docnamefield]+'['+kk[k]+']'});
			_this.db(kk[k].replace('-','/-')+'/rels/'+k1).remove();_this._add(f$.oxyprefix+'log',kk[k],{text:'Unlinked with '+dd[_this.docnamefield]+'['+k1+']'});
	});}});},/*RELATIONS end*//*WORD INDEX START*/
	find:function(s,next,_collection){var _this=this;var popped=[];
	 s=s.replace(/ |{|}|\||<|>|\\|!|"||$|%|&|\/|\(|\)|=|\?|'|"|^|\*|\+|\[|\]|||@|\.|,|;|:/g,' ');
  s=s.replace(/# /g,' ');s=s.replace(/   /g,' ');s=s.replace(/  /g,' ');s=s.toLowerCase();
		var uninext=function(d){if(!popped[d.$key]){popped[d.$key]=true;next(d);}};var step;
		if(_collection){step=function(d){if(d.key.indexOf(_collection)==0){_this.getone(d.key,uninext);}}}
		else{step=function(d){_this.getone(d.key,uninext);}}
	 var xx=s.split(' ');var xlen=xx.length;for(var x=0;x<xlen;x++){console.log('->');xx[x]=xx[x].trim();if(xx[x].length>0){
		this.db('/'+f$.oxyprefix+'Wndex/'+xx[x]+'/keys').on('child_added',step);}}},

	_doindex:function(o,k,f){var RT=this._relevantText(o);var _this=this;var j;
	 var IDX=this._indexAllandHashedWords(RT);
		/* TODO URGENT : REMOVE OLD INDEX INFO ON REINDEX
		this.db('/'+f$.oxyprefix+'Wndex_inv/'+k).once('value',function(data){var yy=data.val();if(yy){var zz=[];
		//TODO:PERFORM Z=Y-X
		var zlen=zz.length;for(var z=0;z<zlen;z++){_this.db('/'+f$.oxyprefix+'Wndex/'+IDX.all[x].v+'/keys/'+zz[z]).remove();}
		}_this.db('/'+f$.oxyprefix+'Wndex_inv/'+k).set(IDX.all);});

		this.db('/'+f$.oxyprefix+'Hndex_inv/'+k).once('value',function(data){var yy=data.val();if(yy){var zz=[];
		//TODO:PERFORM Z=Y-X
		var zlen=zz.length;for(var z=0;z<zlen;z++){_this.db('/'+f$.oxyprefix+'Wndex/'+IDX.hash[x].v+'/keys/'+zz[z]).remove();}
		}_this.db('/'+f$.oxyprefix+'Hndex_inv/'+k).set(IDX.hash);});
		*/
		for(j in IDX.all){if(IDX.all[j].v!=''){this.db('/'+f$.oxyprefix+'Wndex/'+IDX.all[j].v+'/keys/'+k).set({ct:IDX.all[j].c});}}
		for(j in IDX.hash){if(IDX.hash[j].v!=''){this.db('/'+f$.oxyprefix+'Hndex/'+IDX.hash[j].v+'/keys/'+k).set({ct:IDX.hash[j].c});}}
		if(o[f]){this.db('/'+f$.oxyprefix+'Nndex/'+k).set({n:o[f]});}},
	_relevantText:function(o){var s=JSON.stringify(o);
		s=s.replace(/,"([^"]*)":/g,'');s=s.replace(/{"([^"]*)":/g,'');
		s=s.replace(/","/g,' ');s=s.replace(/""/g,' ');s=s.replace(/"/g,' ');
		s=s.replace(/<.*\/>/g,' ');
		s=s.replace(/<!--.*-->/g,' ');
		s=s.replace(/<.*>(.+)<\/.*>/g,' $1 ');
		s=s.replace(/<link .*>/g,' ');
		s=s.replace(/ |{|}|\||<|>|\\|!|"||$|%|&|\/|\(|\)|=|\?|'|"|^|\*|\+|\[|\]|||@|\.|,|;|:/g,' ');
		s=s.replace(/  /g,' ');s=s.replace(/   /g,' ');s=s.replace(/  /g,' ');
		return s.toLowerCase()},
	_indexAllandHashedWords:function(s){var out={all:{},hash:{}};var c=0;var cw='';var ct=1;var gh=''
		var ss=s.split(' ').sort();var len=ss.length;
		while((c<len)&&(ss[c].trim()=='')){c++}
		while(c<len){gh=ss[c].trim();if(cw!=gh){if(cw!=''){if(cw.length>2){out.all[cw.replace('#','')]={v:cw.replace('#',''),c:ct}};if(cw[0]=='#'){out.hash[cw.replace('#','')]={v:cw.replace('#',''),c:ct};}}cw=gh;ct=1;}else{ct++}c++}
	 out.all[cw]={v:cw,c:ct};return out;
	}
		/*------------------------------------------------------------------------------------------------WORD INDEX END*/
	}
  };

		<|endoftext|>