<commit_before>jQuery(function($) {

    // Add AJAX submit handler for each editable form.
    $('.editable-form').submit(function() {
        var form = $(this);
        var loading = $('#editable-loading');
        var showError = function(msg) {
            if (msg) {
                msg = ': ' + msg;
            } else {
                msg = '';
            }
            alert('An error occurred' + msg);
            loading.hide();
            form.show();
        };
        loading.css({
            top: ($(window).height() - loading.height()) / 2 + $(window).scrollTop() + "px",
            left: ($(window).width() - loading.width()) / 2 + $(window).scrollLeft() + "px"
        });
        form.hide();
        loading.show();
        if (typeof tinyMCE != "undefined" ) {
            tinyMCE.triggerSave();
        }
        $('textarea.django-ckeditor').each(function() {
			var $textarea = $(this);
			$textarea.val(CKEDITOR.instances[$textarea.attr('id')].getData());
        });
        form.ajaxSubmit({success: function(data) {
            if (data && data != '') {
                showError(data);
            } else {
                location.reload();
            }
        }, error: function() {
            showError();
        }});
        return false;
    });

    // Iterate through each of the editable areas and set them up.
    var realign = function() {
        $.each($('.editable-original'), function(i, editable) {
            editable = $(editable);
            // Position the editable area's edit link.
            var link = editable.next('.editable-link');
            link.offset({top: editable.offset().top,
                left: editable.offset().left - link.outerWidth() - 1});
            // Apply the editable area's overlay handler.
            var expose = {color: '#333', loadSpeed: 200, opacity: 0.9};
            var overlay = {expose: expose, closeOnClick: true, close: ':button', left: 'center', top: 'center'};
            link.overlay(overlay);
            // Position the editable area's highlight.
            var highlight = link.next('.editable-highlight');
            highlight.css({
                width: editable.width(),
                height: editable.height()
            });
            highlight.offset({top: editable.offset().top, left: editable.offset().left});
        });
    };

    realign();

    // Show/hide the editable area's highlight when mousing over/out the of
    // the edit link.
    $('.editable-link').hover(function(e) {
        $(this).next('.editable-highlight').css('visibility', 'visible');
    }, function(e) {
        $(this).next('.editable-highlight').css('visibility', 'hidden');
    });

    $('body, .editable-original').on('resize', function(e) {
        realign();
    });

    // Add the toolbar HTML and handlers.
    var cookie = 'mezzanine-admin-toolbar';
    var at = ('; ' + document.cookie).indexOf('; ' + cookie + '=');
    var closed = false;
    if (at > -1) {
        closed = document.cookie.substr(at +
            cookie.length + 1).split(';')[0];
    }
    $(window.__toolbar_html).appendTo('body');
    $('#editable-toolbar-toggle').click(function() {
        var toggle = $(this);
        var links = $('.editable-link');
        var toolbar = $('#editable-toolbar *[id!=editable-toolbar-toggle]');
        if (toggle.text() == '<<') {
            toggle.text('>>');
            toolbar.hide();
            links.css('visibility', 'hidden');
            document.cookie = cookie + '=1; path=/';
        } else {
            toggle.text('<<');
            toolbar.show();
            links.css('visibility', 'visible');
            document.cookie = cookie + '=; path=/';
        }
        return false;
    });
    $('#editable-toolbar-logout').click(function() {
        $('#editable-toolbar').submit();
        return false;
    });

    $('#editable-toolbar').fadeIn('slow');
    if (!closed) {
        $('#editable-toolbar-toggle').click();
    }

});
<commit_msg>Fixed the CKEditor integration into front-end mezzanine editing<commit_after>jQuery(function($) {

    // Add AJAX submit handler for each editable form.
    $('.editable-form').submit(function() {
        var form = $(this);
        var loading = $('#editable-loading');
        var showError = function(msg) {
            if (msg) {
                msg = ': ' + msg;
            } else {
                msg = '';
            }
            alert('An error occurred' + msg);
            loading.hide();
            form.show();
        };
        loading.css({
            top: ($(window).height() - loading.height()) / 2 + $(window).scrollTop() + "px",
            left: ($(window).width() - loading.width()) / 2 + $(window).scrollLeft() + "px"
        });
        form.hide();
        loading.show();
        if (typeof tinyMCE != "undefined" ) {
            tinyMCE.triggerSave();
        }
        for(var instanceName in CKEDITOR.instances) {
    		CKEDITOR.instances[instanceName].updateElement();
    	}
        form.ajaxSubmit({success: function(data) {
            if (data && data != '') {
                showError(data);
            } else {
                location.reload();
            }
        }, error: function() {
            showError();
        }});
        return false;
    });

    // Iterate through each of the editable areas and set them up.
    var realign = function() {
        $.each($('.editable-original'), function(i, editable) {
            editable = $(editable);
            // Position the editable area's edit link.
            var link = editable.next('.editable-link');
            link.offset({top: editable.offset().top,
                left: editable.offset().left - link.outerWidth() - 1});
            // Apply the editable area's overlay handler.
            var expose = {color: '#333', loadSpeed: 200, opacity: 0.9};
            var overlay = {expose: expose, closeOnClick: true, close: ':button', left: 'center', top: 'center'};
            link.overlay(overlay);
            // Position the editable area's highlight.
            var highlight = link.next('.editable-highlight');
            highlight.css({
                width: editable.width(),
                height: editable.height()
            });
            highlight.offset({top: editable.offset().top, left: editable.offset().left});
        });
    };

    realign();

    // Show/hide the editable area's highlight when mousing over/out the of
    // the edit link.
    $('.editable-link').hover(function(e) {
        $(this).next('.editable-highlight').css('visibility', 'visible');
    }, function(e) {
        $(this).next('.editable-highlight').css('visibility', 'hidden');
    });

    $('body, .editable-original').on('resize', function(e) {
        realign();
    });

    // Add the toolbar HTML and handlers.
    var cookie = 'mezzanine-admin-toolbar';
    var at = ('; ' + document.cookie).indexOf('; ' + cookie + '=');
    var closed = false;
    if (at > -1) {
        closed = document.cookie.substr(at +
            cookie.length + 1).split(';')[0];
    }
    $(window.__toolbar_html).appendTo('body');
    $('#editable-toolbar-toggle').click(function() {
        var toggle = $(this);
        var links = $('.editable-link');
        var toolbar = $('#editable-toolbar *[id!=editable-toolbar-toggle]');
        if (toggle.text() == '<<') {
            toggle.text('>>');
            toolbar.hide();
            links.css('visibility', 'hidden');
            document.cookie = cookie + '=1; path=/';
        } else {
            toggle.text('<<');
            toolbar.show();
            links.css('visibility', 'visible');
            document.cookie = cookie + '=; path=/';
        }
        return false;
    });
    $('#editable-toolbar-logout').click(function() {
        $('#editable-toolbar').submit();
        return false;
    });

    $('#editable-toolbar').fadeIn('slow');
    if (!closed) {
        $('#editable-toolbar-toggle').click();
    }

});
<|endoftext|>


<commit_before>(function (requirejs, require, define) {

// VideoSpeedControl module.
define(
'video/08_video_speed_control.js',
[],
function () {

    // VideoSpeedControl() function - what this module "exports".
    return function (state) {
        state.videoSpeedControl = {};

        _makeFunctionsPublic(state);
        _renderElements(state);
        _bindHandlers(state);
    };

    // ***************************************************************
    // Private functions start here.
    // ***************************************************************

    // function _makeFunctionsPublic(state)
    //
    //     Functions which will be accessible via 'state' object. When called,
    //     these functions will get the 'state' object as a context.
    function _makeFunctionsPublic(state) {
        state.videoSpeedControl.changeVideoSpeed = _.bind(
            changeVideoSpeed, state
        );
        state.videoSpeedControl.setSpeed = _.bind(setSpeed, state);
        state.videoSpeedControl.reRender = _.bind(reRender, state);
    }

    // function _renderElements(state)
    //
    //     Create any necessary DOM elements, attach them, and set their
    //     initial configuration. Also make the created DOM elements available
    //     via the 'state' object. Much easier to work this way - you don't
    //     have to do repeated jQuery element selects.
    function _renderElements(state) {
        state.videoSpeedControl.speeds = state.speeds;

        state.videoSpeedControl.el = state.el.find('div.speeds');

        state.videoSpeedControl.videoSpeedsEl = state.videoSpeedControl.el
            .find('.video_speeds');

        state.videoControl.secondaryControlsEl.prepend(
            state.videoSpeedControl.el
        );

        $.each(state.videoSpeedControl.speeds, function(index, speed) {
            var link = '' + speed + 'x';

            state.videoSpeedControl.videoSpeedsEl
                .prepend(
                    $('
' + link + '
')
                );
        });

        state.videoSpeedControl.setSpeed(state.speed);
    }

    /**
     * @desc Bind any necessary function callbacks to DOM events (click,
     *     mousemove, etc.).
     *
     * @type {function}
     * @access private
     *
     * @param {object} state The object containg the state of the video player.
     *     All other modules, their parameters, public variables, etc. are
     *     available via this object.
     *
     * @this {object} The global window object.
     *
     * @returns {undefined}
     */
    function _bindHandlers(state) {
        var speedLinks;

        state.videoSpeedControl.videoSpeedsEl.find('a')
            .on('click', state.videoSpeedControl.changeVideoSpeed);

        if (onTouchBasedDevice()) {
            state.videoSpeedControl.el.on('click', function(event) {
                // So that you can't highlight this control via a drag
                // operation, we disable the default browser actions on a
                // click event.
                event.preventDefault();

                state.videoSpeedControl.el.toggleClass('open');
            });
        } else {
            state.videoSpeedControl.el
                .on('mouseenter', function () {
                    state.videoSpeedControl.el.addClass('open');
                })
                .on('mouseleave', function () {
                    state.videoSpeedControl.el.removeClass('open');
                })
                .on('click', function (event) {
                    // So that you can't highlight this control via a drag
                    // operation, we disable the default browser actions on a
                    // click event.
                    event.preventDefault();

                    state.videoSpeedControl.el.removeClass('open');
                });

            // ******************************
            // Attach 'focus', and 'blur' events to the speed button which
            // either brings up the speed dialog with individual speed entries,
            // or closes it.
            state.videoSpeedControl.el.children('a')
                .on('focus', function () {
                    // If the focus is comming from the first speed entry, this
                    // means we are tabbing backwards. In this case we have to
                    // hide the speed entries which will allow us to change the
                    // focus further backwards.
                    if (state.firstSpeedBlur === true) {
                        state.videoSpeedControl.el.removeClass('open');

                        state.firstSpeedBlur = false;
                    }

                    // If the focus is comming from some other element, show
                    // the drop down with the speed entries.
                    else {
                        state.videoSpeedControl.el.addClass('open');
                    }
                })
                .on('blur', function () {
                    // When the focus leaves this element, if the speed entries
                    // dialog is shown (tabbing forwards), then we will set
                    // focus to the first speed entry.
                    //
                    // If the selector does not select anything, then this
                    // means that the speed entries dialog is closed, and we
                    // are tabbing backwads. The browser will select the
                    // previous element to tab to by itself.
                    state.videoSpeedControl.videoSpeedsEl
                        .find('a.speed_link:first')
                        .focus();
                });

            // ******************************
            // Attach 'focus', and 'blur' events to elements which represent
            // individual speed entries.
            speedLinks = state.videoSpeedControl.videoSpeedsEl
                .find('a.speed_link');

            speedLinks.last().on('blur', function () {
                // If we have reached the last speed entry, and the focus
                // changes to the next element, we need to hide the speeds
                // control drop-down.
                state.videoSpeedControl.el.removeClass('open');
            });
            speedLinks.first().on('blur', function () {
                // This flag will indicate that the focus to the next
                // element that will receive it is comming from the first
                // speed entry.
                //
                // This flag will be used to correctly handle scenario of
                // tabbing backwards.
                state.firstSpeedBlur = true;
            });
            speedLinks.on('focus', function () {
                // Clear the flag which is only set when we are un-focusing
                // (the blur event) from the first speed entry.
                state.firstSpeedBlur = false;
            });
        }
    }

    // ***************************************************************
    // Public functions start here.
    // These are available via the 'state' object. Their context ('this'
    // keyword) is the 'state' object. The magic private function that makes
    // them available and sets up their context is makeFunctionsPublic().
    // ***************************************************************

    function setSpeed(speed) {
        this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active');
        this.videoSpeedControl.videoSpeedsEl
            .find("li[data-speed='" + speed + "']")
            .addClass('active');
        this.videoSpeedControl.el.find('p.active').html('' + speed + 'x');
    }

    function changeVideoSpeed(event) {
        var parentEl = $(event.target).parent();

        event.preventDefault();

        if (!parentEl.hasClass('active')) {
            this.videoSpeedControl.currentSpeed = parentEl.data('speed');

            this.videoSpeedControl.setSpeed(
                // To meet the API expected format.
                parseFloat(this.videoSpeedControl.currentSpeed)
                    .toFixed(2)
                    .replace(/\.00$/, '.0')
            );

            this.trigger(
                'videoPlayer.onSpeedChange',
                this.videoSpeedControl.currentSpeed
            );
        }
    }

    function reRender(params) {
        var _this = this;

        this.videoSpeedControl.videoSpeedsEl.empty();
        this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active');
        this.videoSpeedControl.speeds = params.newSpeeds;

        $.each(this.videoSpeedControl.speeds, function(index, speed) {
            var link, listItem;

            link = '' + speed + 'x';

            listItem = $('
' + link + '
');

            if (speed === params.currentSpeed) {
                listItem.addClass('active');
            }

            _this.videoSpeedControl.videoSpeedsEl.prepend(listItem);
        });

        // Re-attach all events with their appropriate callbacks to the
        // newly generated elements.
        _bindHandlers(this);
    }

});

}(RequireJS.requirejs, RequireJS.require, RequireJS.define));
<commit_msg>Disable speed controls for unsupported browsers.<commit_after>(function (requirejs, require, define) {

// VideoSpeedControl module.
define(
'video/08_video_speed_control.js',
[],
function () {

    // VideoSpeedControl() function - what this module "exports".
    return function (state) {
        state.videoSpeedControl = {};

        if (state.videoType === 'html5' && !(_checkPlaybackRates())) {
            _hideSpeedControl(state);

            return;
        }

        _makeFunctionsPublic(state);
        _renderElements(state);
        _bindHandlers(state);
    };

    // ***************************************************************
    // Private functions start here.
    // ***************************************************************

    // function _makeFunctionsPublic(state)
    //
    //     Functions which will be accessible via 'state' object. When called,
    //     these functions will get the 'state' object as a context.
    function _makeFunctionsPublic(state) {
        state.videoSpeedControl.changeVideoSpeed = _.bind(
            changeVideoSpeed, state
        );
        state.videoSpeedControl.setSpeed = _.bind(setSpeed, state);
        state.videoSpeedControl.reRender = _.bind(reRender, state);
    }

    // function _renderElements(state)
    //
    //     Create any necessary DOM elements, attach them, and set their
    //     initial configuration. Also make the created DOM elements available
    //     via the 'state' object. Much easier to work this way - you don't
    //     have to do repeated jQuery element selects.
    function _renderElements(state) {
        state.videoSpeedControl.speeds = state.speeds;

        state.videoSpeedControl.el = state.el.find('div.speeds');

        state.videoSpeedControl.videoSpeedsEl = state.videoSpeedControl.el
            .find('.video_speeds');

        state.videoControl.secondaryControlsEl.prepend(
            state.videoSpeedControl.el
        );

        $.each(state.videoSpeedControl.speeds, function(index, speed) {
            var link = '' + speed + 'x';

            state.videoSpeedControl.videoSpeedsEl
                .prepend(
                    $('
' + link + '
')
                );
        });

        state.videoSpeedControl.setSpeed(state.speed);
    }

    /**
    * @desc Check if playbackRate supports by browser.
    *
    * @type {function}
    * @access private
    *
    * @param {object} state The object containg the state of the video player.
    *     All other modules, their parameters, public variables, etc. are
    *     available via this object.
    *
    * @this {object} The global window object.
    *
    * @returns {Boolean}
    *       true: Browser support playbackRate functionality.
    *       false: Browser doesn't support playbackRate functionality.
    */
    function _checkPlaybackRates() {
        var video = document.createElement('video');

        // If browser supports, 1.0 should be returned by playbackRate property.
        // In this case, function return True. Otherwise, False will be returned.
        return Boolean(video.playbackRate);
    }

    // Hide speed control.
    function _hideSpeedControl(state) {
        state.el.find('div.speeds').hide();
    }

    /**
     * @desc Bind any necessary function callbacks to DOM events (click,
     *     mousemove, etc.).
     *
     * @type {function}
     * @access private
     *
     * @param {object} state The object containg the state of the video player.
     *     All other modules, their parameters, public variables, etc. are
     *     available via this object.
     *
     * @this {object} The global window object.
     *
     * @returns {undefined}
     */
    function _bindHandlers(state) {
        var speedLinks;

        state.videoSpeedControl.videoSpeedsEl.find('a')
            .on('click', state.videoSpeedControl.changeVideoSpeed);

        if (onTouchBasedDevice()) {
            state.videoSpeedControl.el.on('click', function(event) {
                // So that you can't highlight this control via a drag
                // operation, we disable the default browser actions on a
                // click event.
                event.preventDefault();

                state.videoSpeedControl.el.toggleClass('open');
            });
        } else {
            state.videoSpeedControl.el
                .on('mouseenter', function () {
                    state.videoSpeedControl.el.addClass('open');
                })
                .on('mouseleave', function () {
                    state.videoSpeedControl.el.removeClass('open');
                })
                .on('click', function (event) {
                    // So that you can't highlight this control via a drag
                    // operation, we disable the default browser actions on a
                    // click event.
                    event.preventDefault();

                    state.videoSpeedControl.el.removeClass('open');
                });

            // ******************************
            // Attach 'focus', and 'blur' events to the speed button which
            // either brings up the speed dialog with individual speed entries,
            // or closes it.
            state.videoSpeedControl.el.children('a')
                .on('focus', function () {
                    // If the focus is comming from the first speed entry, this
                    // means we are tabbing backwards. In this case we have to
                    // hide the speed entries which will allow us to change the
                    // focus further backwards.
                    if (state.firstSpeedBlur === true) {
                        state.videoSpeedControl.el.removeClass('open');

                        state.firstSpeedBlur = false;
                    }

                    // If the focus is comming from some other element, show
                    // the drop down with the speed entries.
                    else {
                        state.videoSpeedControl.el.addClass('open');
                    }
                })
                .on('blur', function () {
                    // When the focus leaves this element, if the speed entries
                    // dialog is shown (tabbing forwards), then we will set
                    // focus to the first speed entry.
                    //
                    // If the selector does not select anything, then this
                    // means that the speed entries dialog is closed, and we
                    // are tabbing backwads. The browser will select the
                    // previous element to tab to by itself.
                    state.videoSpeedControl.videoSpeedsEl
                        .find('a.speed_link:first')
                        .focus();
                });

            // ******************************
            // Attach 'focus', and 'blur' events to elements which represent
            // individual speed entries.
            speedLinks = state.videoSpeedControl.videoSpeedsEl
                .find('a.speed_link');

            speedLinks.last().on('blur', function () {
                // If we have reached the last speed entry, and the focus
                // changes to the next element, we need to hide the speeds
                // control drop-down.
                state.videoSpeedControl.el.removeClass('open');
            });
            speedLinks.first().on('blur', function () {
                // This flag will indicate that the focus to the next
                // element that will receive it is comming from the first
                // speed entry.
                //
                // This flag will be used to correctly handle scenario of
                // tabbing backwards.
                state.firstSpeedBlur = true;
            });
            speedLinks.on('focus', function () {
                // Clear the flag which is only set when we are un-focusing
                // (the blur event) from the first speed entry.
                state.firstSpeedBlur = false;
            });
        }
    }

    // ***************************************************************
    // Public functions start here.
    // These are available via the 'state' object. Their context ('this'
    // keyword) is the 'state' object. The magic private function that makes
    // them available and sets up their context is makeFunctionsPublic().
    // ***************************************************************

    function setSpeed(speed) {
        this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active');
        this.videoSpeedControl.videoSpeedsEl
            .find("li[data-speed='" + speed + "']")
            .addClass('active');
        this.videoSpeedControl.el.find('p.active').html('' + speed + 'x');
    }

    function changeVideoSpeed(event) {
        var parentEl = $(event.target).parent();

        event.preventDefault();

        if (!parentEl.hasClass('active')) {
            this.videoSpeedControl.currentSpeed = parentEl.data('speed');

            this.videoSpeedControl.setSpeed(
                // To meet the API expected format.
                parseFloat(this.videoSpeedControl.currentSpeed)
                    .toFixed(2)
                    .replace(/\.00$/, '.0')
            );

            this.trigger(
                'videoPlayer.onSpeedChange',
                this.videoSpeedControl.currentSpeed
            );
        }
    }

    function reRender(params) {
        var _this = this;

        this.videoSpeedControl.videoSpeedsEl.empty();
        this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active');
        this.videoSpeedControl.speeds = params.newSpeeds;

        $.each(this.videoSpeedControl.speeds, function(index, speed) {
            var link, listItem;

            link = '' + speed + 'x';

            listItem = $('
' + link + '
');

            if (speed === params.currentSpeed) {
                listItem.addClass('active');
            }

            _this.videoSpeedControl.videoSpeedsEl.prepend(listItem);
        });

        // Re-attach all events with their appropriate callbacks to the
        // newly generated elements.
        _bindHandlers(this);
    }

});

}(RequireJS.requirejs, RequireJS.require, RequireJS.define));
<|endoftext|>


<commit_before>/**
 * @preserve
 * Sharer.js
 *
 * @description Create your own social share buttons
 * @version 0.2.15
 * @author Ellison Leao <ellisonleao@gmail.com>
 * @license GPLv3
 *
 */

(function (window, document) {
    'use strict';
    /**
     * @constructor
     */
    var Sharer = function(elem) {
        this.elem = elem;
    };

    Sharer.prototype = {
        constructor: Sharer,
        /**
         *  @function getValue
         *  @description Helper to get the attribute of a DOM element
         *  @param {String} attr DOM element attribute
         *  @returns {String|Empty} returns the attr value or empty string
         */
        getValue: function(attr) {
            var val = this.elem.getAttribute('data-' + attr);
            return (val === undefined || val === null) ? false : val;
        },

        /**
         * @event share
         * @description Main share event. Will pop a window or redirect to a link
         * based on the data-sharer attribute.
         */
        share: function() {
            var sharer = this.getValue('sharer').toLowerCase(),
                sharers = {
                    facebook: {
                        shareUrl: 'https://www.facebook.com/sharer/sharer.php',
                        params: {u: this.getValue('url')}
                    },
                    googleplus: {
                        shareUrl: 'https://plus.google.com/share',
                        params: {url: this.getValue('url')}
                    },
                    linkedin: {
                        shareUrl: 'https://www.linkedin.com/shareArticle',
                        params: {
                            url: this.getValue('url'),
                            mini: true
                        }
                    },
                    twitter: {
                        shareUrl: 'https://twitter.com/intent/tweet/',
                        params: {
                            text: this.getValue('title'),
                            url: this.getValue('url'),
                            hashtags: this.getValue('hashtags'),
                            via: this.getValue('via')
                        }
                    },
                    email: {
                        shareUrl: 'mailto:' + this.getValue('to'),
                        params: {
                            subject: this.getValue('subject'),
                            body: this.getValue('title') + '\n' + this.getValue('url')
                        },
                        isLink: true
                    },
                    whatsapp: {
                        shareUrl: 'whatsapp://send',
                        params: {
                            text: this.getValue('title') + ' ' + this.getValue('url')
                        },
                        isLink: true
                    },
                    telegram: {
                        shareUrl: 'tg://msg_url',
                        params: {
                            text: this.getValue('title') + ' ' + this.getValue('url')
                        },
                        isLink: true
                    },
                    viber: {
                        shareUrl: 'viber://forward',
                        params: {
                            text: this.getValue('title') + ' ' + this.getValue('url')
                        },
                        isLink: true
                    },
                    line: {
                        shareUrl: 'http://line.me/R/msg/text/?' + encodeURIComponent(this.getValue('title') + ' ' + this.getValue('url')),
                        isLink: true
                    },
                    pinterest: {
                        shareUrl: 'https://www.pinterest.com/pin/create/button/',
                        params: {
                            url: this.getValue('url'),
                            media: this.getValue('image'),
                            description: this.getValue('description')
                        }
                    },
                    tumblr: {
                        shareUrl: 'http://tumblr.com/widgets/share/tool',
                        params: {
                            canonicalUrl: this.getValue('url'),
                            content: this.getValue('url'),
                            posttype: 'link',
                            title: this.getValue('title'),
                            caption: this.getValue('caption'),
                            tags: this.getValue('tags')
                        }
                    },
                    hackernews: {
                        shareUrl: 'https://news.ycombinator.com/submitlink',
                        params: {
                            u: this.getValue('url'),
                            t: this.getValue('title')
                        }
                    },
                    reddit: {
                        shareUrl: 'https://www.reddit.com/submit',
                        params: {'url': this.getValue('url')}
                    },
                    vk: {
                        shareUrl: 'http://vk.com/share.php',
                        params: {
                            url: this.getValue('url'),
                            title: this.getValue('title'),
                            description: this.getValue('caption'),
                            image: this.getValue('image')
                        }
                    },
                    xing: {
                        shareUrl: 'https://www.xing.com/app/user',
                        params: {
                            'op': 'share',
                            'url': this.getValue('url'),
                            'title': this.getValue('title')
                        }
                    },
                    buffer: {
                        shareUrl: 'https://buffer.com/add',
                        params: {
                            url: this.getValue('url'),
                            title: this.getValue('title'),
                            via: this.getValue('via'),
                            picture: this.getValue('picture')
                        }
                    },
                    instapaper: {
                        shareUrl: 'http://www.instapaper.com/edit',
                        params: {
                            url: this.getValue('url'),
                            title: this.getValue('title'),
                            description: this.getValue('description')
                        }
                    },
                    pocket: {
                        shareUrl: 'https://getpocket.com/save',
                        params: {
                            url: this.getValue('url')
                        }
                    },
                    digg: {
                        shareUrl: 'http://www.digg.com/submit',
                        params: {
                            url: this.getValue('url')
                        }
                    },
                    stumbleupon: {
                        shareUrl: 'http://www.stumbleupon.com/submit',
                        params: {
                            url: this.getValue('url'),
                            title: this.getValue('title')
                        }
                    },
                    flipboard: {
                        shareUrl: 'https://share.flipboard.com/bookmarklet/popout',
                        params: {
                            v: 2,
                            title: this.getValue('title'),
                            url: this.getValue('url'),
                            t: Date.now()
                        }
                    },
                    weibo: {
                        shareUrl: 'http://service.weibo.com/share/share.php',
                        params: {
                            url: this.getValue('url'),
                            title: this.getValue('title'),
                            pic: this.getValue('image'),
                            appkey: this.getValue('appkey'),
                            ralateUid: this.getValue('ralateuid'),
                            language: 'zh_cn'
                        }
                    },
                    renren: {
                        shareUrl: 'http://share.renren.com/share/buttonshare',
                        params: {
                            link: this.getValue('url')
                        }
                    },
                    myspace: {
                        shareUrl: 'https://myspace.com/post',
                        params: {
                            u: this.getValue('url'),
                            t: this.getValue('title'),
                            c: this.getValue('description')
                        }
                    },
                    blogger: {
                        shareUrl: 'https://www.blogger.com/blog-this.g',
                        params: {
                            u: this.getValue('url'),
                            n: this.getValue('title'),
                            t: this.getValue('description')
                        }
                    },
                    baidu: {
                        shareUrl: 'http://cang.baidu.com/do/add',
                        params: {
                            it: this.getValue('title'),
                            iu: this.getValue('url')
                        }
                    }
                },
                s = sharers[sharer];

            // custom popups sizes
            if (s) {
                s.width = this.getValue('width');
                s.height = this.getValue('height');
            }
            return s !== undefined ? this.urlSharer(s) : false;
        },
        /**
         * @event urlSharer
         * @param {Object} sharer
         */
        urlSharer: function(sharer) {
            var p = sharer.params || {},
                keys = Object.keys(p),
                i,
                str = keys.length > 0 ? '?' : '';
            for (i = 0; i < keys.length; i++) {
                if (str !== '?') {
                    str += '&';
                }
                if (p[keys[i]]) {
                    str += keys[i] + '=' + encodeURIComponent(p[keys[i]]);
                }
            }
            sharer.shareUrl += str;

            if (!sharer.isLink) {
                var popWidth = sharer.width || 600,
                    popHeight = sharer.height || 480,
                    left = window.innerWidth / 2 - popWidth / 2 + window.screenX,
                    top = window.innerHeight / 2 - popHeight / 2 + window.screenY,
                    popParams = 'scrollbars=no, width=' + popWidth + ', height=' + popHeight + ', top=' + top + ', left=' + left,
                    newWindow = window.open(sharer.shareUrl, '', popParams);

                if (window.focus) {
                    newWindow.focus();
                }
            } else {
                window.location.href = sharer.shareUrl;
            }
        }
    };

    /**
     * Creates a click event on every DOM element which has the `sharer` class
     */
    window.addEventListener('load', function() {
        var elems = document.querySelectorAll('.sharer'),
            i,
            l = elems.length;

        function addShare(elem) {
            var target = elem.currentTarget || elem.srcElement;
            var sharer = new Sharer(target);
            sharer.share();
        }

        for (i = 0; i < l ; i++) {
            elems[i].addEventListener('click', addShare);
        }
    });
})(window, document);
<commit_msg>adding douban #40<commit_after>/**
 * @preserve
 * Sharer.js
 *
 * @description Create your own social share buttons
 * @version 0.2.15
 * @author Ellison Leao <ellisonleao@gmail.com>
 * @license GPLv3
 *
 */

(function (window, document) {
    'use strict';
    /**
     * @constructor
     */
    var Sharer = function(elem) {
        this.elem = elem;
    };

    Sharer.prototype = {
        constructor: Sharer,
        /**
         *  @function getValue
         *  @description Helper to get the attribute of a DOM element
         *  @param {String} attr DOM element attribute
         *  @returns {String|Empty} returns the attr value or empty string
         */
        getValue: function(attr) {
            var val = this.elem.getAttribute('data-' + attr);
            return (val === undefined || val === null) ? false : val;
        },

        /**
         * @event share
         * @description Main share event. Will pop a window or redirect to a link
         * based on the data-sharer attribute.
         */
        share: function() {
            var sharer = this.getValue('sharer').toLowerCase(),
                sharers = {
                    facebook: {
                        shareUrl: 'https://www.facebook.com/sharer/sharer.php',
                        params: {u: this.getValue('url')}
                    },
                    googleplus: {
                        shareUrl: 'https://plus.google.com/share',
                        params: {url: this.getValue('url')}
                    },
                    linkedin: {
                        shareUrl: 'https://www.linkedin.com/shareArticle',
                        params: {
                            url: this.getValue('url'),
                            mini: true
                        }
                    },
                    twitter: {
                        shareUrl: 'https://twitter.com/intent/tweet/',
                        params: {
                            text: this.getValue('title'),
                            url: this.getValue('url'),
                            hashtags: this.getValue('hashtags'),
                            via: this.getValue('via')
                        }
                    },
                    email: {
                        shareUrl: 'mailto:' + this.getValue('to'),
                        params: {
                            subject: this.getValue('subject'),
                            body: this.getValue('title') + '\n' + this.getValue('url')
                        },
                        isLink: true
                    },
                    whatsapp: {
                        shareUrl: 'whatsapp://send',
                        params: {
                            text: this.getValue('title') + ' ' + this.getValue('url')
                        },
                        isLink: true
                    },
                    telegram: {
                        shareUrl: 'tg://msg_url',
                        params: {
                            text: this.getValue('title') + ' ' + this.getValue('url')
                        },
                        isLink: true
                    },
                    viber: {
                        shareUrl: 'viber://forward',
                        params: {
                            text: this.getValue('title') + ' ' + this.getValue('url')
                        },
                        isLink: true
                    },
                    line: {
                        shareUrl: 'http://line.me/R/msg/text/?' + encodeURIComponent(this.getValue('title') + ' ' + this.getValue('url')),
                        isLink: true
                    },
                    pinterest: {
                        shareUrl: 'https://www.pinterest.com/pin/create/button/',
                        params: {
                            url: this.getValue('url'),
                            media: this.getValue('image'),
                            description: this.getValue('description')
                        }
                    },
                    tumblr: {
                        shareUrl: 'http://tumblr.com/widgets/share/tool',
                        params: {
                            canonicalUrl: this.getValue('url'),
                            content: this.getValue('url'),
                            posttype: 'link',
                            title: this.getValue('title'),
                            caption: this.getValue('caption'),
                            tags: this.getValue('tags')
                        }
                    },
                    hackernews: {
                        shareUrl: 'https://news.ycombinator.com/submitlink',
                        params: {
                            u: this.getValue('url'),
                            t: this.getValue('title')
                        }
                    },
                    reddit: {
                        shareUrl: 'https://www.reddit.com/submit',
                        params: {'url': this.getValue('url')}
                    },
                    vk: {
                        shareUrl: 'http://vk.com/share.php',
                        params: {
                            url: this.getValue('url'),
                            title: this.getValue('title'),
                            description: this.getValue('caption'),
                            image: this.getValue('image')
                        }
                    },
                    xing: {
                        shareUrl: 'https://www.xing.com/app/user',
                        params: {
                            'op': 'share',
                            'url': this.getValue('url'),
                            'title': this.getValue('title')
                        }
                    },
                    buffer: {
                        shareUrl: 'https://buffer.com/add',
                        params: {
                            url: this.getValue('url'),
                            title: this.getValue('title'),
                            via: this.getValue('via'),
                            picture: this.getValue('picture')
                        }
                    },
                    instapaper: {
                        shareUrl: 'http://www.instapaper.com/edit',
                        params: {
                            url: this.getValue('url'),
                            title: this.getValue('title'),
                            description: this.getValue('description')
                        }
                    },
                    pocket: {
                        shareUrl: 'https://getpocket.com/save',
                        params: {
                            url: this.getValue('url')
                        }
                    },
                    digg: {
                        shareUrl: 'http://www.digg.com/submit',
                        params: {
                            url: this.getValue('url')
                        }
                    },
                    stumbleupon: {
                        shareUrl: 'http://www.stumbleupon.com/submit',
                        params: {
                            url: this.getValue('url'),
                            title: this.getValue('title')
                        }
                    },
                    flipboard: {
                        shareUrl: 'https://share.flipboard.com/bookmarklet/popout',
                        params: {
                            v: 2,
                            title: this.getValue('title'),
                            url: this.getValue('url'),
                            t: Date.now()
                        }
                    },
                    weibo: {
                        shareUrl: 'http://service.weibo.com/share/share.php',
                        params: {
                            url: this.getValue('url'),
                            title: this.getValue('title'),
                            pic: this.getValue('image'),
                            appkey: this.getValue('appkey'),
                            ralateUid: this.getValue('ralateuid'),
                            language: 'zh_cn'
                        }
                    },
                    renren: {
                        shareUrl: 'http://share.renren.com/share/buttonshare',
                        params: {
                            link: this.getValue('url')
                        }
                    },
                    myspace: {
                        shareUrl: 'https://myspace.com/post',
                        params: {
                            u: this.getValue('url'),
                            t: this.getValue('title'),
                            c: this.getValue('description')
                        }
                    },
                    blogger: {
                        shareUrl: 'https://www.blogger.com/blog-this.g',
                        params: {
                            u: this.getValue('url'),
                            n: this.getValue('title'),
                            t: this.getValue('description')
                        }
                    },
                    baidu: {
                        shareUrl: 'http://cang.baidu.com/do/add',
                        params: {
                            it: this.getValue('title'),
                            iu: this.getValue('url')
                        }
                    },
                    douban: {
                        shareUrl: 'https://www.douban.com/share/service',
                        params: {
                            name: this.getValue('title'),
                            href: this.getValue('url'),
                            image: this.getValue('image')
                        }
                    }
                },
                s = sharers[sharer];

            // custom popups sizes
            if (s) {
                s.width = this.getValue('width');
                s.height = this.getValue('height');
            }
            return s !== undefined ? this.urlSharer(s) : false;
        },
        /**
         * @event urlSharer
         * @param {Object} sharer
         */
        urlSharer: function(sharer) {
            var p = sharer.params || {},
                keys = Object.keys(p),
                i,
                str = keys.length > 0 ? '?' : '';
            for (i = 0; i < keys.length; i++) {
                if (str !== '?') {
                    str += '&';
                }
                if (p[keys[i]]) {
                    str += keys[i] + '=' + encodeURIComponent(p[keys[i]]);
                }
            }
            sharer.shareUrl += str;

            if (!sharer.isLink) {
                var popWidth = sharer.width || 600,
                    popHeight = sharer.height || 480,
                    left = window.innerWidth / 2 - popWidth / 2 + window.screenX,
                    top = window.innerHeight / 2 - popHeight / 2 + window.screenY,
                    popParams = 'scrollbars=no, width=' + popWidth + ', height=' + popHeight + ', top=' + top + ', left=' + left,
                    newWindow = window.open(sharer.shareUrl, '', popParams);

                if (window.focus) {
                    newWindow.focus();
                }
            } else {
                window.location.href = sharer.shareUrl;
            }
        }
    };

    /**
     * Creates a click event on every DOM element which has the `sharer` class
     */
    window.addEventListener('load', function() {
        var elems = document.querySelectorAll('.sharer'),
            i,
            l = elems.length;

        function addShare(elem) {
            var target = elem.currentTarget || elem.srcElement;
            var sharer = new Sharer(target);
            sharer.share();
        }

        for (i = 0; i < l ; i++) {
            elems[i].addEventListener('click', addShare);
        }
    });
})(window, document);
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Redmine Tools
// @namespace    http://devhq.pl/
// @version      0.1
// @description  Set task data
// @author       Hakier
// @match        http://devhq.pl/redmine/*
// @match        http://redmine.dpserver.pl/*
// @grant        none
// @require     http://code.jquery.com/jquery-latest.js
// @require     https://raw.githubusercontent.com/jeresig/jquery.hotkeys/master/jquery.hotkeys.js
// ==/UserScript==

jQuery(function ($) {
    var bindKey = function (keys, fn) {
            $(document).on('keydown', null, keys, fn);
        },
        debug = {
            isEnabled: false,
            dump: function () {
                if (this.isEnabled) {
                    console.log(arguments);
                }
            }
        },
        selectOption = function ($element) {
            if (!$element.length) {
                return false;
            }

            $element.attr('selected', true);

            return true;
        },
        redmine = {
            $: {
                btn: {
                    edit: $('#content > .contextual > a.icon.icon-edit:first')
                },
                container: {
                    top: $('#content > .contextual')
                }
            },
            issue: {
                $: {
                    statusOption: {
                        inProgress: $('#issue_status_id option[value=2]'),
                        done: $('#issue_status_id option[value=5]')
                    },
                    form: $('#issue-form')
                },
                assignToMe: function () {
                    var $assignedToMe = $('#issue_assigned_to_id option:contains("<< ja >>")');

                    selectOption($assignedToMe);

                    return this;
                },
                setRatioDone: function () {
                    var $doneRatio = $('#issue_done_ratio option:last');

                    selectOption($doneRatio);

                    return this;
                },
                setStatus: {
                    _setStatus: function (name) {
                        selectOption(redmine.issue.$.statusOption[name]);

                        return this;
                    },
                    inProgress: function () {
                        return this._setStatus('inProgress');
                    },
                    done: function () {
                        return this._setStatus('done');
                    }
                },
                submitForm: function () {
                    this.$.form.submit();
                }
            },
            init: function () {
                this._addBtnToCreateListFromNotes();
                this._addBtnToCreateListOfChildrenFromNotes();

                this._createChild();

                this
                    ._createBtnToMarkIssueDone()
                    ._createBtnToMarkIssueInProgress()
                    ._createBtnToHideDoneAndInterrupted();

                bindKey('alt+e', function(event) {
                    event.preventDefault();

                    showAndScrollTo("update", "issue_notes");
                });
            },
            _isIssuePage: function () {
                var isIssuePage = location.pathname.match(/\/issues\/[0-9]*/);

                debug.dump('_isIssuePage', isIssuePage);

                return isIssuePage;
            },
            _addBtnToCreateListFromNotes: function () {
                debug.dump('_addBtnToCreateListFromNotes');

                if (!this._isIssuePage()) {
                    return;
                }

                var $createListFromNoteBtn = $('Create list from note'),
                    checkList = {
                        $notes: $('#issue_notes'),
                        getInput: function () {
                            return $('#checklist_form_items .checklist-edit-box > input.edit-box');
                        },
                        getSubmit: function () {
                            return $('#checklist_form_items > span.checklist-item.new > span.icon.icon-add.checklist-new-only.save-new-by-button');
                        }
                    },
                    createListFromNote = function () {
                        var list = checkList.$notes.val().trim().split('\n');

                        $.each(JSON.parse(JSON.stringify(list)), function (key, val) {
                            checkList.getInput().val(val);
                            checkList.getSubmit().click();
                        });

                        checkList.$notes.val('');

                        $('#create-list-from-notes').remove();

                        checkList.getSubmit().after($createListFromNoteBtn);
                    };

                $('body').on('click', '#create-list-from-notes', createListFromNote);
                checkList.getSubmit().after($createListFromNoteBtn);
                bindKey('alt+l', createListFromNote);
            },
            localStorageKeys: {
                childrenList: 'childrenList',
                createChildrenUrl: 'createChildrenUrl'
            },
            _addBtnToCreateListOfChildrenFromNotes: function () {
                debug.dump('_addBtnToCreateListOfChildrenFromNotes');
                if (!this._isIssuePage()) {
                    return;
                }

                var $addChildBtn = $('#issue_tree .contextual a:last-child'),
                    $addChildrenFromNotesBtn = $('Add children from notes'),
                    $notes = $('#issue_notes'),
                    createChildrenFromNotes = function () {
                        var list = $notes.val().trim().split('\n'),
                            createChildrenUrl = $addChildBtn.attr('href');

                        localStorage.setItem(
                            redmine.localStorageKeys.childrenList,
                            JSON.stringify(list)
                        );

                        localStorage.setItem(
                            redmine.localStorageKeys.createChildrenUrl,
                            createChildrenUrl
                        );

                        if (list.length > 1) {
                            $notes.val('');
                            location.href = createChildrenUrl;
                        }
                    };

                $addChildrenFromNotesBtn
                    .css({
                        marginRight: 20
                    })
                    .on('click', createChildrenFromNotes);

                $addChildBtn.before($addChildrenFromNotesBtn);
                bindKey('alt+c', createChildrenFromNotes)
            },
            _createChild: function () {
                debug.dump('_createChild');
                if (!location.pathname.match('/issues/new')) {
                    return;
                }

                var list = JSON.parse(
                        localStorage.getItem(redmine.localStorageKeys.childrenList)
                    ),
                    first = list[0],
                    $addAndContinueBtn = $('#issue-form > input[name="continue"]');

                if (first == undefined) {
                    return;
                }

                list.shift();

                localStorage.setItem(
                    redmine.localStorageKeys.childrenList,
                    JSON.stringify(list)
                );

                $('#issue_subject').val(first);

                //if (first.length > 3) {
                //    $addAndContinueBtn.click();
                //}
            },
            _createBtnToMarkIssueDone: function () {
                debug.dump('_createBtnToMarkIssueDone');

                if (!this._isIssuePage()) {
                    return this;
                }

                var $btnMarkAsDone = $('Mark as done'),
                    markAsDone = function () {
                        redmine.issue
                            .assignToMe()
                            .setRatioDone()
                            .setStatus.inProgress().done();

                        redmine.issue.submitForm();
                    };

                $btnMarkAsDone.on('click', markAsDone);
                this.$.container.top.prepend($btnMarkAsDone);
                bindKey('alt+d', markAsDone);

                return this;
            },
            _createBtnToMarkIssueInProgress: function () {
                debug.dump('_createBtnToMarkIssueInProgress');

                if (!this._isIssuePage()) {
                    return this;
                }

                var $btnMarkAsInProgress = $('Mark as in progress'),
                    markAsInProgress = function () {
                        redmine.issue
                            .assignToMe()
                            .setStatus.inProgress();

                        redmine.issue.submitForm();
                    };

                $btnMarkAsInProgress.on('click', markAsInProgress);
                bindKey('alt+p', markAsInProgress);
                this.$.container.top.prepend($btnMarkAsInProgress);

                return this;
            },
            _createBtnToHideDoneAndInterrupted: function () {
                debug.dump('_createBtnToHideDoneAndInterrupted');

                if (!this._isIssuePage()) {
                    return this;
                }

                var $btnHideDoneAndInterrupted = $('Hide done and interrupted'),
                    hideDoneAndInterrupted = function () {
                        var $statuses = $('#issue_tree .issue > td:nth-child(3)');

                        $statuses.each(function () {
                            var $this = $(this);

                            if ($this.text().match('Zamknięty') || $this.text().match('Przerwany')) {
                                $this.closest('.issue').hide();
                            }
                        });
                    };

                $btnHideDoneAndInterrupted.on('click', hideDoneAndInterrupted);
                this.$.container.top.prepend($btnHideDoneAndInterrupted);
                bindKey('alt+h', hideDoneAndInterrupted);

                debug.dump('this.$.container.top', this.$.container.top);

                return this;
            }
        };

    redmine.init();
});
<commit_msg>redmineTools  ! reorganize methods into sub objects  + com.bind.search<commit_after>// ==UserScript==
// @name         Redmine Tools
// @namespace    http://devhq.pl/
// @version      0.2
// @description  Set task data
// @author       Hakier
// @match        http://devhq.pl/redmine/*
// @match        http://redmine.dpserver.pl/*
// @grant        none
// @require     http://code.jquery.com/jquery-latest.js
// @require     https://raw.githubusercontent.com/jeresig/jquery.hotkeys/master/jquery.hotkeys.js
// ==/UserScript==

jQuery(function ($) {
    var bindKey = function (keys, fn) {
            $(document).on('keydown', null, keys, fn);
        },
        debug = {
            isEnabled: true,
            dump: function () {
                if (this.isEnabled) {
                    console.log(arguments);
                }
            }
        },
        selectOption = function ($element) {
            debug.dump('selectOption');

            if (!$element.length) {
                return false;
            }

            $element.attr('selected', true);

            return true;
        },
        redmine = {
            $: {
                btn: {
                    edit: $('#content > .contextual > a.icon.icon-edit:first')
                },
                container: {
                    top: $('#content > .contextual')
                }
            },
            init: function () {
                debug.dump('redmine.init');

                this._createChild();

                this.com.init();
                this.issue.init();
            },
            com: {
                init: function () {
                    this.bind.init();

                    return redmine;
                },
                isPage: {
                    issue: function () {
                        var isIssuePage = location.pathname.match(/\/issues\/[0-9]*/);

                        debug.dump('redmine.com.isPage.issue', isIssuePage);

                        return isIssuePage;
                    }
                },
                bind: {
                    init: function () {
                        this.search();

                        return redmine;
                    },
                    search: function () {
                        var $search = $('#q');

                        bindKey('alt+/', function () {
                            $search.focus();
                        });

                        return this;
                    }
                }
            },
            issue: {
                $: {
                    statusOption: {
                        inProgress: $('#issue_status_id option[value=2]'),
                        done: $('#issue_status_id option[value=5]')
                    },
                    form: $('#issue-form')
                },
                init: function () {
                    debug.dump('redmine.issue.init');

                    if (!redmine.com.isPage.issue()) {
                        return redmine;
                    }

                    this.bind.init();
                    this.createBtn.init();

                    return redmine;
                },
                assignToMe: function () {
                    var $assignedToMe = $('#issue_assigned_to_id option:contains("<< ja >>")');

                    selectOption($assignedToMe);

                    return this;
                },
                setRatioDone: function () {
                    var $doneRatio = $('#issue_done_ratio option:last');

                    selectOption($doneRatio);

                    return this;
                },
                setStatus: {
                    _setStatus: function (name) {
                        selectOption(redmine.issue.$.statusOption[name]);

                        return this;
                    },
                    inProgress: function () {
                        return this._setStatus('inProgress');
                    },
                    done: function () {
                        return this._setStatus('done');
                    }
                },
                submitForm: function () {
                    this.$.form.submit();
                },
                bind: {
                    init: function() {
                        debug.dump('redmine.issue.bind.init');

                        this
                            .editBtn()
                            .addTimeBtn();

                        return redmine;
                    },
                    editBtn: function () {
                        debug.dump('redmine.issue.bind.editBtn');

                        var $editBtn = $('#content a.icon.icon-edit:contains(Edytuj)');

                        bindKey('alt+e', function(event) {
                            event.preventDefault();

                            $editBtn.click();
                        });

                        $editBtn.html('Edytuj');

                        return this;
                    },
                    addTimeBtn: function () {
                        debug.dump('redmine.issue.bind.addTimeBtn');

                        var $addTimeBtn = $('#content a.icon.icon-edit:contains(Dziennik)');

                        bindKey('alt+d', function(event) {
                            event.preventDefault();

                            $addTimeBtn.click();
                        });

                        $addTimeBtn.html('Dziennik');

                        return this;
                    }
                },
                createBtn: {
                    init: function () {
                        debug.dump('redmine.issue.createBtn.init');

                        this
                            .toMarkIssueDone()
                            .toMarkIssueInProgress()
                            .toHideDoneAndInterrupted()
                            .toCreateListFromNotes()
                            .toCreateListOfChildrenFromNotes();

                        return redmine;
                    },
                    toMarkIssueDone: function () {
                        debug.dump('redmine.issue.createBtn.toMarkIssueDone');

                        var $btnMarkAsDone = $('Mark as done'),
                            markAsDone = function () {
                                redmine.issue
                                    .assignToMe()
                                    .setRatioDone()
                                    .setStatus.inProgress().done();

                                redmine.issue.submitForm();
                            };

                        $btnMarkAsDone.on('click', markAsDone);
                        redmine.$.container.top.prepend($btnMarkAsDone);
                        bindKey('alt+d', markAsDone);

                        return this;
                    },
                    toMarkIssueInProgress: function () {
                        var $btnMarkAsInProgress = $('Mark as in progress'),
                            markAsInProgress = function () {
                                redmine.issue
                                    .assignToMe()
                                    .setStatus.inProgress();

                                redmine.issue.submitForm();
                            };

                        $btnMarkAsInProgress.on('click', markAsInProgress);
                        bindKey('alt+p', markAsInProgress);
                        redmine.$.container.top.prepend($btnMarkAsInProgress);

                        return this;
                    },
                    toHideDoneAndInterrupted: function () {
                        debug.dump('redmine.issue.createBtn.toHideDoneAndInterrupted');

                        var $btnHideDoneAndInterrupted = $('Hide done and interrupted'),
                            hideDoneAndInterrupted = function () {
                                var $statuses = $('#issue_tree .issue > td:nth-child(3)');

                                $statuses.each(function () {
                                    var $this = $(this);

                                    if ($this.text().match('Zamknięty') || $this.text().match('Przerwany')) {
                                        $this.closest('.issue').hide();
                                    }
                                });
                            };

                        $btnHideDoneAndInterrupted.on('click', hideDoneAndInterrupted);
                        redmine.$.container.top.prepend($btnHideDoneAndInterrupted);
                        bindKey('alt+h', hideDoneAndInterrupted);

                        return this;
                    },
                    toCreateListFromNotes: function () {
                        debug.dump('redmine.issue.createBtn.toCreateListFromNotes');

                        var $createListFromNoteBtn = $('Create list from note'),
                            checkList = {
                                $notes: $('#issue_notes'),
                                getInput: function () {
                                    return $('#checklist_form_items .checklist-edit-box > input.edit-box');
                                },
                                getSubmit: function () {
                                    return $('#checklist_form_items > span.checklist-item.new > span.icon.icon-add.checklist-new-only.save-new-by-button');
                                }
                            },
                            createListFromNote = function () {
                                var list = checkList.$notes.val().trim().split('\n');

                                $.each(JSON.parse(JSON.stringify(list)), function (key, val) {
                                    checkList.getInput().val(val);
                                    checkList.getSubmit().click();
                                });

                                checkList.$notes.val('');

                                $('#create-list-from-notes').remove();

                                checkList.getSubmit().after($createListFromNoteBtn);
                            };

                        $('body').on('click', '#create-list-from-notes', createListFromNote);
                        checkList.getSubmit().after($createListFromNoteBtn);
                        bindKey('alt+l', createListFromNote);
                    },
                    toCreateListOfChildrenFromNotes: function () {
                        debug.dump('redmine.issue.createBtn.toCreateListOfChildrenFromNotes');

                        var $addChildBtn = $('#issue_tree .contextual a:last-child'),
                            $addChildrenFromNotesBtn = $('Add children from notes'),
                            $notes = $('#issue_notes'),
                            createChildrenFromNotes = function () {
                                var list = $notes.val().trim().split('\n'),
                                    createChildrenUrl = $addChildBtn.attr('href');

                                localStorage.setItem(
                                    redmine.localStorageKeys.childrenList,
                                    JSON.stringify(list)
                                );

                                localStorage.setItem(
                                    redmine.localStorageKeys.createChildrenUrl,
                                    createChildrenUrl
                                );

                                if (list.length > 1) {
                                    $notes.val('');
                                    location.href = createChildrenUrl;
                                }
                            };

                        $addChildrenFromNotesBtn
                            .css({
                                marginRight: 20
                            })
                            .on('click', createChildrenFromNotes);

                        $addChildBtn.before($addChildrenFromNotesBtn);
                        bindKey('alt+c', createChildrenFromNotes);

                        return this;
                    }
                }
            },
            localStorageKeys: {
                childrenList: 'childrenList',
                createChildrenUrl: 'createChildrenUrl'
            },
            _createChild: function () {
                debug.dump('redmine._createChild');

                if (!location.pathname.match('/issues/new')) {
                    return;
                }

                var list = JSON.parse(
                        localStorage.getItem(redmine.localStorageKeys.childrenList)
                    ),
                    first = list[0],
                    $addAndContinueBtn = $('#issue-form > input[name="continue"]');

                if (first == undefined) {
                    return;
                }

                list.shift();

                localStorage.setItem(
                    redmine.localStorageKeys.childrenList,
                    JSON.stringify(list)
                );

                $('#issue_subject').val(first);

                //if (first.length > 3) {
                //    $addAndContinueBtn.click();
                //}
            }
        };

    redmine.init();
});
<|endoftext|>


<commit_before>require("./app.css")

let Cycle = require('cycle-react')
let React = require('react')
import Rx from 'rx'
import combineTemplate from 'rx.observable.combinetemplate'

import GlView from './components/webgl/GlView'
import BomView from './components/Bom/BomView'
import SettingsView from './components/SettingsView'
import FullScreenToggler from './components/FullScreenToggler'
import ContextMenu2 from './components/ContextMenu2'

import {observableDragAndDrop} from './interactions/dragAndDrop'

//temporary
import {makeInternals, meshResources, entityInstanceFromPartTypes} from './core/tbd0'
import {entityToVisuals, meshInjectPostProcess, applyEntityPropsToMesh} from './core/entityToVisuals'

let pjson = require('../package.json')
let appMetadata$ = Rx.Observable.just({
  name: pjson.name,
  version:pjson.version
})

  //interactions
  /*let inter = require('./core/intents.js')
  let intent = inter.Intent({
    objectsTransforms$ : glview.objectsTransform$,
    selectedMeshes$    : glview.selectedMeshes$,²
    selectedBomEntries$: selectBomEntries$,
    selectEntities$,

    //these indicate an issue, they should not need to be injected into an intent
    appState$: appState$,
    entities$:entities$,
    bom$:bom$,
  })

  intent.entityTransforms$
    .subscribe(updateEntities$)

  intent.entitiesToSelect$
    .subscribe( selectEntities$ )

  intent.bomEntriesToSelect$
    .subscribe( selectBomEntries2$ )
    */

function intent(interactions){
  let glviewInit$ = interactions.get(".glview","initialized$")
  let singleTaps$ = interactions.get(".glview","singleTaps$")
  let doubleTaps$ = interactions.get(".glview","doubleTaps$")
  let contextTaps$ = interactions.get(".glview","contextTaps$")
  let selectTransforms$ = interactions.get(".glview","selectionsTransforms$")

  singleTaps$.pluck("detail").subscribe(event => console.log("singleTaps",event))
  doubleTaps$.pluck("detail").subscribe(event => console.log("doubleTaps",event))
  contextTaps$.pluck("detail").subscribe(event => console.log("contextTaps",event))
  selectTransforms$.pluck("detail").subscribe(event => console.log("selectTransforms",event))

}

function settingsM(interactions){
  let showGrid$   = interactions.get(".settingsView .showGrid", "change").map(event => event.target.checked).startWith(false)
  let showAnnot$  = interactions.get(".settingsView .showAnnot", "change").map(event => event.target.checked).startWith(false)
  let autoRotate$ = interactions.get(".settingsView .autoRotate", "change").map(event => event.target.checked).startWith(false)

  /*function foobar(fieldName){
    return interactions.get(".settingsView "+fieldName, "change").map(event => event.target.checked).startWith(false)
  }
  let fieldNames = [".showGrid",".showAnnot",".autoRotate"]
  fieldNames.map(foobar)*/

  /*let bla$= combineTemplate(
    {
      camera:{
        autoRotate:autoRotate$
      },
      grid:{
        show:showGrid$
      },
      annotations:{
        show:showAnnot$
      }
    }
  )

  //bla$.subscribe(bla=>console.log("lkjfdsfsfsd",bla))*/
  //return bla$
  return Rx.Observable.combineLatest(
    showGrid$,
    autoRotate$,
    function(showGrid$,autoRotate$, showAnnot$){
      return (
        {
          camera:{
            autoRotate:autoRotate$
          },
          grid:{
            show:showGrid$
          },
          annotations:{
            show:showAnnot$
          }
        }
      )
    }
  )
}

function sources(urlSources$, dndSources$){
  //data sources
  let dataSources = require('./core/sources/dataSources').getDataSources
  let urlSources = require('./core/sources/urlSources')

  //urlSources.appMode$.subscribe( appMode => setSetting$({path:"mode",value:appMode}) )
  urlSources.settings$.subscribe(function(settings){
    console.log("settings from old",settings)
    const defaults = {
      persistent:false,
      lastDesignUri:undefined,
      lastDesignName:undefined,

      /*grid:{
        show:false,
      },
      annotations{
        show:false
      }*/
    }
    let _settings = Object.assign({},defaults,settings)

    /*updateDesign$({
      _persistent:_settings.persistent,
      uri:_settings.lastDesignUri,
      name:_settings.lastDesignName
    })*/
  })

  let {meshSources$, designSources$} = dataSources(dndSources$, urlSources)

  let settingsSources$ = urlSources.settings$

  meshSources$
    .subscribe(data => console.log("meshSources",data))

  return {meshSources$, designSources$, settingsSources$}
}

function App(interactions) {
  let activeTool = "translate"

  let dragOvers$ = interactions.subject("dragover")
  let drops$  = interactions.subject("drop")
  let dndSources$ = observableDragAndDrop(dragOvers$, drops$)
    //.subscribe(data => console.log("dndSources",data))
  let urlSources$ =null
  let {meshSources$, designSources$, settingsSources$} = sources(urlSources$, dndSources$)

  let settings$ = settingsM(interactions)

  let {kernel, assetManager} = makeInternals()

  let meshResources$ = meshResources(meshSources$, assetManager)
    //.subscribe(data=>console.log("mesh data",data))
  //doLotsOfThings(kernel,assetManager,meshSources$)

  //register meshes <=> types
  let partTypes = require('./core/partReg')
  let partTypes$ = partTypes({combos$:meshResources$})

  //get new instances from "types"
  let newInstFromTypes$ = entityInstanceFromPartTypes(partTypes$)
    //.subscribe(data=>console.log("mesh data",data))

  let entities = require("./core/entityModel")

  let intent = {
    createEntityInstance$:new Rx.Subject(),//createEntityInstance$,
    addEntities$: newInstFromTypes$,//addEntityInstances$,

    updateEntities$: new Rx.Subject(),
    deleteEntities$: new Rx.Subject(),
    duplicateEntities$: new Rx.Subject(),
    deleteAllEntities$: new Rx.Subject(),
    selectEntities$: new Rx.Subject(),

    newDesign$: new Rx.Subject(),
  }
  let entities$ = entities(intent)

  //entities$
  //  .subscribe(data=>console.log("mesh data",data))
  //what is my visual for any given entity

  let otherData$ = partTypes$
    .zip(meshResources$,function(types, meshResource){

      console.log("types",types,"meshResource",meshResource)

      return {
        typeUid:types.meshNameToPartTypeUId[meshResource.resource.name],
        mesh:meshResource.mesh,
        resource:meshResource.resource
      }
    })
    /*.scan(function(acc,val){
      console.lot("acc",acc,"val",val)
      return acc[val.typeUid] = val.mesh
    },{})*/
  .subscribe(data=>console.log(" data",data))
  //entityToVisuals()

  /*let entitiesToMeshInstancesMap = new WeakMap()
  let meshInstancesToEntitiesMap = new WeakMap()//reverse map

  function entityVisual(entity){
  }

  entities$
  .skip(1)
  .combineLatest(partTypes$,
    function(entities,partTypes){

    }
  )
  .subscribe(data=>console.log(" data",data))
  */

  /*.flatMap(function(data){
    return Rx.Observable.from( kernel.getPartMeshInstance( data[0] ) )
  })
  .map(Rx.Observable.from)
  .subscribe(function(data){
    console.log("mesh data",data)
    //let foo$ = Rx.Observable.from( kernel.getPartMeshInstance(data.instances[0]) )
  })*/

  //let requestVisualForEntity$ = new Rx.Observable()

  let visualMappings$ = entities$
    .pluck("instances")
    .withLatestFrom(partTypes$,function(entries, types){

      console.log("entries",entries,"types",types)

      return entries.map(function(entity){
        let mesh = types.typeUidToTemplateMesh[entity.typeUid].clone()

        mesh = meshInjectPostProcess(mesh)
        mesh = applyEntityPropsToMesh({entity,mesh})

        return mesh
      })

    })
    /*.flatMap(function(items){
      return Rx.Observable.from(items)
    })*/
    //.filter(x=> types.indexOf(x.type) > -1 )

  return Rx.Observable
    .combineLatest(
      appMetadata$,
      entities$,
      settings$,
      visualMappings$,
      function(appMetadata, items, settings, visualMappings){

        //console.log("settings",settings)
        return (

{appMetadata.name}{appMetadata.version}

            <GlView
              activeTool={activeTool}
              settings={settings}
              items={items}
              visualMappings={visualMappings}
              className="glview"/>

            <SettingsView settings={settings} ></SettingsView>
            <FullScreenToggler/>

        )
      }
    )
}

App = Cycle.component('App', App)

export default App<commit_msg>- added entityInfos component (new version) to main app - working on selection system<commit_after>require("./app.css")

let Cycle = require('cycle-react')
let React = require('react')
import Rx from 'rx'
import combineTemplate from 'rx.observable.combinetemplate'

import GlView from './components/webgl/GlView'
import BomView from './components/Bom/BomView'
import SettingsView from './components/SettingsView'
import FullScreenToggler from './components/FullScreenToggler'
import ContextMenu2 from './components/ContextMenu2'
import EntityInfos from './components/EntityInfos2'

import {observableDragAndDrop} from './interactions/dragAndDrop'

//temporary
import {makeInternals, meshResources, entityInstanceFromPartTypes} from './core/tbd0'
import {entityToVisuals, meshInjectPostProcess, applyEntityPropsToMesh} from './core/entityToVisuals'
import {exists} from './utils/obsUtils'
import {hasEntity,getEntity} from './utils/entityUtils'

let pjson = require('../package.json')
let appMetadata$ = Rx.Observable.just({
  name: pjson.name,
  version:pjson.version
})

  //interactions
  /*let inter = require('./core/intents.js')
  let intent = inter.Intent({
    objectsTransforms$ : glview.objectsTransform$,
    selectedMeshes$    : glview.selectedMeshes$,²
    selectedBomEntries$: selectBomEntries$,
    selectEntities$,

    //these indicate an issue, they should not need to be injected into an intent
    appState$: appState$,
    entities$:entities$,
    bom$:bom$,
  })

  intent.entityTransforms$
    .subscribe(updateEntities$)

  intent.entitiesToSelect$
    .subscribe( selectEntities$ )

  intent.bomEntriesToSelect$
    .subscribe( selectBomEntries2$ )
    */

function intent(interactions){
  let glviewInit$ = interactions.get(".glview","initialized$")
  let singleTaps$ = interactions.get(".glview","singleTaps$")
  let doubleTaps$ = interactions.get(".glview","doubleTaps$")
  let contextTaps$ = interactions.get(".glview","contextTaps$")
  let selectTransforms$ = interactions.get(".glview","selectionsTransforms$")

  /*singleTaps$.pluck("detail").subscribe(event => console.log("singleTaps",event))
  doubleTaps$.pluck("detail").subscribe(event => console.log("doubleTaps",event))
  contextTaps$.pluck("detail").subscribe(event => console.log("contextTaps",event))
  selectTransforms$.pluck("detail").subscribe(event => console.log("selectTransforms",event))*/

  let selections$ = interactions.get(".glview","selectedMeshes$")
    .pluck("detail")

  function hasNoEntity( input ){
    return !(input && input.userData && input.userData.entity)
  }

  selections$ = Rx.Observable.merge(
    selections$.filter(hasEntity).map(getEntity).map(e=>e.iuid),
    selections$.filter(hasNoEntity).map([])
  )

  return {
    selections$

  }
}

function settingsM(interactions){
  let showGrid$   = interactions.get(".settingsView .showGrid", "change").map(event => event.target.checked).startWith(false)
  let showAnnot$  = interactions.get(".settingsView .showAnnot", "change").map(event => event.target.checked).startWith(false)
  let autoRotate$ = interactions.get(".settingsView .autoRotate", "change").map(event => event.target.checked).startWith(false)

  /*function foobar(fieldName){
    return interactions.get(".settingsView "+fieldName, "change").map(event => event.target.checked).startWith(false)
  }
  let fieldNames = [".showGrid",".showAnnot",".autoRotate"]
  fieldNames.map(foobar)*/

  /*let bla$= combineTemplate(
    {
      camera:{
        autoRotate:autoRotate$
      },
      grid:{
        show:showGrid$
      },
      annotations:{
        show:showAnnot$
      }
    }
  )

  //bla$.subscribe(bla=>console.log("lkjfdsfsfsd",bla))*/
  //return bla$
  return Rx.Observable.combineLatest(
    showGrid$,
    autoRotate$,
    function(showGrid$,autoRotate$, showAnnot$){
      return (
        {
          camera:{
            autoRotate:autoRotate$
          },
          grid:{
            show:showGrid$
          },
          annotations:{
            show:showAnnot$
          }
        }
      )
    }
  )
}

function sources(urlSources$, dndSources$){
  //data sources
  let dataSources = require('./core/sources/dataSources').getDataSources
  let urlSources = require('./core/sources/urlSources')

  //urlSources.appMode$.subscribe( appMode => setSetting$({path:"mode",value:appMode}) )
  urlSources.settings$.subscribe(function(settings){
    console.log("settings from old",settings)
    const defaults = {
      persistent:false,
      lastDesignUri:undefined,
      lastDesignName:undefined,

      /*grid:{
        show:false,
      },
      annotations{
        show:false
      }*/
    }
    let _settings = Object.assign({},defaults,settings)

    /*updateDesign$({
      _persistent:_settings.persistent,
      uri:_settings.lastDesignUri,
      name:_settings.lastDesignName
    })*/
  })

  let {meshSources$, designSources$} = dataSources(dndSources$, urlSources)

  let settingsSources$ = urlSources.settings$

  meshSources$
    .subscribe(data => console.log("meshSources",data))

  return {meshSources$, designSources$, settingsSources$}
}

function App(interactions) {
  let activeTool = "translate"

  let dragOvers$ = interactions.subject("dragover")
  let drops$  = interactions.subject("drop")
  let dndSources$ = observableDragAndDrop(dragOvers$, drops$)
    //.subscribe(data => console.log("dndSources",data))
  let urlSources$ =null
  let {meshSources$, designSources$, settingsSources$} = sources(urlSources$, dndSources$)

  let settings$ = settingsM(interactions)

  let {kernel, assetManager} = makeInternals()

  let meshResources$ = meshResources(meshSources$, assetManager)
    //.subscribe(data=>console.log("mesh data",data))
  //doLotsOfThings(kernel,assetManager,meshSources$)

  //register meshes <=> types
  let partTypes = require('./core/partReg')
  let partTypes$ = partTypes({combos$:meshResources$})

  //get new instances from "types"
  let newInstFromTypes$ = entityInstanceFromPartTypes(partTypes$)
    //.subscribe(data=>console.log("mesh data",data))

  let intents = intent(interactions)
  intents.selections$
    .subscribe(data=>console.log("selections",data))

  let entities = require("./core/entityModel")

  intents = {
    createEntityInstance$:new Rx.Subject(),//createEntityInstance$,
    addEntities$: newInstFromTypes$,//addEntityInstances$,

    updateEntities$: new Rx.Subject(),
    deleteEntities$: new Rx.Subject(),
    duplicateEntities$: new Rx.Subject(),
    deleteAllEntities$: new Rx.Subject(),
    selectEntities$: new Rx.Subject(),

    newDesign$: new Rx.Subject(),
  }
  let entities$ = entities(intents)

  //entities$
  //  .subscribe(data=>console.log("mesh data",data))
  //what is my visual for any given entity

  let otherData$ = partTypes$
    .zip(meshResources$,function(types, meshResource){

      console.log("types",types,"meshResource",meshResource)

      return {
        typeUid:types.meshNameToPartTypeUId[meshResource.resource.name],
        mesh:meshResource.mesh,
        resource:meshResource.resource
      }
    })
    /*.scan(function(acc,val){
      console.lot("acc",acc,"val",val)
      return acc[val.typeUid] = val.mesh
    },{})*/
  .subscribe(data=>console.log(" data",data))
  //entityToVisuals()

  /*let entitiesToMeshInstancesMap = new WeakMap()
  let meshInstancesToEntitiesMap = new WeakMap()//reverse map

  function entityVisual(entity){
  }

  entities$
  .skip(1)
  .combineLatest(partTypes$,
    function(entities,partTypes){

    }
  )
  .subscribe(data=>console.log(" data",data))
  */

  /*.flatMap(function(data){
    return Rx.Observable.from( kernel.getPartMeshInstance( data[0] ) )
  })
  .map(Rx.Observable.from)
  .subscribe(function(data){
    console.log("mesh data",data)
    //let foo$ = Rx.Observable.from( kernel.getPartMeshInstance(data.instances[0]) )
  })*/

  //let requestVisualForEntity$ = new Rx.Observable()

  let visualMappings$ = entities$
    .pluck("instances")
    .withLatestFrom(partTypes$,function(entries, types){

      console.log("entries",entries,"types",types)

      return entries.map(function(entity){
        let mesh = types.typeUidToTemplateMesh[entity.typeUid].clone()

        mesh = meshInjectPostProcess(mesh)
        mesh = applyEntityPropsToMesh({entity,mesh})

        return mesh
      })

    })
    /*.flatMap(function(items){
      return Rx.Observable.from(items)
    })*/
    //.filter(x=> types.indexOf(x.type) > -1 )

  return Rx.Observable
    .combineLatest(
      appMetadata$,
      entities$,
      settings$,
      visualMappings$,
      function(appMetadata, items, settings, visualMappings){

        console.log("items",items, items.instances)

        return (

{appMetadata.name}{appMetadata.version}

            <GlView
              activeTool={activeTool}
              settings={settings}
              items={items}
              visualMappings={visualMappings}
              className="glview"/>

            <SettingsView settings={settings} ></SettingsView>
            <FullScreenToggler/>
            <EntityInfos entities={items.instances} settings={settings} />

        )
      }
    )
}

App = Cycle.component('App', App)

export default App<|endoftext|>


<commit_before>var http = require('http');
var browserify = require('browserify');
var React = require('react');
var Navigation = require('navigation');
var NavigationShared = require('./NavigationShared');
var NavigationServer = require('./NavigationServer');
var PersonSearch = require('./PersonSearch');

http.createServer(function(req, res) {
	if (req.url === '/favicon.ico') {
		res.end();
		return;
	}
	if (req.url === '/app.js') {
		browserify('./NavigationClient.js', { standalone: 'NavigationClient' })
			.bundle()
			.pipe(res)
		return;
	}
	if (req.url.match(/^\/data\/search/)) {
		PersonSearch.search(1, function(people){
			res.write(JSON.stringify(people));
			res.end();
		});
		return;
	}
	Navigation.StateController.navigateLink(req.url);
	NavigationServer.getProps(function(props){
		Navigation.StateController.navigateLink(req.url);
		res.write('
')
		res.write(React.renderToString(React.createElement(NavigationShared.getContent(), props)));
		res.write('
')
		res.end();
	});
}).listen(8080);

function safeStringify(props) {
  return JSON.stringify(props).replace(/<\/script/g, '<\\/script').replace(/