<commit_before>CKEDITOR.dialog.add(
    'linkDialog',
    function (editor) {
        var urlRegex = '(https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}(\\.[a-z]{2,6})?)?\\/([-a-zA-Z0-9@:%_\\+.~#?&//=]*)';

        return {
            title: editor.lang.medialibrary.addLink,

            minWidth: 400,
            minHeight: 200,

            contents: [
                {
                    id: 'tab',
                    label: '',
                    elements: [
                        {
                            type: 'select',
                            id: 'type',
                            label: editor.lang.medialibrary.type,
                            items: [
                                [
                                    editor.lang.medialibrary.url,
                                    'url'
                                ],
                                [
                                    editor.lang.medialibrary.email,
                                    'email'
                                ]
                            ],
                            default: 'url',
                            onChange: function (element) {
                                var $urlFields = this.getDialog().getContentElement('tab', 'url').getElement().getParent().getParent().getParent().getParent().getParent().getParent();
                                var $localPageField = this.getDialog().getContentElement('tab', 'localPage').getElement().getParent().getParent();
                                var $openInNewWindowField = this.getDialog().getContentElement('tab', 'openInNewWindow').getElement().getParent().getParent();
                                var $emailAddressField = this.getDialog().getContentElement('tab', 'email').getElement().getParent().getParent();
                                var $subjectField = this.getDialog().getContentElement('tab', 'subject').getElement().getParent().getParent();
                                var $contentField = this.getDialog().getContentElement('tab', 'content').getElement().getParent().getParent();

                                var value = this.getValue();

                                // email url
                                if (value === 'email') {
                                    $urlFields.hide();
                                    $localPageField.hide();
                                    $openInNewWindowField.hide();
                                    $emailAddressField.show();
                                    $subjectField.show();
                                    $contentField.show();

                                    return;
                                }

                                // normal url
                                $urlFields.show();
                                $localPageField.show();
                                $openInNewWindowField.show();
                                $emailAddressField.hide();
                                $subjectField.hide();
                                $contentField.hide();
                            },
                            setup: function (element) {
                                var type = 'url';
                                if (element.getAttribute('href').startsWith('mailto:')) {
                                    type = 'email';
                                }

                                this.getDialog().setValueOf('tab', 'type', type);
                            },
                            onLoad: function (element) {
                                var $urlFields = this.getDialog().getContentElement('tab', 'url').getElement().getParent().getParent().getParent().getParent().getParent().getParent();
                                var $localPageField = this.getDialog().getContentElement('tab', 'localPage').getElement().getParent().getParent();
                                var $openInNewWindowField = this.getDialog().getContentElement('tab', 'openInNewWindow').getElement().getParent().getParent();
                                var $emailAddressField = this.getDialog().getContentElement('tab', 'email').getElement().getParent().getParent();
                                var $subjectField = this.getDialog().getContentElement('tab', 'subject').getElement().getParent().getParent();
                                var $contentField = this.getDialog().getContentElement('tab', 'content').getElement().getParent().getParent();

                                $urlFields.show();
                                $localPageField.show();
                                $openInNewWindowField.show();
                                $emailAddressField.hide();
                                $subjectField.hide();
                                $contentField.hide();
                            },
                            onHide: function (element) {
                                var $urlFields = this.getDialog().getContentElement('tab', 'url').getElement().getParent().getParent().getParent().getParent().getParent().getParent();
                                var $localPageField = this.getDialog().getContentElement('tab', 'localPage').getElement().getParent().getParent();
                                var $openInNewWindowField = this.getDialog().getContentElement('tab', 'openInNewWindow').getElement().getParent().getParent();
                                var $emailAddressField = this.getDialog().getContentElement('tab', 'email').getElement().getParent().getParent();
                                var $subjectField = this.getDialog().getContentElement('tab', 'subject').getElement().getParent().getParent();
                                var $contentField = this.getDialog().getContentElement('tab', 'content').getElement().getParent().getParent();

                                $urlFields.show();
                                $localPageField.show();
                                $openInNewWindowField.show();
                                $emailAddressField.hide();
                                $subjectField.hide();
                                $contentField.hide();
                            }
                        },
                        {
                            type: 'text',
                            id: 'displayText',
                            label: editor.lang.medialibrary.displayText,
                            validate: CKEDITOR.dialog.validate.notEmpty(editor.lang.medialibrary.displayCannotBeEmpty),
                            setup: function (element) {
                                this.setValue(element.getText());
                            },
                            commit: function (element) {
                                element.setText(this.getValue());
                            }
                        },
                        {
                            type: 'hbox',
                            widths: ['65%', '5%', '30%'],
                            children: [
                                {
                                    type: 'text',
                                    id: 'url',
                                    label: 'URL',
                                    setup: function (element) {
                                        if (element.getAttribute('href').startsWith('mailto:')) {
                                            return;
                                        }

                                        this.setValue(element.getAttribute('href'));
                                        this.getDialog().setValueOf('tab', 'openInNewWindow', element.getAttribute('target') === '_blank');
                                    },
                                    commit: function (element) {
                                        if (this.getDialog().getValueOf('tab', 'type') === 'email') {
                                            return;
                                        }

                                        element.setAttribute('href', this.getValue());
                                        element.setAttribute('data-cke-saved-href', this.getValue());
                                        element.removeAttribute('target');
                                        if (this.getDialog().getValueOf('tab', 'openInNewWindow')) {
                                            element.setAttribute('target', '_blank');
                                            element.setAttribute('rel', 'noopener noreferrer');
                                        }
                                    }
                                },
                                {
                                    type: 'html',
                                    html: 'or'
                                },
                                {
                                    type: 'button',
                                    id: 'browseServer',
                                    label: editor.lang.medialibrary.browseServer,
                                    onClick: function () {
                                        var editor = this.getDialog().getParentEditor();
                                        editor.popup(window.location.origin + jsData.MediaLibrary.browseAction, 800, 800);

                                        window.onmessage = function (event) {
                                            if (event.data && typeof event.data === 'object' && 'media-url' in event.data) {
                                                this.setValueOf('tab', 'url', event.data['media-url']);
                                            }
                                        }.bind(this.getDialog());
                                    },
                                    style: 'margin-top: 20px;'
                                }
                            ]
                        },
                        {
                            type: 'select',
                            label: jsBackend.locale.msg('EditorSelectInternalPage'),
                            id: 'localPage',
                            title: jsBackend.locale.msg('EditorSelectInternalPage'),
                            items: linkList,
                            onChange: function (event) {
                                this.getDialog().getContentElement('tab', 'url').setValue(event.data.value);
                            }
                        },
                        {
                            type: 'checkbox',
                            id: 'openInNewWindow',
                            label: editor.lang.medialibrary.openInNewWindow
                        },
                        {
                            type: 'text',
                            id: 'email',
                            label: editor.lang.medialibrary.email,
                            setup: function (element) {
                                if (this.getDialog().getValueOf('tab', 'type') === 'url') {
                                    return;
                                }

                                var url = new URL(element.getAttribute('href'));

                                this.setValue(url.pathname);
                                if (url.searchParams.has('subject')) {
                                    this.getDialog().setValueOf('tab', 'subject', url.searchParams.get('subject'));
                                }
                                if (url.searchParams.has('body')) {
                                    this.getDialog().setValueOf('tab', 'content', url.searchParams.get('body'));
                                }
                            },
                            commit: function (element) {
                                if (this.getDialog().getValueOf('tab', 'type') === 'url') {
                                    return;
                                }

                                var url = new URL('mailto:' + this.getValue());
                                if (this.getDialog().getValueOf('tab', 'subject') !== '') {
                                    url.searchParams.append('subject', this.getDialog().getValueOf('tab', 'subject'));
                                }
                                if (this.getDialog().getValueOf('tab', 'content') !== '') {
                                    url.searchParams.append('body', this.getDialog().getValueOf('tab', 'content'));
                                }

                                var href = url.toString().replace(/\+/g, '%20');
                                element.setAttribute('href', href);
                                element.setAttribute('data-cke-saved-href', href);
                            }
                        },
                        {
                            type: 'text',
                            id: 'subject',
                            label: editor.lang.medialibrary.subject
                        },
                        {
                            type: 'textarea',
                            id: 'content',
                            label: editor.lang.medialibrary.content
                        }
                    ]
                }
            ],

            onOk: function () {
                var dialog = this,
                    anchor = dialog.element;

                dialog.commitContent(anchor);

                if (dialog.insertMode) {
                    editor.insertElement(anchor);
                }
            },

            onShow: function () {
                var dialog = this;

                var selection = editor.getSelection();
                var initialText = selection.getSelectedText();
                var element = selection.getStartElement();

                if (element) {
                    element = element.getAscendant('a', true);
                }

                dialog.insertMode = !element || element.getName() !== 'a';
                if (dialog.insertMode) {
                    element = editor.document.createElement('a');

                    dialog.setValueOf('tab', initialText.match(urlRegex) ? 'url' : 'displayText', initialText);
                }

                this.element = element;

                if (!this.insertMode) {
                    this.setupContent(element);
                }
            }
        };
    }
);
<commit_msg>Fix adding links to images in ckeditor<commit_after>CKEDITOR.dialog.add(
    'linkDialog',
    function (editor) {
        var urlRegex = '(https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}(\\.[a-z]{2,6})?)?\\/([-a-zA-Z0-9@:%_\\+.~#?&//=]*)';

        return {
            title: editor.lang.medialibrary.addLink,

            minWidth: 400,
            minHeight: 200,

            contents: [
                {
                    id: 'tab',
                    label: '',
                    elements: [
                        {
                            type: 'select',
                            id: 'type',
                            label: editor.lang.medialibrary.type,
                            items: [
                                [
                                    editor.lang.medialibrary.url,
                                    'url'
                                ],
                                [
                                    editor.lang.medialibrary.email,
                                    'email'
                                ]
                            ],
                            default: 'url',
                            onChange: function (element) {
                                var $urlFields = this.getDialog().getContentElement('tab', 'url').getElement().getParent().getParent().getParent().getParent().getParent().getParent();
                                var $localPageField = this.getDialog().getContentElement('tab', 'localPage').getElement().getParent().getParent();
                                var $openInNewWindowField = this.getDialog().getContentElement('tab', 'openInNewWindow').getElement().getParent().getParent();
                                var $emailAddressField = this.getDialog().getContentElement('tab', 'email').getElement().getParent().getParent();
                                var $subjectField = this.getDialog().getContentElement('tab', 'subject').getElement().getParent().getParent();
                                var $contentField = this.getDialog().getContentElement('tab', 'content').getElement().getParent().getParent();

                                var value = this.getValue();

                                // email url
                                if (value === 'email') {
                                    $urlFields.hide();
                                    $localPageField.hide();
                                    $openInNewWindowField.hide();
                                    $emailAddressField.show();
                                    $subjectField.show();
                                    $contentField.show();

                                    return;
                                }

                                // normal url
                                $urlFields.show();
                                $localPageField.show();
                                $openInNewWindowField.show();
                                $emailAddressField.hide();
                                $subjectField.hide();
                                $contentField.hide();
                            },
                            setup: function (element) {
                                var type = 'url';
                                if (element.getAttribute('href').startsWith('mailto:')) {
                                    type = 'email';
                                }

                                this.getDialog().setValueOf('tab', 'type', type);
                            },
                            onLoad: function (element) {
                                var $urlFields = this.getDialog().getContentElement('tab', 'url').getElement().getParent().getParent().getParent().getParent().getParent().getParent();
                                var $localPageField = this.getDialog().getContentElement('tab', 'localPage').getElement().getParent().getParent();
                                var $openInNewWindowField = this.getDialog().getContentElement('tab', 'openInNewWindow').getElement().getParent().getParent();
                                var $emailAddressField = this.getDialog().getContentElement('tab', 'email').getElement().getParent().getParent();
                                var $subjectField = this.getDialog().getContentElement('tab', 'subject').getElement().getParent().getParent();
                                var $contentField = this.getDialog().getContentElement('tab', 'content').getElement().getParent().getParent();

                                $urlFields.show();
                                $localPageField.show();
                                $openInNewWindowField.show();
                                $emailAddressField.hide();
                                $subjectField.hide();
                                $contentField.hide();
                            },
                            onHide: function (element) {
                                var $urlFields = this.getDialog().getContentElement('tab', 'url').getElement().getParent().getParent().getParent().getParent().getParent().getParent();
                                var $localPageField = this.getDialog().getContentElement('tab', 'localPage').getElement().getParent().getParent();
                                var $openInNewWindowField = this.getDialog().getContentElement('tab', 'openInNewWindow').getElement().getParent().getParent();
                                var $emailAddressField = this.getDialog().getContentElement('tab', 'email').getElement().getParent().getParent();
                                var $subjectField = this.getDialog().getContentElement('tab', 'subject').getElement().getParent().getParent();
                                var $contentField = this.getDialog().getContentElement('tab', 'content').getElement().getParent().getParent();

                                $urlFields.show();
                                $localPageField.show();
                                $openInNewWindowField.show();
                                $emailAddressField.hide();
                                $subjectField.hide();
                                $contentField.hide();
                            }
                        },
                        {
                            type: 'text',
                            id: 'displayText',
                            label: editor.lang.medialibrary.displayText,
                            setup: function (element) {
                                this.setValue(element.getText());
                            },
                            onShow: function (element) {
                                // hide display text when linking a html element
                                if (element.sender.element.htmlElement) {
                                  this.getElement().getParent().getParent().hide();

                                  return;
                                }

                                this.getElement().getParent().getParent().show();
                            },
                            commit: function (element) {
                                // don't set display text when linking a html element
                                if (element.htmlElement) {
                                    return;
                                }

                                // fill in display text
                                if (this.getValue()) {
                                    element.setText(this.getValue());
                                }
                            }
                        },
                        {
                            type: 'hbox',
                            widths: ['65%', '5%', '30%'],
                            children: [
                                {
                                    type: 'text',
                                    id: 'url',
                                    label: 'URL',
                                    setup: function (element) {
                                        if (element.getAttribute('href').startsWith('mailto:')) {
                                            return;
                                        }

                                        this.setValue(element.getAttribute('href'));
                                        this.getDialog().setValueOf('tab', 'openInNewWindow', element.getAttribute('target') === '_blank');
                                    },
                                    commit: function (element) {
                                        if (this.getDialog().getValueOf('tab', 'type') === 'email') {
                                            return;
                                        }

                                        // set url as text when no display text is given
                                        if (!element.htmlElement && !element.getText()) {
                                            element.setText(this.getValue());
                                        }

                                        element.setAttribute('href', this.getValue());
                                        element.setAttribute('data-cke-saved-href', this.getValue());
                                        element.removeAttribute('target');
                                        if (this.getDialog().getValueOf('tab', 'openInNewWindow')) {
                                            element.setAttribute('target', '_blank');
                                            element.setAttribute('rel', 'noopener noreferrer');
                                        }
                                    }
                                },
                                {
                                    type: 'html',
                                    html: 'or'
                                },
                                {
                                    type: 'button',
                                    id: 'browseServer',
                                    label: editor.lang.medialibrary.browseServer,
                                    onClick: function () {
                                        var editor = this.getDialog().getParentEditor();
                                        editor.popup(window.location.origin + jsData.MediaLibrary.browseAction, 800, 800);

                                        window.onmessage = function (event) {
                                            if (event.data && typeof event.data === 'object' && 'media-url' in event.data) {
                                                this.setValueOf('tab', 'url', event.data['media-url']);
                                            }
                                        }.bind(this.getDialog());
                                    },
                                    style: 'margin-top: 20px;'
                                }
                            ]
                        },
                        {
                            type: 'select',
                            label: jsBackend.locale.msg('EditorSelectInternalPage'),
                            id: 'localPage',
                            title: jsBackend.locale.msg('EditorSelectInternalPage'),
                            items: linkList,
                            onChange: function (event) {
                                this.getDialog().getContentElement('tab', 'url').setValue(event.data.value);
                            }
                        },
                        {
                            type: 'checkbox',
                            id: 'openInNewWindow',
                            label: editor.lang.medialibrary.openInNewWindow
                        },
                        {
                            type: 'text',
                            id: 'email',
                            label: editor.lang.medialibrary.email,
                            setup: function (element) {
                                if (this.getDialog().getValueOf('tab', 'type') === 'url') {
                                    return;
                                }

                                var url = new URL(element.getAttribute('href'));

                                this.setValue(url.pathname);
                                if (url.searchParams.has('subject')) {
                                    this.getDialog().setValueOf('tab', 'subject', url.searchParams.get('subject'));
                                }
                                if (url.searchParams.has('body')) {
                                    this.getDialog().setValueOf('tab', 'content', url.searchParams.get('body'));
                                }
                            },
                            commit: function (element) {
                                if (this.getDialog().getValueOf('tab', 'type') === 'url') {
                                    return;
                                }

                                var url = new URL('mailto:' + this.getValue());
                                if (this.getDialog().getValueOf('tab', 'subject') !== '') {
                                    url.searchParams.append('subject', this.getDialog().getValueOf('tab', 'subject'));
                                }
                                if (this.getDialog().getValueOf('tab', 'content') !== '') {
                                    url.searchParams.append('body', this.getDialog().getValueOf('tab', 'content'));
                                }

                                var href = url.toString().replace(/\+/g, '%20');
                                element.setAttribute('href', href);
                                element.setAttribute('data-cke-saved-href', href);
                            }
                        },
                        {
                            type: 'text',
                            id: 'subject',
                            label: editor.lang.medialibrary.subject
                        },
                        {
                            type: 'textarea',
                            id: 'content',
                            label: editor.lang.medialibrary.content
                        }
                    ]
                }
            ],

            onOk: function () {
                var dialog = this,
                    anchor = dialog.element;

                dialog.commitContent(anchor);

                if (dialog.insertMode) {
                    editor.insertElement(anchor);
                }
            },

            onShow: function () {
                var dialog = this;

                var selection = editor.getSelection();
                var initialText = selection.getSelectedText();
                var initialElement = selection.getSelectedElement();
                var element = selection.getStartElement();

                if (element) {
                    element = element.getAscendant('a', true);
                }

                dialog.insertMode = !element || element.getName() !== 'a';
                if (dialog.insertMode) {
                    element = editor.document.createElement('a');

                    dialog.setValueOf('tab', initialText.match(urlRegex) ? 'url' : 'displayText', initialText);
                }

                // save initial element to new a-element
                if (initialElement) {
                    // element used for checks
                    element.htmlElement = initialElement.$.outerHTML;
                    // display element
                    element.setHtml(initialElement.$.outerHTML);
                }

                this.element = element;

                if (!this.insertMode) {
                    this.setupContent(element);
                }
            }
        };
    }
);
<|endoftext|>


<commit_before>define(['jquery'], function($) {

	var Slider = function() { this.initialize.apply(this, arguments) }
	Slider.prototype = {

		initialize: function(slider,deckView,fullCard) {
			//to force scroller on view and review modes thumbnails
			//regardles of monitor size. Homepage or "dashboard" set to false
			if (typeof deckView === "undefined" || typeof fullCard === "undefined")
			{
				this.deckView = false;
				this.fullCard = false;
			}
			else
			{
				this.deckView = deckView;
				this.fullCard = fullCard;
			}

			this.ul = slider.children[0]
			if (!this.ul){
				return;
			}

			//set the li's
			this.li = this.ul.children
			// get the border width for the li's
			// parseInt removes the px, toString makes sure it's a string
			this.liborder = parseInt($(this.li).css('border-left-width')).toString();

			this.currentIndex = 0;

		    this.counter = 0;

			this.totalLi = this.li.length;
			this.clickCealing;

			this.slideAmmount = 0;
			this.slideUnit = '%';
			this.border = 0;
			this.liMargin = 0;

			//show the first card on load
			this.showCard(this.currentIndex);
			//give the first card an active class
			$(this.li).eq(this.currentIndex).addClass('clicked');

		    this.respond();
		},

	    hideAll: function(){
	        $("ul#allCards li").removeClass("show").addClass("hide");
	        $("ul#cards li").removeClass("clicked");
	    },

		goTo: function(index) {
			// filter invalid indices
			if (index < 0 || index > this.li.length - 1 )
			return

			// move <ul> left
			this.ul.style.left = '-' + (this.slideAmmount * index) + this.slideUnit;

			this.cardCounter();
		},

		goToPrev: function() {
		    if ( this.deckView && this.counter > 0 )
			{
				var curr = this.getScardDataAttr(this.counter);
			    this.counter = this.counter - 1;
				var prev = this.getScardDataAttr(this.counter);
				this.hideCard(curr);
				this.showCard(prev);
				this.changeHighlight(curr, prev);
			}
			this.goTo(this.counter);
		},

        getScardDataAttr: function(id){
            card =  document.getElementById(id).children[0];
            return Number(card.getAttribute('data-scard'))
        },

		goToNext: function() {

			if ( this.deckView && this.counter < this.totalLi)
			{
				var curr = this.getScardDataAttr(this.counter);
			    this.counter = this.counter + 1;
				var nxt = this.getScardDataAttr(this.counter);
				this.hideCard(curr);
				this.showCard(nxt);
				this.changeHighlight(curr, nxt);
			}
			this.goTo(this.counter);

		},
	    getSliderCardByData: function(index){
	        return $($("ul#cards").find("[data-scard='" + index + "']")[0]);
	    },

		changeHighlight: function(current, newcard){
	        this.getSliderCardByData(current).parent().removeClass("clicked");
			this.getSliderCardByData(newcard).parent().addClass("clicked");

		},

		goToFirst: function(){
			this.hideCard(this.currentIndex);
			var index = this.getScardDataAttr(0);
			this.showCard(index);
			this.changeHighlight(this.currentIndex, index);
			this.currentIndex = index;
			this.goTo(0);
		},

		goToLast: function(){
			this.hideCard(this.currentIndex);
			var index = this.getScardDataAttr(this.totalLi-1);
			this.showCard(index);
			this.changeHighlight(this.currentIndex, index);
			this.currentIndex = index;
			this.goTo(this.totalLi-1);
		},

	    getCardByData: function(index){
	        return $($("#allCards").find("[data-card='" + index + "']")[0]);
	    },

		showCard: function(index){
			this.getCardByData(index).removeClass('hide').addClass('show');

		},

		hideCard: function(index){
			document.getElementById(index).children[0].blur();
			this.getCardByData(index).removeClass('show').addClass('hide');
		},

		goToCard: function(card){
			this.hideCard(this.currentIndex);
			this.showCard(card);
			this.changeHighlight(this.currentIndex, card);
			this.currentIndex = card;

			this.cardCounter();
		},

		cardCounter: function(){
			if ( this.deckView )
			{
			var counter = document.getElementById("counter");
			this.counter = Number($('.clicked').attr('id'));
			counter.innerHTML = (this.counter + 1) + "/" + this.totalLi;
			}
		},

		respond: function(){
			//iphone portrait	= screen and (min-width: 320px)
			//iphone landscape	= screen and (min-width: 480px)
			//ipad portrait		= screen and (min-width: 768px)
			//desktop			= screen and (min-width: 1024px)
			var oneCard = checkMediaQuery("screen and (min-width: 280px) and (max-width: 320px)");
			var twoCards = checkMediaQuery("screen and (min-width: 321px) and (max-width: 480px)");
			var threeCards = checkMediaQuery("screen and (min-width: 481px) and (max-width: 680px)");
			var fourCards = checkMediaQuery("screen and (min-width: 680px) and (max-width: 1023px)");
			var desktop = checkMediaQuery("screen and (min-width: 1024px)");

			var ulwidth, rspLiWidth, liMargin, ipad, liToShow, borderAmmount, slideWindow, respCards;
			respCards = false;
			if (twoCards)
			{
				liToShow = 2;
				slideWindow = 2;
				respCards = true;
			}
			else if(threeCards)
			{
				liToShow = 3;
				slideWindow = 3;
				respCards = true;
			}
			else if(fourCards || this.deckView)
			{
				liToShow = 4;
				slideWindow = 4;
				respCards = true;
			}

			//border width of scroller li
			borderAmmount = this.liborder;

			var sliderContext = $(this.ul).parent().width();
			//total list item
			var totalLI = this.li.length;
			//li's borders to get added to the ul width
			var liBorders = borderAmmount * totalLI;
			//set a li margin only to be use with ipad
			liMargin = 30;
			this.liMargin = liMargin;
			//li to show on ipad view
			//liToShow = this.liToShow;

			//var mq = window.matchMedia("(min-width: 768px) and (max-width: 1024px)");

			if ((twoCards || threeCards || fourCards || this.deckView) && !(this.fullCard)) //(mq.matches || this.deckView)
			{
				var respUnits = new RespondObj(sliderContext,liMargin,liToShow,this.totalLi,slideWindow, borderAmmount);

				rspLiWidth = respUnits.rspLiWidthAndUnit;
				this.slideAmmount = respUnits.slideAmmount;
				this.slideUnit = respUnits.slideUnit;
				this.ul.style.width = respUnits.ulWidth;
				this.clickCealing = respUnits.clickCealing;

				ipad = true;
				this.goTo(this.currentIndex);//stay in current index when flipping screen
			}
			else if (oneCard)
			{
				//give the UL a new width to accomodate all the li's plus their margins
				ulwidth = (sliderContext * totalLI);
				this.ul.style.width = ( ulwidth + liBorders ) + 'px';
				rspLiWidth = sliderContext-2 + 'px';//width of li
				//ammount to slide: in this 100 since ther is only one card
				this.slideAmmount = 100;
				this.slideUnit = '%';

				this.clickCealing = this.totalLi - 1;
				ipad = false;
				this.goTo(this.currentIndex);//stay in current index when flipping screen
			}
			else if ((oneCard || twoCards || threeCards || this.deckView) && (this.fullCard))
			{
				//give the UL a new width to accomodate all the li's plus their margins
				ulwidth = (sliderContext * totalLI);
				this.ul.style.width = ( ulwidth + liBorders ) + 'px';
				rspLiWidth = sliderContext-2 + 'px';//width of li
				//ammount to slide: in this 100 since ther is only one card
				this.slideAmmount = 100;
				this.slideUnit = '%';

				this.clickCealing = this.totalLi - 1;
			}

			var lastLI = totalLI - 1;
			//apply styles to each li
			for(i=0; i < totalLI; i++)
			{
				this.li[i].style.width = rspLiWidth;//taking 2px away because of borders
				this.li[i].style.clear = 'none';
				if (ipad){
					this.li[i].style.marginRight = liMargin + 'px';
				}else{
					this.li[i].style.marginRight = 0;
				}
			}
			//end for

		},
		resetUL: function(){
			$(this.ul).removeAttr('style');
			for(i=0; i < this.li.length; i++)
			{
				$(this.li[i]).removeAttr('style');
			}
		}
	}

	function RespondObj(sliderContext,liMargin,liToShow,totalLI,slideWindow, borderSize) {
		//multiply by liMargin by 2 because we only need two margins to show
		//take away 2 pixels for css borders
		this.rspLiWidth = Math.floor( (sliderContext - ((slideWindow-1) * liMargin) - ((borderSize * 2) * slideWindow)) / liToShow) ;
		//for sliding ammount purposes: adding the width of card plus margin we can move 1 at a time
		this.slideAmmount = this.rspLiWidth + liMargin + (borderSize * 2);
		this.slideUnit  = 'px';
		//width of container UL slider
		this.ulWidth = ((this.rspLiWidth + liMargin + borderSize) * totalLI) - liMargin + 'px';
		this.rspLiWidthAndUnit = this.rspLiWidth + 'px';
		//set a max for ipad
		this.clickCealing = totalLI - slideWindow;
	}

	/*
		takes in mq = media query to be checked
		returns true/false
	*/
	function checkMediaQuery(mq)
	{
		var mediaQuery = window.matchMedia(mq)
		if ( mediaQuery.matches )
			return true;
		else
			return false;
	}
	/*
		ele = html element
		prop = css property that you are after
		returns the css value but checks if the last two characters are 'px'
		if they are, they get removed so we can have a numeric value
	*/
	function getCSSprop(ele, prop)
	{
		var value = ele.css(prop);
		if ( value.slice(-2) == 'px' )
			return value.slice(0,-2);
		else
			return value;
	}

	return Slider;

});
<commit_msg>shuffle functionally fully working now<commit_after>define(['jquery'], function($) {

	var Slider = function() { this.initialize.apply(this, arguments) }
	Slider.prototype = {

		initialize: function(slider,deckView,fullCard) {
			//to force scroller on view and review modes thumbnails
			//regardles of monitor size. Homepage or "dashboard" set to false
			if (typeof deckView === "undefined" || typeof fullCard === "undefined")
			{
				this.deckView = false;
				this.fullCard = false;
			}
			else
			{
				this.deckView = deckView;
				this.fullCard = fullCard;
			}

			this.ul = slider.children[0]
			if (!this.ul){
				return;
			}

			//set the li's
			this.li = this.ul.children
			// get the border width for the li's
			// parseInt removes the px, toString makes sure it's a string
			this.liborder = parseInt($(this.li).css('border-left-width')).toString();

			this.currentIndex = 0;

		    this.counter = 0;

			this.totalLi = this.li.length;
			this.clickCealing;

			this.slideAmmount = 0;
			this.slideUnit = '%';
			this.border = 0;
			this.liMargin = 0;

			//show the first card on load
			this.showCard(this.currentIndex);
			//give the first card an active class
			$(this.li).eq(this.currentIndex).addClass('clicked');

		    this.respond();
		},

	    hideAll: function(){
	        $("ul#allCards li").removeClass("show").addClass("hide");
	        $("ul#cards li").removeClass("clicked");
	    },

		goTo: function(index) {
			// filter invalid indices
			if (index < 0 || index > this.li.length - 1 )
			return

			// move <ul> left
			this.ul.style.left = '-' + (this.slideAmmount * index) + this.slideUnit;

			this.cardCounter();
		},

		goToPrev: function() {
		    if ( this.deckView && this.counter > 0 )
			{
				var curr = this.getScardDataAttr(this.counter);
			    this.counter = this.counter - 1;
				var prev = this.getScardDataAttr(this.counter);
				this.hideCard(curr);
				this.showCard(prev);
				this.changeHighlight(curr, prev);
			}
			this.goTo(this.counter);
		},

        getScardDataAttr: function(id){
            card =  document.getElementById(id).children[0];
            return Number(card.getAttribute('data-scard'))
        },

		goToNext: function() {

			if ( this.deckView && this.counter < this.totalLi-1)
			{
				var curr = this.getScardDataAttr(this.counter);
			    this.counter = this.counter + 1;
				var nxt = this.getScardDataAttr(this.counter);
				this.hideCard(curr);
				this.showCard(nxt);
				this.changeHighlight(curr, nxt);
			}
			this.goTo(this.counter);

		},
	    getSliderCardByData: function(index){
	        return $($("ul#cards").find("[data-scard='" + index + "']")[0]);
	    },

		changeHighlight: function(current, newcard){
	        this.getSliderCardByData(current).parent().removeClass("clicked");
			this.getSliderCardByData(newcard).parent().addClass("clicked");

		},

		goToFirst: function(){
			this.hideCard(this.currentIndex);
			var index = this.getScardDataAttr(0);
			this.showCard(index);
			this.changeHighlight(this.currentIndex, index);
			this.currentIndex = index;
			this.goTo(0);
		},

		goToLast: function(){
			this.hideCard(this.currentIndex);
			var index = this.getScardDataAttr(this.totalLi-1);
			this.showCard(index);
			this.changeHighlight(this.currentIndex, index);
			this.currentIndex = index;
			this.goTo(this.totalLi-1);
		},

	    getCardByData: function(index){
	        return $($("#allCards").find("[data-card='" + index + "']")[0]);
	    },

		showCard: function(index){
			this.getCardByData(index).removeClass('hide').addClass('show');

		},

		hideCard: function(index){
			document.getElementById(index).children[0].blur();
			this.getCardByData(index).removeClass('show').addClass('hide');
		},

		goToCard: function(card){
			this.hideCard(this.currentIndex);
			this.showCard(card);
			this.changeHighlight(this.currentIndex, card);
			this.currentIndex = card;

			this.cardCounter();
		},

		cardCounter: function(){
			if ( this.deckView )
			{
			var counter = document.getElementById("counter");
			this.counter = Number($('.clicked').attr('id'));
			counter.innerHTML = (this.counter + 1) + "/" + this.totalLi;
			}
		},

		respond: function(){
			//iphone portrait	= screen and (min-width: 320px)
			//iphone landscape	= screen and (min-width: 480px)
			//ipad portrait		= screen and (min-width: 768px)
			//desktop			= screen and (min-width: 1024px)
			var oneCard = checkMediaQuery("screen and (min-width: 280px) and (max-width: 320px)");
			var twoCards = checkMediaQuery("screen and (min-width: 321px) and (max-width: 480px)");
			var threeCards = checkMediaQuery("screen and (min-width: 481px) and (max-width: 680px)");
			var fourCards = checkMediaQuery("screen and (min-width: 680px) and (max-width: 1023px)");
			var desktop = checkMediaQuery("screen and (min-width: 1024px)");

			var ulwidth, rspLiWidth, liMargin, ipad, liToShow, borderAmmount, slideWindow, respCards;
			respCards = false;
			if (twoCards)
			{
				liToShow = 2;
				slideWindow = 2;
				respCards = true;
			}
			else if(threeCards)
			{
				liToShow = 3;
				slideWindow = 3;
				respCards = true;
			}
			else if(fourCards || this.deckView)
			{
				liToShow = 4;
				slideWindow = 4;
				respCards = true;
			}

			//border width of scroller li
			borderAmmount = this.liborder;

			var sliderContext = $(this.ul).parent().width();
			//total list item
			var totalLI = this.li.length;
			//li's borders to get added to the ul width
			var liBorders = borderAmmount * totalLI;
			//set a li margin only to be use with ipad
			liMargin = 30;
			this.liMargin = liMargin;
			//li to show on ipad view
			//liToShow = this.liToShow;

			//var mq = window.matchMedia("(min-width: 768px) and (max-width: 1024px)");

			if ((twoCards || threeCards || fourCards || this.deckView) && !(this.fullCard)) //(mq.matches || this.deckView)
			{
				var respUnits = new RespondObj(sliderContext,liMargin,liToShow,this.totalLi,slideWindow, borderAmmount);

				rspLiWidth = respUnits.rspLiWidthAndUnit;
				this.slideAmmount = respUnits.slideAmmount;
				this.slideUnit = respUnits.slideUnit;
				this.ul.style.width = respUnits.ulWidth;
				this.clickCealing = respUnits.clickCealing;

				ipad = true;
				this.goTo(this.currentIndex);//stay in current index when flipping screen
			}
			else if (oneCard)
			{
				//give the UL a new width to accomodate all the li's plus their margins
				ulwidth = (sliderContext * totalLI);
				this.ul.style.width = ( ulwidth + liBorders ) + 'px';
				rspLiWidth = sliderContext-2 + 'px';//width of li
				//ammount to slide: in this 100 since ther is only one card
				this.slideAmmount = 100;
				this.slideUnit = '%';

				this.clickCealing = this.totalLi - 1;
				ipad = false;
				this.goTo(this.currentIndex);//stay in current index when flipping screen
			}
			else if ((oneCard || twoCards || threeCards || this.deckView) && (this.fullCard))
			{
				//give the UL a new width to accomodate all the li's plus their margins
				ulwidth = (sliderContext * totalLI);
				this.ul.style.width = ( ulwidth + liBorders ) + 'px';
				rspLiWidth = sliderContext-2 + 'px';//width of li
				//ammount to slide: in this 100 since ther is only one card
				this.slideAmmount = 100;
				this.slideUnit = '%';

				this.clickCealing = this.totalLi - 1;
			}

			var lastLI = totalLI - 1;
			//apply styles to each li
			for(i=0; i < totalLI; i++)
			{
				this.li[i].style.width = rspLiWidth;//taking 2px away because of borders
				this.li[i].style.clear = 'none';
				if (ipad){
					this.li[i].style.marginRight = liMargin + 'px';
				}else{
					this.li[i].style.marginRight = 0;
				}
			}
			//end for

		},
		resetUL: function(){
			$(this.ul).removeAttr('style');
			for(i=0; i < this.li.length; i++)
			{
				$(this.li[i]).removeAttr('style');
			}
		}
	}

	function RespondObj(sliderContext,liMargin,liToShow,totalLI,slideWindow, borderSize) {
		//multiply by liMargin by 2 because we only need two margins to show
		//take away 2 pixels for css borders
		this.rspLiWidth = Math.floor( (sliderContext - ((slideWindow-1) * liMargin) - ((borderSize * 2) * slideWindow)) / liToShow) ;
		//for sliding ammount purposes: adding the width of card plus margin we can move 1 at a time
		this.slideAmmount = this.rspLiWidth + liMargin + (borderSize * 2);
		this.slideUnit  = 'px';
		//width of container UL slider
		this.ulWidth = ((this.rspLiWidth + liMargin + borderSize) * totalLI) - liMargin + 'px';
		this.rspLiWidthAndUnit = this.rspLiWidth + 'px';
		//set a max for ipad
		this.clickCealing = totalLI - slideWindow;
	}

	/*
		takes in mq = media query to be checked
		returns true/false
	*/
	function checkMediaQuery(mq)
	{
		var mediaQuery = window.matchMedia(mq)
		if ( mediaQuery.matches )
			return true;
		else
			return false;
	}
	/*
		ele = html element
		prop = css property that you are after
		returns the css value but checks if the last two characters are 'px'
		if they are, they get removed so we can have a numeric value
	*/
	function getCSSprop(ele, prop)
	{
		var value = ele.css(prop);
		if ( value.slice(-2) == 'px' )
			return value.slice(0,-2);
		else
			return value;
	}

	return Slider;

});
<|endoftext|>


<commit_before>//System.paths['*'] = '../lively4-projectional-editor/node_modules/';
//console.log("ASDF");
//console.log(System.paths);
import * as babylon from '../lively4-projectional-editor/node_modules/babylon/lib/index.js';
//import * as types from "../lively4-projectional-editor/node_modules/babel-types/lib/index.js";

/*oldBaseURL = System.baseURL;
System.baseURL = 'https://lively-kernel.org/lively4/lively4-projectional-editor/';
import * as babylon from 'babylon/lib/index.js';
System.baseURL = oldBaseURL;
*/
//delete System.paths['*'];
//import * as generator from '../lively4-projectional-editor/node_modules/babel-generator/lib/index.js';
//import generate from "babel-generator";
//import traverse from "babel-traverse";
//import * as t from "babel-types";
//import * as bt from "./blockly-tools";

const transformCodeOnClick = function(source_id, button_id, target_id) {
  $('#' + button_id).on('click', function() {
      const code_source = $('#' + source_id);
      const target = $('#' + target_id);

      const ast = babylon.parse(code_source.val());
      target.text(JSON.stringify(ast.program, undefined, 4));
    });
}

export { transformCodeOnClick };<commit_msg>SQUASHED: SQUASHED-AUTO-COMMIT-babel-test.js,<commit_after>//System.paths['*'] = '../lively4-projectional-editor/node_modules/';
//console.log("ASDF");
//console.log(System.paths);
//import * as babylon from '../lively4-projectional-editor/node_modules/babylon/lib/index.js';
//import * as types from "../lively4-projectional-editor/node_modules/babel-types/lib/index.js";

/*oldBaseURL = System.baseURL;
System.baseURL = 'https://lively-kernel.org/lively4/lively4-projectional-editor/';
import * as babylon from 'babylon/lib/index.js';
System.baseURL = oldBaseURL;
*/
//delete System.paths['*'];
//import * as generator from '../lively4-projectional-editor/node_modules/babel-generator/lib/index.js';
//import generate from "babel-generator";
//import traverse from "babel-traverse";
//import * as t from "babel-types";
//import * as bt from "./blockly-tools";

import * as deps from '../lively4-projectional-editor/dependencies.js';
console.log("DEPS");
console.log(deps);

const transformCodeOnClick = function(source_id, button_id, target_id) {
  $('#' + button_id).on('click', function() {
      const code_source = $('#' + source_id);
      const target = $('#' + target_id);

      const ast = babylon.parse(code_source.val());
      target.text(JSON.stringify(ast.program, undefined, 4));
    });
}

export { transformCodeOnClick };<|endoftext|>


<commit_before>/**
 * This is a reducer, a pure function with (state, action) => state signature.
 * It describes how an action transforms the state into the next state.
 *
 * The shape of the state is up to you: it can be a primitive, an array, an object,
 * or even an Immutable.js data structure. The only important part is that you should
 * not mutate the state object, but return a new object if the state changes.
 *
 * In this example, we use a `switch` statement and strings, but you can use a helper that
 * follows a different convention (such as function maps) if it makes sense for your
 * project.
 */

// Load all generic data needed.
import appData from '../appData.js'

// TODO load from localStorage if exists? merge? clobber?
// This is default character data structure for a new character,
// before random allocations.
import charData from '../../data/char.json'

const initialState = {
  app: appData,
  char: charData
}

/**
 * Work with arrays of strings or arrays of options.
 * TODO Handle non-singular results (i.e. 20 options for a 1d20 roll).
 */
const getRandomItem = (array) => {
  let val = array[Math.floor(Math.random() * array.length)]
  return val.value || val
}

const setAncestryData = (state) => {
  // Now we know the ancestry, we can work everything else out.
  let ancestryData = state.app[state.char.ancestry.toLowerCase()]

  state.char.name = getRandomItem(ancestryData.commonNames)
  state.char.background = getRandomItem(ancestryData.background)

  state.char.attributes = Object.assign({}, ancestryData.attributes)
}

const initRandomCharacter = (state) => {
  console.error('FIXME forcing ancestry to Human/Orc during dev.');
  state.char.ancestry = getRandomItem(['Human', 'Orc'])
  // state.char.ancestry = getRandomItem(state.app.ancestries)
  setAncestryData(state)
}

// Init new characters with random values.
initRandomCharacter(initialState)

// root reducer
// TODO split this up into smaller parts as I develop the app.
export default function charGen (state = initialState, action) {
  let newState = {
    app: Object.assign({}, state.app),
    char: Object.assign({}, state.char)
  }

  switch (action.type) {
    case 'CREATE_RANDOM':
      initRandomCharacter(newState)
      break
    case 'CHANGE_ANCESTRY':
      newState.char.ancestry = action.value
      setAncestryData(newState)
      break
    case 'CHANGE_SIMPLE_VALUE':
      newState.char[action.name] = action.value
      break
  }

  console.log('newState:', newState)

  return newState
}
<commit_msg>Linting.<commit_after>/**
 * This is a reducer, a pure function with (state, action) => state signature.
 * It describes how an action transforms the state into the next state.
 *
 * The shape of the state is up to you: it can be a primitive, an array, an object,
 * or even an Immutable.js data structure. The only important part is that you should
 * not mutate the state object, but return a new object if the state changes.
 *
 * In this example, we use a `switch` statement and strings, but you can use a helper that
 * follows a different convention (such as function maps) if it makes sense for your
 * project.
 */

// Load all generic data needed.
import appData from '../appData.js'

// TODO load from localStorage if exists? merge? clobber?
// This is default character data structure for a new character,
// before random allocations.
import charData from '../../data/char.json'

const initialState = {
  app: appData,
  char: charData
}

/**
 * Work with arrays of strings or arrays of options.
 * TODO Handle non-singular results (i.e. 20 options for a 1d20 roll).
 */
const getRandomItem = (array) => {
  let val = array[Math.floor(Math.random() * array.length)]
  return val.value || val
}

const setAncestryData = (state) => {
  // Now we know the ancestry, we can work everything else out.
  let ancestryData = state.app[state.char.ancestry.toLowerCase()]

  state.char.name = getRandomItem(ancestryData.commonNames)
  state.char.background = getRandomItem(ancestryData.background)

  state.char.attributes = Object.assign({}, ancestryData.attributes)
}

const initRandomCharacter = (state) => {
  console.error('FIXME forcing ancestry to Human/Orc during dev.')
  state.char.ancestry = getRandomItem(['Human', 'Orc'])
  // state.char.ancestry = getRandomItem(state.app.ancestries)
  setAncestryData(state)
}

// Init new characters with random values.
initRandomCharacter(initialState)

// root reducer
// TODO split this up into smaller parts as I develop the app.
export default function charGen (state = initialState, action) {
  let newState = {
    app: Object.assign({}, state.app),
    char: Object.assign({}, state.char)
  }

  switch (action.type) {
    case 'CREATE_RANDOM':
      initRandomCharacter(newState)
      break
    case 'CHANGE_ANCESTRY':
      newState.char.ancestry = action.value
      setAncestryData(newState)
      break
    case 'CHANGE_SIMPLE_VALUE':
      newState.char[action.name] = action.value
      break
  }

  console.log('newState:', newState)

  return newState
}
<|endoftext|>


<commit_before>//
// Parity
// Author:  Abe Fehr
// Version: 0.1
//

$(document).ready(function() {

  //all the page objects
  var resetLink = $('#reset');
  var levelText = $('#level');
  var overlay   = $('#overlay');
  var button    = $('#overlay > #holder > button');
  var board     = $('#board');
  var cells = [];
  for(var i=0;i<4;++i) {
    cells.push([]);
    for(var j=0;j<4;++j) {
      cells[i].push($('td[data-x="' + i + '"][data-y="' + j + '"]'));
    }
  }

  //the bookmark in the story of the game
  var bookmark = 0;

  var options = {
    fade: 300
  }

  //where we'll store the current level
  var level;

  //where we'll store the instructions and the levels
  var story;

  $(document).keydown(function(e){
    if(story[bookmark].type == 'level') {
      if(e.keyCode == 37) {
        left();
        return false;
      }
      if(e.keyCode == 38) {
        up();
        return false;
      }
      if(e.keyCode == 39) {
        right();
        return false;
      }
      if(e.keyCode == 40) {
        down();
        return false;
      }
    }
    else if(story[bookmark].type == 'overlay') {
      if(e.keyCode == 32) {
        button.trigger('click');
      }
    }
  });

  //selects the cell to the left of the current cell
  function left() {
    if(level.selected.x > 0) {
      select(--level.selected.x, level.selected.y);
      update();
    }
  }

  //selects the cell above the current cell
  function up() {
    if(level.selected.y > 0) {
      select(level.selected.x, --level.selected.y);
      update();
    }
  }

  //selects the cell to the right of the current cell
  function right() {
    if(level.selected.x < 3) {
      select(++level.selected.x, level.selected.y);
      update();
    }
  }

  //selects the cell under the current cell
  function down() {
    if(level.selected.y < 3) {
      select(level.selected.x, ++level.selected.y);
      update();
    }
  }

  //selects a cell and increases its value
  function select(x, y) {
    //increase the number in the selected cell
    cell(level.selected.x, level.selected.y, cell(level.selected.x, level.selected.y)+1);
  }

  // goes through the model(the story), draws the board accordingly,
  // and checks if it's a win scenario
  function update() {
    if(story[bookmark].type == 'level') {
      //go through the board and clear it of all the "selected" classes
      $('td.selected').removeClass('selected');

      console.log(level.selected);

      cells[level.selected.x][level.selected.y].addClass('selected');

      //check if it's a win
      if(isWin()) {
        advanceStory();
      }
    }
  }

  // gets the level in the current page of the story, parses
  // it, and puts it in the grid
  function loadScreen() {
    if(story[bookmark].type == 'level') {
      if(story[bookmark].contents == 'generated') {
        //generate a level
        data = generate(story[bookmark]);
        loadLevel(data);
      }
      else {
        loadLevel(story[bookmark]);
      }
    }
    else if(story[bookmark].type == 'overlay') {
      //get the current slide that the overlay is on
      if(!story[bookmark].current)
        story[bookmark].current = 0;
      var slide = story[bookmark].current;

      //put the text from the thingy into the overlay
      var title   = story[bookmark].contents[slide].title;
      var content = story[bookmark].contents[slide].content;
      var action  = story[bookmark].contents[slide].button;

      $('#overlay > h1').html(title);
      $('#overlay > p').html(content);
      button.html(action);

      overlay.fadeIn(options['fade']);
    }

    update();
  }

  //validation function to be used later
  function valid(direction, x, y) {
    switch(direction) {
      case 0:
        return false;
      case 1: //north
        if(y == 0) {
          return false;
        }
      case 2: //east
        if(x == 3) {
          return false;
        }
      case 3: //south
        if(y == 3) {
          return false;
        }
      case 4: //west
        if(x == 0) {
          return false;
        }
    }
    return true;
  }

  //generates a level
  function generate(level) {
    //create a new object
    //create an array for the level data
    var content = [];

    //push the initial value into the array that number of times
    for(var i=0;i<16;++i) {
      content.push(level.schema.end);
    }

    //generate a random number of steps in the bounds
    var moveRange = level.schema.maxNumMoves - level.schema.minNumMoves;
    var numMoves = level.schema.minNumMoves + Math.random()*(moveRange);

    //generate a random starting location
    var x = Math.floor(Math.random()*4);
    var y = Math.floor(Math.random()*4);

    //loop through all the moves
    for(var i=0;i<numMoves;++i) {
      //for each time, move the coordinates by one in a random direction...
      var direction = 0; //initialize it to 0(impossible)
      while(!valid(direction)) {
        direction = Math.floor(Math.random()*4);
      }
      //at this point, the direction is valid so we're just moving it one
      switch(direction) {
        case 1: //north
          --content[y*4+x];
          --y;
          break;
        case 2: //east
          --content[y*4+x];
          ++x;
          break;
        case 3: //south
          --content[y*4+x];
          ++y;
          break;
        case 4: //west
          --content[y*4+x];
          --x;
          break;
      }
    }

    return {
      type: level.type,
      number: level.number,
      contents: content,
      initialSelected: { x: x, y: y }
    };
  }

  //loads a level
  function loadLevel(data) {
    level = data;
    for(var i=0;i<level.contents.length;++i) {
      cell(i%4,Math.floor(i/4),level.contents[i]);
    }

    level.selected = level.initialSelected;
    console.log(level.selected);

    //put the level number in the corner
    levelText.html("level " + level.number + "/" + numLevels());

    //fade in the level
    board.fadeIn(options['fade']);

  }

  //resets the board back to the level's beginning
  function reset() {
    loadScreen();
  }

  //checks to see if there's a win condition or not
  //returns: boolean
  function isWin() {
    var value = cell(0,0);
    for(var i=0;i<4;++i) {
      for(var j=0;j<4;++j) {
        if(cell(i,j) != value)
          return false
      }
    }
    return true;
  }

  //gets or sets a cells
  //input: -the x/y location of a cell
  //       -the value to put into the cell(optional)
  //returns: -the contents of the cell(if no value is given)
  //         -nothing, if a value is given
  function cell(x, y, value) {
    //either gets the contents of x, y or sets them
    if(arguments.length==3) {
      console.log(x + ", " + y);
      cells[x][y].html(value);
    }
    else {
      //return the value
      return parseInt(cells[x][y].html());
    }
  }

  //starts the game by initializing the level text and displaying
  //the first level
  function start() {
    //put the level number in the corner
    levelText.html("level 0/" + numLevels());
    loadScreen();
  }

  //fades out the board
  //input: -the callback to call when the fade is completed
  function fadeOut(callback) {
    if(board.is(':visible'))
      board.fadeOut(options['fade'], callback);
    if(overlay.is(':visible'))
      overlay.fadeOut(options['fade'], callback);
  }

  //tries to advance the story
  function advanceStory() {
    //tries to advance the current slide first if it's an overlay
    if(story[bookmark].type == 'overlay') {
      if(++story[bookmark].current < story[bookmark].contents.length) {
          fadeOut(loadScreen);
          return;
      }
    }
    if(++bookmark < story.length) {
      fadeOut(loadScreen);
    }
    else {
      //show the end
      end();
    }
  }

  //gets the number of levels in the story
  function numLevels() {
    //go through the stuff in the story
    var sum = 0;
    for(var i=0;i<story.length;++i) {
      if(story[i].type=='level') {
        ++sum;
      }
    }
    return sum;
  }

  //what happens when the game is finished
  function end() {
    alert('the end!');
  }

  //event assignments
  button.click(advanceStory);
  resetLink.click(reset);

  //start the game off by getting the story
  $.getJSON('story.json', function(data) {
    story = data;
    start();
  });
});
<commit_msg>resized the board, fixed reset<commit_after>//
// Parity
// Author:  Abe Fehr
// Version: 0.1
//

$(document).ready(function() {

  //all the page objects
  var resetLink = $('#reset');
  var levelText = $('#level');
  var overlay   = $('#overlay');
  var button    = $('#overlay > #holder > button');
  var board     = $('#board');
  var cells = [];
  for(var i=0;i<4;++i) {
    cells.push([]);
    for(var j=0;j<4;++j) {
      cells[i].push($('td[data-x="' + i + '"][data-y="' + j + '"]'));
    }
  }

  //the bookmark in the story of the game
  var bookmark = 0;

  var options = {
    fade: 300 //the time in ms for the fade
  }

  //where we'll store the current level
  var level;

  //where we'll store the instructions and the levels
  var story;

  $(document).keydown(function(e){
    if(story[bookmark].type == 'level') {
      if(e.keyCode == 37) {
        left();
        return false;
      }
      if(e.keyCode == 38) {
        up();
        return false;
      }
      if(e.keyCode == 39) {
        right();
        return false;
      }
      if(e.keyCode == 40) {
        down();
        return false;
      }
    }
    else if(story[bookmark].type == 'overlay') {
      if(e.keyCode == 32) {
        button.trigger('click');
      }
    }
  });

  //selects the cell to the left of the current cell
  function left() {
    if(level.selected.x > 0) {
      select(--level.selected.x, level.selected.y);
      update();
    }
  }

  //selects the cell above the current cell
  function up() {
    if(level.selected.y > 0) {
      select(level.selected.x, --level.selected.y);
      update();
    }
  }

  //selects the cell to the right of the current cell
  function right() {
    if(level.selected.x < 2) {
      select(++level.selected.x, level.selected.y);
      update();
    }
  }

  //selects the cell under the current cell
  function down() {
    if(level.selected.y < 2) {
      select(level.selected.x, ++level.selected.y);
      update();
    }
  }

  //selects a cell and increases its value
  function select(x, y) {
    //increase the number in the selected cell
    cell(level.selected.x, level.selected.y, cell(level.selected.x, level.selected.y)+1);
  }

  // goes through the model(the story), draws the board accordingly,
  // and checks if it's a win scenario
  function update() {
    if(story[bookmark].type == 'level') {
      //go through the board and clear it of all the "selected" classes
      $('td.selected').removeClass('selected');

      cells[level.selected.x][level.selected.y].addClass('selected');

      //check if it's a win
      if(isWin()) {
        advanceStory();
      }
    }
  }

  // gets the current page of the story where the bookmark is, parses
  // it, and puts it in the grid
  function loadCurrentPage() {
    if(story[bookmark].type == 'level') {
      if(story[bookmark].contents == 'generated') {
        //generate a level
        data = generate(story[bookmark]);
        loadLevel(data);
      }
      else {
        loadLevel(story[bookmark]);
      }
    }
    else if(story[bookmark].type == 'overlay') {
      //get the current slide that the overlay is on
      if(!story[bookmark].current)
        story[bookmark].current = 0;
      var slide = story[bookmark].current;

      //put the text from the thingy into the overlay
      var title   = story[bookmark].contents[slide].title;
      var content = story[bookmark].contents[slide].content;
      var action  = story[bookmark].contents[slide].button;

      $('#overlay > h1').html(title);
      $('#overlay > p').html(content);
      button.html(action);

      overlay.fadeIn(options['fade']);
      update();
    }
  }

  //validation function to be used later
  function valid(direction, x, y) {
    switch(direction) {
      case 0:
        return false;
      case 1: //north
        if(y == 0) {
          return false;
        }
        return true;
      case 2: //east
        if(x == 2) {
          return false;
        }
        return true;
      case 3: //south
        if(y == 2) {
          return false;
        }
        return true;
      case 4: //west
        if(x == 0) {
          return false;
        }
        return true;
    }
  }

  //generates a level
  function generate(level) {
    //create a new object
    //create an array for the level data
    var content = [];

    //push the initial value into the array that number of times
    for(var i=0;i<9;++i) {
      content.push(level.schema.end);
    }

    //generate a random number of steps in the bounds
    var moveRange = level.schema.maxNumMoves - level.schema.minNumMoves;
    var numMoves = level.schema.minNumMoves + Math.random()*(moveRange);

    //generate a random starting location
    var x = Math.floor(Math.random()*3);
    var y = Math.floor(Math.random()*3);

    //loop through all the moves
    for(var i=0;i<numMoves;++i) {
      //for each time, move the coordinates by one in a random direction...
      var direction = 0; //initialize it to 0(non-real direction)
      while(!valid(direction, x, y)) {
        //generate a number between 1 and 4 inclusive
        direction = Math.floor(1 + Math.random()*4);
      }
      //at this point, the direction is valid so we're just moving it one
      switch(direction) {
        case 1: //north
          --content[y*3+x];
          --y;
          break;
        case 2: //east
          --content[y*3+x];
          ++x;
          break;
        case 3: //south
          --content[y*3+x];
          ++y;
          break;
        case 4: //west
          --content[y*3+x];
          --x;
          break;
      }
    }

    return {
      type: level.type,
      number: level.number,
      contents: content,
      initialSelected: { x: x, y: y }
    };
  }

  //loads a level
  function loadLevel(data) {
    //set the level data
    level = data;

    //parse its contents
    for(var i=0;i<level.contents.length;++i) {
      cell(i%3,Math.floor(i/3),level.contents[i]);
    }

    //set the currently selected cell
    level.selected = {
      x: data.initialSelected.x,
      y: data.initialSelected.y
    };

    //put the level number in the corner
    levelText.html("level " + level.number + "/" + numLevels());

    //fade in the level
    board.fadeIn(options['fade']);

    //update the screen
    update();
  }

  //resets the board back to the level's beginning
  function reset() {
    loadLevel(level);
  }

  //checks to see if there's a win condition or not
  //returns: boolean
  function isWin() {
    var value = cell(0,0);
    for(var i=0;i<3;++i) {
      for(var j=0;j<3;++j) {
        if(cell(i,j) != value)
          return false
      }
    }
    return true;
  }

  //gets or sets a cells
  //input: -the x/y location of a cell
  //       -the value to put into the cell(optional)
  //returns: -the contents of the cell(if no value is given)
  //         -nothing, if a value is given
  function cell(x, y, value) {
    //either gets the contents of x, y or sets them
    if(arguments.length==3) {
      cells[x][y].html(value);
    }
    else {
      //return the value
      return parseInt(cells[x][y].html());
    }
  }

  //starts the game by initializing the level text and displaying
  //the first level
  function start() {
    //put the level number in the corner
    levelText.html("level 0/" + numLevels());
    loadCurrentPage();
  }

  //fades out the board
  //input: -the callback to call when the fade is completed
  function fadeOut(callback) {
    //only fade out that visible component
    if(board.is(':visible'))
      board.fadeOut(options['fade'], callback);

    if(overlay.is(':visible'))
      overlay.fadeOut(options['fade'], callback);
  }

  //tries to advance the story
  function advanceStory() {
    //tries to advance the current slide first if it's an overlay
    if(story[bookmark].type == 'overlay') {
      if(++story[bookmark].current < story[bookmark].contents.length) {
          fadeOut(loadCurrentPage);
          return;
      }
    }

    if(++bookmark < story.length) {
      fadeOut(loadCurrentPage);
    }
    else {
      end();
    }
  }

  //gets the number of levels in the story
  function numLevels() {
    //go through the stuff in the story
    var sum = 0;
    for(var i=0;i<story.length;++i) {
      if(story[i].type=='level') {
        ++sum;
      }
    }
    return sum;
  }

  //what happens when the game is finished, still needs to be made
  function end() {
    alert('the end!');
  }

  //event assignments
  button.click(advanceStory);
  resetLink.click(reset);

  //start the game off by getting the story
  $.getJSON('story.json', function(data) {
    story = data;
    start();
  });
});
<|endoftext|>


<commit_before>/*
 * edit.js
 * Copyright (c) 2017 thegrumpydictator@gmail.com
 *
 * This file is part of Firefly III.
 *
 * Firefly III is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Firefly III 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
 */

/** global: what, Modernizr, selectsForeignCurrency, accountInfo, convertForeignToNative, validateCurrencyForTransfer, convertSourceToDestination, journalData, journal, accountInfo, exchangeRateInstructions, currencyInfo */

$(document).ready(function () {
    "use strict";
    console.log('in edit.js document.ready');
    setAutocompletes();
    updateInitialPage();

    // update the two source account currency ID fields (initial value):
    initCurrencyIdValues();

    // respond to user input:
    $('.currency-option').on('click', function () {
        // to display instructions and stuff like that.
        selectsForeignCurrency();
    });
    $('#ffInput_amount').on('change', convertForeignToNative);

    // respond to account changes:
    $('#ffInput_source_id').on('change', function (e) {
        console.log('Event: #ffInput_source_id::change');

        validateCurrencyForTransfer();
        // update the two source account currency ID fields (initial value):
        initCurrencyIdValues();

        // call to selectsForeignCurrency
        console.log('Extra call to selectsForeignCurrency()');
        selectsForeignCurrency();

        // update "source_account_currency".
        updateSourceAccountCurrency();

    });
    $('#ffInput_destination_id').on('change', function () {
        console.log('Event: #ffInput_destination_id::change');
        validateCurrencyForTransfer();
        // update the two source account currency ID fields (initial value):
        initCurrencyIdValues();

        // call to selectsForeignCurrency
        console.log('Extra call to selectsForeignCurrency()');
        selectsForeignCurrency();

        // update "destination_account_currency".
        updateDestinationAccountCurrency();

    });

    // convert source currency to destination currency (slightly different routine for transfers)
    $('#ffInput_source_amount').on('change', convertSourceToDestination);

    //

});

/**
 * Updates the currency ID of the hidden source account field
 * to match the selected account.
 */
function updateSourceAccountCurrency() {
    var accountId = $('#ffInput_source_id').val();
    var currency = parseInt(accountInfo[accountId].preferredCurrency);
    console.log('Now in updateSourceAccountCurrency() for account #' + accountId);
    console.log('Preferred currency for this account is #' + currency);
    $('input[name="source_account_currency"]').val(currency);
}

/**
 * Updates the currency ID of the hidden destination account field
 * to match the selected account.
 */
function updateDestinationAccountCurrency() {
    var accountId = $('#ffInput_destination_id').val();
    var currency = parseInt(accountInfo[accountId].preferredCurrency);
    console.log('Now in updateDestinationAccountCurrency() for account #' + accountId);
    console.log('Preferred currency for this account is #' + currency);
    $('input[name="destination_account_currency"]').val(currency);
}

/**
 * Fills two hidden variables with the correct currency ID.
 */
function initCurrencyIdValues() {
    console.log('in initCurrencyIdValues()');
    var currencyId;
    if (journal.transaction_type.type === "Withdrawal") {
        // update source from page load info:
        currencyId = journalData.native_currency.id;
        console.log('initCurrencyIdValues() withdrawal: Set source account currency to ' + currencyId);
        $('input[name="source_account_currency"]').val(currencyId);
        return;
    }

    if (journal.transaction_type.type === "Deposit") {
        // update destination from page load info:
        currencyId = $('input[name="amount_currency_id_amount"]').val();
        console.log('Set destination account currency to ' + currencyId);
        $('input[name="destination_account_currency"]').val(currencyId);
        return;
    }
    var sourceAccount = $('select[name="source_id"]').val();
    console.log('Source account is ' + sourceAccount);
    var destAccount = $('select[name="destination_id"]').val();
    console.log('Destination account is ' + destAccount);

    var sourceCurrency = parseInt(accountInfo[sourceAccount].preferredCurrency);
    var destCurrency = parseInt(accountInfo[destAccount].preferredCurrency);

    console.log('initCurrencyIdValues(): Set source account currency to ' + sourceCurrency);
    $('input[name="source_account_currency"]').val(sourceCurrency);

    console.log('Set destination account currency to ' + destCurrency);
    $('input[name="destination_account_currency"]').val(destCurrency);
}

/**
 * Set some initial values for the user to see.
 */
function updateInitialPage() {
    console.log('in updateInitialPage()');
    if (journal.transaction_type.type === "Transfer") {
        $('#native_amount_holder').hide();
        $('#amount_holder').hide();

        if (journalData.native_currency.id === journalData.destination_currency.id) {
            $('#exchange_rate_instruction_holder').hide();
            $('#destination_amount_holder').hide();
        }
        if (journalData.native_currency.id !== journalData.destination_currency.id) {
            $('#exchange_rate_instruction_holder').show().find('p').text(getTransferExchangeInstructions());

        }

        return;
    }
    $('#source_amount_holder').hide();
    $('#destination_amount_holder').hide();

    if (journalData.native_currency.id === journalData.currency.id) {
        $('#exchange_rate_instruction_holder').hide();
        $('#native_amount_holder').hide();
    }

    if (journalData.native_currency.id !== journalData.currency.id) {
        $('#ffInput_exchange_rate_instruction').text(getExchangeInstructions());
    }

}

/**
 * Get accountID based on some meta info.
 */
function getAccountId() {
    console.log('in getAccountId()');
    if (journal.transaction_type.type === "Withdrawal") {
        return $('select[name="source_id"]').val();
    }
    if (journal.transaction_type.type === "Deposit") {
        return $('select[name="destination_id"]').val();
    }

    alert('Cannot handle ' + journal.transaction_type.type);
    return undefined;
}

/**
 * Set the auto-complete JSON things.
 */
function setAutocompletes() {

    // do description auto complete:
    var journalNames = new Bloodhound({
                                          datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
                                          queryTokenizer: Bloodhound.tokenizers.whitespace,
                                          prefetch: {
                                              url: 'json/transaction-journals/' + what + '?uid=' + uid,
                                              filter: function (list) {
                                                  return $.map(list, function (name) {
                                                      return {name: name};
                                                  });
                                              }
                                          },
                                          remote: {
                                              url: 'json/transaction-journals/' + what + '?search=%QUERY&uid=' + uid,
                                              wildcard: '%QUERY',
                                              filter: function (list) {
                                                  return $.map(list, function (name) {
                                                      return {name: name};
                                                  });
                                              }
                                          }
                                      });
    journalNames.initialize();
    $('input[name="description"]').typeahead({hint: true, highlight: true,}, {source: journalNames, displayKey: 'name', autoSelect: false});
}

/**
 * This function generates a small helper text to explain the user
 * that they have selected a foreign currency.
 * @returns {XML|string|void}
 */
function getExchangeInstructions() {
    console.log('In getExchangeInstructions()');
    var selectedAccountId = getAccountId();
    var foreignCurrencyId = parseInt($('input[name="amount_currency_id_amount"]').val());
    var nativeCurrencyId = parseInt(accountInfo[selectedAccountId].preferredCurrency);

    var text = exchangeRateInstructions.replace('@name', accountInfo[selectedAccountId].name);
    text = text.replace(/@native_currency/g, currencyInfo[nativeCurrencyId].name);
    text = text.replace(/@foreign_currency/g, currencyInfo[foreignCurrencyId].name);
    return text;
}<commit_msg>Fix #1835<commit_after>/*
 * edit.js
 * Copyright (c) 2017 thegrumpydictator@gmail.com
 *
 * This file is part of Firefly III.
 *
 * Firefly III is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Firefly III 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
 */

/** global: what, Modernizr, selectsForeignCurrency, accountInfo, convertForeignToNative, validateCurrencyForTransfer, convertSourceToDestination, journalData, journal, accountInfo, exchangeRateInstructions, currencyInfo */

$(document).ready(function () {
    "use strict";
    console.log('in edit.js document.ready');
    setAutocompletes();
    updateInitialPage();

    // update the two source account currency ID fields (initial value):
    initCurrencyIdValues();

    // respond to user input:
    $('.currency-option').on('click', function () {
        // to display instructions and stuff like that.
        selectsForeignCurrency();
    });
    $('#ffInput_amount').on('change', convertForeignToNative);

    // respond to account changes:
    $('#ffInput_source_id').on('change', function (e) {
        console.log('Event: #ffInput_source_id::change');

        validateCurrencyForTransfer();
        // update the two source account currency ID fields (initial value):
        initCurrencyIdValues();

        // call to selectsForeignCurrency
        console.log('Extra call to selectsForeignCurrency()');
        selectsForeignCurrency();

        // update "source_account_currency".
        updateSourceAccountCurrency();

    });
    $('#ffInput_destination_id').on('change', function () {
        console.log('Event: #ffInput_destination_id::change');
        validateCurrencyForTransfer();
        // update the two source account currency ID fields (initial value):
        initCurrencyIdValues();

        // call to selectsForeignCurrency
        console.log('Extra call to selectsForeignCurrency()');
        selectsForeignCurrency();

        // update "destination_account_currency".
        updateDestinationAccountCurrency();

    });

    // convert source currency to destination currency (slightly different routine for transfers)
    $('#ffInput_source_amount').on('change', convertSourceToDestination);

    //

});

/**
 * Updates the currency ID of the hidden source account field
 * to match the selected account.
 */
function updateSourceAccountCurrency() {
    var accountId = $('#ffInput_source_id').val();
    var currency = parseInt(accountInfo[accountId].preferredCurrency);
    console.log('Now in updateSourceAccountCurrency() for account #' + accountId);
    console.log('Preferred currency for this account is #' + currency);
    $('input[name="source_account_currency"]').val(currency);
}

/**
 * Updates the currency ID of the hidden destination account field
 * to match the selected account.
 */
function updateDestinationAccountCurrency() {
    var accountId = $('#ffInput_destination_id').val();
    var currency = parseInt(accountInfo[accountId].preferredCurrency);
    console.log('Now in updateDestinationAccountCurrency() for account #' + accountId);
    console.log('Preferred currency for this account is #' + currency);
    $('input[name="destination_account_currency"]').val(currency);
}

/**
 * Fills two hidden variables with the correct currency ID.
 */
function initCurrencyIdValues() {
    console.log('in initCurrencyIdValues()');
    var currencyId;
    if (journal.transaction_type.type === "Withdrawal") {
        // update source from page load info:
        currencyId = journalData.native_currency.id;
        console.log('initCurrencyIdValues() withdrawal: Set source account currency to ' + currencyId);
        $('input[name="source_account_currency"]').val(currencyId);
        return;
    }

    if (journal.transaction_type.type === "Deposit") {
        // update destination from page load info:
        currencyId = $('input[name="amount_currency_id_amount"]').val();
        console.log('Set destination account currency to ' + currencyId);
        $('input[name="destination_account_currency"]').val(currencyId);
        return;
    }
    var sourceAccount = $('select[name="source_id"]').val();
    console.log('Source account is ' + sourceAccount);
    var destAccount = $('select[name="destination_id"]').val();
    console.log('Destination account is ' + destAccount);

    var sourceCurrency = parseInt(accountInfo[sourceAccount].preferredCurrency);
    var destCurrency = parseInt(accountInfo[destAccount].preferredCurrency);

    console.log('initCurrencyIdValues(): Set source account currency to ' + sourceCurrency);
    $('input[name="source_account_currency"]').val(sourceCurrency);

    console.log('Set destination account currency to ' + destCurrency);
    $('input[name="destination_account_currency"]').val(destCurrency);
}

/**
 * Set some initial values for the user to see.
 */
function updateInitialPage() {
    console.log('in updateInitialPage()');
    if (journal.transaction_type.type === "Transfer") {
        $('#native_amount_holder').hide();
        $('#amount_holder').hide();

        if (journalData.native_currency.id === journalData.destination_currency.id) {
            $('#exchange_rate_instruction_holder').hide();
            $('#destination_amount_holder').hide();
        }
        if (journalData.native_currency.id !== journalData.destination_currency.id) {
            $('#exchange_rate_instruction_holder').show().find('p').text(getTransferExchangeInstructions());

        }

        return;
    }
    $('#source_amount_holder').hide();
    $('#destination_amount_holder').hide();

    if (journalData.native_currency.id === journalData.currency.id) {
        $('#exchange_rate_instruction_holder').hide();
        $('#native_amount_holder').hide();
    }

    if (journalData.native_currency.id !== journalData.currency.id) {
        $('#ffInput_exchange_rate_instruction').text(getExchangeInstructions());
    }

}

/**
 * Get accountID based on some meta info.
 */
function getAccountId() {
    console.log('in getAccountId()');
    if (journal.transaction_type.type === "Withdrawal") {
        return $('select[name="source_id"]').val();
    }
    if (journal.transaction_type.type === "Deposit") {
        return $('select[name="destination_id"]').val();
    }

    //alert('Cannot handle ' + journal.transaction_type.type);
    return undefined;
}

/**
 * Set the auto-complete JSON things.
 */
function setAutocompletes() {

    // do description auto complete:
    var journalNames = new Bloodhound({
                                          datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
                                          queryTokenizer: Bloodhound.tokenizers.whitespace,
                                          prefetch: {
                                              url: 'json/transaction-journals/' + what + '?uid=' + uid,
                                              filter: function (list) {
                                                  return $.map(list, function (name) {
                                                      return {name: name};
                                                  });
                                              }
                                          },
                                          remote: {
                                              url: 'json/transaction-journals/' + what + '?search=%QUERY&uid=' + uid,
                                              wildcard: '%QUERY',
                                              filter: function (list) {
                                                  return $.map(list, function (name) {
                                                      return {name: name};
                                                  });
                                              }
                                          }
                                      });
    journalNames.initialize();
    $('input[name="description"]').typeahead({hint: true, highlight: true,}, {source: journalNames, displayKey: 'name', autoSelect: false});
}

/**
 * This function generates a small helper text to explain the user
 * that they have selected a foreign currency.
 * @returns {XML|string|void}
 */
function getExchangeInstructions() {
    console.log('In getExchangeInstructions()');
    var selectedAccountId = getAccountId();
    var foreignCurrencyId = parseInt($('input[name="amount_currency_id_amount"]').val());
    var nativeCurrencyId = parseInt(accountInfo[selectedAccountId].preferredCurrency);

    var text = exchangeRateInstructions.replace('@name', accountInfo[selectedAccountId].name);
    text = text.replace(/@native_currency/g, currencyInfo[nativeCurrencyId].name);
    text = text.replace(/@foreign_currency/g, currencyInfo[foreignCurrencyId].name);
    return text;
}<|endoftext|>