<commit_before>(() => {
    'use strict';

    const ds = require('data-service');

    /**
     * @param {ng.IScope} $scope
     * @param {*} exportStorageService
     * @param {$log} $log
     * @param {Storage} storage
     * @param {User} user
     * @param {*} utils
     * @param {*} $state
     * @param {*} configService
     * @param {*} modalManager
     */
    const controller = ($scope,
                        $state,
                        configService,
                        exportStorageService,
                        $log,
                        storage,
                        user,
                        utils,
                        modalManager) => {
        class DesktopUpdateCtrl {

            /**
             * @type {'askDownload' | 'downloading' | 'installAndRun' | 'success' | 'fail' }
             */
            state = 'askDownload';
            progress = 0;
            error = null;
            isDownloading = false;
            _oldDesktop = false;
            _hasAccounts = false;
            _isCanceled = null;

            constructor() {
                if (!WavesApp.isDesktop()) {
                    $state.go(user.getActiveState('wallet'));
                }

                this._oldDesktop = utils.isVersionLte('1.4.0');
                this._showMoving = !this._oldDesktop;

                storage.load('userList').then(list => {
                    if (list && list.length > 0) {
                        this._hasAccounts = true;
                    }
                });

                // this._export();
            }

            tryExport() {
                const win = window.open('http://localhost:8888');
                setTimeout(() => {
                    window.addEventListener('message', event => {
                        if (event.data && event.data.migrationError != null) {
                            if (event.data.migrationError) {
                                win.close();
                                this.state = 'fail';
                                return storage.save('migrationSuccess', false);
                            } else {
                                const connectProvider = this._getConnectProvider(win);

                                exportStorageService.export({
                                    provider: connectProvider,
                                    attempts: 1000,
                                    timeout: 1500
                                });

                                exportStorageService.onData().then(result => {
                                    win.close();

                                    if (result.payload === 'ok') {
                                        $log.log('done');
                                        this.state = 'success';
                                        $scope.$apply();

                                        return storage.save('migrationSuccess', true);
                                    } else {
                                        win.close();
                                        this.state = 'fail';
                                        return storage.save('migrationSuccess', false);
                                    }
                                });
                            }
                        }
                    });
                    const content = '{migrationError: !!window.location.href.includes(\'error\') }';
                    win.eval(`window.opener.postMessage(${content}, '*')`);
                });
            }

            _export() {
                const connectProvider = this._getConnectProvider();

                exportStorageService.export({
                    provider: connectProvider,
                    attempts: 100,
                    timeout: 10000
                });

                exportStorageService.onData().then(result => {
                    if (result.payload === 'ok') {
                        $log.log('done');
                        this.state = 'success';
                        $scope.$apply();

                        return storage.save('migrationSuccess', true);
                    } else {
                        this.state = 'fail';

                        return storage.save('migrationSuccess', false);
                    }
                });
            }

            download() {
                this._isCanceled = false;
                const url = this._getDistUrl();
                const [fileName] = url.pathname.split('/').slice(-1);

                this.isDownloading = true;
                this.state = 'downloading';

                ds.utils.downloadFile(url, (progress) => {
                    this.progress = Math.ceil(progress);
                    $scope.$digest();
                }).then((content) => {
                    transfer('download', {
                        fileName,
                        fileContent: content
                    }).then(() => {
                        this.state = 'installAndRun';
                        this.isDownloading = false;
                        this._resetProgress();
                        $scope.$digest();
                    }).catch((e) => {
                        if (e.message === 'Cancel') {
                            this.state = 'askDownload';
                            this._resetProgress();
                        } else {
                            this.error = String(e);
                        }

                        this.isDownloading = false;
                        $scope.$digest();
                    });
                }).catch((e) => {
                    this.error = String(e);
                    $scope.$digest();
                });
            }

            _getDistUrl() {
                const urls = configService.get('DESKTOP_URLS');

                return new URL(urls[WavesApp.platform]);
            }

            _resetProgress() {
                this.progress = 0;
            }

            _toHome() {
                $state.go(user.getActiveState('wallet'));
            }

            _toMigration() {
                this._showMoving = true;
            }

            /**
             * @returns {ConnectProvider}
             */
            _getConnectProvider(win) {
                const origins = WavesApp.isProduction() ?
                    WavesApp.network.migration.origins :
                    '*';

                return new ds.connect.PostMessageConnectProvider({
                    win,
                    origins
                });
            }

            _tryAgain() {
                this.state = 'askDownload';
                exportStorageService.destroy();
                // this._export();
            }

            _cancelDownload() {
                this._isCanceled = true;
                this.state = 'askDownload';
                this._resetProgress();
                ds.utils.abortDownloading();
            }

            showFAQ() {
                modalManager.showMigrateFAQ();
            }

        }

        return new DesktopUpdateCtrl();
    };

    controller.$inject = [
        '$scope',
        '$state',
        'configService',
        'exportStorageService',
        '$log',
        'storage',
        'user',
        'utils',
        'modalManager'
    ];

    angular.module('app.desktopUpdate').controller('DesktopUpdateCtrl', controller);
})();
<commit_msg>DEXW-2225: change origins<commit_after>(() => {
    'use strict';

    const ds = require('data-service');

    /**
     * @param {ng.IScope} $scope
     * @param {*} exportStorageService
     * @param {$log} $log
     * @param {Storage} storage
     * @param {User} user
     * @param {*} utils
     * @param {*} $state
     * @param {*} configService
     * @param {*} modalManager
     */
    const controller = ($scope,
                        $state,
                        configService,
                        exportStorageService,
                        $log,
                        storage,
                        user,
                        utils,
                        modalManager) => {
        class DesktopUpdateCtrl {

            /**
             * @type {'askDownload' | 'downloading' | 'installAndRun' | 'success' | 'fail' }
             */
            state = 'askDownload';
            progress = 0;
            error = null;
            isDownloading = false;
            _oldDesktop = false;
            _hasAccounts = false;
            _isCanceled = null;

            constructor() {
                if (!WavesApp.isDesktop()) {
                    $state.go(user.getActiveState('wallet'));
                }

                this._oldDesktop = utils.isVersionLte('1.4.0');
                this._showMoving = !this._oldDesktop;

                storage.load('userList').then(list => {
                    if (list && list.length > 0) {
                        this._hasAccounts = true;
                    }
                });

                // this._export();
            }

            tryExport() {
                const win = window.open('http://localhost:8888');
                setTimeout(() => {
                    window.addEventListener('message', event => {
                        if (event.data && event.data.migrationError != null) {
                            if (event.data.migrationError) {
                                win.close();
                                this.state = 'fail';
                                return storage.save('migrationSuccess', false);
                            } else {
                                const connectProvider = this._getConnectProvider(win);

                                exportStorageService.export({
                                    provider: connectProvider,
                                    attempts: 1000,
                                    timeout: 1500
                                });

                                exportStorageService.onData().then(result => {
                                    win.close();

                                    if (result.payload === 'ok') {
                                        $log.log('done');
                                        this.state = 'success';
                                        $scope.$apply();

                                        return storage.save('migrationSuccess', true);
                                    } else {
                                        win.close();
                                        this.state = 'fail';
                                        return storage.save('migrationSuccess', false);
                                    }
                                });
                            }
                        }
                    });
                    const content = '{migrationError: !!window.location.href.includes(\'error\') }';
                    win.eval(`window.opener.postMessage(${content}, '*')`);
                });
            }

            _export() {
                const connectProvider = this._getConnectProvider();

                exportStorageService.export({
                    provider: connectProvider,
                    attempts: 100,
                    timeout: 10000
                });

                exportStorageService.onData().then(result => {
                    if (result.payload === 'ok') {
                        $log.log('done');
                        this.state = 'success';
                        $scope.$apply();

                        return storage.save('migrationSuccess', true);
                    } else {
                        this.state = 'fail';

                        return storage.save('migrationSuccess', false);
                    }
                });
            }

            download() {
                this._isCanceled = false;
                const url = this._getDistUrl();
                const [fileName] = url.pathname.split('/').slice(-1);

                this.isDownloading = true;
                this.state = 'downloading';

                ds.utils.downloadFile(url, (progress) => {
                    this.progress = Math.ceil(progress);
                    $scope.$digest();
                }).then((content) => {
                    transfer('download', {
                        fileName,
                        fileContent: content
                    }).then(() => {
                        this.state = 'installAndRun';
                        this.isDownloading = false;
                        this._resetProgress();
                        $scope.$digest();
                    }).catch((e) => {
                        if (e.message === 'Cancel') {
                            this.state = 'askDownload';
                            this._resetProgress();
                        } else {
                            this.error = String(e);
                        }

                        this.isDownloading = false;
                        $scope.$digest();
                    });
                }).catch((e) => {
                    this.error = String(e);
                    $scope.$digest();
                });
            }

            _getDistUrl() {
                const urls = configService.get('DESKTOP_URLS');

                return new URL(urls[WavesApp.platform]);
            }

            _resetProgress() {
                this.progress = 0;
            }

            _toHome() {
                $state.go(user.getActiveState('wallet'));
            }

            _toMigration() {
                this._showMoving = true;
            }

            /**
             * @returns {ConnectProvider}
             */
            _getConnectProvider(win) {
                const origins = '*';

                return new ds.connect.PostMessageConnectProvider({
                    win,
                    origins
                });
            }

            _tryAgain() {
                this.state = 'askDownload';
                exportStorageService.destroy();
                // this._export();
            }

            _cancelDownload() {
                this._isCanceled = true;
                this.state = 'askDownload';
                this._resetProgress();
                ds.utils.abortDownloading();
            }

            showFAQ() {
                modalManager.showMigrateFAQ();
            }

        }

        return new DesktopUpdateCtrl();
    };

    controller.$inject = [
        '$scope',
        '$state',
        'configService',
        'exportStorageService',
        '$log',
        'storage',
        'user',
        'utils',
        'modalManager'
    ];

    angular.module('app.desktopUpdate').controller('DesktopUpdateCtrl', controller);
})();
<|endoftext|>


<commit_before>/*
 * Ship Command
 *
 * Blame Kawaiibot
 *
 * Contributed by Capuccino
 */

exports.commands = [
    'ship'
];

exports.ship = {
    desc: 'basically a ship command.',
    longDesc: 'Happy Shipping!',
    usage: '<user Mention (Maximum 2)>',
    main: (bot, ctx) => {
        return new Promise((resolve,reject) => {
            if(ctx.msg.mentions.length < 2) {
                ctx.msg.channel.createMessage('Specify at least two users').then(() => reject(new Error('No User Specified'))).catch(reject);
            } else {
                let waifu1 = ctx.msg.mentions[0];
                let waifu2 = ctx.msg.mentions[1];
                let result = waifu1.username.substring(0, Math.floor(waifu1.username.length / 2)) + waifu2.username.substring(Math.floor(waifu2.username.length / 2));
                ctx.msg.channel.createMessage(`Happy Shipping!\n Your ship name is **${result}**`);
            }
        });
    }
};<commit_msg>I fucked up<commit_after>/*
 * Ship Command
 *
 * Blame Kawaiibot
 *
 * Contributed by Capuccino
 */

exports.commands = [
    'ship'
];

exports.ship = {
    desc: 'Happy Shipping!',
    usage: '<2 Names (Mention or Regular Msg)>',
    main: (bot, ctx) => {
        return new Promise((resolve, reject) => {
            if (ctx.msg.mentions.length > 2 || ctx.args.length > 2) {
                ctx.msg.channel.createMessage('Give me at least two names').then(() => reject(new Error('Now you fucked up.'))).catch(reject);
            } else {
                let senpai = ctx.msg.mentions[0] ? ctx.msg.mentions[0].username : ctx.args[0];
                let kouhai = ctx.msg.mentions[1] ? ctx.msg.mentions[1].username : ctx.args[1];
                let result = senpai.substring(0, Math.floor(senpai.length / 2)) + kouhai.substring(Math.floor(kouhai.length / 2));
                ctx.msg.channel.createMessage(`Happy Shipping!\n Your Ship name is : **${result}**!\n _Disclaimer: We are not responsible if you get attacked by a Yandere prior from this._`).then(() => resolve).catch(reject);
            }
        });
    }
};<|endoftext|>


<commit_before>define(['knockout',
				'jquery',
				'text!./report.html',
				'webapi/IRAnalysisAPI',
				'd3',
				'databindings',
				'../databindings/irTreemapLegend',
				'css!cohortbuilder/css/report.css'
], function (
	ko,
	$,
	template,
	irAPI,
	d3) {

	function bitCounter(bits) {
		counted = 0;
		for (b = 0; b < bits.length; b++) {
			if (bits[b] == '1') {
				counted++;
			}
		}
		return counted;
	}

	function IRAnalysisReportsViewer(params) {
		var self = this;
		var colors = ["#2c7bb6", "#00a6ca","#00ccbc","#90eb9d","#ffff8c","#f9d057","#f29e2e","#e76818","#d7191c"];

		self.report = params.report;
		self.targetCohortId = params.target;
		self.outcomeCohortId = params.outcome;
		self.calculateRate = params.calculateRate;
		self.calculateProportion = params.calculateProportion;
		self.rateModifiers = params.rateModifiers;
		self.rateCaption = params.rateCaption;
		self.ipCaption = params.ipCaption;
		self.rectSummary = ko.observable();
		self.pass = ko.observableArray();
		self.fail = ko.observableArray();

		// behaviors

		self.treeIRExtent = ko.pureComputed(function() {
			var rates = [];
			function traverse(node) {
				if (node.hasOwnProperty("timeAtRisk")  && node.timeAtRisk > 0 && node.cases > 0) {
					rates.push(node.cases / node.timeAtRisk)
				}
				if (node.hasOwnProperty("children")) {
					node.children.forEach(function (child) {
						traverse(child);
					});
				}
			}

			traverse(JSON.parse(self.report().treemapData));
			var extent = d3.extent(rates);
			return [extent[0], Math.max(extent[0] * 1.001, extent[1])]; // padd the upper bound in the case where there is only 1 incidence rate calculated and we want to have an extent > 0
		});

		self.colorPicker = ko.pureComputed(function() {

			var extent = self.treeIRExtent();

			var color = d3.scale.quantize()
				.domain([extent[0], extent[1]])
				.range(colors);

			var picker = function(d) {
				if (d.cases == 0)
					return "#000000";
				else if (d.timeAtRisk > 0)
					return color(d.cases/d.timeAtRisk);
				else
					return "#bababa";

			};
			picker.scale = color;
			return picker;
		});

		self.describeClear = function () {
			self.rectSummary(null);
			self.pass.removeAll();
			self.fail.removeAll();
		}

		self.describe = function (bits, size, cases, timeAtRisk) {
			var matched = bitCounter(bits);
			var pass_count = 0;
			var fail_count = 0;
			var passed = [];
			var failed = [];

			for (b = 0; b < bits.length; b++) {
				if (bits[b] == '1') {
					passed.push(self.report().stratifyStats[b]);
					pass_count++;
				} else {
					failed.push(self.report().stratifyStats[b]);
					fail_count++;
				}
			}

			var percentage = 0;
			if (self.report().summary.totalPersons > 0) {
				percentage = (size / self.report().summary.totalPersons * 100);
			}
			self.pass(passed);
			self.fail(failed);
			//self.rectSummary(`${size people} (${percentage.toFixed(2)}%), ${pass_count} criteria passed, ${fail_count} criteria failed.`);
			self.rectSummary(`${size.toLocaleString()} (${percentage.toFixed(2)}%) people, ${cases.toLocaleString()} cases, ${timeAtRisk.toLocaleString()} TAR, Rate: ${self.calculateRate(cases, timeAtRisk)}
${pass_count} criteria passed, ${fail_count} criteria failed.`);
		}

		self.handleCellOver = function (data, event) {
			if (event.target.__data__) {
				var treemapDatum = event.target.__data__;
				self.describe(treemapDatum.name, treemapDatum.size, treemapDatum.cases, treemapDatum.timeAtRisk);
			} else {
				return false;
			}
		}

		self.treemapOptions = ko.pureComputed(function() {
			var options = {};
			options.colorPicker = self.colorPicker();
			return options;
		});

	}

	var component = {
		viewModel: IRAnalysisReportsViewer,
		template: template
	};

	return component;
});<commit_msg>Added rate label to treeview.<commit_after>define(['knockout',
				'jquery',
				'text!./report.html',
				'webapi/IRAnalysisAPI',
				'd3',
				'databindings',
				'../databindings/irTreemapLegend',
				'css!cohortbuilder/css/report.css'
], function (
	ko,
	$,
	template,
	irAPI,
	d3) {

	function bitCounter(bits) {
		counted = 0;
		for (b = 0; b < bits.length; b++) {
			if (bits[b] == '1') {
				counted++;
			}
		}
		return counted;
	}

	function IRAnalysisReportsViewer(params) {
		var self = this;
		var colors = ["#2c7bb6", "#00a6ca","#00ccbc","#90eb9d","#ffff8c","#f9d057","#f29e2e","#e76818","#d7191c"];

		self.report = params.report;
		self.targetCohortId = params.target;
		self.outcomeCohortId = params.outcome;
		self.calculateRate = params.calculateRate;
		self.calculateProportion = params.calculateProportion;
		self.rateModifiers = params.rateModifiers;
		self.rateCaption = params.rateCaption;
		self.ipCaption = params.ipCaption;
		self.rectSummary = ko.observable();
		self.pass = ko.observableArray();
		self.fail = ko.observableArray();

		// behaviors

		self.treeIRExtent = ko.pureComputed(function() {
			var rates = [];
			function traverse(node) {
				if (node.hasOwnProperty("timeAtRisk")  && node.timeAtRisk > 0 && node.cases > 0) {
					rates.push(node.cases / node.timeAtRisk)
				}
				if (node.hasOwnProperty("children")) {
					node.children.forEach(function (child) {
						traverse(child);
					});
				}
			}

			traverse(JSON.parse(self.report().treemapData));
			var extent = d3.extent(rates);
			return [extent[0], Math.max(extent[0] * 1.001, extent[1])]; // padd the upper bound in the case where there is only 1 incidence rate calculated and we want to have an extent > 0
		});

		self.colorPicker = ko.pureComputed(function() {

			var extent = self.treeIRExtent();

			var color = d3.scale.quantize()
				.domain([extent[0], extent[1]])
				.range(colors);

			var picker = function(d) {
				if (d.cases == 0)
					return "#000000";
				else if (d.timeAtRisk > 0)
					return color(d.cases/d.timeAtRisk);
				else
					return "#bababa";

			};
			picker.scale = color;
			return picker;
		});

		self.describeClear = function () {
			self.rectSummary(null);
			self.pass.removeAll();
			self.fail.removeAll();
		}

		self.describe = function (bits, size, cases, timeAtRisk) {
			var matched = bitCounter(bits);
			var pass_count = 0;
			var fail_count = 0;
			var passed = [];
			var failed = [];

			for (b = 0; b < bits.length; b++) {
				if (bits[b] == '1') {
					passed.push(self.report().stratifyStats[b]);
					pass_count++;
				} else {
					failed.push(self.report().stratifyStats[b]);
					fail_count++;
				}
			}

			var percentage = 0;
			if (self.report().summary.totalPersons > 0) {
				percentage = (size / self.report().summary.totalPersons * 100);
			}
			self.pass(passed);
			self.fail(failed);
			//self.rectSummary(`${size people} (${percentage.toFixed(2)}%), ${pass_count} criteria passed, ${fail_count} criteria failed.`);
			self.rectSummary(`${cases.toLocaleString()} cases, ${timeAtRisk.toLocaleString()} TAR, Rate: ${self.calculateRate(cases, timeAtRisk)} ${self.rateCaption()}
${size.toLocaleString()} (${percentage.toFixed(2)}%) people, ${pass_count} criteria passed, ${fail_count} criteria failed.`);
		}

		self.handleCellOver = function (data, event) {
			if (event.target.__data__) {
				var treemapDatum = event.target.__data__;
				self.describe(treemapDatum.name, treemapDatum.size, treemapDatum.cases, treemapDatum.timeAtRisk);
			} else {
				return false;
			}
		}

		self.treemapOptions = ko.pureComputed(function() {
			var options = {};
			options.colorPicker = self.colorPicker();
			return options;
		});

	}

	var component = {
		viewModel: IRAnalysisReportsViewer,
		template: template
	};

	return component;
});<|endoftext|>


<commit_before>
/* Event-rendering and event-interaction methods for the abstract Grid class
----------------------------------------------------------------------------------------------------------------------*/

$.extend(Grid.prototype, {

	isMouseOverSeg: false, // is the user's mouse over a segment?
	isDraggingSeg: false, // is a segment being dragged?
	isResizingSeg: false, // is a segment being resized?

	// Renders the given events onto the grid
	renderEvents: function(events) {
		// subclasses must implement
	},

	// Retrieves all rendered segment objects in this grid
	getSegs: function() {
		// subclasses must implement
	},

	// Unrenders all events
	destroyEvents: function() {
		// subclasses must implement
	},

	// Renders a `el` property for each seg, and only returns segments that successfully rendered
	renderSegs: function(segs, disableResizing) {
		var view = this.view;
		var html = '';
		var renderedSegs = [];
		var i;

		// build a large concatenation of event segment HTML
		for (i = 0; i < segs.length; i++) {
			html += this.renderSegHtml(segs[i], disableResizing);
		}

		// Grab individual elements from the combined HTML string. Use each as the default rendering.
		// Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false.
		$(html).each(function(i, node) {
			var seg = segs[i];
			var el = view.resolveEventEl(seg.event, $(node));
			if (el) {
				el.data('fc-seg', seg); // used by handlers
				seg.el = el;
				renderedSegs.push(seg);
			}
		});

		return renderedSegs;
	},

	// Generates the HTML for the default rendering of a segment
	renderSegHtml: function(seg, disableResizing) {
		// subclasses must implement
	},

	// Converts an array of event objects into an array of segment objects
	eventsToSegs: function(events, intervalStart, intervalEnd) {
		var _this = this;

		return $.map(events, function(event) {
			return _this.eventToSegs(event, intervalStart, intervalEnd); // $.map flattens all returned arrays together
		});
	},

	// Slices a single event into an array of event segments.
	// When `intervalStart` and `intervalEnd` are specified, intersect the events with that interval.
	// Otherwise, let the subclass decide how it wants to slice the segments over the grid.
	eventToSegs: function(event, intervalStart, intervalEnd) {
		var eventStart = event.start.clone().stripZone(); // normalize
		var eventEnd = this.view.calendar.getEventEnd(event).stripZone(); // compute (if necessary) and normalize
		var segs;
		var i, seg;

		if (intervalStart && intervalEnd) {
			seg = intersectionToSeg(eventStart, eventEnd, intervalStart, intervalEnd);
			segs = seg ? [ seg ] : [];
		}
		else {
			segs = this.rangeToSegs(eventStart, eventEnd); // defined by the subclass
		}

		// assign extra event-related properties to the segment objects
		for (i = 0; i < segs.length; i++) {
			seg = segs[i];
			seg.event = event;
			seg.eventStartMS = +eventStart;
			seg.eventDurationMS = eventEnd - eventStart;
		}

		return segs;
	},

	/* Handlers
	------------------------------------------------------------------------------------------------------------------*/

	// Attaches event-element-related handlers to the container element and leverage bubbling
	bindSegHandlers: function() {
		var _this = this;
		var view = this.view;

		$.each(
			{
				mouseenter: function(seg, ev) {
					_this.triggerSegMouseover(seg, ev);
				},
				mouseleave: function(seg, ev) {
					_this.triggerSegMouseout(seg, ev);
				},
				click: function(seg, ev) {
					return view.trigger('eventClick', this, seg.event, ev); // can return `false` to cancel
				},
				mousedown: function(seg, ev) {
					if ($(ev.target).is('.fc-resizer') && view.isEventResizable(seg.event)) {
						_this.segResizeMousedown(seg, ev);
					}
					else if (view.isEventDraggable(seg.event)) {
						_this.segDragMousedown(seg, ev);
					}
				}
			},
			function(name, func) {
				// attach the handler to the container element and only listen for real event elements via bubbling
				_this.el.on(name, '.fc-event-container > *', function(ev) {
					var seg = $(this).data('fc-seg'); // grab segment data. put there by View::renderEvents

					// only call the handlers if there is not a drag/resize in progress
					if (seg && !_this.isDraggingSeg && !_this.isResizingSeg) {
						func.call(this, seg, ev); // `this` will be the event element
					}
				});
			}
		);
	},

	// Updates internal state and triggers handlers for when an event element is moused over
	triggerSegMouseover: function(seg, ev) {
		if (!this.isMouseOverSeg) {
			this.isMouseOverSeg = true;
			this.view.trigger('eventMouseover', seg.el[0], seg.event, ev);
		}
	},

	// Updates internal state and triggers handlers for when an event element is moused out
	triggerSegMouseout: function(seg, ev) {
		if (this.isMouseOverSeg) {
			this.isMouseOverSeg = false;
			this.view.trigger('eventMouseout', seg.el[0], seg.event, ev);
		}
	},

	/* Dragging
	------------------------------------------------------------------------------------------------------------------*/

	// Called when the user does a mousedown on an event, which might lead to dragging.
	// Generic enough to work with any type of Grid.
	segDragMousedown: function(seg, ev) {
		var _this = this;
		var view = this.view;
		var el = seg.el;
		var event = seg.event;
		var newStart, newEnd;

		// A clone of the original element that will move with the mouse
		var mouseFollower = new MouseFollower(seg.el, {
			parentEl: view.el,
			opacity: view.opt('dragOpacity'),
			revertDuration: view.opt('dragRevertDuration'),
			zIndex: 2 // one above the .fc-view
		});

		// Tracks mouse movement over the *view's* coordinate map. Allows dragging and dropping between subcomponents
		// of the view.
		var dragListener = new DragListener(view.coordMap, {
			distance: 5,
			scroll: view.opt('dragScroll'),
			listenStart: function(ev) {
				mouseFollower.hide(); // don't show until we know this is a real drag
				mouseFollower.start(ev);
			},
			dragStart: function(ev) {
				_this.triggerSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
				_this.isDraggingSeg = true;
				view.hideEvent(event); // hide all event segments. our mouseFollower will take over
				view.trigger('eventDragStart', el[0], event, ev, {}); // last argument is jqui dummy
			},
			cellOver: function(cell, date) {
				var origDate = seg.cellDate || dragListener.origDate;
				var res = _this.computeDraggedEventDates(seg, origDate, date);
				newStart = res.start;
				newEnd = res.end;

				if (view.renderDrag(newStart, newEnd, seg)) { // have the view render a visual indication
					mouseFollower.hide(); // if the view is already using a mock event "helper", hide our own
				}
				else {
					mouseFollower.show();
				}
			},
			cellOut: function() { // called before mouse moves to a different cell OR moved out of all cells
				newStart = null;
				view.destroyDrag(); // unrender whatever was done in view.renderDrag
				mouseFollower.show(); // show in case we are moving out of all cells
			},
			dragStop: function(ev) {
				var hasChanged = newStart && !newStart.isSame(event.start);

				// do revert animation if hasn't changed. calls a callback when finished (whether animation or not)
				mouseFollower.stop(!hasChanged, function() {
					_this.isDraggingSeg = false;
					view.destroyDrag();
					view.showEvent(event);
					view.trigger('eventDragStop', el[0], event, ev, {}); // last argument is jqui dummy

					if (hasChanged) {
						view.eventDrop(el[0], event, newStart, ev); // will rerender all events...
					}
				});
			},
			listenStop: function() {
				mouseFollower.stop(); // put in listenStop in case there was a mousedown but the drag never started
			}
		});

		dragListener.mousedown(ev); // start listening, which will eventually lead to a dragStart
	},

	// Given a segment, the dates where a drag began and ended, calculates the Event Object's new start and end dates
	computeDraggedEventDates: function(seg, dragStartDate, dropDate) {
		var view = this.view;
		var event = seg.event;
		var start = event.start;
		var end = view.calendar.getEventEnd(event);
		var delta;
		var newStart;
		var newEnd;

		if (dropDate.hasTime() === dragStartDate.hasTime()) {
			delta = dayishDiff(dropDate, dragStartDate);
			newStart = start.clone().add(delta);
			if (event.end === null) { // do we need to compute an end?
				newEnd = null;
			}
			else {
				newEnd = end.clone().add(delta);
			}
		}
		else {
			// if switching from day <-> timed, start should be reset to the dropped date, and the end cleared
			newStart = dropDate;
			newEnd = null; // end should be cleared
		}

		return { start: newStart, end: newEnd };
	},

	/* Resizing
	------------------------------------------------------------------------------------------------------------------*/

	// Called when the user does a mousedown on an event's resizer, which might lead to resizing.
	// Generic enough to work with any type of Grid.
	segResizeMousedown: function(seg, ev) {
		var _this = this;
		var view = this.view;
		var el = seg.el;
		var event = seg.event;
		var start = event.start;
		var end = view.calendar.getEventEnd(event);
		var newEnd = null;
		var dragListener;

		function destroy() { // resets the rendering
			_this.destroyResize();
			view.showEvent(event);
		}

		// Tracks mouse movement over the *grid's* coordinate map
		dragListener = new DragListener(this.coordMap, {
			distance: 5,
			scroll: view.opt('dragScroll'),
			dragStart: function(ev) {
				_this.triggerSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
				_this.isResizingSeg = true;
				view.trigger('eventResizeStart', el[0], event, ev, {}); // last argument is jqui dummy
			},
			cellOver: function(cell, date) {
				// compute the new end. don't allow it to go before the event's start
				if (date < start) {
					date = start;
				}
				newEnd = date.clone().add(_this.cellDuration); // make it an exclusive end

				if (newEnd.isSame(end)) {
					newEnd = null;
					destroy();
				}
				else {
					_this.renderResize(start, newEnd, seg);
					view.hideEvent(event);
				}
			},
			cellOut: function() { // called before mouse moves to a different cell OR moved out of all cells
				newEnd = null;
				destroy();
			},
			dragStop: function(ev) {
				_this.isResizingSeg = false;
				destroy();
				view.trigger('eventResizeStop', el[0], event, ev, {}); // last argument is jqui dummy

				if (newEnd) {
					view.eventResize(el[0], event, newEnd, ev); // will rerender all events...
				}
			}
		});

		dragListener.mousedown(ev); // start listening, which will eventually lead to a dragStart
	},

	/* Rendering Utils
	------------------------------------------------------------------------------------------------------------------*/

	// Generic utility for generating the HTML classNames for an event segment's element
	getSegClasses: function(seg, isDraggable, isResizable) {
		var event = seg.event;
		var classes = [
			'fc-event',
			seg.isStart ? 'fc-start' : 'fc-not-start',
			seg.isEnd ? 'fc-end' : 'fc-not-end'
		].concat(
			event.className,
			event.source ? event.source.className : []
		);

		if (isDraggable) {
			classes.push('fc-draggable');
		}
		if (isResizable) {
			classes.push('fc-resizable');
		}

		return classes;
	},

	// Utility for generating a CSS string with all the event skin-related properties
	getEventSkinCss: function(event) {
		var view = this.view;
		var source = event.source || {};
		var eventColor = event.color;
		var sourceColor = source.color;
		var optionColor = view.opt('eventColor');
		var backgroundColor =
			event.backgroundColor ||
			eventColor ||
			source.backgroundColor ||
			sourceColor ||
			view.opt('eventBackgroundColor') ||
			optionColor;
		var borderColor =
			event.borderColor ||
			eventColor ||
			source.borderColor ||
			sourceColor ||
			view.opt('eventBorderColor') ||
			optionColor;
		var textColor =
			event.textColor ||
			source.textColor ||
			view.opt('eventTextColor');
		var statements = [];
		if (backgroundColor) {
			statements.push('background-color:' + backgroundColor);
		}
		if (borderColor) {
			statements.push('border-color:' + borderColor);
		}
		if (textColor) {
			statements.push('color:' + textColor);
		}
		return statements.join(';');
	}

});

/* Event Segment Utilities
----------------------------------------------------------------------------------------------------------------------*/

// A cmp function for determining which segments should take visual priority
function compareSegs(seg1, seg2) {
	return seg1.eventStartMS - seg2.eventStartMS || // earlier events go first
		seg2.eventDurationMS - seg1.eventDurationMS || // tie? longer events go first
		seg2.event.allDay - seg1.event.allDay || // tie? put all-day events first (booleans cast to 0/1)
		(seg1.event.title || '').localeCompare(seg2.event.title); // tie? alphabetically by title
}

<commit_msg>fix bug with resizing events with timezones in agenda slots<commit_after>
/* Event-rendering and event-interaction methods for the abstract Grid class
----------------------------------------------------------------------------------------------------------------------*/

$.extend(Grid.prototype, {

	isMouseOverSeg: false, // is the user's mouse over a segment?
	isDraggingSeg: false, // is a segment being dragged?
	isResizingSeg: false, // is a segment being resized?

	// Renders the given events onto the grid
	renderEvents: function(events) {
		// subclasses must implement
	},

	// Retrieves all rendered segment objects in this grid
	getSegs: function() {
		// subclasses must implement
	},

	// Unrenders all events
	destroyEvents: function() {
		// subclasses must implement
	},

	// Renders a `el` property for each seg, and only returns segments that successfully rendered
	renderSegs: function(segs, disableResizing) {
		var view = this.view;
		var html = '';
		var renderedSegs = [];
		var i;

		// build a large concatenation of event segment HTML
		for (i = 0; i < segs.length; i++) {
			html += this.renderSegHtml(segs[i], disableResizing);
		}

		// Grab individual elements from the combined HTML string. Use each as the default rendering.
		// Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false.
		$(html).each(function(i, node) {
			var seg = segs[i];
			var el = view.resolveEventEl(seg.event, $(node));
			if (el) {
				el.data('fc-seg', seg); // used by handlers
				seg.el = el;
				renderedSegs.push(seg);
			}
		});

		return renderedSegs;
	},

	// Generates the HTML for the default rendering of a segment
	renderSegHtml: function(seg, disableResizing) {
		// subclasses must implement
	},

	// Converts an array of event objects into an array of segment objects
	eventsToSegs: function(events, intervalStart, intervalEnd) {
		var _this = this;

		return $.map(events, function(event) {
			return _this.eventToSegs(event, intervalStart, intervalEnd); // $.map flattens all returned arrays together
		});
	},

	// Slices a single event into an array of event segments.
	// When `intervalStart` and `intervalEnd` are specified, intersect the events with that interval.
	// Otherwise, let the subclass decide how it wants to slice the segments over the grid.
	eventToSegs: function(event, intervalStart, intervalEnd) {
		var eventStart = event.start.clone().stripZone(); // normalize
		var eventEnd = this.view.calendar.getEventEnd(event).stripZone(); // compute (if necessary) and normalize
		var segs;
		var i, seg;

		if (intervalStart && intervalEnd) {
			seg = intersectionToSeg(eventStart, eventEnd, intervalStart, intervalEnd);
			segs = seg ? [ seg ] : [];
		}
		else {
			segs = this.rangeToSegs(eventStart, eventEnd); // defined by the subclass
		}

		// assign extra event-related properties to the segment objects
		for (i = 0; i < segs.length; i++) {
			seg = segs[i];
			seg.event = event;
			seg.eventStartMS = +eventStart;
			seg.eventDurationMS = eventEnd - eventStart;
		}

		return segs;
	},

	/* Handlers
	------------------------------------------------------------------------------------------------------------------*/

	// Attaches event-element-related handlers to the container element and leverage bubbling
	bindSegHandlers: function() {
		var _this = this;
		var view = this.view;

		$.each(
			{
				mouseenter: function(seg, ev) {
					_this.triggerSegMouseover(seg, ev);
				},
				mouseleave: function(seg, ev) {
					_this.triggerSegMouseout(seg, ev);
				},
				click: function(seg, ev) {
					return view.trigger('eventClick', this, seg.event, ev); // can return `false` to cancel
				},
				mousedown: function(seg, ev) {
					if ($(ev.target).is('.fc-resizer') && view.isEventResizable(seg.event)) {
						_this.segResizeMousedown(seg, ev);
					}
					else if (view.isEventDraggable(seg.event)) {
						_this.segDragMousedown(seg, ev);
					}
				}
			},
			function(name, func) {
				// attach the handler to the container element and only listen for real event elements via bubbling
				_this.el.on(name, '.fc-event-container > *', function(ev) {
					var seg = $(this).data('fc-seg'); // grab segment data. put there by View::renderEvents

					// only call the handlers if there is not a drag/resize in progress
					if (seg && !_this.isDraggingSeg && !_this.isResizingSeg) {
						func.call(this, seg, ev); // `this` will be the event element
					}
				});
			}
		);
	},

	// Updates internal state and triggers handlers for when an event element is moused over
	triggerSegMouseover: function(seg, ev) {
		if (!this.isMouseOverSeg) {
			this.isMouseOverSeg = true;
			this.view.trigger('eventMouseover', seg.el[0], seg.event, ev);
		}
	},

	// Updates internal state and triggers handlers for when an event element is moused out
	triggerSegMouseout: function(seg, ev) {
		if (this.isMouseOverSeg) {
			this.isMouseOverSeg = false;
			this.view.trigger('eventMouseout', seg.el[0], seg.event, ev);
		}
	},

	/* Dragging
	------------------------------------------------------------------------------------------------------------------*/

	// Called when the user does a mousedown on an event, which might lead to dragging.
	// Generic enough to work with any type of Grid.
	segDragMousedown: function(seg, ev) {
		var _this = this;
		var view = this.view;
		var el = seg.el;
		var event = seg.event;
		var newStart, newEnd;

		// A clone of the original element that will move with the mouse
		var mouseFollower = new MouseFollower(seg.el, {
			parentEl: view.el,
			opacity: view.opt('dragOpacity'),
			revertDuration: view.opt('dragRevertDuration'),
			zIndex: 2 // one above the .fc-view
		});

		// Tracks mouse movement over the *view's* coordinate map. Allows dragging and dropping between subcomponents
		// of the view.
		var dragListener = new DragListener(view.coordMap, {
			distance: 5,
			scroll: view.opt('dragScroll'),
			listenStart: function(ev) {
				mouseFollower.hide(); // don't show until we know this is a real drag
				mouseFollower.start(ev);
			},
			dragStart: function(ev) {
				_this.triggerSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
				_this.isDraggingSeg = true;
				view.hideEvent(event); // hide all event segments. our mouseFollower will take over
				view.trigger('eventDragStart', el[0], event, ev, {}); // last argument is jqui dummy
			},
			cellOver: function(cell, date) {
				var origDate = seg.cellDate || dragListener.origDate;
				var res = _this.computeDraggedEventDates(seg, origDate, date);
				newStart = res.start;
				newEnd = res.end;

				if (view.renderDrag(newStart, newEnd, seg)) { // have the view render a visual indication
					mouseFollower.hide(); // if the view is already using a mock event "helper", hide our own
				}
				else {
					mouseFollower.show();
				}
			},
			cellOut: function() { // called before mouse moves to a different cell OR moved out of all cells
				newStart = null;
				view.destroyDrag(); // unrender whatever was done in view.renderDrag
				mouseFollower.show(); // show in case we are moving out of all cells
			},
			dragStop: function(ev) {
				var hasChanged = newStart && !newStart.isSame(event.start);

				// do revert animation if hasn't changed. calls a callback when finished (whether animation or not)
				mouseFollower.stop(!hasChanged, function() {
					_this.isDraggingSeg = false;
					view.destroyDrag();
					view.showEvent(event);
					view.trigger('eventDragStop', el[0], event, ev, {}); // last argument is jqui dummy

					if (hasChanged) {
						view.eventDrop(el[0], event, newStart, ev); // will rerender all events...
					}
				});
			},
			listenStop: function() {
				mouseFollower.stop(); // put in listenStop in case there was a mousedown but the drag never started
			}
		});

		dragListener.mousedown(ev); // start listening, which will eventually lead to a dragStart
	},

	// Given a segment, the dates where a drag began and ended, calculates the Event Object's new start and end dates
	computeDraggedEventDates: function(seg, dragStartDate, dropDate) {
		var view = this.view;
		var event = seg.event;
		var start = event.start;
		var end = view.calendar.getEventEnd(event);
		var delta;
		var newStart;
		var newEnd;

		if (dropDate.hasTime() === dragStartDate.hasTime()) {
			delta = dayishDiff(dropDate, dragStartDate);
			newStart = start.clone().add(delta);
			if (event.end === null) { // do we need to compute an end?
				newEnd = null;
			}
			else {
				newEnd = end.clone().add(delta);
			}
		}
		else {
			// if switching from day <-> timed, start should be reset to the dropped date, and the end cleared
			newStart = dropDate;
			newEnd = null; // end should be cleared
		}

		return { start: newStart, end: newEnd };
	},

	/* Resizing
	------------------------------------------------------------------------------------------------------------------*/

	// Called when the user does a mousedown on an event's resizer, which might lead to resizing.
	// Generic enough to work with any type of Grid.
	segResizeMousedown: function(seg, ev) {
		var _this = this;
		var view = this.view;
		var el = seg.el;
		var event = seg.event;
		var start = event.start;
		var end = view.calendar.getEventEnd(event);
		var newEnd = null;
		var dragListener;

		function destroy() { // resets the rendering
			_this.destroyResize();
			view.showEvent(event);
		}

		// Tracks mouse movement over the *grid's* coordinate map
		dragListener = new DragListener(this.coordMap, {
			distance: 5,
			scroll: view.opt('dragScroll'),
			dragStart: function(ev) {
				_this.triggerSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
				_this.isResizingSeg = true;
				view.trigger('eventResizeStart', el[0], event, ev, {}); // last argument is jqui dummy
			},
			cellOver: function(cell, date) {
				// compute the new end. don't allow it to go before the event's start
				if (date.isBefore(start)) { // allows comparing ambig to non-ambig
					date = start;
				}
				newEnd = date.clone().add(_this.cellDuration); // make it an exclusive end

				if (newEnd.isSame(end)) {
					newEnd = null;
					destroy();
				}
				else {
					_this.renderResize(start, newEnd, seg);
					view.hideEvent(event);
				}
			},
			cellOut: function() { // called before mouse moves to a different cell OR moved out of all cells
				newEnd = null;
				destroy();
			},
			dragStop: function(ev) {
				_this.isResizingSeg = false;
				destroy();
				view.trigger('eventResizeStop', el[0], event, ev, {}); // last argument is jqui dummy

				if (newEnd) {
					view.eventResize(el[0], event, newEnd, ev); // will rerender all events...
				}
			}
		});

		dragListener.mousedown(ev); // start listening, which will eventually lead to a dragStart
	},

	/* Rendering Utils
	------------------------------------------------------------------------------------------------------------------*/

	// Generic utility for generating the HTML classNames for an event segment's element
	getSegClasses: function(seg, isDraggable, isResizable) {
		var event = seg.event;
		var classes = [
			'fc-event',
			seg.isStart ? 'fc-start' : 'fc-not-start',
			seg.isEnd ? 'fc-end' : 'fc-not-end'
		].concat(
			event.className,
			event.source ? event.source.className : []
		);

		if (isDraggable) {
			classes.push('fc-draggable');
		}
		if (isResizable) {
			classes.push('fc-resizable');
		}

		return classes;
	},

	// Utility for generating a CSS string with all the event skin-related properties
	getEventSkinCss: function(event) {
		var view = this.view;
		var source = event.source || {};
		var eventColor = event.color;
		var sourceColor = source.color;
		var optionColor = view.opt('eventColor');
		var backgroundColor =
			event.backgroundColor ||
			eventColor ||
			source.backgroundColor ||
			sourceColor ||
			view.opt('eventBackgroundColor') ||
			optionColor;
		var borderColor =
			event.borderColor ||
			eventColor ||
			source.borderColor ||
			sourceColor ||
			view.opt('eventBorderColor') ||
			optionColor;
		var textColor =
			event.textColor ||
			source.textColor ||
			view.opt('eventTextColor');
		var statements = [];
		if (backgroundColor) {
			statements.push('background-color:' + backgroundColor);
		}
		if (borderColor) {
			statements.push('border-color:' + borderColor);
		}
		if (textColor) {
			statements.push('color:' + textColor);
		}
		return statements.join(';');
	}

});

/* Event Segment Utilities
----------------------------------------------------------------------------------------------------------------------*/

// A cmp function for determining which segments should take visual priority
function compareSegs(seg1, seg2) {
	return seg1.eventStartMS - seg2.eventStartMS || // earlier events go first
		seg2.eventDurationMS - seg1.eventDurationMS || // tie? longer events go first
		seg2.event.allDay - seg1.event.allDay || // tie? put all-day events first (booleans cast to 0/1)
		(seg1.event.title || '').localeCompare(seg2.event.title); // tie? alphabetically by title
}

<|endoftext|>


<commit_before>//    render_fills.js - a snapsvg.io plugin to render the infill of svg files into a bitmap.
//    Copyright (C) 2015  Teja Philipp <osd@tejaphilipp.de>
//
//    based on work by http://davidwalsh.name/convert-canvas-image
//    and http://getcontext.net/read/svg-images-on-a-html5-canvas
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Affero General Public License as
//    published by the Free Software Foundation, either version 3 of the
//    License, or (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the GNU Affero General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Snap.plugin(function (Snap, Element, Paper, global) {

	/**
	 * @param {elem} elem start point
	 *
	 * @returns {path}
	 */

	Element.prototype.removeUnfilled = function(fillPaths){
		var elem = this;
		var selection = [];
		var children = elem.children();

		if (children.length > 0) {
			var goRecursive = (elem.type !== "defs" && // ignore these tags
				elem.type !== "clipPath" &&
				elem.type !== "metadata" &&
				elem.type !== "rdf:rdf" &&
				elem.type !== "cc:work" &&
				elem.type !== "sodipodi:namedview");

			if(goRecursive) {
				for (var i = 0; i < children.length; i++) {
					var child = children[i];
					selection = selection.concat(child.removeUnfilled(fillPaths));
				}
			}
		} else {
			if(elem.type === 'image'){
				selection.push(elem);
			} else {
				if(fillPaths && elem.is_filled()){
					selection.push(elem);
				} else {
					elem.remove();
				}
			}
		}
		return selection;
	};

	Element.prototype.is_filled = function(){
		var elem = this;

		// TODO text support
		// TODO opacity support
		if (elem.type !== "circle" &&
			elem.type !== "rect" &&
			elem.type !== "ellipse" &&
			elem.type !== "line" &&
			elem.type !== "polygon" &&
			elem.type !== "polyline" &&
			elem.type !== "path" ){

			return false;
		}

		var fill = elem.attr('fill');
		var opacity = elem.attr('fill-opacity');

		if(fill !== 'none'){
			if(opacity === null || opacity > 0){
				return true;
			}
		}
		return false;
	};

	Element.prototype.embedImage = function(callback){
		var elem = this;
		if(elem.type !== 'image') return;

		var url = elem.attr('href');
		var image = new Image();

		image.onload = function () {
			var canvas = document.createElement('canvas');
			canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
			canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size

			canvas.getContext('2d').drawImage(this, 0, 0);
			var dataUrl = canvas.toDataURL('image/png');
			elem.attr('href', dataUrl);
			canvas.remove();
			if(typeof callback === 'function'){
				callback(elem.attr('id'));
				console.log('embedded img');
			}
		};

		image.src = url;

	};

	Element.prototype.renderPNG = function (wMM, hMM, pxPerMM, callback) {
		var elem = this;

		// get svg as dataUrl
		var svgStr = elem.outerSVG();
		var svgDataUri = 'data:image/svg+xml;base64,' + window.btoa(svgStr);
		var source = new Image();
		source.src = svgDataUri;

		// init render canvas and attach to page
		var renderCanvas = document.createElement('canvas');
		renderCanvas.id = "renderCanvas";
		renderCanvas.width = wMM * pxPerMM;
		renderCanvas.height = hMM * pxPerMM;
		document.getElementsByTagName('body')[0].appendChild(renderCanvas);
		var renderCanvasContext = renderCanvas.getContext('2d');

		// render SVG image to the canvas once it loads.
		source.onload = function () {
			renderCanvasContext.drawImage(source, 0, 0, renderCanvas.width, renderCanvas.height);

			// place fill bitmap into svg
			var fillBitmap = renderCanvas.toDataURL("image/png");
			if(typeof callback === 'function'){
				callback(fillBitmap);
			}
			renderCanvas.remove();
		};

		// catch browsers without native svg support
		source.onerror = function() {
			console.error("Can't export! Maybe your browser doesn't support native SVG. Sorry.");
		};
	};

});

<commit_msg>added text to infill conversion<commit_after>//    render_fills.js - a snapsvg.io plugin to render the infill of svg files into a bitmap.
//    Copyright (C) 2015  Teja Philipp <osd@tejaphilipp.de>
//
//    based on work by http://davidwalsh.name/convert-canvas-image
//    and http://getcontext.net/read/svg-images-on-a-html5-canvas
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Affero General Public License as
//    published by the Free Software Foundation, either version 3 of the
//    License, or (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the GNU Affero General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Snap.plugin(function (Snap, Element, Paper, global) {

	/**
	 * @param {elem} elem start point
	 *
	 * @returns {path}
	 */

	Element.prototype.removeUnfilled = function(fillPaths){
		var elem = this;
		var selection = [];
		var children = elem.children();

		if (children.length > 0) {
			var goRecursive = (elem.type !== "defs" && // ignore these tags
				elem.type !== "clipPath" &&
				elem.type !== "metadata" &&
				elem.type !== "rdf:rdf" &&
				elem.type !== "cc:work" &&
				elem.type !== "sodipodi:namedview");

			if(goRecursive) {
				for (var i = 0; i < children.length; i++) {
					var child = children[i];
					selection = selection.concat(child.removeUnfilled(fillPaths));
				}
			}
		} else {
			if(elem.type === 'image'){
				selection.push(elem);
			} else {
				if(fillPaths && elem.is_filled()){
					selection.push(elem);
				} else {
					elem.remove();
				}
			}
		}
		return selection;
	};

	Element.prototype.is_filled = function(){
		var elem = this;

		// TODO text support --> check if working
		// TODO opacity support
		if (elem.type !== "circle" &&
			elem.type !== "rect" &&
			elem.type !== "ellipse" &&
			elem.type !== "line" &&
			elem.type !== "polygon" &&
			elem.type !== "polyline" &&
			elem.type !== "path" &&
			elem.type !== "text" &&
			elem.type !== "#text")
		{
			return false;
		}

		var fill = elem.attr('fill');
		var opacity = elem.attr('fill-opacity');

		if(fill !== 'none'){
			if(opacity === null || opacity > 0){
				return true;
			}
		}
		return false;
	};

	Element.prototype.embedImage = function(callback){
		var elem = this;
		if(elem.type !== 'image') return;

		var url = elem.attr('href');
		var image = new Image();

		image.onload = function () {
			var canvas = document.createElement('canvas');
			canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
			canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size

			canvas.getContext('2d').drawImage(this, 0, 0);
			var dataUrl = canvas.toDataURL('image/png');
			elem.attr('href', dataUrl);
			canvas.remove();
			if(typeof callback === 'function'){
				callback(elem.attr('id'));
				console.log('embedded img');
			}
		};

		image.src = url;

	};

	Element.prototype.renderPNG = function (wMM, hMM, pxPerMM, callback) {
		var elem = this;

		// get svg as dataUrl
		var svgStr = elem.outerSVG();
		var svgDataUri = 'data:image/svg+xml;base64,' + window.btoa(svgStr);
		var source = new Image();
		source.src = svgDataUri;

		// init render canvas and attach to page
		var renderCanvas = document.createElement('canvas');
		renderCanvas.id = "renderCanvas";
		renderCanvas.width = wMM * pxPerMM;
		renderCanvas.height = hMM * pxPerMM;
		document.getElementsByTagName('body')[0].appendChild(renderCanvas);
		var renderCanvasContext = renderCanvas.getContext('2d');

		// render SVG image to the canvas once it loads.
		source.onload = function () {
			renderCanvasContext.drawImage(source, 0, 0, renderCanvas.width, renderCanvas.height);

			// place fill bitmap into svg
			var fillBitmap = renderCanvas.toDataURL("image/png");
			if(typeof callback === 'function'){
				callback(fillBitmap);
			}
			renderCanvas.remove();
		};

		// catch browsers without native svg support
		source.onerror = function() {
			console.error("Can't export! Maybe your browser doesn't support native SVG. Sorry.");
		};
	};

});

<|endoftext|>


<commit_before>/*jslint browser: true, nomen: true, vars: true*/
/*global define*/

define(function (require) {
    'use strict';

    var $ = require('jquery');
    var _jqueryUI = require('jquery-ui');
    var _ = require('underscore');
    var Backbone = require('backbone');

    var __ = require('oro/translator');
    var DeleteConfirmation = require('oro/delete-confirmation');

    var constants = require('oro/sidebar/constants');

    var IconView = require('oro/sidebar/widget-container/icon-view');
    var WidgetContainerView = require('oro/sidebar/widget-container/view');
    var WidgetAddView = require('oro/sidebar/widget-container/widget-add-view');
    var WidgetSetupView = require('oro/sidebar/widget-container/widget-setup-view');

    var sidebarTemplate = require('text!oro/sidebar/sidebar/template');

    /**
     * @export  oro/sidebar/sidebar/view
     * @class oro.sidebar.sidebar.View
     * @extends Backbone.View
     */
    var SidebarView = Backbone.View.extend({
        template: _.template(sidebarTemplate),

        events: {
            'click .sidebar-add a': 'onClickAdd',
            'click .sidebar-resize a': 'onClickToggle',
            'click .sidebar-toggle a': 'onClickToggle'
        },

        initialize: function () {
            var view = this;
            var model = view.model;

            view.iconViews = {};
            view.hoverViews = {};
            view.widgetViews = {};

            view.padding = model.position === constants.SIDEBAR_LEFT ? 'margin-left' : 'margin-right';

            view.listenTo(model, 'change', view.render);

            view.listenTo(model.widgets, 'reset', view.onWidgetsReset);
            view.listenTo(model.widgets, 'reset', view.render);

            view.listenTo(model.widgets, 'add', view.onWidgetAdded);
            view.listenTo(model.widgets, 'add', view.render);

            view.listenTo(model.widgets, 'remove', view.onWidgetRemoved);
            view.listenTo(model.widgets, 'remove', view.render);

            view.listenTo(Backbone, 'showWidgetHover', view.onShowWidgetHover);
            view.listenTo(Backbone, 'removeWidget', view.onRemoveWidget);
            view.listenTo(Backbone, 'setupWidget', view.onSetupWidget);
        },

        render: function () {
            var view = this;
            var model = view.model;

            view.$el.html(view.template(model.toJSON()));

            if (model.state === constants.SIDEBAR_MAXIMIZED) {
                view.$el.addClass('sidebar-maximized');
            } else {
                view.$el.removeClass('sidebar-maximized');
            }

            view.options.$main.css(view.padding, view.$el.width() + 'px');

            if (model.state === constants.SIDEBAR_MINIMIZED) {
                view.renderIcons();
            } else {
                view.renderWidgets();
            }

            return view;
        },

        renderIcons: function () {
            var view = this;
            var model = view.model;
            var $content = view.$el.find('.sidebar-content');

            model.widgets.each(function (widget) {
                var iconView = view.iconViews[widget.cid];
                if (!iconView) {
                    return;
                }
                iconView.render().delegateEvents();
                $content.append(iconView.$el);
            });

            $content.sortable({
                revert: true,
                axis: 'y',
                containment: 'parent',
                start: function (event, ui) {
                    var cid = ui.item.data('cid');
                    view.onIconDragStart(cid);
                },
                stop: function (event, ui) {
                    var cid = ui.item.data('cid');
                    view.onIconDragStop(cid);

                    view.reorderWidgets();
                }
            });

            return view;
        },

        renderWidgets: function () {
            var view = this;
            var model = view.model;
            var $content = view.$el.find('.sidebar-content');

            model.widgets.each(function (widget) {
                var widgetView = view.widgetViews[widget.cid];
                if (!widgetView) {
                    return;
                }
                widgetView.render().delegateEvents();
                $content.append(widgetView.$el);
            });

            $content.sortable({
                revert: true,
                axis: 'y',
                containment: 'parent',
                start: function (event, ui) {
                    var cid = ui.item.data('cid');
                    view.onIconDragStart(cid);
                },
                stop: function (event, ui) {
                    var cid = ui.item.data('cid');
                    view.onIconDragStop(cid);

                    view.reorderWidgets();
                }
            });

            return view;
        },

        onIconDragStart: function (cid) {
            var widget = this.model.widgets.get(cid);
            if (widget) {
                widget.isDragged = true;
            }
        },

        onIconDragStop: function (cid) {
            var widget = this.model.widgets.get(cid);
            if (widget) {
                widget.isDragged = false;
            }
        },

        reorderWidgets: function () {
            var view = this;
            var $content = view.$el.find('.sidebar-content');

            var ids = $content.sortable('toArray', { attribute: 'data-cid' });
            var widgetOrder = _.object(ids, _.range(ids.length));

            view.model.widgets.each(function (widget) {
                var order = widgetOrder[widget.cid];
                widget.set({ position: order }, { silent: true });
                widget.save();
            });

            view.model.widgets.sort();
        },

        onClickAdd: function (e) {
            var view = this;
            var model = view.model;

            e.stopPropagation();
            e.preventDefault();

            var widgetAddView = new WidgetAddView({
                model: model
            });

            widgetAddView.open();
        },

        onClickToggle: function (e) {
            e.stopPropagation();
            e.preventDefault();

            this.model.toggleState();
        },

        onWidgetsReset: function () {
            var view = this;

            this.model.widgets.each(function (widget) {
                var widgetView = new WidgetContainerView({
                    model: widget
                });

                view.widgetViews[widget.cid] = widgetView;

                var iconView = new IconView({
                    model: widget
                });

                view.iconViews[widget.cid] = iconView;
            });
        },

        onWidgetAdded: function (widget) {
            var widgetView = new WidgetContainerView({
                model: widget
            });

            this.widgetViews[widget.cid] = widgetView;

            var iconView = new IconView({
                model: widget
            });

            this.iconViews[widget.cid] = iconView;
        },

        onWidgetRemoved: function (widget) {
            var cid = widget.cid;

            var widgetView = this.widgetViews[cid];
            if (widgetView) {
                if (widgetView.contentView) {
                    widgetView.contentView.remove();
                }
                widgetView.remove();
                delete this.widgetViews[cid];
            }

            var iconView = this.iconViews[cid];
            if (iconView) {
                iconView.remove();
                delete this.iconViews[cid];
            }

            var hoverView = this.hoverViews[cid];
            if (hoverView) {
                hoverView.contentView.remove();
                hoverView.remove();
                delete this.hoverViews[cid];
            }
        },

        onShowWidgetHover: function (cid, cord) {
            var view = this;

            var widget = view.model.widgets.get(cid);
            if (!widget) {
                return;
            }

            view.hideAllWidgetHovers();

            widget.snapshotState();
            widget.state = constants.WIDGET_MAXIMIZED_HOVER;

            var hoverView = new WidgetContainerView({
                model: widget
            });

            var widgetWidth = 200;
            view.$el.append(hoverView.render().$el);
            hoverView.$el.css('position', 'fixed');
            hoverView.$el.width(widgetWidth);

            var windowWidth = $(window).width();

            if ((cord.left + widgetWidth) > windowWidth) {
                cord.left = windowWidth - widgetWidth;
            }

            var sidebarWidth = view.$el.width();
            if (view.model.position === constants.SIDEBAR_LEFT) {
                cord.left += sidebarWidth;
            } else {
                cord.left -= sidebarWidth;
            }

            hoverView.$el.offset(cord);

            view.hoverViews[cid] = hoverView;
        },

        hideWidgetHover: function (cid) {
            var hoverView = this.hoverViews[cid];
            if (hoverView) {
                hoverView.model.restoreState();
                hoverView.contentView.remove();
                hoverView.remove();
                delete this.hoverViews[cid];
            }
        },

        hideAllWidgetHovers: function () {
            var view = this;
            var model = view.model;

            model.widgets.each(function (widget) {
                view.hideWidgetHover(widget.cid);
            });
        },

        onRemoveWidget: function (cid) {
            var view = this;
            var model = view.model;

            var widget = model.widgets.get(cid);
            if (!widget) {
                return;
            }

            switch (widget.state) {

            case constants.WIDGET_MAXIMIZED_HOVER:
                view.hideWidgetHover(cid);
                break;

            case constants.WIDGET_MAXIMIZED:
                var modal = new DeleteConfirmation({
                    content: __('The widget will be removed')
                });

                modal.on('ok', function () {
                    //model.widgets.remove(widget);
                    widget.destroy();
                    modal.off();
                });

                modal.on('cancel', function () {
                    modal.off();
                });

                modal.open();

                break;
            }
        },

        onSetupWidget: function (cid) {
            var widget = this.model.widgets.get(cid);
            if (!widget) {
                return;
            }

            var widgetSnapshot = JSON.stringify(widget);

            var widgetSetupView = new WidgetSetupView({
                model: widget
            });

            widgetSetupView.on('ok', function () {
                widget.save();
            });

            widgetSetupView.on('cancel', function () {
                widget.set(JSON.parse(widgetSnapshot), { silent: true });
                widget.trigger('change');
            });

            widgetSetupView.open();
        }
    });

    return SidebarView;
});
<commit_msg>BAP-2043: widget hover show/hide edge cases handling<commit_after>/*jslint browser: true, nomen: true, vars: true*/
/*global define*/

define(function (require) {
    'use strict';

    var $ = require('jquery');
    var _jqueryUI = require('jquery-ui');
    var _ = require('underscore');
    var Backbone = require('backbone');

    var __ = require('oro/translator');
    var DeleteConfirmation = require('oro/delete-confirmation');

    var constants = require('oro/sidebar/constants');

    var IconView = require('oro/sidebar/widget-container/icon-view');
    var WidgetContainerView = require('oro/sidebar/widget-container/view');
    var WidgetAddView = require('oro/sidebar/widget-container/widget-add-view');
    var WidgetSetupView = require('oro/sidebar/widget-container/widget-setup-view');

    var sidebarTemplate = require('text!oro/sidebar/sidebar/template');

    /**
     * @export  oro/sidebar/sidebar/view
     * @class oro.sidebar.sidebar.View
     * @extends Backbone.View
     */
    var SidebarView = Backbone.View.extend({
        template: _.template(sidebarTemplate),

        events: {
            'click .sidebar-add a': 'onClickAdd',
            'click .sidebar-resize a': 'onClickToggle',
            'click .sidebar-toggle a': 'onClickToggle'
        },

        initialize: function () {
            var view = this;
            var model = view.model;

            view.iconViews = {};
            view.hoverViews = {};
            view.widgetViews = {};

            view.padding = model.position === constants.SIDEBAR_LEFT ? 'margin-left' : 'margin-right';

            view.listenTo(model, 'change', view.render);

            view.listenTo(model.widgets, 'reset', view.onWidgetsReset);
            view.listenTo(model.widgets, 'reset', view.render);

            view.listenTo(model.widgets, 'add', view.onWidgetAdded);
            view.listenTo(model.widgets, 'add', view.render);

            view.listenTo(model.widgets, 'remove', view.onWidgetRemoved);
            view.listenTo(model.widgets, 'remove', view.render);

            view.listenTo(Backbone, 'showWidgetHover', view.onShowWidgetHover);
            view.listenTo(Backbone, 'removeWidget', view.onRemoveWidget);
            view.listenTo(Backbone, 'setupWidget', view.onSetupWidget);
        },

        render: function () {
            var view = this;
            var model = view.model;

            view.$el.html(view.template(model.toJSON()));

            if (model.state === constants.SIDEBAR_MAXIMIZED) {
                view.$el.addClass('sidebar-maximized');
            } else {
                view.$el.removeClass('sidebar-maximized');
            }

            view.options.$main.css(view.padding, view.$el.width() + 'px');

            if (model.state === constants.SIDEBAR_MINIMIZED) {
                view.renderIcons();
            } else {
                view.renderWidgets();
            }

            return view;
        },

        renderIcons: function () {
            var view = this;
            var model = view.model;
            var $content = view.$el.find('.sidebar-content');

            model.widgets.each(function (widget) {
                var iconView = view.iconViews[widget.cid];
                if (!iconView) {
                    return;
                }
                iconView.render().delegateEvents();
                $content.append(iconView.$el);
            });

            $content.sortable({
                revert: true,
                axis: 'y',
                containment: 'parent',
                start: function (event, ui) {
                    var cid = ui.item.data('cid');
                    view.onIconDragStart(cid);
                },
                stop: function (event, ui) {
                    var cid = ui.item.data('cid');
                    view.onIconDragStop(cid);

                    view.reorderWidgets();
                }
            });

            return view;
        },

        renderWidgets: function () {
            var view = this;
            var model = view.model;
            var $content = view.$el.find('.sidebar-content');

            view.hideAllWidgetHovers();

            model.widgets.each(function (widget) {
                var widgetView = view.widgetViews[widget.cid];
                if (!widgetView) {
                    return;
                }
                widgetView.render().delegateEvents();
                $content.append(widgetView.$el);
            });

            $content.sortable({
                revert: true,
                axis: 'y',
                containment: 'parent',
                start: function (event, ui) {
                    var cid = ui.item.data('cid');
                    view.onIconDragStart(cid);
                },
                stop: function (event, ui) {
                    var cid = ui.item.data('cid');
                    view.onIconDragStop(cid);

                    view.reorderWidgets();
                }
            });

            return view;
        },

        onIconDragStart: function (cid) {
            var widget = this.model.widgets.get(cid);
            if (widget) {
                widget.isDragged = true;
            }
        },

        onIconDragStop: function (cid) {
            var widget = this.model.widgets.get(cid);
            if (widget) {
                widget.isDragged = false;
            }
        },

        reorderWidgets: function () {
            var view = this;
            var $content = view.$el.find('.sidebar-content');

            var ids = $content.sortable('toArray', { attribute: 'data-cid' });
            var widgetOrder = _.object(ids, _.range(ids.length));

            view.model.widgets.each(function (widget) {
                var order = widgetOrder[widget.cid];
                widget.set({ position: order }, { silent: true });
                widget.save();
            });

            view.model.widgets.sort();
        },

        onClickAdd: function (e) {
            var view = this;
            var model = view.model;

            e.stopPropagation();
            e.preventDefault();

            var widgetAddView = new WidgetAddView({
                model: model
            });

            widgetAddView.open();
        },

        onClickToggle: function (e) {
            e.stopPropagation();
            e.preventDefault();

            this.hideAllWidgetHovers();

            this.model.toggleState();
        },

        onWidgetsReset: function () {
            var view = this;

            this.model.widgets.each(function (widget) {
                var widgetView = new WidgetContainerView({
                    model: widget
                });

                view.widgetViews[widget.cid] = widgetView;

                var iconView = new IconView({
                    model: widget
                });

                view.iconViews[widget.cid] = iconView;
            });
        },

        onWidgetAdded: function (widget) {
            var widgetView = new WidgetContainerView({
                model: widget
            });

            this.widgetViews[widget.cid] = widgetView;

            var iconView = new IconView({
                model: widget
            });

            this.iconViews[widget.cid] = iconView;
        },

        onWidgetRemoved: function (widget) {
            var cid = widget.cid;

            var widgetView = this.widgetViews[cid];
            if (widgetView) {
                if (widgetView.contentView) {
                    widgetView.contentView.remove();
                }
                widgetView.remove();
                delete this.widgetViews[cid];
            }

            var iconView = this.iconViews[cid];
            if (iconView) {
                iconView.remove();
                delete this.iconViews[cid];
            }

            var hoverView = this.hoverViews[cid];
            if (hoverView) {
                hoverView.contentView.remove();
                hoverView.remove();
                delete this.hoverViews[cid];
            }
        },

        onShowWidgetHover: function (cid, cord) {
            var view = this;

            var widget = view.model.widgets.get(cid);
            if (!widget) {
                return;
            }

            widget.state = constants.WIDGET_MAXIMIZED;
            widget.snapshotState();
            widget.state = constants.WIDGET_MAXIMIZED_HOVER;

            var hoverView = new WidgetContainerView({
                model: widget
            });

            var widgetWidth = 200;
            view.$el.append(hoverView.render().$el);
            hoverView.$el.css('position', 'fixed');
            hoverView.$el.width(widgetWidth);

            var windowWidth = $(window).width();

            if ((cord.left + widgetWidth) > windowWidth) {
                cord.left = windowWidth - widgetWidth;
            }

            var sidebarWidth = view.$el.width();
            if (view.model.position === constants.SIDEBAR_LEFT) {
                cord.left += sidebarWidth;
            } else {
                cord.left -= sidebarWidth;
            }

            hoverView.$el.offset(cord);

            view.hoverViews[cid] = hoverView;
        },

        hideWidgetHover: function (cid) {
            var hoverView = this.hoverViews[cid];
            if (hoverView) {
                hoverView.model.restoreState();
                hoverView.contentView.remove();
                hoverView.remove();
                delete this.hoverViews[cid];
            }
        },

        hideAllWidgetHovers: function () {
            var view = this;
            var model = view.model;

            model.widgets.each(function (widget) {
                view.hideWidgetHover(widget.cid);
            });
        },

        onRemoveWidget: function (cid) {
            var view = this;
            var model = view.model;

            var widget = model.widgets.get(cid);
            if (!widget) {
                return;
            }

            switch (widget.state) {

            case constants.WIDGET_MAXIMIZED_HOVER:
                view.hideWidgetHover(cid);
                widget.state = constants.WIDGET_MINIMIZED;
                break;

            case constants.WIDGET_MAXIMIZED:
                var modal = new DeleteConfirmation({
                    content: __('The widget will be removed')
                });

                modal.on('ok', function () {
                    //model.widgets.remove(widget);
                    widget.destroy();
                    modal.off();
                });

                modal.on('cancel', function () {
                    modal.off();
                });

                modal.open();

                break;
            }
        },

        onSetupWidget: function (cid) {
            var widget = this.model.widgets.get(cid);
            if (!widget) {
                return;
            }

            var widgetSnapshot = JSON.stringify(widget);

            var widgetSetupView = new WidgetSetupView({
                model: widget
            });

            widgetSetupView.on('ok', function () {
                widget.save();
            });

            widgetSetupView.on('cancel', function () {
                widget.set(JSON.parse(widgetSnapshot), { silent: true });
                widget.trigger('change');
            });

            widgetSetupView.open();
        }
    });

    return SidebarView;
});
<|endoftext|>


<commit_before>define([
    'jquery',
    'underscore',
    'oroui/js/mediator',
    'oroui/js/app/views/base/view'
], function($, _, mediator, BaseView) {
    'use strict';

    var RoleView;

    /**
     * @export orouser/js/views/role-view
     */
    RoleView = BaseView.extend({
        options: {
            elSelector: '',
            formName: '',
            formSelector: '',
            privilegesSelector: '',
            appendUsersSelector: '',
            removeUsersSelector: '',
            fields: ''
        },
        privileges: null,

        $form: null,
        $privileges: null,
        $appendUsers: null,
        $removeUsers: null,
        $fields: null,

        events: {
            'click': 'onSubmit'
        },

        listen: {
            'securityAccessLevelsComponent:link:click mediator': 'onAccessLevelsLinkClicked'
        },

        /**
         * Initialize
         *
         * @param {Object} options
         */
        initialize: function(options) {
            this.options = _.defaults(options || {}, this.options);
            this.$el = $(this.options.elSelector);
            this.$form = $(this.options.formSelector);
            this.$privileges = $(this.options.privilegesSelector);
            this.$appendUsers = $(this.options.appendUsersSelector);
            this.$removeUsers = $(this.options.removeUsersSelector);

            var fields = {};
            _.each(
                this.options.fields,
                function(selector, name) {
                    fields[name] = $(selector);
                }
            );
            this.$fields = fields;
        },

        /**
         * @inheritDoc
         */
        dispose: function() {
            if (this.disposed) {
                return;
            }

            delete this.$form;
            delete this.$privileges;
            delete this.$appendUsers;
            delete this.$removeUsers;
            delete this.$fields;

            RoleView.__super__.dispose.call(this);
        },

        /**
         * onSubmit event listener
         */
        onSubmit: function(event) {
            var $form = this.$form;
            var hasError = false;
            _.each(this.$fields, function(field) {
                hasError = hasError || !field.valid();
            });
            if (hasError) {
                return;
            }
            if ($form.data('nohash') && !$form.data('sent')) {
                $form.data('sent', true);
                return;
            }
            if ($form.data('sent')) {
                return;
            }

            $form.data('sent', true);

            var action = $form.attr('action');
            var method = $form.attr('method');
            var url = (typeof action === 'string') ? $.trim(action) : '';
            url = url || window.location.href || '';
            if (url) {
                // clean url (don't include hash value)
                url = (url.match(/^([^#]+)/) || [])[1];
            }

            var data = this.getData();
            var dataAction = $(event.target).attr('data-action');
            if (dataAction) {
                data.input_action = dataAction;
            }

            var options = {
                url: url,
                type: method || 'GET',
                data: $.param(data)
            };
            mediator.execute('submitPage', options);
        },

        /**
         * @returns {Object}
         */
        getData: function() {
            var data = {};

            var formName = this.options.formName;
            _.each(
                this.$fields,
                function(element, name) {
                    data[formName + '[' + name + ']'] = element.val();
                }
            );

            data[formName + '[privileges]'] = this.$privileges.val();
            data[formName + '[appendUsers]'] = this.$appendUsers.val();
            data[formName + '[removeUsers]'] = this.$removeUsers.val();

            return data;
        },

        /**
         * onClick event listener
         */
        onAccessLevelsLinkClicked: function(data) {
            if (this.disposed) {
                return;
            }
            var obj = JSON.parse(this.$privileges.val());

            var knownIdentities = _.reduce(obj, function(memo, group) {
                memo = _.reduce(group, function(memo, item) {
                    memo[item.identity.id] = item;
                    return memo;
                }, memo);
                return memo;
            }, {});

            var privelege;
            if (data.identityId in knownIdentities) {
                privelege = knownIdentities[data.identityId];
            } else {
                // create privelege
                privelege = {
                    identity: {
                        id: data.identityId
                    },
                    permissions: {}
                };
                if (data.permissionName === 'EXECUTE') {
                    obj.action[Object.keys(knownIdentities).length] = privelege;
                } else {
                    obj.entity[Object.keys(knownIdentities).length] = privelege;
                }
            }

            if (!(data.permissionName in privelege.permissions)) {
                privelege.permissions[data.permissionName] = {
                    name: data.permissionName
                }
            }
            var permission = privelege.permissions[data.permissionName];
            permission.accessLevel = data.accessLevel;

            this.$privileges.val(JSON.stringify(obj)).trigger('change');
        }
    });

    return RoleView;
});
<commit_msg>Code style fix<commit_after>define([
    'jquery',
    'underscore',
    'oroui/js/mediator',
    'oroui/js/app/views/base/view'
], function($, _, mediator, BaseView) {
    'use strict';

    var RoleView;

    /**
     * @export orouser/js/views/role-view
     */
    RoleView = BaseView.extend({
        options: {
            elSelector: '',
            formName: '',
            formSelector: '',
            privilegesSelector: '',
            appendUsersSelector: '',
            removeUsersSelector: '',
            fields: ''
        },
        privileges: null,

        $form: null,
        $privileges: null,
        $appendUsers: null,
        $removeUsers: null,
        $fields: null,

        events: {
            'click': 'onSubmit'
        },

        listen: {
            'securityAccessLevelsComponent:link:click mediator': 'onAccessLevelsLinkClicked'
        },

        /**
         * Initialize
         *
         * @param {Object} options
         */
        initialize: function(options) {
            this.options = _.defaults(options || {}, this.options);
            this.$el = $(this.options.elSelector);
            this.$form = $(this.options.formSelector);
            this.$privileges = $(this.options.privilegesSelector);
            this.$appendUsers = $(this.options.appendUsersSelector);
            this.$removeUsers = $(this.options.removeUsersSelector);

            var fields = {};
            _.each(
                this.options.fields,
                function(selector, name) {
                    fields[name] = $(selector);
                }
            );
            this.$fields = fields;
        },

        /**
         * @inheritDoc
         */
        dispose: function() {
            if (this.disposed) {
                return;
            }

            delete this.$form;
            delete this.$privileges;
            delete this.$appendUsers;
            delete this.$removeUsers;
            delete this.$fields;

            RoleView.__super__.dispose.call(this);
        },

        /**
         * onSubmit event listener
         */
        onSubmit: function(event) {
            var $form = this.$form;
            var hasError = false;
            _.each(this.$fields, function(field) {
                hasError = hasError || !field.valid();
            });
            if (hasError) {
                return;
            }
            if ($form.data('nohash') && !$form.data('sent')) {
                $form.data('sent', true);
                return;
            }
            if ($form.data('sent')) {
                return;
            }

            $form.data('sent', true);

            var action = $form.attr('action');
            var method = $form.attr('method');
            var url = (typeof action === 'string') ? $.trim(action) : '';
            url = url || window.location.href || '';
            if (url) {
                // clean url (don't include hash value)
                url = (url.match(/^([^#]+)/) || [])[1];
            }

            var data = this.getData();
            var dataAction = $(event.target).attr('data-action');
            if (dataAction) {
                data.input_action = dataAction;
            }

            var options = {
                url: url,
                type: method || 'GET',
                data: $.param(data)
            };
            mediator.execute('submitPage', options);
        },

        /**
         * @returns {Object}
         */
        getData: function() {
            var data = {};

            var formName = this.options.formName;
            _.each(
                this.$fields,
                function(element, name) {
                    data[formName + '[' + name + ']'] = element.val();
                }
            );

            data[formName + '[privileges]'] = this.$privileges.val();
            data[formName + '[appendUsers]'] = this.$appendUsers.val();
            data[formName + '[removeUsers]'] = this.$removeUsers.val();

            return data;
        },

        /**
         * onClick event listener
         */
        onAccessLevelsLinkClicked: function(data) {
            if (this.disposed) {
                return;
            }
            var obj = JSON.parse(this.$privileges.val());

            var knownIdentities = _.reduce(obj, function(memo, group) {
                memo = _.reduce(group, function(memo, item) {
                    memo[item.identity.id] = item;
                    return memo;
                }, memo);
                return memo;
            }, {});

            var privelege;
            if (data.identityId in knownIdentities) {
                privelege = knownIdentities[data.identityId];
            } else {
                // create privelege
                privelege = {
                    identity: {
                        id: data.identityId
                    },
                    permissions: {}
                };
                if (data.permissionName === 'EXECUTE') {
                    obj.action[Object.keys(knownIdentities).length] = privelege;
                } else {
                    obj.entity[Object.keys(knownIdentities).length] = privelege;
                }
            }

            if (!(data.permissionName in privelege.permissions)) {
                privelege.permissions[data.permissionName] = {
                    name: data.permissionName
                };
            }
            var permission = privelege.permissions[data.permissionName];
            permission.accessLevel = data.accessLevel;

            this.$privileges.val(JSON.stringify(obj)).trigger('change');
        }
    });

    return RoleView;
});
<|endoftext|>


<commit_before>import React from 'react'

import Component from '../base-component'
import Icon from '../icon'
import propTypes from '../prop-types'

const TOGGLE_STYLE = { visibility: 'hidden' }

@propTypes({
  defaultValue: propTypes.bool,
  onChange: propTypes.func,
  value: propTypes.bool
})
export default class Toggle extends Component {
  get value () {
    return this.refs.input.checked
  }

  set value (value) {
    this.refs.input.checked = Boolean(value)
  }

  componentWillReceiveProps (nextProps) {
    const { value } = nextProps
    if (value !== this.props.value) {
      this.value = value
    }
  }

  _onChange = () => {
    this.forceUpdate()

    const { onChange } = this.props
    onChange && onChange(this.value)
  }

  render () {
    const { props, refs } = this
    const { input } = refs
    const {
      defaultValue = false,
      value = input ? input.checked : defaultValue
    } = props

    return <label className={props.disabled ? 'text-muted' : value ? 'text-success' : null}>
      <Icon icon={`toggle-${value ? 'on' : 'off'}`} size={2} />
      <input
        checked={props.value}
        defaultChecked={defaultValue}
        disabled={props.disabled}
        onChange={this._onChange}
        ref='input'
        style={TOGGLE_STYLE}
        type='checkbox'
      />
    </label>
  }
}
<commit_msg>fix(form/Toggle): controlled/uncontrolled issues<commit_after>import React from 'react'

import Component from '../base-component'
import Icon from '../icon'
import propTypes from '../prop-types'

const TOGGLE_STYLE = { visibility: 'hidden' }

@propTypes({
  defaultValue: propTypes.bool,
  onChange: propTypes.func,
  value: propTypes.bool
})
export default class Toggle extends Component {
  get value () {
    const { props } = this

    const { value } = props
    if (value != null) {
      return value
    }

    const { input } = this.refs
    if (input) {
      return input.checked
    }

    return props.defaultValue || false
  }

  set value (value) {
    if (process.env.NODE_ENV !== 'production') {
      if (this.props.value != null) {
        throw new Error('cannot set value of controlled Toggle')
      }
    }

    this.refs.input.checked = Boolean(value)
  }

  _onChange = event => {
    if (this.props.value == null) {
      this.forceUpdate()
    }

    const { onChange } = this.props
    onChange && onChange(event.target.checked)
  }

  render () {
    const { props, value } = this

    return <label className={props.disabled ? 'text-muted' : value ? 'text-success' : null}>
      <Icon icon={`toggle-${value ? 'on' : 'off'}`} size={2} />
      <input
        checked={props.value}
        defaultChecked={props.defaultChecked}
        disabled={props.disabled}
        onChange={this._onChange}
        ref='input'
        style={TOGGLE_STYLE}
        type='checkbox'
      />
    </label>
  }
}
<|endoftext|>