<commit_before>/**
 * @package info.ajaxplorer.plugins
 *
 * Copyright 2007-2009 Charles du Jeu
 * This file is part of AjaXplorer.
 * The latest code can be found at http://www.ajaxplorer.info/
 *
 * This program is published under the LGPL Gnu Lesser General Public License.
 * You should have received a copy of the license along with AjaXplorer.
 *
 * The main conditions are as follow :
 * You must conspicuously and appropriately publish on each copy distributed
 * an appropriate copyright notice and disclaimer of warranty and keep intact
 * all the notices that refer to this License and to the absence of any warranty;
 * and give any other recipients of the Program a copy of the GNU Lesser General
 * Public License along with the Program.
 *
 * If you modify your copy or copies of the library or any portion of it, you may
 * distribute the resulting library provided you do so under the GNU Lesser
 * General Public License. However, programs that link to the library may be
 * licensed under terms of your choice, so long as the library itself can be changed.
 * Any translation of the GNU Lesser General Public License must be accompanied by the
 * GNU Lesser General Public License.
 *
 * If you copy or distribute the program, you must accompany it with the complete
 * corresponding machine-readable source code or with a written offer, valid for at
 * least three years, to furnish the complete corresponding machine-readable source code.
 *
 * Any of the above conditions can be waived if you get permission from the copyright holder.
 * AjaXplorer 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.
 *
 * Description : The "online edition" manager, encapsulate the CodePress highlighter for some extensions.
 */
Class.create("AjxpCkEditor", TextEditor, {

	initialize: function($super, oFormObject)
	{
		$super(oFormObject);
		this.editorConfig = {
			resize_enabled:false,
			toolbar : "Ajxp",
			filebrowserBrowseUrl : 'index.php?external_selector_type=ckeditor',
			// IF YOU KNOW THE RELATIVE PATH OF THE IMAGES (BETWEEN REPOSITORY ROOT AND REAL FILE)
			// YOU CAN PASS IT WITH THE relative_path PARAMETER. FOR EXAMPLE :
			//filebrowserBrowseUrl : 'index.php?external_selector_type=ckeditor&relative_path=files',
			filebrowserImageBrowseUrl : 'index.php?external_selector_type=ckeditor',
			filebrowserFlashBrowseUrl : 'index.php?external_selector_type=ckeditor',
			language : ajaxplorer.currentLanguage,
			fullPage : true,
			toolbar_Ajxp : [
				['Source','Preview','Templates'],
			    ['Undo','Redo','-', 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Print', 'SpellChecker', 'Scayt'],
			    ['Find','Replace','-','SelectAll','RemoveFormat'],
			    ['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'],
			    '/',
			    ['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
			    ['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
			    ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
			    ['Link','Unlink','Anchor'],
			    ['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],
			    '/',
			    ['Styles','Format','Font','FontSize'],
			    ['TextColor','BGColor'],
			    ['Maximize', 'ShowBlocks','-','About']
			]

		};
	},

	open : function($super, userSelection){
		this.userSelection = userSelection;
		var fileName = userSelection.getUniqueFileName();
		var textarea;
		this.textareaContainer = new Element('div');
		this.textarea = new Element('textarea');
		this.textarea.name =  this.textarea.id = 'content';
		this.contentMainContainer = this.textareaContainer;
		this.textarea.setStyle({width:'100%'});
		this.textarea.setAttribute('wrap', 'off');
		this.element.insert(this.textareaContainer);
		this.textareaContainer.appendChild(this.textarea);
		fitHeightToBottom(this.textareaContainer, $(modal.elementName));
		this.reloadEditor('content');
		this.element.observe("editor:close", function(){
			CKEDITOR.instances.content.destroy();
		});
		this.element.observe("editor:resize", function(event){
			this.resizeEditor();
		}.bind(this));
		var destroy = function(){
			if(CKEDITOR.instances.content){
				this.textarea.value = CKEDITOR.instances.content.getData();
				CKEDITOR.instances.content.destroy();
			}
		};
		var reInit  = function(){
			CKEDITOR.replace('content', this.editorConfig);
			this.resizeEditor();
		}
		this.element.observe("editor:enterFS", destroy.bind(this));
		this.element.observe("editor:enterFSend", reInit.bind(this));
		this.element.observe("editor:exitFS", destroy.bind(this));
		this.element.observe("editor:exitFSend", reInit.bind(this));
		this.element.observe("editor:modified", function(e){
			if(!this.isModified){
				this.launchModifiedObserver();
			}
		}.bind(this) );
		// LOAD FILE NOW
		window.setTimeout(this.resizeEditor.bind(this), 700);
		this.loadFileContent(fileName);
		return;

	},

	launchModifiedObserver : function(){
		// OBSERVE CHANGES
		this.observerInterval = window.setInterval(function(){
			if(this.isModified || !CKEDITOR.instances.content) return;
			var currentData =  CKEDITOR.instances.content.getData();
			if(!this.prevData) {
				this.prevData = currentData;
				return;
			}
			if(this.prevData != currentData){
				this.setModified(true);
				window.clearInterval(this.observerInterval);
			}
			this.prevData = currentData;
		}.bind(this), 500);
		this.element.observe("editor:close", function(){
			window.clearInterval(this.observerInterval);
		});
	},

	reloadEditor : function(instanceId){
		if(!instanceId) instanceId = "code";
		if(CKEDITOR.instances[instanceId]){
			this.textarea.value = CKEDITOR.instances[instanceId].getData();
			CKEDITOR.instances[instanceId].destroy();
		}
		CKEDITOR.replace(instanceId, this.editorConfig);
	},

	resizeEditor : function(){
		var width = this.contentMainContainer.getWidth()-(Prototype.Browser.IE?0:12);
		var height = this.contentMainContainer.getHeight();
		CKEDITOR.instances.content.resize(width,height);
	},

	saveFile : function(){
		var connexion = this.prepareSaveConnexion();
		var value = CKEDITOR.instances.content.getData();
		this.textarea.value = value;
		connexion.addParameter('content', value);
		connexion.sendAsync();
	},

	parseTxt : function(transport){
		this.textarea.value = transport.responseText;
		CKEDITOR.instances.content.setData(transport.responseText);
		this.removeOnLoad(this.textareaContainer);
		this.setModified(false);
	}

});<commit_msg>Bind to the proper CKEditor events instead of listening for modifications in a loop...<commit_after>/**
 * @package info.ajaxplorer.plugins
 *
 * Copyright 2007-2009 Charles du Jeu
 * This file is part of AjaXplorer.
 * The latest code can be found at http://www.ajaxplorer.info/
 *
 * This program is published under the LGPL Gnu Lesser General Public License.
 * You should have received a copy of the license along with AjaXplorer.
 *
 * The main conditions are as follow :
 * You must conspicuously and appropriately publish on each copy distributed
 * an appropriate copyright notice and disclaimer of warranty and keep intact
 * all the notices that refer to this License and to the absence of any warranty;
 * and give any other recipients of the Program a copy of the GNU Lesser General
 * Public License along with the Program.
 *
 * If you modify your copy or copies of the library or any portion of it, you may
 * distribute the resulting library provided you do so under the GNU Lesser
 * General Public License. However, programs that link to the library may be
 * licensed under terms of your choice, so long as the library itself can be changed.
 * Any translation of the GNU Lesser General Public License must be accompanied by the
 * GNU Lesser General Public License.
 *
 * If you copy or distribute the program, you must accompany it with the complete
 * corresponding machine-readable source code or with a written offer, valid for at
 * least three years, to furnish the complete corresponding machine-readable source code.
 *
 * Any of the above conditions can be waived if you get permission from the copyright holder.
 * AjaXplorer 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.
 *
 * Description : The "online edition" manager, encapsulate the CodePress highlighter for some extensions.
 */
Class.create("AjxpCkEditor", TextEditor, {

	initialize: function($super, oFormObject)
	{
		$super(oFormObject);
		this.editorConfig = {
			resize_enabled:false,
			toolbar : "Ajxp",
			filebrowserBrowseUrl : 'index.php?external_selector_type=ckeditor',
			// IF YOU KNOW THE RELATIVE PATH OF THE IMAGES (BETWEEN REPOSITORY ROOT AND REAL FILE)
			// YOU CAN PASS IT WITH THE relative_path PARAMETER. FOR EXAMPLE :
			//filebrowserBrowseUrl : 'index.php?external_selector_type=ckeditor&relative_path=files',
			filebrowserImageBrowseUrl : 'index.php?external_selector_type=ckeditor',
			filebrowserFlashBrowseUrl : 'index.php?external_selector_type=ckeditor',
			language : ajaxplorer.currentLanguage,
			fullPage : true,
			toolbar_Ajxp : [
				['Source','Preview','Templates'],
			    ['Undo','Redo','-', 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Print', 'SpellChecker', 'Scayt'],
			    ['Find','Replace','-','SelectAll','RemoveFormat'],
			    ['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'],
			    '/',
			    ['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
			    ['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
			    ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
			    ['Link','Unlink','Anchor'],
			    ['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],
			    '/',
			    ['Styles','Format','Font','FontSize'],
			    ['TextColor','BGColor'],
			    ['Maximize', 'ShowBlocks','-','About']
			]

		};
	},

	open : function($super, userSelection){
		this.userSelection = userSelection;
		var fileName = userSelection.getUniqueFileName();
		var textarea;
		this.textareaContainer = new Element('div');
		this.textarea = new Element('textarea');
		this.textarea.name =  this.textarea.id = 'content';
		this.contentMainContainer = this.textareaContainer;
		this.textarea.setStyle({width:'100%'});
		this.textarea.setAttribute('wrap', 'off');
		this.element.insert(this.textareaContainer);
		this.textareaContainer.appendChild(this.textarea);
		fitHeightToBottom(this.textareaContainer, $(modal.elementName));
		this.reloadEditor('content');
		this.element.observe("editor:close", function(){
			CKEDITOR.instances.content.destroy();
		});
		this.element.observe("editor:resize", function(event){
			this.resizeEditor();
		}.bind(this));
		var destroy = function(){
			if(CKEDITOR.instances.content){
				this.textarea.value = CKEDITOR.instances.content.getData();
				CKEDITOR.instances.content.destroy();
			}
		};
		var reInit  = function(){
			CKEDITOR.replace('content', this.editorConfig);
			this.resizeEditor();
			this.bindCkEditorEvents();
		}
		this.element.observe("editor:enterFS", destroy.bind(this));
		this.element.observe("editor:enterFSend", reInit.bind(this));
		this.element.observe("editor:exitFS", destroy.bind(this));
		this.element.observe("editor:exitFSend", reInit.bind(this));
		// LOAD FILE NOW
		window.setTimeout(this.resizeEditor.bind(this), 400);
		this.loadFileContent(fileName);
		this.bindCkEditorEvents();
		return;

	},

	bindCkEditorEvents : function(){
		if(this.isModified) return;// useless

		window.setTimeout(function(){
			var editor = CKEDITOR.instances.content;
			var setModified = function(){this.setModified(true)}.bind(this);
				// We'll save snapshots before and after executing a command.
	 		editor.on( 'afterCommandExec', setModified );
	 			// Save snapshots before doing custom changes.
	 		editor.on( 'saveSnapshot', setModified );
	 		// Registering keydown on every document recreation.(#3844)
	 		editor.on( 'contentDom', function(e)
	 		{
	 			e.editor.document.on( 'keydown', function( event ){
	 			// Do not capture CTRL hotkeys.
	 			if ( !event.data.$.ctrlKey && !event.data.$.metaKey )
	 					setModified();
	 			}
	 			);
	 		});
		}.bind(this), 0);
	},

	reloadEditor : function(instanceId){
		if(!instanceId) instanceId = "code";
		if(CKEDITOR.instances[instanceId]){
			this.textarea.value = CKEDITOR.instances[instanceId].getData();
			CKEDITOR.instances[instanceId].destroy();
		}
		CKEDITOR.replace(instanceId, this.editorConfig);
	},

	resizeEditor : function(){
		var width = this.contentMainContainer.getWidth()-(Prototype.Browser.IE?0:12);
		var height = this.contentMainContainer.getHeight();
		CKEDITOR.instances.content.resize(width,height);
	},

	saveFile : function(){
		var connexion = this.prepareSaveConnexion();
		var value = CKEDITOR.instances.content.getData();
		this.textarea.value = value;
		connexion.addParameter('content', value);
		connexion.sendAsync();
	},

	parseTxt : function(transport){
		this.textarea.value = transport.responseText;
		CKEDITOR.instances.content.setData(transport.responseText);
		this.removeOnLoad(this.textareaContainer);
		this.setModified(false);
	}

});<|endoftext|>


<commit_before>import React, { Component } from 'react'

const AboutThumbnailItem = ({contributor}) => {
  var {username, imgUrl, githubUrl} = contributor

  return (

{username}

            Github Profile

  )
}

export default AboutThumbnailItem
<commit_msg>Refactor: simplify about thumbnails<commit_after>import React, { Component } from 'react'

const AboutThumbnailItem = ({ contributor }) => {
  var { username, imgUrl, githubUrl } = contributor

  return (

{username}

  )
}

export default AboutThumbnailItem
<|endoftext|>


<commit_before>/**
 * conjoon
 * (c) 2002-2012 siteartwork.de/conjoon.org
 * licensing@conjoon.org
 *
 * $Author$
 * $Id$
 * $Date$
 * $Revision$
 * $LastChangedDate$
 * $LastChangedBy$
 * $URL$
 */

Ext.namespace('com.conjoon.groupware.feeds');

/**
 * @class com.conjoon.groupware.feeds.FeedViewBaton
 * @singleton
 *
 * Manages the opening of feed items as new tabs. Will not open a new tab if the
 * tab with the passed feed item id does already exist.
 * The class will also load the feed cpntents from the server if, and only if,
 * the fully configured feed item record was not submitted.
 *
 */
com.conjoon.groupware.feeds.FeedViewBaton = function() {

    var openedFeeds = {};

    var AccountStore = com.conjoon.groupware.feeds.AccountStore.getInstance();

    var LinkInterceptor = com.conjoon.groupware.util.LinkInterceptor;

    var contentPanel = null;

    var idPrefix = 'com.conjoon.groupware.feeds.FeedItemView_';

    var toolbar = null;

    var activeRecord = null;

    var _requestIds = {};

    var registerToolbar = function()
    {
        if (toolbar == null) {
            var tbarManager = com.conjoon.groupware.workbench.ToolbarController;

            var linkButton = new Ext.Toolbar.Button({
                id       : 'com.conjoon.groupware.feeds.FeedView.toolbar.LinkButton',
                cls      : 'x-btn-text-icon',
                iconCls  : 'com-conjoon-groupware-feeds-FeedViewBaton-toolbar-visitEntryButton-icon',
                text     : ' '+com.conjoon.Gettext.gettext("Visit entry"),
                handler  : function(){visitFeedEntry();}
            });

            toolbar = new Ext.Toolbar([
                linkButton
            ]);

            tbarManager.register('com.conjoon.groupware.feeds.FeedView.toolbar', toolbar);
        }
    };

    var visitFeedEntry = function(type)
    {
        var tab = contentPanel.getActiveTab();

        var id = tab.id;

        if (!openedFeeds[id]) {
            return;
        }

        (function() {
            this.open(LinkInterceptor.getRedirectLink(openedFeeds[id]['link']));
        }).defer(1, window);
    };

    /**
     * Loads the feed's contents for the specified id from the server.
     *
     * @param {Number} id
     * @param {Number} groupwareFeedsAccountsId
     * @param {String} panelId
     *
     */
    var loadFeedContents = function(id, groupwareFeedsAccountsId, panelId)
    {
        if (_requestIds[panelId]) {
            return;
        }

        _requestIds[panelId] = Ext.Ajax.request({
            url    : './groupware/feeds.item/get.feed.content/format/json',
            params : {
                id                       : id,
                groupwareFeedsAccountsId : groupwareFeedsAccountsId
            },
            panelId : panelId,
            success : onFeedLoadSuccess,
            failure : onFeedLoadFailure
        });
    };

    /**
     * Callback for the successfull loading of a feed's content.
     *
     * @param {XmlHttpResponse} response
     * @param {Object} options
     */
    var onFeedLoadSuccess = function(response, options)
    {
        var inspector = com.conjoon.groupware.ResponseInspector;

        var data = inspector.isSuccess(response);

        if (!data || (data && !data.item)) {
            onFeedLoadFailure(response, options);
            return;
        }
        var item = data.item;
        var rec = com.conjoon.util.Record.convertTo(
            com.conjoon.groupware.feeds.ItemRecord,
            item,
            item.id
        );

        _requestIds[options.panelId] = null;
        delete _requestIds[options.panelId];

        Ext.ux.util.MessageBus.publish(
            'com.conjoon.groupware.feeds.FeedViewBaton.onFeedLoadSuccess', {
            id : item.id
        });

        openedFeeds[options.panelId].view.setTitle(rec.get('title'));
        openedFeeds[options.panelId].view.setIconClass(
            'com-conjoon-groupware-feeds-FeedView-Icon'
        );

        openedFeeds[options.panelId].body.body.update(rec.get('content'));
    };

    /**
     * Callback for an erroneous loading of a feed's content.
     *
     * @param {XmlHttpResponse} response
     * @param {Object} options
     */
    var onFeedLoadFailure = function(response, options)
    {
        var responseInspector = com.conjoon.groupware.ResponseInspector,
            succ        = responseInspector.isSuccess(response),
            authFailure = responseInspector.isAuthenticationFailure(response),
            panel,
            panelBody,
            msg;

        _requestIds[options.panelId] = null;
        delete _requestIds[options.panelId];

        // success is eitehr false or null
        // if succ is null, the no response was returned or response
        // could not be decoded, if success === false, then the item was
        // not found on the server
        if (!succ && !authFailure) {
            panel = openedFeeds[options.panelId].view;
            panelBody = openedFeeds[options.panelId].body.body;

            if (succ === false && panel) {
                msg = responseInspector.generateMessage(response);

                panel.setIconClass('com-conjoon-groupware-feeds-FeedView-Icon');
                panel.setTitle(panel.feedItemRecord.get('title'));

                panelBody.update(
                    com.conjoon.Gettext.gettext("An error occured while trying to load the feed item: ") +
                    msg.text
                );
                Ext.ux.util.MessageBus.publish(
                    'com.conjoon.groupware.feeds.FeedViewBaton.onFeedLoadFailure',
                    {id : options.params.id}
                );
                return;
            }

            panel.ownerCt.remove(panel);
        }

        responseInspector.handleFailure(response, {
            onLogin : {
                fn : function(){
                    loadFeedContents(
                        options.params.id,
                        options.params.groupwareFeedsAccountsId,
                        options.panelId
                    );
                }
            },
            title   : com.conjoon.Gettext.gettext("Error while loading feed item")
        });

    };

    /**
     *
     *
     * @param {com.conjoon.groupware.feeds.ItemRecord}
     * @param {Boolean} loadFromServer
     */
    var buildPanel = function(feedItemRecord, loadFromServer)
    {
        var accRec = AccountStore.getById(feedItemRecord.get('groupwareFeedsAccountsId')),
            link   = accRec.get('link').
            name   = feedItemRecord.get('name')+' - '+accRec.get('description'),
            body = new Ext.Panel({
                region     : 'center',
                autoScroll : true,
                cls        : 'com-conjoon-groupware-feeds-FeedView-panel',
                html       : ''
            }),
            key = idPrefix+feedItemRecord.id,
            view;

        view = new Ext.Panel({
            /**
             * Not creating a specific class in this case. We simply set cnCompType
             * as a helper to indicate we have a panel representing a feed entry
             * @ticket CN-789
             */
            cnCompType : 'feedViewPanel',
            feedItemRecord : feedItemRecord,
            cnLoadContentFromServer : loadFromServer,
            /**
             * @inheritdoc
             * @ticket CN-789
             */
            getState : function() {

                var me = this,
                    feedData = me.feedItemRecord.data;

                // remove unnedded information from the record
                delete feedData.description;
                delete feedData.content;

                return {
                    cnCompType : 'feedViewPanel',
                    feedItem   : feedData,
                    title      : feedItemRecord.get('title'),
                    iconCls    : 'com-conjoon-groupware-feeds-FeedView-Icon'
                };

            },
            layout     : 'border',
            id         : idPrefix+feedItemRecord.id,
            title      : loadFromServer
                         ? com.conjoon.Gettext.gettext("Loading...")
                         : feedItemRecord.get('title'),
            iconCls    : loadFromServer
                         ? 'com-conjoon-groupware-pending-icon'
                         : 'com-conjoon-groupware-feeds-FeedView-Icon',
            closable   : true,
            hideMode   : 'offsets',
            listeners  : com.conjoon.groupware.util.LinkInterceptor.getListener(),
            items      : [{
                region    : 'north',
                bodyStyle : 'border-bottom:none',
                cls       : 'com-conjoon-groupware-feeds-FeedView-header',
                html      :
                   '
'+
                   ''+Ext.util.Format.date(feedItemRecord.get('pubDate'), 'd.m.Y H:i')+''+
                   '
'+feedItemRecord.get('title')+'
'+
                   '
'+name+'
'+
                   '
'+link+'
'+
                   '
'+
                   com.conjoon.Gettext.gettext("Posted by")+': '+
                   (
                    feedItemRecord.get('authorEmail')
                    ? ''+feedItemRecord.get('author')+''
                    : feedItemRecord.get('author')
                   )+
                   (
                    feedItemRecord.get('authorUri')
                    ? ''
                    : ''
                   )+
                   '
'+
                   '
'

            },body
            ]
        });

        var tbarManager = com.conjoon.groupware.workbench.ToolbarController;

        view.on('destroy', function(panel){
            delete openedFeeds[panel.id];
            if (_requestIds[panel.id]) {
                Ext.Ajax.abort(_requestIds[panel.id]);
                delete _requestIds[panel.id];
            }

            // hide this only if there are no more feed tabs to display
            // this is needed if there is no tab which could be activated
            // which shows a toolbar upon activate
            var hide = true;
            for (var i in openedFeeds) {
                hide = false;
                break;
            }
            if (hide) {
                tbarManager.hide('com.conjoon.groupware.feeds.FeedView.toolbar');
            }
        }, view, {single : true});

        view.on('activate', function(panel) {
            if (panel.cnLoadContentFromServer === true) {
                var feedItemRecord = panel.feedItemRecord;
                loadFeedContents(
                    feedItemRecord.id,
                    feedItemRecord.get('groupwareFeedsAccountsId'),
                    idPrefix+feedItemRecord.id
                );
            }
            tbarManager.show('com.conjoon.groupware.feeds.FeedView.toolbar');
        });

        view.on('deactivate', function(panel) {
            tbarManager.hide('com.conjoon.groupware.feeds.FeedView.toolbar');
        });

        contentPanel.add(view);
        contentPanel.setActiveTab(view);

        openedFeeds[key] = {
            view : view,
            /**
             * We are only storing a reference to the body and concatenate
             * to the body's body later on, since the body might not be rendered
             * immediately (see afterrender)
             * @ticket CN-789
             */
            body : body,
            link : feedItemRecord.get('link')
        };

        return openedFeeds[key];
    };

    return {

        /**
         * Displays a feed item's content and it's details in a new tab.
         * If the second argument is set to true, the baton will load additionally
         * feed's contents from the server.
         *
         * @param {com.conjoon.groupware.feeds.ItemRecord} feedItemRecord the fully configured
         * feed item record
         * @param {Boolean} loadFromServer true if the record is not fully
         * configured and needs loading from the server, otherwise false
         *
         * @return {Object}
         */
        showFeed : function(feedItemRecord, loadFromServer)
        {
            if (!contentPanel) {
                contentPanel = com.conjoon.util.Registry.get('com.conjoon.groupware.ContentPanel');
            }

            if (toolbar == null) {
                registerToolbar();
            }

            var recordId = -1;
            var isRecord = true;

            var opened = openedFeeds[idPrefix+feedItemRecord.id];

            if (opened) {
                // needs to be set before activate
                opened.view.cnLoadContentFromServer = loadFromServer;
                contentPanel.setActiveTab(opened['view']);
            } else {
                opened = buildPanel(feedItemRecord, loadFromServer);
                opened.view.cnLoadContentFromServer = loadFromServer;
            }

            if (loadFromServer !== true) {
                openedFeeds[idPrefix+feedItemRecord.id].body.body.update(feedItemRecord.get('content'));
            }

            return opened;
        }
    }
}();
<commit_msg>[Feeds module - client] - enhancement: loading icon and loading text shown when feed content gets loaded from backend (closes CN-832)<commit_after>/**
 * conjoon
 * (c) 2002-2012 siteartwork.de/conjoon.org
 * licensing@conjoon.org
 *
 * $Author$
 * $Id$
 * $Date$
 * $Revision$
 * $LastChangedDate$
 * $LastChangedBy$
 * $URL$
 */

Ext.namespace('com.conjoon.groupware.feeds');

/**
 * @class com.conjoon.groupware.feeds.FeedViewBaton
 * @singleton
 *
 * Manages the opening of feed items as new tabs. Will not open a new tab if the
 * tab with the passed feed item id does already exist.
 * The class will also load the feed cpntents from the server if, and only if,
 * the fully configured feed item record was not submitted.
 *
 */
com.conjoon.groupware.feeds.FeedViewBaton = function() {

    var openedFeeds = {};

    var AccountStore = com.conjoon.groupware.feeds.AccountStore.getInstance();

    var LinkInterceptor = com.conjoon.groupware.util.LinkInterceptor;

    var contentPanel = null;

    var idPrefix = 'com.conjoon.groupware.feeds.FeedItemView_';

    var toolbar = null;

    var activeRecord = null;

    var _requestIds = {};

    var registerToolbar = function()
    {
        if (toolbar == null) {
            var tbarManager = com.conjoon.groupware.workbench.ToolbarController;

            var linkButton = new Ext.Toolbar.Button({
                id       : 'com.conjoon.groupware.feeds.FeedView.toolbar.LinkButton',
                cls      : 'x-btn-text-icon',
                iconCls  : 'com-conjoon-groupware-feeds-FeedViewBaton-toolbar-visitEntryButton-icon',
                text     : ' '+com.conjoon.Gettext.gettext("Visit entry"),
                handler  : function(){visitFeedEntry();}
            });

            toolbar = new Ext.Toolbar([
                linkButton
            ]);

            tbarManager.register('com.conjoon.groupware.feeds.FeedView.toolbar', toolbar);
        }
    };

    var visitFeedEntry = function(type)
    {
        var tab = contentPanel.getActiveTab();

        var id = tab.id;

        if (!openedFeeds[id]) {
            return;
        }

        (function() {
            this.open(LinkInterceptor.getRedirectLink(openedFeeds[id]['link']));
        }).defer(1, window);
    };

    /**
     * Loads the feed's contents for the specified id from the server.
     *
     * @param {Number} id
     * @param {Number} groupwareFeedsAccountsId
     * @param {String} panelId
     *
     */
    var loadFeedContents = function(id, groupwareFeedsAccountsId, panelId)
    {
        if (_requestIds[panelId]) {
            return;
        }

        /**
         * @ticket CN-832
         */
        var tab = openedFeeds[panelId]
                  ? openedFeeds[panelId].view
                  : null;
        if (tab) {
            tab.setTitle(com.conjoon.Gettext.gettext("Loading..."));
            tab.setIconClass('com-conjoon-groupware-pending-icon');
        }

        _requestIds[panelId] = Ext.Ajax.request({
            url    : './groupware/feeds.item/get.feed.content/format/json',
            params : {
                id                       : id,
                groupwareFeedsAccountsId : groupwareFeedsAccountsId
            },
            panelId : panelId,
            success : onFeedLoadSuccess,
            failure : onFeedLoadFailure
        });
    };

    /**
     * Callback for the successfull loading of a feed's content.
     *
     * @param {XmlHttpResponse} response
     * @param {Object} options
     */
    var onFeedLoadSuccess = function(response, options)
    {
        var inspector = com.conjoon.groupware.ResponseInspector;

        var data = inspector.isSuccess(response);

        if (!data || (data && !data.item)) {
            onFeedLoadFailure(response, options);
            return;
        }
        var item = data.item;
        var rec = com.conjoon.util.Record.convertTo(
            com.conjoon.groupware.feeds.ItemRecord,
            item,
            item.id
        );

        _requestIds[options.panelId] = null;
        delete _requestIds[options.panelId];

        Ext.ux.util.MessageBus.publish(
            'com.conjoon.groupware.feeds.FeedViewBaton.onFeedLoadSuccess', {
            id : item.id
        });

        openedFeeds[options.panelId].view.setTitle(rec.get('title'));
        openedFeeds[options.panelId].view.setIconClass(
            'com-conjoon-groupware-feeds-FeedView-Icon'
        );

        openedFeeds[options.panelId].body.body.update(rec.get('content'));
    };

    /**
     * Callback for an erroneous loading of a feed's content.
     *
     * @param {XmlHttpResponse} response
     * @param {Object} options
     */
    var onFeedLoadFailure = function(response, options)
    {
        var responseInspector = com.conjoon.groupware.ResponseInspector,
            succ        = responseInspector.isSuccess(response),
            authFailure = responseInspector.isAuthenticationFailure(response),
            panel,
            panelBody,
            msg;

        _requestIds[options.panelId] = null;
        delete _requestIds[options.panelId];

        // success is eitehr false or null
        // if succ is null, the no response was returned or response
        // could not be decoded, if success === false, then the item was
        // not found on the server
        if (!succ && !authFailure) {
            panel = openedFeeds[options.panelId].view;
            panelBody = openedFeeds[options.panelId].body.body;

            if (succ === false && panel) {
                msg = responseInspector.generateMessage(response);

                panel.setIconClass('com-conjoon-groupware-feeds-FeedView-Icon');
                panel.setTitle(panel.feedItemRecord.get('title'));

                panelBody.update(
                    com.conjoon.Gettext.gettext("An error occured while trying to load the feed item: ") +
                    msg.text
                );
                Ext.ux.util.MessageBus.publish(
                    'com.conjoon.groupware.feeds.FeedViewBaton.onFeedLoadFailure',
                    {id : options.params.id}
                );
                return;
            }

            panel.ownerCt.remove(panel);
        }

        responseInspector.handleFailure(response, {
            onLogin : {
                fn : function(){
                    loadFeedContents(
                        options.params.id,
                        options.params.groupwareFeedsAccountsId,
                        options.panelId
                    );
                }
            },
            title   : com.conjoon.Gettext.gettext("Error while loading feed item")
        });

    };

    /**
     *
     *
     * @param {com.conjoon.groupware.feeds.ItemRecord}
     * @param {Boolean} loadFromServer
     */
    var buildPanel = function(feedItemRecord, loadFromServer)
    {
        var accRec = AccountStore.getById(feedItemRecord.get('groupwareFeedsAccountsId')),
            link   = accRec.get('link').
            name   = feedItemRecord.get('name')+' - '+accRec.get('description'),
            body = new Ext.Panel({
                region     : 'center',
                autoScroll : true,
                cls        : 'com-conjoon-groupware-feeds-FeedView-panel',
                html       : ''
            }),
            key = idPrefix+feedItemRecord.id,
            view;

        view = new Ext.Panel({
            /**
             * Not creating a specific class in this case. We simply set cnCompType
             * as a helper to indicate we have a panel representing a feed entry
             * @ticket CN-789
             */
            cnCompType : 'feedViewPanel',
            feedItemRecord : feedItemRecord,
            cnLoadContentFromServer : loadFromServer,
            /**
             * @inheritdoc
             * @ticket CN-789
             */
            getState : function() {

                var me = this,
                    feedData = me.feedItemRecord.data;

                // remove unnedded information from the record
                delete feedData.description;
                delete feedData.content;

                return {
                    cnCompType : 'feedViewPanel',
                    feedItem   : feedData,
                    title      : feedItemRecord.get('title'),
                    iconCls    : 'com-conjoon-groupware-feeds-FeedView-Icon'
                };

            },
            layout     : 'border',
            id         : idPrefix+feedItemRecord.id,
            title      : loadFromServer
                         ? com.conjoon.Gettext.gettext("Loading...")
                         : feedItemRecord.get('title'),
            iconCls    : loadFromServer
                         ? 'com-conjoon-groupware-pending-icon'
                         : 'com-conjoon-groupware-feeds-FeedView-Icon',
            closable   : true,
            hideMode   : 'offsets',
            listeners  : com.conjoon.groupware.util.LinkInterceptor.getListener(),
            items      : [{
                region    : 'north',
                bodyStyle : 'border-bottom:none',
                cls       : 'com-conjoon-groupware-feeds-FeedView-header',
                html      :
                   '
'+
                   ''+Ext.util.Format.date(feedItemRecord.get('pubDate'), 'd.m.Y H:i')+''+
                   '
'+feedItemRecord.get('title')+'
'+
                   '
'+name+'
'+
                   '
'+link+'
'+
                   '
'+
                   com.conjoon.Gettext.gettext("Posted by")+': '+
                   (
                    feedItemRecord.get('authorEmail')
                    ? ''+feedItemRecord.get('author')+''
                    : feedItemRecord.get('author')
                   )+
                   (
                    feedItemRecord.get('authorUri')
                    ? ''
                    : ''
                   )+
                   '
'+
                   '
'

            },body
            ]
        });

        var tbarManager = com.conjoon.groupware.workbench.ToolbarController;

        view.on('destroy', function(panel){
            delete openedFeeds[panel.id];
            if (_requestIds[panel.id]) {
                Ext.Ajax.abort(_requestIds[panel.id]);
                delete _requestIds[panel.id];
            }

            // hide this only if there are no more feed tabs to display
            // this is needed if there is no tab which could be activated
            // which shows a toolbar upon activate
            var hide = true;
            for (var i in openedFeeds) {
                hide = false;
                break;
            }
            if (hide) {
                tbarManager.hide('com.conjoon.groupware.feeds.FeedView.toolbar');
            }
        }, view, {single : true});

        view.on('activate', function(panel) {
            if (panel.cnLoadContentFromServer === true) {
                var feedItemRecord = panel.feedItemRecord;
                loadFeedContents(
                    feedItemRecord.id,
                    feedItemRecord.get('groupwareFeedsAccountsId'),
                    idPrefix+feedItemRecord.id
                );
            }
            tbarManager.show('com.conjoon.groupware.feeds.FeedView.toolbar');
        });

        view.on('deactivate', function(panel) {
            tbarManager.hide('com.conjoon.groupware.feeds.FeedView.toolbar');
        });

        contentPanel.add(view);
        contentPanel.setActiveTab(view);

        openedFeeds[key] = {
            view : view,
            /**
             * We are only storing a reference to the body and concatenate
             * to the body's body later on, since the body might not be rendered
             * immediately (see afterrender)
             * @ticket CN-789
             */
            body : body,
            link : feedItemRecord.get('link')
        };

        return openedFeeds[key];
    };

    return {

        /**
         * Displays a feed item's content and it's details in a new tab.
         * If the second argument is set to true, the baton will load additionally
         * feed's contents from the server.
         *
         * @param {com.conjoon.groupware.feeds.ItemRecord} feedItemRecord the fully configured
         * feed item record
         * @param {Boolean} loadFromServer true if the record is not fully
         * configured and needs loading from the server, otherwise false
         *
         * @return {Object}
         */
        showFeed : function(feedItemRecord, loadFromServer)
        {
            if (!contentPanel) {
                contentPanel = com.conjoon.util.Registry.get('com.conjoon.groupware.ContentPanel');
            }

            if (toolbar == null) {
                registerToolbar();
            }

            var recordId = -1;
            var isRecord = true;

            var opened = openedFeeds[idPrefix+feedItemRecord.id];

            if (opened) {
                // needs to be set before activate
                opened.view.cnLoadContentFromServer = loadFromServer;
                contentPanel.setActiveTab(opened['view']);
            } else {
                opened = buildPanel(feedItemRecord, loadFromServer);
                opened.view.cnLoadContentFromServer = loadFromServer;
            }

            if (loadFromServer !== true) {
                openedFeeds[idPrefix+feedItemRecord.id].body.body.update(feedItemRecord.get('content'));
            }

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


<commit_before>/**
 * Created by sky on 2017/2/9.
 */

(function () {
    var $$sug = document.getElementById('suggest')
    var $$res = document.getElementById('result')

    var mockData = [
        '今天天气好吗',
        '今天天气如何',
        '明天天气好吗',
        '明天天气如何',
        '今天我和你出去玩',
        '明天我们出去玩好吗',
        '后天天气怎么样',
        '后天天气好吗',
        '今天明天',
        '今天昨天',
        '今天今天',
        '今天明天天明',
        '今天天明天明',
        '明天天明天明',
        '明天明天天明天明'
    ];

    var waitingValue;

    function edit_distance(a, b) {
        var lenA = a.length,
            lenB = b.length,
            d = [],
            res = {
                // 最大的匹配词长度
                maxLength: -1,
                // 匹配词总长度
                count: 0,
                // 首个匹配字符的位置
                position: 30,
                // 最短编辑路径
                distance: -1
            },
            // 是否连续匹配到字符
            isConj = false,
            // 是否匹配到字符
            isMatched = false,
            curA,
            curB,
            curPos,
            tmp,
            tmpPos,
            tmpLen,
            tmpConj,
            i, j, old;

        function init() {
            tmpPos = -1;
            tmpLen = 0;
            tmpConj = '';
        }

        function setRes() {
            tmpLen = tmpConj.length;
            if (tmpLen) {
                // 设置最大匹配字符串长度
                if (tmpLen > res.maxLength) {
                    res.maxLength = tmpLen;
                }
                // 设置所有匹配字符的数量
                res.count += tmpLen;
                // 设置首个匹配字符位置
                if (tmpPos != -1 && res.position > tmpPos) {
                    res.position = tmpPos;
                }
                init();
            }
        }

        init();

        // 创建一个数组，用于单个字符匹配
        for (j = 0; j <= lenB; j++) {
            d[j] = j;
        }

        for (i = 1; i <= lenA; i++) {
            old = d[0];
            d[0] = i;
            curA = a[i - 1];

            for (j = 1; j <= lenB; j++) {
                tmp = d[j];
                curPos = j - 1;
                curB = b[curPos];

                // 是否匹配到字符
                if (curA == curB) {
                    d[j] = old;

                    if (tmpPos == -1 || tmpPos > curPos) {
                        tmpPos = curPos;
                    }

                    // 确保只匹配成功一次
                    if (!isConj) {
                        isMatched = true;
                        // 是否已经匹配到字符串，并且保证匹配的字符串可查询
                        isConj = a[i - 2] == b[j - 2] && b.indexOf(tmpConj + curA) != -1;
                    }
                } else {
                    // 获得最小编辑距离路径
                    d[j] = Math.min(tmp + 1, d[curPos] + 1, old + 1);
                }
                old = tmp;
            }

            // 如果是最后一个字符，无论字符串是否连续都执行设置结果集
            if (lenA == i) {
                // 如果是连续的字符串，就拼接最后一个字符
                if (isConj) {
                    tmpConj += curA;
                    isConj = isMatched = false;
                }

            }

            // 如果是连续的字符串，就拼接这个字符；否则去设置结果集
            if (isConj) {
                tmpConj += curA;
            } else {
                setRes();
                // 如果匹配到了字符，但是字符并不符合当前字符串的要求
                if (isMatched) {
                    tmpConj += curA;
                    // 如果匹配到了字符，但字符在最后一个位置
                    lenA == i && setRes();
                }
            }

            isConj = isMatched = false;
        }

        // 设置编辑距离
        res.distance = d[lenB];

        return res;
    }

    function filterData(data, key) {
        var len = data.length,
            res = [],
            i, sort, item;

        for (i = 0; i < len; i++) {
            item = data[i];
            sort = edit_distance(key, item);
            // 过滤完全没有匹配到的数据
            if (sort.count == 0) {
                continue;
            }

            res.push({
                sort: sort,
                data: item
            });
        }

        var tmp = [];
        res = res.sort(function (a, b) {
            // function rule(sort, txt) {
            //     var maxLength = sort.maxLength * 25,
            //         count = sort.count * 20,
            //         length = txt.length * 15,
            //         position = sort.position * 25,
            //         distance = sort.distance * 15,
            //         res = maxLength + count + length - position - distance;
            //     if ((',' + tmp.join(',') + ',').indexOf(',' + txt + ',') === -1) {
            //         console.log('最大长度:', sort.maxLength, '匹配长度:', sort.count, '内容长度:', txt.length, '首字符的位置:', sort.position, '最短编辑路径:', sort.distance, '权值:', res, txt);
            //         tmp.push(txt);
            //     }
            //     return res;
            // }

            // 设置排序规则，根据权值调整
            function rule(sort, txt) {
                return sort.maxLength * 25 + sort.count * 20 + txt.length * 15 - sort.position * 25 - sort.distance * 15;
            }

            // 等于0 顺序不变， 大于0 a排前面， 小于0 b排前面
            return rule(b.sort, b.data) - rule(a.sort, a.data);
        });

        // 还原数据结构
        return res.map(function (item) {
            return item.data;
        });
    }

    $$sug.addEventListener('keypress', function () {
        waitingValue = this.value;
    });

    $$sug.addEventListener('keyup', function (e) {
        var key = this.value,
            data,
            template = '
';

        if (waitingValue == null) {
            return;
        }

        data = filterData(mockData, key);

        for (var i = 0; i < data.length; i++) {
            template += '
' + data[i] + '
';
        }
        $$res.innerHTML = template += '
';
    }, false);
})()<commit_msg>修改模糊搜索算法<commit_after>/**
 * Created by sky on 2017/2/9.
 */

;(function(win) {
  function editDistance(target, compare) {
    const lenA = target.length
    const lenB = compare.length
    const space = new Array(lenB)
    const result = {
      // 最大的匹配词长度
      maxLength: -1,
      // 匹配词总个数
      count: 0,
      // 首个匹配字符的位置
      position: 1000000000,
      // 最短编辑路径
      distance: -1
    }

    function modifyResult(conj, pos) {
      const len = conj.length
      if (len) {
        // 设置最大匹配字符串长度
        if (len > result.maxLength) {
          result.maxLength = len
        }
        // 设置所有匹配字符的数量
        result.count += len
        // 设置首个匹配字符位置
        if (pos != -1 && result.position > pos) {
          result.position = pos
        }
      }
    }

    // 过滤目标或者比较值为空字符串的情况
    if (target === '' || compare === '') {
      return result
    }

    // 创建一个数组，用于单个字符匹配
    // for (let k = 0; k <= lenB; k++) {
    //   space[k] = k
    // }

    for (let i = 1; i <= lenA; i++) {
      let old = space[0] || 0
      space[0] = i
      const curA = target[i - 1]
      // 是否连续匹配到字符
      let isContinue = false
      // 是否匹配到字符
      let isMatched = false
      // 匹配到的连续字符
      let continuousChar = ''
      // 匹配到的最终位置
      let finalPos = -1

      for (let j = 1; j <= lenB; j++) {
        const tmp = space[j] || j
        const curPos = j - 1
        const curB = compare[curPos]

        // 是否匹配到字符
        if (curA == curB) {
          space[j] = old

          if (finalPos === -1 || finalPos > curPos) {
            finalPos = curPos
          }

          // 确保只匹配成功一次
          if (!isContinue) {
            isMatched = true
            // 是否已经匹配到字符串，并且保证匹配的字符串可查询
            isContinue =
              target[i - 2] == compare[j - 2] &&
              compare.indexOf(continuousChar + curA) != -1
          }
        } else {
          // 获得最小编辑距离路径
          space[j] = Math.min(tmp + 1, space[curPos] + 1, old + 1)
        }
        old = tmp
      }

      // 如果是最后一个字符，无论字符串是否连续都执行设置结果集
      if (lenA == i) {
        // 如果是连续的字符串，就拼接最后一个字符
        if (isContinue) {
          continuousChar += curA
          isContinue = isMatched = false
        } else if (isMatched) {
          continuousChar += curA
          isMatched = false
        }
      }

      // 如果是连续的字符串，就拼接这个字符；否则去设置结果集
      if (isContinue || isMatched) {
        continuousChar += curA
      } else {
        modifyResult(continuousChar, finalPos)
      }
    }

    // 设置编辑距离
    result.distance = space[lenB]

    return result
  }

  // 设置排序规则，根据权值调整
  function calcWeight(sort, text) {
    const textLength = text.length
    const WEIGHT_CONFIG = {
      // 匹配到的最大长度
      maxLength: 40,
      // 匹配到的个数
      count: 20,
      // 匹配到的位置
      position: 5,
      // 编辑文本的距离
      distance: 30
    }

    return (
      sort.maxLength * WEIGHT_CONFIG.maxLength +
      sort.count * WEIGHT_CONFIG.count -
      (sort.position / textLength) * WEIGHT_CONFIG.position -
      (sort.distance / textLength) * WEIGHT_CONFIG.distance
    )
  }

  function getMaxWeight(target, keyNameList = [], match) {
    return keyNameList.reduce((accumulator, currentValue) => {
      const value = getValue(target, currentValue)

      if (typeof value !== 'string') {
        return accumulator
      }

      const sort = editDistance(match.toLowerCase(), value.toLowerCase())

      if (sort.count === 0) {
        return accumulator
      }

      const weight = calcWeight(sort, value)
      console.log(match, value, weight, JSON.stringify(sort))

      if (accumulator.weight !== undefined && weight < accumulator.weight) {
        return accumulator
      }

      return { weight, sort }
    }, {})
  }

  // 获取值
  function getValue(target, key) {
    return target !== null &&
      typeof target === 'object' &&
      typeof key === 'string' &&
      key !== ''
      ? target[key]
      : target
  }

  /**
   * 编辑距离算法排序
   * @param {array} rowList 待排序的数组
   * @param {string} match 排序的目标
   * @param {string} keyNameList 如果数组的每一个value为对象，keyNameList为读取对象的属性
   * @returns {array} sortList 排完序的数组
   */
  function suggest(rowList, match, keyNameList = ['value']) {
    const len = rowList.length
    const result = []

    if (typeof keyNameList === 'string') {
      keyNameList.split(',')
    } else if (!(keyNameList instanceof Array)) {
      throw new Error(`keyNameList 必须是字符串类型或者数组类型`)
    }

    // 遍历每一个数据，获得数据的编辑距离以及其它关键属性
    for (let i = 0; i < len; i++) {
      const data = rowList[i]

      const { weight, sort } = getMaxWeight(data, keyNameList, match)

      // 过滤完全没有匹配到的数据
      if (weight === undefined || sort === undefined) {
        continue
      }

      result.push({ weight, sort, data })
    }

    return (
      result
        // 根据编辑距离计算得到的数据进行排序
        .sort((a, b) => b.weight - a.weight)
        // 还原数据结构
        .map(item => {
          console.log(item.data.key, item.data.value, item.weight)
          return item.data
        })
    )
  }

  win.suggest = suggest
})(window)
;(function() {
  var $$sug = document.getElementById('suggest')
  var $$res = document.getElementById('result')

  var mockData = [
    '今天天气好吗',
    '今天天气如何',
    '明天天气好吗',
    '明天天气如何',
    '今天我和你出去玩',
    '明天我们出去玩好吗',
    '后天天气怎么样',
    '后天天气好吗',
    '今天明天',
    '今天昨天',
    '今天今天',
    '今天明天天明',
    '今天天明天明',
    '明天天明天明',
    '明天明天天明天明'
  ]

  var waitingValue

  $$sug.addEventListener('keypress', function() {
    waitingValue = this.value
  })

  $$sug.addEventListener(
    'keyup',
    function(e) {
      var key = this.value,
        data,
        template = '
'

      if (waitingValue == null) {
        return
      }

      data = window.suggest(mockData, key)

      if (!data.length) {
        data = mockData
      }

      for (var i = 0; i < data.length; i++) {
        template += '
' + data[i] + '
'
      }
      $$res.innerHTML = template += '
'
    },
    false
  )
})()
<|endoftext|>


<commit_before>/*
 * @name Text Rotation
 * @description Draws letters to the screen and rotates them at different angles.
 *  (ported from https://processing.org/examples/textrotation.html)
 */

let font,
  fontsize = 32;

  let angleRotate = 0.0;

  function setup() {
    createCanvas(710, 400);
    background(0);

    // Ensure the .ttf or .otf font stored in the assets directory
    // is loaded before setup() and draw() are called
    font = loadFont('assets/SourceSansPro-Regular.otf');

    // Set text characteristics
    textFont(font);
  }

  function draw() {
    background(0);

    strokeWeight(1);
    stroke(153);

    push();
    let angle1 = radians(45);
    translate(100, 180);
    rotate(angle1);
    // Draw the letter to the screen
    text("45 DEGREES", 0, 0);
    line(0, 0, 150, 0);
    pop();

    push();
    let angle2 = radians(270);
    translate(200, 180);
    rotate(angle2);
    // Draw the letter to the screen
    text("270 DEGREES", 0, 0);
    line(0, 0, 150, 0);
    pop();

    push();
    translate(440, 180);
    rotate(radians(angleRotate));
    text(int(angleRotate) % 360 + " DEGREES ", 0, 0);
    line(0, 0, 150, 0);
    pop();

    angleRotate += 0.25;

    stroke(255, 0, 0);
    strokeWeight(4);
    point(100, 180);
    point(200, 180);
    point(440, 180);
  }<commit_msg>update es text_rotation example<commit_after>/*
 * @name Text Rotation
 * @description Draws letters to the screen and rotates them at different angles.
 *  (ported from https://processing.org/examples/textrotation.html)
 */

let font,
  fontsize = 32;

let angleRotate = 0.0;

function setup() {
  createCanvas(710, 400);
  background(0);

  // Ensure the .ttf or .otf font stored in the assets directory
  // is loaded before setup() and draw() are called
  font = loadFont('assets/SourceSansPro-Regular.otf');

  // Set text characteristics
  textFont(font);
}

function draw() {
  background(0);

  strokeWeight(1);
  stroke(153);

  push();
  let angle1 = radians(45);
  translate(100, 180);
  rotate(angle1);
  // Draw the letter to the screen
  text("45 DEGREES", 0, 0);
  line(0, 0, 150, 0);
  pop();

  push();
  let angle2 = radians(270);
  translate(200, 180);
  rotate(angle2);
  // Draw the letter to the screen
  text("270 DEGREES", 0, 0);
  line(0, 0, 150, 0);
  pop();

  push();
  translate(440, 180);
  rotate(radians(angleRotate));
  text(int(angleRotate) % 360 + " DEGREES ", 0, 0);
  line(0, 0, 150, 0);
  pop();

  angleRotate += 0.25;

  stroke(255, 0, 0);
  strokeWeight(4);
  point(100, 180);
  point(200, 180);
  point(440, 180);
}
<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2018  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('14.4.0');
		this.setClientTag('node:18-08-04');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2018  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('14.4.0');
		this.setClientTag('node:18-08-05');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platforms allow them to do with
// text.
//
// Copyright (C) 2006-2022  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('18.4.0');
		this.setClientTag('node:22-05-10');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platforms allow them to do with
// text.
//
// Copyright (C) 2006-2022  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('18.4.0');
		this.setClientTag('node:22-05-11');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2017  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('3.3.0');
		this.setClientTag('node:17-10-12');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2017  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('3.3.0');
		this.setClientTag('node:17-10-13');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platforms allow them to do with
// text.
//
// Copyright (C) 2006-2022  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('18.3.0');
		this.setClientTag('node:22-04-27');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platforms allow them to do with
// text.
//
// Copyright (C) 2006-2022  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('18.3.0');
		this.setClientTag('node:22-04-28');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platforms allow them to do with
// text.
//
// Copyright (C) 2006-2022  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('18.4.0');
		this.setClientTag('node:22-05-09');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platforms allow them to do with
// text.
//
// Copyright (C) 2006-2022  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('18.4.0');
		this.setClientTag('node:22-05-10');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2018  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('14.6.0');
		this.setClientTag('node:18-09-07');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2018  Kaltura Inc.
//
// 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/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('14.6.0');
		this.setClientTag('node:18-09-08');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>


<commit_before>define([
    'jquery',
    'backbone'
], function ($, Backbone) {
    'use strict';

    var utils = Backbone.View.extend({
        baseUrl: "/api/",
        goToByScroll: function(selector, speed){

            var _speed = speed || 250
            // Scroll
            $('html,body').animate({
                scrollTop: $(selector).offset().top - ($('#navigation').height() - 2)
            }, _speed);

        },
        isValidEmailAddress: function(emailAddress){
            var pattern = /^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i;
            return pattern.test(emailAddress);
        },
        formatEventDate: function(Date, Labels){
            var dateString = Labels.voc.month[Date.getMonth()] + ". " + Date.getDate() + " " + Date.getFullYear();
            return dateString;
        },
        clearHash: function(){
            App.navigate('', {trigger:true, replace:true});
        },
        parseMustachesString: function(str){

            // ex:
            // "Hello {{firstName}} {{lastName}}"
            //  => ['firstName', 'lastName'];

            var array = [];
            var re = /[\{]{2}(.*?)[\}]{2}/g;
            var m;
            while ((m = re.exec(str)) !== null) {
                if (m.index === re.lastIndex) {
                    re.lastIndex++;
                }
                array.push(m[1]);
            }

            return array;
        },
        parseMustacheString: function (str, obj){

            var infos = this.parseMustachesString(str);

            for (var i = infos.length - 1; i >= 0; i--) {
                str = str.replace('{{'+infos[i]+'}}', obj[infos[i]]);
            }

            return str;
        },
        FormatDate: function(date){

            var _d = new Date(date);

            var D = _d.getDate();
            var M = (_d.getMonth()+1);

            if(D <= 9) D = "0"+D;
            if(M <= 9) M = "0"+M;

            return  D + "/" + M;
        },
        FormatFullDate: function(date){

            var _d = new Date(date);

            var D = _d.getDate();
            var M = (_d.getMonth()+1);
            var Y = _d.getFullYear();

            if(D <= 9) D = "0"+D;
            if(M <= 9) M = "0"+M;

            return  D + "/" + M + "/" + Y;
        },
        is_touch_device: function(){

            // console.log("!!!! WARNING !!!! TOUCH DEVICE ENABLED - line 83");
            //return true;

            return 'ontouchstart' in window || navigator.maxTouchPoints;
        },
        transitionEnd: "webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",
        cookie:{
            set: function(cname, cvalue, exdays){
                var d = new Date();
                d.setTime(d.getTime() + (exdays*24*60*60*1000));
                var expires = "expires="+d.toUTCString();
                document.cookie = cname + "=" + cvalue + "; " + expires;
            },
            get: function(cname){
                var name = cname + "=";
                var ca = document.cookie.split(';');
                for(var i = 0; i <ca.length; i++) {
                    var c = ca[i];
                    while (c.charAt(0)==' ') {
                        c = c.substring(1);
                    }
                    if (c.indexOf(name) == 0) {
                        return c.substring(name.length,c.length);
                    }
                }
                return "";
            },
            delete: function ( name, path, domain ) {
              if( this.get( name ) ) {
                document.cookie = name + "=" +
                  ((path) ? ";path="+path:"")+
                  ((domain)?";domain="+domain:"") +
                  ";expires=Thu, 01 Jan 1970 00:00:01 GMT";
              }
            }
        }
    });

    return utils;
});<commit_msg>update base URL for new structure<commit_after>define([
    'jquery',
    'backbone'
], function ($, Backbone) {
    'use strict';

    var utils = Backbone.View.extend({
        baseUrl: "/serviceworkers/api/",
        goToByScroll: function(selector, speed){

            var _speed = speed || 250
            // Scroll
            $('html,body').animate({
                scrollTop: $(selector).offset().top - ($('#navigation').height() - 2)
            }, _speed);

        },
        isValidEmailAddress: function(emailAddress){
            var pattern = /^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i;
            return pattern.test(emailAddress);
        },
        formatEventDate: function(Date, Labels){
            var dateString = Labels.voc.month[Date.getMonth()] + ". " + Date.getDate() + " " + Date.getFullYear();
            return dateString;
        },
        clearHash: function(){
            App.navigate('', {trigger:true, replace:true});
        },
        parseMustachesString: function(str){

            // ex:
            // "Hello {{firstName}} {{lastName}}"
            //  => ['firstName', 'lastName'];

            var array = [];
            var re = /[\{]{2}(.*?)[\}]{2}/g;
            var m;
            while ((m = re.exec(str)) !== null) {
                if (m.index === re.lastIndex) {
                    re.lastIndex++;
                }
                array.push(m[1]);
            }

            return array;
        },
        parseMustacheString: function (str, obj){

            var infos = this.parseMustachesString(str);

            for (var i = infos.length - 1; i >= 0; i--) {
                str = str.replace('{{'+infos[i]+'}}', obj[infos[i]]);
            }

            return str;
        },
        FormatDate: function(date){

            var _d = new Date(date);

            var D = _d.getDate();
            var M = (_d.getMonth()+1);

            if(D <= 9) D = "0"+D;
            if(M <= 9) M = "0"+M;

            return  D + "/" + M;
        },
        FormatFullDate: function(date){

            var _d = new Date(date);

            var D = _d.getDate();
            var M = (_d.getMonth()+1);
            var Y = _d.getFullYear();

            if(D <= 9) D = "0"+D;
            if(M <= 9) M = "0"+M;

            return  D + "/" + M + "/" + Y;
        },
        is_touch_device: function(){

            // console.log("!!!! WARNING !!!! TOUCH DEVICE ENABLED - line 83");
            //return true;

            return 'ontouchstart' in window || navigator.maxTouchPoints;
        },
        transitionEnd: "webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",
        cookie:{
            set: function(cname, cvalue, exdays){
                var d = new Date();
                d.setTime(d.getTime() + (exdays*24*60*60*1000));
                var expires = "expires="+d.toUTCString();
                document.cookie = cname + "=" + cvalue + "; " + expires;
            },
            get: function(cname){
                var name = cname + "=";
                var ca = document.cookie.split(';');
                for(var i = 0; i <ca.length; i++) {
                    var c = ca[i];
                    while (c.charAt(0)==' ') {
                        c = c.substring(1);
                    }
                    if (c.indexOf(name) == 0) {
                        return c.substring(name.length,c.length);
                    }
                }
                return "";
            },
            delete: function ( name, path, domain ) {
              if( this.get( name ) ) {
                document.cookie = name + "=" +
                  ((path) ? ";path="+path:"")+
                  ((domain)?";domain="+domain:"") +
                  ";expires=Thu, 01 Jan 1970 00:00:01 GMT";
              }
            }
        }
    });

    return utils;
});<|endoftext|>